summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Makefile30
-rw-r--r--abc.dsp1310
-rw-r--r--abc.rc89
-rw-r--r--abclib.dsp2844
-rw-r--r--abclib.dsw29
-rw-r--r--abctestlib.dsp102
-rw-r--r--abctestlib.dsw29
-rw-r--r--copyright.txt18
-rw-r--r--demo.c181
-rw-r--r--graph_lib.txt1407
-rw-r--r--readme26
-rw-r--r--regtest.script119
-rw-r--r--regtest_output.txt241
-rw-r--r--src/abc8/vec2/vec2.h121
-rw-r--r--src/abc8/vec2/vecInt.h834
-rw-r--r--src/abc8/vec2/vecPtr.h812
-rw-r--r--src/abc8/vec2/vecStr.h583
-rw-r--r--src/abc8/vec2/vecVec.h356
-rw-r--r--src/aig/aig/aig.h (renamed from src/abc8/aig/aig.h)2
-rw-r--r--src/aig/aig/aigCheck.c (renamed from src/abc8/aig/aigCheck.c)0
-rw-r--r--src/aig/aig/aigCuts.c (renamed from src/abc8/aig/aigCuts.c)0
-rw-r--r--src/aig/aig/aigDfs.c (renamed from src/abc8/aig/aigDfs.c)0
-rw-r--r--src/aig/aig/aigFanout.c (renamed from src/abc8/aig/aigFanout.c)0
-rw-r--r--src/aig/aig/aigFrames.c (renamed from src/abc8/aig/aigFrames.c)0
-rw-r--r--src/aig/aig/aigHaig.c (renamed from src/abc8/aig/aigHaig.c)0
-rw-r--r--src/aig/aig/aigInter.c (renamed from src/abc8/aig/aigInter.c)0
-rw-r--r--src/aig/aig/aigMan.c (renamed from src/abc8/aig/aigMan.c)6
-rw-r--r--src/aig/aig/aigMem.c (renamed from src/abc8/aig/aigMem.c)0
-rw-r--r--src/aig/aig/aigMffc.c (renamed from src/abc8/aig/aigMffc.c)0
-rw-r--r--src/aig/aig/aigObj.c (renamed from src/abc8/aig/aigObj.c)0
-rw-r--r--src/aig/aig/aigOper.c (renamed from src/abc8/aig/aigOper.c)0
-rw-r--r--src/aig/aig/aigOrder.c (renamed from src/abc8/aig/aigOrder.c)0
-rw-r--r--src/aig/aig/aigPart.c (renamed from src/abc8/aig/aigPart.c)0
-rw-r--r--src/aig/aig/aigRepr.c (renamed from src/abc8/aig/aigRepr.c)0
-rw-r--r--src/aig/aig/aigRet.c (renamed from src/abc8/aig/aigRet.c)0
-rw-r--r--src/aig/aig/aigRetF.c (renamed from src/abc8/aig/aigRetF.c)0
-rw-r--r--src/aig/aig/aigScl.c (renamed from src/abc8/aig/aigScl.c)0
-rw-r--r--src/aig/aig/aigSeq.c (renamed from src/abc8/aig/aigSeq.c)0
-rw-r--r--src/aig/aig/aigShow.c (renamed from src/abc8/aig/aigShow.c)0
-rw-r--r--src/aig/aig/aigTable.c (renamed from src/abc8/aig/aigTable.c)0
-rw-r--r--src/aig/aig/aigTiming.c (renamed from src/abc8/aig/aigTiming.c)0
-rw-r--r--src/aig/aig/aigTruth.c (renamed from src/abc8/aig/aigTruth.c)0
-rw-r--r--src/aig/aig/aigTsim.c (renamed from src/abc8/aig/aigTsim.c)0
-rw-r--r--src/aig/aig/aigUtil.c (renamed from src/abc8/aig/aigUtil.c)0
-rw-r--r--src/aig/aig/aigWin.c (renamed from src/abc8/aig/aigWin.c)0
-rw-r--r--src/aig/aig/aig_.c (renamed from src/abc8/aig/aig_.c)0
-rw-r--r--src/aig/aig/module.make (renamed from src/abc8/aig/module.make)3
-rw-r--r--src/aig/bar/bar.c177
-rw-r--r--src/aig/bar/bar.h74
-rw-r--r--src/aig/bar/module.make1
-rw-r--r--src/aig/bdc/bdc.h73
-rw-r--r--src/aig/bdc/bdcCore.c189
-rw-r--r--src/aig/bdc/bdcDec.c461
-rw-r--r--src/aig/bdc/bdcInt.h150
-rw-r--r--src/aig/bdc/bdcTable.c140
-rw-r--r--src/aig/bdc/bdc_.c49
-rw-r--r--src/aig/bdc/module.make4
-rw-r--r--src/aig/cnf/cnf.h (renamed from src/abc8/cnf/cnf.h)2
-rw-r--r--src/aig/cnf/cnfCore.c (renamed from src/abc8/cnf/cnfCore.c)0
-rw-r--r--src/aig/cnf/cnfCut.c (renamed from src/abc8/cnf/cnfCut.c)0
-rw-r--r--src/aig/cnf/cnfData.c (renamed from src/abc8/cnf/cnfData.c)0
-rw-r--r--src/aig/cnf/cnfMan.c (renamed from src/abc8/cnf/cnfMan.c)0
-rw-r--r--src/aig/cnf/cnfMap.c (renamed from src/abc8/cnf/cnfMap.c)0
-rw-r--r--src/aig/cnf/cnfPost.c (renamed from src/abc8/cnf/cnfPost.c)0
-rw-r--r--src/aig/cnf/cnfUtil.c (renamed from src/abc8/cnf/cnfUtil.c)0
-rw-r--r--src/aig/cnf/cnfWrite.c (renamed from src/abc8/cnf/cnfWrite.c)0
-rw-r--r--src/aig/cnf/cnf_.c (renamed from src/abc8/cnf/cnf_.c)0
-rw-r--r--src/aig/cnf/module.make (renamed from src/abc8/cnf/module.make)0
-rw-r--r--src/aig/csw/csw.h65
-rw-r--r--src/aig/csw/cswCore.c94
-rw-r--r--src/aig/csw/cswCut.c602
-rw-r--r--src/aig/csw/cswInt.h157
-rw-r--r--src/aig/csw/cswMan.c125
-rw-r--r--src/aig/csw/cswTable.c161
-rw-r--r--src/aig/csw/csw_.c48
-rw-r--r--src/aig/csw/module.make4
-rw-r--r--src/aig/dar/dar.h (renamed from src/abc8/dar/dar.h)0
-rw-r--r--src/aig/dar/darBalance.c (renamed from src/abc8/dar/darBalance.c)0
-rw-r--r--src/aig/dar/darCore.c (renamed from src/abc8/dar/darCore.c)0
-rw-r--r--src/aig/dar/darCut.c (renamed from src/abc8/dar/darCut.c)0
-rw-r--r--src/aig/dar/darData.c (renamed from src/abc8/dar/darData.c)0
-rw-r--r--src/aig/dar/darInt.h (renamed from src/abc8/dar/darInt.h)2
-rw-r--r--src/aig/dar/darLib.c (renamed from src/abc8/dar/darLib.c)0
-rw-r--r--src/aig/dar/darMan.c (renamed from src/abc8/dar/darMan.c)0
-rw-r--r--src/aig/dar/darPrec.c (renamed from src/abc8/dar/darPrec.c)0
-rw-r--r--src/aig/dar/darRefact.c (renamed from src/abc8/dar/darRefact.c)2
-rw-r--r--src/aig/dar/darResub.c (renamed from src/abc8/dar/darResub.c)0
-rw-r--r--src/aig/dar/darScript.c (renamed from src/abc8/dar/darScript.c)0
-rw-r--r--src/aig/dar/dar_.c (renamed from src/abc8/dar/dar_.c)0
-rw-r--r--src/aig/dar/module.make (renamed from src/abc8/dar/module.make)0
-rw-r--r--src/aig/deco/deco.h703
-rw-r--r--src/aig/deco/module.make (renamed from src/abc8/vec2/module.make)0
-rw-r--r--src/aig/fra/fra.h (renamed from src/abc8/fra/fra.h)2
-rw-r--r--src/aig/fra/fraBmc.c (renamed from src/abc8/fra/fraBmc.c)0
-rw-r--r--src/aig/fra/fraCec.c (renamed from src/abc8/fra/fraCec.c)0
-rw-r--r--src/aig/fra/fraClass.c (renamed from src/abc8/fra/fraClass.c)0
-rw-r--r--src/aig/fra/fraClau.c (renamed from src/abc8/fra/fraClau.c)0
-rw-r--r--src/aig/fra/fraClaus.c (renamed from src/abc8/fra/fraClaus.c)0
-rw-r--r--src/aig/fra/fraCnf.c (renamed from src/abc8/fra/fraCnf.c)0
-rw-r--r--src/aig/fra/fraCore.c (renamed from src/abc8/fra/fraCore.c)0
-rw-r--r--src/aig/fra/fraImp.c (renamed from src/abc8/fra/fraImp.c)0
-rw-r--r--src/aig/fra/fraInd.c (renamed from src/abc8/fra/fraInd.c)0
-rw-r--r--src/aig/fra/fraLcr.c (renamed from src/abc8/fra/fraLcr.c)0
-rw-r--r--src/aig/fra/fraMan.c (renamed from src/abc8/fra/fraMan.c)0
-rw-r--r--src/aig/fra/fraPart.c (renamed from src/abc8/fra/fraPart.c)0
-rw-r--r--src/aig/fra/fraSat.c (renamed from src/abc8/fra/fraSat.c)0
-rw-r--r--src/aig/fra/fraSec.c (renamed from src/abc8/fra/fraSec.c)0
-rw-r--r--src/aig/fra/fraSim.c (renamed from src/abc8/fra/fraSim.c)0
-rw-r--r--src/aig/fra/fra_.c (renamed from src/abc8/fra/fra_.c)0
-rw-r--r--src/aig/fra/module.make (renamed from src/abc8/fra/module.make)0
-rw-r--r--src/aig/hop/cudd2.c355
-rw-r--r--src/aig/hop/cudd2.h82
-rw-r--r--src/aig/hop/hop.h (renamed from src/misc/hop/hop.h)38
-rw-r--r--src/aig/hop/hopBalance.c (renamed from src/misc/hop/hopBalance.c)0
-rw-r--r--src/aig/hop/hopCheck.c (renamed from src/misc/hop/hopCheck.c)0
-rw-r--r--src/aig/hop/hopDfs.c (renamed from src/misc/hop/hopDfs.c)0
-rw-r--r--src/aig/hop/hopMan.c (renamed from src/misc/hop/hopMan.c)0
-rw-r--r--src/aig/hop/hopMem.c (renamed from src/misc/hop/hopMem.c)0
-rw-r--r--src/aig/hop/hopObj.c (renamed from src/misc/hop/hopObj.c)0
-rw-r--r--src/aig/hop/hopOper.c (renamed from src/misc/hop/hopOper.c)0
-rw-r--r--src/aig/hop/hopTable.c (renamed from src/misc/hop/hopTable.c)4
-rw-r--r--src/aig/hop/hopUtil.c (renamed from src/misc/hop/hopUtil.c)6
-rw-r--r--src/aig/hop/hop_.c (renamed from src/misc/hop/hop_.c)0
-rw-r--r--src/aig/hop/module.make (renamed from src/misc/hop/module.make)0
-rw-r--r--src/aig/ioa/ioa.h (renamed from src/abc8/ioa/ioa.h)2
-rw-r--r--src/aig/ioa/ioaReadAig.c (renamed from src/abc8/ioa/ioaReadAig.c)0
-rw-r--r--src/aig/ioa/ioaUtil.c (renamed from src/abc8/ioa/ioaUtil.c)0
-rw-r--r--src/aig/ioa/ioaWriteAig.c (renamed from src/abc8/ioa/ioaWriteAig.c)0
-rw-r--r--src/aig/ioa/module.make (renamed from src/abc8/ioa/module.make)0
-rw-r--r--src/aig/ivy/attr.h414
-rw-r--r--src/aig/ivy/ivy.h557
-rw-r--r--src/aig/ivy/ivyBalance.c404
-rw-r--r--src/aig/ivy/ivyCanon.c144
-rw-r--r--src/aig/ivy/ivyCheck.c273
-rw-r--r--src/aig/ivy/ivyCut.c989
-rw-r--r--src/aig/ivy/ivyCutTrav.c473
-rw-r--r--src/aig/ivy/ivyDfs.c493
-rw-r--r--src/aig/ivy/ivyDsd.c819
-rw-r--r--src/aig/ivy/ivyFanout.c309
-rw-r--r--src/aig/ivy/ivyFastMap.c1593
-rw-r--r--src/aig/ivy/ivyFraig.c2760
-rw-r--r--src/aig/ivy/ivyHaig.c530
-rw-r--r--src/aig/ivy/ivyMan.c546
-rw-r--r--src/aig/ivy/ivyMem.c116
-rw-r--r--src/aig/ivy/ivyMulti.c301
-rw-r--r--src/aig/ivy/ivyMulti8.c427
-rw-r--r--src/aig/ivy/ivyObj.c476
-rw-r--r--src/aig/ivy/ivyOper.c293
-rw-r--r--src/aig/ivy/ivyResyn.c196
-rw-r--r--src/aig/ivy/ivyRwr.c609
-rw-r--r--src/aig/ivy/ivyRwrAlg.c408
-rw-r--r--src/aig/ivy/ivySeq.c1134
-rw-r--r--src/aig/ivy/ivyShow.c338
-rw-r--r--src/aig/ivy/ivyTable.c301
-rw-r--r--src/aig/ivy/ivyUtil.c818
-rw-r--r--src/aig/ivy/ivy_.c48
-rw-r--r--src/aig/ivy/module.make22
-rw-r--r--src/aig/kit/cloud.c (renamed from src/abc8/kit/cloud.c)0
-rw-r--r--src/aig/kit/cloud.h (renamed from src/abc8/kit/cloud.h)0
-rw-r--r--src/aig/kit/kit.h (renamed from src/abc8/kit/kit.h)6
-rw-r--r--src/aig/kit/kitAig.c (renamed from src/abc8/kit/kitAig.c)0
-rw-r--r--src/aig/kit/kitBdd.c (renamed from src/abc8/kit/kitBdd.c)0
-rw-r--r--src/aig/kit/kitCloud.c (renamed from src/abc8/kit/kitCloud.c)0
-rw-r--r--src/aig/kit/kitDsd.c (renamed from src/abc8/kit/kitDsd.c)0
-rw-r--r--src/aig/kit/kitFactor.c (renamed from src/abc8/kit/kitFactor.c)0
-rw-r--r--src/aig/kit/kitGraph.c (renamed from src/abc8/kit/kitGraph.c)0
-rw-r--r--src/aig/kit/kitHop.c (renamed from src/abc8/kit/kitHop.c)0
-rw-r--r--src/aig/kit/kitIsop.c (renamed from src/abc8/kit/kitIsop.c)0
-rw-r--r--src/aig/kit/kitSop.c (renamed from src/abc8/kit/kitSop.c)0
-rw-r--r--src/aig/kit/kitTruth.c (renamed from src/abc8/kit/kitTruth.c)0
-rw-r--r--src/aig/kit/kit_.c (renamed from src/abc8/kit/kit_.c)0
-rw-r--r--src/aig/kit/module.make (renamed from src/abc8/kit/module.make)2
-rw-r--r--src/aig/mem/mem.c604
-rw-r--r--src/aig/mem/mem.h72
-rw-r--r--src/aig/mem/module.make1
-rw-r--r--src/aig/ntl/module.make11
-rw-r--r--src/aig/ntl/ntl.h277
-rw-r--r--src/aig/ntl/ntlAig.c596
-rw-r--r--src/aig/ntl/ntlCheck.c126
-rw-r--r--src/aig/ntl/ntlDfs.c184
-rw-r--r--src/aig/ntl/ntlMan.c196
-rw-r--r--src/aig/ntl/ntlMap.c624
-rw-r--r--src/aig/ntl/ntlObj.c238
-rw-r--r--src/aig/ntl/ntlReadBlif.c1163
-rw-r--r--src/aig/ntl/ntlTable.c217
-rw-r--r--src/aig/ntl/ntlTime.c128
-rw-r--r--src/aig/ntl/ntlWriteBlif.c127
-rw-r--r--src/aig/ntl/ntl_.c47
-rw-r--r--src/aig/rwt/module.make3
-rw-r--r--src/aig/rwt/rwt.h156
-rw-r--r--src/aig/rwt/rwtDec.c150
-rw-r--r--src/aig/rwt/rwtMan.c358
-rw-r--r--src/aig/rwt/rwtUtil.c665
-rw-r--r--src/aig/tim/module.make1
-rw-r--r--src/aig/tim/tim.c532
-rw-r--r--src/aig/tim/tim.h85
-rw-r--r--src/base/abc/1.txt21
-rw-r--r--src/base/abc/abc.h880
-rw-r--r--src/base/abc/abcAig.c769
-rw-r--r--src/base/abc/abcBlifMv.c970
-rw-r--r--src/base/abc/abcCheck.c442
-rw-r--r--src/base/abc/abcDfs.c961
-rw-r--r--src/base/abc/abcFanio.c167
-rw-r--r--src/base/abc/abcFunc.c781
-rw-r--r--src/base/abc/abcHie.c492
-rw-r--r--src/base/abc/abcInt.h10
-rw-r--r--src/base/abc/abcLatch.c238
-rw-r--r--src/base/abc/abcLib.c454
-rw-r--r--src/base/abc/abcMinBase.c288
-rw-r--r--src/base/abc/abcNames.c366
-rw-r--r--src/base/abc/abcNetlist.c201
-rw-r--r--src/base/abc/abcNtk.c970
-rw-r--r--src/base/abc/abcObj.c817
-rw-r--r--src/base/abc/abcRefs.c310
-rw-r--r--src/base/abc/abcShow.c100
-rw-r--r--src/base/abc/abcSop.c470
-rw-r--r--src/base/abc/abcUtil.c1100
-rw-r--r--src/base/abc/abc_.c2
-rw-r--r--src/base/abc/module.make3
-rw-r--r--src/base/abci/abc.c10812
-rw-r--r--src/base/abci/abcAttach.c12
-rw-r--r--src/base/abci/abcAuto.c239
-rw-r--r--src/base/abci/abcBalance.c427
-rw-r--r--src/base/abci/abcBmc.c115
-rw-r--r--src/base/abci/abcCas.c111
-rw-r--r--src/base/abci/abcClpBdd.c (renamed from src/base/abci/abcCollapse.c)63
-rw-r--r--src/base/abci/abcClpSop.c53
-rw-r--r--src/base/abci/abcCut.c494
-rw-r--r--src/base/abci/abcDar.c1196
-rw-r--r--src/base/abci/abcDebug.c208
-rw-r--r--src/base/abci/abcDress.c209
-rw-r--r--src/base/abci/abcDsd.c102
-rw-r--r--src/base/abci/abcEspresso.c250
-rw-r--r--src/base/abci/abcExtract.c (renamed from src/base/abcs/abc_.c)14
-rw-r--r--src/base/abci/abcFpga.c44
-rw-r--r--src/base/abci/abcFpgaFast.c190
-rw-r--r--src/base/abci/abcFraig.c446
-rw-r--r--src/base/abci/abcFxu.c19
-rw-r--r--src/base/abci/abcGen.c511
-rw-r--r--src/base/abci/abcHaig.c179
-rw-r--r--src/base/abci/abcIf.c497
-rw-r--r--src/base/abci/abcIvy.c1105
-rw-r--r--src/base/abci/abcLut.c786
-rw-r--r--src/base/abci/abcMap.c100
-rw-r--r--src/base/abci/abcMeasure.c478
-rw-r--r--src/base/abci/abcMini.c153
-rw-r--r--src/base/abci/abcMiter.c778
-rw-r--r--src/base/abci/abcMulti.c643
-rw-r--r--src/base/abci/abcMv.c369
-rw-r--r--src/base/abci/abcNtbdd.c389
-rw-r--r--src/base/abci/abcOdc.c1134
-rw-r--r--src/base/abci/abcOrder.c131
-rw-r--r--src/base/abci/abcPart.c890
-rw-r--r--src/base/abci/abcPlace.c255
-rw-r--r--src/base/abci/abcPrint.c536
-rw-r--r--src/base/abci/abcProve.c341
-rw-r--r--src/base/abci/abcQbf.c260
-rw-r--r--src/base/abci/abcQuant.c419
-rw-r--r--src/base/abci/abcRec.c1173
-rw-r--r--src/base/abci/abcReconv.c32
-rw-r--r--src/base/abci/abcRefactor.c51
-rw-r--r--src/base/abci/abcRenode.c651
-rw-r--r--src/base/abci/abcReorder.c102
-rw-r--r--src/base/abci/abcRestruct.c1497
-rw-r--r--src/base/abci/abcResub.c1952
-rw-r--r--src/base/abci/abcRewrite.c281
-rw-r--r--src/base/abci/abcRr.c999
-rw-r--r--src/base/abci/abcSat.c776
-rw-r--r--src/base/abci/abcStrash.c441
-rw-r--r--src/base/abci/abcSweep.c586
-rw-r--r--src/base/abci/abcSymm.c29
-rw-r--r--src/base/abci/abcTiming.c250
-rw-r--r--src/base/abci/abcUnate.c155
-rw-r--r--src/base/abci/abcUnreach.c70
-rw-r--r--src/base/abci/abcVerify.c817
-rw-r--r--src/base/abci/abcXsim.c224
-rw-r--r--src/base/abci/abc_.c5
-rw-r--r--src/base/abci/abc_new.h23
-rw-r--r--src/base/abci/module.make34
-rw-r--r--src/base/abcs/abcRetime.c203
-rw-r--r--src/base/abcs/abcSeq.c642
-rw-r--r--src/base/abcs/module.make2
-rw-r--r--src/base/cmd/cmd.c360
-rw-r--r--src/base/cmd/cmd.h16
-rw-r--r--src/base/cmd/cmdAlias.c6
-rw-r--r--src/base/cmd/cmdApi.c6
-rw-r--r--src/base/cmd/cmdFlag.c9
-rw-r--r--src/base/cmd/cmdHist.c6
-rw-r--r--src/base/cmd/cmdInt.h4
-rw-r--r--src/base/cmd/cmdUtils.c30
-rw-r--r--src/base/io/io.c1599
-rw-r--r--src/base/io/io.h110
-rw-r--r--src/base/io/ioInt.h6
-rw-r--r--src/base/io/ioRead.c81
-rw-r--r--src/base/io/ioReadAiger.c366
-rw-r--r--src/base/io/ioReadBaf.c171
-rw-r--r--src/base/io/ioReadBench.c223
-rw-r--r--src/base/io/ioReadBlif.c772
-rw-r--r--src/base/io/ioReadBlifAig.c1013
-rw-r--r--src/base/io/ioReadBlifMv.c1702
-rw-r--r--src/base/io/ioReadDsd.c308
-rw-r--r--src/base/io/ioReadEdif.c17
-rw-r--r--src/base/io/ioReadEqn.c73
-rw-r--r--src/base/io/ioReadPla.c7
-rw-r--r--src/base/io/ioReadVerilog.c727
-rw-r--r--src/base/io/ioUtil.c571
-rw-r--r--src/base/io/ioWriteAiger.c375
-rw-r--r--src/base/io/ioWriteBaf.c168
-rw-r--r--src/base/io/ioWriteBench.c188
-rw-r--r--src/base/io/ioWriteBlif.c173
-rw-r--r--src/base/io/ioWriteBlifMv.c519
-rw-r--r--src/base/io/ioWriteCnf.c65
-rw-r--r--src/base/io/ioWriteDot.c572
-rw-r--r--src/base/io/ioWriteEqn.c117
-rw-r--r--src/base/io/ioWriteGml.c2
-rw-r--r--src/base/io/ioWriteList.c288
-rw-r--r--src/base/io/ioWritePla.c23
-rw-r--r--src/base/io/ioWriteVerilog.c639
-rw-r--r--src/base/io/io_.c48
-rw-r--r--src/base/io/module.make13
-rw-r--r--src/base/main/libSupport.c193
-rw-r--r--src/base/main/main.c107
-rw-r--r--src/base/main/main.h40
-rw-r--r--src/base/main/mainFrame.c62
-rw-r--r--src/base/main/mainInit.c8
-rw-r--r--src/base/main/mainInt.h16
-rw-r--r--src/base/main/mainUtils.c91
-rw-r--r--src/base/main/module.make1
-rw-r--r--src/base/seq/module.make14
-rw-r--r--src/base/seq/seq.h101
-rw-r--r--src/base/seq/seqAigCore.c977
-rw-r--r--src/base/seq/seqAigIter.c268
-rw-r--r--src/base/seq/seqCreate.c482
-rw-r--r--src/base/seq/seqFpgaCore.c643
-rw-r--r--src/base/seq/seqFpgaIter.c270
-rw-r--r--src/base/seq/seqInt.h256
-rw-r--r--src/base/seq/seqLatch.c223
-rw-r--r--src/base/seq/seqMan.c133
-rw-r--r--src/base/seq/seqMapCore.c652
-rw-r--r--src/base/seq/seqMapIter.c623
-rw-r--r--src/base/seq/seqMaxMeanCycle.c567
-rw-r--r--src/base/seq/seqRetCore.c493
-rw-r--r--src/base/seq/seqRetIter.c403
-rw-r--r--src/base/seq/seqShare.c388
-rw-r--r--src/base/seq/seqUtil.c597
-rw-r--r--src/base/temp.c83
-rw-r--r--src/base/ver/module.make4
-rw-r--r--src/base/ver/ver.h118
-rw-r--r--src/base/ver/verCore.c2949
-rw-r--r--src/base/ver/verFormula.c474
-rw-r--r--src/base/ver/verParse.c117
-rw-r--r--src/base/ver/verStream.c443
-rw-r--r--src/base/ver/verWords.c48
-rw-r--r--src/base/ver/ver_.c48
-rw-r--r--src/bdd/cas/cas.h62
-rw-r--r--src/bdd/cas/casCore.c1263
-rw-r--r--src/bdd/cas/casDec.c508
-rw-r--r--src/bdd/cas/module.make3
-rw-r--r--src/bdd/cudd/cuddAPI.c2
-rw-r--r--src/bdd/cudd/cuddAddAbs.c2
-rw-r--r--src/bdd/cudd/cuddAddApply.c2
-rw-r--r--src/bdd/cudd/cuddAddFind.c2
-rw-r--r--src/bdd/cudd/cuddAddInv.c2
-rw-r--r--src/bdd/cudd/cuddAddIte.c2
-rw-r--r--src/bdd/cudd/cuddAddNeg.c2
-rw-r--r--src/bdd/cudd/cuddAddWalsh.c2
-rw-r--r--src/bdd/cudd/cuddAndAbs.c2
-rw-r--r--src/bdd/cudd/cuddAnneal.c2
-rw-r--r--src/bdd/cudd/cuddApa.c2
-rw-r--r--src/bdd/cudd/cuddApprox.c2
-rw-r--r--src/bdd/cudd/cuddBddAbs.c2
-rw-r--r--src/bdd/cudd/cuddBddCorr.c2
-rw-r--r--src/bdd/cudd/cuddBddIte.c2
-rw-r--r--src/bdd/cudd/cuddBridge.c2
-rw-r--r--src/bdd/cudd/cuddCache.c2
-rw-r--r--src/bdd/cudd/cuddCheck.c2
-rw-r--r--src/bdd/cudd/cuddClip.c2
-rw-r--r--src/bdd/cudd/cuddCof.c2
-rw-r--r--src/bdd/cudd/cuddCompose.c2
-rw-r--r--src/bdd/cudd/cuddDecomp.c2
-rw-r--r--src/bdd/cudd/cuddEssent.c2
-rw-r--r--src/bdd/cudd/cuddExact.c2
-rw-r--r--src/bdd/cudd/cuddExport.c2
-rw-r--r--src/bdd/cudd/cuddGenCof.c2
-rw-r--r--src/bdd/cudd/cuddGenetic.c2
-rw-r--r--src/bdd/cudd/cuddGroup.c2
-rw-r--r--src/bdd/cudd/cuddHarwell.c2
-rw-r--r--src/bdd/cudd/cuddInit.c2
-rw-r--r--src/bdd/cudd/cuddInteract.c2
-rw-r--r--src/bdd/cudd/cuddLCache.c2
-rw-r--r--src/bdd/cudd/cuddLevelQ.c2
-rw-r--r--src/bdd/cudd/cuddLinear.c2
-rw-r--r--src/bdd/cudd/cuddLiteral.c2
-rw-r--r--src/bdd/cudd/cuddMatMult.c2
-rw-r--r--src/bdd/cudd/cuddPriority.c2
-rw-r--r--src/bdd/cudd/cuddRead.c2
-rw-r--r--src/bdd/cudd/cuddRef.c2
-rw-r--r--src/bdd/cudd/cuddReorder.c2
-rw-r--r--src/bdd/cudd/cuddSat.c2
-rw-r--r--src/bdd/cudd/cuddSign.c2
-rw-r--r--src/bdd/cudd/cuddSolve.c2
-rw-r--r--src/bdd/cudd/cuddSplit.c2
-rw-r--r--src/bdd/cudd/cuddSubsetHB.c2
-rw-r--r--src/bdd/cudd/cuddSubsetSP.c2
-rw-r--r--src/bdd/cudd/cuddSymmetry.c2
-rw-r--r--src/bdd/cudd/cuddTable.c2
-rw-r--r--src/bdd/cudd/cuddUtil.c2
-rw-r--r--src/bdd/cudd/cuddWindow.c2
-rw-r--r--src/bdd/cudd/cuddZddCount.c2
-rw-r--r--src/bdd/cudd/cuddZddFuncs.c2
-rw-r--r--src/bdd/cudd/cuddZddGroup.c2
-rw-r--r--src/bdd/cudd/cuddZddIsop.c2
-rw-r--r--src/bdd/cudd/cuddZddLin.c2
-rw-r--r--src/bdd/cudd/cuddZddMisc.c2
-rw-r--r--src/bdd/cudd/cuddZddPort.c2
-rw-r--r--src/bdd/cudd/cuddZddReord.c2
-rw-r--r--src/bdd/cudd/cuddZddSetop.c2
-rw-r--r--src/bdd/cudd/cuddZddSymm.c2
-rw-r--r--src/bdd/cudd/cuddZddUtil.c2
-rw-r--r--src/bdd/cudd/testcudd.c2
-rw-r--r--src/bdd/dsd/dsd.h29
-rw-r--r--src/bdd/dsd/dsdApi.c3
-rw-r--r--src/bdd/dsd/dsdCheck.c4
-rw-r--r--src/bdd/dsd/dsdInt.h9
-rw-r--r--src/bdd/dsd/dsdMan.c1
-rw-r--r--src/bdd/dsd/dsdProc.c4
-rw-r--r--src/bdd/dsd/dsdTree.c304
-rw-r--r--src/bdd/epd/epd.c2
-rw-r--r--src/bdd/mtr/mtrBasic.c2
-rw-r--r--src/bdd/mtr/mtrGroup.c2
-rw-r--r--src/bdd/parse/module.make1
-rw-r--r--src/bdd/parse/parse.h7
-rw-r--r--src/bdd/parse/parseCore.c2
-rw-r--r--src/bdd/parse/parseEqn.c349
-rw-r--r--src/bdd/parse/parseInt.h11
-rw-r--r--src/bdd/parse/parseStack.c10
-rw-r--r--src/bdd/reo/module.make1
-rw-r--r--src/bdd/reo/reo.h24
-rw-r--r--src/bdd/reo/reoProfile.c2
-rw-r--r--src/bdd/reo/reoShuffle.c224
-rw-r--r--src/bdd/reo/reoSwap.c26
-rw-r--r--src/bdd/reo/reoTransfer.c14
-rw-r--r--src/generic.c2
-rw-r--r--src/generic.h14
-rw-r--r--src/map/fpga/fpga.c72
-rw-r--r--src/map/fpga/fpga.h41
-rw-r--r--src/map/fpga/fpgaCore.c49
-rw-r--r--src/map/fpga/fpgaCreate.c13
-rw-r--r--src/map/fpga/fpgaCut.c54
-rw-r--r--src/map/fpga/fpgaCutUtils.c10
-rw-r--r--src/map/fpga/fpgaFanout.c2
-rw-r--r--src/map/fpga/fpgaGENERIC.c2
-rw-r--r--src/map/fpga/fpgaInt.h42
-rw-r--r--src/map/fpga/fpgaLib.c91
-rw-r--r--src/map/fpga/fpgaMatch.c40
-rw-r--r--src/map/fpga/fpgaSwitch.c6
-rw-r--r--src/map/fpga/fpgaTime.c69
-rw-r--r--src/map/fpga/fpgaTruth.c61
-rw-r--r--src/map/fpga/fpgaUtils.c53
-rw-r--r--src/map/fpga/fpgaVec.c2
-rw-r--r--src/map/if/if.h410
-rw-r--r--src/map/if/ifCore.c148
-rw-r--r--src/map/if/ifCut.c988
-rw-r--r--src/map/if/ifMan.c577
-rw-r--r--src/map/if/ifMap.c350
-rw-r--r--src/map/if/ifReduce.c575
-rw-r--r--src/map/if/ifSeq.c405
-rw-r--r--src/map/if/ifTime.c228
-rw-r--r--src/map/if/ifTruth.c404
-rw-r--r--src/map/if/ifUtil.c658
-rw-r--r--src/map/if/if_.c47
-rw-r--r--src/map/if/module.make8
-rw-r--r--src/map/mapper/mapper.c22
-rw-r--r--src/map/mapper/mapper.h23
-rw-r--r--src/map/mapper/mapperCanon.c8
-rw-r--r--src/map/mapper/mapperCore.c8
-rw-r--r--src/map/mapper/mapperCreate.c12
-rw-r--r--src/map/mapper/mapperCut.c9
-rw-r--r--src/map/mapper/mapperCutUtils.c2
-rw-r--r--src/map/mapper/mapperFanout.c2
-rw-r--r--src/map/mapper/mapperGENERIC.c2
-rw-r--r--src/map/mapper/mapperInt.h16
-rw-r--r--src/map/mapper/mapperLib.c10
-rw-r--r--src/map/mapper/mapperMatch.c2
-rw-r--r--src/map/mapper/mapperRefs.c6
-rw-r--r--src/map/mapper/mapperSuper.c2
-rw-r--r--src/map/mapper/mapperSwitch.c2
-rw-r--r--src/map/mapper/mapperTable.c6
-rw-r--r--src/map/mapper/mapperTime.c2
-rw-r--r--src/map/mapper/mapperTree.c13
-rw-r--r--src/map/mapper/mapperTruth.c13
-rw-r--r--src/map/mapper/mapperUtils.c2
-rw-r--r--src/map/mapper/mapperVec.c2
-rw-r--r--src/map/mio/mio.c28
-rw-r--r--src/map/mio/mio.h23
-rw-r--r--src/map/mio/mioApi.c32
-rw-r--r--src/map/mio/mioFunc.c6
-rw-r--r--src/map/mio/mioGENERIC.c2
-rw-r--r--src/map/mio/mioInt.h9
-rw-r--r--src/map/mio/mioRead.c39
-rw-r--r--src/map/mio/mioUtils.c10
-rw-r--r--src/map/super/super.c50
-rw-r--r--src/map/super/super.h15
-rw-r--r--src/map/super/superAnd.c12
-rw-r--r--src/map/super/superGENERIC.c2
-rw-r--r--src/map/super/superGate.c4
-rw-r--r--src/map/super/superInt.h8
-rw-r--r--src/map/super/superWrite.c2
-rw-r--r--src/misc/espresso/cofactor.c382
-rw-r--r--src/misc/espresso/cols.c314
-rw-r--r--src/misc/espresso/compl.c680
-rw-r--r--src/misc/espresso/contain.c441
-rw-r--r--src/misc/espresso/cubehack.c138
-rw-r--r--src/misc/espresso/cubestr.c152
-rw-r--r--src/misc/espresso/cvrin.c810
-rw-r--r--src/misc/espresso/cvrm.c539
-rw-r--r--src/misc/espresso/cvrmisc.c142
-rw-r--r--src/misc/espresso/cvrout.c609
-rw-r--r--src/misc/espresso/dominate.c98
-rw-r--r--src/misc/espresso/equiv.c94
-rw-r--r--src/misc/espresso/espresso.c139
-rw-r--r--src/misc/espresso/espresso.h782
-rw-r--r--src/misc/espresso/essen.c179
-rw-r--r--src/misc/espresso/exact.c181
-rw-r--r--src/misc/espresso/expand.c693
-rw-r--r--src/misc/espresso/gasp.c228
-rw-r--r--src/misc/espresso/gimpel.c106
-rw-r--r--src/misc/espresso/globals.c76
-rw-r--r--src/misc/espresso/hack.c641
-rw-r--r--src/misc/espresso/indep.c134
-rw-r--r--src/misc/espresso/irred.c440
-rw-r--r--src/misc/espresso/main.c746
-rw-r--r--src/misc/espresso/main.h122
-rw-r--r--src/misc/espresso/map.c115
-rw-r--r--src/misc/espresso/matrix.c574
-rw-r--r--src/misc/espresso/mincov.c378
-rw-r--r--src/misc/espresso/mincov.h11
-rw-r--r--src/misc/espresso/mincov_int.h55
-rw-r--r--src/misc/espresso/module.make39
-rw-r--r--src/misc/espresso/opo.c624
-rw-r--r--src/misc/espresso/pair.c675
-rw-r--r--src/misc/espresso/part.c122
-rw-r--r--src/misc/espresso/primes.c170
-rw-r--r--src/misc/espresso/reduce.c258
-rw-r--r--src/misc/espresso/rows.c314
-rw-r--r--src/misc/espresso/set.c820
-rw-r--r--src/misc/espresso/setc.c483
-rw-r--r--src/misc/espresso/sharp.c247
-rw-r--r--src/misc/espresso/sminterf.c44
-rw-r--r--src/misc/espresso/solution.c114
-rw-r--r--src/misc/espresso/sparse.c146
-rw-r--r--src/misc/espresso/sparse.h135
-rw-r--r--src/misc/espresso/sparse_int.h121
-rw-r--r--src/misc/espresso/unate.c441
-rw-r--r--src/misc/espresso/util_old.h301
-rw-r--r--src/misc/espresso/verify.c193
-rw-r--r--src/misc/extra/extra.h364
-rw-r--r--src/misc/extra/extraBddAuto.c1558
-rw-r--r--src/misc/extra/extraBddCas.c1230
-rw-r--r--src/misc/extra/extraBddKmap.c783
-rw-r--r--src/misc/extra/extraBddMisc.c574
-rw-r--r--src/misc/extra/extraBddSymm.c2
-rw-r--r--src/misc/extra/extraBddUnate.c641
-rw-r--r--src/misc/extra/extraUtilBitMatrix.c2
-rw-r--r--src/misc/extra/extraUtilCanon.c24
-rw-r--r--src/misc/extra/extraUtilFile.c114
-rw-r--r--src/misc/extra/extraUtilMemory.c103
-rw-r--r--src/misc/extra/extraUtilMisc.c805
-rw-r--r--src/misc/extra/extraUtilProgress.c30
-rw-r--r--src/misc/extra/extraUtilReader.c21
-rw-r--r--src/misc/extra/extraUtilTruth.c1148
-rw-r--r--src/misc/extra/extraUtilUtil.c356
-rw-r--r--src/misc/extra/module.make10
-rw-r--r--src/misc/hash/hash.h65
-rw-r--r--src/misc/hash/hashFlt.h330
-rw-r--r--src/misc/hash/hashInt.h293
-rw-r--r--src/misc/hash/hashPtr.h331
-rw-r--r--src/misc/hash/module.make1
-rw-r--r--src/misc/mvc/mvc.c2
-rw-r--r--src/misc/mvc/mvc.h13
-rw-r--r--src/misc/mvc/mvcApi.c2
-rw-r--r--src/misc/mvc/mvcCompare.c2
-rw-r--r--src/misc/mvc/mvcContain.c2
-rw-r--r--src/misc/mvc/mvcCover.c2
-rw-r--r--src/misc/mvc/mvcCube.c2
-rw-r--r--src/misc/mvc/mvcDivide.c2
-rw-r--r--src/misc/mvc/mvcDivisor.c2
-rw-r--r--src/misc/mvc/mvcList.c2
-rw-r--r--src/misc/mvc/mvcLits.c2
-rw-r--r--src/misc/mvc/mvcMan.c10
-rw-r--r--src/misc/mvc/mvcOpAlg.c2
-rw-r--r--src/misc/mvc/mvcOpBool.c2
-rw-r--r--src/misc/mvc/mvcPrint.c2
-rw-r--r--src/misc/mvc/mvcSort.c2
-rw-r--r--src/misc/mvc/mvcUtils.c2
-rw-r--r--src/misc/nm/module.make2
-rw-r--r--src/misc/nm/nm.h92
-rw-r--r--src/misc/nm/nmApi.c272
-rw-r--r--src/misc/nm/nmInt.h91
-rw-r--r--src/misc/nm/nmTable.c340
-rw-r--r--src/misc/st/st.c115
-rw-r--r--src/misc/st/st.h52
-rw-r--r--src/misc/st/stmm.c105
-rw-r--r--src/misc/st/stmm.h10
-rw-r--r--src/misc/util/cpu_stats.c122
-rw-r--r--src/misc/util/cpu_time.c128
-rw-r--r--src/misc/util/datalimit.c95
-rw-r--r--src/misc/util/getopt.c84
-rw-r--r--src/misc/util/leaks.h8
-rw-r--r--src/misc/util/module.make9
-rw-r--r--src/misc/util/pathsearch.c131
-rw-r--r--src/misc/util/safe_mem.c104
-rw-r--r--src/misc/util/strsav.c157
-rw-r--r--src/misc/util/texpand.c66
-rw-r--r--src/misc/util/util.h331
-rw-r--r--src/misc/util/util_hack.h95
-rw-r--r--src/misc/vec/vec.h80
-rw-r--r--src/misc/vec/vecAtt.h (renamed from src/abc8/vec2/vecAtt.h)0
-rw-r--r--src/misc/vec/vecFan.h374
-rw-r--r--src/misc/vec/vecFlt.h (renamed from src/abc8/vec2/vecFlt.h)0
-rw-r--r--src/misc/vec/vecInt.h223
-rw-r--r--src/misc/vec/vecPtr.h290
-rw-r--r--src/misc/vec/vecStr.h88
-rw-r--r--src/misc/vec/vecVec.h114
-rw-r--r--src/opt/cut/abcCut.c492
-rw-r--r--src/opt/cut/cut.h124
-rw-r--r--src/opt/cut/cutApi.c197
-rw-r--r--src/opt/cut/cutCut.c359
-rw-r--r--src/opt/cut/cutExpand.c184
-rw-r--r--src/opt/cut/cutInt.h79
-rw-r--r--src/opt/cut/cutList.h120
-rw-r--r--src/opt/cut/cutMan.c243
-rw-r--r--src/opt/cut/cutMerge.c11
-rw-r--r--src/opt/cut/cutNode.c1072
-rw-r--r--src/opt/cut/cutOracle.c428
-rw-r--r--src/opt/cut/cutPre22.c988
-rw-r--r--src/opt/cut/cutSeq.c184
-rw-r--r--src/opt/cut/cutTable.c253
-rw-r--r--src/opt/cut/cutTruth.c314
-rw-r--r--src/opt/cut/module.make7
-rw-r--r--src/opt/dec/dec.h118
-rw-r--r--src/opt/dec/decAbc.c154
-rw-r--r--src/opt/dec/decFactor.c18
-rw-r--r--src/opt/dec/decMan.c2
-rw-r--r--src/opt/dec/decPrint.c67
-rw-r--r--src/opt/dec/decUtil.c2
-rw-r--r--src/opt/fret/fretFlow.c696
-rw-r--r--src/opt/fret/fretInit.c762
-rw-r--r--src/opt/fret/fretMain.c1059
-rw-r--r--src/opt/fret/fretTime.c763
-rw-r--r--src/opt/fret/fretime.h165
-rw-r--r--src/opt/fret/module.make5
-rw-r--r--src/opt/fxu/fxu.c19
-rw-r--r--src/opt/fxu/fxu.h21
-rw-r--r--src/opt/fxu/fxuCreate.c46
-rw-r--r--src/opt/fxu/fxuHeapD.c2
-rw-r--r--src/opt/fxu/fxuHeapS.c2
-rw-r--r--src/opt/fxu/fxuInt.h12
-rw-r--r--src/opt/fxu/fxuList.c2
-rw-r--r--src/opt/fxu/fxuMatrix.c4
-rw-r--r--src/opt/fxu/fxuPair.c2
-rw-r--r--src/opt/fxu/fxuPrint.c2
-rw-r--r--src/opt/fxu/fxuReduce.c12
-rw-r--r--src/opt/fxu/fxuSelect.c2
-rw-r--r--src/opt/fxu/fxuSingle.c140
-rw-r--r--src/opt/fxu/fxuUpdate.c5
-rw-r--r--src/opt/lpk/lpk.h84
-rw-r--r--src/opt/lpk/lpkAbcDec.c290
-rw-r--r--src/opt/lpk/lpkAbcDsd.c603
-rw-r--r--src/opt/lpk/lpkAbcMux.c235
-rw-r--r--src/opt/lpk/lpkAbcUtil.c244
-rw-r--r--src/opt/lpk/lpkCore.c659
-rw-r--r--src/opt/lpk/lpkCut.c683
-rw-r--r--src/opt/lpk/lpkInt.h246
-rw-r--r--src/opt/lpk/lpkMan.c122
-rw-r--r--src/opt/lpk/lpkMap.c205
-rw-r--r--src/opt/lpk/lpkMulti.c495
-rw-r--r--src/opt/lpk/lpkMux.c247
-rw-r--r--src/opt/lpk/lpkSets.c440
-rw-r--r--src/opt/lpk/lpk_.c48
-rw-r--r--src/opt/lpk/module.make11
-rw-r--r--src/opt/res/module.make7
-rw-r--r--src/opt/res/res.h75
-rw-r--r--src/opt/res/resCore.c419
-rw-r--r--src/opt/res/resDivs.c285
-rw-r--r--src/opt/res/resFilter.c434
-rw-r--r--src/opt/res/resInt.h137
-rw-r--r--src/opt/res/resSat.c407
-rw-r--r--src/opt/res/resSim.c790
-rw-r--r--src/opt/res/resSim_old.c521
-rw-r--r--src/opt/res/resStrash.c117
-rw-r--r--src/opt/res/resWin.c485
-rw-r--r--src/opt/res/res_.c50
-rw-r--r--src/opt/ret/module.make8
-rw-r--r--src/opt/ret/retArea.c540
-rw-r--r--src/opt/ret/retCore.c132
-rw-r--r--src/opt/ret/retDelay.c305
-rw-r--r--src/opt/ret/retFlow.c783
-rw-r--r--src/opt/ret/retIncrem.c464
-rw-r--r--src/opt/ret/retInit.c349
-rw-r--r--src/opt/ret/retInt.h80
-rw-r--r--src/opt/ret/retLvalue.c395
-rw-r--r--src/opt/ret/ret_.c48
-rw-r--r--src/opt/rwr/rwr.h40
-rw-r--r--src/opt/rwr/rwrDec.c7
-rw-r--r--src/opt/rwr/rwrEva.c431
-rw-r--r--src/opt/rwr/rwrExp.c2
-rw-r--r--src/opt/rwr/rwrLib.c2
-rw-r--r--src/opt/rwr/rwrMan.c79
-rw-r--r--src/opt/rwr/rwrPrint.c33
-rw-r--r--src/opt/rwr/rwrTemp.c121
-rw-r--r--src/opt/rwr/rwrUtil.c2
-rw-r--r--src/opt/sim/module.make1
-rw-r--r--src/opt/sim/sim.h38
-rw-r--r--src/opt/sim/simMan.c43
-rw-r--r--src/opt/sim/simSat.c2
-rw-r--r--src/opt/sim/simSeq.c171
-rw-r--r--src/opt/sim/simSupp.c17
-rw-r--r--src/opt/sim/simSwitch.c6
-rw-r--r--src/opt/sim/simSym.c5
-rw-r--r--src/opt/sim/simSymSat.c8
-rw-r--r--src/opt/sim/simSymSim.c12
-rw-r--r--src/opt/sim/simSymStr.c12
-rw-r--r--src/opt/sim/simUtils.c210
-rw-r--r--src/phys/place/Makefile30
-rw-r--r--src/phys/place/README50
-rw-r--r--src/phys/place/hpwl57
-rw-r--r--src/phys/place/libhmetis.h31
-rw-r--r--src/phys/place/module.make10
-rw-r--r--src/phys/place/place_base.c345
-rw-r--r--src/phys/place/place_base.h137
-rw-r--r--src/phys/place/place_bin.c277
-rw-r--r--src/phys/place/place_genqp.c309
-rw-r--r--src/phys/place/place_gordian.c160
-rw-r--r--src/phys/place/place_gordian.h78
-rw-r--r--src/phys/place/place_inc.c106
-rw-r--r--src/phys/place/place_io.c94
-rw-r--r--src/phys/place/place_legalize.c23
-rw-r--r--src/phys/place/place_pads.c141
-rw-r--r--src/phys/place/place_partition.c1135
-rw-r--r--src/phys/place/place_qpsolver.c1270
-rw-r--r--src/phys/place/place_qpsolver.h140
-rw-r--r--src/phys/place/place_test.c360
-rw-r--r--src/sat/asat/added.c126
-rw-r--r--src/sat/asat/main.c195
-rw-r--r--src/sat/asat/module.make2
-rw-r--r--src/sat/asat/solver.c1167
-rw-r--r--src/sat/asat/solver.h137
-rw-r--r--src/sat/asat/solver_vec.h53
-rw-r--r--src/sat/bsat/module.make (renamed from src/abc8/bsat/module.make)1
-rw-r--r--src/sat/bsat/satInter.c (renamed from src/abc8/bsat/satInter.c)0
-rw-r--r--src/sat/bsat/satInterA.c (renamed from src/abc8/bsat/satInterA.c)0
-rw-r--r--src/sat/bsat/satMem.c (renamed from src/abc8/bsat/satMem.c)0
-rw-r--r--src/sat/bsat/satMem.h (renamed from src/abc8/bsat/satMem.h)0
-rw-r--r--src/sat/bsat/satSolver.c (renamed from src/abc8/bsat/satSolver.c)0
-rw-r--r--src/sat/bsat/satSolver.h (renamed from src/abc8/bsat/satSolver.h)0
-rw-r--r--src/sat/bsat/satStore.c (renamed from src/abc8/bsat/satStore.c)0
-rw-r--r--src/sat/bsat/satStore.h (renamed from src/abc8/bsat/satStore.h)0
-rw-r--r--src/sat/bsat/satTrace.c (renamed from src/abc8/bsat/satTrace.c)0
-rw-r--r--src/sat/bsat/satUtil.c (renamed from src/abc8/bsat/satUtil.c)0
-rw-r--r--src/sat/bsat/satVec.h (renamed from src/abc8/bsat/satVec.h)0
-rw-r--r--src/sat/csat/csat_apis.c386
-rw-r--r--src/sat/csat/csat_apis.h154
-rw-r--r--src/sat/fraig/fraig.h82
-rw-r--r--src/sat/fraig/fraigApi.c8
-rw-r--r--src/sat/fraig/fraigCanon.c12
-rw-r--r--src/sat/fraig/fraigChoice.c241
-rw-r--r--src/sat/fraig/fraigFanout.c2
-rw-r--r--src/sat/fraig/fraigFeed.c6
-rw-r--r--src/sat/fraig/fraigInt.h24
-rw-r--r--src/sat/fraig/fraigMan.c310
-rw-r--r--src/sat/fraig/fraigMem.c4
-rw-r--r--src/sat/fraig/fraigNode.c3
-rw-r--r--src/sat/fraig/fraigPrime.c8
-rw-r--r--src/sat/fraig/fraigSat.c461
-rw-r--r--src/sat/fraig/fraigTable.c2
-rw-r--r--src/sat/fraig/fraigUtil.c2
-rw-r--r--src/sat/fraig/fraigVec.c2
-rw-r--r--src/sat/msat/msat.h20
-rw-r--r--src/sat/msat/msatActivity.c6
-rw-r--r--src/sat/msat/msatClause.c7
-rw-r--r--src/sat/msat/msatClauseVec.c2
-rw-r--r--src/sat/msat/msatInt.h10
-rw-r--r--src/sat/msat/msatMem.c4
-rw-r--r--src/sat/msat/msatOrderH.c2
-rw-r--r--src/sat/msat/msatOrderJ.c46
-rw-r--r--src/sat/msat/msatQueue.c2
-rw-r--r--src/sat/msat/msatRead.c2
-rw-r--r--src/sat/msat/msatSolverApi.c50
-rw-r--r--src/sat/msat/msatSolverCore.c33
-rw-r--r--src/sat/msat/msatSolverIo.c2
-rw-r--r--src/sat/msat/msatSolverSearch.c10
-rw-r--r--src/sat/msat/msatSort.c2
-rw-r--r--src/sat/msat/msatVec.c2
-rw-r--r--src/sat/proof/pr.c1263
-rw-r--r--src/sat/proof/pr.h65
-rw-r--r--src/sat/proof/stats.txt66
-rw-r--r--todo.txt26
798 files changed, 155853 insertions, 17514 deletions
diff --git a/Makefile b/Makefile
index adb4cf94..3b680f92 100644
--- a/Makefile
+++ b/Makefile
@@ -6,22 +6,30 @@ CP := cp
PROG := abc
-MODULES := src/base/abc src/base/abci src/base/abcs src/base/cmd src/base/io src/base/main \
- src/bdd/cudd src/bdd/dsd src/bdd/epd src/bdd/mtr src/bdd/parse src/bdd/reo \
- src/map/fpga src/map/mapper src/map/mio src/map/super \
- src/misc/extra src/misc/mvc src/misc/st src/misc/util src/misc/vec \
- src/opt/cut src/opt/dec src/opt/fxu src/opt/rwr src/opt/sim \
- src/sat/asat src/sat/csat src/sat/msat src/sat/fraig
+MODULES := src/base/abc src/base/abci src/base/cmd \
+ src/base/io src/base/main src/base/ver \
+ src/bdd/cudd src/bdd/dsd src/bdd/epd src/bdd/mtr \
+ src/bdd/parse src/bdd/reo src/bdd/cas \
+ src/map/fpga src/map/mapper src/map/mio src/map/super src/map/if \
+ src/misc/extra src/misc/mvc src/misc/st src/misc/util \
+ src/misc/espresso src/misc/nm src/misc/vec src/misc/hash \
+ src/opt/cut src/opt/dec src/opt/fxu src/opt/rwr \
+ src/opt/sim src/opt/ret src/opt/res src/opt/lpk src/opt/fret \
+ src/sat/bsat src/sat/csat src/sat/msat src/sat/fraig \
+ src/aig/ivy src/aig/hop src/aig/rwt src/aig/deco \
+ src/aig/mem src/aig/dar src/aig/fra src/aig/cnf \
+ src/aig/csw src/aig/ioa src/aig/aig src/aig/kit \
+ src/aig/bdc src/aig/bar src/aig/ntl src/aig/tim
default: $(PROG)
-OPTFLAGS := -DNDEBUG -O3
-#OPTFLAGS := -g -O
+#OPTFLAGS := -DNDEBUG -O3
+OPTFLAGS := -g -O
CFLAGS += -Wall -Wno-unused-function $(OPTFLAGS) $(patsubst %, -I%, $(MODULES))
CXXFLAGS += $(CFLAGS)
-LIBS :=
+LIBS := -ldl -rdynamic -lreadline -ltermcap
SRC :=
GARBAGE := core core.* *.stackdump ./tags $(PROG)
@@ -59,6 +67,10 @@ tags:
$(PROG): $(OBJ)
$(LD) -o $@ $^ $(LIBS)
+lib$(PROG).a: $(OBJ)
+ ar rv $@ $?
+ ranlib $@
+
docs:
doxygen doxygen.conf
diff --git a/abc.dsp b/abc.dsp
index e5f2bd63..c44a610e 100644
--- a/abc.dsp
+++ b/abc.dsp
@@ -42,7 +42,7 @@ RSC=rc.exe
# PROP Ignore_Export_Lib 0
# PROP Target_Dir ""
# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c
-# ADD CPP /nologo /W3 /GX /O2 /I "src\base\abc" /I "src\base\cmd" /I "src\base\io" /I "src\base\main" /I "src\bdd\cudd" /I "src\bdd\epd" /I "src\bdd\mtr" /I "src\bdd\parse" /I "src\bdd\dsd" /I "src\bdd\reo" /I "src\sop\ft" /I "src\sat\asat" /I "src\sat\msat" /I "src\sat\fraig" /I "src\opt\cut" /I "src\opt\dec" /I "src\opt\fxu" /I "src\opt\rwr" /I "src\map\fpga" /I "src\map\mapper" /I "src\map\mio" /I "src\map\super" /I "src\misc\extra" /I "src\misc\st" /I "src\misc\mvc" /I "src\misc\util" /I "src\misc\vec" /I "src\misc\hop" /I "src\abc8\aig" /I "src\abc8\bsat" /I "src\abc8\cnf" /I "src\abc8\dar" /I "src\abc8\fra" /I "src\abc8\vec2" /I "src\abc8\ioa" /I "src\abc8\kit" /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /D "__STDC__" /D "HAVE_ASSERT_H" /FR /YX /FD /c
+# ADD CPP /nologo /W3 /GX /O2 /I "src/base/abc" /I "src/base/abci" /I "src/base/cmd" /I "src/base/io" /I "src/base/main" /I "src/base/ver" /I "src/bdd/cudd" /I "src/bdd/dsd" /I "src/bdd/epd" /I "src/bdd/mtr" /I "src/bdd/parse" /I "src/bdd/reo" /I "src/bdd/cas" /I "src/map/fpga" /I "src/map/mapper" /I "src/map/mio" /I "src/map/super" /I "src/map/if" /I "src/map/pcm" /I "src/map/ply" /I "src/misc/extra" /I "src/misc/mvc" /I "src/misc/st" /I "src/misc/util" /I "src/misc/espresso" /I "src/misc/nm" /I "src/misc/vec" /I "src/misc/hash" /I "src/opt/cut" /I "src/opt/dec" /I "src/opt/fxu" /I "src/opt/rwr" /I "src/opt/sim" /I "src/opt/ret" /I "src/opt/res" /I "src/opt/lpk" /I "src/sat/bsat" /I "src/sat/csat" /I "src/sat/msat" /I "src/sat/fraig" /I "src/aig/ivy" /I "src/aig/hop" /I "src/aig/rwt" /I "src/aig/deco" /I "src/aig/mem" /I "src/aig/dar" /I "src/aig/fra" /I "src/aig/cnf" /I "src/aig/csw" /I "src/aig/ioa" /I "src/aig/aig" /I "src/aig/kit" /I "src/aig/bdc" /I "src/aig/bar" /I "src/aig/ntl" /I "src/aig/tim" /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /D "__STDC__" /FR /YX /FD /c
# ADD BASE RSC /l 0x409 /d "NDEBUG"
# ADD RSC /l 0x409 /d "NDEBUG"
BSC32=bscmake.exe
@@ -50,7 +50,7 @@ BSC32=bscmake.exe
# ADD BSC32 /nologo
LINK32=link.exe
# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386
-# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386 /out:"_TEST/abc.exe"
+# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /profile /machine:I386 /out:"_TEST/abc.exe"
!ELSEIF "$(CFG)" == "abc - Win32 Debug"
@@ -66,7 +66,7 @@ LINK32=link.exe
# PROP Ignore_Export_Lib 0
# PROP Target_Dir ""
# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /GZ /c
-# ADD CPP /nologo /W3 /Gm /GX /ZI /Od /I "src\base\abc" /I "src\base\cmd" /I "src\base\io" /I "src\base\main" /I "src\bdd\cudd" /I "src\bdd\epd" /I "src\bdd\mtr" /I "src\bdd\parse" /I "src\bdd\dsd" /I "src\bdd\reo" /I "src\sop\ft" /I "src\sat\asat" /I "src\sat\msat" /I "src\sat\fraig" /I "src\opt\cut" /I "src\opt\dec" /I "src\opt\fxu" /I "src\opt\rwr" /I "src\map\fpga" /I "src\map\mapper" /I "src\map\mio" /I "src\map\super" /I "src\misc\extra" /I "src\misc\st" /I "src\misc\mvc" /I "src\misc\util" /I "src\misc\vec" /I "src\misc\hop" /I "src\abc8\aig" /I "src\abc8\bsat" /I "src\abc8\cnf" /I "src\abc8\dar" /I "src\abc8\fra" /I "src\abc8\vec2" /I "src\abc8\ioa" /I "src\abc8\kit" /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /D "__STDC__" /D "HAVE_ASSERT_H" /FR /YX /FD /GZ /c
+# ADD CPP /nologo /W3 /Gm /GX /ZI /Od /I "src/base/abc" /I "src/base/abci" /I "src/base/cmd" /I "src/base/io" /I "src/base/main" /I "src/base/ver" /I "src/bdd/cudd" /I "src/bdd/dsd" /I "src/bdd/epd" /I "src/bdd/mtr" /I "src/bdd/parse" /I "src/bdd/reo" /I "src/bdd/cas" /I "src/map/fpga" /I "src/map/mapper" /I "src/map/mio" /I "src/map/super" /I "src/map/if" /I "src/map/pcm" /I "src/map/ply" /I "src/misc/extra" /I "src/misc/mvc" /I "src/misc/st" /I "src/misc/util" /I "src/misc/espresso" /I "src/misc/nm" /I "src/misc/vec" /I "src/misc/hash" /I "src/opt/cut" /I "src/opt/dec" /I "src/opt/fxu" /I "src/opt/rwr" /I "src/opt/sim" /I "src/opt/ret" /I "src/opt/res" /I "src/opt/lpk" /I "src/sat/bsat" /I "src/sat/csat" /I "src/sat/msat" /I "src/sat/fraig" /I "src/aig/ivy" /I "src/aig/hop" /I "src/aig/rwt" /I "src/aig/deco" /I "src/aig/mem" /I "src/aig/dar" /I "src/aig/fra" /I "src/aig/cnf" /I "src/aig/csw" /I "src/aig/ioa" /I "src/aig/aig" /I "src/aig/kit" /I "src/aig/bdc" /I "src/aig/bar" /I "src/aig/ntl" /I "src/aig/tim" /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /D "__STDC__" /FR /YX /FD /GZ /c
# SUBTRACT CPP /X
# ADD BASE RSC /l 0x409 /d "_DEBUG"
# ADD RSC /l 0x409 /d "_DEBUG"
@@ -102,6 +102,10 @@ SOURCE=.\src\base\abc\abcAig.c
# End Source File
# Begin Source File
+SOURCE=.\src\base\abc\abcBlifMv.c
+# End Source File
+# Begin Source File
+
SOURCE=.\src\base\abc\abcCheck.c
# End Source File
# Begin Source File
@@ -118,6 +122,10 @@ SOURCE=.\src\base\abc\abcFunc.c
# End Source File
# Begin Source File
+SOURCE=.\src\base\abc\abcHie.c
+# End Source File
+# Begin Source File
+
SOURCE=.\src\base\abc\abcInt.h
# End Source File
# Begin Source File
@@ -126,6 +134,10 @@ SOURCE=.\src\base\abc\abcLatch.c
# End Source File
# Begin Source File
+SOURCE=.\src\base\abc\abcLib.c
+# End Source File
+# Begin Source File
+
SOURCE=.\src\base\abc\abcMinBase.c
# End Source File
# Begin Source File
@@ -174,11 +186,27 @@ SOURCE=.\src\base\abci\abcAttach.c
# End Source File
# Begin Source File
+SOURCE=.\src\base\abci\abcAuto.c
+# End Source File
+# Begin Source File
+
SOURCE=.\src\base\abci\abcBalance.c
# End Source File
# Begin Source File
-SOURCE=.\src\base\abci\abcCollapse.c
+SOURCE=.\src\base\abci\abcBmc.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\base\abci\abcCas.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\base\abci\abcClpBdd.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\base\abci\abcClpSop.c
# End Source File
# Begin Source File
@@ -190,14 +218,34 @@ SOURCE=.\src\base\abci\abcDar.c
# End Source File
# Begin Source File
+SOURCE=.\src\base\abci\abcDebug.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\base\abci\abcDress.c
+# End Source File
+# Begin Source File
+
SOURCE=.\src\base\abci\abcDsd.c
# End Source File
# Begin Source File
+SOURCE=.\src\base\abci\abcEspresso.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\base\abci\abcExtract.c
+# End Source File
+# Begin Source File
+
SOURCE=.\src\base\abci\abcFpga.c
# End Source File
# Begin Source File
+SOURCE=.\src\base\abci\abcFpgaFast.c
+# End Source File
+# Begin Source File
+
SOURCE=.\src\base\abci\abcFraig.c
# End Source File
# Begin Source File
@@ -206,22 +254,62 @@ SOURCE=.\src\base\abci\abcFxu.c
# End Source File
# Begin Source File
+SOURCE=.\src\base\abci\abcGen.c
+# End Source File
+# Begin Source File
+
SOURCE=.\src\base\abci\abcHaig.c
# End Source File
# Begin Source File
+SOURCE=.\src\base\abci\abcIf.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\base\abci\abcIvy.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\base\abci\abcLut.c
+# End Source File
+# Begin Source File
+
SOURCE=.\src\base\abci\abcMap.c
# End Source File
# Begin Source File
+SOURCE=.\src\base\abci\abcMeasure.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\base\abci\abcMini.c
+# End Source File
+# Begin Source File
+
SOURCE=.\src\base\abci\abcMiter.c
# End Source File
# Begin Source File
+SOURCE=.\src\base\abci\abcMulti.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\base\abci\abcMv.c
+# End Source File
+# Begin Source File
+
SOURCE=.\src\base\abci\abcNtbdd.c
# End Source File
# Begin Source File
+SOURCE=.\src\base\abci\abcOdc.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\base\abci\abcOrder.c
+# End Source File
+# Begin Source File
+
SOURCE=.\src\base\abci\abcPart.c
# End Source File
# Begin Source File
@@ -230,6 +318,22 @@ SOURCE=.\src\base\abci\abcPrint.c
# End Source File
# Begin Source File
+SOURCE=.\src\base\abci\abcProve.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\base\abci\abcQbf.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\base\abci\abcQuant.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\base\abci\abcRec.c
+# End Source File
+# Begin Source File
+
SOURCE=.\src\base\abci\abcReconv.c
# End Source File
# Begin Source File
@@ -242,10 +346,26 @@ SOURCE=.\src\base\abci\abcRenode.c
# End Source File
# Begin Source File
+SOURCE=.\src\base\abci\abcReorder.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\base\abci\abcRestruct.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\base\abci\abcResub.c
+# End Source File
+# Begin Source File
+
SOURCE=.\src\base\abci\abcRewrite.c
# End Source File
# Begin Source File
+SOURCE=.\src\base\abci\abcRr.c
+# End Source File
+# Begin Source File
+
SOURCE=.\src\base\abci\abcSat.c
# End Source File
# Begin Source File
@@ -266,23 +386,19 @@ SOURCE=.\src\base\abci\abcTiming.c
# End Source File
# Begin Source File
-SOURCE=.\src\base\abci\abcUnreach.c
+SOURCE=.\src\base\abci\abcUnate.c
# End Source File
# Begin Source File
-SOURCE=.\src\base\abci\abcVerify.c
+SOURCE=.\src\base\abci\abcUnreach.c
# End Source File
-# End Group
-# Begin Group "abcs"
-
-# PROP Default_Filter ""
# Begin Source File
-SOURCE=.\src\base\abcs\abcRetime.c
+SOURCE=.\src\base\abci\abcVerify.c
# End Source File
# Begin Source File
-SOURCE=.\src\base\abcs\abcSeq.c
+SOURCE=.\src\base\abci\abcXsim.c
# End Source File
# End Group
# Begin Group "cmd"
@@ -338,7 +454,11 @@ SOURCE=.\src\base\io\ioInt.h
# End Source File
# Begin Source File
-SOURCE=.\src\base\io\ioRead.c
+SOURCE=.\src\base\io\ioReadAiger.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\base\io\ioReadBaf.c
# End Source File
# Begin Source File
@@ -350,6 +470,18 @@ SOURCE=.\src\base\io\ioReadBlif.c
# End Source File
# Begin Source File
+SOURCE=.\src\base\io\ioReadBlifAig.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\base\io\ioReadBlifMv.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\base\io\ioReadDsd.c
+# End Source File
+# Begin Source File
+
SOURCE=.\src\base\io\ioReadEdif.c
# End Source File
# Begin Source File
@@ -370,6 +502,14 @@ SOURCE=.\src\base\io\ioUtil.c
# End Source File
# Begin Source File
+SOURCE=.\src\base\io\ioWriteAiger.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\base\io\ioWriteBaf.c
+# End Source File
+# Begin Source File
+
SOURCE=.\src\base\io\ioWriteBench.c
# End Source File
# Begin Source File
@@ -378,6 +518,10 @@ SOURCE=.\src\base\io\ioWriteBlif.c
# End Source File
# Begin Source File
+SOURCE=.\src\base\io\ioWriteBlifMv.c
+# End Source File
+# Begin Source File
+
SOURCE=.\src\base\io\ioWriteCnf.c
# End Source File
# Begin Source File
@@ -394,14 +538,26 @@ SOURCE=.\src\base\io\ioWriteGml.c
# End Source File
# Begin Source File
+SOURCE=.\src\base\io\ioWriteList.c
+# End Source File
+# Begin Source File
+
SOURCE=.\src\base\io\ioWritePla.c
# End Source File
+# Begin Source File
+
+SOURCE=.\src\base\io\ioWriteVerilog.c
+# End Source File
# End Group
# Begin Group "main"
# PROP Default_Filter ""
# Begin Source File
+SOURCE=.\src\base\main\libSupport.c
+# End Source File
+# Begin Source File
+
SOURCE=.\src\base\main\main.c
# End Source File
# Begin Source File
@@ -425,6 +581,30 @@ SOURCE=.\src\base\main\mainInt.h
SOURCE=.\src\base\main\mainUtils.c
# End Source File
# End Group
+# Begin Group "ver"
+
+# PROP Default_Filter ""
+# Begin Source File
+
+SOURCE=.\src\base\ver\ver.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\base\ver\verCore.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\base\ver\verFormula.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\base\ver\verParse.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\base\ver\verStream.c
+# End Source File
+# End Group
# End Group
# Begin Group "bdd"
@@ -730,6 +910,10 @@ SOURCE=.\src\bdd\parse\parseCore.c
# End Source File
# Begin Source File
+SOURCE=.\src\bdd\parse\parseEqn.c
+# End Source File
+# Begin Source File
+
SOURCE=.\src\bdd\parse\parseInt.h
# End Source File
# Begin Source File
@@ -794,6 +978,10 @@ SOURCE=.\src\bdd\reo\reoProfile.c
# End Source File
# Begin Source File
+SOURCE=.\src\bdd\reo\reoShuffle.c
+# End Source File
+# Begin Source File
+
SOURCE=.\src\bdd\reo\reoSift.c
# End Source File
# Begin Source File
@@ -813,30 +1001,26 @@ SOURCE=.\src\bdd\reo\reoTransfer.c
SOURCE=.\src\bdd\reo\reoUnits.c
# End Source File
# End Group
-# End Group
-# Begin Group "sat"
-
-# PROP Default_Filter ""
-# Begin Group "asat"
+# Begin Group "cas"
# PROP Default_Filter ""
# Begin Source File
-SOURCE=.\src\sat\asat\added.c
+SOURCE=.\src\bdd\cas\cas.h
# End Source File
# Begin Source File
-SOURCE=.\src\sat\asat\solver.c
+SOURCE=.\src\bdd\cas\casCore.c
# End Source File
# Begin Source File
-SOURCE=.\src\sat\asat\solver.h
-# End Source File
-# Begin Source File
-
-SOURCE=.\src\sat\asat\solver_vec.h
+SOURCE=.\src\bdd\cas\casDec.c
# End Source File
# End Group
+# End Group
+# Begin Group "sat"
+
+# PROP Default_Filter ""
# Begin Group "msat"
# PROP Default_Filter ""
@@ -866,7 +1050,7 @@ SOURCE=.\src\sat\msat\msatMem.c
# End Source File
# Begin Source File
-SOURCE=.\src\sat\msat\msatOrderJ.c
+SOURCE=.\src\sat\msat\msatOrderH.c
# End Source File
# Begin Source File
@@ -918,6 +1102,10 @@ 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
@@ -973,6 +1161,66 @@ SOURCE=.\src\sat\csat\csat_apis.c
SOURCE=.\src\sat\csat\csat_apis.h
# End Source File
# End Group
+# Begin Group "bsat"
+
+# PROP Default_Filter ""
+# Begin Source File
+
+SOURCE=.\src\sat\bsat\satInter.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\sat\bsat\satInterA.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\sat\bsat\satMem.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\sat\bsat\satMem.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\sat\bsat\satSolver.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\sat\bsat\satSolver.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\sat\bsat\satStore.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\sat\bsat\satStore.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\sat\bsat\satTrace.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\sat\bsat\satUtil.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\sat\bsat\satVec.h
+# End Source File
+# End Group
+# Begin Group "proof"
+
+# PROP Default_Filter ""
+# Begin Source File
+
+SOURCE=.\src\sat\proof\pr.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\sat\proof\pr.h
+# End Source File
+# End Group
# End Group
# Begin Group "opt"
@@ -1070,6 +1318,10 @@ SOURCE=.\src\opt\rwr\rwrPrint.c
# End Source File
# Begin Source File
+SOURCE=.\src\opt\rwr\rwrTemp.c
+# End Source File
+# Begin Source File
+
SOURCE=.\src\opt\rwr\rwrUtil.c
# End Source File
# End Group
@@ -1082,6 +1334,18 @@ SOURCE=.\src\opt\cut\cut.h
# End Source File
# Begin Source File
+SOURCE=.\src\opt\cut\cutApi.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\opt\cut\cutCut.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\opt\cut\cutExpand.c
+# End Source File
+# Begin Source File
+
SOURCE=.\src\opt\cut\cutInt.h
# End Source File
# Begin Source File
@@ -1102,11 +1366,15 @@ SOURCE=.\src\opt\cut\cutNode.c
# End Source File
# Begin Source File
-SOURCE=.\src\opt\cut\cutSeq.c
+SOURCE=.\src\opt\cut\cutOracle.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\opt\cut\cutPre22.c
# End Source File
# Begin Source File
-SOURCE=.\src\opt\cut\cutTable.c
+SOURCE=.\src\opt\cut\cutSeq.c
# End Source File
# Begin Source File
@@ -1158,6 +1426,10 @@ SOURCE=.\src\opt\sim\simSat.c
# End Source File
# Begin Source File
+SOURCE=.\src\opt\sim\simSeq.c
+# End Source File
+# Begin Source File
+
SOURCE=.\src\opt\sim\simSupp.c
# End Source File
# Begin Source File
@@ -1185,6 +1457,162 @@ SOURCE=.\src\opt\sim\simSymStr.c
SOURCE=.\src\opt\sim\simUtils.c
# End Source File
# End Group
+# Begin Group "ret"
+
+# PROP Default_Filter ""
+# Begin Source File
+
+SOURCE=.\src\opt\ret\retArea.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\opt\ret\retCore.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\opt\ret\retDelay.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\opt\ret\retFlow.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\opt\ret\retIncrem.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\opt\ret\retInit.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\opt\ret\retInt.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\opt\ret\retLvalue.c
+# End Source File
+# End Group
+# Begin Group "res"
+
+# PROP Default_Filter ""
+# Begin Source File
+
+SOURCE=.\src\opt\res\res.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\opt\res\resCore.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\opt\res\resDivs.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\opt\res\resFilter.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\opt\res\resInt.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\opt\res\resSat.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\opt\res\resSim.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\opt\res\resStrash.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\opt\res\resWin.c
+# End Source File
+# End Group
+# Begin Group "lpk"
+
+# PROP Default_Filter ""
+# Begin Source File
+
+SOURCE=.\src\opt\lpk\lpk.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\opt\lpk\lpkAbcDec.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\opt\lpk\lpkAbcDsd.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\opt\lpk\lpkAbcMux.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\opt\lpk\lpkAbcUtil.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\opt\lpk\lpkCore.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\opt\lpk\lpkCut.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\opt\lpk\lpkInt.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\opt\lpk\lpkMan.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\opt\lpk\lpkMap.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\opt\lpk\lpkMulti.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\opt\lpk\lpkMux.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\opt\lpk\lpkSets.c
+# End Source File
+# End Group
+# Begin Group "fret"
+
+# PROP Default_Filter ""
+# Begin Source File
+
+SOURCE=.\src\opt\fret\fretFlow.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\opt\fret\fretime.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\opt\fret\fretInit.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\opt\fret\fretMain.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\opt\fret\fretTime.c
+# End Source File
+# End Group
# End Group
# Begin Group "map"
@@ -1397,120 +1825,220 @@ SOURCE=.\src\map\super\superInt.h
SOURCE=.\src\map\super\superWrite.c
# End Source File
# End Group
-# End Group
-# Begin Group "misc"
+# Begin Group "if"
# PROP Default_Filter ""
-# Begin Group "extra"
+# Begin Source File
-# PROP Default_Filter ""
+SOURCE=.\src\map\if\if.h
+# End Source File
# Begin Source File
-SOURCE=.\src\misc\extra\extra.h
+SOURCE=.\src\map\if\ifCore.c
# End Source File
# Begin Source File
-SOURCE=.\src\misc\extra\extraBddMisc.c
+SOURCE=.\src\map\if\ifCut.c
# End Source File
# Begin Source File
-SOURCE=.\src\misc\extra\extraBddSymm.c
+SOURCE=.\src\map\if\ifMan.c
# End Source File
# Begin Source File
-SOURCE=.\src\misc\extra\extraUtilBitMatrix.c
+SOURCE=.\src\map\if\ifMap.c
# End Source File
# Begin Source File
-SOURCE=.\src\misc\extra\extraUtilCanon.c
+SOURCE=.\src\map\if\ifReduce.c
# End Source File
# Begin Source File
-SOURCE=.\src\misc\extra\extraUtilFile.c
+SOURCE=.\src\map\if\ifTime.c
# End Source File
# Begin Source File
-SOURCE=.\src\misc\extra\extraUtilMemory.c
+SOURCE=.\src\map\if\ifTruth.c
# End Source File
# Begin Source File
-SOURCE=.\src\misc\extra\extraUtilMisc.c
+SOURCE=.\src\map\if\ifUtil.c
# End Source File
+# End Group
+# Begin Group "pcm"
+
+# PROP Default_Filter ""
# Begin Source File
-SOURCE=.\src\misc\extra\extraUtilProgress.c
+SOURCE=.\src\map\pcm\pcmCore.c
# End Source File
# Begin Source File
-SOURCE=.\src\misc\extra\extraUtilReader.c
+SOURCE=.\src\map\pcm\pcmCut.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\map\pcm\pcmInt.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\map\pcm\pcmMan.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\map\pcm\pcmMap.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\map\pcm\pcmReduce.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\map\pcm\pcmTime.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\map\pcm\pcmTruth.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\map\pcm\pcmUtil.c
# End Source File
# End Group
-# Begin Group "st"
+# Begin Group "ply"
# PROP Default_Filter ""
# Begin Source File
-SOURCE=.\src\misc\st\st.c
+SOURCE=.\src\map\ply\ply.h
# End Source File
# Begin Source File
-SOURCE=.\src\misc\st\st.h
+SOURCE=.\src\map\ply\plyAbc.c
# End Source File
# Begin Source File
-SOURCE=.\src\misc\st\stmm.c
+SOURCE=.\src\map\ply\plyAig.c
# End Source File
# Begin Source File
-SOURCE=.\src\misc\st\stmm.h
+SOURCE=.\src\map\ply\plyInt.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\map\ply\plyIter.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\map\ply\plyLib.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\map\ply\plyMan.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\map\ply\plyMap.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\map\ply\plyNtk.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\map\ply\plyPar.c
# End Source File
# End Group
-# Begin Group "util"
+# End Group
+# Begin Group "misc"
+
+# PROP Default_Filter ""
+# Begin Group "extra"
# PROP Default_Filter ""
# Begin Source File
-SOURCE=.\src\misc\util\cpu_stats.c
+SOURCE=.\src\misc\extra\extra.h
# End Source File
# Begin Source File
-SOURCE=.\src\misc\util\cpu_time.c
+SOURCE=.\src\misc\extra\extraBddAuto.c
# End Source File
# Begin Source File
-SOURCE=.\src\misc\util\datalimit.c
+SOURCE=.\src\misc\extra\extraBddCas.c
# End Source File
# Begin Source File
-SOURCE=.\src\misc\util\getopt.c
+SOURCE=.\src\misc\extra\extraBddKmap.c
# End Source File
# Begin Source File
-SOURCE=.\src\misc\util\leaks.h
+SOURCE=.\src\misc\extra\extraBddMisc.c
# End Source File
# Begin Source File
-SOURCE=.\src\misc\util\pathsearch.c
+SOURCE=.\src\misc\extra\extraBddSymm.c
# End Source File
# Begin Source File
-SOURCE=.\src\misc\util\safe_mem.c
+SOURCE=.\src\misc\extra\extraBddUnate.c
# End Source File
# Begin Source File
-SOURCE=.\src\misc\util\stdlib_hack.h
+SOURCE=.\src\misc\extra\extraUtilBitMatrix.c
# End Source File
# Begin Source File
-SOURCE=.\src\misc\util\strsav.c
+SOURCE=.\src\misc\extra\extraUtilCanon.c
# End Source File
# Begin Source File
-SOURCE=.\src\misc\util\texpand.c
+SOURCE=.\src\misc\extra\extraUtilFile.c
# End Source File
# Begin Source File
-SOURCE=.\src\misc\util\util.h
+SOURCE=.\src\misc\extra\extraUtilMemory.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\misc\extra\extraUtilMisc.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\misc\extra\extraUtilProgress.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\misc\extra\extraUtilReader.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\misc\extra\extraUtilTruth.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\misc\extra\extraUtilUtil.c
+# End Source File
+# End Group
+# Begin Group "st"
+
+# PROP Default_Filter ""
+# Begin Source File
+
+SOURCE=.\src\misc\st\st.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\misc\st\st.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\misc\st\stmm.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\misc\st\stmm.h
# End Source File
# End Group
# Begin Group "mvc"
@@ -1594,7 +2122,11 @@ SOURCE=.\src\misc\vec\vec.h
# End Source File
# Begin Source File
-SOURCE=.\src\misc\vec\vecFan.h
+SOURCE=.\src\misc\vec\vecAtt.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\misc\vec\vecFlt.h
# End Source File
# Begin Source File
@@ -1613,236 +2145,436 @@ SOURCE=.\src\misc\vec\vecStr.h
SOURCE=.\src\misc\vec\vecVec.h
# End Source File
# End Group
-# Begin Group "hop"
+# Begin Group "espresso"
# PROP Default_Filter ""
# Begin Source File
-SOURCE=.\src\misc\hop\hop.h
+SOURCE=.\src\misc\espresso\cofactor.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\misc\espresso\cols.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\misc\espresso\compl.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\misc\espresso\contain.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\misc\espresso\cubehack.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\misc\espresso\cubestr.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\misc\espresso\cvrin.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\misc\espresso\cvrm.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\misc\espresso\cvrmisc.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\misc\espresso\cvrout.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\misc\espresso\dominate.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\misc\espresso\equiv.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\misc\espresso\espresso.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\misc\espresso\espresso.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\misc\espresso\essen.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\misc\espresso\exact.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\misc\espresso\expand.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\misc\espresso\gasp.c
# End Source File
# Begin Source File
-SOURCE=.\src\misc\hop\hopBalance.c
+SOURCE=.\src\misc\espresso\gimpel.c
# End Source File
# Begin Source File
-SOURCE=.\src\misc\hop\hopCheck.c
+SOURCE=.\src\misc\espresso\globals.c
# End Source File
# Begin Source File
-SOURCE=.\src\misc\hop\hopDfs.c
+SOURCE=.\src\misc\espresso\hack.c
# End Source File
# Begin Source File
-SOURCE=.\src\misc\hop\hopMan.c
+SOURCE=.\src\misc\espresso\indep.c
# End Source File
# Begin Source File
-SOURCE=.\src\misc\hop\hopMem.c
+SOURCE=.\src\misc\espresso\irred.c
# End Source File
# Begin Source File
-SOURCE=.\src\misc\hop\hopObj.c
+SOURCE=.\src\misc\espresso\map.c
# End Source File
# Begin Source File
-SOURCE=.\src\misc\hop\hopOper.c
+SOURCE=.\src\misc\espresso\matrix.c
# End Source File
# Begin Source File
-SOURCE=.\src\misc\hop\hopTable.c
+SOURCE=.\src\misc\espresso\mincov.c
# End Source File
# Begin Source File
-SOURCE=.\src\misc\hop\hopUtil.c
+SOURCE=.\src\misc\espresso\mincov.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\misc\espresso\mincov_int.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\misc\espresso\opo.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\misc\espresso\pair.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\misc\espresso\part.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\misc\espresso\primes.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\misc\espresso\reduce.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\misc\espresso\rows.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\misc\espresso\set.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\misc\espresso\setc.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\misc\espresso\sharp.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\misc\espresso\sminterf.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\misc\espresso\solution.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\misc\espresso\sparse.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\misc\espresso\sparse.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\misc\espresso\sparse_int.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\misc\espresso\unate.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\misc\espresso\verify.c
# End Source File
# End Group
+# Begin Group "util"
+
+# PROP Default_Filter ""
+# Begin Source File
+
+SOURCE=.\src\misc\util\util_hack.h
+# End Source File
# End Group
-# Begin Group "abc8"
+# Begin Group "nm"
# PROP Default_Filter ""
-# Begin Group "aig"
+# Begin Source File
+
+SOURCE=.\src\misc\nm\nm.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\misc\nm\nmApi.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\misc\nm\nmInt.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\misc\nm\nmTable.c
+# End Source File
+# End Group
+# Begin Group "hash"
# PROP Default_Filter ""
# Begin Source File
-SOURCE=.\src\abc8\aig\aig.h
+SOURCE=.\src\misc\hash\hash.h
# End Source File
# Begin Source File
-SOURCE=.\src\abc8\aig\aigCheck.c
+SOURCE=.\src\misc\hash\hashFlt.h
# End Source File
# Begin Source File
-SOURCE=.\src\abc8\aig\aigDfs.c
+SOURCE=.\src\misc\hash\hashInt.h
# End Source File
# Begin Source File
-SOURCE=.\src\abc8\aig\aigFanout.c
+SOURCE=.\src\misc\hash\hashPtr.h
# End Source File
+# End Group
+# End Group
+# Begin Group "ai"
+
+# PROP Default_Filter ""
+# Begin Group "hop"
+
+# PROP Default_Filter ""
# Begin Source File
-SOURCE=.\src\abc8\aig\aigFrames.c
+SOURCE=.\src\aig\hop\hop.h
# End Source File
# Begin Source File
-SOURCE=.\src\abc8\aig\aigHaig.c
+SOURCE=.\src\aig\hop\hopBalance.c
# End Source File
# Begin Source File
-SOURCE=.\src\abc8\aig\aigMan.c
+SOURCE=.\src\aig\hop\hopCheck.c
# End Source File
# Begin Source File
-SOURCE=.\src\abc8\aig\aigMem.c
+SOURCE=.\src\aig\hop\hopDfs.c
# End Source File
# Begin Source File
-SOURCE=.\src\abc8\aig\aigMffc.c
+SOURCE=.\src\aig\hop\hopMan.c
# End Source File
# Begin Source File
-SOURCE=.\src\abc8\aig\aigObj.c
+SOURCE=.\src\aig\hop\hopMem.c
# End Source File
# Begin Source File
-SOURCE=.\src\abc8\aig\aigOper.c
+SOURCE=.\src\aig\hop\hopObj.c
# End Source File
# Begin Source File
-SOURCE=.\src\abc8\aig\aigOrder.c
+SOURCE=.\src\aig\hop\hopOper.c
# End Source File
# Begin Source File
-SOURCE=.\src\abc8\aig\aigPart.c
+SOURCE=.\src\aig\hop\hopTable.c
# End Source File
# Begin Source File
-SOURCE=.\src\abc8\aig\aigRepr.c
+SOURCE=.\src\aig\hop\hopUtil.c
# End Source File
+# End Group
+# Begin Group "ivy"
+
+# PROP Default_Filter ""
# Begin Source File
-SOURCE=.\src\abc8\aig\aigRet.c
+SOURCE=.\src\aig\ivy\ivy.h
# End Source File
# Begin Source File
-SOURCE=.\src\abc8\aig\aigRetF.c
+SOURCE=.\src\aig\ivy\ivyBalance.c
# End Source File
# Begin Source File
-SOURCE=.\src\abc8\aig\aigScl.c
+SOURCE=.\src\aig\ivy\ivyCanon.c
# End Source File
# Begin Source File
-SOURCE=.\src\abc8\aig\aigSeq.c
+SOURCE=.\src\aig\ivy\ivyCheck.c
# End Source File
# Begin Source File
-SOURCE=.\src\abc8\aig\aigTable.c
+SOURCE=.\src\aig\ivy\ivyCut.c
# End Source File
# Begin Source File
-SOURCE=.\src\abc8\aig\aigTiming.c
+SOURCE=.\src\aig\ivy\ivyCutTrav.c
# End Source File
# Begin Source File
-SOURCE=.\src\abc8\aig\aigTruth.c
+SOURCE=.\src\aig\ivy\ivyDfs.c
# End Source File
# Begin Source File
-SOURCE=.\src\abc8\aig\aigTsim.c
+SOURCE=.\src\aig\ivy\ivyDsd.c
# End Source File
# Begin Source File
-SOURCE=.\src\abc8\aig\aigUtil.c
+SOURCE=.\src\aig\ivy\ivyFanout.c
# End Source File
# Begin Source File
-SOURCE=.\src\abc8\aig\aigWin.c
+SOURCE=.\src\aig\ivy\ivyFastMap.c
# End Source File
-# End Group
-# Begin Group "bsat"
+# Begin Source File
-# PROP Default_Filter ""
+SOURCE=.\src\aig\ivy\ivyFraig.c
+# End Source File
# Begin Source File
-SOURCE=.\src\abc8\bsat\satInter.c
+SOURCE=.\src\aig\ivy\ivyHaig.c
# End Source File
# Begin Source File
-SOURCE=.\src\abc8\bsat\satMem.c
+SOURCE=.\src\aig\ivy\ivyMan.c
# End Source File
# Begin Source File
-SOURCE=.\src\abc8\bsat\satMem.h
+SOURCE=.\src\aig\ivy\ivyMem.c
# End Source File
# Begin Source File
-SOURCE=.\src\abc8\bsat\satSolver.c
+SOURCE=.\src\aig\ivy\ivyMulti.c
# End Source File
# Begin Source File
-SOURCE=.\src\abc8\bsat\satSolver.h
+SOURCE=.\src\aig\ivy\ivyObj.c
# End Source File
# Begin Source File
-SOURCE=.\src\abc8\bsat\satStore.c
+SOURCE=.\src\aig\ivy\ivyOper.c
# End Source File
# Begin Source File
-SOURCE=.\src\abc8\bsat\satStore.h
+SOURCE=.\src\aig\ivy\ivyResyn.c
# End Source File
# Begin Source File
-SOURCE=.\src\abc8\bsat\satTrace.c
+SOURCE=.\src\aig\ivy\ivyRwr.c
# End Source File
# Begin Source File
-SOURCE=.\src\abc8\bsat\satUtil.c
+SOURCE=.\src\aig\ivy\ivySeq.c
# End Source File
# Begin Source File
-SOURCE=.\src\abc8\bsat\satVec.h
+SOURCE=.\src\aig\ivy\ivyShow.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\aig\ivy\ivyTable.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\aig\ivy\ivyUtil.c
# End Source File
# End Group
-# Begin Group "cnf"
+# Begin Group "rwt"
# PROP Default_Filter ""
# Begin Source File
-SOURCE=.\src\abc8\cnf\cnf.h
+SOURCE=.\src\aig\rwt\rwt.h
# End Source File
# Begin Source File
-SOURCE=.\src\abc8\cnf\cnfCore.c
+SOURCE=.\src\aig\rwt\rwtDec.c
# End Source File
# Begin Source File
-SOURCE=.\src\abc8\cnf\cnfCut.c
+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\abc8\cnf\cnfData.c
+SOURCE=.\src\aig\mem\mem.c
# End Source File
# Begin Source File
-SOURCE=.\src\abc8\cnf\cnfMan.c
+SOURCE=.\src\aig\mem\mem.h
# End Source File
+# End Group
+# Begin Group "ioa"
+
+# PROP Default_Filter ""
# Begin Source File
-SOURCE=.\src\abc8\cnf\cnfMap.c
+SOURCE=.\src\aig\ioa\ioa.h
# End Source File
# Begin Source File
-SOURCE=.\src\abc8\cnf\cnfPost.c
+SOURCE=.\src\aig\ioa\ioaReadAig.c
# End Source File
# Begin Source File
-SOURCE=.\src\abc8\cnf\cnfUtil.c
+SOURCE=.\src\aig\ioa\ioaUtil.c
# End Source File
# Begin Source File
-SOURCE=.\src\abc8\cnf\cnfWrite.c
+SOURCE=.\src\aig\ioa\ioaWriteAig.c
# End Source File
# End Group
# Begin Group "dar"
@@ -1850,51 +2582,51 @@ SOURCE=.\src\abc8\cnf\cnfWrite.c
# PROP Default_Filter ""
# Begin Source File
-SOURCE=.\src\abc8\dar\dar.h
+SOURCE=.\src\aig\dar\dar.h
# End Source File
# Begin Source File
-SOURCE=.\src\abc8\dar\darBalance.c
+SOURCE=.\src\aig\dar\darBalance.c
# End Source File
# Begin Source File
-SOURCE=.\src\abc8\dar\darCore.c
+SOURCE=.\src\aig\dar\darCore.c
# End Source File
# Begin Source File
-SOURCE=.\src\abc8\dar\darCut.c
+SOURCE=.\src\aig\dar\darCut.c
# End Source File
# Begin Source File
-SOURCE=.\src\abc8\dar\darData.c
+SOURCE=.\src\aig\dar\darData.c
# End Source File
# Begin Source File
-SOURCE=.\src\abc8\dar\darInt.h
+SOURCE=.\src\aig\dar\darInt.h
# End Source File
# Begin Source File
-SOURCE=.\src\abc8\dar\darLib.c
+SOURCE=.\src\aig\dar\darLib.c
# End Source File
# Begin Source File
-SOURCE=.\src\abc8\dar\darMan.c
+SOURCE=.\src\aig\dar\darMan.c
# End Source File
# Begin Source File
-SOURCE=.\src\abc8\dar\darPrec.c
+SOURCE=.\src\aig\dar\darPrec.c
# End Source File
# Begin Source File
-SOURCE=.\src\abc8\dar\darRefact.c
+SOURCE=.\src\aig\dar\darRefact.c
# End Source File
# Begin Source File
-SOURCE=.\src\abc8\dar\darResub.c
+SOURCE=.\src\aig\dar\darResub.c
# End Source File
# Begin Source File
-SOURCE=.\src\abc8\dar\darScript.c
+SOURCE=.\src\aig\dar\darScript.c
# End Source File
# End Group
# Begin Group "fra"
@@ -1902,115 +2634,135 @@ SOURCE=.\src\abc8\dar\darScript.c
# PROP Default_Filter ""
# Begin Source File
-SOURCE=.\src\abc8\fra\fra.h
+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\abc8\fra\fraBmc.c
+SOURCE=.\src\aig\fra\fraCec.c
# End Source File
# Begin Source File
-SOURCE=.\src\abc8\fra\fraCec.c
+SOURCE=.\src\aig\fra\fraClass.c
# End Source File
# Begin Source File
-SOURCE=.\src\abc8\fra\fraClass.c
+SOURCE=.\src\aig\fra\fraClau.c
# End Source File
# Begin Source File
-SOURCE=.\src\abc8\fra\fraClau.c
+SOURCE=.\src\aig\fra\fraClaus.c
# End Source File
# Begin Source File
-SOURCE=.\src\abc8\fra\fraCnf.c
+SOURCE=.\src\aig\fra\fraCnf.c
# End Source File
# Begin Source File
-SOURCE=.\src\abc8\fra\fraCore.c
+SOURCE=.\src\aig\fra\fraCore.c
# End Source File
# Begin Source File
-SOURCE=.\src\abc8\fra\fraImp.c
+SOURCE=.\src\aig\fra\fraImp.c
# End Source File
# Begin Source File
-SOURCE=.\src\abc8\fra\fraInd.c
+SOURCE=.\src\aig\fra\fraInd.c
# End Source File
# Begin Source File
-SOURCE=.\src\abc8\fra\fraLcr.c
+SOURCE=.\src\aig\fra\fraLcr.c
# End Source File
# Begin Source File
-SOURCE=.\src\abc8\fra\fraMan.c
+SOURCE=.\src\aig\fra\fraMan.c
# End Source File
# Begin Source File
-SOURCE=.\src\abc8\fra\fraPart.c
+SOURCE=.\src\aig\fra\fraPart.c
# End Source File
# Begin Source File
-SOURCE=.\src\abc8\fra\fraSat.c
+SOURCE=.\src\aig\fra\fraSat.c
# End Source File
# Begin Source File
-SOURCE=.\src\abc8\fra\fraSec.c
+SOURCE=.\src\aig\fra\fraSec.c
# End Source File
# Begin Source File
-SOURCE=.\src\abc8\fra\fraSim.c
+SOURCE=.\src\aig\fra\fraSim.c
# End Source File
# End Group
-# Begin Group "vec2"
+# Begin Group "cnf"
# PROP Default_Filter ""
# Begin Source File
-SOURCE=.\src\abc8\vec2\vec2.h
+SOURCE=.\src\aig\cnf\cnf.h
# End Source File
# Begin Source File
-SOURCE=.\src\abc8\vec2\vecAtt.h
+SOURCE=.\src\aig\cnf\cnfCore.c
# End Source File
# Begin Source File
-SOURCE=.\src\abc8\vec2\vecFlt.h
+SOURCE=.\src\aig\cnf\cnfCut.c
# End Source File
# Begin Source File
-SOURCE=.\src\abc8\vec2\vecInt.h
+SOURCE=.\src\aig\cnf\cnfData.c
# End Source File
# Begin Source File
-SOURCE=.\src\abc8\vec2\vecPtr.h
+SOURCE=.\src\aig\cnf\cnfMan.c
# End Source File
# Begin Source File
-SOURCE=.\src\abc8\vec2\vecStr.h
+SOURCE=.\src\aig\cnf\cnfMap.c
# End Source File
# Begin Source File
-SOURCE=.\src\abc8\vec2\vecVec.h
+SOURCE=.\src\aig\cnf\cnfPost.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\aig\cnf\cnfUtil.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\aig\cnf\cnfWrite.c
# End Source File
# End Group
-# Begin Group "ioa"
+# Begin Group "csw"
# PROP Default_Filter ""
# Begin Source File
-SOURCE=.\src\abc8\ioa\ioa.h
+SOURCE=.\src\aig\csw\csw.h
# End Source File
# Begin Source File
-SOURCE=.\src\abc8\ioa\ioaReadAig.c
+SOURCE=.\src\aig\csw\cswCore.c
# End Source File
# Begin Source File
-SOURCE=.\src\abc8\ioa\ioaUtil.c
+SOURCE=.\src\aig\csw\cswCut.c
# End Source File
# Begin Source File
-SOURCE=.\src\abc8\ioa\ioaWriteAig.c
+SOURCE=.\src\aig\csw\cswInt.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\aig\csw\cswMan.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\aig\csw\cswTable.c
# End Source File
# End Group
# Begin Group "kit"
@@ -2018,47 +2770,263 @@ SOURCE=.\src\abc8\ioa\ioaWriteAig.c
# PROP Default_Filter ""
# Begin Source File
-SOURCE=.\src\abc8\kit\cloud.c
+SOURCE=.\src\aig\kit\cloud.c
# End Source File
# Begin Source File
-SOURCE=.\src\abc8\kit\cloud.h
+SOURCE=.\src\aig\kit\cloud.h
# End Source File
# Begin Source File
-SOURCE=.\src\abc8\kit\kit.h
+SOURCE=.\src\aig\kit\kit.h
# End Source File
# Begin Source File
-SOURCE=.\src\abc8\kit\kitAig.c
+SOURCE=.\src\aig\kit\kitAig.c
# End Source File
# Begin Source File
-SOURCE=.\src\abc8\kit\kitCloud.c
+SOURCE=.\src\aig\kit\kitBdd.c
# End Source File
# Begin Source File
-SOURCE=.\src\abc8\kit\kitFactor.c
+SOURCE=.\src\aig\kit\kitCloud.c
# End Source File
# Begin Source File
-SOURCE=.\src\abc8\kit\kitGraph.c
+SOURCE=.\src\aig\kit\kitDsd.c
# End Source File
# Begin Source File
-SOURCE=.\src\abc8\kit\kitHop.c
+SOURCE=.\src\aig\kit\kitFactor.c
# End Source File
# Begin Source File
-SOURCE=.\src\abc8\kit\kitIsop.c
+SOURCE=.\src\aig\kit\kitGraph.c
# End Source File
# Begin Source File
-SOURCE=.\src\abc8\kit\kitSop.c
+SOURCE=.\src\aig\kit\kitHop.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\aig\kit\kitIsop.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\aig\kit\kitSop.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\aig\kit\kitTruth.c
+# End Source File
+# End Group
+# Begin Group "bdc"
+
+# PROP Default_Filter ""
+# Begin Source File
+
+SOURCE=.\src\aig\bdc\bdc.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\aig\bdc\bdcCore.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\aig\bdc\bdcDec.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\aig\bdc\bdcInt.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\aig\bdc\bdcTable.c
+# End Source File
+# End Group
+# Begin Group "aig"
+
+# PROP Default_Filter ""
+# Begin Source File
+
+SOURCE=.\src\aig\aig\aig.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\aig\aig\aigCheck.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\aig\aig\aigCuts.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\aig\aig\aigDfs.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\aig\aig\aigFanout.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\aig\aig\aigFrames.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\aig\aig\aigHaig.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\aig\aig\aigInter.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\aig\aig\aigMan.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\aig\aig\aigMem.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\aig\aig\aigMffc.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\aig\aig\aigObj.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\aig\aig\aigOper.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\aig\aig\aigOrder.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\aig\aig\aigPart.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\aig\aig\aigRepr.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\aig\aig\aigRet.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\aig\aig\aigRetF.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\aig\aig\aigScl.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\aig\aig\aigSeq.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\aig\aig\aigShow.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\aig\aig\aigTable.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\aig\aig\aigTiming.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\aig\aig\aigTruth.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\aig\aig\aigTsim.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\aig\aig\aigUtil.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\aig\aig\aigWin.c
+# End Source File
+# End Group
+# Begin Group "bar"
+
+# PROP Default_Filter ""
+# Begin Source File
+
+SOURCE=.\src\aig\bar\bar.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\aig\bar\bar.h
+# End Source File
+# End Group
+# Begin Group "ntl"
+
+# PROP Default_Filter ""
+# Begin Source File
+
+SOURCE=.\src\aig\ntl\ntl.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\aig\ntl\ntlAig.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\aig\ntl\ntlCheck.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\aig\ntl\ntlDfs.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\aig\ntl\ntlMan.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\aig\ntl\ntlMap.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\aig\ntl\ntlObj.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\aig\ntl\ntlReadBlif.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\aig\ntl\ntlTable.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\aig\ntl\ntlTime.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\aig\ntl\ntlWriteBlif.c
+# End Source File
+# End Group
+# Begin Group "tim"
+
+# PROP Default_Filter ""
+# Begin Source File
+
+SOURCE=.\src\aig\tim\tim.c
# End Source File
# Begin Source File
-SOURCE=.\src\abc8\kit\kitTruth.c
+SOURCE=.\src\aig\tim\tim.h
# End Source File
# End Group
# End Group
diff --git a/abc.rc b/abc.rc
index 6028a522..ce5b1240 100644
--- a/abc.rc
+++ b/abc.rc
@@ -1,9 +1,10 @@
# global parameters
-#set check # checks intermediate networks
+set check # checks intermediate networks
#set checkfio # prints warnings when fanins/fanouts are duplicated
set checkread # checks new networks after reading from file
set backup # saves backup networks retrived by "undo" and "recall"
-set savesteps 1 # sets the maximum number of backup networks to save
+set savesteps 1 # sets the maximum number of backup networks to save
+set progressbar # display the progress bar
# program names for internal calls
set dotwin dot.exe
@@ -14,6 +15,10 @@ set siswin sis.exe
set sisunix sis
set mvsiswin mvsis.exe
set mvsisunix mvsis
+set capowin MetaPl-Capo10.1-Win32.exe
+set capounix MetaPl-Capo10.1
+set gnuplotwin wgnuplot.exe
+set gnuplotunix gnuplot
# standard aliases
alias b balance
@@ -22,48 +27,102 @@ alias clp collapse
alias esd ext_seq_dcs
alias f fraig
alias fs fraig_sweep
+alias fsto fraig_store
+alias fres fraig_restore
alias ft fraig_trust
-alias mu renode -m
+alias lp lutpack
+alias pd print_dsd
+alias pex print_exdc -d
alias pf print_factor
alias pfan print_fanio
alias pl print_level
alias pio print_io
+alias pk print_kmap
alias ps print_stats
alias psu print_supp
alias psy print_symm
+alias pun print_unate
alias q quit
alias r read
+alias r3 retime -M 3
+alias r3f retime -M 3 -f
+alias r3b retime -M 3 -b
alias ren renode
+alias rh read_hie
alias rl read_blif
alias rb read_bench
+alias ret retime
+alias dret dretime
alias rp read_pla
+alias rt read_truth
alias rv read_verilog
+alias rvl read_verlib
alias rsup read_super mcnc5_old.super
alias rlib read_library
+alias rlibc read_library cadence.genlib
alias rw rewrite
alias rwz rewrite -z
alias rf refactor
alias rfz refactor -z
+alias re restructure
+alias rez restructure -z
+alias rs resub
+alias rsz resub -z
alias sa set autoexec ps
+alias scl scleanup
+alias sif if -s
alias so source -x
alias st strash
alias sw sweep
+alias ssw ssweep
+alias tr0 trace_start
+alias tr1 trace_check
+alias trt "r c.blif; st; tr0; b; tr1"
alias u undo
-alias wb write_blif
+alias w write
+alias wa write_aiger
+alias wb write_bench
+alias wc write_cnf
+alias wh write_hie
alias wl write_blif
alias wp write_pla
+alias wv write_verilog
# standard scripts
-alias cnf "st; ren -c; write_cnf"
-alias prove "st; ren -c; sat"
-alias opt "b; ren; b"
-alias share "b; ren; fx; b"
-alias sharem "b; ren -m; fx; b"
-alias sharedsd "b; ren; dsd -g; sw; fx; b"
-alias resyn "b; rw; rwz; b; rwz; b"
-alias resyn2 "b; rw; rf; b; rw; rwz; b; rfz; rwz; b"
-alias choice "fraig_store; resyn; fraig_store; resyn2; fraig_store; fraig_restore"
+alias resyn "b; rw; rwz; b; rwz; b"
+alias resyn2 "b; rw; rf; b; rw; rwz; b; rfz; rwz; b"
+alias resyn2a "b; rw; b; rw; rwz; b; rwz; b"
+alias resyn3 "b; rs; rs -K 6; b; rsz; rsz -K 6; b; rsz -K 5; b"
+alias compress "b -l; rw -l; rwz -l; b -l; rwz -l; b -l"
+alias compress2 "b -l; rw -l; rf -l; b -l; rw -l; rwz -l; b -l; rfz -l; rwz -l; b -l"
+alias choice "fraig_store; resyn; fraig_store; resyn2; fraig_store; fraig_restore"
+alias choice2 "fraig_store; balance; fraig_store; resyn; fraig_store; resyn2; fraig_store; resyn2; fraig_store; fraig_restore"
+alias rwsat "st; rw -l; b -l; rw -l; rf -l"
+alias rwsat2 "st; rw -l; b -l; rw -l; rf -l; fraig; rw -l; b -l; rw -l; rf -l"
+alias shake "st; ps; sat -C 5000; rw -l; ps; sat -C 5000; b -l; rf -l; ps; sat -C 5000; rfz -l; ps; sat -C 5000; rwz -l; ps; sat -C 5000; rfz -l; ps; sat -C 5000"
+alias share "st; multi -m; fx; resyn2"
-alias scl scleanup
-alias ssw ssweep
+# resubstitution scripts for the IWLS paper
+alias src_rw "st; rw -l; rwz -l; rwz -l"
+alias src_rs "st; rs -K 6 -N 2 -l; rs -K 9 -N 2 -l; rs -K 12 -N 2 -l"
+alias src_rws "st; rw -l; rs -K 6 -N 2 -l; rwz -l; rs -K 9 -N 2 -l; rwz -l; rs -K 12 -N 2 -l"
+alias resyn2rs "b; rs -K 6; rw; rs -K 6 -N 2; rf; rs -K 8; b; rs -K 8 -N 2; rw; rs -K 10; rwz; rs -K 10 -N 2; b; rs -K 12; rfz; rs -K 12 -N 2; rwz; b"
+alias compress2rs "b -l; rs -K 6 -l; rw -l; rs -K 6 -N 2 -l; rf -l; rs -K 8 -l; b -l; rs -K 8 -N 2 -l; rw -l; rs -K 10 -l; rwz -l; rs -K 10 -N 2 -l; b -l; rs -K 12 -l; rfz -l; rs -K 12 -N 2 -l; rwz -l; b -l"
+
+# experimental implementation of don't-cares
+alias resyn2rsdc "b; rs -K 6 -F 2; rw; rs -K 6 -N 2 -F 2; rf; rs -K 8 -F 2; b; rs -K 8 -N 2 -F 2; rw; rs -K 10 -F 2; rwz; rs -K 10 -N 2 -F 2; b; rs -K 12 -F 2; rfz; rs -K 12 -N 2 -F 2; rwz; b"
+alias compress2rsdc "b -l; rs -K 6 -F 2 -l; rw -l; rs -K 6 -N 2 -F 2 -l; rf -l; rs -K 8 -F 2 -l; b -l; rs -K 8 -N 2 -F 2 -l; rw -l; rs -K 10 -F 2 -l; rwz -l; rs -K 10 -N 2 -F 2 -l; b -l; rs -K 12 -F 2 -l; rfz -l; rs -K 12 -N 2 -F 2 -l; rwz -l; b -l"
+
+# temporaries
+alias reach "st; ps; compress2; ps; qrel; ps; compress2; ps; qreach -v; ps"
+alias chnew "st; haig_start; resyn2; haig_use"
+alias chnewrs "st; haig_start; resyn2rs; haig_use"
+alias stdsd "r test/6in.blif; st; ps; u; bdd; dsd -g; st; ps"
+alias trec "rec_start; r c.blif; st; rec_add; rec_use"
+alias trec4 "rec_start -K 4; r i10.blif; st; rec_add; rec_use"
+alias bmc2 "frames -i -F 10; orpos; iprove"
+
+alias t0 "r test/mc1.blif; st; test"
+alias t1 "r s27mc2.blif; st; test"
+alias t2 "r i/intel_001.aig; ps; indcut -v"
diff --git a/abclib.dsp b/abclib.dsp
new file mode 100644
index 00000000..df244f0f
--- /dev/null
+++ b/abclib.dsp
@@ -0,0 +1,2844 @@
+# Microsoft Developer Studio Project File - Name="abclib" - Package Owner=<4>
+# Microsoft Developer Studio Generated Build File, Format Version 6.00
+# ** DO NOT EDIT **
+
+# TARGTYPE "Win32 (x86) Static Library" 0x0104
+
+CFG=abclib - Win32 Debug
+!MESSAGE This is not a valid makefile. To build this project using NMAKE,
+!MESSAGE use the Export Makefile command and run
+!MESSAGE
+!MESSAGE NMAKE /f "abclib.mak".
+!MESSAGE
+!MESSAGE You can specify a configuration when running NMAKE
+!MESSAGE by defining the macro CFG on the command line. For example:
+!MESSAGE
+!MESSAGE NMAKE /f "abclib.mak" CFG="abclib - Win32 Debug"
+!MESSAGE
+!MESSAGE Possible choices for configuration are:
+!MESSAGE
+!MESSAGE "abclib - Win32 Release" (based on "Win32 (x86) Static Library")
+!MESSAGE "abclib - Win32 Debug" (based on "Win32 (x86) Static Library")
+!MESSAGE
+
+# Begin Project
+# PROP AllowPerConfigDependencies 0
+# PROP Scc_ProjName ""
+# PROP Scc_LocalPath ""
+CPP=cl.exe
+RSC=rc.exe
+
+!IF "$(CFG)" == "abclib - Win32 Release"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 0
+# PROP BASE Output_Dir "abclib___Win32_Release"
+# PROP BASE Intermediate_Dir "abclib___Win32_Release"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 0
+# PROP Output_Dir "abclib\ReleaseLib"
+# PROP Intermediate_Dir "abclib\ReleaseLib"
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_MBCS" /D "_LIB" /YX /FD /c
+# ADD CPP /nologo /W3 /GX /O2 /I "src/base/abc" /I "src/base/abci" /I "src/base/cmd" /I "src/base/io" /I "src/base/main" /I "src/base/ver" /I "src/bdd/cudd" /I "src/bdd/dsd" /I "src/bdd/epd" /I "src/bdd/mtr" /I "src/bdd/parse" /I "src/bdd/reo" /I "src/bdd/cas" /I "src/map/fpga" /I "src/map/mapper" /I "src/map/mio" /I "src/map/super" /I "src/map/if" /I "src/map/pcm" /I "src/map/ply" /I "src/misc/extra" /I "src/misc/mvc" /I "src/misc/st" /I "src/misc/util" /I "src/misc/espresso" /I "src/misc/nm" /I "src/misc/vec" /I "src/misc/hash" /I "src/opt/cut" /I "src/opt/dec" /I "src/opt/fxu" /I "src/opt/rwr" /I "src/opt/sim" /I "src/opt/ret" /I "src/opt/res" /I "src/opt/lpk" /I "src/sat/bsat" /I "src/sat/csat" /I "src/sat/msat" /I "src/sat/fraig" /I "src/aig/ivy" /I "src/aig/hop" /I "src/aig/rwt" /I "src/aig/deco" /I "src/aig/mem" /I "src/aig/dar" /I "src/aig/fra" /I "src/aig/cnf" /I "src/aig/csw" /I "src/aig/ioa" /I "src/aig/aig" /I "src/aig/kit" /I "src/aig/bdc" /I "src/aig/bar" /D "WIN32" /D "NDEBUG" /D "_MBCS" /D "_LIB" /D "__STDC__" /D "HAVE_ASSERT_H" /FR /YX /FD /c
+# ADD BASE RSC /l 0x409 /d "NDEBUG"
+# ADD RSC /l 0x409 /d "NDEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LIB32=link.exe -lib
+# ADD BASE LIB32 /nologo
+# ADD LIB32 /nologo /out:"abclib\abclib_release.lib"
+
+!ELSEIF "$(CFG)" == "abclib - Win32 Debug"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 1
+# PROP BASE Output_Dir "abclib___Win32_Debug"
+# PROP BASE Intermediate_Dir "abclib___Win32_Debug"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 1
+# PROP Output_Dir "abclib\DebugLib"
+# PROP Intermediate_Dir "abclib\DebugLib"
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_MBCS" /D "_LIB" /YX /FD /GZ /c
+# ADD CPP /nologo /W3 /Gm /GX /ZI /Od /I "src/base/abc" /I "src/base/abci" /I "src/base/cmd" /I "src/base/io" /I "src/base/main" /I "src/base/ver" /I "src/bdd/cudd" /I "src/bdd/dsd" /I "src/bdd/epd" /I "src/bdd/mtr" /I "src/bdd/parse" /I "src/bdd/reo" /I "src/bdd/cas" /I "src/map/fpga" /I "src/map/mapper" /I "src/map/mio" /I "src/map/super" /I "src/map/if" /I "src/map/pcm" /I "src/map/ply" /I "src/misc/extra" /I "src/misc/mvc" /I "src/misc/st" /I "src/misc/util" /I "src/misc/espresso" /I "src/misc/nm" /I "src/misc/vec" /I "src/misc/hash" /I "src/opt/cut" /I "src/opt/dec" /I "src/opt/fxu" /I "src/opt/rwr" /I "src/opt/sim" /I "src/opt/ret" /I "src/opt/res" /I "src/opt/lpk" /I "src/sat/bsat" /I "src/sat/csat" /I "src/sat/msat" /I "src/sat/fraig" /I "src/aig/ivy" /I "src/aig/hop" /I "src/aig/rwt" /I "src/aig/deco" /I "src/aig/mem" /I "src/aig/dar" /I "src/aig/fra" /I "src/aig/cnf" /I "src/aig/csw" /I "src/aig/ioa" /I "src/aig/aig" /I "src/aig/kit" /I "src/aig/bdc" /I "src/aig/bar" /D "WIN32" /D "_DEBUG" /D "_MBCS" /D "_LIB" /D "__STDC__" /D "HAVE_ASSERT_H" /FR /YX /FD /GZ /c
+# ADD BASE RSC /l 0x409 /d "_DEBUG"
+# ADD RSC /l 0x409 /d "_DEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LIB32=link.exe -lib
+# ADD BASE LIB32 /nologo
+# ADD LIB32 /nologo /out:"abclib\abclib_debug.lib"
+
+!ENDIF
+
+# Begin Target
+
+# Name "abclib - Win32 Release"
+# Name "abclib - Win32 Debug"
+# Begin Group "Source Files"
+
+# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat"
+# Begin Group "base"
+
+# PROP Default_Filter ""
+# Begin Group "abc"
+
+# PROP Default_Filter ""
+# Begin Source File
+
+SOURCE=.\src\base\abc\abc.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\base\abc\abcAig.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\base\abc\abcBlifMv.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\base\abc\abcCheck.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\base\abc\abcDfs.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\base\abc\abcFanio.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\base\abc\abcFunc.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\base\abc\abcHie.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\base\abc\abcInt.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\base\abc\abcLatch.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\base\abc\abcLib.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\base\abc\abcMinBase.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\base\abc\abcNames.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\base\abc\abcNetlist.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\base\abc\abcNtk.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\base\abc\abcObj.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\base\abc\abcRefs.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\base\abc\abcShow.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\base\abc\abcSop.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\base\abc\abcUtil.c
+# End Source File
+# End Group
+# Begin Group "abci"
+
+# PROP Default_Filter ""
+# Begin Source File
+
+SOURCE=.\src\base\abci\abc.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\base\abci\abcAttach.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\base\abci\abcAuto.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\base\abci\abcBalance.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\base\abci\abcBmc.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\base\abci\abcCas.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\base\abci\abcClpBdd.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\base\abci\abcClpSop.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\base\abci\abcCut.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\base\abci\abcDar.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\base\abci\abcDebug.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\base\abci\abcDress.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\base\abci\abcDsd.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\base\abci\abcEspresso.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\base\abci\abcExtract.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\base\abci\abcFpga.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\base\abci\abcFpgaFast.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\base\abci\abcFraig.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\base\abci\abcFxu.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\base\abci\abcGen.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\base\abci\abcHaig.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\base\abci\abcIf.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\base\abci\abcIvy.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\base\abci\abcLut.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\base\abci\abcMap.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\base\abci\abcMeasure.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\base\abci\abcMini.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\base\abci\abcMiter.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\base\abci\abcMulti.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\base\abci\abcMv.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\base\abci\abcNtbdd.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\base\abci\abcOdc.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\base\abci\abcOrder.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\base\abci\abcPart.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\base\abci\abcPrint.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\base\abci\abcProve.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\base\abci\abcQbf.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\base\abci\abcQuant.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\base\abci\abcRec.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\base\abci\abcReconv.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\base\abci\abcRefactor.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\base\abci\abcRenode.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\base\abci\abcReorder.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\base\abci\abcRestruct.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\base\abci\abcResub.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\base\abci\abcRewrite.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\base\abci\abcRr.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\base\abci\abcSat.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\base\abci\abcStrash.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\base\abci\abcSweep.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\base\abci\abcSymm.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\base\abci\abcTiming.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\base\abci\abcUnate.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\base\abci\abcUnreach.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\base\abci\abcVerify.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\base\abci\abcXsim.c
+# End Source File
+# End Group
+# Begin Group "cmd"
+
+# PROP Default_Filter ""
+# Begin Source File
+
+SOURCE=.\src\base\cmd\cmd.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\base\cmd\cmd.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\base\cmd\cmdAlias.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\base\cmd\cmdApi.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\base\cmd\cmdFlag.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\base\cmd\cmdHist.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\base\cmd\cmdInt.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\base\cmd\cmdUtils.c
+# End Source File
+# End Group
+# Begin Group "io"
+
+# PROP Default_Filter ""
+# Begin Source File
+
+SOURCE=.\src\base\io\io.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\base\io\io.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\base\io\ioInt.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\base\io\ioReadAiger.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\base\io\ioReadBaf.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\base\io\ioReadBench.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\base\io\ioReadBlif.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\base\io\ioReadBlifAig.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\base\io\ioReadBlifMv.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\base\io\ioReadDsd.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\base\io\ioReadEdif.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\base\io\ioReadEqn.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\base\io\ioReadPla.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\base\io\ioReadVerilog.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\base\io\ioUtil.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\base\io\ioWriteAiger.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\base\io\ioWriteBaf.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\base\io\ioWriteBench.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\base\io\ioWriteBlif.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\base\io\ioWriteBlifMv.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\base\io\ioWriteCnf.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\base\io\ioWriteDot.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\base\io\ioWriteEqn.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\base\io\ioWriteGml.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\base\io\ioWriteList.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\base\io\ioWritePla.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\base\io\ioWriteVerilog.c
+# End Source File
+# End Group
+# Begin Group "main"
+
+# PROP Default_Filter ""
+# Begin Source File
+
+SOURCE=.\src\base\main\libSupport.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\base\main\main.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\base\main\main.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\base\main\mainFrame.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\base\main\mainInit.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\base\main\mainInt.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\base\main\mainUtils.c
+# End Source File
+# End Group
+# Begin Group "ver"
+
+# PROP Default_Filter ""
+# Begin Source File
+
+SOURCE=.\src\base\ver\ver.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\base\ver\verCore.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\base\ver\verFormula.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\base\ver\verParse.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\base\ver\verStream.c
+# End Source File
+# End Group
+# End Group
+# Begin Group "bdd"
+
+# PROP Default_Filter ""
+# Begin Group "cudd"
+
+# PROP Default_Filter ""
+# Begin Source File
+
+SOURCE=.\src\bdd\cudd\cudd.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\bdd\cudd\cuddAddAbs.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\bdd\cudd\cuddAddApply.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\bdd\cudd\cuddAddFind.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\bdd\cudd\cuddAddInv.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\bdd\cudd\cuddAddIte.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\bdd\cudd\cuddAddNeg.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\bdd\cudd\cuddAddWalsh.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\bdd\cudd\cuddAndAbs.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\bdd\cudd\cuddAnneal.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\bdd\cudd\cuddApa.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\bdd\cudd\cuddAPI.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\bdd\cudd\cuddApprox.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\bdd\cudd\cuddBddAbs.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\bdd\cudd\cuddBddCorr.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\bdd\cudd\cuddBddIte.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\bdd\cudd\cuddBridge.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\bdd\cudd\cuddCache.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\bdd\cudd\cuddCheck.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\bdd\cudd\cuddClip.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\bdd\cudd\cuddCof.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\bdd\cudd\cuddCompose.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\bdd\cudd\cuddDecomp.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\bdd\cudd\cuddEssent.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\bdd\cudd\cuddExact.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\bdd\cudd\cuddExport.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\bdd\cudd\cuddGenCof.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\bdd\cudd\cuddGenetic.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\bdd\cudd\cuddGroup.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\bdd\cudd\cuddHarwell.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\bdd\cudd\cuddInit.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\bdd\cudd\cuddInt.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\bdd\cudd\cuddInteract.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\bdd\cudd\cuddLCache.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\bdd\cudd\cuddLevelQ.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\bdd\cudd\cuddLinear.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\bdd\cudd\cuddLiteral.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\bdd\cudd\cuddMatMult.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\bdd\cudd\cuddPriority.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\bdd\cudd\cuddRead.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\bdd\cudd\cuddRef.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\bdd\cudd\cuddReorder.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\bdd\cudd\cuddSat.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\bdd\cudd\cuddSign.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\bdd\cudd\cuddSolve.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\bdd\cudd\cuddSplit.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\bdd\cudd\cuddSubsetHB.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\bdd\cudd\cuddSubsetSP.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\bdd\cudd\cuddSymmetry.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\bdd\cudd\cuddTable.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\bdd\cudd\cuddUtil.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\bdd\cudd\cuddWindow.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\bdd\cudd\cuddZddCount.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\bdd\cudd\cuddZddFuncs.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\bdd\cudd\cuddZddGroup.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\bdd\cudd\cuddZddIsop.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\bdd\cudd\cuddZddLin.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\bdd\cudd\cuddZddMisc.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\bdd\cudd\cuddZddPort.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\bdd\cudd\cuddZddReord.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\bdd\cudd\cuddZddSetop.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\bdd\cudd\cuddZddSymm.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\bdd\cudd\cuddZddUtil.c
+# End Source File
+# End Group
+# Begin Group "epd"
+
+# PROP Default_Filter ""
+# Begin Source File
+
+SOURCE=.\src\bdd\epd\epd.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\bdd\epd\epd.h
+# End Source File
+# End Group
+# Begin Group "mtr"
+
+# PROP Default_Filter ""
+# Begin Source File
+
+SOURCE=.\src\bdd\mtr\mtr.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\bdd\mtr\mtrBasic.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\bdd\mtr\mtrGroup.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\bdd\mtr\mtrInt.h
+# End Source File
+# End Group
+# Begin Group "parse"
+
+# PROP Default_Filter ""
+# Begin Source File
+
+SOURCE=.\src\bdd\parse\parse.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\bdd\parse\parseCore.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\bdd\parse\parseEqn.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\bdd\parse\parseInt.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\bdd\parse\parseStack.c
+# End Source File
+# End Group
+# Begin Group "dsd"
+
+# PROP Default_Filter ""
+# Begin Source File
+
+SOURCE=.\src\bdd\dsd\dsd.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\bdd\dsd\dsdApi.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\bdd\dsd\dsdCheck.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\bdd\dsd\dsdInt.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\bdd\dsd\dsdLocal.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\bdd\dsd\dsdMan.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\bdd\dsd\dsdProc.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\bdd\dsd\dsdTree.c
+# End Source File
+# End Group
+# Begin Group "reo"
+
+# PROP Default_Filter ""
+# Begin Source File
+
+SOURCE=.\src\bdd\reo\reo.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\bdd\reo\reoApi.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\bdd\reo\reoCore.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\bdd\reo\reoProfile.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\bdd\reo\reoSift.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\bdd\reo\reoSwap.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\bdd\reo\reoTest.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\bdd\reo\reoTransfer.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\bdd\reo\reoUnits.c
+# End Source File
+# End Group
+# Begin Group "cas"
+
+# PROP Default_Filter ""
+# Begin Source File
+
+SOURCE=.\src\bdd\cas\cas.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\bdd\cas\casCore.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\bdd\cas\casDec.c
+# End Source File
+# End Group
+# End Group
+# Begin Group "sat"
+
+# PROP Default_Filter ""
+# Begin Group "msat"
+
+# PROP Default_Filter ""
+# Begin Source File
+
+SOURCE=.\src\sat\msat\msat.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\sat\msat\msatActivity.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\sat\msat\msatClause.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\sat\msat\msatClauseVec.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\sat\msat\msatInt.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\sat\msat\msatMem.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\sat\msat\msatOrderH.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\sat\msat\msatQueue.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\sat\msat\msatRead.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\sat\msat\msatSolverApi.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\sat\msat\msatSolverCore.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\sat\msat\msatSolverIo.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\sat\msat\msatSolverSearch.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\sat\msat\msatSort.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\sat\msat\msatVec.c
+# End Source File
+# End Group
+# Begin Group "fraig"
+
+# PROP Default_Filter ""
+# Begin Source File
+
+SOURCE=.\src\sat\fraig\fraig.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\sat\fraig\fraigApi.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\sat\fraig\fraigCanon.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\sat\fraig\fraigChoice.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\sat\fraig\fraigFanout.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\sat\fraig\fraigFeed.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\sat\fraig\fraigInt.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\sat\fraig\fraigMan.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\sat\fraig\fraigMem.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\sat\fraig\fraigNode.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\sat\fraig\fraigPrime.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\sat\fraig\fraigSat.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\sat\fraig\fraigTable.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\sat\fraig\fraigUtil.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\sat\fraig\fraigVec.c
+# End Source File
+# End Group
+# Begin Group "csat"
+
+# PROP Default_Filter ""
+# Begin Source File
+
+SOURCE=.\src\sat\csat\csat_apis.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\sat\csat\csat_apis.h
+# End Source File
+# End Group
+# Begin Group "bsat"
+
+# PROP Default_Filter ""
+# Begin Source File
+
+SOURCE=.\src\sat\bsat\satInter.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\sat\bsat\satMem.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\sat\bsat\satMem.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\sat\bsat\satSolver.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\sat\bsat\satSolver.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\sat\bsat\satStore.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\sat\bsat\satStore.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\sat\bsat\satTrace.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\sat\bsat\satUtil.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\sat\bsat\satVec.h
+# End Source File
+# End Group
+# Begin Group "proof"
+
+# PROP Default_Filter ""
+# Begin Source File
+
+SOURCE=.\src\sat\proof\pr.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\sat\proof\pr.h
+# End Source File
+# End Group
+# End Group
+# Begin Group "opt"
+
+# PROP Default_Filter ""
+# Begin Group "fxu"
+
+# PROP Default_Filter ""
+# Begin Source File
+
+SOURCE=.\src\opt\fxu\fxu.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\opt\fxu\fxu.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\opt\fxu\fxuCreate.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\opt\fxu\fxuHeapD.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\opt\fxu\fxuHeapS.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\opt\fxu\fxuInt.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\opt\fxu\fxuList.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\opt\fxu\fxuMatrix.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\opt\fxu\fxuPair.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\opt\fxu\fxuPrint.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\opt\fxu\fxuReduce.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\opt\fxu\fxuSelect.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\opt\fxu\fxuSingle.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\opt\fxu\fxuUpdate.c
+# End Source File
+# End Group
+# Begin Group "rwr"
+
+# PROP Default_Filter ""
+# Begin Source File
+
+SOURCE=.\src\opt\rwr\rwr.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\opt\rwr\rwrDec.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\opt\rwr\rwrEva.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\opt\rwr\rwrExp.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\opt\rwr\rwrLib.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\opt\rwr\rwrMan.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\opt\rwr\rwrPrint.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\opt\rwr\rwrTemp.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\opt\rwr\rwrUtil.c
+# End Source File
+# End Group
+# Begin Group "cut"
+
+# PROP Default_Filter ""
+# Begin Source File
+
+SOURCE=.\src\opt\cut\cut.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\opt\cut\cutApi.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\opt\cut\cutCut.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\opt\cut\cutExpand.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\opt\cut\cutInt.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\opt\cut\cutList.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\opt\cut\cutMan.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\opt\cut\cutMerge.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\opt\cut\cutNode.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\opt\cut\cutOracle.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\opt\cut\cutPre22.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\opt\cut\cutSeq.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\opt\cut\cutTruth.c
+# End Source File
+# End Group
+# Begin Group "dec"
+
+# PROP Default_Filter ""
+# Begin Source File
+
+SOURCE=.\src\opt\dec\dec.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\opt\dec\decAbc.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\opt\dec\decFactor.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\opt\dec\decMan.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\opt\dec\decPrint.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\opt\dec\decUtil.c
+# End Source File
+# End Group
+# Begin Group "sim"
+
+# PROP Default_Filter ""
+# Begin Source File
+
+SOURCE=.\src\opt\sim\sim.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\opt\sim\simMan.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\opt\sim\simSat.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\opt\sim\simSeq.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\opt\sim\simSupp.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\opt\sim\simSwitch.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\opt\sim\simSym.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\opt\sim\simSymSat.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\opt\sim\simSymSim.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\opt\sim\simSymStr.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\opt\sim\simUtils.c
+# End Source File
+# End Group
+# Begin Group "ret"
+
+# PROP Default_Filter ""
+# Begin Source File
+
+SOURCE=.\src\opt\ret\retArea.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\opt\ret\retCore.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\opt\ret\retDelay.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\opt\ret\retFlow.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\opt\ret\retIncrem.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\opt\ret\retInit.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\opt\ret\retInt.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\opt\ret\retLvalue.c
+# End Source File
+# End Group
+# Begin Group "res"
+
+# PROP Default_Filter ""
+# Begin Source File
+
+SOURCE=.\src\opt\res\res.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\opt\res\resCore.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\opt\res\resDivs.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\opt\res\resFilter.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\opt\res\resInt.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\opt\res\resSat.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\opt\res\resSim.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\opt\res\resStrash.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\opt\res\resWin.c
+# End Source File
+# End Group
+# Begin Group "lpk"
+
+# PROP Default_Filter ""
+# Begin Source File
+
+SOURCE=.\src\opt\lpk\lpk.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\opt\lpk\lpkAbcDec.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\opt\lpk\lpkAbcDsd.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\opt\lpk\lpkAbcMux.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\opt\lpk\lpkAbcUtil.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\opt\lpk\lpkCore.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\opt\lpk\lpkCut.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\opt\lpk\lpkInt.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\opt\lpk\lpkMan.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\opt\lpk\lpkMap.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\opt\lpk\lpkMulti.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\opt\lpk\lpkMux.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\opt\lpk\lpkSets.c
+# End Source File
+# End Group
+# End Group
+# Begin Group "map"
+
+# PROP Default_Filter ""
+# Begin Group "fpga"
+
+# PROP Default_Filter ""
+# Begin Source File
+
+SOURCE=.\src\map\fpga\fpga.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\map\fpga\fpga.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\map\fpga\fpgaCore.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\map\fpga\fpgaCreate.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\map\fpga\fpgaCut.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\map\fpga\fpgaCutUtils.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\map\fpga\fpgaFanout.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\map\fpga\fpgaInt.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\map\fpga\fpgaLib.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\map\fpga\fpgaMatch.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\map\fpga\fpgaSwitch.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\map\fpga\fpgaTime.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\map\fpga\fpgaTruth.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\map\fpga\fpgaUtils.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\map\fpga\fpgaVec.c
+# End Source File
+# End Group
+# Begin Group "mapper"
+
+# PROP Default_Filter ""
+# Begin Source File
+
+SOURCE=.\src\map\mapper\mapper.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\map\mapper\mapper.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\map\mapper\mapperCanon.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\map\mapper\mapperCore.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\map\mapper\mapperCreate.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\map\mapper\mapperCut.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\map\mapper\mapperCutUtils.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\map\mapper\mapperFanout.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\map\mapper\mapperInt.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\map\mapper\mapperLib.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\map\mapper\mapperMatch.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\map\mapper\mapperRefs.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\map\mapper\mapperSuper.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\map\mapper\mapperSwitch.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\map\mapper\mapperTable.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\map\mapper\mapperTime.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\map\mapper\mapperTree.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\map\mapper\mapperTruth.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\map\mapper\mapperUtils.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\map\mapper\mapperVec.c
+# End Source File
+# End Group
+# Begin Group "mio"
+
+# PROP Default_Filter ""
+# Begin Source File
+
+SOURCE=.\src\map\mio\mio.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\map\mio\mio.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\map\mio\mioApi.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\map\mio\mioFunc.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\map\mio\mioInt.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\map\mio\mioRead.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\map\mio\mioUtils.c
+# End Source File
+# End Group
+# Begin Group "super"
+
+# PROP Default_Filter ""
+# Begin Source File
+
+SOURCE=.\src\map\super\super.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\map\super\super.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\map\super\superAnd.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\map\super\superGate.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\map\super\superInt.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\map\super\superWrite.c
+# End Source File
+# End Group
+# Begin Group "if"
+
+# PROP Default_Filter ""
+# Begin Source File
+
+SOURCE=.\src\map\if\if.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\map\if\ifCore.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\map\if\ifCut.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\map\if\ifMan.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\map\if\ifMap.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\map\if\ifReduce.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\map\if\ifSeq.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\map\if\ifTime.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\map\if\ifTruth.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\map\if\ifUtil.c
+# End Source File
+# End Group
+# End Group
+# Begin Group "misc"
+
+# PROP Default_Filter ""
+# Begin Group "extra"
+
+# PROP Default_Filter ""
+# Begin Source File
+
+SOURCE=.\src\misc\extra\extra.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\misc\extra\extraBddAuto.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\misc\extra\extraBddCas.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\misc\extra\extraBddKmap.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\misc\extra\extraBddMisc.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\misc\extra\extraBddSymm.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\misc\extra\extraBddUnate.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\misc\extra\extraUtilBitMatrix.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\misc\extra\extraUtilCanon.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\misc\extra\extraUtilFile.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\misc\extra\extraUtilMemory.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\misc\extra\extraUtilMisc.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\misc\extra\extraUtilProgress.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\misc\extra\extraUtilReader.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\misc\extra\extraUtilTruth.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\misc\extra\extraUtilUtil.c
+# End Source File
+# End Group
+# Begin Group "st"
+
+# PROP Default_Filter ""
+# Begin Source File
+
+SOURCE=.\src\misc\st\st.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\misc\st\st.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\misc\st\stmm.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\misc\st\stmm.h
+# End Source File
+# End Group
+# Begin Group "util"
+
+# PROP Default_Filter ""
+# Begin Source File
+
+SOURCE=.\src\misc\util\util_hack.h
+# End Source File
+# End Group
+# Begin Group "mvc"
+
+# PROP Default_Filter ""
+# Begin Source File
+
+SOURCE=.\src\misc\mvc\mvc.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\misc\mvc\mvc.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\misc\mvc\mvcApi.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\misc\mvc\mvcCompare.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\misc\mvc\mvcContain.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\misc\mvc\mvcCover.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\misc\mvc\mvcCube.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\misc\mvc\mvcDivide.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\misc\mvc\mvcDivisor.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\misc\mvc\mvcList.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\misc\mvc\mvcLits.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\misc\mvc\mvcMan.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\misc\mvc\mvcOpAlg.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\misc\mvc\mvcOpBool.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\misc\mvc\mvcPrint.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\misc\mvc\mvcSort.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\misc\mvc\mvcUtils.c
+# End Source File
+# End Group
+# Begin Group "vec"
+
+# PROP Default_Filter ""
+# Begin Source File
+
+SOURCE=.\src\misc\vec\vec.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\misc\vec\vecAtt.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\misc\vec\vecFlt.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\misc\vec\vecInt.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\misc\vec\vecPtr.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\misc\vec\vecStr.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\misc\vec\vecVec.h
+# End Source File
+# End Group
+# Begin Group "espresso"
+
+# PROP Default_Filter ""
+# Begin Source File
+
+SOURCE=.\src\misc\espresso\cofactor.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\misc\espresso\cols.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\misc\espresso\compl.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\misc\espresso\contain.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\misc\espresso\cubehack.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\misc\espresso\cubestr.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\misc\espresso\cvrin.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\misc\espresso\cvrm.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\misc\espresso\cvrmisc.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\misc\espresso\cvrout.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\misc\espresso\dominate.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\misc\espresso\equiv.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\misc\espresso\espresso.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\misc\espresso\espresso.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\misc\espresso\essen.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\misc\espresso\exact.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\misc\espresso\expand.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\misc\espresso\gasp.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\misc\espresso\gimpel.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\misc\espresso\globals.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\misc\espresso\hack.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\misc\espresso\indep.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\misc\espresso\irred.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\misc\espresso\map.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\misc\espresso\matrix.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\misc\espresso\mincov.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\misc\espresso\mincov.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\misc\espresso\mincov_int.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\misc\espresso\opo.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\misc\espresso\pair.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\misc\espresso\part.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\misc\espresso\primes.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\misc\espresso\reduce.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\misc\espresso\rows.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\misc\espresso\set.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\misc\espresso\setc.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\misc\espresso\sharp.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\misc\espresso\sminterf.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\misc\espresso\solution.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\misc\espresso\sparse.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\misc\espresso\sparse.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\misc\espresso\sparse_int.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\misc\espresso\unate.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\misc\espresso\util_old.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\misc\espresso\verify.c
+# End Source File
+# End Group
+# Begin Group "nm"
+
+# PROP Default_Filter ""
+# Begin Source File
+
+SOURCE=.\src\misc\nm\nm.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\misc\nm\nmApi.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\misc\nm\nmInt.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\misc\nm\nmTable.c
+# End Source File
+# End Group
+# Begin Group "hash"
+
+# PROP Default_Filter ""
+# Begin Source File
+
+SOURCE=.\src\misc\hash\hash.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\misc\hash\hashFlt.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\misc\hash\hashInt.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\misc\hash\hashPtr.h
+# End Source File
+# End Group
+# End Group
+# Begin Group "ai"
+
+# PROP Default_Filter ""
+# Begin Group "hop"
+
+# PROP Default_Filter ""
+# Begin Source File
+
+SOURCE=.\src\aig\hop\hop.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\aig\hop\hopBalance.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\aig\hop\hopCheck.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\aig\hop\hopDfs.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\aig\hop\hopMan.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\aig\hop\hopMem.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\aig\hop\hopObj.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\aig\hop\hopOper.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\aig\hop\hopTable.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\aig\hop\hopUtil.c
+# End Source File
+# End Group
+# Begin Group "ivy"
+
+# PROP Default_Filter ""
+# Begin Source File
+
+SOURCE=.\src\aig\ivy\ivy.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\aig\ivy\ivyBalance.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\aig\ivy\ivyCanon.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\aig\ivy\ivyCheck.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\aig\ivy\ivyCut.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\aig\ivy\ivyCutTrav.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\aig\ivy\ivyDfs.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\aig\ivy\ivyDsd.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\aig\ivy\ivyFanout.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\aig\ivy\ivyFastMap.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\aig\ivy\ivyFraig.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\aig\ivy\ivyHaig.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\aig\ivy\ivyMan.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\aig\ivy\ivyMem.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\aig\ivy\ivyMulti.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\aig\ivy\ivyObj.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\aig\ivy\ivyOper.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\aig\ivy\ivyResyn.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\aig\ivy\ivyRwr.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\aig\ivy\ivySeq.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\aig\ivy\ivyShow.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\aig\ivy\ivyTable.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\aig\ivy\ivyUtil.c
+# End Source File
+# End Group
+# Begin Group "rwt"
+
+# PROP Default_Filter ""
+# Begin Source File
+
+SOURCE=.\src\aig\rwt\rwt.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\aig\rwt\rwtDec.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\aig\rwt\rwtMan.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\aig\rwt\rwtUtil.c
+# End Source File
+# End Group
+# Begin Group "deco"
+
+# PROP Default_Filter ""
+# Begin Source File
+
+SOURCE=.\src\aig\deco\deco.h
+# End Source File
+# End Group
+# Begin Group "mem"
+
+# PROP Default_Filter ""
+# Begin Source File
+
+SOURCE=.\src\aig\mem\mem.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\aig\mem\mem.h
+# End Source File
+# End Group
+# Begin Group "ioa"
+
+# PROP Default_Filter ""
+# Begin Source File
+
+SOURCE=.\src\aig\ioa\ioa.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\aig\ioa\ioaReadAig.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\aig\ioa\ioaUtil.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\aig\ioa\ioaWriteAig.c
+# End Source File
+# End Group
+# Begin Group "dar"
+
+# PROP Default_Filter ""
+# Begin Source File
+
+SOURCE=.\src\aig\dar\dar.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\aig\dar\darBalance.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\aig\dar\darCore.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\aig\dar\darCut.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\aig\dar\darData.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\aig\dar\darInt.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\aig\dar\darLib.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\aig\dar\darMan.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\aig\dar\darPrec.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\aig\dar\darRefact.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\aig\dar\darResub.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\aig\dar\darScript.c
+# End Source File
+# End Group
+# Begin Group "fra"
+
+# PROP Default_Filter ""
+# Begin Source File
+
+SOURCE=.\src\aig\fra\fra.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\aig\fra\fraBmc.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\aig\fra\fraCec.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\aig\fra\fraClass.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\aig\fra\fraCnf.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\aig\fra\fraCore.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\aig\fra\fraImp.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\aig\fra\fraInd.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\aig\fra\fraLcr.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\aig\fra\fraMan.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\aig\fra\fraPart.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\aig\fra\fraSat.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\aig\fra\fraSec.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\aig\fra\fraSim.c
+# End Source File
+# End Group
+# Begin Group "cnf"
+
+# PROP Default_Filter ""
+# Begin Source File
+
+SOURCE=.\src\aig\cnf\cnf.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\aig\cnf\cnfCore.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\aig\cnf\cnfCut.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\aig\cnf\cnfData.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\aig\cnf\cnfMan.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\aig\cnf\cnfMap.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\aig\cnf\cnfPost.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\aig\cnf\cnfUtil.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\aig\cnf\cnfWrite.c
+# End Source File
+# End Group
+# Begin Group "csw"
+
+# PROP Default_Filter ""
+# Begin Source File
+
+SOURCE=.\src\aig\csw\csw.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\aig\csw\cswCore.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\aig\csw\cswCut.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\aig\csw\cswInt.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\aig\csw\cswMan.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\aig\csw\cswTable.c
+# End Source File
+# End Group
+# Begin Group "kit"
+
+# PROP Default_Filter ""
+# Begin Source File
+
+SOURCE=.\src\aig\kit\cloud.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\aig\kit\cloud.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\aig\kit\kit.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\aig\kit\kitAig.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\aig\kit\kitBdd.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\aig\kit\kitCloud.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\aig\kit\kitDsd.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\aig\kit\kitFactor.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\aig\kit\kitGraph.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\aig\kit\kitHop.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\aig\kit\kitIsop.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\aig\kit\kitSop.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\aig\kit\kitTruth.c
+# End Source File
+# End Group
+# Begin Group "bdc"
+
+# PROP Default_Filter ""
+# Begin Source File
+
+SOURCE=.\src\aig\bdc\bdc.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\aig\bdc\bdcCore.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\aig\bdc\bdcDec.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\aig\bdc\bdcInt.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\aig\bdc\bdcTable.c
+# End Source File
+# End Group
+# Begin Group "aig"
+
+# PROP Default_Filter ""
+# Begin Source File
+
+SOURCE=.\src\aig\aig\aig.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\aig\aig\aigCheck.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\aig\aig\aigDfs.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\aig\aig\aigFanout.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\aig\aig\aigMan.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\aig\aig\aigMem.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\aig\aig\aigMffc.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\aig\aig\aigObj.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\aig\aig\aigOper.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\aig\aig\aigOrder.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\aig\aig\aigPart.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\aig\aig\aigRepr.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\aig\aig\aigRet.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\aig\aig\aigScl.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\aig\aig\aigSeq.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\aig\aig\aigShow.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\aig\aig\aigTable.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\aig\aig\aigTime.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\aig\aig\aigTiming.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\aig\aig\aigTruth.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\aig\aig\aigTsim.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\aig\aig\aigUtil.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\aig\aig\aigWin.c
+# End Source File
+# End Group
+# Begin Group "bar"
+
+# PROP Default_Filter ""
+# Begin Source File
+
+SOURCE=.\src\aig\bar\bar.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\aig\bar\bar.h
+# End Source File
+# End Group
+# End Group
+# End Group
+# Begin Group "Header Files"
+
+# PROP Default_Filter "h;hpp;hxx;hm;inl"
+# End Group
+# End Target
+# End Project
diff --git a/abclib.dsw b/abclib.dsw
new file mode 100644
index 00000000..260ade17
--- /dev/null
+++ b/abclib.dsw
@@ -0,0 +1,29 @@
+Microsoft Developer Studio Workspace File, Format Version 6.00
+# WARNING: DO NOT EDIT OR DELETE THIS WORKSPACE FILE!
+
+###############################################################################
+
+Project: "abclib"=.\abclib.dsp - Package Owner=<4>
+
+Package=<5>
+{{{
+}}}
+
+Package=<4>
+{{{
+}}}
+
+###############################################################################
+
+Global:
+
+Package=<5>
+{{{
+}}}
+
+Package=<3>
+{{{
+}}}
+
+###############################################################################
+
diff --git a/abctestlib.dsp b/abctestlib.dsp
new file mode 100644
index 00000000..e901cbda
--- /dev/null
+++ b/abctestlib.dsp
@@ -0,0 +1,102 @@
+# Microsoft Developer Studio Project File - Name="abctestlib" - Package Owner=<4>
+# Microsoft Developer Studio Generated Build File, Format Version 6.00
+# ** DO NOT EDIT **
+
+# TARGTYPE "Win32 (x86) Console Application" 0x0103
+
+CFG=abctestlib - Win32 Debug
+!MESSAGE This is not a valid makefile. To build this project using NMAKE,
+!MESSAGE use the Export Makefile command and run
+!MESSAGE
+!MESSAGE NMAKE /f "abctestlib.mak".
+!MESSAGE
+!MESSAGE You can specify a configuration when running NMAKE
+!MESSAGE by defining the macro CFG on the command line. For example:
+!MESSAGE
+!MESSAGE NMAKE /f "abctestlib.mak" CFG="abctestlib - Win32 Debug"
+!MESSAGE
+!MESSAGE Possible choices for configuration are:
+!MESSAGE
+!MESSAGE "abctestlib - Win32 Release" (based on "Win32 (x86) Console Application")
+!MESSAGE "abctestlib - Win32 Debug" (based on "Win32 (x86) Console Application")
+!MESSAGE
+
+# Begin Project
+# PROP AllowPerConfigDependencies 0
+# PROP Scc_ProjName ""
+# PROP Scc_LocalPath ""
+CPP=cl.exe
+RSC=rc.exe
+
+!IF "$(CFG)" == "abctestlib - Win32 Release"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 0
+# PROP BASE Output_Dir "Release"
+# PROP BASE Intermediate_Dir "Release"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 0
+# PROP Output_Dir "Release"
+# PROP Intermediate_Dir "Release"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c
+# ADD CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c
+# ADD BASE RSC /l 0x409 /d "NDEBUG"
+# ADD RSC /l 0x409 /d "NDEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386
+# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib C:\_projects\abc\abclib\abclib_release.lib /nologo /subsystem:console /machine:I386 /out:"_TEST/abctestlib.exe"
+
+!ELSEIF "$(CFG)" == "abctestlib - Win32 Debug"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 1
+# PROP BASE Output_Dir "Debug"
+# PROP BASE Intermediate_Dir "Debug"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 1
+# PROP Output_Dir "Debug"
+# PROP Intermediate_Dir "Debug"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /GZ /c
+# ADD CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /FR /YX /FD /GZ /c
+# ADD BASE RSC /l 0x409 /d "_DEBUG"
+# ADD RSC /l 0x409 /d "_DEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept
+# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib C:\_projects\abc\abclib\abclib_debug.lib /nologo /subsystem:console /debug /machine:I386 /out:"_TEST/abctestlib.exe" /pdbtype:sept
+
+!ENDIF
+
+# Begin Target
+
+# Name "abctestlib - Win32 Release"
+# Name "abctestlib - Win32 Debug"
+# Begin Group "Source Files"
+
+# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat"
+# Begin Source File
+
+SOURCE=.\demo.c
+# End Source File
+# End Group
+# Begin Group "Header Files"
+
+# PROP Default_Filter "h;hpp;hxx;hm;inl"
+# End Group
+# Begin Group "Resource Files"
+
+# PROP Default_Filter "ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe"
+# End Group
+# End Target
+# End Project
diff --git a/abctestlib.dsw b/abctestlib.dsw
new file mode 100644
index 00000000..7ae6cac9
--- /dev/null
+++ b/abctestlib.dsw
@@ -0,0 +1,29 @@
+Microsoft Developer Studio Workspace File, Format Version 6.00
+# WARNING: DO NOT EDIT OR DELETE THIS WORKSPACE FILE!
+
+###############################################################################
+
+Project: "abctestlib"=.\abctestlib.dsp - Package Owner=<4>
+
+Package=<5>
+{{{
+}}}
+
+Package=<4>
+{{{
+}}}
+
+###############################################################################
+
+Global:
+
+Package=<5>
+{{{
+}}}
+
+Package=<3>
+{{{
+}}}
+
+###############################################################################
+
diff --git a/copyright.txt b/copyright.txt
new file mode 100644
index 00000000..121d63e8
--- /dev/null
+++ b/copyright.txt
@@ -0,0 +1,18 @@
+Copyright (c) The Regents of the University of California. All rights reserved.
+
+Permission is hereby granted, without written agreement and without license or
+royalty fees, to use, copy, modify, and distribute this software and its
+documentation for any purpose, provided that the above copyright notice and
+the following two paragraphs appear in all copies of this software.
+
+IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY FOR
+DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT OF
+THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF THE UNIVERSITY OF
+CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
+BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS ON AN "AS IS" BASIS,
+AND THE UNIVERSITY OF CALIFORNIA HAS NO OBLIGATION TO PROVIDE MAINTENANCE,
+SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
+
diff --git a/demo.c b/demo.c
new file mode 100644
index 00000000..de162409
--- /dev/null
+++ b/demo.c
@@ -0,0 +1,181 @@
+/**CFile****************************************************************
+
+ FileName [demo.c]
+
+ SystemName [ABC: Logic synthesis and verification system.]
+
+ PackageName [ABC as a static library.]
+
+ Synopsis [A demo program illustrating the use of ABC as a static library.]
+
+ Author [Alan Mishchenko]
+
+ Affiliation [UC Berkeley]
+
+ Date [Ver. 1.0. Started - June 20, 2005.]
+
+ Revision [$Id: demo.c,v 1.00 2005/11/14 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include <stdio.h>
+#include <time.h>
+
+////////////////////////////////////////////////////////////////////////
+/// DECLARATIONS ///
+////////////////////////////////////////////////////////////////////////
+
+// procedures to start and stop the ABC framework
+// (should be called before and after the ABC procedures are called)
+extern void Abc_Start();
+extern void Abc_Stop();
+
+// procedures to get the ABC framework and execute commands in it
+extern void * Abc_FrameGetGlobalFrame();
+extern int Cmd_CommandExecute( void * pAbc, char * sCommand );
+
+////////////////////////////////////////////////////////////////////////
+/// FUNCTION DEFINITIONS ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+ Synopsis [The main() procedure.]
+
+ Description [This procedure compiles into a stand-alone program for
+ DAG-aware rewriting of the AIGs. A BLIF or PLA file to be considered
+ for rewriting should be given as a command-line argument. Implementation
+ of the rewriting is inspired by the paper: Per Bjesse, Arne Boralv,
+ "DAG-aware circuit compression for formal verification", Proc. ICCAD 2004.]
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int main( int argc, char * argv[] )
+{
+ // parameters
+ int fUseResyn2 = 0;
+ int fPrintStats = 1;
+ int fVerify = 1;
+ // variables
+ void * pAbc;
+ char * pFileName;
+ char Command[1000];
+ int clkRead, clkResyn, clkVer, clk;
+
+ //////////////////////////////////////////////////////////////////////////
+ // get the input file name
+ if ( argc != 2 )
+ {
+ printf( "Wrong number of command-line arguments.\n" );
+ return 1;
+ }
+ pFileName = argv[1];
+
+ //////////////////////////////////////////////////////////////////////////
+ // start the ABC framework
+ Abc_Start();
+ pAbc = Abc_FrameGetGlobalFrame();
+
+clk = clock();
+ //////////////////////////////////////////////////////////////////////////
+ // read the file
+ sprintf( Command, "read %s", pFileName );
+ if ( Cmd_CommandExecute( pAbc, Command ) )
+ {
+ fprintf( stdout, "Cannot execute command \"%s\".\n", Command );
+ return 1;
+ }
+
+ //////////////////////////////////////////////////////////////////////////
+ // balance
+ sprintf( Command, "balance" );
+ if ( Cmd_CommandExecute( pAbc, Command ) )
+ {
+ fprintf( stdout, "Cannot execute command \"%s\".\n", Command );
+ return 1;
+ }
+clkRead = clock() - clk;
+
+ //////////////////////////////////////////////////////////////////////////
+ // print stats
+ if ( fPrintStats )
+ {
+ sprintf( Command, "print_stats" );
+ if ( Cmd_CommandExecute( pAbc, Command ) )
+ {
+ fprintf( stdout, "Cannot execute command \"%s\".\n", Command );
+ return 1;
+ }
+ }
+
+clk = clock();
+ //////////////////////////////////////////////////////////////////////////
+ // synthesize
+ if ( fUseResyn2 )
+ {
+ sprintf( Command, "balance; rewrite -l; refactor -l; balance; rewrite -l; rewrite -lz; balance; refactor -lz; rewrite -lz; balance" );
+ if ( Cmd_CommandExecute( pAbc, Command ) )
+ {
+ fprintf( stdout, "Cannot execute command \"%s\".\n", Command );
+ return 1;
+ }
+ }
+ else
+ {
+ sprintf( Command, "balance; rewrite -l; rewrite -lz; balance; rewrite -lz; balance" );
+ if ( Cmd_CommandExecute( pAbc, Command ) )
+ {
+ fprintf( stdout, "Cannot execute command \"%s\".\n", Command );
+ return 1;
+ }
+ }
+clkResyn = clock() - clk;
+
+ //////////////////////////////////////////////////////////////////////////
+ // print stats
+ if ( fPrintStats )
+ {
+ sprintf( Command, "print_stats" );
+ if ( Cmd_CommandExecute( pAbc, Command ) )
+ {
+ fprintf( stdout, "Cannot execute command \"%s\".\n", Command );
+ return 1;
+ }
+ }
+
+ //////////////////////////////////////////////////////////////////////////
+ // write the result in blif
+ sprintf( Command, "write_blif result.blif" );
+ if ( Cmd_CommandExecute( pAbc, Command ) )
+ {
+ fprintf( stdout, "Cannot execute command \"%s\".\n", Command );
+ return 1;
+ }
+
+ //////////////////////////////////////////////////////////////////////////
+ // perform verification
+clk = clock();
+ if ( fVerify )
+ {
+ sprintf( Command, "cec %s result.blif", pFileName );
+ if ( Cmd_CommandExecute( pAbc, Command ) )
+ {
+ fprintf( stdout, "Cannot execute command \"%s\".\n", Command );
+ return 1;
+ }
+ }
+clkVer = clock() - clk;
+
+ printf( "Reading = %6.2f sec ", (float)(clkRead)/(float)(CLOCKS_PER_SEC) );
+ printf( "Rewriting = %6.2f sec ", (float)(clkResyn)/(float)(CLOCKS_PER_SEC) );
+ printf( "Verification = %6.2f sec\n", (float)(clkVer)/(float)(CLOCKS_PER_SEC) );
+
+ //////////////////////////////////////////////////////////////////////////
+ // stop the ABC framework
+ Abc_Stop();
+ return 0;
+}
+
diff --git a/graph_lib.txt b/graph_lib.txt
deleted file mode 100644
index 14bfc335..00000000
--- a/graph_lib.txt
+++ /dev/null
@@ -1,1407 +0,0 @@
-
-Class 1. Func 0. Functions = 15. Volume = 33. 0000000000000001
- 288 : 0x0001 tt=0000000000000001 lev=2 vol=3 (d'a')(c'b')
- 367 : 0x0001 tt=0000000000000001 lev=2 vol=3 (d'b')(c'a')
- 457 : 0x0001 tt=0000000000000001 lev=2 vol=3 (d'c')(b'a')
- 637 : 0x0001 tt=0000000000000001 lev=3 vol=3 ((b'a')c')d'
- 693 : 0x0001 tt=0000000000000001 lev=3 vol=3 ((b'a')d')c'
- 768 : 0x0001 tt=0000000000000001 lev=3 vol=3 ((c'a')b')d'
- 781 : 0x0001 tt=0000000000000001 lev=3 vol=3 ((c'a')d')b'
- 880 : 0x0001 tt=0000000000000001 lev=3 vol=3 ((c'b')a')d'
- 914 : 0x0001 tt=0000000000000001 lev=3 vol=3 ((c'b')d')a'
- 1103 : 0x0001 tt=0000000000000001 lev=3 vol=3 ((d'a')b')c'
- 1110 : 0x0001 tt=0000000000000001 lev=3 vol=3 ((d'a')c')b'
- 1231 : 0x0001 tt=0000000000000001 lev=3 vol=3 ((d'b')a')c'
- 1236 : 0x0001 tt=0000000000000001 lev=3 vol=3 ((d'b')c')a'
- 1397 : 0x0001 tt=0000000000000001 lev=3 vol=3 ((d'c')a')b'
- 1404 : 0x0001 tt=0000000000000001 lev=3 vol=3 ((d'c')b')a'
-
-Class 2. Func 1. Functions = 3. Volume = 6. 0000000000000011
- 190 : 0x0003 tt=0000000000000011 lev=2 vol=2 (c'b')d'
- 356 : 0x0003 tt=0000000000000011 lev=2 vol=2 (d'b')c'
- 449 : 0x0003 tt=0000000000000011 lev=2 vol=2 (d'c')b'
-
-Class 3. Func 2. Functions = 3. Volume = 7. 0000000000000110
- 461 : 0x0006 tt=0000000000000110 lev=2 vol=4 (d'c')(b+a)
- 716 : 0x0006 tt=0000000000000110 lev=3 vol=4 ((b+a)c')d'
- 731 : 0x0006 tt=0000000000000110 lev=3 vol=4 ((b+a)d')c'
-
-Class 4. Func 3. Functions = 3. Volume = 7. 0000000000000111
- 452 : 0x0007 tt=0000000000000111 lev=2 vol=3 (d'c')(ba)'
- 525 : 0x0007 tt=0000000000000111 lev=3 vol=3 ((ba)'c')d'
- 552 : 0x0007 tt=0000000000000111 lev=3 vol=3 ((ba)'d')c'
-
-Class 5. Func 4. Functions = 1. Volume = 1. 0000000000001111
- 33 : 0x000f tt=0000000000001111 lev=1 vol=1 d'c'
-
-Class 6. Func 5. Functions = 6. Volume = 22. 0000000000010110
- 671 : 0x0016 tt=0000000000010110 lev=3 vol=6 ((b'a')+c)'((ba)'d')
- 773 : 0x0016 tt=0000000000010110 lev=3 vol=6 ((c'a')+b)'((ca)'d')
- 889 : 0x0016 tt=0000000000010110 lev=3 vol=6 ((c'b')+a)'((cb)'d')
- 1538 : 0x0016 tt=0000000000010110 lev=4 vol=6 (((ba)'c')+(b'a'))d'
- 1732 : 0x0016 tt=0000000000010110 lev=4 vol=6 (((b'a')+c)'d')(ba)'
- 1734 : 0x0016 tt=0000000000010110 lev=4 vol=6 (((b'a')+c)'(ba)')d'
-
-Class 7. Func 6. Functions = 6. Volume = 22. 0000000000010111
- 635 : 0x0017 tt=0000000000010111 lev=3 vol=5 ((b'a')'c)'((ba)'d')
- 767 : 0x0017 tt=0000000000010111 lev=3 vol=5 ((c'a')'b)'((ca)'d')
- 879 : 0x0017 tt=0000000000010111 lev=3 vol=5 ((c'b')'a)'((cb)'d')
- 1536 : 0x0017 tt=0000000000010111 lev=4 vol=5 (((ba)'c')'(b'a')')'d'
- 1671 : 0x0017 tt=0000000000010111 lev=4 vol=5 (((b'a')'c)'d')(ba)'
- 1674 : 0x0017 tt=0000000000010111 lev=4 vol=5 (((b'a')'c)'(ba)')d'
-
-Class 8. Func 7. Functions = 29. Volume = 80. 0000000000011000
- 733 : 0x0018 tt=0000000000011000 lev=3 vol=6 ((b+a)'d')(c+a)
- 735 : 0x0018 tt=0000000000011000 lev=3 vol=6 ((b+a)'d')(c+b)
- 804 : 0x0018 tt=0000000000011000 lev=3 vol=6 ((c+a)d')(b+a)'
- 806 : 0x0018 tt=0000000000011000 lev=3 vol=6 ((c+a)d')(c+b)
- 811 : 0x0018 tt=0000000000011000 lev=3 vol=6 ((c+a)(b+a)')d'
- 832 : 0x0018 tt=0000000000011000 lev=3 vol=6 ((cb)'d')((ca')'(ba)')'
- 834 : 0x0018 tt=0000000000011000 lev=3 vol=6 ((cb)'d')((c'a')'(b'a)')
- 837 : 0x0018 tt=0000000000011000 lev=3 vol=6 ((cb)'(b'a)')((c'a')'d')
- 843 : 0x0018 tt=0000000000011000 lev=3 vol=6 ((cb)'(c'a')')((b'a)'d')
- 853 : 0x0018 tt=0000000000011000 lev=3 vol=6 ((c'b)'(b'a')')'((c'a')'d')
- 856 : 0x0018 tt=0000000000011000 lev=3 vol=6 ((c'b)'(ca')')'((ba')'d')
- 866 : 0x0018 tt=0000000000011000 lev=3 vol=6 ((cb')'(ba)')'((ca)'d')
- 874 : 0x0018 tt=0000000000011000 lev=3 vol=6 ((cb')'(c'a)')'((b'a)'d')
- 916 : 0x0018 tt=0000000000011000 lev=3 vol=6 ((c'b')'d')((ca)'(ba')')
- 917 : 0x0018 tt=0000000000011000 lev=3 vol=6 ((c'b')'d')((c'a)'(b'a')')'
- 941 : 0x0018 tt=0000000000011000 lev=3 vol=6 ((c'b')'(ba')')((ca)'d')
- 945 : 0x0018 tt=0000000000011000 lev=3 vol=6 ((c'b')'(ca)')((ba')'d')
- 971 : 0x0018 tt=0000000000011000 lev=3 vol=6 ((c+b)d')(b+a)'
- 972 : 0x0018 tt=0000000000011000 lev=3 vol=6 ((c+b)d')(c+a)
- 989 : 0x0018 tt=0000000000011000 lev=3 vol=6 ((c+b)(b+a)')d'
- 1004 : 0x0018 tt=0000000000011000 lev=3 vol=6 ((c+b)(c+a))d'
- 1528 : 0x0018 tt=0000000000011000 lev=4 vol=6 (((ba)'c')'d')((b'a')'c)'
- 1618 : 0x0018 tt=0000000000011000 lev=4 vol=6 (((b'a)'d')(c'a')')(cb)'
- 1622 : 0x0018 tt=0000000000011000 lev=4 vol=6 (((b'a)'d')(cb)')(c'a')'
- 1660 : 0x0018 tt=0000000000011000 lev=4 vol=6 (((ba')'d')(ca)')(c'b')'
- 1663 : 0x0018 tt=0000000000011000 lev=4 vol=6 (((ba')'d')(c'b')')(ca)'
- 1669 : 0x0018 tt=0000000000011000 lev=4 vol=6 (((b'a')c)'((ba)c')')'d'
- 1672 : 0x0018 tt=0000000000011000 lev=4 vol=6 (((b'a')'c)'d')((ba)'c')'
- 1676 : 0x0018 tt=0000000000011000 lev=4 vol=6 (((b'a')'c)'((ba)'c')')d'
-
-Class 9. Func 8. Functions = 9. Volume = 29. 0000000000011001
- 732 : 0x0019 tt=0000000000011001 lev=3 vol=5 ((b+a)'d')(ca)'
- 734 : 0x0019 tt=0000000000011001 lev=3 vol=5 ((b+a)'d')(cb)'
- 747 : 0x0019 tt=0000000000011001 lev=3 vol=5 ((ca)'d')(b+a)'
- 751 : 0x0019 tt=0000000000011001 lev=3 vol=5 ((ca)'(b+a)')d'
- 755 : 0x0019 tt=0000000000011001 lev=3 vol=5 ((c'a)'b)'((b'a)'d')
- 827 : 0x0019 tt=0000000000011001 lev=3 vol=5 ((cb)'d')(b+a)'
- 838 : 0x0019 tt=0000000000011001 lev=3 vol=5 ((cb)'(b+a)')d'
- 847 : 0x0019 tt=0000000000011001 lev=3 vol=5 ((c'b)'a)'((ba')'d')
- 1511 : 0x0019 tt=0000000000011001 lev=4 vol=5 (((ba)c')'(b'a')')'d'
-
-Class 10. Func 9. Functions = 4. Volume = 12. 0000000000011011
- 621 : 0x001b tt=0000000000011011 lev=3 vol=4 ((ba')'d')(ca)'
- 746 : 0x001b tt=0000000000011011 lev=3 vol=4 ((ca)'d')(ba')'
- 749 : 0x001b tt=0000000000011011 lev=3 vol=4 ((ca)'(ba')')d'
- 757 : 0x001b tt=0000000000011011 lev=3 vol=4 ((c'a)'(b'a')')'d'
-
-Class 11. Func 10. Functions = 1. Volume = 3. 0000000000011110
- 667 : 0x001e tt=0000000000011110 lev=3 vol=4 ((b'a')+c)'d'
-
-Class 12. Func 11. Functions = 1. Volume = 3. 0000000000011111
- 631 : 0x001f tt=0000000000011111 lev=3 vol=3 ((b'a')'c)'d'
-
-Class 13. Func 12. Functions = 1. Volume = 2. 0000000000111100
- 207 : 0x003c tt=0000000000111100 lev=2 vol=3 (c+b)d'
-
-Class 14. Func 13. Functions = 9. Volume = 29. 0000000000111101
- 829 : 0x003d tt=0000000000111101 lev=3 vol=5 ((cb)'d')((b'a)c')'
- 831 : 0x003d tt=0000000000111101 lev=3 vol=5 ((cb)'d')((c'a)b')'
- 878 : 0x003d tt=0000000000111101 lev=3 vol=5 ((c'b')a)'((cb)'d')
- 984 : 0x003d tt=0000000000111101 lev=3 vol=5 ((c+b)'(b'a')')'d'
- 1001 : 0x003d tt=0000000000111101 lev=3 vol=5 ((c+b)'(c'a')')'d'
- 1591 : 0x003d tt=0000000000111101 lev=4 vol=5 (((b'a)c')'d')(cb)'
- 1594 : 0x003d tt=0000000000111101 lev=4 vol=5 (((b'a)c')'(cb)')d'
- 1600 : 0x003d tt=0000000000111101 lev=4 vol=5 (((b'a)'c')'(cb')')'d'
- 1711 : 0x003d tt=0000000000111101 lev=4 vol=5 (((b'a')'c')+b)'d'
-
-Class 15. Func 14. Functions = 1. Volume = 2. 0000000000111111
- 150 : 0x003f tt=0000000000111111 lev=2 vol=2 (cb)'d'
-
-Class 16. Func 15. Functions = 3. Volume = 9. 0000000001101001
- 721 : 0x0069 tt=0000000001101001 lev=3 vol=5 ((b+a)+c)'d'
- 794 : 0x0069 tt=0000000001101001 lev=3 vol=5 ((c+a)+b)'d'
- 958 : 0x0069 tt=0000000001101001 lev=3 vol=5 ((c+b)+a)'d'
-
-Class 17. Func 16. Functions = 11. Volume = 43. 0000000001101011
- 1086 : 0x006b tt=0000000001101011 lev=3 vol=8 ((d'a)(c'b')')+((c+b)'d')
- 1121 : 0x006b tt=0000000001101011 lev=3 vol=7 ((d'a')(c'b')')+((cb)'d')
- 1198 : 0x006b tt=0000000001101011 lev=3 vol=7 ((d'b)(c'a)')+((ca')'d')
- 1351 : 0x006b tt=0000000001101011 lev=3 vol=7 ((d'c)(b'a)')+((ba')'d')
- 1480 : 0x006b tt=0000000001101011 lev=4 vol=7 (((ba)c)'d')((c+b)a')'
- 1584 : 0x006b tt=0000000001101011 lev=4 vol=7 (((b'a)'c)d')+((ba')'d')
- 1585 : 0x006b tt=0000000001101011 lev=4 vol=7 (((b'a)'c)'d')+((ba')d')
- 1586 : 0x006b tt=0000000001101011 lev=4 vol=7 (((b'a)'c)'d')+((d'a')b)
- 1587 : 0x006b tt=0000000001101011 lev=4 vol=7 (((b'a)'c)'d')+((d'b)a')
- 1589 : 0x006b tt=0000000001101011 lev=4 vol=6 (((b'a)'c)+(ba'))'d'
- 1644 : 0x006b tt=0000000001101011 lev=4 vol=6 (((ba')+c)(b'a)')'d'
-
-Class 18. Func 17. Functions = 1. Volume = 3. 0000000001101111
- 714 : 0x006f tt=0000000001101111 lev=3 vol=4 ((b+a)'c)'d'
-
-Class 19. Func 18. Functions = 11. Volume = 35. 0000000001111110
- 812 : 0x007e tt=0000000001111110 lev=3 vol=6 ((c+a)'(b+a)')'d'
- 990 : 0x007e tt=0000000001111110 lev=3 vol=6 ((c+b)'(b+a)')'d'
- 1006 : 0x007e tt=0000000001111110 lev=3 vol=6 ((c+b)'(c+a)')'d'
- 1477 : 0x007e tt=0000000001111110 lev=4 vol=6 (((ba)c)'d')((b'a')c')'
- 1478 : 0x007e tt=0000000001111110 lev=4 vol=6 (((ba)c)'d')((c'a')b')'
- 1479 : 0x007e tt=0000000001111110 lev=4 vol=6 (((ba)c)'d')((c'b')a')'
- 1692 : 0x007e tt=0000000001111110 lev=4 vol=6 (((b'a')c')'d')((ba)c)'
- 1693 : 0x007e tt=0000000001111110 lev=4 vol=6 (((b'a')c')'d')((ca)b)'
- 1694 : 0x007e tt=0000000001111110 lev=4 vol=6 (((b'a')c')'d')((cb)a)'
- 1708 : 0x007e tt=0000000001111110 lev=4 vol=6 (((b'a')c')'((ba)c)')d'
- 1728 : 0x007e tt=0000000001111110 lev=4 vol=6 (((b'a')'c')'((ba)'c)')'d'
-
-Class 20. Func 19. Functions = 3. Volume = 9. 0000000001111111
- 494 : 0x007f tt=0000000001111111 lev=3 vol=3 ((ba)c)'d'
- 741 : 0x007f tt=0000000001111111 lev=3 vol=3 ((ca)b)'d'
- 820 : 0x007f tt=0000000001111111 lev=3 vol=3 ((cb)a)'d'
-
-Class 21. Func 20. Functions = 6. Volume = 12. 0000000011111111
- 229 : 0x00ff tt=0000000011111111 lev=2 vol=2 (da)'d'
- 264 : 0x00ff tt=0000000011111111 lev=2 vol=2 (da')'d'
- 316 : 0x00ff tt=0000000011111111 lev=2 vol=2 (db)'d'
- 343 : 0x00ff tt=0000000011111111 lev=2 vol=2 (db')'d'
- 400 : 0x00ff tt=0000000011111111 lev=2 vol=2 (dc)'d'
- 432 : 0x00ff tt=0000000011111111 lev=2 vol=2 (dc')'d'
-
-Class 22. Func 21. Functions = 18. Volume = 57. 0000000100010110
- 1116 : 0x0116 tt=0000000100010110 lev=3 vol=8 ((d'a')(cb)')+((da)'(c'b'))
- 1122 : 0x0116 tt=0000000100010110 lev=3 vol=8 ((d'a')+(c'b'))((da)'(cb)')
- 1243 : 0x0116 tt=0000000100010110 lev=3 vol=8 ((d'b')(ca)')+((db)'(c'a'))
- 1250 : 0x0116 tt=0000000100010110 lev=3 vol=8 ((d'b')'(c'a')')'((d'a')+(c'b'))
- 1251 : 0x0116 tt=0000000100010110 lev=3 vol=8 ((d'b')+(c'a'))((d'a')'(c'b')')'
- 1252 : 0x0116 tt=0000000100010110 lev=3 vol=8 ((d'b')+(c'a'))((db)'(ca)')
- 1410 : 0x0116 tt=0000000100010110 lev=3 vol=8 ((d'c')(ba)')+((dc)'(b'a'))
- 1426 : 0x0116 tt=0000000100010110 lev=3 vol=8 ((d'c')'(b'a')')'((d'a')+(c'b'))
- 1427 : 0x0116 tt=0000000100010110 lev=3 vol=8 ((d'c')'(b'a')')'((d'b')+(c'a'))
- 1429 : 0x0116 tt=0000000100010110 lev=3 vol=8 ((d'c')+(b'a'))((d'a')'(c'b')')'
- 1430 : 0x0116 tt=0000000100010110 lev=3 vol=8 ((d'c')+(b'a'))((d'b')'(c'a')')'
- 1431 : 0x0116 tt=0000000100010110 lev=3 vol=8 ((d'c')+(b'a'))((dc)'(ba)')
- 1527 : 0x0116 tt=0000000100010110 lev=4 vol=8 (((ba)'c')d')+((dc)'(b'a'))
- 1572 : 0x0116 tt=0000000100010110 lev=4 vol=8 (((ba)'d')c')+((dc)'(b'a'))
- 1677 : 0x0116 tt=0000000100010110 lev=4 vol=8 (((b'a')'c)'((ba)'d'))+((b'a')c')
- 1710 : 0x0116 tt=0000000100010110 lev=4 vol=8 (((b'a')c')+((ba)'d'))((b'a')'c)'
- 1757 : 0x0116 tt=0000000100010110 lev=4 vol=8 (((b'a')'d)'((ba)'c'))+((b'a')d')
- 1770 : 0x0116 tt=0000000100010110 lev=4 vol=8 (((b'a')d')+((ba)'c'))((b'a')'d)'
-
-Class 24. Func 22. Functions = 27. Volume = 85. 0000000100011000
- 786 : 0x0118 tt=0000000100011000 lev=3 vol=8 ((c'a')+d)'((ca)'(b+a)')
- 841 : 0x0118 tt=0000000100011000 lev=3 vol=8 ((cb)'(b+a)')((c'a')+d)'
- 928 : 0x0118 tt=0000000100011000 lev=3 vol=8 ((c'b')+d)'((ca)'(b+a)')
- 936 : 0x0118 tt=0000000100011000 lev=3 vol=8 ((c'b')+d)'((cb)'(b+a)')
- 1114 : 0x0118 tt=0000000100011000 lev=3 vol=8 ((d'a')+c)'((da)'(b+a)')
- 1168 : 0x0118 tt=0000000100011000 lev=3 vol=8 ((db)'(b+a)')((d'a')+c)'
- 1240 : 0x0118 tt=0000000100011000 lev=3 vol=8 ((d'b')+c)'((da)'(b+a)')
- 1241 : 0x0118 tt=0000000100011000 lev=3 vol=8 ((d'b')+c)'((db)'(b+a)')
- 1400 : 0x0118 tt=0000000100011000 lev=3 vol=8 ((d'c')+a)'((dc)'(b+a)')
- 1409 : 0x0118 tt=0000000100011000 lev=3 vol=8 ((d'c')+b)'((dc)'(b+a)')
- 1455 : 0x0118 tt=0000000100011000 lev=3 vol=8 ((d+c)'(ba)')'((d'c')'(b'a')')'
- 1514 : 0x0118 tt=0000000100011000 lev=4 vol=8 (((ba)c')'(b'a')')'((c'a')+d)'
- 1516 : 0x0118 tt=0000000100011000 lev=4 vol=8 (((ba)c')'(b'a')')'((c'b')+d)'
- 1520 : 0x0118 tt=0000000100011000 lev=4 vol=8 (((ba)c')'(d+c)')'((d+c)(b'a')')'
- 1535 : 0x0118 tt=0000000100011000 lev=4 vol=8 (((ba)'c')+d)'((d'c')'(b'a')')'
- 1556 : 0x0118 tt=0000000100011000 lev=4 vol=8 (((ba)d')'(b'a')')'((d'a')+c)'
- 1558 : 0x0118 tt=0000000100011000 lev=4 vol=8 (((ba)d')'(b'a')')'((d'b')+c)'
- 1568 : 0x0118 tt=0000000100011000 lev=4 vol=8 (((ba)d')'(d+c)')'((d+c)(b'a')')'
- 1575 : 0x0118 tt=0000000100011000 lev=4 vol=8 (((ba)'d')+c)'((d'c')'(b'a')')'
- 1603 : 0x0118 tt=0000000100011000 lev=4 vol=8 (((b'a)'c')+(d'a'))((d'a)'b)'
- 1604 : 0x0118 tt=0000000100011000 lev=4 vol=8 (((b'a)'c')+(d'a'))((d'c')'b)'
- 1620 : 0x0118 tt=0000000100011000 lev=4 vol=8 (((b'a)'d')+(c'a'))((c'a)'b)'
- 1621 : 0x0118 tt=0000000100011000 lev=4 vol=8 (((b'a)'d')+(c'a'))((d'c')'b)'
- 1641 : 0x0118 tt=0000000100011000 lev=4 vol=8 (((ba')'c')+(d'b'))((d'b)'a)'
- 1642 : 0x0118 tt=0000000100011000 lev=4 vol=8 (((ba')'c')+(d'b'))((d'c')'a)'
- 1665 : 0x0118 tt=0000000100011000 lev=4 vol=8 (((ba')'d')+(c'b'))((c'b)'a)'
- 1666 : 0x0118 tt=0000000100011000 lev=4 vol=8 (((ba')'d')+(c'b'))((d'c')'a)'
-
-Class 25. Func 23. Functions = 18. Volume = 64. 0000000100011001
- 777 : 0x0119 tt=0000000100011001 lev=3 vol=7 ((c'a')'d)'((ca)'(b+a)')
- 840 : 0x0119 tt=0000000100011001 lev=3 vol=7 ((cb)'(b+a)')((c'a')'d)'
- 903 : 0x0119 tt=0000000100011001 lev=3 vol=7 ((c'b')'d)'((ca)'(b+a)')
- 910 : 0x0119 tt=0000000100011001 lev=3 vol=7 ((c'b')'d)'((cb)'(b+a)')
- 1106 : 0x0119 tt=0000000100011001 lev=3 vol=7 ((d'a')'c)'((da)'(b+a)')
- 1167 : 0x0119 tt=0000000100011001 lev=3 vol=7 ((db)'(b+a)')((d'a')'c)'
- 1234 : 0x0119 tt=0000000100011001 lev=3 vol=7 ((d'b')'c)'((da)'(b+a)')
- 1235 : 0x0119 tt=0000000100011001 lev=3 vol=7 ((d'b')'c)'((db)'(b+a)')
- 1396 : 0x0119 tt=0000000100011001 lev=3 vol=7 ((d'c')'a)'((dc)'(b+a)')
- 1403 : 0x0119 tt=0000000100011001 lev=3 vol=7 ((d'c')'b)'((dc)'(b+a)')
- 1513 : 0x0119 tt=0000000100011001 lev=4 vol=7 (((ba)c')'(b'a')')'((c'a')'d)'
- 1515 : 0x0119 tt=0000000100011001 lev=4 vol=7 (((ba)c')'(b'a')')'((c'b')'d)'
- 1555 : 0x0119 tt=0000000100011001 lev=4 vol=7 (((ba)d')'(b'a')')'((d'a')'c)'
- 1557 : 0x0119 tt=0000000100011001 lev=4 vol=7 (((ba)d')'(b'a')')'((d'b')'c)'
- 1602 : 0x0119 tt=0000000100011001 lev=4 vol=7 (((b'a)'c')'(d'a')')'((d'a)'b)'
- 1619 : 0x0119 tt=0000000100011001 lev=4 vol=7 (((b'a)'d')'(c'a')')'((c'a)'b)'
- 1640 : 0x0119 tt=0000000100011001 lev=4 vol=7 (((ba')'c')'(d'b')')'((d'b)'a)'
- 1664 : 0x0119 tt=0000000100011001 lev=4 vol=7 (((ba')'d')'(c'b')')'((c'b)'a)'
-
-Class 26. Func 24. Functions = 12. Volume = 40. 0000000100011010
- 785 : 0x011a tt=0000000100011010 lev=3 vol=7 ((c'a')+d)'((ca)'(ba')')
- 787 : 0x011a tt=0000000100011010 lev=3 vol=7 ((c'a')+d)'((c'a)'(b'a')')'
- 1113 : 0x011a tt=0000000100011010 lev=3 vol=7 ((d'a')+c)'((da)'(ba')')
- 1115 : 0x011a tt=0000000100011010 lev=3 vol=7 ((d'a')+c)'((d'a)'(b'a')')'
- 1399 : 0x011a tt=0000000100011010 lev=3 vol=7 ((d'c')+a)'((dc)'(ba')')
- 1424 : 0x011a tt=0000000100011010 lev=3 vol=7 ((d'c')'(b'a')')'((c'a')+d)'
- 1425 : 0x011a tt=0000000100011010 lev=3 vol=7 ((d'c')'(b'a')')'((d'a')+c)'
- 1448 : 0x011a tt=0000000100011010 lev=3 vol=7 ((d+c)'a')'((d'c')'(b'a')')'
- 1464 : 0x011a tt=0000000100011010 lev=3 vol=7 ((d+c)'(c'a)')'((d+c)(b'a')')'
- 1472 : 0x011a tt=0000000100011010 lev=3 vol=7 ((d+c)'(d'a)')'((d+c)(b'a')')'
- 1701 : 0x011a tt=0000000100011010 lev=4 vol=7 (((b'a')c')+d)'((c'a)'(b'a')')'
- 1768 : 0x011a tt=0000000100011010 lev=4 vol=7 (((b'a')d')+c)'((d'a)'(b'a')')'
-
-Class 27. Func 25. Functions = 7. Volume = 29. 0000000100011011
- 776 : 0x011b tt=0000000100011011 lev=3 vol=6 ((c'a')'d)'((ca)'(ba')')
- 778 : 0x011b tt=0000000100011011 lev=3 vol=6 ((c'a')'d)'((c'a)'(b'a')')'
- 1105 : 0x011b tt=0000000100011011 lev=3 vol=6 ((d'a')'c)'((da)'(ba')')
- 1107 : 0x011b tt=0000000100011011 lev=3 vol=6 ((d'a')'c)'((d'a)'(b'a')')'
- 1395 : 0x011b tt=0000000100011011 lev=3 vol=6 ((d'c')'a)'((dc)'(ba')')
- 1685 : 0x011b tt=0000000100011011 lev=4 vol=6 (((b'a')c')'d)'((c'a)'(b'a')')'
- 1764 : 0x011b tt=0000000100011011 lev=4 vol=6 (((b'a')d')'c)'((d'a)'(b'a')')'
-
-Class 28. Func 26. Functions = 6. Volume = 19. 0000000100011110
- 1315 : 0x011e tt=0000000100011110 lev=3 vol=6 ((dc)'(b'a'))+(d'c')
- 1428 : 0x011e tt=0000000100011110 lev=3 vol=6 ((d'c')+(b'a'))(dc)'
- 1673 : 0x011e tt=0000000100011110 lev=4 vol=6 (((b'a')'c)'d')+((b'a')c')
- 1699 : 0x011e tt=0000000100011110 lev=4 vol=6 (((b'a')c')+d)'((b'a')'c)'
- 1743 : 0x011e tt=0000000100011110 lev=4 vol=6 (((b'a')'d)'c')+((b'a')d')
- 1767 : 0x011e tt=0000000100011110 lev=4 vol=6 (((b'a')d')+c)'((b'a')'d)'
-
-Class 29. Func 27. Functions = 4. Volume = 16. 0000000100011111
- 1422 : 0x011f tt=0000000100011111 lev=3 vol=7 ((d'c')(b'a')')+((dc)'(b'a'))
- 1423 : 0x011f tt=0000000100011111 lev=3 vol=5 ((d'c')'(b'a')')'(dc)'
- 1682 : 0x011f tt=0000000100011111 lev=4 vol=5 (((b'a')c')'d)'((b'a')'c)'
- 1763 : 0x011f tt=0000000100011111 lev=4 vol=5 (((b'a')d')'c)'((b'a')'d)'
-
-Class 30. Func 28. Functions = 5. Volume = 21. 0000000100101100
- 711 : 0x012c tt=0000000100101100 lev=3 vol=7 ((b'a')+d)'((b'a)+c)'
- 922 : 0x012c tt=0000000100101100 lev=3 vol=7 ((c'b')+d)'((b'a)+c)'
- 1239 : 0x012c tt=0000000100101100 lev=3 vol=7 ((d'b')+c)'((b'a')+d)'
- 1407 : 0x012c tt=0000000100101100 lev=3 vol=7 ((d'c')+b)'((da)'(ca')')
- 1408 : 0x012c tt=0000000100101100 lev=3 vol=7 ((d'c')+b)'((d'a)'(c'a')')'
-
-Class 31. Func 29. Functions = 2. Volume = 8. 0000000100101101
- 690 : 0x012d tt=0000000100101101 lev=3 vol=6 ((b'a')'d)'((b'a)+c)'
- 898 : 0x012d tt=0000000100101101 lev=3 vol=6 ((c'b')'d)'((b'a)+c)'
-
-Class 32. Func 30. Functions = 1. Volume = 5. 0000000100101111
- 688 : 0x012f tt=0000000100101111 lev=3 vol=5 ((b'a')'d)'((b'a)'c)'
-
-Class 33. Func 31. Functions = 10. Volume = 33. 0000000100111100
- 978 : 0x013c tt=0000000100111100 lev=3 vol=7 ((c+b)+d)((b'a')'d)'
- 979 : 0x013c tt=0000000100111100 lev=3 vol=7 ((c+b)+d)((c'a')'d)'
- 987 : 0x013c tt=0000000100111100 lev=3 vol=7 ((c+b)'(b'a')')'((c+b)+d)
- 1003 : 0x013c tt=0000000100111100 lev=3 vol=7 ((c+b)'(c'a')')'((c+b)+d)
- 1050 : 0x013c tt=0000000100111100 lev=3 vol=7 ((da)'(cb)')((c'b')+d)'
- 1060 : 0x013c tt=0000000100111100 lev=3 vol=7 ((da)'(c'b'))+((cb)'d')
- 1101 : 0x013c tt=0000000100111100 lev=3 vol=7 ((da')'(c+b)')'((c'b')'d)'
- 1238 : 0x013c tt=0000000100111100 lev=3 vol=6 ((d'b')+c)'((b'a')'d)'
- 1406 : 0x013c tt=0000000100111100 lev=3 vol=6 ((d'c')+b)'((c'a')'d)'
- 1742 : 0x013c tt=0000000100111100 lev=4 vol=6 (((b'a')'d)'c')+(d'b')
-
-Class 34. Func 32. Functions = 6. Volume = 18. 0000000100111101
- 973 : 0x013d tt=0000000100111101 lev=3 vol=7 ((c+b)d')+((b'a')c')
- 974 : 0x013d tt=0000000100111101 lev=3 vol=7 ((c+b)d')+((c'a')b')
- 975 : 0x013d tt=0000000100111101 lev=3 vol=7 ((c+b)d')+((c'b')a')
- 985 : 0x013d tt=0000000100111101 lev=3 vol=7 ((c+b)'(b'a')')'((c'b')'d)'
- 986 : 0x013d tt=0000000100111101 lev=3 vol=6 ((c+b)'(b'a')')'((c+b)d)'
- 1002 : 0x013d tt=0000000100111101 lev=3 vol=6 ((c+b)'(c'a')')'((c+b)d)'
-
-Class 35. Func 33. Functions = 4. Volume = 13. 0000000100111110
- 830 : 0x013e tt=0000000100111110 lev=3 vol=6 ((cb)'d')+((b'a')c')
- 833 : 0x013e tt=0000000100111110 lev=3 vol=6 ((cb)'d')+((c'a')b')
- 883 : 0x013e tt=0000000100111110 lev=3 vol=6 ((c'b')a')+((cb)'d')
- 1695 : 0x013e tt=0000000100111110 lev=4 vol=6 (((b'a')c')+d)'(cb)'
-
-Class 36. Func 34. Functions = 5. Volume = 22. 0000000100111111
- 1049 : 0x013f tt=0000000100111111 lev=3 vol=6 ((da)'(cb)')((c'b')'d)'
- 1171 : 0x013f tt=0000000100111111 lev=3 vol=6 ((db)'(cb)')((c'a')'d)'
- 1233 : 0x013f tt=0000000100111111 lev=3 vol=5 ((d'b')'c)'((b'a')'d)'
- 1402 : 0x013f tt=0000000100111111 lev=3 vol=5 ((d'c')'b)'((c'a')'d)'
- 1678 : 0x013f tt=0000000100111111 lev=4 vol=5 (((b'a')c')'d)'(cb)'
-
-Class 37. Func 35. Functions = 10. Volume = 25. 0000000101101000
- 727 : 0x0168 tt=0000000101101000 lev=3 vol=8 ((b+a)+c)'((b'a')+d)'
- 784 : 0x0168 tt=0000000101101000 lev=3 vol=8 ((c'a')+d)'((b+a)+c)'
- 800 : 0x0168 tt=0000000101101000 lev=3 vol=8 ((c+a)+b)'((b'a')+d)'
- 803 : 0x0168 tt=0000000101101000 lev=3 vol=8 ((c+a)+b)'((c'a')+d)'
- 925 : 0x0168 tt=0000000101101000 lev=3 vol=8 ((c'b')+d)'((b+a)+c)'
- 932 : 0x0168 tt=0000000101101000 lev=3 vol=8 ((c'b')+d)'((c+a)+b)'
- 964 : 0x0168 tt=0000000101101000 lev=3 vol=8 ((c+b)+a)'((b'a')+d)'
- 967 : 0x0168 tt=0000000101101000 lev=3 vol=8 ((c+b)+a)'((c'a')+d)'
- 970 : 0x0168 tt=0000000101101000 lev=3 vol=8 ((c+b)+a)'((c'b')+d)'
- 1574 : 0x0168 tt=0000000101101000 lev=4 vol=8 (((ba)'d')+c)'((b'a')+d)'
-
-Class 38. Func 36. Functions = 9. Volume = 21. 0000000101101001
- 726 : 0x0169 tt=0000000101101001 lev=3 vol=7 ((b+a)+c)'((b'a')'d)'
- 775 : 0x0169 tt=0000000101101001 lev=3 vol=7 ((c'a')'d)'((b+a)+c)'
- 799 : 0x0169 tt=0000000101101001 lev=3 vol=7 ((c+a)+b)'((b'a')'d)'
- 802 : 0x0169 tt=0000000101101001 lev=3 vol=7 ((c+a)+b)'((c'a')'d)'
- 900 : 0x0169 tt=0000000101101001 lev=3 vol=7 ((c'b')'d)'((b+a)+c)'
- 905 : 0x0169 tt=0000000101101001 lev=3 vol=7 ((c'b')'d)'((c+a)+b)'
- 963 : 0x0169 tt=0000000101101001 lev=3 vol=7 ((c+b)+a)'((b'a')'d)'
- 966 : 0x0169 tt=0000000101101001 lev=3 vol=7 ((c+b)+a)'((c'a')'d)'
- 969 : 0x0169 tt=0000000101101001 lev=3 vol=7 ((c+b)+a)'((c'b')'d)'
-
-Class 42. Func 37. Functions = 1. Volume = 5. 0000000101101111
- 715 : 0x016f tt=0000000101101111 lev=3 vol=6 ((b+a)'c)'((b'a')'d)'
-
-Class 44. Func 38. Functions = 10. Volume = 39. 0000000101111111
- 1481 : 0x017f tt=0000000101111111 lev=4 vol=8 (((ba)c)'d')+((da')(c'b'))
- 1482 : 0x017f tt=0000000101111111 lev=4 vol=8 (((ba)c)'d')+((db')(c'a'))
- 1483 : 0x017f tt=0000000101111111 lev=4 vol=8 (((ba)c)'d')+((dc')(b'a'))
- 1486 : 0x017f tt=0000000101111111 lev=4 vol=7 (((ba)c)'(da)')((c'b')'d)'
- 1488 : 0x017f tt=0000000101111111 lev=4 vol=7 (((ba)c)'(db)')((c'a')'d)'
- 1490 : 0x017f tt=0000000101111111 lev=4 vol=7 (((ba)c)'(dc)')((b'a')'d)'
- 1569 : 0x017f tt=0000000101111111 lev=4 vol=6 (((ba)'d')'c)'((b'a')'d)'
- 1680 : 0x017f tt=0000000101111111 lev=4 vol=6 (((b'a')c')'d)'((ba)c)'
- 1684 : 0x017f tt=0000000101111111 lev=4 vol=6 (((b'a')c')'d)'((ca)b)'
- 1687 : 0x017f tt=0000000101111111 lev=4 vol=6 (((b'a')c')'d)'((cb)a)'
-
-Class 45. Func 39. Functions = 106. Volume = 249. 0000000110000000
- 814 : 0x0180 tt=0000000110000000 lev=3 vol=8 ((c+a)'(b+a)')(d+a)
- 816 : 0x0180 tt=0000000110000000 lev=3 vol=8 ((c+a)'(b+a)')(d+b)
- 818 : 0x0180 tt=0000000110000000 lev=3 vol=8 ((c+a)'(b+a)')(d+c)
- 992 : 0x0180 tt=0000000110000000 lev=3 vol=8 ((c+b)'(b+a)')(d+a)
- 994 : 0x0180 tt=0000000110000000 lev=3 vol=8 ((c+b)'(b+a)')(d+b)
- 996 : 0x0180 tt=0000000110000000 lev=3 vol=8 ((c+b)'(b+a)')(d+c)
- 1008 : 0x0180 tt=0000000110000000 lev=3 vol=8 ((c+b)'(c+a)')(d+a)
- 1010 : 0x0180 tt=0000000110000000 lev=3 vol=8 ((c+b)'(c+a)')(d+b)
- 1012 : 0x0180 tt=0000000110000000 lev=3 vol=8 ((c+b)'(c+a)')(d+c)
- 1099 : 0x0180 tt=0000000110000000 lev=3 vol=7 ((da')'(cb)')'((d'a)'(c'b')')'
- 1169 : 0x0180 tt=0000000110000000 lev=3 vol=7 ((db)'(c'a)')((d'a')'(cb')')
- 1170 : 0x0180 tt=0000000110000000 lev=3 vol=7 ((db)'(ca')')((da')'(cb)')'
- 1176 : 0x0180 tt=0000000110000000 lev=3 vol=7 ((db)'(cb')')((da')'(ca)')'
- 1177 : 0x0180 tt=0000000110000000 lev=3 vol=7 ((db)'(cb')')((d'a')'(c'a)')
- 1185 : 0x0180 tt=0000000110000000 lev=3 vol=7 ((db)'(d'a')')((cb)'(c'a')')'
- 1186 : 0x0180 tt=0000000110000000 lev=3 vol=7 ((db)'(d'a')')((cb')'(c'a)')
- 1201 : 0x0180 tt=0000000110000000 lev=3 vol=7 ((d'b)'(c'a')')'((d'a')'(c'b)')
- 1206 : 0x0180 tt=0000000110000000 lev=3 vol=7 ((d'b)'(c'b')')'((da')'(ca)')'
- 1207 : 0x0180 tt=0000000110000000 lev=3 vol=7 ((d'b)'(c'b')')'((d'a')'(c'a)')
- 1209 : 0x0180 tt=0000000110000000 lev=3 vol=7 ((d'b)'(da')')'((c'b)'(ca')')
- 1210 : 0x0180 tt=0000000110000000 lev=3 vol=7 ((d'b)'(da')')'((c'b')'(ca)')'
- 1218 : 0x0180 tt=0000000110000000 lev=3 vol=7 ((db')'(ca)')'((da)'(cb')')
- 1219 : 0x0180 tt=0000000110000000 lev=3 vol=7 ((db')'(ca)')'((d'b)'(c'a')')'
- 1222 : 0x0180 tt=0000000110000000 lev=3 vol=7 ((db')'(cb)')'((da)'(ca')')
- 1223 : 0x0180 tt=0000000110000000 lev=3 vol=7 ((db')'(cb)')'((d'a)'(c'a')')'
- 1225 : 0x0180 tt=0000000110000000 lev=3 vol=7 ((db')'(d'a)')'((cb)'(c'a')')'
- 1226 : 0x0180 tt=0000000110000000 lev=3 vol=7 ((db')'(d'a)')'((cb')'(c'a)')
- 1245 : 0x0180 tt=0000000110000000 lev=3 vol=7 ((d'b')'(c'a)')((d'a)'(c'b')')'
- 1248 : 0x0180 tt=0000000110000000 lev=3 vol=7 ((d'b')'(ca')')((da)'(c'b)')
- 1254 : 0x0180 tt=0000000110000000 lev=3 vol=7 ((d'b')'(c'b)')((da)'(ca')')
- 1255 : 0x0180 tt=0000000110000000 lev=3 vol=7 ((d'b')'(c'b)')((d'a)'(c'a')')'
- 1256 : 0x0180 tt=0000000110000000 lev=3 vol=7 ((d'b')'(da)')((c'b)'(ca')')
- 1257 : 0x0180 tt=0000000110000000 lev=3 vol=7 ((d'b')'(da)')((c'b')'(ca)')'
- 1309 : 0x0180 tt=0000000110000000 lev=3 vol=7 ((dc)'(b'a)')((d'a')'(c'b)')
- 1310 : 0x0180 tt=0000000110000000 lev=3 vol=7 ((dc)'(b'a)')((db')'(ca)')'
- 1312 : 0x0180 tt=0000000110000000 lev=3 vol=7 ((dc)'(ba')')((da')'(cb)')'
- 1314 : 0x0180 tt=0000000110000000 lev=3 vol=7 ((dc)'(ba')')((d'b')'(c'a)')
- 1317 : 0x0180 tt=0000000110000000 lev=3 vol=7 ((dc)'(c'a)')((db')'(ba)')'
- 1318 : 0x0180 tt=0000000110000000 lev=3 vol=7 ((dc)'(c'a)')((d'b')'(ba')')
- 1323 : 0x0180 tt=0000000110000000 lev=3 vol=7 ((dc)'(c'b)')((da')'(ba)')'
- 1324 : 0x0180 tt=0000000110000000 lev=3 vol=7 ((dc)'(c'b)')((d'a')'(b'a)')
- 1335 : 0x0180 tt=0000000110000000 lev=3 vol=7 ((dc)'(d'a')')((cb)'(b'a')')'
- 1336 : 0x0180 tt=0000000110000000 lev=3 vol=7 ((dc)'(d'a')')((c'b)'(b'a)')
- 1340 : 0x0180 tt=0000000110000000 lev=3 vol=7 ((dc)'(d'b')')((ca)'(b'a')')'
- 1341 : 0x0180 tt=0000000110000000 lev=3 vol=7 ((dc)'(d'b')')((c'a)'(ba')')
- 1353 : 0x0180 tt=0000000110000000 lev=3 vol=7 ((d'c)'(b'a')')'((d'a')'(cb')')
- 1354 : 0x0180 tt=0000000110000000 lev=3 vol=7 ((d'c)'(b'a')')'((d'b')'(ca')')
- 1356 : 0x0180 tt=0000000110000000 lev=3 vol=7 ((d'c)'(c'a')')'((db')'(ba)')'
- 1357 : 0x0180 tt=0000000110000000 lev=3 vol=7 ((d'c)'(c'a')')'((d'b')'(ba')')
- 1359 : 0x0180 tt=0000000110000000 lev=3 vol=7 ((d'c)'(c'b')')'((da')'(ba)')'
- 1360 : 0x0180 tt=0000000110000000 lev=3 vol=7 ((d'c)'(c'b')')'((d'a')'(b'a)')
- 1362 : 0x0180 tt=0000000110000000 lev=3 vol=7 ((d'c)'(da')')'((cb')'(ba')')
- 1363 : 0x0180 tt=0000000110000000 lev=3 vol=7 ((d'c)'(da')')'((c'b')'(ba)')'
- 1365 : 0x0180 tt=0000000110000000 lev=3 vol=7 ((d'c)'(db')')'((ca')'(b'a)')
- 1366 : 0x0180 tt=0000000110000000 lev=3 vol=7 ((d'c)'(db')')'((c'a')'(ba)')'
- 1374 : 0x0180 tt=0000000110000000 lev=3 vol=7 ((dc')'(ba)')'((da)'(c'b)')
- 1375 : 0x0180 tt=0000000110000000 lev=3 vol=7 ((dc')'(ba)')'((db)'(c'a)')
- 1376 : 0x0180 tt=0000000110000000 lev=3 vol=7 ((dc')'(ba)')'((d'c)'(b'a')')'
- 1381 : 0x0180 tt=0000000110000000 lev=3 vol=7 ((dc')'(ca)')'((db)'(b'a)')
- 1382 : 0x0180 tt=0000000110000000 lev=3 vol=7 ((dc')'(ca)')'((d'b)'(b'a')')'
- 1384 : 0x0180 tt=0000000110000000 lev=3 vol=7 ((dc')'(cb)')'((da)'(ba')')
- 1385 : 0x0180 tt=0000000110000000 lev=3 vol=7 ((dc')'(cb)')'((d'a)'(b'a')')'
- 1386 : 0x0180 tt=0000000110000000 lev=3 vol=7 ((dc')'(d'a)')'((cb)'(b'a')')'
- 1387 : 0x0180 tt=0000000110000000 lev=3 vol=7 ((dc')'(d'a)')'((c'b)'(b'a)')
- 1389 : 0x0180 tt=0000000110000000 lev=3 vol=7 ((dc')'(d'b)')'((ca)'(b'a')')'
- 1390 : 0x0180 tt=0000000110000000 lev=3 vol=7 ((dc')'(d'b)')'((c'a)'(ba')')
- 1413 : 0x0180 tt=0000000110000000 lev=3 vol=7 ((d'c')'(b'a)')((d'a)'(c'b')')'
- 1414 : 0x0180 tt=0000000110000000 lev=3 vol=7 ((d'c')'(b'a)')((db)'(ca')')
- 1416 : 0x0180 tt=0000000110000000 lev=3 vol=7 ((d'c')'(ba')')((da)'(cb')')
- 1417 : 0x0180 tt=0000000110000000 lev=3 vol=7 ((d'c')'(ba')')((d'b)'(c'a')')'
- 1436 : 0x0180 tt=0000000110000000 lev=3 vol=7 ((d'c')'(ca')')((db)'(b'a)')
- 1437 : 0x0180 tt=0000000110000000 lev=3 vol=7 ((d'c')'(ca')')((d'b)'(b'a')')'
- 1439 : 0x0180 tt=0000000110000000 lev=3 vol=7 ((d'c')'(cb')')((da)'(ba')')
- 1440 : 0x0180 tt=0000000110000000 lev=3 vol=7 ((d'c')'(cb')')((d'a)'(b'a')')'
- 1441 : 0x0180 tt=0000000110000000 lev=3 vol=7 ((d'c')'(da)')((cb')'(ba')')
- 1442 : 0x0180 tt=0000000110000000 lev=3 vol=7 ((d'c')'(da)')((c'b')'(ba)')'
- 1444 : 0x0180 tt=0000000110000000 lev=3 vol=7 ((d'c')'(db)')((ca')'(b'a)')
- 1445 : 0x0180 tt=0000000110000000 lev=3 vol=7 ((d'c')'(db)')((c'a')'(ba)')'
- 1487 : 0x0180 tt=0000000110000000 lev=4 vol=7 (((ba)c)'(da')')'((c'b')'d)'
- 1489 : 0x0180 tt=0000000110000000 lev=4 vol=7 (((ba)c)'(db')')'((c'a')'d)'
- 1491 : 0x0180 tt=0000000110000000 lev=4 vol=7 (((ba)c)'(dc')')'((b'a')'d)'
- 1501 : 0x0180 tt=0000000110000000 lev=4 vol=7 (((ba)'c)'(da)')((db')'c')'
- 1505 : 0x0180 tt=0000000110000000 lev=4 vol=7 (((ba)'c)'(db)')((da')'c')'
- 1507 : 0x0180 tt=0000000110000000 lev=4 vol=7 (((ba)'c)'(d'c')')((b'a')'d)'
- 1560 : 0x0180 tt=0000000110000000 lev=4 vol=7 (((ba)d')'(c'a')')'((db')'c')'
- 1563 : 0x0180 tt=0000000110000000 lev=4 vol=7 (((ba)d')'(c'b')')'((da')'c')'
- 1566 : 0x0180 tt=0000000110000000 lev=4 vol=7 (((ba)d')'(dc')')'((b'a')'c')'
- 1576 : 0x0180 tt=0000000110000000 lev=4 vol=7 (((ba)'d')'(c'a)')((c'b')'d)'
- 1579 : 0x0180 tt=0000000110000000 lev=4 vol=7 (((ba)'d')'(c'b)')((c'a')'d)'
- 1581 : 0x0180 tt=0000000110000000 lev=4 vol=7 (((ba)'d')'(dc)')((b'a')'c')'
- 1703 : 0x0180 tt=0000000110000000 lev=4 vol=7 (((b'a')c')'(d'a)')'((cb)'d')'
- 1704 : 0x0180 tt=0000000110000000 lev=4 vol=7 (((b'a')c')'(d'b)')'((ca)'d')'
- 1707 : 0x0180 tt=0000000110000000 lev=4 vol=7 (((b'a')c')'(d'c)')'((ba)'d')'
- 1709 : 0x0180 tt=0000000110000000 lev=4 vol=7 (((b'a')c')'((ba)d')')'(d'c')'
- 1720 : 0x0180 tt=0000000110000000 lev=4 vol=7 (((b'a')'c')'(d'a')')((d'b)'c)'
- 1723 : 0x0180 tt=0000000110000000 lev=4 vol=7 (((b'a')'c')'(d'b')')((d'a)'c)'
- 1724 : 0x0180 tt=0000000110000000 lev=4 vol=7 (((b'a')'c')'(dc)')((ba)'d')'
- 1729 : 0x0180 tt=0000000110000000 lev=4 vol=7 (((b'a')'c')'((ba)'d')')(dc)'
- 1736 : 0x0180 tt=0000000110000000 lev=4 vol=7 (((b'a')d)'(ca)')'((d'b)'c)'
- 1737 : 0x0180 tt=0000000110000000 lev=4 vol=7 (((b'a')d)'(cb)')'((d'a)'c)'
- 1739 : 0x0180 tt=0000000110000000 lev=4 vol=7 (((b'a')d)'(d'c)')'((ba)'c)'
- 1740 : 0x0180 tt=0000000110000000 lev=4 vol=7 (((b'a')d)'((ba)c)')'(dc)'
- 1746 : 0x0180 tt=0000000110000000 lev=4 vol=7 (((b'a')'d)'(ca')')((cb)'d')'
- 1752 : 0x0180 tt=0000000110000000 lev=4 vol=7 (((b'a')'d)'(cb')')((ca)'d')'
- 1755 : 0x0180 tt=0000000110000000 lev=4 vol=7 (((b'a')'d)'(d'c')')((ba)'c)'
- 1756 : 0x0180 tt=0000000110000000 lev=4 vol=7 (((b'a')'d)'((ba)'c)')(d'c')'
-
-Class 46. Func 40. Functions = 46. Volume = 109. 0000000110000001
- 813 : 0x0181 tt=0000000110000001 lev=3 vol=7 ((c+a)'(b+a)')(da)'
- 815 : 0x0181 tt=0000000110000001 lev=3 vol=7 ((c+a)'(b+a)')(db)'
- 817 : 0x0181 tt=0000000110000001 lev=3 vol=7 ((c+a)'(b+a)')(dc)'
- 991 : 0x0181 tt=0000000110000001 lev=3 vol=7 ((c+b)'(b+a)')(da)'
- 993 : 0x0181 tt=0000000110000001 lev=3 vol=7 ((c+b)'(b+a)')(db)'
- 995 : 0x0181 tt=0000000110000001 lev=3 vol=7 ((c+b)'(b+a)')(dc)'
- 1007 : 0x0181 tt=0000000110000001 lev=3 vol=7 ((c+b)'(c+a)')(da)'
- 1009 : 0x0181 tt=0000000110000001 lev=3 vol=7 ((c+b)'(c+a)')(db)'
- 1011 : 0x0181 tt=0000000110000001 lev=3 vol=7 ((c+b)'(c+a)')(dc)'
- 1027 : 0x0181 tt=0000000110000001 lev=3 vol=7 ((da)'(b'a)')((c'b)'(ca')')
- 1029 : 0x0181 tt=0000000110000001 lev=3 vol=7 ((da)'(b'a)')((c'b')'(ca)')'
- 1033 : 0x0181 tt=0000000110000001 lev=3 vol=7 ((da)'(ba')')((cb)'(c'a')')'
- 1034 : 0x0181 tt=0000000110000001 lev=3 vol=7 ((da)'(ba')')((cb')'(c'a)')
- 1036 : 0x0181 tt=0000000110000001 lev=3 vol=7 ((da)'(b+a)')(c+a)'
- 1038 : 0x0181 tt=0000000110000001 lev=3 vol=7 ((da)'(b+a)')(c+b)'
- 1040 : 0x0181 tt=0000000110000001 lev=3 vol=7 ((da)'(c'a)')((cb')'(ba')')
- 1041 : 0x0181 tt=0000000110000001 lev=3 vol=7 ((da)'(c'a)')((c'b')'(ba)')'
- 1044 : 0x0181 tt=0000000110000001 lev=3 vol=7 ((da)'(ca')')((cb)'(b'a')')'
- 1045 : 0x0181 tt=0000000110000001 lev=3 vol=7 ((da)'(ca')')((c'b)'(b'a)')
- 1047 : 0x0181 tt=0000000110000001 lev=3 vol=7 ((da)'(c+a)')(b+a)'
- 1048 : 0x0181 tt=0000000110000001 lev=3 vol=7 ((da)'(c+a)')(c+b)'
- 1052 : 0x0181 tt=0000000110000001 lev=3 vol=7 ((da)'(c'b)')((ca')'(b'a)')
- 1053 : 0x0181 tt=0000000110000001 lev=3 vol=7 ((da)'(c'b)')((c'a')'(ba)')'
- 1057 : 0x0181 tt=0000000110000001 lev=3 vol=7 ((da)'(cb')')((ca)'(b'a')')'
- 1058 : 0x0181 tt=0000000110000001 lev=3 vol=7 ((da)'(cb')')((c'a)'(ba')')
- 1062 : 0x0181 tt=0000000110000001 lev=3 vol=7 ((da)'(c+b)')(b+a)'
- 1064 : 0x0181 tt=0000000110000001 lev=3 vol=7 ((da)'(c+b)')(c+a)'
- 1070 : 0x0181 tt=0000000110000001 lev=3 vol=7 ((d'a)'b)'((c+a)'(b'a)')
- 1071 : 0x0181 tt=0000000110000001 lev=3 vol=6 ((d'a)'b)'((cb)'(c'a')')'
- 1072 : 0x0181 tt=0000000110000001 lev=3 vol=6 ((d'a)'b)'((cb')'(c'a)')
- 1075 : 0x0181 tt=0000000110000001 lev=3 vol=6 ((d'a)'c)'((cb)'(b'a')')'
- 1076 : 0x0181 tt=0000000110000001 lev=3 vol=6 ((d'a)'c)'((c'b)'(b'a)')
- 1088 : 0x0181 tt=0000000110000001 lev=3 vol=6 ((d'a)'(c'b')')'((cb)'a)'
- 1188 : 0x0181 tt=0000000110000001 lev=3 vol=6 ((d'b)'a)'((c'b)'(ca')')
- 1190 : 0x0181 tt=0000000110000001 lev=3 vol=6 ((d'b)'a)'((c'b')'(ca)')'
- 1193 : 0x0181 tt=0000000110000001 lev=3 vol=6 ((d'b)'c)'((ca)'(b'a')')'
- 1194 : 0x0181 tt=0000000110000001 lev=3 vol=6 ((d'b)'c)'((c'a)'(ba')')
- 1200 : 0x0181 tt=0000000110000001 lev=3 vol=6 ((d'b)'(c'a')')'((ca)'b)'
- 1343 : 0x0181 tt=0000000110000001 lev=3 vol=6 ((d'c)'a)'((cb')'(ba')')
- 1344 : 0x0181 tt=0000000110000001 lev=3 vol=6 ((d'c)'a)'((c'b')'(ba)')'
- 1347 : 0x0181 tt=0000000110000001 lev=3 vol=6 ((d'c)'b)'((ca')'(b'a)')
- 1348 : 0x0181 tt=0000000110000001 lev=3 vol=6 ((d'c)'b)'((c'a')'(ba)')'
- 1352 : 0x0181 tt=0000000110000001 lev=3 vol=6 ((d'c)'(b'a')')'((ba)'c)'
- 1554 : 0x0181 tt=0000000110000001 lev=4 vol=6 (((ba)d')'c)'((b'a')'c')'
- 1559 : 0x0181 tt=0000000110000001 lev=4 vol=6 (((ba)d')'(c'a')')'(c'b)'
- 1562 : 0x0181 tt=0000000110000001 lev=4 vol=6 (((ba)d')'(c'b')')'(c'a)'
-
-Class 47. Func 41. Functions = 28. Volume = 81. 0000000110000010
- 983 : 0x0182 tt=0000000110000010 lev=3 vol=7 ((c+b)'(ba')')(d+a)
- 999 : 0x0182 tt=0000000110000010 lev=3 vol=7 ((c+b)'(ca')')(d+a)
- 1125 : 0x0182 tt=0000000110000010 lev=3 vol=7 ((d'a')'(c+b)')((b'a')'d)'
- 1126 : 0x0182 tt=0000000110000010 lev=3 vol=7 ((d'a')'(c+b)')((c'a')'d)'
- 1133 : 0x0182 tt=0000000110000010 lev=3 vol=7 ((d+a)(ba')')(c+b)'
- 1136 : 0x0182 tt=0000000110000010 lev=3 vol=7 ((d+a)(ca')')(c+b)'
- 1139 : 0x0182 tt=0000000110000010 lev=3 vol=7 ((d+a)(c'b)')((ba)'c)'
- 1140 : 0x0182 tt=0000000110000010 lev=3 vol=7 ((d+a)(cb')')((ca)'b)'
- 1142 : 0x0182 tt=0000000110000010 lev=3 vol=7 ((d+a)(c+b)')(ba')'
- 1143 : 0x0182 tt=0000000110000010 lev=3 vol=7 ((d+a)(c+b)')(ca')'
- 1144 : 0x0182 tt=0000000110000010 lev=3 vol=7 ((d+a)(c+b)')(db)'
- 1145 : 0x0182 tt=0000000110000010 lev=3 vol=7 ((d+a)(c+b)')(dc)'
- 1180 : 0x0182 tt=0000000110000010 lev=3 vol=7 ((db)'(c+b)')(d+a)
- 1187 : 0x0182 tt=0000000110000010 lev=3 vol=7 ((db)'(d+a))(c+b)'
- 1196 : 0x0182 tt=0000000110000010 lev=3 vol=7 ((d'b)'c)'((d+a)(c'b)')
- 1212 : 0x0182 tt=0000000110000010 lev=3 vol=7 ((db')'a')'((da)'(c+b)')
- 1328 : 0x0182 tt=0000000110000010 lev=3 vol=7 ((dc)'(c+b)')(d+a)
- 1337 : 0x0182 tt=0000000110000010 lev=3 vol=7 ((dc)'(d+a))(c+b)'
- 1349 : 0x0182 tt=0000000110000010 lev=3 vol=7 ((d'c)'b)'((d+a)(cb')')
- 1368 : 0x0182 tt=0000000110000010 lev=3 vol=7 ((dc')'a')'((da)'(c+b)')
- 1485 : 0x0182 tt=0000000110000010 lev=4 vol=7 (((ba)c)'(c'b')')'(d+a)
- 1499 : 0x0182 tt=0000000110000010 lev=4 vol=7 (((ba)'c)'(c'b)')(d+a)
- 1504 : 0x0182 tt=0000000110000010 lev=4 vol=7 (((ba)'c)'(d+a))(c'b)'
- 1629 : 0x0182 tt=0000000110000010 lev=4 vol=7 (((ba')'c)+b)'(d+a)
- 1649 : 0x0182 tt=0000000110000010 lev=4 vol=7 (((ba')'d)+a)(c+b)'
- 1738 : 0x0182 tt=0000000110000010 lev=4 vol=7 (((b'a')d)'(d'a)')'(c+b)'
- 1753 : 0x0182 tt=0000000110000010 lev=4 vol=7 (((b'a')'d)'(c+b)')(d'a')'
- 1754 : 0x0182 tt=0000000110000010 lev=4 vol=7 (((b'a')'d)'(d'a')')(c+b)'
-
-Class 48. Func 42. Functions = 14. Volume = 43. 0000000110000011
- 982 : 0x0183 tt=0000000110000011 lev=3 vol=6 ((c+b)'(ba')')(da)'
- 998 : 0x0183 tt=0000000110000011 lev=3 vol=6 ((c+b)'(ca')')(da)'
- 1031 : 0x0183 tt=0000000110000011 lev=3 vol=6 ((da)'(ba')')(c+b)'
- 1043 : 0x0183 tt=0000000110000011 lev=3 vol=6 ((da)'(ca')')(c+b)'
- 1051 : 0x0183 tt=0000000110000011 lev=3 vol=6 ((da)'(c'b)')((ba)'c)'
- 1056 : 0x0183 tt=0000000110000011 lev=3 vol=6 ((da)'(cb')')((ca)'b)'
- 1061 : 0x0183 tt=0000000110000011 lev=3 vol=6 ((da)'(c+b)')(ba')'
- 1063 : 0x0183 tt=0000000110000011 lev=3 vol=6 ((da)'(c+b)')(ca')'
- 1078 : 0x0183 tt=0000000110000011 lev=3 vol=6 ((d'a)'(b'a')')'(c+b)'
- 1079 : 0x0183 tt=0000000110000011 lev=3 vol=6 ((d'a)'(c'a')')'(c+b)'
- 1484 : 0x0183 tt=0000000110000011 lev=4 vol=6 (((ba)c)'(c'b')')'(da)'
- 1498 : 0x0183 tt=0000000110000011 lev=4 vol=6 (((ba)'c)'(c'b)')(da)'
- 1500 : 0x0183 tt=0000000110000011 lev=4 vol=6 (((ba)'c)'(da)')(c'b)'
- 1628 : 0x0183 tt=0000000110000011 lev=4 vol=6 (((ba')'c)+b)'(da)'
-
-Class 49. Func 43. Functions = 1. Volume = 5. 0000000110000110
- 710 : 0x0186 tt=0000000110000110 lev=3 vol=7 ((b'a')+d)'((ba)+c)'
-
-Class 51. Func 44. Functions = 22. Volume = 56. 0000000110001001
- 648 : 0x0189 tt=0000000110001001 lev=3 vol=6 ((b'a')c')+((ba)d')
- 764 : 0x0189 tt=0000000110001001 lev=3 vol=6 ((ca')'(b+a)')(da)'
- 765 : 0x0189 tt=0000000110001001 lev=3 vol=6 ((ca')'(b+a)')(db)'
- 770 : 0x0189 tt=0000000110001001 lev=3 vol=6 ((c'a')b')+((ba)d')
- 869 : 0x0189 tt=0000000110001001 lev=3 vol=6 ((cb')'(b+a)')(da)'
- 870 : 0x0189 tt=0000000110001001 lev=3 vol=6 ((cb')'(b+a)')(db)'
- 882 : 0x0189 tt=0000000110001001 lev=3 vol=6 ((c'b')a')+((ba)d')
- 1019 : 0x0189 tt=0000000110001001 lev=3 vol=6 ((da)'b)+((cb')'a')
- 1028 : 0x0189 tt=0000000110001001 lev=3 vol=6 ((da)'(b'a)')((c'b')'a')'
- 1032 : 0x0189 tt=0000000110001001 lev=3 vol=6 ((da)'(ba')')((c'a')'b')'
- 1035 : 0x0189 tt=0000000110001001 lev=3 vol=6 ((da)'(b+a)')(ca')'
- 1037 : 0x0189 tt=0000000110001001 lev=3 vol=6 ((da)'(b+a)')(cb')'
- 1042 : 0x0189 tt=0000000110001001 lev=3 vol=6 ((da)'(ca')')(b+a)'
- 1055 : 0x0189 tt=0000000110001001 lev=3 vol=6 ((da)'(cb')')(b+a)'
- 1065 : 0x0189 tt=0000000110001001 lev=3 vol=6 ((d'a)b)+((b'a')c')
- 1066 : 0x0189 tt=0000000110001001 lev=3 vol=6 ((d'a)b)+((c'a')b')
- 1067 : 0x0189 tt=0000000110001001 lev=3 vol=6 ((d'a)b)+((c'b')a')
- 1068 : 0x0189 tt=0000000110001001 lev=3 vol=6 ((d'a)'b)'((ca')'(b'a)')
- 1069 : 0x0189 tt=0000000110001001 lev=3 vol=5 ((d'a)'b)'((c'a')'b')'
- 1087 : 0x0189 tt=0000000110001001 lev=3 vol=5 ((d'a)'(c'b')')'(b'a)'
- 1189 : 0x0189 tt=0000000110001001 lev=3 vol=5 ((d'b)'a)'((c'b')'a')'
- 1199 : 0x0189 tt=0000000110001001 lev=3 vol=5 ((d'b)'(c'a')')'(ba')'
-
-Class 52. Func 45. Functions = 5. Volume = 17. 0000000110001011
- 868 : 0x018b tt=0000000110001011 lev=3 vol=5 ((cb')'(ba')')(da)'
- 940 : 0x018b tt=0000000110001011 lev=3 vol=5 ((c'b')'(ba)')'(da)'
- 1030 : 0x018b tt=0000000110001011 lev=3 vol=5 ((da)'(ba')')(cb')'
- 1054 : 0x018b tt=0000000110001011 lev=3 vol=5 ((da)'(cb')')(ba')'
- 1077 : 0x018b tt=0000000110001011 lev=3 vol=5 ((d'a)'(b'a')')'(cb')'
-
-Class 53. Func 46. Functions = 1. Volume = 5. 0000000110001111
- 685 : 0x018f tt=0000000110001111 lev=3 vol=5 ((b'a')'d)'((ba)'c)'
-
-Class 56. Func 47. Functions = 4. Volume = 13. 0000000110011000
- 736 : 0x0198 tt=0000000110011000 lev=3 vol=7 ((b+a)'d')+((b'a')c')
- 771 : 0x0198 tt=0000000110011000 lev=3 vol=7 ((c'a')b')+((b+a)'d')
- 782 : 0x0198 tt=0000000110011000 lev=3 vol=6 ((c'a')+d)'(b+a)'
- 918 : 0x0198 tt=0000000110011000 lev=3 vol=6 ((c'b')+d)'(b+a)'
-
-Class 57. Func 48. Functions = 2. Volume = 7. 0000000110011001
- 774 : 0x0199 tt=0000000110011001 lev=3 vol=5 ((c'a')'d)'(b+a)'
- 894 : 0x0199 tt=0000000110011001 lev=3 vol=5 ((c'b')'d)'(b+a)'
-
-Class 59. Func 49. Functions = 7. Volume = 28. 0000000110011011
- 779 : 0x019b tt=0000000110011011 lev=3 vol=7 ((c'a')'d)'((c'a)'(b+a))'
- 944 : 0x019b tt=0000000110011011 lev=3 vol=7 ((c'b')'(b+a))'((c'a')'d)'
- 1118 : 0x019b tt=0000000110011011 lev=3 vol=7 ((d'a')'(cb'))'((da)'(ba')')
- 1119 : 0x019b tt=0000000110011011 lev=3 vol=7 ((d'a')'(cb'))'((d'a)'(b'a')')'
- 1583 : 0x019b tt=0000000110011011 lev=4 vol=7 (((b'a)c)'(ba')')((c'a')'d)'
- 1615 : 0x019b tt=0000000110011011 lev=4 vol=7 (((b'a)'d')'c)'((da)'(ba')')
- 1616 : 0x019b tt=0000000110011011 lev=4 vol=7 (((b'a)'d')'c)'((d'a)'(b'a')')'
-
-Class 62. Func 50. Functions = 6. Volume = 20. 0000000110101000
- 861 : 0x01a8 tt=0000000110101000 lev=3 vol=8 ((c'b)+(c+a))'(d+a)
- 873 : 0x01a8 tt=0000000110101000 lev=3 vol=8 ((cb')+(b+a))'(d+a)
- 888 : 0x01a8 tt=0000000110101000 lev=3 vol=6 ((c'b')+a)(d+a)
- 920 : 0x01a8 tt=0000000110101000 lev=3 vol=6 ((c'b')+d)'(d+a)
- 939 : 0x01a8 tt=0000000110101000 lev=3 vol=6 ((c'b')+d)'((c'b')+a)
- 1100 : 0x01a8 tt=0000000110101000 lev=3 vol=6 ((da')'(c'b'))'((d'a)'(c'b')')'
-
-Class 63. Func 51. Functions = 5. Volume = 18. 0000000110101001
- 860 : 0x01a9 tt=0000000110101001 lev=3 vol=7 ((c'b)+(c+a))'(da)'
- 872 : 0x01a9 tt=0000000110101001 lev=3 vol=7 ((cb')+(b+a))'(da)'
- 887 : 0x01a9 tt=0000000110101001 lev=3 vol=5 ((c'b')+a)(da)'
- 913 : 0x01a9 tt=0000000110101001 lev=3 vol=5 ((c'b')'d)'((c'b')+a)
- 1089 : 0x01a9 tt=0000000110101001 lev=3 vol=5 ((d'a)'(c'b')')'((c'b')a)'
-
-Class 64. Func 52. Functions = 6. Volume = 24. 0000000110101010
- 761 : 0x01aa tt=0000000110101010 lev=3 vol=6 ((ca')'(ba')')(d+a)
- 885 : 0x01aa tt=0000000110101010 lev=3 vol=5 ((c'b')'a')'(d+a)
- 897 : 0x01aa tt=0000000110101010 lev=3 vol=5 ((c'b')'d)'(d+a)
- 1211 : 0x01aa tt=0000000110101010 lev=3 vol=5 ((db')'a')'((c'a')'d)'
- 1367 : 0x01aa tt=0000000110101010 lev=3 vol=5 ((dc')'a')'((b'a')'d)'
- 1679 : 0x01aa tt=0000000110101010 lev=4 vol=5 (((b'a')c')'d)'(d'a')'
-
-Class 65. Func 53. Functions = 5. Volume = 17. 0000000110101011
- 642 : 0x01ab tt=0000000110101011 lev=3 vol=5 ((b'a')c')+(d'a)
- 760 : 0x01ab tt=0000000110101011 lev=3 vol=5 ((ca')'(ba')')(da)'
- 769 : 0x01ab tt=0000000110101011 lev=3 vol=5 ((c'a')b')+(d'a)
- 881 : 0x01ab tt=0000000110101011 lev=3 vol=5 ((c'b')a')+(d'a)
- 884 : 0x01ab tt=0000000110101011 lev=3 vol=4 ((c'b')'a')'(da)'
-
-Class 66. Func 54. Functions = 13. Volume = 41. 0000000110101100
- 809 : 0x01ac tt=0000000110101100 lev=3 vol=8 ((c+a)(ba)')'((b'a')+d)'
- 859 : 0x01ac tt=0000000110101100 lev=3 vol=8 ((c'b)'(c+a))'((b'a')+d)'
- 934 : 0x01ac tt=0000000110101100 lev=3 vol=8 ((c'b')+d)'((c+a)(ba)')'
- 937 : 0x01ac tt=0000000110101100 lev=3 vol=8 ((c'b')+d)'((c'b)'(c+a))'
- 1046 : 0x01ac tt=0000000110101100 lev=3 vol=7 ((da)'(ca')')((c'b')+d)'
- 1059 : 0x01ac tt=0000000110101100 lev=3 vol=7 ((da)'(c'b'))+((ca')'d')
- 1080 : 0x01ac tt=0000000110101100 lev=3 vol=7 ((d'a)'(c'a')')'((c'b')+d)'
- 1263 : 0x01ac tt=0000000110101100 lev=3 vol=7 ((d+b)'c')'((da)'(ca')')
- 1264 : 0x01ac tt=0000000110101100 lev=3 vol=7 ((d+b)'c')'((d'a)'(c'a')')'
- 1398 : 0x01ac tt=0000000110101100 lev=3 vol=7 ((d'c')'a')+((da)'(c'b')')
- 1748 : 0x01ac tt=0000000110101100 lev=4 vol=7 (((b'a')'d)'(ca')')((c'b')d')'
- 1749 : 0x01ac tt=0000000110101100 lev=4 vol=7 (((b'a')'d)'(ca')')((d'b')c')'
- 1750 : 0x01ac tt=0000000110101100 lev=4 vol=7 (((b'a')'d)'(ca')')((d'c')b')'
-
-Class 67. Func 55. Functions = 17. Volume = 50. 0000000110101101
- 808 : 0x01ad tt=0000000110101101 lev=3 vol=7 ((c+a)(ba)')'((b'a')'d)'
- 858 : 0x01ad tt=0000000110101101 lev=3 vol=7 ((c'b)'(c+a))'((b'a')'d)'
- 907 : 0x01ad tt=0000000110101101 lev=3 vol=7 ((c'b')'d)'((c+a)(ba)')'
- 911 : 0x01ad tt=0000000110101101 lev=3 vol=7 ((c'b')'d)'((c'b)'(c+a))'
- 1350 : 0x01ad tt=0000000110101101 lev=3 vol=7 ((d'c)'(b'a))'((db)'(ca')')
- 1521 : 0x01ad tt=0000000110101101 lev=4 vol=7 (((ba)'c')+a)((b'a')'d)'
- 1522 : 0x01ad tt=0000000110101101 lev=4 vol=7 (((ba)'c')+a)((c'b')'d)'
- 1592 : 0x01ad tt=0000000110101101 lev=4 vol=7 (((b'a)c')'(ca')')((b'a')'d)'
- 1593 : 0x01ad tt=0000000110101101 lev=4 vol=7 (((b'a)c')'(ca')')((c'b')'d)'
- 1595 : 0x01ad tt=0000000110101101 lev=4 vol=7 (((b'a)c')'(db)')((d'a)'c)'
- 1598 : 0x01ad tt=0000000110101101 lev=4 vol=7 (((b'a)'c')'(ca)')'((b'a')'d)'
- 1599 : 0x01ad tt=0000000110101101 lev=4 vol=7 (((b'a)'c')'(ca)')'((c'b')'d)'
- 1721 : 0x01ad tt=0000000110101101 lev=4 vol=7 (((b'a')'c')(d'b)')'((d'a)'c)'
- 1744 : 0x01ad tt=0000000110101101 lev=4 vol=7 (((b'a')'d)'(ca')')((b'a)c')'
- 1745 : 0x01ad tt=0000000110101101 lev=4 vol=7 (((b'a')'d)'(ca')')((c'a)b')'
- 1747 : 0x01ad tt=0000000110101101 lev=4 vol=7 (((b'a')'d)'(ca')')((c'b')a)'
- 1759 : 0x01ad tt=0000000110101101 lev=4 vol=7 (((b'a')'d)'((b'a)c')')(ca')'
-
-Class 68. Func 56. Functions = 1. Volume = 4. 0000000110101110
- 708 : 0x01ae tt=0000000110101110 lev=3 vol=5 ((b'a')+d)'(ca')'
-
-Class 69. Func 57. Functions = 1. Volume = 4. 0000000110101111
- 679 : 0x01af tt=0000000110101111 lev=3 vol=4 ((b'a')'d)'(ca')'
-
-Class 73. Func 58. Functions = 8. Volume = 29. 0000000110111111
- 1246 : 0x01bf tt=0000000110111111 lev=3 vol=6 ((d'b')'(ca'))'((b'a')'d)'
- 1415 : 0x01bf tt=0000000110111111 lev=3 vol=6 ((d'c')'(ba'))'((c'a')'d)'
- 1652 : 0x01bf tt=0000000110111111 lev=4 vol=6 (((ba')'d')'c)'((b'a')'d)'
- 1661 : 0x01bf tt=0000000110111111 lev=4 vol=6 (((ba')'d')'(c'a')')'(db)'
- 1662 : 0x01bf tt=0000000110111111 lev=4 vol=6 (((ba')'d')'(c'a')')'((ba')d)'
- 1681 : 0x01bf tt=0000000110111111 lev=4 vol=6 (((b'a')c')'d)'((ba')c)'
- 1686 : 0x01bf tt=0000000110111111 lev=4 vol=6 (((b'a')c')'d)'((ca')b)'
- 1688 : 0x01bf tt=0000000110111111 lev=4 vol=6 (((b'a')c')'d)'((cb)a')'
-
-Class 75. Func 59. Functions = 7. Volume = 25. 0000000111101001
- 1495 : 0x01e9 tt=0000000111101001 lev=4 vol=9 (((ba)'c)+(b+a))'((b'a')'d)'
- 1496 : 0x01e9 tt=0000000111101001 lev=4 vol=9 (((ba)'c)+(b+a))'((c'a')'d)'
- 1497 : 0x01e9 tt=0000000111101001 lev=4 vol=9 (((ba)'c)+(b+a))'((c'b')'d)'
- 1529 : 0x01e9 tt=0000000111101001 lev=4 vol=8 (((ba)'c')'d')+((dc)'(b'a'))
- 1539 : 0x01e9 tt=0000000111101001 lev=4 vol=7 (((ba)'c')+(b'a'))'((b'a')'d)'
- 1735 : 0x01e9 tt=0000000111101001 lev=4 vol=7 (((b'a')+c)'(ba)')'((b'a')'d)'
- 1758 : 0x01e9 tt=0000000111101001 lev=4 vol=7 (((b'a')'d)'((ba)'c')')+(b'a')
-
-Class 76. Func 60. Functions = 17. Volume = 52. 0000000111101010
- 763 : 0x01ea tt=0000000111101010 lev=3 vol=8 ((ca')+(ba'))'((b'a')+d)'
- 783 : 0x01ea tt=0000000111101010 lev=3 vol=7 ((c'a')+d)'((b'a')+d)'
- 789 : 0x01ea tt=0000000111101010 lev=3 vol=7 ((c'a')+(b'a'))'((b'a')+d)'
- 791 : 0x01ea tt=0000000111101010 lev=3 vol=7 ((c'a')+(b'a'))'((c'a')+d)'
- 955 : 0x01ea tt=0000000111101010 lev=3 vol=7 ((c+b)a')'((b'a')+d)'
- 957 : 0x01ea tt=0000000111101010 lev=3 vol=7 ((c+b)a')'((c'a')+d)'
- 1138 : 0x01ea tt=0000000111101010 lev=3 vol=7 ((d+a)'(cb)')'((c'b')'d)'
- 1258 : 0x01ea tt=0000000111101010 lev=3 vol=7 ((d+b)'a')'((c'a')+d)'
- 1447 : 0x01ea tt=0000000111101010 lev=3 vol=7 ((d+c)'a')'((b'a')+d)'
- 1689 : 0x01ea tt=0000000111101010 lev=4 vol=7 (((b'a')c')'d)'((d'a')(cb)')'
- 1760 : 0x01ea tt=0000000111101010 lev=4 vol=7 (((b'a')'d)'((b'a')c)')((c'a')d')'
- 1761 : 0x01ea tt=0000000111101010 lev=4 vol=7 (((b'a')'d)'((b'a')c)')((d'a')c')'
- 1762 : 0x01ea tt=0000000111101010 lev=4 vol=7 (((b'a')'d)'((b'a')c)')((d'c')a')'
- 1779 : 0x01ea tt=0000000111101010 lev=4 vol=7 (((b'a')'d')'(c'a')')'((db')'(c'a'))'
- 1781 : 0x01ea tt=0000000111101010 lev=4 vol=7 (((b'a')'d')'((b'a')c')')'((c'a')d')'
- 1782 : 0x01ea tt=0000000111101010 lev=4 vol=7 (((b'a')'d')'((b'a')c')')'((d'a')c')'
- 1783 : 0x01ea tt=0000000111101010 lev=4 vol=7 (((b'a')'d')'((b'a')c')')'((d'c')a')'
-
-Class 77. Func 61. Functions = 8. Volume = 22. 0000000111101011
- 762 : 0x01eb tt=0000000111101011 lev=3 vol=7 ((ca')+(ba'))'((b'a')'d)'
- 780 : 0x01eb tt=0000000111101011 lev=3 vol=7 ((c'a')'d)'((ca')+(ba'))'
- 788 : 0x01eb tt=0000000111101011 lev=3 vol=6 ((c'a')+(b'a'))'((b'a')'d)'
- 790 : 0x01eb tt=0000000111101011 lev=3 vol=6 ((c'a')+(b'a'))'((c'a')'d)'
- 954 : 0x01eb tt=0000000111101011 lev=3 vol=6 ((c+b)a')'((b'a')'d)'
- 956 : 0x01eb tt=0000000111101011 lev=3 vol=6 ((c+b)a')'((c'a')'d)'
- 1751 : 0x01eb tt=0000000111101011 lev=4 vol=6 (((b'a')'d)'(c'a')')+(b'a')
- 1778 : 0x01eb tt=0000000111101011 lev=4 vol=6 (((b'a')'d')'(c'a')')'((c'a')b)'
-
-Class 78. Func 62. Functions = 4. Volume = 14. 0000000111101110
- 709 : 0x01ee tt=0000000111101110 lev=3 vol=5 ((b'a')+d)'(dc)'
- 712 : 0x01ee tt=0000000111101110 lev=3 vol=5 ((b'a')+d)'((b'a')c)'
- 1377 : 0x01ee tt=0000000111101110 lev=3 vol=5 ((dc')'(b'a'))'((b'a')'d)'
- 1683 : 0x01ee tt=0000000111101110 lev=4 vol=5 (((b'a')c')'d)'((b'a')d')'
-
-Class 79. Func 63. Functions = 1. Volume = 4. 0000000111101111
- 691 : 0x01ef tt=0000000111101111 lev=3 vol=4 ((b'a')'d)'((b'a')c)'
-
-Class 80. Func 64. Functions = 32. Volume = 70. 0000000111111110
- 662 : 0x01fe tt=0000000111111110 lev=3 vol=6 ((b'a')'c')+(d+c)
- 772 : 0x01fe tt=0000000111111110 lev=3 vol=6 ((c'a')'b')+(d+b)
- 886 : 0x01fe tt=0000000111111110 lev=3 vol=6 ((c'b')'a')+(d+a)
- 1023 : 0x01fe tt=0000000111111110 lev=3 vol=6 ((da)'d')+((b'a')c')
- 1025 : 0x01fe tt=0000000111111110 lev=3 vol=6 ((da)'d')+((c'a')b')
- 1026 : 0x01fe tt=0000000111111110 lev=3 vol=6 ((da)'d')+((c'b')a')
- 1095 : 0x01fe tt=0000000111111110 lev=3 vol=6 ((da')'d')+((b'a')c')
- 1097 : 0x01fe tt=0000000111111110 lev=3 vol=6 ((da')'d')+((c'a')b')
- 1098 : 0x01fe tt=0000000111111110 lev=3 vol=6 ((da')'d')+((c'b')a')
- 1141 : 0x01fe tt=0000000111111110 lev=3 vol=6 ((d+a)'(c'b'))'((c'b')'d)'
- 1162 : 0x01fe tt=0000000111111110 lev=3 vol=6 ((db)'d')+((b'a')c')
- 1164 : 0x01fe tt=0000000111111110 lev=3 vol=6 ((db)'d')+((c'a')b')
- 1165 : 0x01fe tt=0000000111111110 lev=3 vol=6 ((db)'d')+((c'b')a')
- 1214 : 0x01fe tt=0000000111111110 lev=3 vol=6 ((db')'d')+((b'a')c')
- 1216 : 0x01fe tt=0000000111111110 lev=3 vol=6 ((db')'d')+((c'a')b')
- 1217 : 0x01fe tt=0000000111111110 lev=3 vol=6 ((db')'d')+((c'b')a')
- 1271 : 0x01fe tt=0000000111111110 lev=3 vol=6 ((d+b)'(c'a'))'((c'a')'d)'
- 1295 : 0x01fe tt=0000000111111110 lev=3 vol=6 ((dc)'d')+((b'a')c')
- 1297 : 0x01fe tt=0000000111111110 lev=3 vol=6 ((dc)'d')+((c'a')b')
- 1298 : 0x01fe tt=0000000111111110 lev=3 vol=6 ((dc)'d')+((c'b')a')
- 1370 : 0x01fe tt=0000000111111110 lev=3 vol=6 ((dc')'d')+((b'a')c')
- 1372 : 0x01fe tt=0000000111111110 lev=3 vol=6 ((dc')'d')+((c'a')b')
- 1373 : 0x01fe tt=0000000111111110 lev=3 vol=6 ((dc')'d')+((c'b')a')
- 1456 : 0x01fe tt=0000000111111110 lev=3 vol=6 ((d+c)'(b'a'))'((b'a')'d)'
- 1690 : 0x01fe tt=0000000111111110 lev=4 vol=6 (((b'a')c')'d)'((d'c')(b'a'))'
- 1696 : 0x01fe tt=0000000111111110 lev=4 vol=6 (((b'a')c')+d)'(da)'
- 1697 : 0x01fe tt=0000000111111110 lev=4 vol=6 (((b'a')c')+d)'(db)'
- 1698 : 0x01fe tt=0000000111111110 lev=4 vol=6 (((b'a')c')+d)'(dc)'
- 1700 : 0x01fe tt=0000000111111110 lev=4 vol=6 (((b'a')c')+d)'((b'a')'d)'
- 1712 : 0x01fe tt=0000000111111110 lev=4 vol=6 (((b'a')'c')+c)+d
- 1717 : 0x01fe tt=0000000111111110 lev=4 vol=6 (((b'a')'c')+d)+c
- 1784 : 0x01fe tt=0000000111111110 lev=4 vol=6 (((b'a')+d)c')'(dc)'
-
-Class 81. Func 65. Functions = 7. Volume = 21. 0000001100111100
- 826 : 0x033c tt=0000001100111100 lev=3 vol=6 ((cb)'d)+(c+b)
- 828 : 0x033c tt=0000001100111100 lev=3 vol=5 ((cb)'d')+(c'b')
- 919 : 0x033c tt=0000001100111100 lev=3 vol=5 ((c'b')+d)'(cb)'
- 1160 : 0x033c tt=0000001100111100 lev=3 vol=5 ((db)'c')+(d'b')
- 1237 : 0x033c tt=0000001100111100 lev=3 vol=5 ((d'b')+c)'(db)'
- 1291 : 0x033c tt=0000001100111100 lev=3 vol=5 ((dc)'b')+(d'c')
- 1405 : 0x033c tt=0000001100111100 lev=3 vol=5 ((d'c')+b)'(dc)'
-
-Class 82. Func 66. Functions = 8. Volume = 38. 0000001100111101
- 1085 : 0x033d tt=0000001100111101 lev=3 vol=8 ((d'a)'(c'b'))+((c+b)d')
- 1120 : 0x033d tt=0000001100111101 lev=3 vol=7 ((d'a')'(c'b'))+((cb)'d')
- 1249 : 0x033d tt=0000001100111101 lev=3 vol=7 ((d'b')(c'a')')+((db)'c')
- 1421 : 0x033d tt=0000001100111101 lev=3 vol=7 ((d'c')(b'a')')+((dc)'b')
- 1605 : 0x033d tt=0000001100111101 lev=4 vol=7 (((b'a)'c')'(d+c)')'((d+c)b)'
- 1627 : 0x033d tt=0000001100111101 lev=4 vol=7 (((b'a)'d')'(d+c)')'((d+c)b)'
- 1715 : 0x033d tt=0000001100111101 lev=4 vol=7 (((b'a')'c')d')+((dc)'b')
- 1775 : 0x033d tt=0000001100111101 lev=4 vol=7 (((b'a')'d')c')+((dc)'b')
-
-Class 83. Func 67. Functions = 4. Volume = 15. 0000001100111111
- 893 : 0x033f tt=0000001100111111 lev=3 vol=6 ((c'b')d)+((cb)'d')
- 896 : 0x033f tt=0000001100111111 lev=3 vol=4 ((c'b')'d)'(cb)'
- 1232 : 0x033f tt=0000001100111111 lev=3 vol=4 ((d'b')'c)'(db)'
- 1401 : 0x033f tt=0000001100111111 lev=3 vol=4 ((d'c')'b)'(dc)'
-
-Class 84. Func 68. Functions = 1. Volume = 3. 0000001101010110
- 292 : 0x0356 tt=0000001101010110 lev=2 vol=4 (d'a')+(c'b')
-
-Class 85. Func 69. Functions = 3. Volume = 12. 0000001101010111
- 901 : 0x0357 tt=0000001101010111 lev=3 vol=6 ((c'b')'d)'((ca)'(ba)')
- 912 : 0x0357 tt=0000001101010111 lev=3 vol=4 ((c'b')'d)'((c'b')'a)'
- 1109 : 0x0357 tt=0000001101010111 lev=3 vol=4 ((d'a')'c)'((d'a')'b)'
-
-Class 86. Func 70. Functions = 5. Volume = 15. 0000001101011000
- 933 : 0x0358 tt=0000001101011000 lev=3 vol=7 ((c'b')+d)'((c+a)'d')'
- 950 : 0x0358 tt=0000001101011000 lev=3 vol=7 ((c'b')'(c+a)')'((c'b')+d)'
- 1112 : 0x0358 tt=0000001101011000 lev=3 vol=7 ((d'a')+c)'((c'b')+d)'
- 1265 : 0x0358 tt=0000001101011000 lev=3 vol=7 ((d+b)'c')'((d'a')+c)'
- 1284 : 0x0358 tt=0000001101011000 lev=3 vol=7 ((d+b)'(d'a')')'((d'a')+c)'
-
-Class 87. Func 71. Functions = 5. Volume = 17. 0000001101011001
- 805 : 0x0359 tt=0000001101011001 lev=3 vol=6 ((c+a)d')+(c'b')
- 1083 : 0x0359 tt=0000001101011001 lev=3 vol=6 ((d'a)+(c'b))'(dc)'
- 1261 : 0x0359 tt=0000001101011001 lev=3 vol=6 ((d+b)c')+(d'a')
- 1320 : 0x0359 tt=0000001101011001 lev=3 vol=6 ((dc)'(c'b)')+(d'a)
- 1334 : 0x0359 tt=0000001101011001 lev=3 vol=6 ((dc)'(d'a)')+(c'b)
-
-Class 88. Func 72. Functions = 4. Volume = 14. 0000001101011010
- 892 : 0x035a tt=0000001101011010 lev=3 vol=7 ((c'b')d)+((c+a)d')
- 906 : 0x035a tt=0000001101011010 lev=3 vol=6 ((c'b')'d)'((c+a)'d')'
- 1111 : 0x035a tt=0000001101011010 lev=3 vol=5 ((d'a')+c)'(db)'
- 1159 : 0x035a tt=0000001101011010 lev=3 vol=5 ((db)'c')+(d'a')
-
-Class 89. Func 73. Functions = 3. Volume = 14. 0000001101011011
- 908 : 0x035b tt=0000001101011011 lev=3 vol=7 ((c'b')'d)'((c+a)'(b'a')')'
- 949 : 0x035b tt=0000001101011011 lev=3 vol=6 ((c'b')'(c+a)')'((c'b')'d)'
- 1108 : 0x035b tt=0000001101011011 lev=3 vol=6 ((d'a')'c)'((d'a)'(c'b))'
-
-Class 91. Func 74. Functions = 3. Volume = 11. 0000001101011111
- 891 : 0x035f tt=0000001101011111 lev=3 vol=6 ((c'b')d)+((ca)'d')
- 895 : 0x035f tt=0000001101011111 lev=3 vol=4 ((c'b')'d)'(ca)'
- 1104 : 0x035f tt=0000001101011111 lev=3 vol=4 ((d'a')'c)'(db)'
-
-Class 92. Func 75. Functions = 3. Volume = 15. 0000001101101000
- 1094 : 0x0368 tt=0000001101101000 lev=3 vol=9 ((d'a)+(c+b))'((c'b')+d)'
- 1117 : 0x0368 tt=0000001101101000 lev=3 vol=8 ((d'a')+(cb))'((c'b')+d)'
- 1446 : 0x0368 tt=0000001101101000 lev=3 vol=8 ((d'c')'(d'b')')+((d'a')'(c'b')')
-
-Class 93. Func 76. Functions = 7. Volume = 24. 0000001101101001
- 1090 : 0x0369 tt=0000001101101001 lev=3 vol=8 ((d'a)+(c'b'))+((cb)d')
- 1092 : 0x0369 tt=0000001101101001 lev=3 vol=7 ((d'a)+(c+b))'(db)'
- 1093 : 0x0369 tt=0000001101101001 lev=3 vol=7 ((d'a)+(c+b))'(dc)'
- 1161 : 0x0369 tt=0000001101101001 lev=3 vol=7 ((db)'c')+((b+a)d')
- 1179 : 0x0369 tt=0000001101101001 lev=3 vol=7 ((db)'(c+b)')+(d'a)
- 1293 : 0x0369 tt=0000001101101001 lev=3 vol=7 ((dc)'b')+((c+a)d')
- 1327 : 0x0369 tt=0000001101101001 lev=3 vol=7 ((dc)'(c+b)')+(d'a)
-
-Class 96. Func 77. Functions = 4. Volume = 17. 0000001101101100
- 924 : 0x036c tt=0000001101101100 lev=3 vol=7 ((c'b')+d)'((b+a)'c)'
- 1244 : 0x036c tt=0000001101101100 lev=3 vol=7 ((d'b')+(ca))'((c'b')'d)'
- 1269 : 0x036c tt=0000001101101100 lev=3 vol=7 ((d+b)+(ca))(dc)'
- 1292 : 0x036c tt=0000001101101100 lev=3 vol=6 ((dc)'b')+((ca)'d')
-
-Class 98. Func 78. Functions = 10. Volume = 44. 0000001101101110
- 1278 : 0x036e tt=0000001101101110 lev=3 vol=9 ((d+b)(cb')')+((d'a)(c'b)')
- 1338 : 0x036e tt=0000001101101110 lev=3 vol=9 ((dc)+(d'b))+((d'a')'(c'b)')
- 1342 : 0x036e tt=0000001101101110 lev=3 vol=9 ((dc)'(d+b))+((d'a)(c'b)')
- 1391 : 0x036e tt=0000001101101110 lev=3 vol=8 ((dc')'(d'b')')+((d'a')'(c'b)')
- 1570 : 0x036e tt=0000001101101110 lev=4 vol=8 (((ba)'d')'c)'((d+b)'(b'a)')'
- 1571 : 0x036e tt=0000001101101110 lev=4 vol=8 (((ba)'d')'c)'((d+b)'(d'a)')'
- 1617 : 0x036e tt=0000001101101110 lev=4 vol=8 (((b'a)'d')(ca)')+((dc)'b')
- 1632 : 0x036e tt=0000001101101110 lev=4 vol=8 (((ba')'c)(d+b))'((d+b)'(b'a)')'
- 1633 : 0x036e tt=0000001101101110 lev=4 vol=8 (((ba')'c)(d+b))'((d+b)'(d'a)')'
- 1769 : 0x036e tt=0000001101101110 lev=4 vol=8 (((b'a')d')'((ba)c)')((c'b')'d)'
-
-Class 101. Func 79. Functions = 1. Volume = 6. 0000001101111101
- 1091 : 0x037d tt=0000001101111101 lev=3 vol=7 ((d'a)(c+b)')'((c'b')'d)'
-
-Class 103. Func 80. Functions = 18. Volume = 51. 0000001111000000
- 392 : 0x03c0 tt=0000001111000000 lev=2 vol=5 (d+b)(c+b)'
- 488 : 0x03c0 tt=0000001111000000 lev=2 vol=5 (d+c)(c+b)'
- 492 : 0x03c0 tt=0000001111000000 lev=2 vol=5 (d+c)(d+b)
- 909 : 0x03c0 tt=0000001111000000 lev=3 vol=5 ((c'b')'d)'((cb)'d')'
- 1172 : 0x03c0 tt=0000001111000000 lev=3 vol=5 ((db)'(cb')')(d'c')'
- 1202 : 0x03c0 tt=0000001111000000 lev=3 vol=5 ((d'b)'(c'b')')'(d'c')'
- 1213 : 0x03c0 tt=0000001111000000 lev=3 vol=5 ((db')'c')'((d'b)'c)'
- 1221 : 0x03c0 tt=0000001111000000 lev=3 vol=5 ((db')'(cb)')'(dc)'
- 1253 : 0x03c0 tt=0000001111000000 lev=3 vol=5 ((d'b')'(c'b)')(dc)'
- 1321 : 0x03c0 tt=0000001111000000 lev=3 vol=5 ((dc)'(c'b)')(d'b')'
- 1339 : 0x03c0 tt=0000001111000000 lev=3 vol=5 ((dc)'(d'b')')(c'b)'
- 1358 : 0x03c0 tt=0000001111000000 lev=3 vol=5 ((d'c)'(c'b')')'(d'b')'
- 1364 : 0x03c0 tt=0000001111000000 lev=3 vol=5 ((d'c)'(db')')'(cb')'
- 1369 : 0x03c0 tt=0000001111000000 lev=3 vol=5 ((dc')'b')'((d'c)'b)'
- 1383 : 0x03c0 tt=0000001111000000 lev=3 vol=5 ((dc')'(cb)')'(db)'
- 1388 : 0x03c0 tt=0000001111000000 lev=3 vol=5 ((dc')'(d'b)')'(c'b)'
- 1438 : 0x03c0 tt=0000001111000000 lev=3 vol=5 ((d'c')'(cb')')(db)'
- 1443 : 0x03c0 tt=0000001111000000 lev=3 vol=5 ((d'c')'(db)')(cb')'
-
-Class 104. Func 81. Functions = 42. Volume = 109. 0000001111000001
- 1084 : 0x03c1 tt=0000001111000001 lev=3 vol=7 ((d'a)'(c'b'))+((cb)d')
- 1181 : 0x03c1 tt=0000001111000001 lev=3 vol=7 ((db)'(c+b)')((b'a)d')'
- 1182 : 0x03c1 tt=0000001111000001 lev=3 vol=7 ((db)'(c+b)')((c'a)d')'
- 1183 : 0x03c1 tt=0000001111000001 lev=3 vol=7 ((db)'(c+b)')((d'a)b')'
- 1184 : 0x03c1 tt=0000001111000001 lev=3 vol=7 ((db)'(c+b)')((d'a)c')'
- 1191 : 0x03c1 tt=0000001111000001 lev=3 vol=7 ((d'b)c)+((d'a)'(c'b'))
- 1230 : 0x03c1 tt=0000001111000001 lev=3 vol=7 ((d'b')a)'((db)'(c+b)')
- 1267 : 0x03c1 tt=0000001111000001 lev=3 vol=7 ((d+b)'(b'a')')'(c+b)'
- 1272 : 0x03c1 tt=0000001111000001 lev=3 vol=7 ((d+b)'(c'a')')'(c+b)'
- 1283 : 0x03c1 tt=0000001111000001 lev=3 vol=7 ((d+b)'(d'a')')'(c+b)'
- 1326 : 0x03c1 tt=0000001111000001 lev=3 vol=7 ((dc)'(c'b)')((d'b')(c'a')')'
- 1329 : 0x03c1 tt=0000001111000001 lev=3 vol=7 ((dc)'(c+b)')((b'a)d')'
- 1330 : 0x03c1 tt=0000001111000001 lev=3 vol=7 ((dc)'(c+b)')((c'a)d')'
- 1331 : 0x03c1 tt=0000001111000001 lev=3 vol=7 ((dc)'(c+b)')((d'a)b')'
- 1332 : 0x03c1 tt=0000001111000001 lev=3 vol=7 ((dc)'(c+b)')((d'a)c')'
- 1333 : 0x03c1 tt=0000001111000001 lev=3 vol=7 ((dc)'(c+b)')((d'b')a)'
- 1345 : 0x03c1 tt=0000001111000001 lev=3 vol=7 ((d'c)b)+((d'a)'(c'b'))
- 1361 : 0x03c1 tt=0000001111000001 lev=3 vol=7 ((d'c)'(c'b')')'((d'b')(c'a')')'
- 1393 : 0x03c1 tt=0000001111000001 lev=3 vol=7 ((d'c')a)'((db)'(c+b)')
- 1394 : 0x03c1 tt=0000001111000001 lev=3 vol=7 ((d'c')a)'((dc)'(c+b)')
- 1419 : 0x03c1 tt=0000001111000001 lev=3 vol=7 ((d'c')(b'a')')'((db)'(cb')')
- 1420 : 0x03c1 tt=0000001111000001 lev=3 vol=7 ((d'c')(b'a')')'((d'b)'(c'b')')'
- 1457 : 0x03c1 tt=0000001111000001 lev=3 vol=7 ((d+c)'(b'a')')'(c+b)'
- 1465 : 0x03c1 tt=0000001111000001 lev=3 vol=7 ((d+c)'(c'a')')'(c+b)'
- 1473 : 0x03c1 tt=0000001111000001 lev=3 vol=7 ((d+c)'(d'a')')'(c+b)'
- 1596 : 0x03c1 tt=0000001111000001 lev=4 vol=7 (((b'a)'c')'d')+((dc)'b')
- 1606 : 0x03c1 tt=0000001111000001 lev=4 vol=7 (((b'a)d')'c')+((dc)'b)
- 1607 : 0x03c1 tt=0000001111000001 lev=4 vol=7 (((b'a)d')'(c'b)')((d'b)'c)'
- 1608 : 0x03c1 tt=0000001111000001 lev=4 vol=7 (((b'a)d')'(cb')')((d'c)'b)'
- 1610 : 0x03c1 tt=0000001111000001 lev=4 vol=7 (((b'a)d')'(c+b)')(db)'
- 1611 : 0x03c1 tt=0000001111000001 lev=4 vol=7 (((b'a)d')'(c+b)')(dc)'
- 1612 : 0x03c1 tt=0000001111000001 lev=4 vol=7 (((b'a)d')'(db)')(c+b)'
- 1613 : 0x03c1 tt=0000001111000001 lev=4 vol=7 (((b'a)d')'(dc)')(c+b)'
- 1624 : 0x03c1 tt=0000001111000001 lev=4 vol=7 (((b'a)'d')'(db')')'(c+b)'
- 1625 : 0x03c1 tt=0000001111000001 lev=4 vol=7 (((b'a)'d')'(dc')')'(c+b)'
- 1713 : 0x03c1 tt=0000001111000001 lev=4 vol=7 (((b'a')'c')d')'((db)'(cb')')
- 1714 : 0x03c1 tt=0000001111000001 lev=4 vol=7 (((b'a')'c')d')'((d'b)'(c'b')')'
- 1722 : 0x03c1 tt=0000001111000001 lev=4 vol=7 (((b'a')'c')(db')')'((d'b)'c)'
- 1772 : 0x03c1 tt=0000001111000001 lev=4 vol=7 (((b'a')'d')+b)'(c+b)'
- 1773 : 0x03c1 tt=0000001111000001 lev=4 vol=7 (((b'a')'d')c')'((db)'(cb')')
- 1774 : 0x03c1 tt=0000001111000001 lev=4 vol=7 (((b'a')'d')c')'((d'b)'(c'b')')'
- 1776 : 0x03c1 tt=0000001111000001 lev=4 vol=7 (((b'a')'d')+c)'(c+b)'
-
-Class 105. Func 82. Functions = 4. Volume = 13. 0000001111000011
- 326 : 0x03c3 tt=0000001111000011 lev=2 vol=4 (db)'(c+b)'
- 412 : 0x03c3 tt=0000001111000011 lev=2 vol=4 (dc)'(c+b)'
- 1192 : 0x03c3 tt=0000001111000011 lev=3 vol=4 ((d'b)'c)'(c'b)'
- 1346 : 0x03c3 tt=0000001111000011 lev=3 vol=4 ((d'c)'b)'(cb')'
-
-Class 108. Func 83. Functions = 15. Volume = 44. 0000001111000111
- 981 : 0x03c7 tt=0000001111000111 lev=3 vol=6 ((c+b)(ba')')'(db)'
- 1000 : 0x03c7 tt=0000001111000111 lev=3 vol=6 ((c+b)(c'a')')'(db)'
- 1173 : 0x03c7 tt=0000001111000111 lev=3 vol=6 ((db)'(cb')')((ba)c')'
- 1174 : 0x03c7 tt=0000001111000111 lev=3 vol=6 ((db)'(cb')')((c'a)b)'
- 1175 : 0x03c7 tt=0000001111000111 lev=3 vol=6 ((db)'(cb')')((c'b)a)'
- 1195 : 0x03c7 tt=0000001111000111 lev=3 vol=6 ((d'b)'c)'((d'a')'(c'b))'
- 1197 : 0x03c7 tt=0000001111000111 lev=3 vol=6 ((d'b)(c'a)')+(c'b')
- 1203 : 0x03c7 tt=0000001111000111 lev=3 vol=6 ((d'b)'(c'b')')'((ba)c')'
- 1204 : 0x03c7 tt=0000001111000111 lev=3 vol=6 ((d'b)'(c'b')')'((c'a)b)'
- 1205 : 0x03c7 tt=0000001111000111 lev=3 vol=6 ((d'b)'(c'b')')'((c'b)a)'
- 1208 : 0x03c7 tt=0000001111000111 lev=3 vol=6 ((d'b)'(c'b')')'((d'b)(c'a))'
- 1517 : 0x03c7 tt=0000001111000111 lev=4 vol=6 (((ba)c')'(cb')')(db)'
- 1518 : 0x03c7 tt=0000001111000111 lev=4 vol=6 (((ba)c')'(db)')(cb')'
- 1540 : 0x03c7 tt=0000001111000111 lev=4 vol=6 (((ba)'c')'(cb)')'(db)'
- 1637 : 0x03c7 tt=0000001111000111 lev=4 vol=6 (((ba')'c')+b)(db)'
-
-Class 109. Func 84. Functions = 1. Volume = 3. 0000001111001111
- 325 : 0x03cf tt=0000001111001111 lev=2 vol=3 (db)'(cb')'
-
-Class 110. Func 85. Functions = 4. Volume = 17. 0000001111010100
- 927 : 0x03d4 tt=0000001111010100 lev=3 vol=8 ((c'b')+d)'((ca)+(ba))'
- 929 : 0x03d4 tt=0000001111010100 lev=3 vol=8 ((c'b')+d)'((c'a)+(b'a))'
- 953 : 0x03d4 tt=0000001111010100 lev=3 vol=7 ((c+b)a)'((c'b')+d)'
- 1082 : 0x03d4 tt=0000001111010100 lev=3 vol=7 ((d'a)(cb)')'((c'b')+d)'
-
-Class 111. Func 86. Functions = 1. Volume = 6. 0000001111010101
- 1081 : 0x03d5 tt=0000001111010101 lev=3 vol=6 ((d'a)(cb)')'((c'b')'d)'
-
-Class 113. Func 87. Functions = 5. Volume = 19. 0000001111010111
- 902 : 0x03d7 tt=0000001111010111 lev=3 vol=7 ((c'b')'d)'((ca)+(ba))'
- 904 : 0x03d7 tt=0000001111010111 lev=3 vol=7 ((c'b')'d)'((c'a)+(b'a))'
- 952 : 0x03d7 tt=0000001111010111 lev=3 vol=6 ((c+b)a)'((c'b')'d)'
- 1123 : 0x03d7 tt=0000001111010111 lev=3 vol=6 ((d'a')'(c+b))'(db)'
- 1124 : 0x03d7 tt=0000001111010111 lev=3 vol=6 ((d'a')'(c+b))'(dc)'
-
-Class 114. Func 88. Functions = 20. Volume = 58. 0000001111011000
- 935 : 0x03d8 tt=0000001111011000 lev=3 vol=9 ((c'b')+d)'((c+a)'(b+a))'
- 988 : 0x03d8 tt=0000001111011000 lev=3 vol=9 ((c+b)(b+a))'((c'b')+d)'
- 1005 : 0x03d8 tt=0000001111011000 lev=3 vol=9 ((c+b)(c+a)')'((c'b')+d)'
- 1452 : 0x03d8 tt=0000001111011000 lev=3 vol=9 ((d+c)'(ba)')'((d+b)'(b'a')')'
- 1453 : 0x03d8 tt=0000001111011000 lev=3 vol=9 ((d+c)'(ba)')'((d+b)'(ca')')'
- 1454 : 0x03d8 tt=0000001111011000 lev=3 vol=9 ((d+c)'(ba)')'((d+b)'(d'a')')'
- 1461 : 0x03d8 tt=0000001111011000 lev=3 vol=9 ((d+c)'(c'a)')'((d+b)'(b'a')')'
- 1462 : 0x03d8 tt=0000001111011000 lev=3 vol=9 ((d+c)'(c'a)')'((d+b)'(ca')')'
- 1463 : 0x03d8 tt=0000001111011000 lev=3 vol=9 ((d+c)'(c'a)')'((d+b)'(d'a')')'
- 1469 : 0x03d8 tt=0000001111011000 lev=3 vol=9 ((d+c)'(d'a)')'((d+b)'(b'a')')'
- 1470 : 0x03d8 tt=0000001111011000 lev=3 vol=9 ((d+c)'(d'a)')'((d+b)'(ca')')'
- 1471 : 0x03d8 tt=0000001111011000 lev=3 vol=9 ((d+c)'(d'a)')'((d+b)'(d'a')')'
- 1502 : 0x03d8 tt=0000001111011000 lev=4 vol=9 (((ba)'c)+(d'a'))'((c'b')+d)'
- 1503 : 0x03d8 tt=0000001111011000 lev=4 vol=9 (((ba)'c)+(d'a'))'((d+b)'(d'a')')'
- 1532 : 0x03d8 tt=0000001111011000 lev=4 vol=9 (((ba)'c')+d)'((d+b)'(b'a')')'
- 1533 : 0x03d8 tt=0000001111011000 lev=4 vol=9 (((ba)'c')+d)'((d+b)'(ca')')'
- 1534 : 0x03d8 tt=0000001111011000 lev=4 vol=9 (((ba)'c')+d)'((d+b)'(d'a')')'
- 1545 : 0x03d8 tt=0000001111011000 lev=4 vol=9 (((ba)+c)'(db)')+((ca)'d')
- 1567 : 0x03d8 tt=0000001111011000 lev=4 vol=9 (((ba)d')'(d'c')')+((d'a')'(c'b')')
- 1578 : 0x03d8 tt=0000001111011000 lev=4 vol=7 (((ba)'d')(ca')')'((c'b')'d)'
-
-Class 115. Func 89. Functions = 10. Volume = 48. 0000001111011001
- 1279 : 0x03d9 tt=0000001111011001 lev=3 vol=9 ((d+b)(cb')')+((d'a')(cb)')
- 1294 : 0x03d9 tt=0000001111011001 lev=3 vol=8 ((dc)+b)+((d'a)'(cb)')
- 1322 : 0x03d9 tt=0000001111011001 lev=3 vol=8 ((dc)'(c'b)')+((d'a)(cb)')
- 1506 : 0x03d9 tt=0000001111011001 lev=4 vol=8 (((ba)'c)'(d+b))+(d'a')
- 1614 : 0x03d9 tt=0000001111011001 lev=4 vol=8 (((b'a)d')'(dc)')((d'a)'(c'b))'
- 1626 : 0x03d9 tt=0000001111011001 lev=4 vol=8 (((b'a)'d')'(dc')')'((d'a)'(c'b))'
- 1634 : 0x03d9 tt=0000001111011001 lev=4 vol=8 (((ba')c')'(dc)')((d+b)'a)'
- 1636 : 0x03d9 tt=0000001111011001 lev=4 vol=8 (((ba')c')'((b'a)d')')((c'b')'d)'
- 1643 : 0x03d9 tt=0000001111011001 lev=4 vol=8 (((ba')'c')'(d'c)')'((d+b)'a)'
- 1777 : 0x03d9 tt=0000001111011001 lev=4 vol=8 (((b'a')'d')(c'a')')+((dc)'b')
-
-Class 117. Func 90. Functions = 11. Volume = 35. 0000001111011100
- 921 : 0x03dc tt=0000001111011100 lev=3 vol=6 ((c'b')+d)'((b'a)c)'
- 923 : 0x03dc tt=0000001111011100 lev=3 vol=6 ((c'b')+d)'((b'a)d')'
- 926 : 0x03dc tt=0000001111011100 lev=3 vol=6 ((c'b')+d)'((ca)b')'
- 938 : 0x03dc tt=0000001111011100 lev=3 vol=6 ((c'b')+d)'((cb')a)'
- 1074 : 0x03dc tt=0000001111011100 lev=3 vol=6 ((d'a)b')'((c'b')+d)'
- 1229 : 0x03dc tt=0000001111011100 lev=3 vol=6 ((d'b')a)'((c'b')+d)'
- 1247 : 0x03dc tt=0000001111011100 lev=3 vol=6 ((d'b')(ca')')'((c'b')'d)'
- 1270 : 0x03dc tt=0000001111011100 lev=3 vol=6 ((d+b)'(ca')')'(dc)'
- 1582 : 0x03dc tt=0000001111011100 lev=4 vol=6 (((b'a)c)'d')+(c'b')
- 1609 : 0x03dc tt=0000001111011100 lev=4 vol=6 (((b'a)d')'(c'b')')+d
- 1623 : 0x03dc tt=0000001111011100 lev=4 vol=6 (((b'a)'d')'(c'b')')'((c'b')d')'
-
-Class 118. Func 91. Functions = 4. Volume = 14. 0000001111011101
- 890 : 0x03dd tt=0000001111011101 lev=3 vol=6 ((c'b')d)+((b'a)'d')
- 899 : 0x03dd tt=0000001111011101 lev=3 vol=5 ((c'b')'d)'((b'a)d')'
- 1073 : 0x03dd tt=0000001111011101 lev=3 vol=5 ((d'a)b')'((c'b')'d)'
- 1228 : 0x03dd tt=0000001111011101 lev=3 vol=5 ((d'b')a)'((c'b')'d)'
-
-Class 119. Func 92. Functions = 1. Volume = 4. 0000001111011110
- 593 : 0x03de tt=0000001111011110 lev=3 vol=5 ((b'a)'d')+(c'b')
-
-Class 120. Func 93. Functions = 7. Volume = 18. 0000001111111100
- 389 : 0x03fc tt=0000001111111100 lev=2 vol=5 (d+b)+(cb')
- 486 : 0x03fc tt=0000001111111100 lev=2 vol=5 (d+c)+(c'b)
- 849 : 0x03fc tt=0000001111111100 lev=3 vol=5 ((c'b)+c)+d
- 850 : 0x03fc tt=0000001111111100 lev=3 vol=5 ((c'b)+d)+c
- 862 : 0x03fc tt=0000001111111100 lev=3 vol=5 ((cb')+b)+d
- 864 : 0x03fc tt=0000001111111100 lev=3 vol=5 ((cb')+d)+b
- 915 : 0x03fc tt=0000001111111100 lev=3 vol=4 ((c'b')d')'((c'b')'d)'
-
-Class 121. Func 94. Functions = 1. Volume = 3. 0000011001100000
- 481 : 0x0660 tt=0000011001100000 lev=2 vol=5 (d+c)(b+a)
-
-Class 122. Func 95. Functions = 12. Volume = 35. 0000011001100001
- 1147 : 0x0661 tt=0000011001100001 lev=3 vol=11 ((d+a)+(c+b))'((c'a')'(b+a)')'
- 1148 : 0x0661 tt=0000011001100001 lev=3 vol=11 ((d+a)+(c+b))'((c'b')'(b+a)')'
- 1149 : 0x0661 tt=0000011001100001 lev=3 vol=11 ((d+a)+(c+b))'((d'a')'(b+a)')'
- 1242 : 0x0661 tt=0000011001100001 lev=3 vol=11 ((d'b')'(b+a)')'((d+a)+(c+b))'
- 1274 : 0x0661 tt=0000011001100001 lev=3 vol=11 ((d+b)+(c+a))'((c'a')'(b+a)')'
- 1275 : 0x0661 tt=0000011001100001 lev=3 vol=11 ((d+b)+(c+a))'((c'b')'(b+a)')'
- 1276 : 0x0661 tt=0000011001100001 lev=3 vol=11 ((d+b)+(c+a))'((d'a')'(b+a)')'
- 1277 : 0x0661 tt=0000011001100001 lev=3 vol=11 ((d+b)+(c+a))'((d'b')'(b+a)')'
- 1306 : 0x0661 tt=0000011001100001 lev=3 vol=10 ((dc)'(ba)')((d+a)+(c+b))'
- 1308 : 0x0661 tt=0000011001100001 lev=3 vol=10 ((dc)'(ba)')((d+b)+(c+a))'
- 1411 : 0x0661 tt=0000011001100001 lev=3 vol=9 ((d'c')(ba)')+((dc)'(b+a))
- 1432 : 0x0661 tt=0000011001100001 lev=3 vol=8 ((d'c')+(b'a'))'((dc)'(ba)')
-
-Class 125. Func 96. Functions = 1. Volume = 3. 0000011001100110
- 407 : 0x0666 tt=0000011001100110 lev=2 vol=4 (dc)'(b+a)
-
-Class 127. Func 97. Functions = 4. Volume = 15. 0000011001101001
- 1146 : 0x0669 tt=0000011001101001 lev=3 vol=8 ((d+a)+(c+b))'(dc)'
- 1273 : 0x0669 tt=0000011001101001 lev=3 vol=8 ((d+b)+(c+a))'(dc)'
- 1316 : 0x0669 tt=0000011001101001 lev=3 vol=7 ((dc)'(b+a))+(d'c')
- 1435 : 0x0669 tt=0000011001101001 lev=3 vol=7 ((d'c')+(b+a))(dc)'
-
-Class 129. Func 98. Functions = 6. Volume = 32. 0000011001101111
- 1178 : 0x066f tt=0000011001101111 lev=3 vol=10 ((db)'(cb')')+((d+a)(c+a)')
- 1224 : 0x066f tt=0000011001101111 lev=3 vol=10 ((db')'(cb)')+((d+a)'(c+a))
- 1281 : 0x066f tt=0000011001101111 lev=3 vol=10 ((d+b)'(c+b))+((da')'(ca)')
- 1282 : 0x066f tt=0000011001101111 lev=3 vol=10 ((d+b)(c+b)')+((da)'(ca')')
- 1433 : 0x066f tt=0000011001101111 lev=3 vol=8 ((d'c')(b+a)')+((dc)'(b+a))
- 1434 : 0x066f tt=0000011001101111 lev=3 vol=6 ((d'c')'(b+a)')'(dc)'
-
-Class 132. Func 99. Functions = 8. Volume = 27. 0000011001110110
- 766 : 0x0676 tt=0000011001110110 lev=3 vol=6 ((ca')'(b+a)')'(dc)'
- 871 : 0x0676 tt=0000011001110110 lev=3 vol=6 ((cb')'(b+a)')'(dc)'
- 1301 : 0x0676 tt=0000011001110110 lev=3 vol=6 ((dc)'(ba)')((b'a')c')'
- 1302 : 0x0676 tt=0000011001110110 lev=3 vol=6 ((dc)'(ba)')((c'a')b')'
- 1303 : 0x0676 tt=0000011001110110 lev=3 vol=6 ((dc)'(ba)')((c'b')a')'
- 1702 : 0x0676 tt=0000011001110110 lev=4 vol=6 (((b'a')c')'(ba)')(dc)'
- 1705 : 0x0676 tt=0000011001110110 lev=4 vol=6 (((b'a')c')'(dc)')(ba)'
- 1725 : 0x0676 tt=0000011001110110 lev=4 vol=6 (((b'a')'c')'(d'c)')'(ba)'
-
-Class 137. Func 100. Functions = 9. Volume = 39. 0000011001111110
- 1524 : 0x067e tt=0000011001111110 lev=4 vol=9 (((ba)'c')'d)'((c+a)'(b+a)')'
- 1525 : 0x067e tt=0000011001111110 lev=4 vol=9 (((ba)'c')'d)'((c+b)'(b+a)')'
- 1526 : 0x067e tt=0000011001111110 lev=4 vol=9 (((ba)'c')'d)'((c+b)'(c+a)')'
- 1542 : 0x067e tt=0000011001111110 lev=4 vol=9 (((ba)+c)d')+((b+a)c')
- 1561 : 0x067e tt=0000011001111110 lev=4 vol=9 (((ba)d')'(c'a')')+((d'c)'(c'b')')
- 1564 : 0x067e tt=0000011001111110 lev=4 vol=9 (((ba)d')'(c'b')')+((d'c)'(c'a')')
- 1565 : 0x067e tt=0000011001111110 lev=4 vol=9 (((ba)d')'(dc)')+((b+a)'c')
- 1706 : 0x067e tt=0000011001111110 lev=4 vol=8 (((b'a')c')'(dc)')((d'c')'(ba))'
- 1726 : 0x067e tt=0000011001111110 lev=4 vol=8 (((b'a')'c')'(d'c)')'((d'c')'(ba))'
-
-Class 138. Func 101. Functions = 8. Volume = 24. 0000011010010000
- 724 : 0x0690 tt=0000011010010000 lev=3 vol=7 ((b+a)+c)(d+c)
- 738 : 0x0690 tt=0000011010010000 lev=3 vol=7 ((b+a)+d)'(d+c)
- 740 : 0x0690 tt=0000011010010000 lev=3 vol=7 ((b+a)+d)'((b+a)+c)
- 797 : 0x0690 tt=0000011010010000 lev=3 vol=7 ((c+a)+b)(d+c)
- 961 : 0x0690 tt=0000011010010000 lev=3 vol=7 ((c+b)+a)(d+c)
- 1130 : 0x0690 tt=0000011010010000 lev=3 vol=7 ((d+a)+b)'(d+c)
- 1260 : 0x0690 tt=0000011010010000 lev=3 vol=7 ((d+b)+a)'(d+c)
- 1380 : 0x0690 tt=0000011010010000 lev=3 vol=7 ((dc')'(b+a))'((d'c)'(b+a)')'
-
-Class 141. Func 102. Functions = 5. Volume = 16. 0000011010010110
- 723 : 0x0696 tt=0000011010010110 lev=3 vol=6 ((b+a)+c)(dc)'
- 730 : 0x0696 tt=0000011010010110 lev=3 vol=6 ((b+a)'d)'((b+a)+c)
- 796 : 0x0696 tt=0000011010010110 lev=3 vol=6 ((c+a)+b)(dc)'
- 960 : 0x0696 tt=0000011010010110 lev=3 vol=6 ((c+b)+a)(dc)'
- 1355 : 0x0696 tt=0000011010010110 lev=3 vol=6 ((d'c)'(b+a)')'((b+a)c)'
-
-Class 142. Func 103. Functions = 8. Volume = 40. 0000011010010111
- 1509 : 0x0697 tt=0000011010010111 lev=4 vol=10 (((ba)c')'d')+((d+c)(b+a))
- 1543 : 0x0697 tt=0000011010010111 lev=4 vol=9 (((ba)+c)(b'a')')'((b+a)'d)'
- 1675 : 0x0697 tt=0000011010010111 lev=4 vol=9 (((b'a')'c)+(ba))'((b+a)'d)'
- 1716 : 0x0697 tt=0000011010010111 lev=4 vol=9 (((b'a')'c')'d')+((dc)'(b+a))
- 1730 : 0x0697 tt=0000011010010111 lev=4 vol=9 (((b'a')'c')'((b'a)'d')')'((c+a)b)'
- 1731 : 0x0697 tt=0000011010010111 lev=4 vol=9 (((b'a')'c')'((ba')'d')')'((c+b)a)'
- 1741 : 0x0697 tt=0000011010010111 lev=4 vol=9 (((b'a')d)'((b'a')'c)')+((dc)'(ba))
- 1766 : 0x0697 tt=0000011010010111 lev=4 vol=9 (((b'a')d')'c')+((dc)'(b+a)')
-
-Class 143. Func 104. Functions = 1. Volume = 4. 0000011010011111
- 729 : 0x069f tt=0000011010011111 lev=3 vol=5 ((b+a)'d)'((b+a)c)'
-
-Class 145. Func 105. Functions = 7. Volume = 35. 0000011010110001
- 1544 : 0x06b1 tt=0000011010110001 lev=4 vol=10 (((ba)+c)'(d+a))+((dc)'b')
- 1553 : 0x06b1 tt=0000011010110001 lev=4 vol=9 (((ba)'d)'(ca)')+((dc)'(b'a')')
- 1577 : 0x06b1 tt=0000011010110001 lev=4 vol=9 (((ba)'d')+(c'a))+((dc)'b)
- 1580 : 0x06b1 tt=0000011010110001 lev=4 vol=9 (((ba)'d')'(c'b)')+((d'b)'(c'a)')
- 1650 : 0x06b1 tt=0000011010110001 lev=4 vol=8 (((ba')d')'(c'a)')+((c'b)'d)
- 1718 : 0x06b1 tt=0000011010110001 lev=4 vol=8 (((b'a')'c')+d)'((c+a)b)'
- 1719 : 0x06b1 tt=0000011010110001 lev=4 vol=8 (((b'a')'c')+d)'((d+a)'b)'
-
-Class 150. Func 106. Functions = 4. Volume = 16. 0000011010110110
- 1311 : 0x06b6 tt=0000011010110110 lev=3 vol=7 ((dc)'(ba')')+((b'a)'c')
- 1597 : 0x06b6 tt=0000011010110110 lev=4 vol=7 (((b'a)'c')+(ba'))'(dc)'
- 1645 : 0x06b6 tt=0000011010110110 lev=4 vol=7 (((ba')+c)'(b'a)')'(dc)'
- 1653 : 0x06b6 tt=0000011010110110 lev=4 vol=7 (((ba')'d')'c)'((b+a)'c')'
-
-Class 154. Func 107. Functions = 2. Volume = 6. 0000011011110000
- 719 : 0x06f0 tt=0000011011110000 lev=3 vol=6 ((b+a)'c')'(d+c)
- 728 : 0x06f0 tt=0000011011110000 lev=3 vol=6 ((b+a)'d)'(d+c)
-
-Class 156. Func 108. Functions = 14. Volume = 62. 0000011011110010
- 1137 : 0x06f2 tt=0000011011110010 lev=3 vol=10 ((d+a)'(c+a)')'((da')+(c'b))'
- 1280 : 0x06f2 tt=0000011011110010 lev=3 vol=10 ((d+b)(c+b))'((db)+(c'a'))'
- 1319 : 0x06f2 tt=0000011011110010 lev=3 vol=8 ((dc)'(c'a')')+((d'a')'(c'b))
- 1325 : 0x06f2 tt=0000011011110010 lev=3 vol=8 ((dc)'(c'b)')+((d'b)'(c'a'))
- 1459 : 0x06f2 tt=0000011011110010 lev=3 vol=8 ((d+c)'(c'a)')'((b+a)'c')'
- 1467 : 0x06f2 tt=0000011011110010 lev=3 vol=8 ((d+c)'(c'b')')'((b+a)'c')'
- 1468 : 0x06f2 tt=0000011011110010 lev=3 vol=8 ((d+c)'(d'a)')'((b+a)'c')'
- 1475 : 0x06f2 tt=0000011011110010 lev=3 vol=8 ((d+c)'(d'b')')'((b+a)'c')'
- 1519 : 0x06f2 tt=0000011011110010 lev=4 vol=8 (((ba)c')'(dc)')((db)'(c'a'))'
- 1541 : 0x06f2 tt=0000011011110010 lev=4 vol=8 (((ba)'c')'(d'c)')'((db)'(c'a'))'
- 1638 : 0x06f2 tt=0000011011110010 lev=4 vol=8 (((ba')'c')'d)+((c'b)'(c'a')')
- 1639 : 0x06f2 tt=0000011011110010 lev=4 vol=8 (((ba')'c')'d')+((b+a)c')
- 1647 : 0x06f2 tt=0000011011110010 lev=4 vol=8 (((ba')d)'(dc)')+((b'a)'c')
- 1648 : 0x06f2 tt=0000011011110010 lev=4 vol=7 (((ba')d)'((b'a)'c'))'(dc)'
-
-Class 157. Func 109. Functions = 2. Volume = 7. 0000011011110110
- 717 : 0x06f6 tt=0000011011110110 lev=3 vol=6 ((b+a)c')+(d'c)
- 718 : 0x06f6 tt=0000011011110110 lev=3 vol=5 ((b+a)'c')'(dc)'
-
-Class 158. Func 110. Functions = 11. Volume = 42. 0000011011111001
- 720 : 0x06f9 tt=0000011011111001 lev=3 vol=7 ((b+a)'c')+(d+c)
- 842 : 0x06f9 tt=0000011011111001 lev=3 vol=7 ((cb)'(c'a)')+(d+b)
- 855 : 0x06f9 tt=0000011011111001 lev=3 vol=7 ((c'b)'(ca)')+(d+a)
- 1024 : 0x06f9 tt=0000011011111001 lev=3 vol=7 ((da)'d')+((b+a)c')
- 1096 : 0x06f9 tt=0000011011111001 lev=3 vol=7 ((da')'d')+((b+a)c')
- 1163 : 0x06f9 tt=0000011011111001 lev=3 vol=7 ((db)'d')+((b+a)c')
- 1215 : 0x06f9 tt=0000011011111001 lev=3 vol=7 ((db')'d')+((b+a)c')
- 1296 : 0x06f9 tt=0000011011111001 lev=3 vol=7 ((dc)'d')+((b+a)c')
- 1371 : 0x06f9 tt=0000011011111001 lev=3 vol=7 ((dc')'d')+((b+a)c')
- 1458 : 0x06f9 tt=0000011011111001 lev=3 vol=7 ((d+c)'(b+a))'((b+a)'d)'
- 1635 : 0x06f9 tt=0000011011111001 lev=4 vol=7 (((ba')c')'((b'a)c')')+d
-
-Class 159. Func 111. Functions = 7. Volume = 28. 0000011101110110
- 1305 : 0x0776 tt=0000011101110110 lev=3 vol=7 ((dc)'(ba)')((d'a')(c'b'))'
- 1307 : 0x0776 tt=0000011101110110 lev=3 vol=7 ((dc)'(ba)')((d'b')(c'a'))'
- 1418 : 0x0776 tt=0000011101110110 lev=3 vol=7 ((d'c')(b'a'))'((dc)'(ba)')
- 1691 : 0x0776 tt=0000011101110110 lev=4 vol=7 (((b'a')c')d')'((dc)'(ba)')
- 1727 : 0x0776 tt=0000011101110110 lev=4 vol=7 (((b'a')'c')'(d+c)')'(ba)'
- 1765 : 0x0776 tt=0000011101110110 lev=4 vol=7 (((b'a')d')c')'((dc)'(ba)')
- 1780 : 0x0776 tt=0000011101110110 lev=4 vol=7 (((b'a')'d')'(d+c)')'(ba)'
-
-Class 160. Func 112. Functions = 7. Volume = 22. 0000011101111000
- 1299 : 0x0778 tt=0000011101111000 lev=3 vol=7 ((dc)'(ba))+(d+c)
- 1300 : 0x0778 tt=0000011101111000 lev=3 vol=6 ((dc)'(ba)')+(d'c')
- 1412 : 0x0778 tt=0000011101111000 lev=3 vol=6 ((d'c')+(ba))'(dc)'
- 1476 : 0x0778 tt=0000011101111000 lev=4 vol=6 (((ba)c)'d')+((ba)'c')
- 1530 : 0x0778 tt=0000011101111000 lev=4 vol=6 (((ba)'c')+d)'((ba)c)'
- 1548 : 0x0778 tt=0000011101111000 lev=4 vol=6 (((ba)d)'c')+((ba)'d')
- 1573 : 0x0778 tt=0000011101111000 lev=4 vol=6 (((ba)'d')+c)'((ba)d)'
-
-Class 164. Func 113. Functions = 2. Volume = 7. 0000011110110000
- 792 : 0x07b0 tt=0000011110110000 lev=3 vol=6 ((c+a)b)'(d+c)
- 1127 : 0x07b0 tt=0000011110110000 lev=3 vol=6 ((d+a)'b)'(d+c)
-
-Class 165. Func 114. Functions = 4. Volume = 21. 0000011110110001
- 1466 : 0x07b1 tt=0000011110110001 lev=3 vol=8 ((d+c)'(c'a')')'((d+a)'b)'
- 1474 : 0x07b1 tt=0000011110110001 lev=3 vol=8 ((d+c)'(d'a')')'((d+a)'b)'
- 1651 : 0x07b1 tt=0000011110110001 lev=4 vol=8 (((ba')d')'(dc)')((db')'(c'a))'
- 1667 : 0x07b1 tt=0000011110110001 lev=4 vol=8 (((ba')'d')'(dc')')'((db')'(c'a))'
-
-Class 166. Func 115. Functions = 13. Volume = 44. 0000011110110100
- 1220 : 0x07b4 tt=0000011110110100 lev=3 vol=9 ((db')'(c'a)')+((d'a)'(c+b)')
- 1304 : 0x07b4 tt=0000011110110100 lev=3 vol=8 ((dc)'(ba)')+((c+b)'d')
- 1313 : 0x07b4 tt=0000011110110100 lev=3 vol=7 ((dc)'(ba')')+((db')'c')
- 1547 : 0x07b4 tt=0000011110110100 lev=4 vol=7 (((ba)d)'c)+((d'b')'(ba)')
- 1549 : 0x07b4 tt=0000011110110100 lev=4 vol=7 (((ba)d)'c')+((ba')'d')
- 1646 : 0x07b4 tt=0000011110110100 lev=4 vol=7 (((ba')+c)'(db')')'(dc)'
- 1654 : 0x07b4 tt=0000011110110100 lev=4 vol=7 (((ba')'d')+c)'((ba)c')'
- 1655 : 0x07b4 tt=0000011110110100 lev=4 vol=7 (((ba')'d')+c)'((ba)d)'
- 1656 : 0x07b4 tt=0000011110110100 lev=4 vol=7 (((ba')'d')+c)'((c'a)b)'
- 1657 : 0x07b4 tt=0000011110110100 lev=4 vol=7 (((ba')'d')+c)'((c'b)a)'
- 1658 : 0x07b4 tt=0000011110110100 lev=4 vol=7 (((ba')'d')+c)'((da)b)'
- 1659 : 0x07b4 tt=0000011110110100 lev=4 vol=7 (((ba')'d')+c)'((db)a)'
- 1668 : 0x07b4 tt=0000011110110100 lev=4 vol=7 (((ba')'d')'((ba)c')')+c
-
-Class 169. Func 116. Functions = 1. Volume = 5. 0000011110111100
- 628 : 0x07bc tt=0000011110111100 lev=3 vol=6 ((ba')'d')+((ba)'c')
-
-Class 176. Func 117. Functions = 9. Volume = 28. 0000011111110000
- 520 : 0x07f0 tt=0000011111110000 lev=3 vol=5 ((ba)c')'(d+c)
- 539 : 0x07f0 tt=0000011111110000 lev=3 vol=5 ((ba)d)'(d+c)
- 753 : 0x07f0 tt=0000011111110000 lev=3 vol=5 ((c'a)b)'(d+c)
- 845 : 0x07f0 tt=0000011111110000 lev=3 vol=5 ((c'b)a)'(d+c)
- 1013 : 0x07f0 tt=0000011111110000 lev=3 vol=5 ((da)b)'(d+c)
- 1150 : 0x07f0 tt=0000011111110000 lev=3 vol=5 ((db)a)'(d+c)
- 1508 : 0x07f0 tt=0000011111110000 lev=4 vol=5 (((ba)c')'d)+c
- 1523 : 0x07f0 tt=0000011111110000 lev=4 vol=5 (((ba)'c')'d)'(d'c')'
- 1552 : 0x07f0 tt=0000011111110000 lev=4 vol=5 (((ba)'d)'c')'(dc)'
-
-Class 178. Func 118. Functions = 3. Volume = 15. 0000011111110010
- 756 : 0x07f2 tt=0000011111110010 lev=3 vol=6 ((c'a)'d')+((ba)'c')
- 1460 : 0x07f2 tt=0000011111110010 lev=3 vol=6 ((d+c)'(c'a)')'((c'a)b)'
- 1601 : 0x07f2 tt=0000011111110010 lev=4 vol=6 (((b'a)'c')(da')')'(dc)'
-
-Class 179. Func 119. Functions = 5. Volume = 17. 0000011111111000
- 522 : 0x07f8 tt=0000011111111000 lev=3 vol=6 ((ba)c')+(d+c)
- 559 : 0x07f8 tt=0000011111111000 lev=3 vol=6 ((ba)+d)+((ba)'c)
- 754 : 0x07f8 tt=0000011111111000 lev=3 vol=6 ((c'a)b)+(d+c)
- 846 : 0x07f8 tt=0000011111111000 lev=3 vol=6 ((c'b)a)+(d+c)
- 947 : 0x07f8 tt=0000011111111000 lev=3 vol=5 ((c'b')'(c'a')')+d
-
-Class 180. Func 120. Functions = 1. Volume = 1. 0000111111110000
- 34 : 0x0ff0 tt=0000111111110000 lev=1 vol=2 d+c
-
-Class 188. Func 121. Functions = 3. Volume = 12. 0001011010000011
- 1102 : 0x1683 tt=0001011010000011 lev=3 vol=9 ((da')+(c+b))'((d'a)'(cb))'
- 1128 : 0x1683 tt=0001011010000011 lev=3 vol=9 ((d+a)'b)'((da')+(c+b))'
- 1131 : 0x1683 tt=0001011010000011 lev=3 vol=9 ((d+a)'c)'((da')+(c+b))'
-
-Class 194. Func 122. Functions = 28. Volume = 50. 0001011010010110
- 725 : 0x1696 tt=0001011010010110 lev=3 vol=7 ((b+a)+c)((ba)d)'
- 745 : 0x1696 tt=0001011010010110 lev=3 vol=7 ((ca)d)'((b+a)+c)
- 798 : 0x1696 tt=0001011010010110 lev=3 vol=7 ((c+a)+b)((ba)d)'
- 801 : 0x1696 tt=0001011010010110 lev=3 vol=7 ((c+a)+b)((ca)d)'
- 824 : 0x1696 tt=0001011010010110 lev=3 vol=7 ((cb)d)'((b+a)+c)
- 825 : 0x1696 tt=0001011010010110 lev=3 vol=7 ((cb)d)'((c+a)+b)
- 962 : 0x1696 tt=0001011010010110 lev=3 vol=7 ((c+b)+a)((ba)d)'
- 965 : 0x1696 tt=0001011010010110 lev=3 vol=7 ((c+b)+a)((ca)d)'
- 968 : 0x1696 tt=0001011010010110 lev=3 vol=7 ((c+b)+a)((cb)d)'
- 1014 : 0x1696 tt=0001011010010110 lev=3 vol=7 ((da)b)'((b+a)+c)
- 1015 : 0x1696 tt=0001011010010110 lev=3 vol=7 ((da)b)'((c+a)+b)
- 1016 : 0x1696 tt=0001011010010110 lev=3 vol=7 ((da)b)'((c+b)+a)
- 1020 : 0x1696 tt=0001011010010110 lev=3 vol=7 ((da)c)'((b+a)+c)
- 1021 : 0x1696 tt=0001011010010110 lev=3 vol=7 ((da)c)'((c+a)+b)
- 1022 : 0x1696 tt=0001011010010110 lev=3 vol=7 ((da)c)'((c+b)+a)
- 1151 : 0x1696 tt=0001011010010110 lev=3 vol=7 ((db)a)'((b+a)+c)
- 1152 : 0x1696 tt=0001011010010110 lev=3 vol=7 ((db)a)'((c+a)+b)
- 1153 : 0x1696 tt=0001011010010110 lev=3 vol=7 ((db)a)'((c+b)+a)
- 1156 : 0x1696 tt=0001011010010110 lev=3 vol=7 ((db)c)'((b+a)+c)
- 1157 : 0x1696 tt=0001011010010110 lev=3 vol=7 ((db)c)'((c+a)+b)
- 1158 : 0x1696 tt=0001011010010110 lev=3 vol=7 ((db)c)'((c+b)+a)
- 1285 : 0x1696 tt=0001011010010110 lev=3 vol=7 ((dc)a)'((b+a)+c)
- 1286 : 0x1696 tt=0001011010010110 lev=3 vol=7 ((dc)a)'((c+a)+b)
- 1287 : 0x1696 tt=0001011010010110 lev=3 vol=7 ((dc)a)'((c+b)+a)
- 1288 : 0x1696 tt=0001011010010110 lev=3 vol=7 ((dc)b)'((b+a)+c)
- 1289 : 0x1696 tt=0001011010010110 lev=3 vol=7 ((dc)b)'((c+a)+b)
- 1290 : 0x1696 tt=0001011010010110 lev=3 vol=7 ((dc)b)'((c+b)+a)
- 1546 : 0x1696 tt=0001011010010110 lev=4 vol=7 (((ba)d)'c)+(b+a)
-
-Class 196. Func 123. Functions = 2. Volume = 11. 0001011010011000
- 1378 : 0x1698 tt=0001011010011000 lev=3 vol=9 ((dc')'(b+a))'((da)+(c'b'))'
- 1379 : 0x1698 tt=0001011010011000 lev=3 vol=9 ((dc')'(b+a))'((db)+(c'a'))'
-
-Class 200. Func 124. Functions = 12. Volume = 43. 0001011010011110
- 1017 : 0x169e tt=0001011010011110 lev=3 vol=8 ((da)'b)+((c+a)(ba)')
- 1018 : 0x169e tt=0001011010011110 lev=3 vol=8 ((da)'b)+((c'b)'(c+a))
- 1039 : 0x169e tt=0001011010011110 lev=3 vol=8 ((da)'(b+a)')+((ba)'c')
- 1154 : 0x169e tt=0001011010011110 lev=3 vol=8 ((db)'a)+((c+b)(ba)')
- 1155 : 0x169e tt=0001011010011110 lev=3 vol=8 ((db)'a)+((c+b)(c'a)')
- 1166 : 0x169e tt=0001011010011110 lev=3 vol=8 ((db)'(b+a)')+((ba)'c')
- 1492 : 0x169e tt=0001011010011110 lev=4 vol=8 (((ba)'c)+a)+((d'a)'b)
- 1493 : 0x169e tt=0001011010011110 lev=4 vol=8 (((ba)'c)+b)+((d'b)'a)
- 1494 : 0x169e tt=0001011010011110 lev=4 vol=7 (((ba)'c)+(b'a'))'((ba)d)'
- 1550 : 0x169e tt=0001011010011110 lev=4 vol=7 (((ba)d)'(b'a')')+((ba)'c)
- 1551 : 0x169e tt=0001011010011110 lev=4 vol=7 (((ba)d)'((ba)'c)')+(b'a')
- 1733 : 0x169e tt=0001011010011110 lev=4 vol=7 (((b'a')+c)(ba)')'((ba)d)'
-
-Class 205. Func 125. Functions = 12. Volume = 48. 0001011011101001
- 752 : 0x16e9 tt=0001011011101001 lev=3 vol=8 ((ca)'(b+a)')+(d+c)
- 810 : 0x16e9 tt=0001011011101001 lev=3 vol=8 ((c+a)'(ba)')+(d+b)
- 839 : 0x16e9 tt=0001011011101001 lev=3 vol=8 ((cb)'(b+a)')+(d+c)
- 844 : 0x16e9 tt=0001011011101001 lev=3 vol=8 ((cb)'(c+a)')+(d+b)
- 931 : 0x16e9 tt=0001011011101001 lev=3 vol=8 ((c'b')+d)+((c'a')'(b'a')')
- 943 : 0x16e9 tt=0001011011101001 lev=3 vol=8 ((c'b')'(b'a')')+((c'a')+d)
- 948 : 0x16e9 tt=0001011011101001 lev=3 vol=8 ((c'b')'(c'a')')+((b'a')+d)
- 980 : 0x16e9 tt=0001011011101001 lev=3 vol=8 ((c+b)'(ba)')+(d+a)
- 997 : 0x16e9 tt=0001011011101001 lev=3 vol=8 ((c+b)'(ca)')+(d+a)
- 1590 : 0x16e9 tt=0001011011101001 lev=4 vol=8 (((b'a)'c)'(c'a)')+(d+b)
- 1631 : 0x16e9 tt=0001011011101001 lev=4 vol=8 (((ba')'c)'(c'b)')+(d+a)
- 1771 : 0x16e9 tt=0001011011101001 lev=4 vol=8 (((b'a')d')'((b'a')'d)')+((ba)'c')
-
-Class 207. Func 126. Functions = 3. Volume = 11. 0001011110001110
- 1134 : 0x178e tt=0001011110001110 lev=3 vol=8 ((d+a)(b+a)')+((b+a)c')
- 1135 : 0x178e tt=0001011110001110 lev=3 vol=7 ((d+a)'(b+a)')'((b+a)c)'
- 1268 : 0x178e tt=0001011110001110 lev=3 vol=7 ((d+b)'(b+a)')'((b+a)c)'
-
-Class 212. Func 127. Functions = 11. Volume = 49. 0001011111101000
- 713 : 0x17e8 tt=0001011111101000 lev=3 vol=8 ((b+a)c)+((ba)+d)
- 793 : 0x17e8 tt=0001011111101000 lev=3 vol=8 ((c+a)b)+((ca)+d)
- 851 : 0x17e8 tt=0001011111101000 lev=3 vol=8 ((c'b)+d)+((c'a)'(b'a')')
- 852 : 0x17e8 tt=0001011111101000 lev=3 vol=8 ((c'b)'(b'a')')+((c'a)+d)
- 865 : 0x17e8 tt=0001011111101000 lev=3 vol=8 ((cb')+d)+((c'a')'(b'a)')
- 876 : 0x17e8 tt=0001011111101000 lev=3 vol=8 ((cb')'(c'a')')+((b'a)+d)
- 942 : 0x17e8 tt=0001011111101000 lev=3 vol=8 ((c'b')'(ba')')+((ca')+d)
- 946 : 0x17e8 tt=0001011111101000 lev=3 vol=8 ((c'b')'(ca')')+((ba')+d)
- 951 : 0x17e8 tt=0001011111101000 lev=3 vol=8 ((c+b)a)+((cb)+d)
- 1510 : 0x17e8 tt=0001011111101000 lev=4 vol=8 (((ba)c')+d)+((b'a')'c)
- 1537 : 0x17e8 tt=0001011111101000 lev=4 vol=6 (((ba)'c')'(b'a')')+d
-
-Class 213. Func 128. Functions = 11. Volume = 51. 0001100011100111
- 819 : 0x18e7 tt=0001100011100111 lev=3 vol=9 ((c+a)'(b+a)')+((b+a)+d)
- 836 : 0x18e7 tt=0001100011100111 lev=3 vol=8 ((cb)+d)+((ca')'(ba)')
- 854 : 0x18e7 tt=0001100011100111 lev=3 vol=8 ((c'b)'(b'a')')+((c'a')+d)
- 857 : 0x18e7 tt=0001100011100111 lev=3 vol=8 ((c'b)'(ca')')+((ba')+d)
- 867 : 0x18e7 tt=0001100011100111 lev=3 vol=8 ((cb')'(ba)')+((ca)+d)
- 875 : 0x18e7 tt=0001100011100111 lev=3 vol=8 ((cb')'(c'a)')+((b'a)+d)
- 930 : 0x18e7 tt=0001100011100111 lev=3 vol=8 ((c'b')+d)+((c'a)'(b'a')')
- 1531 : 0x18e7 tt=0001100011100111 lev=4 vol=8 (((ba)'c')+d)+((b'a')'c)
- 1588 : 0x18e7 tt=0001100011100111 lev=4 vol=8 (((b'a)'c)'(ba')')+(d+b)
- 1630 : 0x18e7 tt=0001100011100111 lev=4 vol=8 (((ba')'c)'(b'a)')+(d+a)
- 1670 : 0x18e7 tt=0001100011100111 lev=4 vol=7 (((b'a')c)'((ba)c')')+d
-
-Class 216. Func 129. Functions = 5. Volume = 19. 0001100111100110
- 739 : 0x19e6 tt=0001100111100110 lev=3 vol=8 ((b+a)+d)+((ba)c)
- 742 : 0x19e6 tt=0001100111100110 lev=3 vol=8 ((ca)b)+((b+a)+d)
- 743 : 0x19e6 tt=0001100111100110 lev=3 vol=6 ((ca)'b)+(d+a)
- 821 : 0x19e6 tt=0001100111100110 lev=3 vol=6 ((cb)'a)+(d+b)
- 1512 : 0x19e6 tt=0001100111100110 lev=4 vol=6 (((ba)c')'(b'a')')+d
-
-Class 218. Func 130. Functions = 4. Volume = 12. 0001101111100100
- 629 : 0x1be4 tt=0001101111100100 lev=3 vol=6 ((ba')+d)+(ca)
- 748 : 0x1be4 tt=0001101111100100 lev=3 vol=6 ((ca)+d)+(ba')
- 750 : 0x1be4 tt=0001101111100100 lev=3 vol=6 ((ca)+(ba'))+d
- 758 : 0x1be4 tt=0001101111100100 lev=3 vol=5 ((c'a)'(b'a')')+d
-
-Class 219. Func 131. Functions = 3. Volume = 7. 0001111011100001
- 480 : 0x1ee1 tt=0001111011100001 lev=2 vol=5 (d+c)+(b'a')
- 668 : 0x1ee1 tt=0001111011100001 lev=3 vol=5 ((b'a')+c)+d
- 707 : 0x1ee1 tt=0001111011100001 lev=3 vol=5 ((b'a')+d)+c
-
-Class 220. Func 132. Functions = 15. Volume = 48. 0011110011000011
- 493 : 0x3cc3 tt=0011110011000011 lev=3 vol=6 ((ba)'b')+(d+c)
- 597 : 0x3cc3 tt=0011110011000011 lev=3 vol=6 ((ba')'b')+(d+c)
- 744 : 0x3cc3 tt=0011110011000011 lev=3 vol=6 ((ca)'c')+(d+b)
- 759 : 0x3cc3 tt=0011110011000011 lev=3 vol=6 ((ca')'c')+(d+b)
- 822 : 0x3cc3 tt=0011110011000011 lev=3 vol=6 ((cb)'b')+(d+c)
- 823 : 0x3cc3 tt=0011110011000011 lev=3 vol=6 ((cb)'c')+(d+b)
- 835 : 0x3cc3 tt=0011110011000011 lev=3 vol=6 ((cb)+d)+(c'b')
- 848 : 0x3cc3 tt=0011110011000011 lev=3 vol=6 ((c'b)'b')+(d+c)
- 863 : 0x3cc3 tt=0011110011000011 lev=3 vol=6 ((cb')'c')+(d+b)
- 877 : 0x3cc3 tt=0011110011000011 lev=3 vol=5 ((cb')'(c'b)')+d
- 976 : 0x3cc3 tt=0011110011000011 lev=3 vol=5 ((c+b)d')'((c+b)'d)'
- 1227 : 0x3cc3 tt=0011110011000011 lev=3 vol=5 ((db')'(d'b)')+c
- 1262 : 0x3cc3 tt=0011110011000011 lev=3 vol=5 ((d+b)c')'((d+b)'c)'
- 1392 : 0x3cc3 tt=0011110011000011 lev=3 vol=5 ((dc')'(d'c)')+b
- 1450 : 0x3cc3 tt=0011110011000011 lev=3 vol=5 ((d+c)b')'((d+c)'b)'
-
-Class 221. Func 133. Functions = 15. Volume = 33. 0110100110010110
- 311 : 0x6996 tt=0110100110010110 lev=2 vol=6 (d+a)+(c+b)
- 387 : 0x6996 tt=0110100110010110 lev=2 vol=6 (d+b)+(c+a)
- 483 : 0x6996 tt=0110100110010110 lev=2 vol=6 (d+c)+(b+a)
- 722 : 0x6996 tt=0110100110010110 lev=3 vol=6 ((b+a)+c)+d
- 737 : 0x6996 tt=0110100110010110 lev=3 vol=6 ((b+a)+d)+c
- 795 : 0x6996 tt=0110100110010110 lev=3 vol=6 ((c+a)+b)+d
- 807 : 0x6996 tt=0110100110010110 lev=3 vol=6 ((c+a)+d)+b
- 959 : 0x6996 tt=0110100110010110 lev=3 vol=6 ((c+b)+a)+d
- 977 : 0x6996 tt=0110100110010110 lev=3 vol=6 ((c+b)+d)+a
- 1129 : 0x6996 tt=0110100110010110 lev=3 vol=6 ((d+a)+b)+c
- 1132 : 0x6996 tt=0110100110010110 lev=3 vol=6 ((d+a)+c)+b
- 1259 : 0x6996 tt=0110100110010110 lev=3 vol=6 ((d+b)+a)+c
- 1266 : 0x6996 tt=0110100110010110 lev=3 vol=6 ((d+b)+c)+a
- 1449 : 0x6996 tt=0110100110010110 lev=3 vol=6 ((d+c)+a)+b
- 1451 : 0x6996 tt=0110100110010110 lev=3 vol=6 ((d+c)+b)+a
diff --git a/readme b/readme
new file mode 100644
index 00000000..5c06d4b5
--- /dev/null
+++ b/readme
@@ -0,0 +1,26 @@
+Often the code comes directly from a Windows computer.
+The following steps may be needed to compile it on UNIX:
+
+>> dos2unix Makefile Makefile
+>> dos2unix depends.sh depends.sh
+>> chmod 755 depends.sh
+>> make // on Solaris, try "gmake"
+
+If compiling as a static library, it is necessary to uncomment
+#define _LIB in "src/abc/main/main.c"
+
+Several things to try if it does not compile on your platform:
+- Try running all code (not only Makefile and depends.sh) through dos2unix
+- Try the following actions:
+ (a) Remove flags from the libs line (LIBS :=) in Makefile
+ (b) Remove "src\base\main\libSupport.c" from "src\base\main\module.make"
+ (c) Comment calls to Libs_Init() and Libs_End() in "src\base\main\mainInit.c"
+- Try linking with gcc (rather than g++)
+ For this replace "LD := g++" with "LD := gcc -lm" in Makefile
+- If your Linux distributin does not have "readline", you may have problems
+ compiling ABC with gcc. Please try installing this library from
+ http://tiswww.case.edu/php/chet/readline/rltop.html
+
+
+Finally, run regression test:
+abc>>> so regtest.script
diff --git a/regtest.script b/regtest.script
index a047af53..c4a23a89 100644
--- a/regtest.script
+++ b/regtest.script
@@ -1,103 +1,18 @@
-r examples/apex4.pla
-resyn
-sharem
-fpga
-cec
-ps
-
-clp
-share
-resyn
-map
-cec
-ps
-
-r examples/C2670.blif
-resyn
-fpga
-cec
-ps
-
-u
-map
-cec
-ps
-
-r examples/frg2.blif
-dsd
-muxes
-cec
-clp
-share
-resyn
-map
-cec
-ps
-
-r examples/pj1.blif
-resyn
-fpga
-cec
-ps
-
-u
-map
-cec
-ps
-
-r examples/s38584.bench
-resyn
-fpga
-cec
-ps
-
-u
-map
-cec
-ps
-
-r examples/ac.v
-resyn
-fpga
-cec
-ps
-
-u
-map
-cec
-ps
-
-r examples/s444.blif
-b
-esd -v
-dsd
-cec
-ps
-
-r examples/i10.blif
-fpga
-cec
-ps
-u
-map
-cec
-ps
-
-r examples/i10.blif
-b
-fraig_store
-resyn
-fraig_store
-resyn2
-fraig_store
-fraig_restore
-fpga
-cec
-ps
-
-u
-map
-cec
-ps
-
+r examples/apex4.pla; resyn; if; cec; ps; clp; resyn; map; cec; ps
+r examples/C2670.blif; st; w 1.aig; cec 1.aig
+r examples/C2670.blif; st; short_names; w 1.bench; cec 1.bench
+r examples/C2670.blif; st; short_names; ren -s; w 1.eqn; cec 1.eqn
+r examples/C2670.blif; resyn2; if -K 8; cec; ps; u; map; cec; ps
+r examples/frg2.blif; dsd; muxes; cec; ps; clp; share; resyn; map; cec; ps
+r examples/frg2.blif; bdd; muxes; cec; ps; clp; st; ren -b; muxes; cec; ps
+r examples/i10.blif; resyn2; fpga; cec; ps; u; map; cec; ps
+r examples/i10.blif; choice; fpga; cec; ps; u; map; cec; ps
+r examples/pj1.blif; st; if; cec; ps; u; map; cec; ps
+r examples/s38417.blif; comb; w 1.blif; resyn; if; cec 1.blif; ps
+r examples/s38417.blif; resyn; if; cec; ps; u; map; cec; ps
+r examples/s38584.bench; resyn; ren -s; fx; if; cec; ps; u; map; cec; ps
+r examples/s444.blif; b; esd -v; print_exdc; dsd; cec; ps
+r examples/s444.blif; double; frames -F 5; w 1.blif; ffpga -K 8; cec 1.blif
+r examples/s5378.blif; frames -F 5; cycle; w 1.blif; ps; ret; ps; sec 1.blif
+r examples/s6669.blif; cycle; w 1.blif; ps; ret -M 3; resyn; ps; sec 1.blif
time
diff --git a/regtest_output.txt b/regtest_output.txt
index f66ee380..6e0ffec3 100644
--- a/regtest_output.txt
+++ b/regtest_output.txt
@@ -1,110 +1,75 @@
-UC Berkeley, ABC 1.01 (compiled Sep 5 2005 23:36:08)
+UC Berkeley, ABC 1.01 (compiled Dec 25 2006 17:15:00)
abc 01> so regtest.script
-abc - > r examples/apex4.pla
-abc - > resyn
-abc - > sharem
-abc - > fpga
-abc - > cec
-Networks are equivalent after fraiging.
-abc - > ps
-examples/apex4.pla: i/o = 9/ 19 lat = 0 nd = 784 cube = 1985 lev = 5
-abc - >
-abc - > clp
-The shared BDD size is 917 nodes.
-abc - > share
-abc - > resyn
-abc - > map
+abc - > r examples/apex4.pla; resyn; if; cec; ps; clp; resyn; map; cec; ps
+Networks are equivalent.
+examples/apex4: i/o = 9/ 19 lat = 0 nd = 1172 aig = 4365 lev = 7
+The shared BDD size is 917 nodes. BDD construction time = 0.04 sec
A simple supergate library is derived from gate library "mcnc_temp.genlib".
Loaded 20 unique 5-input supergates from "mcnc_temp.super". Time = 0.02 sec
-abc - > cec
-Networks are equivalent after fraiging.
-abc - > ps
-examples/apex4.pla: i/o = 9/ 19 lat = 0 nd = 1816 area = 4599.00 delay = 11.50 lev = 11
-abc - >
-abc - > r examples/C2670.blif
-abc - > resyn
-abc - > fpga
-abc - > cec
-Networks are equivalent after fraiging.
-abc - > ps
-C2670.iscas : i/o = 233/ 140 lat = 0 nd = 169 cube = 482 lev = 6
-abc - >
-abc - > u
-abc - > map
-abc - > cec
-Networks are equivalent after fraiging.
-abc - > ps
-C2670.iscas : i/o = 233/ 140 lat = 0 nd = 465 area = 1142.00 delay = 15.50 lev = 14
-abc - >
-abc - > r examples/frg2.blif
-abc - > dsd
-abc - > muxes
-abc - > cec
-Networks are equivalent after fraiging.
-abc - > clp
-The shared BDD size is 1111 nodes.
-abc - > share
-abc - > resyn
-abc - > map
-abc - > cec
-Networks are equivalent after fraiging.
-abc - > ps
-frg2 : i/o = 143/ 139 lat = 0 nd = 540 area = 1360.00 delay = 10.10 lev = 9
-abc - >
-abc - > r examples/pj1.blif
-abc - > resyn
-abc - > fpga
-abc - > cec
-Networks are equivalent after fraiging.
-abc - > ps
-exCombCkt : i/o = 1769/1063 lat = 0 nd = 4730 cube = 10662 lev = 12
-abc - >
-abc - > u
-abc - > map
-abc - > cec
-Networks are equivalent after fraiging.
-abc - > ps
-exCombCkt : i/o = 1769/1063 lat = 0 nd = 10396 area = 25170.00 delay = 29.20 lev = 27
-abc - >
-abc - > r examples/s38584.bench
-abc - > resyn
-The network has 26 self-feeding latches.
-abc - > fpga
-abc - > cec
-The network has 26 self-feeding latches.
-The network has 26 self-feeding latches.
-Networks are equivalent after fraiging.
-abc - > ps
-examples/s38584.bench: i/o = 12/ 278 lat = 1452 nd = 3239 cube = 6769 lev = 7
-abc - >
-abc - > u
-abc - > map
-The network has 26 self-feeding latches.
-abc - > cec
-The network has 26 self-feeding latches.
-The network has 26 self-feeding latches.
-Networks are equivalent after fraiging.
-abc - > ps
-examples/s38584.bench: i/o = 12/ 278 lat = 1452 nd = 8522 area = 19305.00 delay = 20.60 lev = 17
-abc - >
-abc - > r examples/ac.v
-abc - > resyn
-abc - > fpga
-abc - > cec
-Networks are equivalent after fraiging.
-abc - > ps
-ac97_ctrl : i/o = 84/ 48 lat = 2199 nd = 3652 cube = 9391 lev = 3
-abc - >
-abc - > u
-abc - > map
-abc - > cec
-Networks are equivalent after fraiging.
-abc - > ps
-ac97_ctrl : i/o = 84/ 48 lat = 2199 nd = 8337 area = 19861.00 delay = 8.10 lev = 8
-abc - >
-abc - > r examples/s444.blif
-abc - > b
-abc - > esd -v
+Networks are equivalent.
+examples/apex4: i/o = 9/ 19 lat = 0 nd = 1734 aig = 2576 lev = 12
+abc - > r examples/C2670.blif; st; w 1.aig; cec 1.aig
+Networks are equivalent after structural hashing.
+abc - > r examples/C2670.blif; st; short_names; w 1.bench; cec 1.bench
+Networks are equivalent after structural hashing.
+abc - > r examples/C2670.blif; st; short_names; ren -s; w 1.eqn; cec 1.eqn
+Networks are equivalent.
+abc - > r examples/C2670.blif; resyn2; if -K 8; cec; ps; u; map; cec; ps
+Networks are equivalent.
+C2670.iscas : i/o = 233/ 140 lat = 0 nd = 120 aig = 1056 lev = 4
+Networks are equivalent.
+C2670.iscas : i/o = 233/ 140 lat = 0 nd = 467 aig = 651 lev = 14
+abc - > r examples/frg2.blif; dsd; muxes; cec; ps; clp; share; resyn; map; cec; ps
+Networks are equivalent.
+frg2 : i/o = 143/ 139 lat = 0 nd = 1648 aig = 2268 lev = 18
+The shared BDD size is 1672 nodes. BDD construction time = 0.14 sec
+Networks are equivalent.
+frg2 : i/o = 143/ 139 lat = 0 nd = 533 aig = 778 lev = 8
+abc - > r examples/frg2.blif; bdd; muxes; cec; ps; clp; st; ren -b; muxes; cec; ps
+Networks are equivalent.
+frg2 : i/o = 143/ 139 lat = 0 nd = 2868 aig = 4221 lev = 38
+The shared BDD size is 1684 nodes. BDD construction time = 0.14 sec
+Networks are equivalent.
+frg2 : i/o = 143/ 139 lat = 0 nd = 2331 aig = 3180 lev = 20
+abc - > r examples/i10.blif; resyn2; fpga; cec; ps; u; map; cec; ps
+Networks are equivalent.
+i10 : i/o = 257/ 224 lat = 0 nd = 808 aig = 2630 lev = 12
+Networks are equivalent.
+i10 : i/o = 257/ 224 lat = 0 nd = 1555 aig = 1980 lev = 24
+abc - > r examples/i10.blif; choice; fpga; cec; ps; u; map; cec; ps
+Currently stored 3 networks with 5801 nodes will be fraiged.
+Total fraiging time = 0.39 sec
+Performing FPGA mapping with choices.
+Networks are equivalent.
+i10 : i/o = 257/ 224 lat = 0 nd = 798 aig = 2543 lev = 12
+Performing mapping with choices.
+Networks are equivalent.
+i10 : i/o = 257/ 224 lat = 0 nd = 1463 aig = 1993 lev = 23
+abc - > r examples/pj1.blif; st; if; cec; ps; u; map; cec; ps
+Networks are equivalent after structural hashing.
+exCombCkt : i/o = 1769/1063 lat = 0 nd = 5984 aig = 23156 lev = 52
+Networks are equivalent.
+exCombCkt : i/o = 1769/1063 lat = 0 nd = 11474 aig = 16032 lev = 80
+abc - > r examples/s38417.blif; comb; w 1.blif; resyn; if; cec 1.blif; ps
+examples/s38417.blif (line 14): Skipping directive ".wire_load_slope".
+Networks are equivalent.
+s38417 : i/o = 1664/1742 lat = 0 nd = 3479 aig = 10120 lev = 9
+abc - > r examples/s38417.blif; resyn; if; cec; ps; u; map; cec; ps
+examples/s38417.blif (line 14): Skipping directive ".wire_load_slope".
+examples/s38417.blif (line 14): Skipping directive ".wire_load_slope".
+Networks are equivalent.
+s38417 : i/o = 28/ 106 lat = 1636 nd = 3479 aig = 10120 lev = 9
+examples/s38417.blif (line 14): Skipping directive ".wire_load_slope".
+Networks are equivalent.
+s38417 : i/o = 28/ 106 lat = 1636 nd = 7189 aig = 8689 lev = 17
+abc - > r examples/s38584.bench; resyn; ren -s; fx; if; cec; ps; u; map; cec; ps
+The network was strashed and balanced before FPGA mapping.
+Networks are equivalent.
+examples/s38584: i/o = 12/ 278 lat = 1452 nd = 4266 aig = 12569 lev = 10
+The network was strashed and balanced before mapping.
+Networks are equivalent.
+examples/s38584: i/o = 12/ 278 lat = 1452 nd = 8135 aig = 10674 lev = 18
+abc - > r examples/s444.blif; b; esd -v; print_exdc; dsd; cec; ps
The shared BDD size is 181 nodes.
BDD nodes in the transition relation before reordering 557.
BDD nodes in the transition relation after reordering 456.
@@ -112,54 +77,20 @@ Reachability analysis completed in 151 iterations.
The number of minterms in the reachable state set = 8865.
BDD nodes in the unreachable states before reordering 124.
BDD nodes in the unreachable states after reordering 113.
-abc - > dsd
-abc - > cec
-Networks are equivalent after fraiging.
-abc - > ps
-iscas\s444.bench: i/o = 3/ 6 lat = 21 nd = 81 cube = 119 lev = 7
-abc - >
-abc - > r examples/i10.blif
-abc - > fpga
-The network was strashed and balanced before FPGA mapping.
-abc - > cec
-Networks are equivalent after fraiging.
-abc - > ps
-i10 : i/o = 257/ 224 lat = 0 nd = 741 cube = 1616 lev = 11
-abc - > u
-abc - > map
-The network was strashed and balanced before mapping.
-abc - > cec
-Networks are equivalent after fraiging.
-abc - > ps
-i10 : i/o = 257/ 224 lat = 0 nd = 1659 area = 4215.00 delay = 30.80 lev = 27
-abc - >
-abc - > r examples/i10.blif
-abc - > b
-abc - > fraig_store
-The number of AIG nodes added to storage = 2425.
-abc - > resyn
-abc - > fraig_store
-The number of AIG nodes added to storage = 1678.
-abc - > resyn2
-abc - > fraig_store
-The number of AIG nodes added to storage = 1323.
-abc - > fraig_restore
-Currently stored 3 networks with 5426 nodes will be fraiged.
-abc - > fpga
-Performing FPGA mapping with choices.
-abc - > cec
-Networks are equivalent after fraiging.
-abc - > ps
-i10 : i/o = 257/ 224 lat = 0 nd = 674 cube = 1498 lev = 10
-abc - >
-abc - > u
-abc - > map
-Performing mapping with choices.
-abc - > cec
-Networks are equivalent after fraiging.
-abc - > ps
-i10 : i/o = 257/ 224 lat = 0 nd = 1505 area = 3561.00 delay = 25.00 lev = 22
-abc - >
-abc 109> time
-elapse: 77.52 seconds, total: 77.52 seconds
-abc 109> \ No newline at end of file
+EXDC network statistics:
+exdc : i/o = 21/ 21 lat = 0 nd = 21 cube = 86 lev = 2
+Networks are equivalent.
+s444 : i/o = 3/ 6 lat = 21 nd = 82 aig = 176 lev = 7
+abc - > r examples/s444.blif; double; frames -F 5; w 1.blif; ffpga -K 8; cec 1.blif
+Networks are equivalent after structural hashing.
+abc - > r examples/s5378.blif; frames -F 5; cycle; w 1.blif; ps; ret; ps; sec 1.blif
+s5378_5_frames: i/o = 175/ 245 lat = 164 and = 6629 (exor = 115) lev = 59
+s5378_5_frames: i/o = 175/ 245 lat = 182 nd = 6957 cube = 6956 lev = 50
+Networks are equivalent after framing.
+abc - > r examples/s6669.blif; cycle; w 1.blif; ps; ret -M 3; resyn; ps; sec 1.blif
+s6669 : i/o = 83/ 55 lat = 239 nd = 3080 cube = 3080 lev = 93
+s6669 : i/o = 83/ 55 lat = 183 and = 1915 (exor = 371) lev = 97
+Networks are equivalent after fraiging.
+abc - > time
+elapse: 44.07 seconds, total: 44.07 seconds
+abc 150> \ No newline at end of file
diff --git a/src/abc8/vec2/vec2.h b/src/abc8/vec2/vec2.h
deleted file mode 100644
index a4bd4771..00000000
--- a/src/abc8/vec2/vec2.h
+++ /dev/null
@@ -1,121 +0,0 @@
-/**CFile****************************************************************
-
- FileName [vec.h]
-
- SystemName [ABC: Logic synthesis and verification system.]
-
- PackageName [Resizable arrays.]
-
- Synopsis [External declarations.]
-
- Author [Alan Mishchenko]
-
- Affiliation [UC Berkeley]
-
- Date [Ver. 1.0. Started - June 20, 2005.]
-
- Revision [$Id: vec.h,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
-
-***********************************************************************/
-
-#ifndef __VEC_H__
-#define __VEC_H__
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-#ifdef _WIN32
-#define inline __inline // compatible with MS VS 6.0
-#pragma warning(disable : 4152) // warning C4152: nonstandard extension, function/data pointer conversion in expression
-#pragma warning(disable : 4244) // warning C4244: '+=' : conversion from 'int ' to 'unsigned short ', possible loss of data
-#pragma warning(disable : 4514) // warning C4514: 'Vec_StrPop' : unreferenced inline function has been removed
-#pragma warning(disable : 4710) // warning C4710: function 'Vec_PtrGrow' not inlined
-#endif
-
-#ifndef SINT64
-#define SINT64
-
-#ifdef _WIN32
-typedef signed __int64 sint64; // compatible with MS VS 6.0
-#else
-typedef long long sint64;
-#endif
-
-#endif
-
-////////////////////////////////////////////////////////////////////////
-/// INCLUDES ///
-////////////////////////////////////////////////////////////////////////
-
-// this include should be the first one in the list
-// it is used to catch memory leaks on Windows
-#include "leaks.h"
-
-////////////////////////////////////////////////////////////////////////
-/// MACRO DEFINITIONS ///
-////////////////////////////////////////////////////////////////////////
-
-#ifndef ABS
-#define ABS(a) ((a) < 0 ? -(a) : (a))
-#endif
-
-#ifndef MAX
-#define MAX(a,b) ((a) > (b) ? (a) : (b))
-#endif
-
-#ifndef MIN
-#define MIN(a,b) ((a) < (b) ? (a) : (b))
-#endif
-
-#ifndef ALLOC
-#define ALLOC(type, num) ((type *) malloc(sizeof(type) * (num)))
-#endif
-
-#ifndef FREE
-#define FREE(obj) ((obj) ? (free((char *) (obj)), (obj) = 0) : 0)
-#endif
-
-#ifndef REALLOC
-#define REALLOC(type, obj, num) \
- ((obj) ? ((type *) realloc((char *)(obj), sizeof(type) * (num))) : \
- ((type *) malloc(sizeof(type) * (num))))
-#endif
-
-#ifndef PRT
-#define PRT(a,t) printf("%s = ", (a)); printf("%6.2f sec\n", (float)(t)/(float)(CLOCKS_PER_SEC))
-#endif
-
-#ifndef PRTP
-#define PRTP(a,t,T) printf("%s = ", (a)); printf("%6.2f sec (%6.2f %%)\n", (float)(t)/(float)(CLOCKS_PER_SEC), (T)? 100.0*(t)/(T) : 0.0)
-#endif
-
-#include "vecInt.h"
-#include "vecFlt.h"
-#include "vecStr.h"
-#include "vecPtr.h"
-#include "vecVec.h"
-#include "vecAtt.h"
-
-////////////////////////////////////////////////////////////////////////
-/// PARAMETERS ///
-////////////////////////////////////////////////////////////////////////
-
-////////////////////////////////////////////////////////////////////////
-/// BASIC TYPES ///
-////////////////////////////////////////////////////////////////////////
-
-////////////////////////////////////////////////////////////////////////
-/// FUNCTION DECLARATIONS ///
-////////////////////////////////////////////////////////////////////////
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif
-
-////////////////////////////////////////////////////////////////////////
-/// END OF FILE ///
-////////////////////////////////////////////////////////////////////////
-
diff --git a/src/abc8/vec2/vecInt.h b/src/abc8/vec2/vecInt.h
deleted file mode 100644
index 082ebe70..00000000
--- a/src/abc8/vec2/vecInt.h
+++ /dev/null
@@ -1,834 +0,0 @@
-/**CFile****************************************************************
-
- FileName [vecInt.h]
-
- SystemName [ABC: Logic synthesis and verification system.]
-
- PackageName [Resizable arrays.]
-
- Synopsis [Resizable arrays of integers.]
-
- Author [Alan Mishchenko]
-
- Affiliation [UC Berkeley]
-
- Date [Ver. 1.0. Started - June 20, 2005.]
-
- Revision [$Id: vecInt.h,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
-
-***********************************************************************/
-
-#ifndef __VEC_INT_H__
-#define __VEC_INT_H__
-
-////////////////////////////////////////////////////////////////////////
-/// INCLUDES ///
-////////////////////////////////////////////////////////////////////////
-
-#include <stdio.h>
-
-////////////////////////////////////////////////////////////////////////
-/// PARAMETERS ///
-////////////////////////////////////////////////////////////////////////
-
-////////////////////////////////////////////////////////////////////////
-/// BASIC TYPES ///
-////////////////////////////////////////////////////////////////////////
-
-typedef struct Vec_Int_t_ Vec_Int_t;
-struct Vec_Int_t_
-{
- int nCap;
- int nSize;
- int * pArray;
-};
-
-////////////////////////////////////////////////////////////////////////
-/// MACRO DEFINITIONS ///
-////////////////////////////////////////////////////////////////////////
-
-#define Vec_IntForEachEntry( vVec, Entry, i ) \
- for ( i = 0; (i < Vec_IntSize(vVec)) && (((Entry) = Vec_IntEntry(vVec, i)), 1); i++ )
-#define Vec_IntForEachEntryStart( vVec, Entry, i, Start ) \
- for ( i = Start; (i < Vec_IntSize(vVec)) && (((Entry) = Vec_IntEntry(vVec, i)), 1); i++ )
-#define Vec_IntForEachEntryStartStop( vVec, Entry, i, Start, Stop ) \
- for ( i = Start; (i < Stop) && (((Entry) = Vec_IntEntry(vVec, i)), 1); i++ )
-#define Vec_IntForEachEntryReverse( vVec, pEntry, i ) \
- for ( i = Vec_IntSize(vVec) - 1; (i >= 0) && (((pEntry) = Vec_IntEntry(vVec, i)), 1); i-- )
-
-////////////////////////////////////////////////////////////////////////
-/// FUNCTION DEFINITIONS ///
-////////////////////////////////////////////////////////////////////////
-
-/**Function*************************************************************
-
- Synopsis [Allocates a vector with the given capacity.]
-
- Description []
-
- SideEffects []
-
- SeeAlso []
-
-***********************************************************************/
-static inline Vec_Int_t * Vec_IntAlloc( int nCap )
-{
- Vec_Int_t * p;
- p = ALLOC( Vec_Int_t, 1 );
- if ( nCap > 0 && nCap < 16 )
- nCap = 16;
- p->nSize = 0;
- p->nCap = nCap;
- p->pArray = p->nCap? ALLOC( int, p->nCap ) : NULL;
- return p;
-}
-
-/**Function*************************************************************
-
- Synopsis [Allocates a vector with the given size and cleans it.]
-
- Description []
-
- SideEffects []
-
- SeeAlso []
-
-***********************************************************************/
-static inline Vec_Int_t * Vec_IntStart( int nSize )
-{
- Vec_Int_t * p;
- p = Vec_IntAlloc( nSize );
- p->nSize = nSize;
- memset( p->pArray, 0, sizeof(int) * nSize );
- return p;
-}
-
-/**Function*************************************************************
-
- Synopsis [Allocates a vector with the given size and cleans it.]
-
- Description []
-
- SideEffects []
-
- SeeAlso []
-
-***********************************************************************/
-static inline Vec_Int_t * Vec_IntStartNatural( int nSize )
-{
- Vec_Int_t * p;
- int i;
- p = Vec_IntAlloc( nSize );
- p->nSize = nSize;
- for ( i = 0; i < nSize; i++ )
- p->pArray[i] = i;
- return p;
-}
-
-/**Function*************************************************************
-
- Synopsis [Creates the vector from an integer array of the given size.]
-
- Description []
-
- SideEffects []
-
- SeeAlso []
-
-***********************************************************************/
-static inline Vec_Int_t * Vec_IntAllocArray( int * pArray, int nSize )
-{
- Vec_Int_t * p;
- p = ALLOC( Vec_Int_t, 1 );
- p->nSize = nSize;
- p->nCap = nSize;
- p->pArray = pArray;
- return p;
-}
-
-/**Function*************************************************************
-
- Synopsis [Creates the vector from an integer array of the given size.]
-
- Description []
-
- SideEffects []
-
- SeeAlso []
-
-***********************************************************************/
-static inline Vec_Int_t * Vec_IntAllocArrayCopy( int * pArray, int nSize )
-{
- Vec_Int_t * p;
- p = ALLOC( Vec_Int_t, 1 );
- p->nSize = nSize;
- p->nCap = nSize;
- p->pArray = ALLOC( int, nSize );
- memcpy( p->pArray, pArray, sizeof(int) * nSize );
- return p;
-}
-
-/**Function*************************************************************
-
- Synopsis [Duplicates the integer array.]
-
- Description []
-
- SideEffects []
-
- SeeAlso []
-
-***********************************************************************/
-static inline Vec_Int_t * Vec_IntDup( Vec_Int_t * pVec )
-{
- Vec_Int_t * p;
- p = ALLOC( Vec_Int_t, 1 );
- p->nSize = pVec->nSize;
- p->nCap = pVec->nSize;
- p->pArray = p->nCap? ALLOC( int, p->nCap ) : NULL;
- memcpy( p->pArray, pVec->pArray, sizeof(int) * pVec->nSize );
- return p;
-}
-
-/**Function*************************************************************
-
- Synopsis [Transfers the array into another vector.]
-
- Description []
-
- SideEffects []
-
- SeeAlso []
-
-***********************************************************************/
-static inline Vec_Int_t * Vec_IntDupArray( Vec_Int_t * pVec )
-{
- Vec_Int_t * p;
- p = ALLOC( Vec_Int_t, 1 );
- p->nSize = pVec->nSize;
- p->nCap = pVec->nCap;
- p->pArray = pVec->pArray;
- pVec->nSize = 0;
- pVec->nCap = 0;
- pVec->pArray = NULL;
- return p;
-}
-
-/**Function*************************************************************
-
- Synopsis []
-
- Description []
-
- SideEffects []
-
- SeeAlso []
-
-***********************************************************************/
-static inline void Vec_IntFree( Vec_Int_t * p )
-{
- FREE( p->pArray );
- FREE( p );
-}
-
-/**Function*************************************************************
-
- Synopsis []
-
- Description []
-
- SideEffects []
-
- SeeAlso []
-
-***********************************************************************/
-static inline int * Vec_IntReleaseArray( Vec_Int_t * p )
-{
- int * pArray = p->pArray;
- p->nCap = 0;
- p->nSize = 0;
- p->pArray = NULL;
- return pArray;
-}
-
-/**Function*************************************************************
-
- Synopsis []
-
- Description []
-
- SideEffects []
-
- SeeAlso []
-
-***********************************************************************/
-static inline int * Vec_IntArray( Vec_Int_t * p )
-{
- return p->pArray;
-}
-
-/**Function*************************************************************
-
- Synopsis []
-
- Description []
-
- SideEffects []
-
- SeeAlso []
-
-***********************************************************************/
-static inline int Vec_IntSize( Vec_Int_t * p )
-{
- return p->nSize;
-}
-
-/**Function*************************************************************
-
- Synopsis []
-
- Description []
-
- SideEffects []
-
- SeeAlso []
-
-***********************************************************************/
-static inline int Vec_IntEntry( Vec_Int_t * p, int i )
-{
- assert( i >= 0 && i < p->nSize );
- return p->pArray[i];
-}
-
-/**Function*************************************************************
-
- Synopsis []
-
- Description []
-
- SideEffects []
-
- SeeAlso []
-
-***********************************************************************/
-static inline void Vec_IntWriteEntry( Vec_Int_t * p, int i, int Entry )
-{
- assert( i >= 0 && i < p->nSize );
- p->pArray[i] = Entry;
-}
-
-/**Function*************************************************************
-
- Synopsis []
-
- Description []
-
- SideEffects []
-
- SeeAlso []
-
-***********************************************************************/
-static inline void Vec_IntAddToEntry( Vec_Int_t * p, int i, int Addition )
-{
- assert( i >= 0 && i < p->nSize );
- p->pArray[i] += Addition;
-}
-
-/**Function*************************************************************
-
- Synopsis []
-
- Description []
-
- SideEffects []
-
- SeeAlso []
-
-***********************************************************************/
-static inline int Vec_IntEntryLast( Vec_Int_t * p )
-{
- assert( p->nSize > 0 );
- return p->pArray[p->nSize-1];
-}
-
-/**Function*************************************************************
-
- Synopsis [Resizes the vector to the given capacity.]
-
- Description []
-
- SideEffects []
-
- SeeAlso []
-
-***********************************************************************/
-static inline void Vec_IntGrow( Vec_Int_t * p, int nCapMin )
-{
- if ( p->nCap >= nCapMin )
- return;
- p->pArray = REALLOC( int, p->pArray, nCapMin );
- assert( p->pArray );
- p->nCap = nCapMin;
-}
-
-/**Function*************************************************************
-
- Synopsis [Fills the vector with given number of entries.]
-
- Description []
-
- SideEffects []
-
- SeeAlso []
-
-***********************************************************************/
-static inline void Vec_IntFill( Vec_Int_t * p, int nSize, int Entry )
-{
- int i;
- Vec_IntGrow( p, nSize );
- for ( i = 0; i < nSize; i++ )
- p->pArray[i] = Entry;
- p->nSize = nSize;
-}
-
-/**Function*************************************************************
-
- Synopsis [Fills the vector with given number of entries.]
-
- Description []
-
- SideEffects []
-
- SeeAlso []
-
-***********************************************************************/
-static inline void Vec_IntFillExtra( Vec_Int_t * p, int nSize, int Entry )
-{
- int i;
- if ( p->nSize >= nSize )
- return;
- Vec_IntGrow( p, nSize );
- for ( i = p->nSize; i < nSize; i++ )
- p->pArray[i] = Entry;
- p->nSize = nSize;
-}
-
-/**Function*************************************************************
-
- Synopsis []
-
- Description []
-
- SideEffects []
-
- SeeAlso []
-
-***********************************************************************/
-static inline void Vec_IntShrink( Vec_Int_t * p, int nSizeNew )
-{
- assert( p->nSize >= nSizeNew );
- p->nSize = nSizeNew;
-}
-
-/**Function*************************************************************
-
- Synopsis []
-
- Description []
-
- SideEffects []
-
- SeeAlso []
-
-***********************************************************************/
-static inline void Vec_IntClear( Vec_Int_t * p )
-{
- p->nSize = 0;
-}
-
-/**Function*************************************************************
-
- Synopsis []
-
- Description []
-
- SideEffects []
-
- SeeAlso []
-
-***********************************************************************/
-static inline void Vec_IntPush( Vec_Int_t * p, int Entry )
-{
- if ( p->nSize == p->nCap )
- {
- if ( p->nCap < 16 )
- Vec_IntGrow( p, 16 );
- else
- Vec_IntGrow( p, 2 * p->nCap );
- }
- p->pArray[p->nSize++] = Entry;
-}
-
-/**Function*************************************************************
-
- Synopsis []
-
- Description []
-
- SideEffects []
-
- SeeAlso []
-
-***********************************************************************/
-static inline void Vec_IntPushFirst( Vec_Int_t * p, int Entry )
-{
- int i;
- if ( p->nSize == p->nCap )
- {
- if ( p->nCap < 16 )
- Vec_IntGrow( p, 16 );
- else
- Vec_IntGrow( p, 2 * p->nCap );
- }
- p->nSize++;
- for ( i = p->nSize - 1; i >= 1; i-- )
- p->pArray[i] = p->pArray[i-1];
- p->pArray[0] = Entry;
-}
-
-/**Function*************************************************************
-
- Synopsis [Inserts the entry while preserving the increasing order.]
-
- Description []
-
- SideEffects []
-
- SeeAlso []
-
-***********************************************************************/
-static inline void Vec_IntPushOrder( Vec_Int_t * p, int Entry )
-{
- int i;
- if ( p->nSize == p->nCap )
- {
- if ( p->nCap < 16 )
- Vec_IntGrow( p, 16 );
- else
- Vec_IntGrow( p, 2 * p->nCap );
- }
- p->nSize++;
- for ( i = p->nSize-2; i >= 0; i-- )
- if ( p->pArray[i] > Entry )
- p->pArray[i+1] = p->pArray[i];
- else
- break;
- p->pArray[i+1] = Entry;
-}
-
-/**Function*************************************************************
-
- Synopsis [Inserts the entry while preserving the increasing order.]
-
- Description []
-
- SideEffects []
-
- SeeAlso []
-
-***********************************************************************/
-static inline int Vec_IntPushUniqueOrder( Vec_Int_t * p, int Entry )
-{
- int i;
- for ( i = 0; i < p->nSize; i++ )
- if ( p->pArray[i] == Entry )
- return 1;
- Vec_IntPushOrder( p, Entry );
- return 0;
-}
-
-/**Function*************************************************************
-
- Synopsis []
-
- Description []
-
- SideEffects []
-
- SeeAlso []
-
-***********************************************************************/
-static inline int Vec_IntPushUnique( Vec_Int_t * p, int Entry )
-{
- int i;
- for ( i = 0; i < p->nSize; i++ )
- if ( p->pArray[i] == Entry )
- return 1;
- Vec_IntPush( p, Entry );
- return 0;
-}
-
-/**Function*************************************************************
-
- Synopsis [Returns the pointer to the next nWords entries in the vector.]
-
- Description []
-
- SideEffects []
-
- SeeAlso []
-
-***********************************************************************/
-static inline unsigned * Vec_IntFetch( Vec_Int_t * p, int nWords )
-{
- if ( nWords == 0 )
- return NULL;
- assert( nWords > 0 );
- p->nSize += nWords;
- if ( p->nSize > p->nCap )
- {
-// Vec_IntGrow( p, 2 * p->nSize );
- return NULL;
- }
- return ((unsigned *)p->pArray) + p->nSize - nWords;
-}
-
-/**Function*************************************************************
-
- Synopsis [Returns the last entry and removes it from the list.]
-
- Description []
-
- SideEffects []
-
- SeeAlso []
-
-***********************************************************************/
-static inline int Vec_IntPop( Vec_Int_t * p )
-{
- assert( p->nSize > 0 );
- return p->pArray[--p->nSize];
-}
-
-/**Function*************************************************************
-
- Synopsis [Find entry.]
-
- Description []
-
- SideEffects []
-
- SeeAlso []
-
-***********************************************************************/
-static inline int Vec_IntFind( Vec_Int_t * p, int Entry )
-{
- int i;
- for ( i = 0; i < p->nSize; i++ )
- if ( p->pArray[i] == Entry )
- return i;
- return -1;
-}
-
-/**Function*************************************************************
-
- Synopsis []
-
- Description []
-
- SideEffects []
-
- SeeAlso []
-
-***********************************************************************/
-static inline int Vec_IntRemove( Vec_Int_t * p, int Entry )
-{
- int i;
- for ( i = 0; i < p->nSize; i++ )
- if ( p->pArray[i] == Entry )
- break;
- if ( i == p->nSize )
- return 0;
- assert( i < p->nSize );
- for ( i++; i < p->nSize; i++ )
- p->pArray[i-1] = p->pArray[i];
- p->nSize--;
- return 1;
-}
-
-/**Function*************************************************************
-
- Synopsis [Comparison procedure for two integers.]
-
- Description []
-
- SideEffects []
-
- SeeAlso []
-
-***********************************************************************/
-static inline int Vec_IntSortCompare1( int * pp1, int * pp2 )
-{
- // for some reason commenting out lines (as shown) led to crashing of the release version
- if ( *pp1 < *pp2 )
- return -1;
- if ( *pp1 > *pp2 ) //
- return 1;
- return 0; //
-}
-
-/**Function*************************************************************
-
- Synopsis [Comparison procedure for two integers.]
-
- Description []
-
- SideEffects []
-
- SeeAlso []
-
-***********************************************************************/
-static inline int Vec_IntSortCompare2( int * pp1, int * pp2 )
-{
- // for some reason commenting out lines (as shown) led to crashing of the release version
- if ( *pp1 > *pp2 )
- return -1;
- if ( *pp1 < *pp2 ) //
- return 1;
- return 0; //
-}
-
-/**Function*************************************************************
-
- Synopsis [Sorting the entries by their integer value.]
-
- Description []
-
- SideEffects []
-
- SeeAlso []
-
-***********************************************************************/
-static inline void Vec_IntSort( Vec_Int_t * p, int fReverse )
-{
- if ( fReverse )
- qsort( (void *)p->pArray, p->nSize, sizeof(int),
- (int (*)(const void *, const void *)) Vec_IntSortCompare2 );
- else
- qsort( (void *)p->pArray, p->nSize, sizeof(int),
- (int (*)(const void *, const void *)) Vec_IntSortCompare1 );
-}
-
-
-/**Function*************************************************************
-
- Synopsis [Comparison procedure for two integers.]
-
- Description []
-
- SideEffects []
-
- SeeAlso []
-
-***********************************************************************/
-static inline int Vec_IntSortCompareUnsigned( unsigned * pp1, unsigned * pp2 )
-{
- if ( *pp1 < *pp2 )
- return -1;
- if ( *pp1 > *pp2 )
- return 1;
- return 0;
-}
-
-/**Function*************************************************************
-
- Synopsis [Sorting the entries by their integer value.]
-
- Description []
-
- SideEffects []
-
- SeeAlso []
-
-***********************************************************************/
-static inline void Vec_IntSortUnsigned( Vec_Int_t * p )
-{
- qsort( (void *)p->pArray, p->nSize, sizeof(int),
- (int (*)(const void *, const void *)) Vec_IntSortCompareUnsigned );
-}
-
-/**Function*************************************************************
-
- Synopsis [Returns the number of common entries.]
-
- Description [Assumes that the vectors are sorted in the increasing order.]
-
- SideEffects []
-
- SeeAlso []
-
-***********************************************************************/
-static inline int Vec_IntTwoCountCommon( Vec_Int_t * vArr1, Vec_Int_t * vArr2 )
-{
- int * pBeg1 = vArr1->pArray;
- int * pBeg2 = vArr2->pArray;
- int * pEnd1 = vArr1->pArray + vArr1->nSize;
- int * pEnd2 = vArr2->pArray + vArr2->nSize;
- int Counter = 0;
- while ( pBeg1 < pEnd1 && pBeg2 < pEnd2 )
- {
- if ( *pBeg1 == *pBeg2 )
- pBeg1++, pBeg2++, Counter++;
- else if ( *pBeg1 < *pBeg2 )
- pBeg1++;
- else
- pBeg2++;
- }
- return Counter;
-}
-
-/**Function*************************************************************
-
- Synopsis [Returns the result of merging the two vectors.]
-
- Description [Assumes that the vectors are sorted in the increasing order.]
-
- SideEffects []
-
- SeeAlso []
-
-***********************************************************************/
-static inline Vec_Int_t * Vec_IntTwoMerge( Vec_Int_t * vArr1, Vec_Int_t * vArr2 )
-{
- Vec_Int_t * vArr = Vec_IntAlloc( vArr1->nSize + vArr2->nSize );
- int * pBeg = vArr->pArray;
- int * pBeg1 = vArr1->pArray;
- int * pBeg2 = vArr2->pArray;
- int * pEnd1 = vArr1->pArray + vArr1->nSize;
- int * pEnd2 = vArr2->pArray + vArr2->nSize;
- while ( pBeg1 < pEnd1 && pBeg2 < pEnd2 )
- {
- if ( *pBeg1 == *pBeg2 )
- *pBeg++ = *pBeg1++, pBeg2++;
- else if ( *pBeg1 < *pBeg2 )
- *pBeg++ = *pBeg1++;
- else
- *pBeg++ = *pBeg2++;
- }
- while ( pBeg1 < pEnd1 )
- *pBeg++ = *pBeg1++;
- while ( pBeg2 < pEnd2 )
- *pBeg++ = *pBeg2++;
- vArr->nSize = pBeg - vArr->pArray;
- assert( vArr->nSize <= vArr->nCap );
- assert( vArr->nSize >= vArr1->nSize );
- assert( vArr->nSize >= vArr2->nSize );
- return vArr;
-}
-
-#endif
-
-////////////////////////////////////////////////////////////////////////
-/// END OF FILE ///
-////////////////////////////////////////////////////////////////////////
-
diff --git a/src/abc8/vec2/vecPtr.h b/src/abc8/vec2/vecPtr.h
deleted file mode 100644
index 9595bc72..00000000
--- a/src/abc8/vec2/vecPtr.h
+++ /dev/null
@@ -1,812 +0,0 @@
-/**CFile****************************************************************
-
- FileName [vecPtr.h]
-
- SystemName [ABC: Logic synthesis and verification system.]
-
- PackageName [Resizable arrays.]
-
- Synopsis [Resizable arrays of generic pointers.]
-
- Author [Alan Mishchenko]
-
- Affiliation [UC Berkeley]
-
- Date [Ver. 1.0. Started - June 20, 2005.]
-
- Revision [$Id: vecPtr.h,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
-
-***********************************************************************/
-
-#ifndef __VEC_PTR_H__
-#define __VEC_PTR_H__
-
-////////////////////////////////////////////////////////////////////////
-/// INCLUDES ///
-////////////////////////////////////////////////////////////////////////
-
-#include <stdio.h>
-
-////////////////////////////////////////////////////////////////////////
-/// PARAMETERS ///
-////////////////////////////////////////////////////////////////////////
-
-////////////////////////////////////////////////////////////////////////
-/// BASIC TYPES ///
-////////////////////////////////////////////////////////////////////////
-
-typedef struct Vec_Ptr_t_ Vec_Ptr_t;
-struct Vec_Ptr_t_
-{
- int nCap;
- int nSize;
- void ** pArray;
-};
-
-////////////////////////////////////////////////////////////////////////
-/// MACRO DEFINITIONS ///
-////////////////////////////////////////////////////////////////////////
-
-// iterators through entries
-#define Vec_PtrForEachEntry( vVec, pEntry, i ) \
- for ( i = 0; (i < Vec_PtrSize(vVec)) && (((pEntry) = Vec_PtrEntry(vVec, i)), 1); i++ )
-#define Vec_PtrForEachEntryStart( vVec, pEntry, i, Start ) \
- for ( i = Start; (i < Vec_PtrSize(vVec)) && (((pEntry) = Vec_PtrEntry(vVec, i)), 1); i++ )
-#define Vec_PtrForEachEntryStop( vVec, pEntry, i, Stop ) \
- for ( i = 0; (i < Stop) && (((pEntry) = Vec_PtrEntry(vVec, i)), 1); i++ )
-#define Vec_PtrForEachEntryStartStop( vVec, pEntry, i, Start, Stop ) \
- for ( i = Start; (i < Stop) && (((pEntry) = Vec_PtrEntry(vVec, i)), 1); i++ )
-#define Vec_PtrForEachEntryReverse( vVec, pEntry, i ) \
- for ( i = Vec_PtrSize(vVec) - 1; (i >= 0) && (((pEntry) = Vec_PtrEntry(vVec, i)), 1); i-- )
-
-////////////////////////////////////////////////////////////////////////
-/// FUNCTION DEFINITIONS ///
-////////////////////////////////////////////////////////////////////////
-
-/**Function*************************************************************
-
- Synopsis [Allocates a vector with the given capacity.]
-
- Description []
-
- SideEffects []
-
- SeeAlso []
-
-***********************************************************************/
-static inline Vec_Ptr_t * Vec_PtrAlloc( int nCap )
-{
- Vec_Ptr_t * p;
- p = ALLOC( Vec_Ptr_t, 1 );
- if ( nCap > 0 && nCap < 8 )
- nCap = 8;
- p->nSize = 0;
- p->nCap = nCap;
- p->pArray = p->nCap? ALLOC( void *, p->nCap ) : NULL;
- return p;
-}
-
-/**Function*************************************************************
-
- Synopsis [Allocates a vector with the given size and cleans it.]
-
- Description []
-
- SideEffects []
-
- SeeAlso []
-
-***********************************************************************/
-static inline Vec_Ptr_t * Vec_PtrStart( int nSize )
-{
- Vec_Ptr_t * p;
- p = Vec_PtrAlloc( nSize );
- p->nSize = nSize;
- memset( p->pArray, 0, sizeof(void *) * nSize );
- return p;
-}
-
-/**Function*************************************************************
-
- Synopsis [Creates the vector from an integer array of the given size.]
-
- Description []
-
- SideEffects []
-
- SeeAlso []
-
-***********************************************************************/
-static inline Vec_Ptr_t * Vec_PtrAllocArray( void ** pArray, int nSize )
-{
- Vec_Ptr_t * p;
- p = ALLOC( Vec_Ptr_t, 1 );
- p->nSize = nSize;
- p->nCap = nSize;
- p->pArray = pArray;
- return p;
-}
-
-/**Function*************************************************************
-
- Synopsis [Creates the vector from an integer array of the given size.]
-
- Description []
-
- SideEffects []
-
- SeeAlso []
-
-***********************************************************************/
-static inline Vec_Ptr_t * Vec_PtrAllocArrayCopy( void ** pArray, int nSize )
-{
- Vec_Ptr_t * p;
- p = ALLOC( Vec_Ptr_t, 1 );
- p->nSize = nSize;
- p->nCap = nSize;
- p->pArray = ALLOC( void *, nSize );
- memcpy( p->pArray, pArray, sizeof(void *) * nSize );
- return p;
-}
-
-/**Function*************************************************************
-
- Synopsis [Duplicates the integer array.]
-
- Description []
-
- SideEffects []
-
- SeeAlso []
-
-***********************************************************************/
-static inline Vec_Ptr_t * Vec_PtrDup( Vec_Ptr_t * pVec )
-{
- Vec_Ptr_t * p;
- p = ALLOC( Vec_Ptr_t, 1 );
- p->nSize = pVec->nSize;
- p->nCap = pVec->nCap;
- p->pArray = p->nCap? ALLOC( void *, p->nCap ) : NULL;
- memcpy( p->pArray, pVec->pArray, sizeof(void *) * pVec->nSize );
- return p;
-}
-
-/**Function*************************************************************
-
- Synopsis [Transfers the array into another vector.]
-
- Description []
-
- SideEffects []
-
- SeeAlso []
-
-***********************************************************************/
-static inline Vec_Ptr_t * Vec_PtrDupArray( Vec_Ptr_t * pVec )
-{
- Vec_Ptr_t * p;
- p = ALLOC( Vec_Ptr_t, 1 );
- p->nSize = pVec->nSize;
- p->nCap = pVec->nCap;
- p->pArray = pVec->pArray;
- pVec->nSize = 0;
- pVec->nCap = 0;
- pVec->pArray = NULL;
- return p;
-}
-
-/**Function*************************************************************
-
- Synopsis [Frees the vector.]
-
- Description []
-
- SideEffects []
-
- SeeAlso []
-
-***********************************************************************/
-static inline void Vec_PtrFree( Vec_Ptr_t * p )
-{
- FREE( p->pArray );
- FREE( p );
-}
-
-/**Function*************************************************************
-
- Synopsis []
-
- Description []
-
- SideEffects []
-
- SeeAlso []
-
-***********************************************************************/
-static inline void ** Vec_PtrReleaseArray( Vec_Ptr_t * p )
-{
- void ** pArray = p->pArray;
- p->nCap = 0;
- p->nSize = 0;
- p->pArray = NULL;
- return pArray;
-}
-
-/**Function*************************************************************
-
- Synopsis []
-
- Description []
-
- SideEffects []
-
- SeeAlso []
-
-***********************************************************************/
-static inline void ** Vec_PtrArray( Vec_Ptr_t * p )
-{
- return p->pArray;
-}
-
-/**Function*************************************************************
-
- Synopsis []
-
- Description []
-
- SideEffects []
-
- SeeAlso []
-
-***********************************************************************/
-static inline int Vec_PtrSize( Vec_Ptr_t * p )
-{
- return p->nSize;
-}
-
-/**Function*************************************************************
-
- Synopsis []
-
- Description []
-
- SideEffects []
-
- SeeAlso []
-
-***********************************************************************/
-static inline void * Vec_PtrEntry( Vec_Ptr_t * p, int i )
-{
- assert( i >= 0 && i < p->nSize );
- return p->pArray[i];
-}
-
-/**Function*************************************************************
-
- Synopsis []
-
- Description []
-
- SideEffects []
-
- SeeAlso []
-
-***********************************************************************/
-static inline void ** Vec_PtrEntryP( Vec_Ptr_t * p, int i )
-{
- assert( i >= 0 && i < p->nSize );
- return p->pArray + i;
-}
-
-/**Function*************************************************************
-
- Synopsis []
-
- Description []
-
- SideEffects []
-
- SeeAlso []
-
-***********************************************************************/
-static inline void Vec_PtrWriteEntry( Vec_Ptr_t * p, int i, void * Entry )
-{
- assert( i >= 0 && i < p->nSize );
- p->pArray[i] = Entry;
-}
-
-/**Function*************************************************************
-
- Synopsis []
-
- Description []
-
- SideEffects []
-
- SeeAlso []
-
-***********************************************************************/
-static inline void * Vec_PtrEntryLast( Vec_Ptr_t * p )
-{
- assert( p->nSize > 0 );
- return p->pArray[p->nSize-1];
-}
-
-/**Function*************************************************************
-
- Synopsis [Resizes the vector to the given capacity.]
-
- Description []
-
- SideEffects []
-
- SeeAlso []
-
-***********************************************************************/
-static inline void Vec_PtrGrow( Vec_Ptr_t * p, int nCapMin )
-{
- if ( p->nCap >= nCapMin )
- return;
- p->pArray = REALLOC( void *, p->pArray, nCapMin );
- p->nCap = nCapMin;
-}
-
-/**Function*************************************************************
-
- Synopsis [Fills the vector with given number of entries.]
-
- Description []
-
- SideEffects []
-
- SeeAlso []
-
-***********************************************************************/
-static inline void Vec_PtrFill( Vec_Ptr_t * p, int nSize, void * Entry )
-{
- int i;
- Vec_PtrGrow( p, nSize );
- for ( i = 0; i < nSize; i++ )
- p->pArray[i] = Entry;
- p->nSize = nSize;
-}
-
-/**Function*************************************************************
-
- Synopsis [Fills the vector with given number of entries.]
-
- Description []
-
- SideEffects []
-
- SeeAlso []
-
-***********************************************************************/
-static inline void Vec_PtrFillExtra( Vec_Ptr_t * p, int nSize, void * Entry )
-{
- int i;
- if ( p->nSize >= nSize )
- return;
- assert( p->nSize < nSize );
- if ( 2 * p->nSize > nSize )
- Vec_PtrGrow( p, 2 * nSize );
- else
- Vec_PtrGrow( p, nSize );
- for ( i = p->nSize; i < nSize; i++ )
- p->pArray[i] = Entry;
- p->nSize = nSize;
-}
-
-/**Function*************************************************************
-
- Synopsis [Returns the entry even if the place not exist.]
-
- Description []
-
- SideEffects []
-
- SeeAlso []
-
-***********************************************************************/
-static inline void * Vec_PtrGetEntry( Vec_Ptr_t * p, int i )
-{
- Vec_PtrFillExtra( p, i + 1, NULL );
- return Vec_PtrEntry( p, i );
-}
-
-/**Function*************************************************************
-
- Synopsis [Inserts the entry even if the place does not exist.]
-
- Description []
-
- SideEffects []
-
- SeeAlso []
-
-***********************************************************************/
-static inline void Vec_PtrSetEntry( Vec_Ptr_t * p, int i, void * Entry )
-{
- Vec_PtrFillExtra( p, i + 1, NULL );
- Vec_PtrWriteEntry( p, i, Entry );
-}
-
-/**Function*************************************************************
-
- Synopsis []
-
- Description []
-
- SideEffects []
-
- SeeAlso []
-
-***********************************************************************/
-static inline void Vec_PtrShrink( Vec_Ptr_t * p, int nSizeNew )
-{
- assert( p->nSize >= nSizeNew );
- p->nSize = nSizeNew;
-}
-
-/**Function*************************************************************
-
- Synopsis []
-
- Description []
-
- SideEffects []
-
- SeeAlso []
-
-***********************************************************************/
-static inline void Vec_PtrClear( Vec_Ptr_t * p )
-{
- p->nSize = 0;
-}
-
-/**Function*************************************************************
-
- Synopsis [Copies the interger array.]
-
- Description []
-
- SideEffects []
-
- SeeAlso []
-
-***********************************************************************/
-static inline void Vec_PtrCopy( Vec_Ptr_t * pDest, Vec_Ptr_t * pSour )
-{
- pDest->nSize = 0;
- Vec_PtrGrow( pDest, pSour->nSize );
- memcpy( pDest->pArray, pSour->pArray, sizeof(void *) * pSour->nSize );
- pDest->nSize = pSour->nSize;
-}
-
-/**Function*************************************************************
-
- Synopsis []
-
- Description []
-
- SideEffects []
-
- SeeAlso []
-
-***********************************************************************/
-static inline void Vec_PtrPush( Vec_Ptr_t * p, void * Entry )
-{
- if ( p->nSize == p->nCap )
- {
- if ( p->nCap < 16 )
- Vec_PtrGrow( p, 16 );
- else
- Vec_PtrGrow( p, 2 * p->nCap );
- }
- p->pArray[p->nSize++] = Entry;
-}
-
-/**Function*************************************************************
-
- Synopsis []
-
- Description []
-
- SideEffects []
-
- SeeAlso []
-
-***********************************************************************/
-static inline int Vec_PtrPushUnique( Vec_Ptr_t * p, void * Entry )
-{
- int i;
- for ( i = 0; i < p->nSize; i++ )
- if ( p->pArray[i] == Entry )
- return 1;
- Vec_PtrPush( p, Entry );
- return 0;
-}
-
-/**Function*************************************************************
-
- Synopsis [Returns the last entry and removes it from the list.]
-
- Description []
-
- SideEffects []
-
- SeeAlso []
-
-***********************************************************************/
-static inline void * Vec_PtrPop( Vec_Ptr_t * p )
-{
- assert( p->nSize > 0 );
- return p->pArray[--p->nSize];
-}
-
-/**Function*************************************************************
-
- Synopsis [Find entry.]
-
- Description []
-
- SideEffects []
-
- SeeAlso []
-
-***********************************************************************/
-static inline int Vec_PtrFind( Vec_Ptr_t * p, void * Entry )
-{
- int i;
- for ( i = 0; i < p->nSize; i++ )
- if ( p->pArray[i] == Entry )
- return i;
- return -1;
-}
-
-/**Function*************************************************************
-
- Synopsis []
-
- Description []
-
- SideEffects []
-
- SeeAlso []
-
-***********************************************************************/
-static inline void Vec_PtrRemove( Vec_Ptr_t * p, void * Entry )
-{
- int i;
- // delete assuming that it is closer to the end
- for ( i = p->nSize - 1; i >= 0; i-- )
- if ( p->pArray[i] == Entry )
- break;
- assert( i >= 0 );
-/*
- // delete assuming that it is closer to the beginning
- for ( i = 0; i < p->nSize; i++ )
- if ( p->pArray[i] == Entry )
- break;
- assert( i < p->nSize );
-*/
- for ( i++; i < p->nSize; i++ )
- p->pArray[i-1] = p->pArray[i];
- p->nSize--;
-}
-
-/**Function*************************************************************
-
- Synopsis [Moves the first nItems to the end.]
-
- Description []
-
- SideEffects []
-
- SeeAlso []
-
-***********************************************************************/
-static inline void Vec_PtrReorder( Vec_Ptr_t * p, int nItems )
-{
- assert( nItems < p->nSize );
- Vec_PtrGrow( p, nItems + p->nSize );
- memmove( (char **)p->pArray + p->nSize, p->pArray, nItems * sizeof(void*) );
- memmove( p->pArray, (char **)p->pArray + nItems, p->nSize * sizeof(void*) );
-}
-
-/**Function*************************************************************
-
- Synopsis [Sorting the entries by their integer value.]
-
- Description []
-
- SideEffects []
-
- SeeAlso []
-
-***********************************************************************/
-static inline void Vec_PtrSort( Vec_Ptr_t * p, int (*Vec_PtrSortCompare)() )
-{
- if ( p->nSize < 2 )
- return;
- qsort( (void *)p->pArray, p->nSize, sizeof(void *),
- (int (*)(const void *, const void *)) Vec_PtrSortCompare );
-}
-
-/**Function*************************************************************
-
- Synopsis [Sorting the entries by their integer value.]
-
- Description []
-
- SideEffects []
-
- SeeAlso []
-
-***********************************************************************/
-static inline void Vec_PtrUniqify( Vec_Ptr_t * p, int (*Vec_PtrSortCompare)() )
-{
- int i, k;
- if ( p->nSize < 2 )
- return;
- qsort( (void *)p->pArray, p->nSize, sizeof(void *),
- (int (*)(const void *, const void *)) Vec_PtrSortCompare );
- for ( i = k = 1; i < p->nSize; i++ )
- if ( p->pArray[i] != p->pArray[i-1] )
- p->pArray[k++] = p->pArray[i];
- p->nSize = k;
-}
-
-
-
-/**Function*************************************************************
-
- Synopsis [Allocates the array of simulation info.]
-
- Description [Allocates the array containing given number of entries,
- each of which contains given number of unsigned words of simulation data.
- The resulting array can be freed using regular procedure Vec_PtrFree().
- It is the responsibility of the user to ensure this array is never grown.]
-
- SideEffects []
-
- SeeAlso []
-
-***********************************************************************/
-static inline Vec_Ptr_t * Vec_PtrAllocSimInfo( int nEntries, int nWords )
-{
- void ** pMemory;
- unsigned * pInfo;
- int i;
- pMemory = (void **)ALLOC( char, (sizeof(void *) + sizeof(unsigned) * nWords) * nEntries );
- pInfo = (unsigned *)(pMemory + nEntries);
- for ( i = 0; i < nEntries; i++ )
- pMemory[i] = pInfo + i * nWords;
- return Vec_PtrAllocArray( pMemory, nEntries );
-}
-
-/**Function*************************************************************
-
- Synopsis [Cleans simulation info of each entry beginning with iWord.]
-
- Description []
-
- SideEffects []
-
- SeeAlso []
-
-***********************************************************************/
-static inline void Vec_PtrCleanSimInfo( Vec_Ptr_t * vInfo, int iWord, int nWords )
-{
- int i;
- for ( i = 0; i < vInfo->nSize; i++ )
- memset( (char*)Vec_PtrEntry(vInfo,i) + 4*iWord, 0, 4*(nWords-iWord) );
-}
-
-/**Function*************************************************************
-
- Synopsis [Resizes the array of simulation info.]
-
- Description [Doubles the number of objects for which siminfo is allocated.]
-
- SideEffects []
-
- SeeAlso []
-
-***********************************************************************/
-static inline void Vec_PtrDoubleSimInfo( Vec_Ptr_t * vInfo )
-{
- Vec_Ptr_t * vInfoNew;
- int nWords;
- assert( Vec_PtrSize(vInfo) > 1 );
- // get the new array
- nWords = (unsigned *)Vec_PtrEntry(vInfo,1) - (unsigned *)Vec_PtrEntry(vInfo,0);
- vInfoNew = Vec_PtrAllocSimInfo( 2*Vec_PtrSize(vInfo), nWords );
- // copy the simulation info
- memcpy( Vec_PtrEntry(vInfoNew,0), Vec_PtrEntry(vInfo,0), Vec_PtrSize(vInfo) * nWords * 4 );
- // replace the array
- free( vInfo->pArray );
- vInfo->pArray = vInfoNew->pArray;
- vInfo->nSize *= 2;
- vInfo->nCap *= 2;
- // free the old array
- vInfoNew->pArray = NULL;
- free( vInfoNew );
-}
-
-/**Function*************************************************************
-
- Synopsis [Resizes the array of simulation info.]
-
- Description [Doubles the number of simulation patterns stored for each object.]
-
- SideEffects []
-
- SeeAlso []
-
-***********************************************************************/
-static inline void Vec_PtrReallocSimInfo( Vec_Ptr_t * vInfo )
-{
- Vec_Ptr_t * vInfoNew;
- int nWords, i;
- assert( Vec_PtrSize(vInfo) > 1 );
- // get the new array
- nWords = (unsigned *)Vec_PtrEntry(vInfo,1) - (unsigned *)Vec_PtrEntry(vInfo,0);
- vInfoNew = Vec_PtrAllocSimInfo( Vec_PtrSize(vInfo), 2*nWords );
- // copy the simulation info
- for ( i = 0; i < vInfo->nSize; i++ )
- memcpy( Vec_PtrEntry(vInfoNew,i), Vec_PtrEntry(vInfo,i), nWords * 4 );
- // replace the array
- free( vInfo->pArray );
- vInfo->pArray = vInfoNew->pArray;
- // free the old array
- vInfoNew->pArray = NULL;
- free( vInfoNew );
-}
-
-/**Function*************************************************************
-
- Synopsis [Allocates the array of truth tables for the given number of vars.]
-
- Description []
-
- SideEffects []
-
- SeeAlso []
-
-***********************************************************************/
-static inline Vec_Ptr_t * Vec_PtrAllocTruthTables( int nVars )
-{
- Vec_Ptr_t * p;
- unsigned Masks[5] = { 0xAAAAAAAA, 0xCCCCCCCC, 0xF0F0F0F0, 0xFF00FF00, 0xFFFF0000 };
- unsigned * pTruth;
- int i, k, nWords;
- nWords = (nVars <= 5 ? 1 : (1 << (nVars - 5)));
- p = Vec_PtrAllocSimInfo( nVars, nWords );
- for ( i = 0; i < nVars; i++ )
- {
- pTruth = (unsigned *)p->pArray[i];
- if ( i < 5 )
- {
- for ( k = 0; k < nWords; k++ )
- pTruth[k] = Masks[i];
- }
- else
- {
- for ( k = 0; k < nWords; k++ )
- if ( k & (1 << (i-5)) )
- pTruth[k] = ~(unsigned)0;
- else
- pTruth[k] = 0;
- }
- }
- return p;
-}
-
-#endif
-
-
-////////////////////////////////////////////////////////////////////////
-/// END OF FILE ///
-////////////////////////////////////////////////////////////////////////
-
diff --git a/src/abc8/vec2/vecStr.h b/src/abc8/vec2/vecStr.h
deleted file mode 100644
index 47367bc6..00000000
--- a/src/abc8/vec2/vecStr.h
+++ /dev/null
@@ -1,583 +0,0 @@
-/**CFile****************************************************************
-
- FileName [vecStr.h]
-
- SystemName [ABC: Logic synthesis and verification system.]
-
- PackageName [Resizable arrays.]
-
- Synopsis [Resizable arrays of characters.]
-
- Author [Alan Mishchenko]
-
- Affiliation [UC Berkeley]
-
- Date [Ver. 1.0. Started - June 20, 2005.]
-
- Revision [$Id: vecStr.h,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
-
-***********************************************************************/
-
-#ifndef __VEC_STR_H__
-#define __VEC_STR_H__
-
-////////////////////////////////////////////////////////////////////////
-/// INCLUDES ///
-////////////////////////////////////////////////////////////////////////
-
-#include <stdio.h>
-
-////////////////////////////////////////////////////////////////////////
-/// PARAMETERS ///
-////////////////////////////////////////////////////////////////////////
-
-////////////////////////////////////////////////////////////////////////
-/// BASIC TYPES ///
-////////////////////////////////////////////////////////////////////////
-
-typedef struct Vec_Str_t_ Vec_Str_t;
-struct Vec_Str_t_
-{
- int nCap;
- int nSize;
- char * pArray;
-};
-
-////////////////////////////////////////////////////////////////////////
-/// MACRO DEFINITIONS ///
-////////////////////////////////////////////////////////////////////////
-
-#define Vec_StrForEachEntry( vVec, Entry, i ) \
- for ( i = 0; (i < Vec_StrSize(vVec)) && (((Entry) = Vec_StrEntry(vVec, i)), 1); i++ )
-
-////////////////////////////////////////////////////////////////////////
-/// FUNCTION DEFINITIONS ///
-////////////////////////////////////////////////////////////////////////
-
-/**Function*************************************************************
-
- Synopsis [Allocates a vector with the given capacity.]
-
- Description []
-
- SideEffects []
-
- SeeAlso []
-
-***********************************************************************/
-static inline Vec_Str_t * Vec_StrAlloc( int nCap )
-{
- Vec_Str_t * p;
- p = ALLOC( Vec_Str_t, 1 );
- if ( nCap > 0 && nCap < 16 )
- nCap = 16;
- p->nSize = 0;
- p->nCap = nCap;
- p->pArray = p->nCap? ALLOC( char, p->nCap ) : NULL;
- return p;
-}
-
-/**Function*************************************************************
-
- Synopsis [Allocates a vector with the given size and cleans it.]
-
- Description []
-
- SideEffects []
-
- SeeAlso []
-
-***********************************************************************/
-static inline Vec_Str_t * Vec_StrStart( int nSize )
-{
- Vec_Str_t * p;
- p = Vec_StrAlloc( nSize );
- p->nSize = nSize;
- memset( p->pArray, 0, sizeof(char) * nSize );
- return p;
-}
-
-/**Function*************************************************************
-
- Synopsis [Creates the vector from an integer array of the given size.]
-
- Description []
-
- SideEffects []
-
- SeeAlso []
-
-***********************************************************************/
-static inline Vec_Str_t * Vec_StrAllocArray( char * pArray, int nSize )
-{
- Vec_Str_t * p;
- p = ALLOC( Vec_Str_t, 1 );
- p->nSize = nSize;
- p->nCap = nSize;
- p->pArray = pArray;
- return p;
-}
-
-/**Function*************************************************************
-
- Synopsis [Creates the vector from an integer array of the given size.]
-
- Description []
-
- SideEffects []
-
- SeeAlso []
-
-***********************************************************************/
-static inline Vec_Str_t * Vec_StrAllocArrayCopy( char * pArray, int nSize )
-{
- Vec_Str_t * p;
- p = ALLOC( Vec_Str_t, 1 );
- p->nSize = nSize;
- p->nCap = nSize;
- p->pArray = ALLOC( char, nSize );
- memcpy( p->pArray, pArray, sizeof(char) * nSize );
- return p;
-}
-
-/**Function*************************************************************
-
- Synopsis [Duplicates the integer array.]
-
- Description []
-
- SideEffects []
-
- SeeAlso []
-
-***********************************************************************/
-static inline Vec_Str_t * Vec_StrDup( Vec_Str_t * pVec )
-{
- Vec_Str_t * p;
- p = ALLOC( Vec_Str_t, 1 );
- p->nSize = pVec->nSize;
- p->nCap = pVec->nCap;
- p->pArray = p->nCap? ALLOC( char, p->nCap ) : NULL;
- memcpy( p->pArray, pVec->pArray, sizeof(char) * pVec->nSize );
- return p;
-}
-
-/**Function*************************************************************
-
- Synopsis [Transfers the array into another vector.]
-
- Description []
-
- SideEffects []
-
- SeeAlso []
-
-***********************************************************************/
-static inline Vec_Str_t * Vec_StrDupArray( Vec_Str_t * pVec )
-{
- Vec_Str_t * p;
- p = ALLOC( Vec_Str_t, 1 );
- p->nSize = pVec->nSize;
- p->nCap = pVec->nCap;
- p->pArray = pVec->pArray;
- pVec->nSize = 0;
- pVec->nCap = 0;
- pVec->pArray = NULL;
- return p;
-}
-
-/**Function*************************************************************
-
- Synopsis []
-
- Description []
-
- SideEffects []
-
- SeeAlso []
-
-***********************************************************************/
-static inline void Vec_StrFree( Vec_Str_t * p )
-{
- FREE( p->pArray );
- FREE( p );
-}
-
-/**Function*************************************************************
-
- Synopsis []
-
- Description []
-
- SideEffects []
-
- SeeAlso []
-
-***********************************************************************/
-static inline char * Vec_StrReleaseArray( Vec_Str_t * p )
-{
- char * pArray = p->pArray;
- p->nCap = 0;
- p->nSize = 0;
- p->pArray = NULL;
- return pArray;
-}
-
-/**Function*************************************************************
-
- Synopsis []
-
- Description []
-
- SideEffects []
-
- SeeAlso []
-
-***********************************************************************/
-static inline char * Vec_StrArray( Vec_Str_t * p )
-{
- return p->pArray;
-}
-
-/**Function*************************************************************
-
- Synopsis []
-
- Description []
-
- SideEffects []
-
- SeeAlso []
-
-***********************************************************************/
-static inline int Vec_StrSize( Vec_Str_t * p )
-{
- return p->nSize;
-}
-
-/**Function*************************************************************
-
- Synopsis []
-
- Description []
-
- SideEffects []
-
- SeeAlso []
-
-***********************************************************************/
-static inline char Vec_StrEntry( Vec_Str_t * p, int i )
-{
- assert( i >= 0 && i < p->nSize );
- return p->pArray[i];
-}
-
-/**Function*************************************************************
-
- Synopsis []
-
- Description []
-
- SideEffects []
-
- SeeAlso []
-
-***********************************************************************/
-static inline void Vec_StrWriteEntry( Vec_Str_t * p, int i, char Entry )
-{
- assert( i >= 0 && i < p->nSize );
- p->pArray[i] = Entry;
-}
-
-/**Function*************************************************************
-
- Synopsis []
-
- Description []
-
- SideEffects []
-
- SeeAlso []
-
-***********************************************************************/
-static inline char Vec_StrEntryLast( Vec_Str_t * p )
-{
- assert( p->nSize > 0 );
- return p->pArray[p->nSize-1];
-}
-
-/**Function*************************************************************
-
- Synopsis [Resizes the vector to the given capacity.]
-
- Description []
-
- SideEffects []
-
- SeeAlso []
-
-***********************************************************************/
-static inline void Vec_StrGrow( Vec_Str_t * p, int nCapMin )
-{
- if ( p->nCap >= nCapMin )
- return;
- p->pArray = REALLOC( char, p->pArray, 2 * nCapMin );
- p->nCap = 2 * nCapMin;
-}
-
-/**Function*************************************************************
-
- Synopsis [Fills the vector with given number of entries.]
-
- Description []
-
- SideEffects []
-
- SeeAlso []
-
-***********************************************************************/
-static inline void Vec_StrFill( Vec_Str_t * p, int nSize, char Entry )
-{
- int i;
- Vec_StrGrow( p, nSize );
- p->nSize = nSize;
- for ( i = 0; i < p->nSize; i++ )
- p->pArray[i] = Entry;
-}
-
-/**Function*************************************************************
-
- Synopsis []
-
- Description []
-
- SideEffects []
-
- SeeAlso []
-
-***********************************************************************/
-static inline void Vec_StrShrink( Vec_Str_t * p, int nSizeNew )
-{
- assert( p->nSize >= nSizeNew );
- p->nSize = nSizeNew;
-}
-
-/**Function*************************************************************
-
- Synopsis []
-
- Description []
-
- SideEffects []
-
- SeeAlso []
-
-***********************************************************************/
-static inline void Vec_StrClear( Vec_Str_t * p )
-{
- p->nSize = 0;
-}
-
-/**Function*************************************************************
-
- Synopsis []
-
- Description []
-
- SideEffects []
-
- SeeAlso []
-
-***********************************************************************/
-static inline void Vec_StrPush( Vec_Str_t * p, char Entry )
-{
- if ( p->nSize == p->nCap )
- {
- if ( p->nCap < 16 )
- Vec_StrGrow( p, 16 );
- else
- Vec_StrGrow( p, 2 * p->nCap );
- }
- p->pArray[p->nSize++] = Entry;
-}
-
-/**Function********************************************************************
-
- Synopsis [Finds the smallest integer larger of equal than the logarithm.]
-
- Description [Returns [Log10(Num)].]
-
- SideEffects []
-
- SeeAlso []
-
-******************************************************************************/
-static inline int Vec_StrBase10Log( unsigned Num )
-{
- int Res;
- assert( Num >= 0 );
- if ( Num == 0 ) return 0;
- if ( Num == 1 ) return 1;
- for ( Res = 0, Num--; Num; Num /= 10, Res++ );
- return Res;
-} /* end of Extra_Base2Log */
-
-/**Function*************************************************************
-
- Synopsis []
-
- Description []
-
- SideEffects []
-
- SeeAlso []
-
-***********************************************************************/
-static inline void Vec_StrPrintNum( Vec_Str_t * p, int Num )
-{
- int i, nDigits;
- if ( Num < 0 )
- {
- Vec_StrPush( p, '-' );
- Num = -Num;
- }
- if ( Num < 10 )
- {
- Vec_StrPush( p, (char)('0' + Num) );
- return;
- }
- nDigits = Vec_StrBase10Log( Num );
- Vec_StrGrow( p, p->nSize + nDigits );
- for ( i = nDigits - 1; i >= 0; i-- )
- {
- Vec_StrWriteEntry( p, p->nSize + i, (char)('0' + Num % 10) );
- Num /= 10;
- }
- assert( Num == 0 );
- p->nSize += nDigits;
-}
-
-/**Function*************************************************************
-
- Synopsis []
-
- Description []
-
- SideEffects []
-
- SeeAlso []
-
-***********************************************************************/
-static inline void Vec_StrPrintStr( Vec_Str_t * p, char * pStr )
-{
- int i, Length = strlen(pStr);
- for ( i = 0; i < Length; i++ )
- Vec_StrPush( p, pStr[i] );
-}
-
-/**Function*************************************************************
-
- Synopsis [Appends the string to the char vector.]
-
- Description []
-
- SideEffects []
-
- SeeAlso []
-
-***********************************************************************/
-static inline void Vec_StrAppend( Vec_Str_t * p, char * pString )
-{
- int i, nLength = strlen(pString);
- Vec_StrGrow( p, p->nSize + nLength );
- for ( i = 0; i < nLength; i++ )
- p->pArray[p->nSize + i] = pString[i];
- p->nSize += nLength;
-}
-
-/**Function*************************************************************
-
- Synopsis [Returns the last entry and removes it from the list.]
-
- Description []
-
- SideEffects []
-
- SeeAlso []
-
-***********************************************************************/
-static inline char Vec_StrPop( Vec_Str_t * p )
-{
- assert( p->nSize > 0 );
- return p->pArray[--p->nSize];
-}
-
-/**Function*************************************************************
-
- Synopsis [Comparison procedure for two clauses.]
-
- Description []
-
- SideEffects []
-
- SeeAlso []
-
-***********************************************************************/
-static inline int Vec_StrSortCompare1( char * pp1, char * pp2 )
-{
- // for some reason commenting out lines (as shown) led to crashing of the release version
- if ( *pp1 < *pp2 )
- return -1;
- if ( *pp1 > *pp2 ) //
- return 1;
- return 0; //
-}
-
-/**Function*************************************************************
-
- Synopsis [Comparison procedure for two clauses.]
-
- Description []
-
- SideEffects []
-
- SeeAlso []
-
-***********************************************************************/
-static inline int Vec_StrSortCompare2( char * pp1, char * pp2 )
-{
- // for some reason commenting out lines (as shown) led to crashing of the release version
- if ( *pp1 > *pp2 )
- return -1;
- if ( *pp1 < *pp2 ) //
- return 1;
- return 0; //
-}
-
-/**Function*************************************************************
-
- Synopsis [Sorting the entries by their integer value.]
-
- Description []
-
- SideEffects []
-
- SeeAlso []
-
-***********************************************************************/
-static inline void Vec_StrSort( Vec_Str_t * p, int fReverse )
-{
- if ( fReverse )
- qsort( (void *)p->pArray, p->nSize, sizeof(char),
- (int (*)(const void *, const void *)) Vec_StrSortCompare2 );
- else
- qsort( (void *)p->pArray, p->nSize, sizeof(char),
- (int (*)(const void *, const void *)) Vec_StrSortCompare1 );
-}
-
-#endif
-
-////////////////////////////////////////////////////////////////////////
-/// END OF FILE ///
-////////////////////////////////////////////////////////////////////////
-
diff --git a/src/abc8/vec2/vecVec.h b/src/abc8/vec2/vecVec.h
deleted file mode 100644
index 55ffdf4f..00000000
--- a/src/abc8/vec2/vecVec.h
+++ /dev/null
@@ -1,356 +0,0 @@
-/**CFile****************************************************************
-
- FileName [vecVec.h]
-
- SystemName [ABC: Logic synthesis and verification system.]
-
- PackageName [Resizable arrays.]
-
- Synopsis [Resizable vector of resizable vectors.]
-
- Author [Alan Mishchenko]
-
- Affiliation [UC Berkeley]
-
- Date [Ver. 1.0. Started - June 20, 2005.]
-
- Revision [$Id: vecVec.h,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
-
-***********************************************************************/
-
-#ifndef __VEC_VEC_H__
-#define __VEC_VEC_H__
-
-////////////////////////////////////////////////////////////////////////
-/// INCLUDES ///
-////////////////////////////////////////////////////////////////////////
-
-#include <stdio.h>
-
-////////////////////////////////////////////////////////////////////////
-/// PARAMETERS ///
-////////////////////////////////////////////////////////////////////////
-
-////////////////////////////////////////////////////////////////////////
-/// BASIC TYPES ///
-////////////////////////////////////////////////////////////////////////
-
-typedef struct Vec_Vec_t_ Vec_Vec_t;
-struct Vec_Vec_t_
-{
- int nCap;
- int nSize;
- void ** pArray;
-};
-
-////////////////////////////////////////////////////////////////////////
-/// MACRO DEFINITIONS ///
-////////////////////////////////////////////////////////////////////////
-
-// iterators through levels
-#define Vec_VecForEachLevel( vGlob, vVec, i ) \
- for ( i = 0; (i < Vec_VecSize(vGlob)) && (((vVec) = (Vec_Ptr_t*)Vec_VecEntry(vGlob, i)), 1); i++ )
-#define Vec_VecForEachLevelStart( vGlob, vVec, i, LevelStart ) \
- for ( i = LevelStart; (i < Vec_VecSize(vGlob)) && (((vVec) = (Vec_Ptr_t*)Vec_VecEntry(vGlob, i)), 1); i++ )
-#define Vec_VecForEachLevelStartStop( vGlob, vVec, i, LevelStart, LevelStop ) \
- for ( i = LevelStart; (i <= LevelStop) && (((vVec) = (Vec_Ptr_t*)Vec_VecEntry(vGlob, i)), 1); i++ )
-#define Vec_VecForEachLevelReverse( vGlob, vVec, i ) \
- for ( i = Vec_VecSize(vGlob) - 1; (i >= 0) && (((vVec) = (Vec_Ptr_t*)Vec_VecEntry(vGlob, i)), 1); i-- )
-#define Vec_VecForEachLevelReverseStartStop( vGlob, vVec, i, LevelStart, LevelStop ) \
- for ( i = LevelStart; (i >= LevelStop) && (((vVec) = (Vec_Ptr_t*)Vec_VecEntry(vGlob, i)), 1); i-- )
-
-// iteratores through entries
-#define Vec_VecForEachEntry( vGlob, pEntry, i, k ) \
- for ( i = 0; i < Vec_VecSize(vGlob); i++ ) \
- Vec_PtrForEachEntry( Vec_VecEntry(vGlob, i), pEntry, k )
-#define Vec_VecForEachEntryLevel( vGlob, pEntry, i, Level ) \
- Vec_PtrForEachEntry( Vec_VecEntry(vGlob, Level), pEntry, i )
-#define Vec_VecForEachEntryStart( vGlob, pEntry, i, k, LevelStart ) \
- for ( i = LevelStart; i < Vec_VecSize(vGlob); i++ ) \
- Vec_PtrForEachEntry( Vec_VecEntry(vGlob, i), pEntry, k )
-#define Vec_VecForEachEntryStartStop( vGlob, pEntry, i, k, LevelStart, LevelStop ) \
- for ( i = LevelStart; i <= LevelStop; i++ ) \
- Vec_PtrForEachEntry( Vec_VecEntry(vGlob, i), pEntry, k )
-#define Vec_VecForEachEntryReverse( vGlob, pEntry, i, k ) \
- for ( i = 0; i < Vec_VecSize(vGlob); i++ ) \
- Vec_PtrForEachEntryReverse( Vec_VecEntry(vGlob, i), pEntry, k )
-#define Vec_VecForEachEntryReverseReverse( vGlob, pEntry, i, k ) \
- for ( i = Vec_VecSize(vGlob) - 1; i >= 0; i-- ) \
- Vec_PtrForEachEntryReverse( Vec_VecEntry(vGlob, i), pEntry, k )
-#define Vec_VecForEachEntryReverseStart( vGlob, pEntry, i, k, LevelStart ) \
- for ( i = LevelStart; i >= 0; i-- ) \
- Vec_PtrForEachEntry( Vec_VecEntry(vGlob, i), pEntry, k )
-
-////////////////////////////////////////////////////////////////////////
-/// FUNCTION DEFINITIONS ///
-////////////////////////////////////////////////////////////////////////
-
-/**Function*************************************************************
-
- Synopsis [Allocates a vector with the given capacity.]
-
- Description []
-
- SideEffects []
-
- SeeAlso []
-
-***********************************************************************/
-static inline Vec_Vec_t * Vec_VecAlloc( int nCap )
-{
- Vec_Vec_t * p;
- p = ALLOC( Vec_Vec_t, 1 );
- if ( nCap > 0 && nCap < 8 )
- nCap = 8;
- p->nSize = 0;
- p->nCap = nCap;
- p->pArray = p->nCap? ALLOC( void *, p->nCap ) : NULL;
- return p;
-}
-
-/**Function*************************************************************
-
- Synopsis [Allocates a vector with the given capacity.]
-
- Description []
-
- SideEffects []
-
- SeeAlso []
-
-***********************************************************************/
-static inline Vec_Vec_t * Vec_VecStart( int nSize )
-{
- Vec_Vec_t * p;
- int i;
- p = Vec_VecAlloc( nSize );
- for ( i = 0; i < nSize; i++ )
- p->pArray[i] = Vec_PtrAlloc( 0 );
- p->nSize = nSize;
- return p;
-}
-
-/**Function*************************************************************
-
- Synopsis [Allocates a vector with the given capacity.]
-
- Description []
-
- SideEffects []
-
- SeeAlso []
-
-***********************************************************************/
-static inline void Vec_VecExpand( Vec_Vec_t * p, int Level )
-{
- int i;
- if ( p->nSize >= Level + 1 )
- return;
- Vec_PtrGrow( (Vec_Ptr_t *)p, Level + 1 );
- for ( i = p->nSize; i <= Level; i++ )
- p->pArray[i] = Vec_PtrAlloc( 0 );
- p->nSize = Level + 1;
-}
-
-/**Function*************************************************************
-
- Synopsis []
-
- Description []
-
- SideEffects []
-
- SeeAlso []
-
-***********************************************************************/
-static inline int Vec_VecSize( Vec_Vec_t * p )
-{
- return p->nSize;
-}
-
-/**Function*************************************************************
-
- Synopsis []
-
- Description []
-
- SideEffects []
-
- SeeAlso []
-
-***********************************************************************/
-static inline void * Vec_VecEntry( Vec_Vec_t * p, int i )
-{
- assert( i >= 0 && i < p->nSize );
- return p->pArray[i];
-}
-
-/**Function*************************************************************
-
- Synopsis [Frees the vector.]
-
- Description []
-
- SideEffects []
-
- SeeAlso []
-
-***********************************************************************/
-static inline void Vec_VecFree( Vec_Vec_t * p )
-{
- Vec_Ptr_t * vVec;
- int i;
- Vec_VecForEachLevel( p, vVec, i )
- Vec_PtrFree( vVec );
- Vec_PtrFree( (Vec_Ptr_t *)p );
-}
-
-/**Function*************************************************************
-
- Synopsis [Frees the vector of vectors.]
-
- Description []
-
- SideEffects []
-
- SeeAlso []
-
-***********************************************************************/
-static inline int Vec_VecSizeSize( Vec_Vec_t * p )
-{
- Vec_Ptr_t * vVec;
- int i, Counter = 0;
- Vec_VecForEachLevel( p, vVec, i )
- Counter += vVec->nSize;
- return Counter;
-}
-
-/**Function*************************************************************
-
- Synopsis []
-
- Description []
-
- SideEffects []
-
- SeeAlso []
-
-***********************************************************************/
-static inline void Vec_VecClear( Vec_Vec_t * p )
-{
- Vec_Ptr_t * vVec;
- int i;
- Vec_VecForEachLevel( p, vVec, i )
- Vec_PtrClear( vVec );
-}
-
-/**Function*************************************************************
-
- Synopsis []
-
- Description []
-
- SideEffects []
-
- SeeAlso []
-
-***********************************************************************/
-static inline void Vec_VecPush( Vec_Vec_t * p, int Level, void * Entry )
-{
- if ( p->nSize < Level + 1 )
- {
- int i;
- Vec_PtrGrow( (Vec_Ptr_t *)p, Level + 1 );
- for ( i = p->nSize; i < Level + 1; i++ )
- p->pArray[i] = Vec_PtrAlloc( 0 );
- p->nSize = Level + 1;
- }
- Vec_PtrPush( (Vec_Ptr_t*)p->pArray[Level], Entry );
-}
-
-/**Function*************************************************************
-
- Synopsis []
-
- Description []
-
- SideEffects []
-
- SeeAlso []
-
-***********************************************************************/
-static inline void Vec_VecPushUnique( Vec_Vec_t * p, int Level, void * Entry )
-{
- if ( p->nSize < Level + 1 )
- Vec_VecPush( p, Level, Entry );
- else
- Vec_PtrPushUnique( (Vec_Ptr_t*)p->pArray[Level], Entry );
-}
-
-/**Function*************************************************************
-
- Synopsis [Comparison procedure for two arrays.]
-
- Description []
-
- SideEffects []
-
- SeeAlso []
-
-***********************************************************************/
-static inline int Vec_VecSortCompare1( Vec_Ptr_t ** pp1, Vec_Ptr_t ** pp2 )
-{
- if ( Vec_PtrSize(*pp1) < Vec_PtrSize(*pp2) )
- return -1;
- if ( Vec_PtrSize(*pp1) > Vec_PtrSize(*pp2) )
- return 1;
- return 0;
-}
-
-/**Function*************************************************************
-
- Synopsis [Comparison procedure for two integers.]
-
- Description []
-
- SideEffects []
-
- SeeAlso []
-
-***********************************************************************/
-static inline int Vec_VecSortCompare2( Vec_Ptr_t ** pp1, Vec_Ptr_t ** pp2 )
-{
- if ( Vec_PtrSize(*pp1) > Vec_PtrSize(*pp2) )
- return -1;
- if ( Vec_PtrSize(*pp1) < Vec_PtrSize(*pp2) )
- return 1;
- return 0;
-}
-
-/**Function*************************************************************
-
- Synopsis [Sorting the entries by their integer value.]
-
- Description []
-
- SideEffects []
-
- SeeAlso []
-
-***********************************************************************/
-static inline void Vec_VecSort( Vec_Vec_t * p, int fReverse )
-{
- if ( fReverse )
- qsort( (void *)p->pArray, p->nSize, sizeof(void *),
- (int (*)(const void *, const void *)) Vec_VecSortCompare2 );
- else
- qsort( (void *)p->pArray, p->nSize, sizeof(void *),
- (int (*)(const void *, const void *)) Vec_VecSortCompare1 );
-}
-
-#endif
-
-////////////////////////////////////////////////////////////////////////
-/// END OF FILE ///
-////////////////////////////////////////////////////////////////////////
-
diff --git a/src/abc8/aig/aig.h b/src/aig/aig/aig.h
index 31e347ca..5bff39f7 100644
--- a/src/abc8/aig/aig.h
+++ b/src/aig/aig/aig.h
@@ -35,7 +35,7 @@ extern "C" {
#include <assert.h>
#include <time.h>
-#include "vec2.h"
+#include "vec.h"
////////////////////////////////////////////////////////////////////////
/// PARAMETERS ///
diff --git a/src/abc8/aig/aigCheck.c b/src/aig/aig/aigCheck.c
index 8c53e635..8c53e635 100644
--- a/src/abc8/aig/aigCheck.c
+++ b/src/aig/aig/aigCheck.c
diff --git a/src/abc8/aig/aigCuts.c b/src/aig/aig/aigCuts.c
index 494d0d5b..494d0d5b 100644
--- a/src/abc8/aig/aigCuts.c
+++ b/src/aig/aig/aigCuts.c
diff --git a/src/abc8/aig/aigDfs.c b/src/aig/aig/aigDfs.c
index c7488487..c7488487 100644
--- a/src/abc8/aig/aigDfs.c
+++ b/src/aig/aig/aigDfs.c
diff --git a/src/abc8/aig/aigFanout.c b/src/aig/aig/aigFanout.c
index d0beb128..d0beb128 100644
--- a/src/abc8/aig/aigFanout.c
+++ b/src/aig/aig/aigFanout.c
diff --git a/src/abc8/aig/aigFrames.c b/src/aig/aig/aigFrames.c
index 4a3b0c7c..4a3b0c7c 100644
--- a/src/abc8/aig/aigFrames.c
+++ b/src/aig/aig/aigFrames.c
diff --git a/src/abc8/aig/aigHaig.c b/src/aig/aig/aigHaig.c
index eaf9fd05..eaf9fd05 100644
--- a/src/abc8/aig/aigHaig.c
+++ b/src/aig/aig/aigHaig.c
diff --git a/src/abc8/aig/aigInter.c b/src/aig/aig/aigInter.c
index b3bc28b2..b3bc28b2 100644
--- a/src/abc8/aig/aigInter.c
+++ b/src/aig/aig/aigInter.c
diff --git a/src/abc8/aig/aigMan.c b/src/aig/aig/aigMan.c
index da6fb9ba..1388c73e 100644
--- a/src/abc8/aig/aigMan.c
+++ b/src/aig/aig/aigMan.c
@@ -19,7 +19,7 @@
***********************************************************************/
#include "aig.h"
-//#include "tim.h"
+#include "tim.h"
////////////////////////////////////////////////////////////////////////
/// DECLARATIONS ///
@@ -277,8 +277,8 @@ void Aig_ManStop( Aig_Man_t * p )
if ( p->time1 ) { PRT( "time1", p->time1 ); }
if ( p->time2 ) { PRT( "time2", p->time2 ); }
// delete timing
-// if ( p->pManTime )
-// Tim_ManStop( p->pManTime );
+ if ( p->pManTime )
+ Tim_ManStop( p->pManTime );
// delete fanout
if ( p->pFanData )
Aig_ManFanoutStop( p );
diff --git a/src/abc8/aig/aigMem.c b/src/aig/aig/aigMem.c
index dab90777..dab90777 100644
--- a/src/abc8/aig/aigMem.c
+++ b/src/aig/aig/aigMem.c
diff --git a/src/abc8/aig/aigMffc.c b/src/aig/aig/aigMffc.c
index 47ce896d..47ce896d 100644
--- a/src/abc8/aig/aigMffc.c
+++ b/src/aig/aig/aigMffc.c
diff --git a/src/abc8/aig/aigObj.c b/src/aig/aig/aigObj.c
index 80838e19..80838e19 100644
--- a/src/abc8/aig/aigObj.c
+++ b/src/aig/aig/aigObj.c
diff --git a/src/abc8/aig/aigOper.c b/src/aig/aig/aigOper.c
index c19f551e..c19f551e 100644
--- a/src/abc8/aig/aigOper.c
+++ b/src/aig/aig/aigOper.c
diff --git a/src/abc8/aig/aigOrder.c b/src/aig/aig/aigOrder.c
index 62aeca6e..62aeca6e 100644
--- a/src/abc8/aig/aigOrder.c
+++ b/src/aig/aig/aigOrder.c
diff --git a/src/abc8/aig/aigPart.c b/src/aig/aig/aigPart.c
index de13653c..de13653c 100644
--- a/src/abc8/aig/aigPart.c
+++ b/src/aig/aig/aigPart.c
diff --git a/src/abc8/aig/aigRepr.c b/src/aig/aig/aigRepr.c
index 5ee6c9af..5ee6c9af 100644
--- a/src/abc8/aig/aigRepr.c
+++ b/src/aig/aig/aigRepr.c
diff --git a/src/abc8/aig/aigRet.c b/src/aig/aig/aigRet.c
index d1784b1b..d1784b1b 100644
--- a/src/abc8/aig/aigRet.c
+++ b/src/aig/aig/aigRet.c
diff --git a/src/abc8/aig/aigRetF.c b/src/aig/aig/aigRetF.c
index 8ca4fba1..8ca4fba1 100644
--- a/src/abc8/aig/aigRetF.c
+++ b/src/aig/aig/aigRetF.c
diff --git a/src/abc8/aig/aigScl.c b/src/aig/aig/aigScl.c
index 9721dd17..9721dd17 100644
--- a/src/abc8/aig/aigScl.c
+++ b/src/aig/aig/aigScl.c
diff --git a/src/abc8/aig/aigSeq.c b/src/aig/aig/aigSeq.c
index daafeab1..daafeab1 100644
--- a/src/abc8/aig/aigSeq.c
+++ b/src/aig/aig/aigSeq.c
diff --git a/src/abc8/aig/aigShow.c b/src/aig/aig/aigShow.c
index 96b0e37f..96b0e37f 100644
--- a/src/abc8/aig/aigShow.c
+++ b/src/aig/aig/aigShow.c
diff --git a/src/abc8/aig/aigTable.c b/src/aig/aig/aigTable.c
index 357b63c3..357b63c3 100644
--- a/src/abc8/aig/aigTable.c
+++ b/src/aig/aig/aigTable.c
diff --git a/src/abc8/aig/aigTiming.c b/src/aig/aig/aigTiming.c
index de8fdc7c..de8fdc7c 100644
--- a/src/abc8/aig/aigTiming.c
+++ b/src/aig/aig/aigTiming.c
diff --git a/src/abc8/aig/aigTruth.c b/src/aig/aig/aigTruth.c
index a92f9e1d..a92f9e1d 100644
--- a/src/abc8/aig/aigTruth.c
+++ b/src/aig/aig/aigTruth.c
diff --git a/src/abc8/aig/aigTsim.c b/src/aig/aig/aigTsim.c
index a8a3dda8..a8a3dda8 100644
--- a/src/abc8/aig/aigTsim.c
+++ b/src/aig/aig/aigTsim.c
diff --git a/src/abc8/aig/aigUtil.c b/src/aig/aig/aigUtil.c
index f6f34de9..f6f34de9 100644
--- a/src/abc8/aig/aigUtil.c
+++ b/src/aig/aig/aigUtil.c
diff --git a/src/abc8/aig/aigWin.c b/src/aig/aig/aigWin.c
index 0485b243..0485b243 100644
--- a/src/abc8/aig/aigWin.c
+++ b/src/aig/aig/aigWin.c
diff --git a/src/abc8/aig/aig_.c b/src/aig/aig/aig_.c
index b2313d35..b2313d35 100644
--- a/src/abc8/aig/aig_.c
+++ b/src/aig/aig/aig_.c
diff --git a/src/abc8/aig/module.make b/src/aig/aig/module.make
index 4b81834f..67040e2c 100644
--- a/src/abc8/aig/module.make
+++ b/src/aig/aig/module.make
@@ -1,8 +1,10 @@
SRC += src/aig/aig/aigCheck.c \
+ src/aig/aig/aigCuts.c \
src/aig/aig/aigDfs.c \
src/aig/aig/aigFanout.c \
src/aig/aig/aigFrames.c \
src/aig/aig/aigHaig.c \
+ src/aig/aig/aigInter.c \
src/aig/aig/aigMan.c \
src/aig/aig/aigMem.c \
src/aig/aig/aigMffc.c \
@@ -15,6 +17,7 @@ SRC += src/aig/aig/aigCheck.c \
src/aig/aig/aigRetF.c \
src/aig/aig/aigScl.c \
src/aig/aig/aigSeq.c \
+ src/aig/aig/aigShow.c \
src/aig/aig/aigTable.c \
src/aig/aig/aigTiming.c \
src/aig/aig/aigTruth.c \
diff --git a/src/aig/bar/bar.c b/src/aig/bar/bar.c
new file mode 100644
index 00000000..8c215b48
--- /dev/null
+++ b/src/aig/bar/bar.c
@@ -0,0 +1,177 @@
+/**CFile****************************************************************
+
+ FileName [bar.c]
+
+ SystemName [ABC: Logic synthesis and verification system.]
+
+ PackageName [extra]
+
+ Synopsis [Progress bar.]
+
+ Author [Alan Mishchenko]
+
+ Affiliation [UC Berkeley]
+
+ Date [Ver. 1.0. Started - June 20, 2005.]
+
+ Revision [$Id: bar.c,v 1.0 2003/02/01 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include "bar.h"
+
+////////////////////////////////////////////////////////////////////////
+/// DECLARATIONS ///
+////////////////////////////////////////////////////////////////////////
+
+struct Bar_Progress_t_
+{
+ int nItemsNext; // the number of items for the next update of the progress bar
+ int nItemsTotal; // the total number of items
+ int posTotal; // the total number of positions
+ int posCur; // the current position
+ FILE * pFile; // the output stream
+};
+
+static void Bar_ProgressShow( Bar_Progress_t * p, char * pString );
+static void Bar_ProgressClean( Bar_Progress_t * p );
+
+////////////////////////////////////////////////////////////////////////
+/// FUNCTION DEFINITIONS ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+ Synopsis [Starts the progress bar.]
+
+ Description [The first parameter is the output stream (pFile), where
+ the progress is printed. The current printing position should be the
+ first one on the given line. The second parameters is the total
+ number of items that correspond to 100% position of the progress bar.]
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Bar_Progress_t * Bar_ProgressStart( FILE * pFile, int nItemsTotal )
+{
+ Bar_Progress_t * p;
+// extern int Abc_FrameShowProgress( void * p );
+// extern void * Abc_FrameGetGlobalFrame();
+// if ( !Abc_FrameShowProgress(Abc_FrameGetGlobalFrame()) ) return NULL;
+ p = (Bar_Progress_t *) malloc(sizeof(Bar_Progress_t));
+ memset( p, 0, sizeof(Bar_Progress_t) );
+ p->pFile = pFile;
+ p->nItemsTotal = nItemsTotal;
+ p->posTotal = 78;
+ p->posCur = 1;
+ p->nItemsNext = (int)((7.0+p->posCur)*p->nItemsTotal/p->posTotal);
+ Bar_ProgressShow( p, NULL );
+ return p;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Updates the progress bar.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Bar_ProgressUpdate_int( Bar_Progress_t * p, int nItemsCur, char * pString )
+{
+ if ( p == NULL ) return;
+ if ( nItemsCur < p->nItemsNext )
+ return;
+ if ( nItemsCur >= p->nItemsTotal )
+ {
+ p->posCur = 78;
+ p->nItemsNext = 0x7FFFFFFF;
+ }
+ else
+ {
+ p->posCur += 7;
+ p->nItemsNext = (int)((7.0+p->posCur)*p->nItemsTotal/p->posTotal);
+ }
+ Bar_ProgressShow( p, pString );
+}
+
+
+/**Function*************************************************************
+
+ Synopsis [Stops the progress bar.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Bar_ProgressStop( Bar_Progress_t * p )
+{
+ if ( p == NULL ) return;
+ Bar_ProgressClean( p );
+ free( p );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Prints the progress bar of the given size.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Bar_ProgressShow( Bar_Progress_t * p, char * pString )
+{
+ int i;
+ if ( p == NULL ) return;
+ if ( pString )
+ fprintf( p->pFile, "%s ", pString );
+ for ( i = (pString? strlen(pString) + 1 : 0); i < p->posCur; i++ )
+ fprintf( p->pFile, "-" );
+ if ( i == p->posCur )
+ fprintf( p->pFile, ">" );
+ for ( i++ ; i <= p->posTotal; i++ )
+ fprintf( p->pFile, " " );
+ fprintf( p->pFile, "\r" );
+ fflush( stdout );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Cleans the progress bar before quitting.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Bar_ProgressClean( Bar_Progress_t * p )
+{
+ int i;
+ if ( p == NULL ) return;
+ for ( i = 0; i <= p->posTotal; i++ )
+ fprintf( p->pFile, " " );
+ fprintf( p->pFile, "\r" );
+ fflush( stdout );
+}
+
+////////////////////////////////////////////////////////////////////////
+/// END OF FILE ///
+////////////////////////////////////////////////////////////////////////
+
+
diff --git a/src/aig/bar/bar.h b/src/aig/bar/bar.h
new file mode 100644
index 00000000..814fbe6f
--- /dev/null
+++ b/src/aig/bar/bar.h
@@ -0,0 +1,74 @@
+/**CFile****************************************************************
+
+ FileName [bar.h]
+
+ SystemName [ABC: Logic synthesis and verification system.]
+
+ PackageName [Progress bar.]
+
+ Synopsis [External declarations.]
+
+ Author [Alan Mishchenko]
+
+ Affiliation [UC Berkeley]
+
+ Date [Ver. 1.0. Started - June 20, 2005.]
+
+ Revision [$Id: bar.h,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#ifndef __BAR_H__
+#define __BAR_H__
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#ifdef _WIN32
+#define inline __inline // compatible with MS VS 6.0
+#endif
+
+////////////////////////////////////////////////////////////////////////
+/// INCLUDES ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+/// PARAMETERS ///
+////////////////////////////////////////////////////////////////////////
+
+#define BAR_PROGRESS_USE 1
+
+////////////////////////////////////////////////////////////////////////
+/// BASIC TYPES ///
+////////////////////////////////////////////////////////////////////////
+
+typedef struct Bar_Progress_t_ Bar_Progress_t;
+
+////////////////////////////////////////////////////////////////////////
+/// MACRO DEFINITIONS ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+/// FUNCTION DECLARATIONS ///
+////////////////////////////////////////////////////////////////////////
+
+/*=== bar.c ==========================================================*/
+extern Bar_Progress_t * Bar_ProgressStart( FILE * pFile, int nItemsTotal );
+extern void Bar_ProgressStop( Bar_Progress_t * p );
+extern void Bar_ProgressUpdate_int( Bar_Progress_t * p, int nItemsCur, char * pString );
+
+static inline void Bar_ProgressUpdate( Bar_Progress_t * p, int nItemsCur, char * pString ) {
+ if ( BAR_PROGRESS_USE && p && (nItemsCur < *((int*)p)) ) return; Bar_ProgressUpdate_int(p, nItemsCur, pString); }
+
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
+
+////////////////////////////////////////////////////////////////////////
+/// END OF FILE ///
+////////////////////////////////////////////////////////////////////////
+
diff --git a/src/aig/bar/module.make b/src/aig/bar/module.make
new file mode 100644
index 00000000..26161ba1
--- /dev/null
+++ b/src/aig/bar/module.make
@@ -0,0 +1 @@
+SRC += src/aig/bar/bar.c
diff --git a/src/aig/bdc/bdc.h b/src/aig/bdc/bdc.h
new file mode 100644
index 00000000..71875edb
--- /dev/null
+++ b/src/aig/bdc/bdc.h
@@ -0,0 +1,73 @@
+/**CFile****************************************************************
+
+ FileName [bdc.h]
+
+ SystemName [ABC: Logic synthesis and verification system.]
+
+ PackageName [Truth-table-based bi-decomposition engine.]
+
+ Synopsis [External declarations.]
+
+ Author [Alan Mishchenko]
+
+ Affiliation [UC Berkeley]
+
+ Date [Ver. 1.0. Started - January 30, 2007.]
+
+ Revision [$Id: bdc.h,v 1.00 2007/01/30 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#ifndef __BDC_H__
+#define __BDC_H__
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+////////////////////////////////////////////////////////////////////////
+/// INCLUDES ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+/// PARAMETERS ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+/// BASIC TYPES ///
+////////////////////////////////////////////////////////////////////////
+
+typedef struct Bdc_Man_t_ Bdc_Man_t;
+typedef struct Bdc_Par_t_ Bdc_Par_t;
+struct Bdc_Par_t_
+{
+ // general parameters
+ int nVarsMax; // the maximum support
+ int fVerbose; // enable basic stats
+ int fVeryVerbose; // enable detailed stats
+};
+
+////////////////////////////////////////////////////////////////////////
+/// MACRO DEFINITIONS ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+/// FUNCTION DECLARATIONS ///
+////////////////////////////////////////////////////////////////////////
+
+/*=== bdcCore.c ==========================================================*/
+extern Bdc_Man_t * Bdc_ManAlloc( Bdc_Par_t * pPars );
+extern void Bdc_ManFree( Bdc_Man_t * p );
+extern int Bdc_ManDecompose( Bdc_Man_t * p, unsigned * puFunc, unsigned * puCare, int nVars, Vec_Ptr_t * vDivs, int nNodesLimit );
+
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
+
+////////////////////////////////////////////////////////////////////////
+/// END OF FILE ///
+////////////////////////////////////////////////////////////////////////
+
diff --git a/src/aig/bdc/bdcCore.c b/src/aig/bdc/bdcCore.c
new file mode 100644
index 00000000..157927b1
--- /dev/null
+++ b/src/aig/bdc/bdcCore.c
@@ -0,0 +1,189 @@
+/**CFile****************************************************************
+
+ FileName [bdcCore.c]
+
+ SystemName [ABC: Logic synthesis and verification system.]
+
+ PackageName [Truth-table-based bi-decomposition engine.]
+
+ Synopsis [The gateway to bi-decomposition.]
+
+ Author [Alan Mishchenko]
+
+ Affiliation [UC Berkeley]
+
+ Date [Ver. 1.0. Started - January 30, 2007.]
+
+ Revision [$Id: bdcCore.c,v 1.00 2007/01/30 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "bdcInt.h"
+
+////////////////////////////////////////////////////////////////////////
+/// DECLARATIONS ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+/// FUNCTION DEFINITIONS ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+ Synopsis [Allocate resynthesis manager.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Bdc_Man_t * Bdc_ManAlloc( Bdc_Par_t * pPars )
+{
+ Bdc_Man_t * p;
+ unsigned * pData;
+ int i, k, nBits;
+ p = ALLOC( Bdc_Man_t, 1 );
+ memset( p, 0, sizeof(Bdc_Man_t) );
+ assert( pPars->nVarsMax > 3 && pPars->nVarsMax < 16 );
+ p->pPars = pPars;
+ p->nWords = Kit_TruthWordNum( pPars->nVarsMax );
+ p->nDivsLimit = 200;
+ p->nNodesLimit = 0; // will be set later
+ // memory
+ p->vMemory = Vec_IntStart( 1 << 16 );
+ // internal nodes
+ p->nNodesAlloc = 512;
+ p->pNodes = ALLOC( Bdc_Fun_t, p->nNodesAlloc );
+ // set up hash table
+ p->nTableSize = (1 << p->pPars->nVarsMax);
+ p->pTable = ALLOC( Bdc_Fun_t *, p->nTableSize );
+ memset( p->pTable, 0, sizeof(Bdc_Fun_t *) * p->nTableSize );
+ p->vSpots = Vec_IntAlloc( 256 );
+ // truth tables
+ p->vTruths = Vec_PtrAllocSimInfo( pPars->nVarsMax + 5, p->nWords );
+ // set elementary truth tables
+ nBits = (1 << pPars->nVarsMax);
+ Kit_TruthFill( Vec_PtrEntry(p->vTruths, 0), p->nVars );
+ for ( k = 0; k < pPars->nVarsMax; k++ )
+ {
+ pData = Vec_PtrEntry( p->vTruths, k+1 );
+ Kit_TruthClear( pData, p->nVars );
+ for ( i = 0; i < nBits; i++ )
+ if ( i & (1 << k) )
+ pData[i>>5] |= (1 << (i&31));
+ }
+ p->puTemp1 = Vec_PtrEntry( p->vTruths, pPars->nVarsMax + 1 );
+ p->puTemp2 = Vec_PtrEntry( p->vTruths, pPars->nVarsMax + 2 );
+ p->puTemp3 = Vec_PtrEntry( p->vTruths, pPars->nVarsMax + 3 );
+ p->puTemp4 = Vec_PtrEntry( p->vTruths, pPars->nVarsMax + 4 );
+ // start the internal ISFs
+ p->pIsfOL = &p->IsfOL; Bdc_IsfStart( p, p->pIsfOL );
+ p->pIsfOR = &p->IsfOR; Bdc_IsfStart( p, p->pIsfOR );
+ p->pIsfAL = &p->IsfAL; Bdc_IsfStart( p, p->pIsfAL );
+ p->pIsfAR = &p->IsfAR; Bdc_IsfStart( p, p->pIsfAR );
+ return p;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Deallocate resynthesis manager.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Bdc_ManFree( Bdc_Man_t * p )
+{
+ Vec_IntFree( p->vMemory );
+ Vec_IntFree( p->vSpots );
+ Vec_PtrFree( p->vTruths );
+ free( p->pNodes );
+ free( p->pTable );
+ free( p );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Clears the manager.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Bdc_ManPrepare( Bdc_Man_t * p, Vec_Ptr_t * vDivs )
+{
+ unsigned * puTruth;
+ Bdc_Fun_t * pNode;
+ int i;
+ Bdc_TableClear( p );
+ Vec_IntClear( p->vMemory );
+ // add constant 1 and elementary vars
+ p->nNodes = p->nNodesNew = 0;
+ for ( i = 0; i <= p->pPars->nVarsMax; i++ )
+ {
+ pNode = Bdc_FunNew( p );
+ pNode->Type = BDC_TYPE_PI;
+ pNode->puFunc = Vec_PtrEntry( p->vTruths, i );
+ pNode->uSupp = i? (1 << (i-1)) : 0;
+ Bdc_TableAdd( p, pNode );
+ }
+ // add the divisors
+ Vec_PtrForEachEntry( vDivs, puTruth, i )
+ {
+ pNode = Bdc_FunNew( p );
+ pNode->Type = BDC_TYPE_PI;
+ pNode->puFunc = puTruth;
+ pNode->uSupp = Kit_TruthSupport( puTruth, p->nVars );
+ Bdc_TableAdd( p, pNode );
+ if ( i == p->nDivsLimit )
+ break;
+ }
+}
+
+/**Function*************************************************************
+
+ Synopsis [Performs decomposition of one function.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Bdc_ManDecompose( Bdc_Man_t * p, unsigned * puFunc, unsigned * puCare, int nVars, Vec_Ptr_t * vDivs, int nNodesMax )
+{
+ Bdc_Isf_t Isf, * pIsf = &Isf;
+ // set current manager parameters
+ p->nVars = nVars;
+ p->nWords = Kit_TruthWordNum( nVars );
+ Bdc_ManPrepare( p, vDivs );
+ p->nNodesLimit = (p->nNodes + nNodesMax < p->nNodesAlloc)? p->nNodes + nNodesMax : p->nNodesAlloc;
+ // copy the function
+ Bdc_IsfStart( p, pIsf );
+ Bdc_IsfClean( pIsf );
+ pIsf->uSupp = Kit_TruthSupport( puFunc, p->nVars ) | Kit_TruthSupport( puCare, p->nVars );
+ Kit_TruthAnd( pIsf->puOn, puCare, puFunc, p->nVars );
+ Kit_TruthSharp( pIsf->puOff, puCare, puFunc, p->nVars );
+ // call decomposition
+ Bdc_SuppMinimize( p, pIsf );
+ p->pRoot = Bdc_ManDecompose_rec( p, pIsf );
+ if ( p->pRoot == NULL )
+ return -1;
+ return p->nNodesNew;
+}
+
+
+////////////////////////////////////////////////////////////////////////
+/// END OF FILE ///
+////////////////////////////////////////////////////////////////////////
+
+
diff --git a/src/aig/bdc/bdcDec.c b/src/aig/bdc/bdcDec.c
new file mode 100644
index 00000000..747fcb14
--- /dev/null
+++ b/src/aig/bdc/bdcDec.c
@@ -0,0 +1,461 @@
+/**CFile****************************************************************
+
+ FileName [bdcDec.c]
+
+ SystemName [ABC: Logic synthesis and verification system.]
+
+ PackageName [Truth-table-based bi-decomposition engine.]
+
+ Synopsis [Decomposition procedures.]
+
+ Author [Alan Mishchenko]
+
+ Affiliation [UC Berkeley]
+
+ Date [Ver. 1.0. Started - January 30, 2007.]
+
+ Revision [$Id: bdcDec.c,v 1.00 2007/01/30 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "bdcInt.h"
+
+////////////////////////////////////////////////////////////////////////
+/// DECLARATIONS ///
+////////////////////////////////////////////////////////////////////////
+
+static Bdc_Type_t Bdc_DecomposeStep( Bdc_Man_t * p, Bdc_Isf_t * pIsf, Bdc_Isf_t * pIsfL, Bdc_Isf_t * pIsfR );
+static int Bdc_DecomposeUpdateRight( Bdc_Man_t * p, Bdc_Isf_t * pIsf, Bdc_Isf_t * pIsfL, Bdc_Isf_t * pIsfR, unsigned * puTruth, Bdc_Type_t Type );
+
+////////////////////////////////////////////////////////////////////////
+/// FUNCTION DEFINITIONS ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+ Synopsis [Performs one step of bi-decomposition.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Bdc_Fun_t * Bdc_ManDecompose_rec( Bdc_Man_t * p, Bdc_Isf_t * pIsf )
+{
+ Bdc_Fun_t * pFunc;
+ Bdc_Isf_t IsfL, * pIsfL = &IsfL;
+ Bdc_Isf_t IsfB, * pIsfR = &IsfB;
+ // check computed results
+ if ( pFunc = Bdc_TableLookup( p, pIsf ) )
+ return pFunc;
+ // decide on the decomposition type
+ pFunc = Bdc_FunNew( p );
+ if ( pFunc == NULL )
+ return NULL;
+ pFunc->Type = Bdc_DecomposeStep( p, pIsf, pIsfL, pIsfR );
+ // decompose the left branch
+ pFunc->pFan0 = Bdc_ManDecompose_rec( p, pIsfL );
+ if ( pFunc->pFan0 == NULL )
+ return NULL;
+ // decompose the right branch
+ if ( Bdc_DecomposeUpdateRight( p, pIsf, pIsfL, pIsfR, pFunc->pFan0->puFunc, pFunc->Type ) )
+ {
+ p->nNodes--;
+ return pFunc->pFan0;
+ }
+ pFunc->pFan1 = Bdc_ManDecompose_rec( p, pIsfL );
+ if ( pFunc->pFan1 == NULL )
+ return NULL;
+ // compute the function of node
+ pFunc->puFunc = (unsigned *)Vec_IntFetch(p->vMemory, p->nWords);
+ if ( pFunc->Type == BDC_TYPE_AND )
+ Kit_TruthAnd( pFunc->puFunc, pFunc->pFan0->puFunc, pFunc->pFan1->puFunc, p->nVars );
+ else if ( pFunc->Type == BDC_TYPE_OR )
+ Kit_TruthOr( pFunc->puFunc, pFunc->pFan0->puFunc, pFunc->pFan1->puFunc, p->nVars );
+ else
+ assert( 0 );
+ // verify correctness
+ assert( Bdc_TableCheckContainment(p, pIsf, pFunc->puFunc) );
+ // convert from OR to AND
+ if ( pFunc->Type == BDC_TYPE_OR )
+ {
+ pFunc->Type = BDC_TYPE_AND;
+ pFunc->pFan0 = Bdc_Not(pFunc->pFan0);
+ pFunc->pFan1 = Bdc_Not(pFunc->pFan1);
+ Kit_TruthNot( pFunc->puFunc, pFunc->puFunc, p->nVars );
+ pFunc = Bdc_Not(pFunc);
+ }
+ Bdc_TableAdd( p, Bdc_Regular(pFunc) );
+ return pFunc;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Updates the ISF of the right after the left was decompoosed.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Bdc_DecomposeUpdateRight( Bdc_Man_t * p, Bdc_Isf_t * pIsf, Bdc_Isf_t * pIsfL, Bdc_Isf_t * pIsfR, unsigned * puTruth, Bdc_Type_t Type )
+{
+ if ( Type == BDC_TYPE_OR )
+ {
+// Right.Q = bdd_appex( Q, CompSpecLeftF, bddop_diff, setRightRes );
+// Right.R = bdd_exist( R, setRightRes );
+
+// if ( pR->Q ) Cudd_RecursiveDeref( dd, pR->Q );
+// if ( pR->R ) Cudd_RecursiveDeref( dd, pR->R );
+// pR->Q = Cudd_bddAndAbstract( dd, pF->Q, Cudd_Not(CompSpecF), pL->V ); Cudd_Ref( pR->Q );
+// pR->R = Cudd_bddExistAbstract( dd, pF->R, pL->V ); Cudd_Ref( pR->R );
+
+// assert( pR->R != b0 );
+// return (int)( pR->Q == b0 );
+
+ Kit_TruthSharp( pIsfR->puOn, pIsf->puOn, puTruth, p->nVars );
+ Kit_TruthExistSet( pIsfR->puOn, pIsfR->puOn, p->nVars, pIsfL->uSupp );
+ Kit_TruthExistSet( pIsfR->puOff, pIsf->puOff, p->nVars, pIsfL->uSupp );
+ assert( !Kit_TruthIsConst0(pIsfR->puOff, p->nVars) );
+ return Kit_TruthIsConst0(pIsfR->puOn, p->nVars);
+ }
+ else if ( Type == BDC_TYPE_AND )
+ {
+// Right.R = bdd_appex( R, CompSpecLeftF, bddop_and, setRightRes );
+// Right.Q = bdd_exist( Q, setRightRes );
+
+// if ( pR->Q ) Cudd_RecursiveDeref( dd, pR->Q );
+// if ( pR->R ) Cudd_RecursiveDeref( dd, pR->R );
+// pR->R = Cudd_bddAndAbstract( dd, pF->R, CompSpecF, pL->V ); Cudd_Ref( pR->R );
+// pR->Q = Cudd_bddExistAbstract( dd, pF->Q, pL->V ); Cudd_Ref( pR->Q );
+
+// assert( pR->Q != b0 );
+// return (int)( pR->R == b0 );
+
+ Kit_TruthSharp( pIsfR->puOn, pIsf->puOn, puTruth, p->nVars );
+ Kit_TruthExistSet( pIsfR->puOn, pIsfR->puOn, p->nVars, pIsfL->uSupp );
+ Kit_TruthExistSet( pIsfR->puOff, pIsf->puOff, p->nVars, pIsfL->uSupp );
+ assert( !Kit_TruthIsConst0(pIsfR->puOff, p->nVars) );
+ return Kit_TruthIsConst0(pIsfR->puOn, p->nVars);
+ }
+ return 0;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Checks existence of OR-bidecomposition.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+static inline int Bdc_DecomposeGetCost( Bdc_Man_t * p, int nLeftVars, int nRightVars )
+{
+ assert( nLeftVars > 0 );
+ assert( nRightVars > 0 );
+ // compute the decomposition coefficient
+ if ( nLeftVars >= nRightVars )
+ return BDC_SCALE * (p->nVars * nRightVars + nLeftVars);
+ else // if ( nLeftVars < nRightVars )
+ return BDC_SCALE * (p->nVars * nLeftVars + nRightVars);
+}
+
+/**Function*************************************************************
+
+ Synopsis [Checks existence of weak OR-bidecomposition.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Bdc_DecomposeFindInitialVarSet( Bdc_Man_t * p, Bdc_Isf_t * pIsf, Bdc_Isf_t * pIsfL, Bdc_Isf_t * pIsfR )
+{
+ char pVars[16];
+ int v, nVars, Beg, End;
+
+ assert( pIsfL->uSupp == 0 );
+ assert( pIsfR->uSupp == 0 );
+
+ // fill in the variables
+ nVars = 0;
+ for ( v = 0; v < p->nVars; v++ )
+ if ( pIsf->uSupp & (1 << v) )
+ pVars[nVars++] = v;
+
+ // try variable pairs
+ for ( Beg = 0; Beg < nVars; Beg++ )
+ {
+ Kit_TruthExistNew( p->puTemp1, pIsf->puOff, p->nVars, pVars[Beg] );
+ for ( End = nVars - 1; End > Beg; End-- )
+ {
+ Kit_TruthExistNew( p->puTemp2, pIsf->puOff, p->nVars, pVars[End] );
+ if ( Kit_TruthIsDisjoint3(pIsf->puOn, p->puTemp1, p->puTemp2, p->nVars) )
+ {
+ pIsfL->uSupp = (1 << Beg);
+ pIsfR->uSupp = (1 << End);
+ pIsfL->Var = Beg;
+ pIsfR->Var = End;
+ return 1;
+ }
+ }
+ }
+ return 0;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Checks existence of weak OR-bidecomposition.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Bdc_DecomposeWeakOr( Bdc_Man_t * p, Bdc_Isf_t * pIsf, Bdc_Isf_t * pIsfL, Bdc_Isf_t * pIsfR )
+{
+ int v, VarCost, VarBest, Cost, VarCostBest = 0;
+
+ for ( v = 0; v < p->nVars; v++ )
+ {
+ Kit_TruthExistNew( p->puTemp1, pIsf->puOff, p->nVars, v );
+// if ( (Q & !bdd_exist( R, VarSetXa )) != bddfalse )
+// Exist = Cudd_bddExistAbstract( dd, pF->R, Var ); Cudd_Ref( Exist );
+// if ( Cudd_bddIteConstant( dd, pF->Q, Cudd_Not(Exist), b0 ) != b0 )
+ if ( !Kit_TruthIsImply( pIsf->puOn, p->puTemp1, p->nVars ) )
+ {
+ // measure the cost of this variable
+// VarCost = bdd_satcountset( bdd_forall( Q, VarSetXa ), VarCube );
+
+// Univ = Cudd_bddUnivAbstract( dd, pF->Q, Var ); Cudd_Ref( Univ );
+// VarCost = Kit_TruthCountOnes( Univ, p->nVars );
+// Cudd_RecursiveDeref( dd, Univ );
+
+ Kit_TruthForallNew( p->puTemp2, pIsf->puOn, p->nVars, v );
+ VarCost = Kit_TruthCountOnes( p->puTemp2, p->nVars );
+ if ( VarCost == 0 )
+ VarCost = 1;
+ if ( VarCostBest < VarCost )
+ {
+ VarCostBest = VarCost;
+ VarBest = v;
+ }
+ }
+ }
+
+ // derive the components for weak-bi-decomposition if the variable is found
+ if ( VarCostBest )
+ {
+// funQLeftRes = Q & bdd_exist( R, setRightORweak );
+
+// Temp = Cudd_bddExistAbstract( dd, pF->R, VarBest ); Cudd_Ref( Temp );
+// pL->Q = Cudd_bddAnd( dd, pF->Q, Temp ); Cudd_Ref( pL->Q );
+// Cudd_RecursiveDeref( dd, Temp );
+
+ Kit_TruthExistNew( p->puTemp1, pIsf->puOff, p->nVars, VarBest );
+ Kit_TruthAnd( pIsfL->puOn, pIsf->puOn, p->puTemp1, p->nVars );
+
+// pL->R = pF->R; Cudd_Ref( pL->R );
+// pL->V = VarBest; Cudd_Ref( pL->V );
+ Kit_TruthCopy( pIsfL->puOff, pIsf->puOff, p->nVars );
+ pIsfL->Var = VarBest;
+
+// assert( pL->Q != b0 );
+// assert( pL->R != b0 );
+// assert( Cudd_bddIteConstant( dd, pL->Q, pL->R, b0 ) == b0 );
+
+ // express cost in percents of the covered boolean space
+ Cost = VarCostBest * BDC_SCALE / (1<<p->nVars);
+ if ( Cost == 0 )
+ Cost = 1;
+ return Cost;
+ }
+ return 0;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Checks existence of OR-bidecomposition.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Bdc_DecomposeOr( Bdc_Man_t * p, Bdc_Isf_t * pIsf, Bdc_Isf_t * pIsfL, Bdc_Isf_t * pIsfR )
+{
+ unsigned uSuppRem;
+ int v, nLeftVars = 1, nRightVars = 1;
+ // clean the var sets
+ Bdc_IsfClean( pIsfL );
+ Bdc_IsfClean( pIsfR );
+ // find initial variable sets
+ if ( !Bdc_DecomposeFindInitialVarSet( p, pIsf, pIsfL, pIsfR ) )
+ return Bdc_DecomposeWeakOr( p, pIsf, pIsfL, pIsfR );
+ // prequantify the variables in the offset
+ Kit_TruthExistNew( p->puTemp1, pIsf->puOff, p->nVars, pIsfL->Var );
+ Kit_TruthExistNew( p->puTemp2, pIsf->puOff, p->nVars, pIsfR->Var );
+ // go through the remaining variables
+ uSuppRem = pIsf->uSupp & ~pIsfL->uSupp & ~pIsfR->uSupp;
+ assert( Kit_WordCountOnes(uSuppRem) > 0 );
+ for ( v = 0; v < p->nVars; v++ )
+ {
+ if ( (uSuppRem & (1 << v)) == 0 )
+ continue;
+ // prequantify this variable
+ Kit_TruthExistNew( p->puTemp3, p->puTemp1, p->nVars, v );
+ Kit_TruthExistNew( p->puTemp4, p->puTemp2, p->nVars, v );
+ if ( nLeftVars < nRightVars )
+ {
+// if ( (Q & bdd_exist( pF->R, pL->V & VarNew ) & bdd_exist( pF->R, pR->V )) == bddfalse )
+// if ( VerifyORCondition( dd, pF->Q, pF->R, pL->V, pR->V, VarNew ) )
+ if ( Kit_TruthIsDisjoint3(pIsf->puOn, p->puTemp3, p->puTemp2, p->nVars) )
+ {
+// pL->V &= VarNew;
+ pIsfL->uSupp |= (1 << v);
+ nLeftVars++;
+ }
+// else if ( (Q & bdd_exist( pF->R, pR->V & VarNew ) & bdd_exist( pF->R, pL->V )) == bddfalse )
+ else if ( Kit_TruthIsDisjoint3(pIsf->puOn, p->puTemp4, p->puTemp1, p->nVars) )
+ {
+// pR->V &= VarNew;
+ pIsfR->uSupp |= (1 << v);
+ nRightVars++;
+ }
+ }
+ else
+ {
+// if ( (Q & bdd_exist( pF->R, pR->V & VarNew ) & bdd_exist( pF->R, pL->V )) == bddfalse )
+ if ( Kit_TruthIsDisjoint3(pIsf->puOn, p->puTemp4, p->puTemp1, p->nVars) )
+ {
+// pR->V &= VarNew;
+ pIsfR->uSupp |= (1 << v);
+ nRightVars++;
+ }
+// else if ( (Q & bdd_exist( pF->R, pL->V & VarNew ) & bdd_exist( pF->R, pR->V )) == bddfalse )
+ else if ( Kit_TruthIsDisjoint3(pIsf->puOn, p->puTemp3, p->puTemp2, p->nVars) )
+ {
+// pL->V &= VarNew;
+ pIsfL->uSupp |= (1 << v);
+ nLeftVars++;
+ }
+ }
+ }
+
+ // derive the functions Q and R for the left branch
+// pL->Q = bdd_appex( pF->Q, bdd_exist( pF->R, pL->V ), bddop_and, pR->V );
+// pL->R = bdd_exist( pF->R, pR->V );
+
+// Temp = Cudd_bddExistAbstract( dd, pF->R, pL->V ); Cudd_Ref( Temp );
+// pL->Q = Cudd_bddAndAbstract( dd, pF->Q, Temp, pR->V ); Cudd_Ref( pL->Q );
+// Cudd_RecursiveDeref( dd, Temp );
+// pL->R = Cudd_bddExistAbstract( dd, pF->R, pR->V ); Cudd_Ref( pL->R );
+
+ Kit_TruthAnd( pIsfL->puOn, pIsf->puOn, p->puTemp1, p->nVars );
+ Kit_TruthExistSet( pIsfL->puOn, pIsfL->puOn, p->nVars, pIsfR->uSupp );
+ Kit_TruthCopy( pIsfL->puOff, p->puTemp2, p->nVars );
+
+ // derive the functions Q and R for the right branch
+// Temp = Cudd_bddExistAbstract( dd, pF->R, pR->V ); Cudd_Ref( Temp );
+// pR->Q = Cudd_bddAndAbstract( dd, pF->Q, Temp, pL->V ); Cudd_Ref( pR->Q );
+// Cudd_RecursiveDeref( dd, Temp );
+// pR->R = Cudd_bddExistAbstract( dd, pF->R, pL->V ); Cudd_Ref( pR->R );
+
+/*
+ Kit_TruthAnd( pIsfR->puOn, pIsf->puOn, p->puTemp2, p->nVars );
+ Kit_TruthExistSet( pIsfR->puOn, pIsfR->puOn, p->nVars, pIsfL->uSupp );
+ Kit_TruthCopy( pIsfR->puOff, p->puTemp1, p->nVars );
+*/
+
+// assert( pL->Q != b0 );
+// assert( pL->R != b0 );
+// assert( Cudd_bddIteConstant( dd, pL->Q, pL->R, b0 ) == b0 );
+ assert( !Kit_TruthIsConst0(pIsfL->puOn, p->nVars) );
+ assert( !Kit_TruthIsConst0(pIsfL->puOff, p->nVars) );
+ assert( Kit_TruthIsDisjoint(pIsfL->puOn, pIsfL->puOff, p->nVars) );
+
+ return Bdc_DecomposeGetCost( p, nLeftVars, nRightVars );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Performs one step of bi-decomposition.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Bdc_Type_t Bdc_DecomposeStep( Bdc_Man_t * p, Bdc_Isf_t * pIsf, Bdc_Isf_t * pIsfL, Bdc_Isf_t * pIsfR )
+{
+ int CostOr, CostAnd, CostOrL, CostOrR, CostAndL, CostAndR;
+
+ Bdc_IsfClean( p->pIsfOL );
+ Bdc_IsfClean( p->pIsfOR );
+ Bdc_IsfClean( p->pIsfAL );
+ Bdc_IsfClean( p->pIsfAR );
+
+ // perform OR decomposition
+ CostOr = Bdc_DecomposeOr( p, pIsf, p->pIsfOL, p->pIsfOR );
+
+ // perform AND decomposition
+ Bdc_IsfNot( pIsf );
+ CostAnd = Bdc_DecomposeOr( p, pIsf, p->pIsfAL, p->pIsfAR );
+ Bdc_IsfNot( pIsf );
+ Bdc_IsfNot( p->pIsfAL );
+ Bdc_IsfNot( p->pIsfAR );
+
+ // check the hash table
+ Bdc_SuppMinimize( p, p->pIsfOL );
+ CostOrL = (Bdc_TableLookup(p, p->pIsfOL) != NULL);
+ Bdc_SuppMinimize( p, p->pIsfOR );
+ CostOrR = (Bdc_TableLookup(p, p->pIsfOR) != NULL);
+ Bdc_SuppMinimize( p, p->pIsfAL );
+ CostAndL = (Bdc_TableLookup(p, p->pIsfAL) != NULL);
+ Bdc_SuppMinimize( p, p->pIsfAR );
+ CostAndR = (Bdc_TableLookup(p, p->pIsfAR) != NULL);
+
+ // check if there is any reuse for the components
+ if ( CostOrL + CostOrR < CostAndL + CostAndR )
+ {
+ Bdc_IsfCopy( pIsfL, p->pIsfOL );
+ Bdc_IsfCopy( pIsfR, p->pIsfOR );
+ return BDC_TYPE_OR;
+ }
+ if ( CostOrL + CostOrR > CostAndL + CostAndR )
+ {
+ Bdc_IsfCopy( pIsfL, p->pIsfAL );
+ Bdc_IsfCopy( pIsfR, p->pIsfAR );
+ return BDC_TYPE_AND;
+ }
+
+ // compare the two-component costs
+ if ( CostOr < CostAnd )
+ {
+ Bdc_IsfCopy( pIsfL, p->pIsfOL );
+ Bdc_IsfCopy( pIsfR, p->pIsfOR );
+ return BDC_TYPE_OR;
+ }
+ return BDC_TYPE_AND;
+}
+
+////////////////////////////////////////////////////////////////////////
+/// END OF FILE ///
+////////////////////////////////////////////////////////////////////////
+
+
diff --git a/src/aig/bdc/bdcInt.h b/src/aig/bdc/bdcInt.h
new file mode 100644
index 00000000..9649f870
--- /dev/null
+++ b/src/aig/bdc/bdcInt.h
@@ -0,0 +1,150 @@
+/**CFile****************************************************************
+
+ FileName [bdcInt.h]
+
+ SystemName [ABC: Logic synthesis and verification system.]
+
+ PackageName [Truth-table-based bi-decomposition engine.]
+
+ Synopsis [Internal declarations.]
+
+ Author [Alan Mishchenko]
+
+ Affiliation [UC Berkeley]
+
+ Date [Ver. 1.0. Started - January 15, 2007.]
+
+ Revision [$Id: resInt.h,v 1.00 2007/01/15 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#ifndef __BDC_INT_H__
+#define __BDC_INT_H__
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+////////////////////////////////////////////////////////////////////////
+/// INCLUDES ///
+////////////////////////////////////////////////////////////////////////
+
+#include "kit.h"
+#include "bdc.h"
+
+////////////////////////////////////////////////////////////////////////
+/// PARAMETERS ///
+////////////////////////////////////////////////////////////////////////
+
+#define BDC_SCALE 100 // value used to compute the cost
+
+////////////////////////////////////////////////////////////////////////
+/// BASIC TYPES ///
+////////////////////////////////////////////////////////////////////////
+
+// network types
+typedef enum {
+ BDC_TYPE_NONE = 0, // 0: unknown
+ BDC_TYPE_CONST1, // 1: constant 1
+ BDC_TYPE_PI, // 2: primary input
+ BDC_TYPE_AND, // 4: AND-gate
+ BDC_TYPE_OR, // 5: OR-gate (temporary)
+ BDC_TYPE_XOR, // 6: XOR-gate
+ BDC_TYPE_MUX, // 7: MUX-gate
+ BDC_TYPE_OTHER // 8: unused
+} Bdc_Type_t;
+
+typedef struct Bdc_Fun_t_ Bdc_Fun_t;
+struct Bdc_Fun_t_
+{
+ int Type; // Const1, PI, AND, XOR, MUX
+ Bdc_Fun_t * pFan0; // fanin of the given node
+ Bdc_Fun_t * pFan1; // fanin of the given node
+ Bdc_Fun_t * pFan2; // fanin of the given node
+ unsigned uSupp; // bit mask of current support
+ unsigned * puFunc; // the function of the node
+ Bdc_Fun_t * pNext; // next function with same support
+ void * pCopy; // the copy field
+};
+
+typedef struct Bdc_Isf_t_ Bdc_Isf_t;
+struct Bdc_Isf_t_
+{
+ int Var; // the first variable assigned
+ unsigned uSupp; // the current support
+ unsigned * puOn; // on-set
+ unsigned * puOff; // off-set
+};
+
+struct Bdc_Man_t_
+{
+ // external parameters
+ Bdc_Par_t * pPars; // parameter set
+ int nVars; // the number of variables
+ int nWords; // the number of words
+ int nNodesLimit; // the limit on the number of new nodes
+ int nDivsLimit; // the limit on the number of divisors
+ // internal nodes
+ Bdc_Fun_t * pNodes; // storage for decomposition nodes
+ int nNodes; // the number of nodes used
+ int nNodesNew; // the number of nodes used
+ int nNodesAlloc; // the number of nodes allocated
+ Bdc_Fun_t * pRoot; // the root node
+ // resub candidates
+ Bdc_Fun_t ** pTable; // hash table of candidates
+ int nTableSize; // hash table size (1 << nVarsMax)
+ Vec_Int_t * vSpots; // the occupied spots in the table
+ // elementary truth tables
+ Vec_Ptr_t * vTruths; // for const 1 and elementary variables
+ unsigned * puTemp1; // temporary truth table
+ unsigned * puTemp2; // temporary truth table
+ unsigned * puTemp3; // temporary truth table
+ unsigned * puTemp4; // temporary truth table
+ // temporary ISFs
+ Bdc_Isf_t * pIsfOL, IsfOL;
+ Bdc_Isf_t * pIsfOR, IsfOR;
+ Bdc_Isf_t * pIsfAL, IsfAL;
+ Bdc_Isf_t * pIsfAR, IsfAR;
+ // internal memory manager
+ Vec_Int_t * vMemory; // memory for internal truth tables
+};
+
+// working with complemented attributes of objects
+static inline int Bdc_IsComplement( Bdc_Fun_t * p ) { return (int)((unsigned long)p & (unsigned long)01); }
+static inline Bdc_Fun_t * Bdc_Regular( Bdc_Fun_t * p ) { return (Bdc_Fun_t *)((unsigned long)p & ~(unsigned long)01); }
+static inline Bdc_Fun_t * Bdc_Not( Bdc_Fun_t * p ) { return (Bdc_Fun_t *)((unsigned long)p ^ (unsigned long)01); }
+static inline Bdc_Fun_t * Bdc_NotCond( Bdc_Fun_t * p, int c ) { return (Bdc_Fun_t *)((unsigned long)p ^ (unsigned long)(c!=0)); }
+
+static inline Bdc_Fun_t * Bdc_FunNew( Bdc_Man_t * p ) { Bdc_Fun_t * pRes; if ( p->nNodes == p->nNodesLimit ) return NULL; pRes = p->pNodes + p->nNodes++; memset( pRes, 0, sizeof(Bdc_Fun_t) ); p->nNodesNew++; return pRes; }
+static inline void Bdc_IsfStart( Bdc_Man_t * p, Bdc_Isf_t * pF ) { pF->puOn = Vec_IntFetch( p->vMemory, p->nWords ); pF->puOff = Vec_IntFetch( p->vMemory, p->nWords ); }
+static inline void Bdc_IsfClean( Bdc_Isf_t * p ) { p->uSupp = 0; p->Var = 0; }
+static inline void Bdc_IsfCopy( Bdc_Isf_t * p, Bdc_Isf_t * q ) { Bdc_Isf_t T = *p; *p = *q; *q = T; }
+static inline void Bdc_IsfNot( Bdc_Isf_t * p ) { unsigned * puT = p->puOn; p->puOn = p->puOff; p->puOff = puT; }
+
+////////////////////////////////////////////////////////////////////////
+/// MACRO DEFINITIONS ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+/// FUNCTION DECLARATIONS ///
+////////////////////////////////////////////////////////////////////////
+
+/*=== bdcDec.c ==========================================================*/
+extern Bdc_Fun_t * Bdc_ManDecompose_rec( Bdc_Man_t * p, Bdc_Isf_t * pIsf );
+/*=== bdcTable.c ==========================================================*/
+extern Bdc_Fun_t * Bdc_TableLookup( Bdc_Man_t * p, Bdc_Isf_t * pIsf );
+extern void Bdc_TableAdd( Bdc_Man_t * p, Bdc_Fun_t * pFunc );
+extern void Bdc_TableClear( Bdc_Man_t * p );
+extern void Bdc_SuppMinimize( Bdc_Man_t * p, Bdc_Isf_t * pIsf );
+extern int Bdc_TableCheckContainment( Bdc_Man_t * p, Bdc_Isf_t * pIsf, unsigned * puTruth );
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
+
+////////////////////////////////////////////////////////////////////////
+/// END OF FILE ///
+////////////////////////////////////////////////////////////////////////
+
diff --git a/src/aig/bdc/bdcTable.c b/src/aig/bdc/bdcTable.c
new file mode 100644
index 00000000..d86a938d
--- /dev/null
+++ b/src/aig/bdc/bdcTable.c
@@ -0,0 +1,140 @@
+/**CFile****************************************************************
+
+ FileName [bdcTable.c]
+
+ SystemName [ABC: Logic synthesis and verification system.]
+
+ PackageName [Truth-table-based bi-decomposition engine.]
+
+ Synopsis [Hash table for intermediate nodes.]
+
+ Author [Alan Mishchenko]
+
+ Affiliation [UC Berkeley]
+
+ Date [Ver. 1.0. Started - January 30, 2007.]
+
+ Revision [$Id: bdcTable.c,v 1.00 2007/01/30 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "bdcInt.h"
+
+////////////////////////////////////////////////////////////////////////
+/// DECLARATIONS ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+/// FUNCTION DEFINITIONS ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+ Synopsis [Minimizes the support of the ISF.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Bdc_SuppMinimize( Bdc_Man_t * p, Bdc_Isf_t * pIsf )
+{
+ int v;
+ // go through the support variables
+ for ( v = 0; v < p->nVars; v++ )
+ {
+ if ( (pIsf->uSupp & (1 << v)) == 0 )
+ continue;
+ Kit_TruthExistNew( p->puTemp1, pIsf->puOn, p->nVars, v );
+ Kit_TruthExistNew( p->puTemp2, pIsf->puOff, p->nVars, v );
+ if ( !Kit_TruthIsDisjoint( p->puTemp1, p->puTemp2, p->nVars ) )
+ continue;
+ // remove the variable
+ Kit_TruthCopy( pIsf->puOn, p->puTemp1, p->nVars );
+ Kit_TruthCopy( pIsf->puOff, p->puTemp2, p->nVars );
+ pIsf->uSupp &= ~(1 << v);
+ }
+}
+
+/**Function*************************************************************
+
+ Synopsis [Checks containment of the function in the ISF.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Bdc_TableCheckContainment( Bdc_Man_t * p, Bdc_Isf_t * pIsf, unsigned * puTruth )
+{
+ return Kit_TruthIsImply( pIsf->puOn, puTruth, p->nVars ) &&
+ Kit_TruthIsDisjoint( pIsf->puOff, puTruth, p->nVars );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Adds the new entry to the hash table.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Bdc_Fun_t * Bdc_TableLookup( Bdc_Man_t * p, Bdc_Isf_t * pIsf )
+{
+ Bdc_Fun_t * pFunc;
+ for ( pFunc = p->pTable[pIsf->uSupp]; pFunc; pFunc = pFunc->pNext )
+ if ( Bdc_TableCheckContainment( p, pIsf, pFunc->puFunc ) )
+ return pFunc;
+ return NULL;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Adds the new entry to the hash table.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Bdc_TableAdd( Bdc_Man_t * p, Bdc_Fun_t * pFunc )
+{
+ if ( p->pTable[pFunc->uSupp] == NULL )
+ Vec_IntPush( p->vSpots, pFunc->uSupp );
+ pFunc->pNext = p->pTable[pFunc->uSupp];
+ p->pTable[pFunc->uSupp] = pFunc;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Adds the new entry to the hash table.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Bdc_TableClear( Bdc_Man_t * p )
+{
+ int Spot, i;
+ Vec_IntForEachEntry( p->vSpots, Spot, i )
+ p->pTable[Spot] = NULL;
+ Vec_IntClear( p->vSpots );
+}
+
+////////////////////////////////////////////////////////////////////////
+/// END OF FILE ///
+////////////////////////////////////////////////////////////////////////
+
+
diff --git a/src/aig/bdc/bdc_.c b/src/aig/bdc/bdc_.c
new file mode 100644
index 00000000..9d0a9462
--- /dev/null
+++ b/src/aig/bdc/bdc_.c
@@ -0,0 +1,49 @@
+/**CFile****************************************************************
+
+ FileName [bdc_.c]
+
+ SystemName [ABC: Logic synthesis and verification system.]
+
+ PackageName [Truth-table-based bi-decomposition engine.]
+
+ Synopsis []
+
+ Author [Alan Mishchenko]
+
+ Affiliation [UC Berkeley]
+
+ Date [Ver. 1.0. Started - January 30, 2007.]
+
+ Revision [$Id: bdc_.c,v 1.00 2007/01/30 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "bdcInt.h"
+
+////////////////////////////////////////////////////////////////////////
+/// DECLARATIONS ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+/// FUNCTION DEFINITIONS ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+
+
+
+////////////////////////////////////////////////////////////////////////
+/// END OF FILE ///
+////////////////////////////////////////////////////////////////////////
+
+
diff --git a/src/aig/bdc/module.make b/src/aig/bdc/module.make
new file mode 100644
index 00000000..8697c998
--- /dev/null
+++ b/src/aig/bdc/module.make
@@ -0,0 +1,4 @@
+SRC += src/aig/bdc/bdcCore.c \
+ src/aig/bdc/bdcDec.c \
+ src/aig/bdc/bdcTable.c
+
diff --git a/src/abc8/cnf/cnf.h b/src/aig/cnf/cnf.h
index 5f31ef37..5726469f 100644
--- a/src/abc8/cnf/cnf.h
+++ b/src/aig/cnf/cnf.h
@@ -35,7 +35,7 @@ extern "C" {
#include <assert.h>
#include <time.h>
-#include "vec2.h"
+#include "vec.h"
#include "aig.h"
#include "darInt.h"
diff --git a/src/abc8/cnf/cnfCore.c b/src/aig/cnf/cnfCore.c
index e1d62de0..e1d62de0 100644
--- a/src/abc8/cnf/cnfCore.c
+++ b/src/aig/cnf/cnfCore.c
diff --git a/src/abc8/cnf/cnfCut.c b/src/aig/cnf/cnfCut.c
index 17ab0c78..17ab0c78 100644
--- a/src/abc8/cnf/cnfCut.c
+++ b/src/aig/cnf/cnfCut.c
diff --git a/src/abc8/cnf/cnfData.c b/src/aig/cnf/cnfData.c
index 01f6ff8a..01f6ff8a 100644
--- a/src/abc8/cnf/cnfData.c
+++ b/src/aig/cnf/cnfData.c
diff --git a/src/abc8/cnf/cnfMan.c b/src/aig/cnf/cnfMan.c
index 47bc0b67..47bc0b67 100644
--- a/src/abc8/cnf/cnfMan.c
+++ b/src/aig/cnf/cnfMan.c
diff --git a/src/abc8/cnf/cnfMap.c b/src/aig/cnf/cnfMap.c
index d966df15..d966df15 100644
--- a/src/abc8/cnf/cnfMap.c
+++ b/src/aig/cnf/cnfMap.c
diff --git a/src/abc8/cnf/cnfPost.c b/src/aig/cnf/cnfPost.c
index 988275b2..988275b2 100644
--- a/src/abc8/cnf/cnfPost.c
+++ b/src/aig/cnf/cnfPost.c
diff --git a/src/abc8/cnf/cnfUtil.c b/src/aig/cnf/cnfUtil.c
index cd47cb58..cd47cb58 100644
--- a/src/abc8/cnf/cnfUtil.c
+++ b/src/aig/cnf/cnfUtil.c
diff --git a/src/abc8/cnf/cnfWrite.c b/src/aig/cnf/cnfWrite.c
index 5a96f23f..5a96f23f 100644
--- a/src/abc8/cnf/cnfWrite.c
+++ b/src/aig/cnf/cnfWrite.c
diff --git a/src/abc8/cnf/cnf_.c b/src/aig/cnf/cnf_.c
index 7c9ca499..7c9ca499 100644
--- a/src/abc8/cnf/cnf_.c
+++ b/src/aig/cnf/cnf_.c
diff --git a/src/abc8/cnf/module.make b/src/aig/cnf/module.make
index dbcaeba4..dbcaeba4 100644
--- a/src/abc8/cnf/module.make
+++ b/src/aig/cnf/module.make
diff --git a/src/aig/csw/csw.h b/src/aig/csw/csw.h
new file mode 100644
index 00000000..1443f4d9
--- /dev/null
+++ b/src/aig/csw/csw.h
@@ -0,0 +1,65 @@
+/**CFile****************************************************************
+
+ FileName [csw.h]
+
+ SystemName [ABC: Logic synthesis and verification system.]
+
+ PackageName [Cut sweeping.]
+
+ Synopsis [External declarations.]
+
+ Author [Alan Mishchenko]
+
+ Affiliation [UC Berkeley]
+
+ Date [Ver. 1.0. Started - July 11, 2007.]
+
+ Revision [$Id: csw.h,v 1.00 2007/07/11 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#ifndef __CSW_H__
+#define __CSW_H__
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+////////////////////////////////////////////////////////////////////////
+/// INCLUDES ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+/// PARAMETERS ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+/// BASIC TYPES ///
+////////////////////////////////////////////////////////////////////////
+
+
+////////////////////////////////////////////////////////////////////////
+/// MACRO DEFINITIONS ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+/// ITERATORS ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+/// FUNCTION DECLARATIONS ///
+////////////////////////////////////////////////////////////////////////
+
+/*=== cnfCore.c ========================================================*/
+extern Aig_Man_t * Csw_Sweep( Aig_Man_t * pAig, int nCutsMax, int nLeafMax, int fVerbose );
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
+
+////////////////////////////////////////////////////////////////////////
+/// END OF FILE ///
+////////////////////////////////////////////////////////////////////////
+
diff --git a/src/aig/csw/cswCore.c b/src/aig/csw/cswCore.c
new file mode 100644
index 00000000..20893058
--- /dev/null
+++ b/src/aig/csw/cswCore.c
@@ -0,0 +1,94 @@
+/**CFile****************************************************************
+
+ FileName [cswCore.c]
+
+ SystemName [ABC: Logic synthesis and verification system.]
+
+ PackageName [Cut sweeping.]
+
+ Synopsis []
+
+ Author [Alan Mishchenko]
+
+ Affiliation [UC Berkeley]
+
+ Date [Ver. 1.0. Started - July 11, 2007.]
+
+ Revision [$Id: cswCore.c,v 1.00 2007/07/11 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "cswInt.h"
+
+////////////////////////////////////////////////////////////////////////
+/// DECLARATIONS ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+/// FUNCTION DEFINITIONS ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Aig_Man_t * Csw_Sweep( Aig_Man_t * pAig, int nCutsMax, int nLeafMax, int fVerbose )
+{
+ Csw_Man_t * p;
+ Aig_Man_t * pRes;
+ Aig_Obj_t * pObj, * pObjNew, * pObjRes;
+ int i, clk;
+clk = clock();
+ // start the manager
+ p = Csw_ManStart( pAig, nCutsMax, nLeafMax, fVerbose );
+ // set elementary cuts at the PIs
+ Aig_ManForEachPi( p->pManRes, pObj, i )
+ {
+ Csw_ObjPrepareCuts( p, pObj, 1 );
+ Csw_ObjAddRefs( p, pObj, Aig_ManPi(p->pManAig,i)->nRefs );
+ }
+ // process the nodes
+ Aig_ManForEachNode( pAig, pObj, i )
+ {
+ // create the new node
+ pObjNew = Aig_And( p->pManRes, Csw_ObjChild0Equiv(p, pObj), Csw_ObjChild1Equiv(p, pObj) );
+ // check if this node can be represented using another node
+// pObjRes = Csw_ObjSweep( p, Aig_Regular(pObjNew), pObj->nRefs > 1 );
+// pObjRes = Aig_NotCond( pObjRes, Aig_IsComplement(pObjNew) );
+ // try recursively if resubsitution is used
+ do {
+ pObjRes = Csw_ObjSweep( p, Aig_Regular(pObjNew), pObj->nRefs > 1 );
+ pObjRes = Aig_NotCond( pObjRes, Aig_IsComplement(pObjNew) );
+ pObjNew = pObjRes;
+ } while ( Csw_ObjCuts(p, Aig_Regular(pObjNew)) == NULL && !Aig_ObjIsConst1(Aig_Regular(pObjNew)) );
+ // save the resulting node
+ Csw_ObjSetEquiv( p, pObj, pObjRes );
+ // add to the reference counter
+ Csw_ObjAddRefs( p, Aig_Regular(pObjRes), pObj->nRefs );
+ }
+ // add the POs
+ Aig_ManForEachPo( pAig, pObj, i )
+ Aig_ObjCreatePo( p->pManRes, Csw_ObjChild0Equiv(p, pObj) );
+ // remove dangling nodes
+ Aig_ManCleanup( p->pManRes );
+ // return the resulting manager
+p->timeTotal = clock() - clk;
+p->timeOther = p->timeTotal - p->timeCuts - p->timeHash;
+ pRes = p->pManRes;
+ Csw_ManStop( p );
+ return pRes;
+}
+
+
+////////////////////////////////////////////////////////////////////////
+/// END OF FILE ///
+////////////////////////////////////////////////////////////////////////
+
+
diff --git a/src/aig/csw/cswCut.c b/src/aig/csw/cswCut.c
new file mode 100644
index 00000000..b3b7152b
--- /dev/null
+++ b/src/aig/csw/cswCut.c
@@ -0,0 +1,602 @@
+/**CFile****************************************************************
+
+ FileName [cswCut.c]
+
+ SystemName [ABC: Logic synthesis and verification system.]
+
+ PackageName [Cut sweeping.]
+
+ Synopsis []
+
+ Author [Alan Mishchenko]
+
+ Affiliation [UC Berkeley]
+
+ Date [Ver. 1.0. Started - July 11, 2007.]
+
+ Revision [$Id: cswCut.c,v 1.00 2007/07/11 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "cswInt.h"
+
+////////////////////////////////////////////////////////////////////////
+/// DECLARATIONS ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+/// FUNCTION DEFINITIONS ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+ Synopsis [Compute the cost of the cut.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+static inline int Csw_CutFindCost( Csw_Man_t * p, Csw_Cut_t * pCut )
+{
+ Aig_Obj_t * pLeaf;
+ int i, Cost = 0;
+ assert( pCut->nFanins > 0 );
+ Csw_CutForEachLeaf( p->pManRes, pCut, pLeaf, i )
+ {
+// Cost += pLeaf->nRefs;
+ Cost += Csw_ObjRefs( p, pLeaf );
+// printf( "%d ", pLeaf->nRefs );
+ }
+//printf( "\n" );
+ return Cost * 100 / pCut->nFanins;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Compute the cost of the cut.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+static inline float Csw_CutFindCost2( Csw_Man_t * p, Csw_Cut_t * pCut )
+{
+ Aig_Obj_t * pLeaf;
+ float Cost = 0.0;
+ int i;
+ assert( pCut->nFanins > 0 );
+ Csw_CutForEachLeaf( p->pManRes, pCut, pLeaf, i )
+ Cost += (float)1.0/pLeaf->nRefs;
+ return 1/Cost;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Returns the next free cut to use.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+static inline Csw_Cut_t * Csw_CutFindFree( Csw_Man_t * p, Aig_Obj_t * pObj )
+{
+ Csw_Cut_t * pCut, * pCutMax;
+ int i;
+ pCutMax = NULL;
+ Csw_ObjForEachCut( p, pObj, pCut, i )
+ {
+ if ( pCut->nFanins == 0 )
+ return pCut;
+ if ( pCutMax == NULL || pCutMax->Cost < pCut->Cost )
+ pCutMax = pCut;
+ }
+ assert( pCutMax != NULL );
+ pCutMax->nFanins = 0;
+ return pCutMax;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Computes the stretching phase of the cut w.r.t. the merged cut.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+static inline unsigned Cut_TruthPhase( Csw_Cut_t * pCut, Csw_Cut_t * pCut1 )
+{
+ unsigned uPhase = 0;
+ int i, k;
+ for ( i = k = 0; i < pCut->nFanins; i++ )
+ {
+ if ( k == pCut1->nFanins )
+ break;
+ if ( pCut->pFanins[i] < pCut1->pFanins[k] )
+ continue;
+ assert( pCut->pFanins[i] == pCut1->pFanins[k] );
+ uPhase |= (1 << i);
+ k++;
+ }
+ return uPhase;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Performs truth table computation.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+unsigned * Csw_CutComputeTruth( Csw_Man_t * p, Csw_Cut_t * pCut, Csw_Cut_t * pCut0, Csw_Cut_t * pCut1, int fCompl0, int fCompl1 )
+{
+ // permute the first table
+ if ( fCompl0 )
+ Kit_TruthNot( p->puTemp[0], Csw_CutTruth(pCut0), p->nLeafMax );
+ else
+ Kit_TruthCopy( p->puTemp[0], Csw_CutTruth(pCut0), p->nLeafMax );
+ Kit_TruthStretch( p->puTemp[2], p->puTemp[0], pCut0->nFanins, p->nLeafMax, Cut_TruthPhase(pCut, pCut0), 0 );
+ // permute the second table
+ if ( fCompl1 )
+ Kit_TruthNot( p->puTemp[1], Csw_CutTruth(pCut1), p->nLeafMax );
+ else
+ Kit_TruthCopy( p->puTemp[1], Csw_CutTruth(pCut1), p->nLeafMax );
+ Kit_TruthStretch( p->puTemp[3], p->puTemp[1], pCut1->nFanins, p->nLeafMax, Cut_TruthPhase(pCut, pCut1), 0 );
+ // produce the resulting table
+ Kit_TruthAnd( Csw_CutTruth(pCut), p->puTemp[2], p->puTemp[3], p->nLeafMax );
+// assert( pCut->nFanins >= Kit_TruthSupportSize( Csw_CutTruth(pCut), p->nLeafMax ) );
+ return Csw_CutTruth(pCut);
+}
+
+/**Function*************************************************************
+
+ Synopsis [Performs support minimization for the truth table.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Csw_CutSupportMinimize( Csw_Man_t * p, Csw_Cut_t * pCut )
+{
+ unsigned * pTruth;
+ int uSupp, nFansNew, i, k;
+ // get truth table
+ pTruth = Csw_CutTruth( pCut );
+ // get support
+ uSupp = Kit_TruthSupport( pTruth, p->nLeafMax );
+ // get the new support size
+ nFansNew = Kit_WordCountOnes( uSupp );
+ // check if there are redundant variables
+ if ( nFansNew == pCut->nFanins )
+ return nFansNew;
+ assert( nFansNew < pCut->nFanins );
+ // minimize support
+ Kit_TruthShrink( p->puTemp[0], pTruth, nFansNew, p->nLeafMax, uSupp, 1 );
+ for ( i = k = 0; i < pCut->nFanins; i++ )
+ if ( uSupp & (1 << i) )
+ pCut->pFanins[k++] = pCut->pFanins[i];
+ assert( k == nFansNew );
+ pCut->nFanins = nFansNew;
+// assert( nFansNew == Kit_TruthSupportSize( pTruth, p->nLeafMax ) );
+//Extra_PrintBinary( stdout, pTruth, (1<<p->nLeafMax) ); printf( "\n" );
+ return nFansNew;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Returns 1 if pDom is contained in pCut.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+static inline int Csw_CutCheckDominance( Csw_Cut_t * pDom, Csw_Cut_t * pCut )
+{
+ int i, k;
+ for ( i = 0; i < (int)pDom->nFanins; i++ )
+ {
+ for ( k = 0; k < (int)pCut->nFanins; k++ )
+ if ( pDom->pFanins[i] == pCut->pFanins[k] )
+ break;
+ if ( k == (int)pCut->nFanins ) // node i in pDom is not contained in pCut
+ return 0;
+ }
+ // every node in pDom is contained in pCut
+ return 1;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Returns 1 if the cut is contained.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Csw_CutFilter( Csw_Man_t * p, Aig_Obj_t * pObj, Csw_Cut_t * pCut )
+{
+ Csw_Cut_t * pTemp;
+ int i;
+ // go through the cuts of the node
+ Csw_ObjForEachCut( p, pObj, pTemp, i )
+ {
+ if ( pTemp->nFanins < 2 )
+ continue;
+ if ( pTemp == pCut )
+ continue;
+ if ( pTemp->nFanins > pCut->nFanins )
+ {
+ // skip the non-contained cuts
+ if ( (pTemp->uSign & pCut->uSign) != pCut->uSign )
+ continue;
+ // check containment seriously
+ if ( Csw_CutCheckDominance( pCut, pTemp ) )
+ {
+ // remove contained cut
+ pTemp->nFanins = 0;
+ }
+ }
+ else
+ {
+ // skip the non-contained cuts
+ if ( (pTemp->uSign & pCut->uSign) != pTemp->uSign )
+ continue;
+ // check containment seriously
+ if ( Csw_CutCheckDominance( pTemp, pCut ) )
+ {
+ // remove the given
+ pCut->nFanins = 0;
+ return 1;
+ }
+ }
+ }
+ return 0;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Merges two cuts.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+static inline int Csw_CutMergeOrdered( Csw_Man_t * p, Csw_Cut_t * pC0, Csw_Cut_t * pC1, Csw_Cut_t * pC )
+{
+ int i, k, c;
+ assert( pC0->nFanins >= pC1->nFanins );
+ // the case of the largest cut sizes
+ if ( pC0->nFanins == p->nLeafMax && pC1->nFanins == p->nLeafMax )
+ {
+ for ( i = 0; i < pC0->nFanins; i++ )
+ if ( pC0->pFanins[i] != pC1->pFanins[i] )
+ return 0;
+ for ( i = 0; i < pC0->nFanins; i++ )
+ pC->pFanins[i] = pC0->pFanins[i];
+ pC->nFanins = pC0->nFanins;
+ return 1;
+ }
+ // the case when one of the cuts is the largest
+ if ( pC0->nFanins == p->nLeafMax )
+ {
+ for ( i = 0; i < pC1->nFanins; i++ )
+ {
+ for ( k = pC0->nFanins - 1; k >= 0; k-- )
+ if ( pC0->pFanins[k] == pC1->pFanins[i] )
+ break;
+ if ( k == -1 ) // did not find
+ return 0;
+ }
+ for ( i = 0; i < pC0->nFanins; i++ )
+ pC->pFanins[i] = pC0->pFanins[i];
+ pC->nFanins = pC0->nFanins;
+ return 1;
+ }
+
+ // compare two cuts with different numbers
+ i = k = 0;
+ for ( c = 0; c < p->nLeafMax; c++ )
+ {
+ if ( k == pC1->nFanins )
+ {
+ if ( i == pC0->nFanins )
+ {
+ pC->nFanins = c;
+ return 1;
+ }
+ pC->pFanins[c] = pC0->pFanins[i++];
+ continue;
+ }
+ if ( i == pC0->nFanins )
+ {
+ if ( k == pC1->nFanins )
+ {
+ pC->nFanins = c;
+ return 1;
+ }
+ pC->pFanins[c] = pC1->pFanins[k++];
+ continue;
+ }
+ if ( pC0->pFanins[i] < pC1->pFanins[k] )
+ {
+ pC->pFanins[c] = pC0->pFanins[i++];
+ continue;
+ }
+ if ( pC0->pFanins[i] > pC1->pFanins[k] )
+ {
+ pC->pFanins[c] = pC1->pFanins[k++];
+ continue;
+ }
+ pC->pFanins[c] = pC0->pFanins[i++];
+ k++;
+ }
+ if ( i < pC0->nFanins || k < pC1->nFanins )
+ return 0;
+ pC->nFanins = c;
+ return 1;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Prepares the object for FPGA mapping.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Csw_CutMerge( Csw_Man_t * p, Csw_Cut_t * pCut0, Csw_Cut_t * pCut1, Csw_Cut_t * pCut )
+{
+ assert( p->nLeafMax > 0 );
+ // merge the nodes
+ if ( pCut0->nFanins < pCut1->nFanins )
+ {
+ if ( !Csw_CutMergeOrdered( p, pCut1, pCut0, pCut ) )
+ return 0;
+ }
+ else
+ {
+ if ( !Csw_CutMergeOrdered( p, pCut0, pCut1, pCut ) )
+ return 0;
+ }
+ pCut->uSign = pCut0->uSign | pCut1->uSign;
+ return 1;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Consider cut with more than 2 fanins having 2 true variables.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Aig_Obj_t * Csw_ObjTwoVarCut( Csw_Man_t * p, Csw_Cut_t * pCut )
+{
+ Aig_Obj_t * pRes, * pIn0, * pIn1;
+ int nVars, uTruth, fCompl = 0;
+ assert( pCut->nFanins > 2 );
+ // minimize support of this cut
+ nVars = Csw_CutSupportMinimize( p, pCut );
+ assert( nVars == 2 );
+ // get the fanins
+ pIn0 = Aig_ManObj( p->pManRes, pCut->pFanins[0] );
+ pIn1 = Aig_ManObj( p->pManRes, pCut->pFanins[1] );
+ // derive the truth table
+ uTruth = 0xF & *Csw_CutTruth(pCut);
+ if ( uTruth == 14 || uTruth == 13 || uTruth == 11 || uTruth == 7 )
+ {
+ uTruth = 0xF & ~uTruth;
+ fCompl = 1;
+ }
+ // compute the result
+ pRes = NULL;
+ if ( uTruth == 1 ) // 0001 // 1110 14
+ pRes = Aig_And( p->pManRes, Aig_Not(pIn0), Aig_Not(pIn1) );
+ if ( uTruth == 2 ) // 0010 // 1101 13
+ pRes = Aig_And( p->pManRes, pIn0 , Aig_Not(pIn1) );
+ if ( uTruth == 4 ) // 0100 // 1011 11
+ pRes = Aig_And( p->pManRes, Aig_Not(pIn0), pIn1 );
+ if ( uTruth == 8 ) // 1000 // 0111 7
+ pRes = Aig_And( p->pManRes, pIn0 , pIn1 );
+ if ( pRes )
+ pRes = Aig_NotCond( pRes, fCompl );
+ return pRes;
+}
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Csw_Cut_t * Csw_ObjPrepareCuts( Csw_Man_t * p, Aig_Obj_t * pObj, int fTriv )
+{
+ Csw_Cut_t * pCutSet, * pCut;
+ int i;
+ // create the cutset of the node
+ pCutSet = (Csw_Cut_t *)Aig_MmFixedEntryFetch( p->pMemCuts );
+ Csw_ObjSetCuts( p, pObj, pCutSet );
+ Csw_ObjForEachCut( p, pObj, pCut, i )
+ {
+ pCut->nFanins = 0;
+ pCut->iNode = pObj->Id;
+ pCut->nCutSize = p->nCutSize;
+ pCut->nLeafMax = p->nLeafMax;
+ }
+ // add unit cut if needed
+ if ( fTriv )
+ {
+ pCut = pCutSet;
+ pCut->Cost = 0;
+ pCut->iNode = pObj->Id;
+ pCut->nFanins = 1;
+ pCut->pFanins[0] = pObj->Id;
+ pCut->uSign = Aig_ObjCutSign( pObj->Id );
+ memset( Csw_CutTruth(pCut), 0xAA, sizeof(unsigned) * p->nTruthWords );
+ }
+ return pCutSet;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Derives cuts for one node and sweeps this node.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Aig_Obj_t * Csw_ObjSweep( Csw_Man_t * p, Aig_Obj_t * pObj, int fTriv )
+{
+ int fUseResub = 1;
+ Csw_Cut_t * pCut0, * pCut1, * pCut, * pCutSet;
+ Aig_Obj_t * pFanin0 = Aig_ObjFanin0(pObj);
+ Aig_Obj_t * pFanin1 = Aig_ObjFanin1(pObj);
+ Aig_Obj_t * pObjNew;
+ unsigned * pTruth;
+ int i, k, nVars, nFanins, iVar, clk;
+
+ assert( !Aig_IsComplement(pObj) );
+ if ( !Aig_ObjIsNode(pObj) )
+ return pObj;
+ if ( Csw_ObjCuts(p, pObj) )
+ return pObj;
+ // the node is not processed yet
+ assert( Csw_ObjCuts(p, pObj) == NULL );
+ assert( Aig_ObjIsNode(pObj) );
+
+ // set up the first cut
+ pCutSet = Csw_ObjPrepareCuts( p, pObj, fTriv );
+
+ // compute pair-wise cut combinations while checking table
+ Csw_ObjForEachCut( p, pFanin0, pCut0, i )
+ if ( pCut0->nFanins > 0 )
+ Csw_ObjForEachCut( p, pFanin1, pCut1, k )
+ if ( pCut1->nFanins > 0 )
+ {
+ // make sure K-feasible cut exists
+ if ( Kit_WordCountOnes(pCut0->uSign | pCut1->uSign) > p->nLeafMax )
+ continue;
+ // get the next cut of this node
+ pCut = Csw_CutFindFree( p, pObj );
+clk = clock();
+ // assemble the new cut
+ if ( !Csw_CutMerge( p, pCut0, pCut1, pCut ) )
+ {
+ assert( pCut->nFanins == 0 );
+ continue;
+ }
+ // check containment
+ if ( Csw_CutFilter( p, pObj, pCut ) )
+ {
+ assert( pCut->nFanins == 0 );
+ continue;
+ }
+ // create its truth table
+ pTruth = Csw_CutComputeTruth( p, pCut, pCut0, pCut1, Aig_ObjFaninC0(pObj), Aig_ObjFaninC1(pObj) );
+ // support minimize the truth table
+ nFanins = pCut->nFanins;
+// nVars = Csw_CutSupportMinimize( p, pCut ); // leads to quality degradation
+ nVars = Kit_TruthSupportSize( pTruth, p->nLeafMax );
+p->timeCuts += clock() - clk;
+
+ // check for trivial truth tables
+ if ( nVars == 0 )
+ {
+ p->nNodesTriv0++;
+ return Aig_NotCond( Aig_ManConst1(p->pManRes), !(pTruth[0] & 1) );
+ }
+ if ( nVars == 1 )
+ {
+ p->nNodesTriv1++;
+ iVar = Kit_WordFindFirstBit( Kit_TruthSupport(pTruth, p->nLeafMax) );
+ assert( iVar < pCut->nFanins );
+ return Aig_NotCond( Aig_ManObj(p->pManRes, pCut->pFanins[iVar]), (pTruth[0] & 1) );
+ }
+ if ( nVars == 2 && nFanins > 2 && fUseResub )
+ {
+ if ( pObjNew = Csw_ObjTwoVarCut( p, pCut ) )
+ {
+ p->nNodesTriv2++;
+ return pObjNew;
+ }
+ }
+
+ // check if an equivalent node with the same cut exists
+clk = clock();
+ pObjNew = pCut->nFanins > 2 ? Csw_TableCutLookup( p, pCut ) : NULL;
+p->timeHash += clock() - clk;
+ if ( pObjNew )
+ {
+ p->nNodesCuts++;
+ return pObjNew;
+ }
+
+ // assign the cost
+ pCut->Cost = Csw_CutFindCost( p, pCut );
+ assert( pCut->nFanins > 0 );
+ assert( pCut->Cost > 0 );
+ }
+ p->nNodesTried++;
+
+ // load the resulting cuts into the table
+clk = clock();
+ Csw_ObjForEachCut( p, pObj, pCut, i )
+ {
+ if ( pCut->nFanins > 2 )
+ {
+ assert( pCut->Cost > 0 );
+ Csw_TableCutInsert( p, pCut );
+ }
+ }
+p->timeHash += clock() - clk;
+
+ // return the node if could not replace it
+ return pObj;
+}
+
+////////////////////////////////////////////////////////////////////////
+/// END OF FILE ///
+////////////////////////////////////////////////////////////////////////
+
+
diff --git a/src/aig/csw/cswInt.h b/src/aig/csw/cswInt.h
new file mode 100644
index 00000000..37efe9b4
--- /dev/null
+++ b/src/aig/csw/cswInt.h
@@ -0,0 +1,157 @@
+/**CFile****************************************************************
+
+ FileName [cswInt.h]
+
+ SystemName [ABC: Logic synthesis and verification system.]
+
+ PackageName [Cut sweeping.]
+
+ Synopsis [External declarations.]
+
+ Author [Alan Mishchenko]
+
+ Affiliation [UC Berkeley]
+
+ Date [Ver. 1.0. Started - July 11, 2007.]
+
+ Revision [$Id: cswInt.h,v 1.00 2007/07/11 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#ifndef __CSW_INT_H__
+#define __CSW_INT_H__
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+////////////////////////////////////////////////////////////////////////
+/// INCLUDES ///
+////////////////////////////////////////////////////////////////////////
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <assert.h>
+#include <time.h>
+
+#include "aig.h"
+#include "dar.h"
+#include "kit.h"
+#include "csw.h"
+
+////////////////////////////////////////////////////////////////////////
+/// PARAMETERS ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+/// BASIC TYPES ///
+////////////////////////////////////////////////////////////////////////
+
+typedef struct Csw_Man_t_ Csw_Man_t;
+typedef struct Csw_Cut_t_ Csw_Cut_t;
+
+// the cut used to represent node in the AIG
+struct Csw_Cut_t_
+{
+ Csw_Cut_t * pNext; // the next cut in the table
+ int Cost; // the cost of the cut
+// float Cost; // the cost of the cut
+ unsigned uSign; // cut signature
+ int iNode; // the node, for which it is the cut
+ short nCutSize; // the number of bytes in the cut
+ char nLeafMax; // the maximum number of fanins
+ char nFanins; // the current number of fanins
+ int pFanins[0]; // the fanins (followed by the truth table)
+};
+
+// the CNF computation manager
+struct Csw_Man_t_
+{
+ // AIG manager
+ Aig_Man_t * pManAig; // the input AIG manager
+ Aig_Man_t * pManRes; // the output AIG manager
+ Aig_Obj_t ** pEquiv; // the equivalent nodes in the resulting manager
+ Csw_Cut_t ** pCuts; // the cuts for each node in the output manager
+ int * pnRefs; // the number of references of each new node
+ // hash table for cuts
+ Csw_Cut_t ** pTable; // the table composed of cuts
+ int nTableSize; // the size of hash table
+ // parameters
+ int nCutsMax; // the max number of cuts at the node
+ int nLeafMax; // the max number of leaves of a cut
+ int fVerbose; // enables verbose output
+ // internal variables
+ int nCutSize; // the number of bytes needed to store one cut
+ int nTruthWords; // the number of truth table words
+ Aig_MmFixed_t * pMemCuts; // memory manager for cuts
+ unsigned * puTemp[4]; // used for the truth table computation
+ // statistics
+ int nNodesTriv0; // the number of trivial nodes
+ int nNodesTriv1; // the number of trivial nodes
+ int nNodesTriv2; // the number of trivial nodes
+ int nNodesCuts; // the number of rewritten nodes
+ int nNodesTried; // the number of nodes tried
+ int timeCuts; // time to compute the cut and its truth table
+ int timeHash; // time for hashing cuts
+ int timeOther; // other time
+ int timeTotal; // total time
+};
+
+static inline int Csw_CutLeaveNum( Csw_Cut_t * pCut ) { return pCut->nFanins; }
+static inline int * Csw_CutLeaves( Csw_Cut_t * pCut ) { return pCut->pFanins; }
+static inline unsigned * Csw_CutTruth( Csw_Cut_t * pCut ) { return (unsigned *)(pCut->pFanins + pCut->nLeafMax); }
+static inline Csw_Cut_t * Csw_CutNext( Csw_Cut_t * pCut ) { return (Csw_Cut_t *)(((char *)pCut) + pCut->nCutSize); }
+
+static inline int Csw_ObjRefs( Csw_Man_t * p, Aig_Obj_t * pObj ) { return p->pnRefs[pObj->Id]; }
+static inline void Csw_ObjAddRefs( Csw_Man_t * p, Aig_Obj_t * pObj, int nRefs ) { p->pnRefs[pObj->Id] += nRefs; }
+
+static inline Csw_Cut_t * Csw_ObjCuts( Csw_Man_t * p, Aig_Obj_t * pObj ) { return p->pCuts[pObj->Id]; }
+static inline void Csw_ObjSetCuts( Csw_Man_t * p, Aig_Obj_t * pObj, Csw_Cut_t * pCuts ) { p->pCuts[pObj->Id] = pCuts; }
+
+static inline Aig_Obj_t * Csw_ObjEquiv( Csw_Man_t * p, Aig_Obj_t * pObj ) { return p->pEquiv[pObj->Id]; }
+static inline void Csw_ObjSetEquiv( Csw_Man_t * p, Aig_Obj_t * pObj, Aig_Obj_t * pEquiv ) { p->pEquiv[pObj->Id] = pEquiv; }
+
+static inline Aig_Obj_t * Csw_ObjChild0Equiv( Csw_Man_t * p, Aig_Obj_t * pObj ) { assert( !Aig_IsComplement(pObj) ); return Aig_ObjFanin0(pObj)? Aig_NotCond(Csw_ObjEquiv(p, Aig_ObjFanin0(pObj)), Aig_ObjFaninC0(pObj)) : NULL; }
+static inline Aig_Obj_t * Csw_ObjChild1Equiv( Csw_Man_t * p, Aig_Obj_t * pObj ) { assert( !Aig_IsComplement(pObj) ); return Aig_ObjFanin1(pObj)? Aig_NotCond(Csw_ObjEquiv(p, Aig_ObjFanin1(pObj)), Aig_ObjFaninC1(pObj)) : NULL; }
+
+////////////////////////////////////////////////////////////////////////
+/// MACRO DEFINITIONS ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+/// ITERATORS ///
+////////////////////////////////////////////////////////////////////////
+
+// iterator over cuts of the node
+#define Csw_ObjForEachCut( p, pObj, pCut, i ) \
+ for ( i = 0, pCut = Csw_ObjCuts(p, pObj); i < p->nCutsMax; i++, pCut = Csw_CutNext(pCut) )
+// iterator over leaves of the cut
+#define Csw_CutForEachLeaf( p, pCut, pLeaf, i ) \
+ for ( i = 0; (i < (int)(pCut)->nFanins) && ((pLeaf) = Aig_ManObj(p, (pCut)->pFanins[i])); i++ )
+
+////////////////////////////////////////////////////////////////////////
+/// FUNCTION DECLARATIONS ///
+////////////////////////////////////////////////////////////////////////
+
+/*=== cnfCut.c ========================================================*/
+extern Csw_Cut_t * Csw_ObjPrepareCuts( Csw_Man_t * p, Aig_Obj_t * pObj, int fTriv );
+extern Aig_Obj_t * Csw_ObjSweep( Csw_Man_t * p, Aig_Obj_t * pObj, int fTriv );
+/*=== cnfMan.c ========================================================*/
+extern Csw_Man_t * Csw_ManStart( Aig_Man_t * pMan, int nCutsMax, int nLeafMax, int fVerbose );
+extern void Csw_ManStop( Csw_Man_t * p );
+/*=== cnfTable.c ========================================================*/
+extern int Csw_TableCountCuts( Csw_Man_t * p );
+extern void Csw_TableCutInsert( Csw_Man_t * p, Csw_Cut_t * pCut );
+extern Aig_Obj_t * Csw_TableCutLookup( Csw_Man_t * p, Csw_Cut_t * pCut );
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
+
+////////////////////////////////////////////////////////////////////////
+/// END OF FILE ///
+////////////////////////////////////////////////////////////////////////
+
diff --git a/src/aig/csw/cswMan.c b/src/aig/csw/cswMan.c
new file mode 100644
index 00000000..c3061dee
--- /dev/null
+++ b/src/aig/csw/cswMan.c
@@ -0,0 +1,125 @@
+/**CFile****************************************************************
+
+ FileName [cswMan.c]
+
+ SystemName [ABC: Logic synthesis and verification system.]
+
+ PackageName [Cut sweeping.]
+
+ Synopsis []
+
+ Author [Alan Mishchenko]
+
+ Affiliation [UC Berkeley]
+
+ Date [Ver. 1.0. Started - July 11, 2007.]
+
+ Revision [$Id: cswMan.c,v 1.00 2007/07/11 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "cswInt.h"
+
+////////////////////////////////////////////////////////////////////////
+/// DECLARATIONS ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+/// FUNCTION DEFINITIONS ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+ Synopsis [Starts the cut sweeping manager.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Csw_Man_t * Csw_ManStart( Aig_Man_t * pMan, int nCutsMax, int nLeafMax, int fVerbose )
+{
+ Csw_Man_t * p;
+ Aig_Obj_t * pObj;
+ int i;
+ assert( nCutsMax >= 2 );
+ assert( nLeafMax <= 16 );
+ // allocate the fraiging manager
+ p = ALLOC( Csw_Man_t, 1 );
+ memset( p, 0, sizeof(Csw_Man_t) );
+ p->nCutsMax = nCutsMax;
+ p->nLeafMax = nLeafMax;
+ p->fVerbose = fVerbose;
+ p->pManAig = pMan;
+ // create the new manager
+ p->pManRes = Aig_ManStartFrom( pMan );
+ assert( Aig_ManPiNum(p->pManAig) == Aig_ManPiNum(p->pManRes) );
+ // allocate room for cuts and equivalent nodes
+ p->pnRefs = ALLOC( int, Aig_ManObjNumMax(pMan) );
+ p->pEquiv = ALLOC( Aig_Obj_t *, Aig_ManObjNumMax(pMan) );
+ p->pCuts = ALLOC( Csw_Cut_t *, Aig_ManObjNumMax(pMan) );
+ memset( p->pCuts, 0, sizeof(Aig_Obj_t *) * Aig_ManObjNumMax(pMan) );
+ memset( p->pnRefs, 0, sizeof(int) * Aig_ManObjNumMax(pMan) );
+ // allocate memory manager
+ p->nTruthWords = Aig_TruthWordNum(nLeafMax);
+ p->nCutSize = sizeof(Csw_Cut_t) + sizeof(int) * nLeafMax + sizeof(unsigned) * p->nTruthWords;
+ p->pMemCuts = Aig_MmFixedStart( p->nCutSize * p->nCutsMax, 512 );
+ // allocate hash table for cuts
+ p->nTableSize = Aig_PrimeCudd( Aig_ManNodeNum(pMan) * p->nCutsMax / 2 );
+ p->pTable = ALLOC( Csw_Cut_t *, p->nTableSize );
+ memset( p->pTable, 0, sizeof(Aig_Obj_t *) * p->nTableSize );
+ // set the pointers to the available fraig nodes
+ Csw_ObjSetEquiv( p, Aig_ManConst1(p->pManAig), Aig_ManConst1(p->pManRes) );
+ Aig_ManForEachPi( p->pManAig, pObj, i )
+ Csw_ObjSetEquiv( p, pObj, Aig_ManPi(p->pManRes, i) );
+ // room for temporary truth tables
+ p->puTemp[0] = ALLOC( unsigned, 4 * p->nTruthWords );
+ p->puTemp[1] = p->puTemp[0] + p->nTruthWords;
+ p->puTemp[2] = p->puTemp[1] + p->nTruthWords;
+ p->puTemp[3] = p->puTemp[2] + p->nTruthWords;
+ return p;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Stops the fraiging manager.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Csw_ManStop( Csw_Man_t * p )
+{
+ if ( p->fVerbose )
+ {
+ int nNodesBeg = Aig_ManNodeNum(p->pManAig);
+ int nNodesEnd = Aig_ManNodeNum(p->pManRes);
+ printf( "Beg = %7d. End = %7d. (%6.2f %%) Try = %7d. Cuts = %8d.\n",
+ nNodesBeg, nNodesEnd, 100.0*(nNodesBeg-nNodesEnd)/nNodesBeg,
+ p->nNodesTried, Csw_TableCountCuts( p ) );
+ printf( "Triv0 = %6d. Triv1 = %6d. Triv2 = %6d. Cut-replace = %6d.\n",
+ p->nNodesTriv0, p->nNodesTriv1, p->nNodesTriv2, p->nNodesCuts );
+ PRTP( "Cuts ", p->timeCuts, p->timeTotal );
+ PRTP( "Hashing ", p->timeHash, p->timeTotal );
+ PRTP( "Other ", p->timeOther, p->timeTotal );
+ PRTP( "TOTAL ", p->timeTotal, p->timeTotal );
+ }
+ free( p->puTemp[0] );
+ Aig_MmFixedStop( p->pMemCuts, 0 );
+ free( p->pnRefs );
+ free( p->pEquiv );
+ free( p->pCuts );
+ free( p->pTable );
+ free( p );
+}
+
+////////////////////////////////////////////////////////////////////////
+/// END OF FILE ///
+////////////////////////////////////////////////////////////////////////
+
+
diff --git a/src/aig/csw/cswTable.c b/src/aig/csw/cswTable.c
new file mode 100644
index 00000000..87e36ae1
--- /dev/null
+++ b/src/aig/csw/cswTable.c
@@ -0,0 +1,161 @@
+/**CFile****************************************************************
+
+ FileName [cswTable.c]
+
+ SystemName [ABC: Logic synthesis and verification system.]
+
+ PackageName [Cut sweeping.]
+
+ Synopsis []
+
+ Author [Alan Mishchenko]
+
+ Affiliation [UC Berkeley]
+
+ Date [Ver. 1.0. Started - July 11, 2007.]
+
+ Revision [$Id: cswTable.c,v 1.00 2007/07/11 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "cswInt.h"
+
+////////////////////////////////////////////////////////////////////////
+/// DECLARATIONS ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+/// FUNCTION DEFINITIONS ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+ Synopsis [Computes hash value of the cut.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+unsigned Csw_CutHash( Csw_Cut_t * pCut )
+{
+ static int s_FPrimes[128] = {
+ 1009, 1049, 1093, 1151, 1201, 1249, 1297, 1361, 1427, 1459,
+ 1499, 1559, 1607, 1657, 1709, 1759, 1823, 1877, 1933, 1997,
+ 2039, 2089, 2141, 2213, 2269, 2311, 2371, 2411, 2467, 2543,
+ 2609, 2663, 2699, 2741, 2797, 2851, 2909, 2969, 3037, 3089,
+ 3169, 3221, 3299, 3331, 3389, 3461, 3517, 3557, 3613, 3671,
+ 3719, 3779, 3847, 3907, 3943, 4013, 4073, 4129, 4201, 4243,
+ 4289, 4363, 4441, 4493, 4549, 4621, 4663, 4729, 4793, 4871,
+ 4933, 4973, 5021, 5087, 5153, 5227, 5281, 5351, 5417, 5471,
+ 5519, 5573, 5651, 5693, 5749, 5821, 5861, 5923, 6011, 6073,
+ 6131, 6199, 6257, 6301, 6353, 6397, 6481, 6563, 6619, 6689,
+ 6737, 6803, 6863, 6917, 6977, 7027, 7109, 7187, 7237, 7309,
+ 7393, 7477, 7523, 7561, 7607, 7681, 7727, 7817, 7877, 7933,
+ 8011, 8039, 8059, 8081, 8093, 8111, 8123, 8147
+ };
+ unsigned uHash;
+ int i;
+ assert( pCut->nFanins <= 16 );
+ uHash = 0;
+ for ( i = 0; i < pCut->nFanins; i++ )
+ uHash ^= pCut->pFanins[i] * s_FPrimes[i];
+ return uHash;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Returns the total number of cuts in the table.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Csw_TableCountCuts( Csw_Man_t * p )
+{
+ Csw_Cut_t * pEnt;
+ int i, Counter = 0;
+ for ( i = 0; i < p->nTableSize; i++ )
+ for ( pEnt = p->pTable[i]; pEnt; pEnt = pEnt->pNext )
+ Counter++;
+ return Counter;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Adds the cut to the hash table.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Csw_TableCutInsert( Csw_Man_t * p, Csw_Cut_t * pCut )
+{
+ int iEntry = Csw_CutHash(pCut) % p->nTableSize;
+ pCut->pNext = p->pTable[iEntry];
+ p->pTable[iEntry] = pCut;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Returns an equivalent node if it exists.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Aig_Obj_t * Csw_TableCutLookup( Csw_Man_t * p, Csw_Cut_t * pCut )
+{
+ Aig_Obj_t * pRes = NULL;
+ Csw_Cut_t * pEnt;
+ unsigned * pTruthNew, * pTruthOld;
+ int iEntry = Csw_CutHash(pCut) % p->nTableSize;
+ for ( pEnt = p->pTable[iEntry]; pEnt; pEnt = pEnt->pNext )
+ {
+ if ( pEnt->nFanins != pCut->nFanins )
+ continue;
+ if ( pEnt->uSign != pCut->uSign )
+ continue;
+ if ( memcmp( pEnt->pFanins, pCut->pFanins, sizeof(int) * pCut->nFanins ) )
+ continue;
+ pTruthOld = Csw_CutTruth(pEnt);
+ pTruthNew = Csw_CutTruth(pCut);
+ if ( (pTruthOld[0] & 1) == (pTruthNew[0] & 1) )
+ {
+ if ( Kit_TruthIsEqual( pTruthOld, pTruthNew, pCut->nFanins ) )
+ {
+ pRes = Aig_ManObj( p->pManRes, pEnt->iNode );
+ assert( pRes->fPhase == Aig_ManObj( p->pManRes, pCut->iNode )->fPhase );
+ break;
+ }
+ }
+ else
+ {
+ if ( Kit_TruthIsOpposite( pTruthOld, pTruthNew, pCut->nFanins ) )
+ {
+ pRes = Aig_Not( Aig_ManObj( p->pManRes, pEnt->iNode ) );
+ assert( Aig_Regular(pRes)->fPhase != Aig_ManObj( p->pManRes, pCut->iNode )->fPhase );
+ break;
+ }
+ }
+ }
+ return pRes;
+}
+
+
+////////////////////////////////////////////////////////////////////////
+/// END OF FILE ///
+////////////////////////////////////////////////////////////////////////
+
+
diff --git a/src/aig/csw/csw_.c b/src/aig/csw/csw_.c
new file mode 100644
index 00000000..1c59f152
--- /dev/null
+++ b/src/aig/csw/csw_.c
@@ -0,0 +1,48 @@
+/**CFile****************************************************************
+
+ FileName [csw_.c]
+
+ SystemName [ABC: Logic synthesis and verification system.]
+
+ PackageName [Cut sweeping.]
+
+ Synopsis []
+
+ Author [Alan Mishchenko]
+
+ Affiliation [UC Berkeley]
+
+ Date [Ver. 1.0. Started - July 11, 2007.]
+
+ Revision [$Id: csw_.c,v 1.00 2007/07/11 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "cswInt.h"
+
+////////////////////////////////////////////////////////////////////////
+/// DECLARATIONS ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+/// FUNCTION DEFINITIONS ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+
+
+////////////////////////////////////////////////////////////////////////
+/// END OF FILE ///
+////////////////////////////////////////////////////////////////////////
+
+
diff --git a/src/aig/csw/module.make b/src/aig/csw/module.make
new file mode 100644
index 00000000..8fdb7bef
--- /dev/null
+++ b/src/aig/csw/module.make
@@ -0,0 +1,4 @@
+SRC += src/aig/csw/cswCore.c \
+ src/aig/csw/cswCut.c \
+ src/aig/csw/cswMan.c \
+ src/aig/csw/cswTable.c
diff --git a/src/abc8/dar/dar.h b/src/aig/dar/dar.h
index 72e7d3d1..72e7d3d1 100644
--- a/src/abc8/dar/dar.h
+++ b/src/aig/dar/dar.h
diff --git a/src/abc8/dar/darBalance.c b/src/aig/dar/darBalance.c
index b3c5d645..b3c5d645 100644
--- a/src/abc8/dar/darBalance.c
+++ b/src/aig/dar/darBalance.c
diff --git a/src/abc8/dar/darCore.c b/src/aig/dar/darCore.c
index 141d9b79..141d9b79 100644
--- a/src/abc8/dar/darCore.c
+++ b/src/aig/dar/darCore.c
diff --git a/src/abc8/dar/darCut.c b/src/aig/dar/darCut.c
index 79e4dcc4..79e4dcc4 100644
--- a/src/abc8/dar/darCut.c
+++ b/src/aig/dar/darCut.c
diff --git a/src/abc8/dar/darData.c b/src/aig/dar/darData.c
index cb403b8a..cb403b8a 100644
--- a/src/abc8/dar/darData.c
+++ b/src/aig/dar/darData.c
diff --git a/src/abc8/dar/darInt.h b/src/aig/dar/darInt.h
index dbca5fb2..afa3bd07 100644
--- a/src/abc8/dar/darInt.h
+++ b/src/aig/dar/darInt.h
@@ -36,7 +36,7 @@ extern "C" {
#include <time.h>
//#include "bar.h"
-#include "vec2.h"
+#include "vec.h"
#include "aig.h"
#include "dar.h"
diff --git a/src/abc8/dar/darLib.c b/src/aig/dar/darLib.c
index e0e97055..e0e97055 100644
--- a/src/abc8/dar/darLib.c
+++ b/src/aig/dar/darLib.c
diff --git a/src/abc8/dar/darMan.c b/src/aig/dar/darMan.c
index 0a5a36b1..0a5a36b1 100644
--- a/src/abc8/dar/darMan.c
+++ b/src/aig/dar/darMan.c
diff --git a/src/abc8/dar/darPrec.c b/src/aig/dar/darPrec.c
index 8c3a4ce3..8c3a4ce3 100644
--- a/src/abc8/dar/darPrec.c
+++ b/src/aig/dar/darPrec.c
diff --git a/src/abc8/dar/darRefact.c b/src/aig/dar/darRefact.c
index fafaf6da..a765ec30 100644
--- a/src/abc8/dar/darRefact.c
+++ b/src/aig/dar/darRefact.c
@@ -18,8 +18,8 @@
***********************************************************************/
-#include "kit.h"
#include "darInt.h"
+#include "kit.h"
////////////////////////////////////////////////////////////////////////
/// DECLARATIONS ///
diff --git a/src/abc8/dar/darResub.c b/src/aig/dar/darResub.c
index f819934e..f819934e 100644
--- a/src/abc8/dar/darResub.c
+++ b/src/aig/dar/darResub.c
diff --git a/src/abc8/dar/darScript.c b/src/aig/dar/darScript.c
index 530e913e..530e913e 100644
--- a/src/abc8/dar/darScript.c
+++ b/src/aig/dar/darScript.c
diff --git a/src/abc8/dar/dar_.c b/src/aig/dar/dar_.c
index 12fd7d17..12fd7d17 100644
--- a/src/abc8/dar/dar_.c
+++ b/src/aig/dar/dar_.c
diff --git a/src/abc8/dar/module.make b/src/aig/dar/module.make
index b1b0332c..b1b0332c 100644
--- a/src/abc8/dar/module.make
+++ b/src/aig/dar/module.make
diff --git a/src/aig/deco/deco.h b/src/aig/deco/deco.h
new file mode 100644
index 00000000..67126902
--- /dev/null
+++ b/src/aig/deco/deco.h
@@ -0,0 +1,703 @@
+/**CFile****************************************************************
+
+ FileName [deco.h]
+
+ SystemName [ABC: Logic synthesis and verification system.]
+
+ PackageName [A simple decomposition tree/node data structure and its APIs.]
+
+ Synopsis [External declarations.]
+
+ Author [Alan Mishchenko]
+
+ Affiliation [UC Berkeley]
+
+ Date [Ver. 1.0. Started - June 20, 2005.]
+
+ Revision [$Id: deco.h,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#ifndef __DEC_H__
+#define __DEC_H__
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+////////////////////////////////////////////////////////////////////////
+/// INCLUDES ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+/// PARAMETERS ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+/// BASIC TYPES ///
+////////////////////////////////////////////////////////////////////////
+
+typedef struct Dec_Edge_t_ Dec_Edge_t;
+struct Dec_Edge_t_
+{
+ unsigned fCompl : 1; // the complemented bit
+ unsigned Node : 30; // the decomposition node pointed by the edge
+};
+
+typedef struct Dec_Node_t_ Dec_Node_t;
+struct Dec_Node_t_
+{
+ Dec_Edge_t eEdge0; // the left child of the node
+ Dec_Edge_t eEdge1; // the right child of the node
+ // other info
+ void * pFunc; // the function of the node (BDD or AIG)
+ unsigned Level : 14; // the level of this node in the global AIG
+ // printing info
+ unsigned fNodeOr : 1; // marks the original OR node
+ unsigned fCompl0 : 1; // marks the original complemented edge
+ unsigned fCompl1 : 1; // marks the original complemented edge
+ // latch info
+ unsigned nLat0 : 5; // the number of latches on the first edge
+ unsigned nLat1 : 5; // the number of latches on the second edge
+ unsigned nLat2 : 5; // the number of latches on the output edge
+};
+
+typedef struct Dec_Graph_t_ Dec_Graph_t;
+struct Dec_Graph_t_
+{
+ int fConst; // marks the constant 1 graph
+ int nLeaves; // the number of leaves
+ int nSize; // the number of nodes (including the leaves)
+ int nCap; // the number of allocated nodes
+ Dec_Node_t * pNodes; // the array of leaves and internal nodes
+ Dec_Edge_t eRoot; // the pointer to the topmost node
+};
+
+typedef struct Dec_Man_t_ Dec_Man_t;
+struct Dec_Man_t_
+{
+ void * pMvcMem; // memory manager for MVC cover (used for factoring)
+ Vec_Int_t * vCubes; // storage for cubes
+ Vec_Int_t * vLits; // storage for literals
+ // precomputation information about 4-variable functions
+ unsigned short * puCanons; // canonical forms
+ char * pPhases; // canonical phases
+ char * pPerms; // canonical permutations
+ unsigned char * pMap; // mapping of functions into class numbers
+};
+
+
+////////////////////////////////////////////////////////////////////////
+/// ITERATORS ///
+////////////////////////////////////////////////////////////////////////
+
+// interator throught the leaves
+#define Dec_GraphForEachLeaf( pGraph, pLeaf, i ) \
+ for ( i = 0; (i < (pGraph)->nLeaves) && (((pLeaf) = Dec_GraphNode(pGraph, i)), 1); i++ )
+// interator throught the internal nodes
+#define Dec_GraphForEachNode( pGraph, pAnd, i ) \
+ for ( i = (pGraph)->nLeaves; (i < (pGraph)->nSize) && (((pAnd) = Dec_GraphNode(pGraph, i)), 1); i++ )
+
+////////////////////////////////////////////////////////////////////////
+/// FUNCTION DECLARATIONS ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+/// FUNCTION DEFINITIONS ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+ Synopsis [Creates an edge pointing to the node in the given polarity.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+static inline Dec_Edge_t Dec_EdgeCreate( int Node, int fCompl )
+{
+ Dec_Edge_t eEdge = { fCompl, Node };
+ return eEdge;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Converts the edge into unsigned integer.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+static inline unsigned Dec_EdgeToInt( Dec_Edge_t eEdge )
+{
+ return (eEdge.Node << 1) | eEdge.fCompl;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Converts unsigned integer into the edge.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+static inline Dec_Edge_t Dec_IntToEdge( unsigned Edge )
+{
+ return Dec_EdgeCreate( Edge >> 1, Edge & 1 );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Converts the edge into unsigned integer.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+static inline unsigned Dec_EdgeToInt_( Dec_Edge_t eEdge )
+{
+ return *(unsigned *)&eEdge;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Converts unsigned integer into the edge.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+static inline Dec_Edge_t Dec_IntToEdge_( unsigned Edge )
+{
+ return *(Dec_Edge_t *)&Edge;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Creates a graph with the given number of leaves.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+static inline Dec_Graph_t * Dec_GraphCreate( int nLeaves )
+{
+ Dec_Graph_t * pGraph;
+ pGraph = ALLOC( Dec_Graph_t, 1 );
+ memset( pGraph, 0, sizeof(Dec_Graph_t) );
+ pGraph->nLeaves = nLeaves;
+ pGraph->nSize = nLeaves;
+ pGraph->nCap = 2 * nLeaves + 50;
+ pGraph->pNodes = ALLOC( Dec_Node_t, pGraph->nCap );
+ memset( pGraph->pNodes, 0, sizeof(Dec_Node_t) * pGraph->nSize );
+ return pGraph;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Creates constant 0 graph.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+static inline Dec_Graph_t * Dec_GraphCreateConst0()
+{
+ Dec_Graph_t * pGraph;
+ pGraph = ALLOC( Dec_Graph_t, 1 );
+ memset( pGraph, 0, sizeof(Dec_Graph_t) );
+ pGraph->fConst = 1;
+ pGraph->eRoot.fCompl = 1;
+ return pGraph;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Creates constant 1 graph.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+static inline Dec_Graph_t * Dec_GraphCreateConst1()
+{
+ Dec_Graph_t * pGraph;
+ pGraph = ALLOC( Dec_Graph_t, 1 );
+ memset( pGraph, 0, sizeof(Dec_Graph_t) );
+ pGraph->fConst = 1;
+ return pGraph;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Creates the literal graph.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+static inline Dec_Graph_t * Dec_GraphCreateLeaf( int iLeaf, int nLeaves, int fCompl )
+{
+ Dec_Graph_t * pGraph;
+ assert( 0 <= iLeaf && iLeaf < nLeaves );
+ pGraph = Dec_GraphCreate( nLeaves );
+ pGraph->eRoot.Node = iLeaf;
+ pGraph->eRoot.fCompl = fCompl;
+ return pGraph;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Creates a graph with the given number of leaves.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+static inline void Dec_GraphFree( Dec_Graph_t * pGraph )
+{
+ FREE( pGraph->pNodes );
+ free( pGraph );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Returns 1 if the graph is a constant.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+static inline int Dec_GraphIsConst( Dec_Graph_t * pGraph )
+{
+ return pGraph->fConst;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Returns 1 if the graph is constant 0.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+static inline int Dec_GraphIsConst0( Dec_Graph_t * pGraph )
+{
+ return pGraph->fConst && pGraph->eRoot.fCompl;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Returns 1 if the graph is constant 1.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+static inline int Dec_GraphIsConst1( Dec_Graph_t * pGraph )
+{
+ return pGraph->fConst && !pGraph->eRoot.fCompl;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Returns 1 if the graph is complemented.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+static inline int Dec_GraphIsComplement( Dec_Graph_t * pGraph )
+{
+ return pGraph->eRoot.fCompl;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Checks if the graph is complemented.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+static inline void Dec_GraphComplement( Dec_Graph_t * pGraph )
+{
+ pGraph->eRoot.fCompl ^= 1;
+}
+
+
+/**Function*************************************************************
+
+ Synopsis [Returns the number of leaves.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+static inline int Dec_GraphLeaveNum( Dec_Graph_t * pGraph )
+{
+ return pGraph->nLeaves;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Returns the number of internal nodes.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+static inline int Dec_GraphNodeNum( Dec_Graph_t * pGraph )
+{
+ return pGraph->nSize - pGraph->nLeaves;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Returns the pointer to the node.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+static inline Dec_Node_t * Dec_GraphNode( Dec_Graph_t * pGraph, int i )
+{
+ return pGraph->pNodes + i;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Returns the pointer to the node.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+static inline Dec_Node_t * Dec_GraphNodeLast( Dec_Graph_t * pGraph )
+{
+ return pGraph->pNodes + pGraph->nSize - 1;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Returns the number of the given node.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+static inline int Dec_GraphNodeInt( Dec_Graph_t * pGraph, Dec_Node_t * pNode )
+{
+ return pNode - pGraph->pNodes;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Check if the graph represents elementary variable.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+static inline int Dec_GraphIsVar( Dec_Graph_t * pGraph )
+{
+ return pGraph->eRoot.Node < (unsigned)pGraph->nLeaves;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Check if the graph represents elementary variable.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+static inline int Dec_GraphNodeIsVar( Dec_Graph_t * pGraph, Dec_Node_t * pNode )
+{
+ return Dec_GraphNodeInt(pGraph,pNode) < pGraph->nLeaves;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Returns the elementary variable elementary variable.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+static inline Dec_Node_t * Dec_GraphVar( Dec_Graph_t * pGraph )
+{
+ assert( Dec_GraphIsVar( pGraph ) );
+ return Dec_GraphNode( pGraph, pGraph->eRoot.Node );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Returns the number of the elementary variable.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+static inline int Dec_GraphVarInt( Dec_Graph_t * pGraph )
+{
+ assert( Dec_GraphIsVar( pGraph ) );
+ return Dec_GraphNodeInt( pGraph, Dec_GraphVar(pGraph) );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Sets the root of the graph.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+static inline void Dec_GraphSetRoot( Dec_Graph_t * pGraph, Dec_Edge_t eRoot )
+{
+ pGraph->eRoot = eRoot;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Appends a new node to the graph.]
+
+ Description [This procedure is meant for internal use.]
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+static inline Dec_Node_t * Dec_GraphAppendNode( Dec_Graph_t * pGraph )
+{
+ Dec_Node_t * pNode;
+ if ( pGraph->nSize == pGraph->nCap )
+ {
+ pGraph->pNodes = REALLOC( Dec_Node_t, pGraph->pNodes, 2 * pGraph->nCap );
+ pGraph->nCap = 2 * pGraph->nCap;
+ }
+ pNode = pGraph->pNodes + pGraph->nSize++;
+ memset( pNode, 0, sizeof(Dec_Node_t) );
+ return pNode;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Creates an AND node.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+static inline Dec_Edge_t Dec_GraphAddNodeAnd( Dec_Graph_t * pGraph, Dec_Edge_t eEdge0, Dec_Edge_t eEdge1 )
+{
+ Dec_Node_t * pNode;
+ // get the new node
+ pNode = Dec_GraphAppendNode( pGraph );
+ // set the inputs and other info
+ pNode->eEdge0 = eEdge0;
+ pNode->eEdge1 = eEdge1;
+ pNode->fCompl0 = eEdge0.fCompl;
+ pNode->fCompl1 = eEdge1.fCompl;
+ return Dec_EdgeCreate( pGraph->nSize - 1, 0 );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Creates an OR node.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+static inline Dec_Edge_t Dec_GraphAddNodeOr( Dec_Graph_t * pGraph, Dec_Edge_t eEdge0, Dec_Edge_t eEdge1 )
+{
+ Dec_Node_t * pNode;
+ // get the new node
+ pNode = Dec_GraphAppendNode( pGraph );
+ // set the inputs and other info
+ pNode->eEdge0 = eEdge0;
+ pNode->eEdge1 = eEdge1;
+ pNode->fCompl0 = eEdge0.fCompl;
+ pNode->fCompl1 = eEdge1.fCompl;
+ // make adjustments for the OR gate
+ pNode->fNodeOr = 1;
+ pNode->eEdge0.fCompl = !pNode->eEdge0.fCompl;
+ pNode->eEdge1.fCompl = !pNode->eEdge1.fCompl;
+ return Dec_EdgeCreate( pGraph->nSize - 1, 1 );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Creates an XOR node.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+static inline Dec_Edge_t Dec_GraphAddNodeXor( Dec_Graph_t * pGraph, Dec_Edge_t eEdge0, Dec_Edge_t eEdge1, int Type )
+{
+ Dec_Edge_t eNode0, eNode1, eNode;
+ if ( Type == 0 )
+ {
+ // derive the first AND
+ eEdge0.fCompl ^= 1;
+ eNode0 = Dec_GraphAddNodeAnd( pGraph, eEdge0, eEdge1 );
+ eEdge0.fCompl ^= 1;
+ // derive the second AND
+ eEdge1.fCompl ^= 1;
+ eNode1 = Dec_GraphAddNodeAnd( pGraph, eEdge0, eEdge1 );
+ // derive the final OR
+ eNode = Dec_GraphAddNodeOr( pGraph, eNode0, eNode1 );
+ }
+ else
+ {
+ // derive the first AND
+ eNode0 = Dec_GraphAddNodeAnd( pGraph, eEdge0, eEdge1 );
+ // derive the second AND
+ eEdge0.fCompl ^= 1;
+ eEdge1.fCompl ^= 1;
+ eNode1 = Dec_GraphAddNodeAnd( pGraph, eEdge0, eEdge1 );
+ // derive the final OR
+ eNode = Dec_GraphAddNodeOr( pGraph, eNode0, eNode1 );
+ eNode.fCompl ^= 1;
+ }
+ return eNode;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Creates an XOR node.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+static inline Dec_Edge_t Dec_GraphAddNodeMux( Dec_Graph_t * pGraph, Dec_Edge_t eEdgeC, Dec_Edge_t eEdgeT, Dec_Edge_t eEdgeE, int Type )
+{
+ Dec_Edge_t eNode0, eNode1, eNode;
+ if ( Type == 0 )
+ {
+ // derive the first AND
+ eNode0 = Dec_GraphAddNodeAnd( pGraph, eEdgeC, eEdgeT );
+ // derive the second AND
+ eEdgeC.fCompl ^= 1;
+ eNode1 = Dec_GraphAddNodeAnd( pGraph, eEdgeC, eEdgeE );
+ // derive the final OR
+ eNode = Dec_GraphAddNodeOr( pGraph, eNode0, eNode1 );
+ }
+ else
+ {
+ // complement the arguments
+ eEdgeT.fCompl ^= 1;
+ eEdgeE.fCompl ^= 1;
+ // derive the first AND
+ eNode0 = Dec_GraphAddNodeAnd( pGraph, eEdgeC, eEdgeT );
+ // derive the second AND
+ eEdgeC.fCompl ^= 1;
+ eNode1 = Dec_GraphAddNodeAnd( pGraph, eEdgeC, eEdgeE );
+ // derive the final OR
+ eNode = Dec_GraphAddNodeOr( pGraph, eNode0, eNode1 );
+ eNode.fCompl ^= 1;
+ }
+ return eNode;
+}
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
+
+////////////////////////////////////////////////////////////////////////
+/// END OF FILE ///
+////////////////////////////////////////////////////////////////////////
+
diff --git a/src/abc8/vec2/module.make b/src/aig/deco/module.make
index d6d908e7..d6d908e7 100644
--- a/src/abc8/vec2/module.make
+++ b/src/aig/deco/module.make
diff --git a/src/abc8/fra/fra.h b/src/aig/fra/fra.h
index c024a736..8d7116c7 100644
--- a/src/abc8/fra/fra.h
+++ b/src/aig/fra/fra.h
@@ -35,7 +35,7 @@ extern "C" {
#include <assert.h>
#include <time.h>
-#include "vec2.h"
+#include "vec.h"
#include "aig.h"
#include "dar.h"
#include "satSolver.h"
diff --git a/src/abc8/fra/fraBmc.c b/src/aig/fra/fraBmc.c
index cf026fac..cf026fac 100644
--- a/src/abc8/fra/fraBmc.c
+++ b/src/aig/fra/fraBmc.c
diff --git a/src/abc8/fra/fraCec.c b/src/aig/fra/fraCec.c
index bdab25dd..bdab25dd 100644
--- a/src/abc8/fra/fraCec.c
+++ b/src/aig/fra/fraCec.c
diff --git a/src/abc8/fra/fraClass.c b/src/aig/fra/fraClass.c
index 2d03e65d..2d03e65d 100644
--- a/src/abc8/fra/fraClass.c
+++ b/src/aig/fra/fraClass.c
diff --git a/src/abc8/fra/fraClau.c b/src/aig/fra/fraClau.c
index fc239a40..fc239a40 100644
--- a/src/abc8/fra/fraClau.c
+++ b/src/aig/fra/fraClau.c
diff --git a/src/abc8/fra/fraClaus.c b/src/aig/fra/fraClaus.c
index e5b8a126..e5b8a126 100644
--- a/src/abc8/fra/fraClaus.c
+++ b/src/aig/fra/fraClaus.c
diff --git a/src/abc8/fra/fraCnf.c b/src/aig/fra/fraCnf.c
index d96fe8a1..d96fe8a1 100644
--- a/src/abc8/fra/fraCnf.c
+++ b/src/aig/fra/fraCnf.c
diff --git a/src/abc8/fra/fraCore.c b/src/aig/fra/fraCore.c
index 95d65e25..95d65e25 100644
--- a/src/abc8/fra/fraCore.c
+++ b/src/aig/fra/fraCore.c
diff --git a/src/abc8/fra/fraImp.c b/src/aig/fra/fraImp.c
index e2bee834..e2bee834 100644
--- a/src/abc8/fra/fraImp.c
+++ b/src/aig/fra/fraImp.c
diff --git a/src/abc8/fra/fraInd.c b/src/aig/fra/fraInd.c
index 1c2140bb..1c2140bb 100644
--- a/src/abc8/fra/fraInd.c
+++ b/src/aig/fra/fraInd.c
diff --git a/src/abc8/fra/fraLcr.c b/src/aig/fra/fraLcr.c
index a6460ed7..a6460ed7 100644
--- a/src/abc8/fra/fraLcr.c
+++ b/src/aig/fra/fraLcr.c
diff --git a/src/abc8/fra/fraMan.c b/src/aig/fra/fraMan.c
index f505b0c2..f505b0c2 100644
--- a/src/abc8/fra/fraMan.c
+++ b/src/aig/fra/fraMan.c
diff --git a/src/abc8/fra/fraPart.c b/src/aig/fra/fraPart.c
index f4964746..f4964746 100644
--- a/src/abc8/fra/fraPart.c
+++ b/src/aig/fra/fraPart.c
diff --git a/src/abc8/fra/fraSat.c b/src/aig/fra/fraSat.c
index 819605d6..819605d6 100644
--- a/src/abc8/fra/fraSat.c
+++ b/src/aig/fra/fraSat.c
diff --git a/src/abc8/fra/fraSec.c b/src/aig/fra/fraSec.c
index c6bdc20e..c6bdc20e 100644
--- a/src/abc8/fra/fraSec.c
+++ b/src/aig/fra/fraSec.c
diff --git a/src/abc8/fra/fraSim.c b/src/aig/fra/fraSim.c
index 1ad2d4f7..1ad2d4f7 100644
--- a/src/abc8/fra/fraSim.c
+++ b/src/aig/fra/fraSim.c
diff --git a/src/abc8/fra/fra_.c b/src/aig/fra/fra_.c
index 2b601587..2b601587 100644
--- a/src/abc8/fra/fra_.c
+++ b/src/aig/fra/fra_.c
diff --git a/src/abc8/fra/module.make b/src/aig/fra/module.make
index ffaca75c..ffaca75c 100644
--- a/src/abc8/fra/module.make
+++ b/src/aig/fra/module.make
diff --git a/src/aig/hop/cudd2.c b/src/aig/hop/cudd2.c
new file mode 100644
index 00000000..28d13ce0
--- /dev/null
+++ b/src/aig/hop/cudd2.c
@@ -0,0 +1,355 @@
+/**CFile****************************************************************
+
+ FileName [cudd2.c]
+
+ SystemName [ABC: Logic synthesis and verification system.]
+
+ PackageName [Minimalistic And-Inverter Graph package.]
+
+ Synopsis [Recording AIGs for the BDD operations.]
+
+ Author [Alan Mishchenko]
+
+ Affiliation [UC Berkeley]
+
+ Date [Ver. 1.0. Started - October 3, 2006.]
+
+ Revision [$Id: cudd2.c,v 1.00 2006/10/03 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "hop.h"
+#include "st.h"
+
+////////////////////////////////////////////////////////////////////////
+/// DECLARATIONS ///
+////////////////////////////////////////////////////////////////////////
+
+typedef struct Aig_CuddMan_t_ Aig_CuddMan_t;
+struct Aig_CuddMan_t_
+{
+ Aig_Man_t * pAig; // internal AIG package
+ st_table * pTable; // hash table mapping BDD nodes into AIG nodes
+};
+
+// static Cudd AIG manager used in this experiment
+static Aig_CuddMan_t * s_pCuddMan = NULL;
+
+////////////////////////////////////////////////////////////////////////
+/// FUNCTION DEFINITIONS ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+ Synopsis [Start AIG recording.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Cudd2_Init( unsigned int numVars, unsigned int numVarsZ, unsigned int numSlots, unsigned int cacheSize, unsigned long maxMemory, void * pCudd )
+{
+ int v;
+ // start the BDD-to-AIG manager when the first BDD manager is allocated
+ if ( s_pCuddMan != NULL )
+ return;
+ s_pCuddMan = ALLOC( Aig_CuddMan_t, 1 );
+ s_pCuddMan->pAig = Aig_ManStart();
+ s_pCuddMan->pTable = st_init_table( st_ptrcmp, st_ptrhash );
+ for ( v = 0; v < (int)numVars; v++ )
+ Aig_ObjCreatePi( s_pCuddMan->pAig );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Stops AIG recording.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Cudd2_Quit( void * pCudd )
+{
+ assert( s_pCuddMan != NULL );
+ Aig_ManDumpBlif( s_pCuddMan->pAig, "aig_temp.blif" );
+ Aig_ManStop( s_pCuddMan->pAig );
+ st_free_table( s_pCuddMan->pTable );
+ free( s_pCuddMan );
+ s_pCuddMan = NULL;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Fetches AIG node corresponding to the BDD node from the hash table.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+static Aig_Obj_t * Cudd2_GetArg( void * pArg )
+{
+ Aig_Obj_t * pNode;
+ assert( s_pCuddMan != NULL );
+ if ( !st_lookup( s_pCuddMan->pTable, (char *)Aig_Regular(pArg), (char **)&pNode ) )
+ {
+ printf( "Cudd2_GetArg(): An argument BDD is not in the hash table.\n" );
+ return NULL;
+ }
+ return Aig_NotCond( pNode, Aig_IsComplement(pArg) );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Inserts the AIG node corresponding to the BDD node into the hash table.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+static void Cudd2_SetArg( Aig_Obj_t * pNode, void * pResult )
+{
+ assert( s_pCuddMan != NULL );
+ if ( st_is_member( s_pCuddMan->pTable, (char *)Aig_Regular(pResult) ) )
+ return;
+ pNode = Aig_NotCond( pNode, Aig_IsComplement(pResult) );
+ st_insert( s_pCuddMan->pTable, (char *)Aig_Regular(pResult), (char *)pNode );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Registers constant 1 node.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Cudd2_bddOne( void * pCudd, void * pResult )
+{
+ Cudd2_SetArg( Aig_ManConst1(s_pCuddMan->pAig), pResult );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Adds elementary variable.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Cudd2_bddIthVar( void * pCudd, int iVar, void * pResult )
+{
+ int v;
+ assert( s_pCuddMan != NULL );
+ for ( v = Aig_ManPiNum(s_pCuddMan->pAig); v <= iVar; v++ )
+ Aig_ObjCreatePi( s_pCuddMan->pAig );
+ Cudd2_SetArg( Aig_ManPi(s_pCuddMan->pAig, iVar), pResult );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Performs BDD operation.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Cudd2_bddAnd( void * pCudd, void * pArg0, void * pArg1, void * pResult )
+{
+ Aig_Obj_t * pNode0, * pNode1, * pNode;
+ pNode0 = Cudd2_GetArg( pArg0 );
+ pNode1 = Cudd2_GetArg( pArg1 );
+ pNode = Aig_And( s_pCuddMan->pAig, pNode0, pNode1 );
+ Cudd2_SetArg( pNode, pResult );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Performs BDD operation.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Cudd2_bddOr( void * pCudd, void * pArg0, void * pArg1, void * pResult )
+{
+ Cudd2_bddAnd( pCudd, Aig_Not(pArg0), Aig_Not(pArg1), Aig_Not(pResult) );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Performs BDD operation.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Cudd2_bddNand( void * pCudd, void * pArg0, void * pArg1, void * pResult )
+{
+ Cudd2_bddAnd( pCudd, pArg0, pArg1, Aig_Not(pResult) );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Performs BDD operation.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Cudd2_bddNor( void * pCudd, void * pArg0, void * pArg1, void * pResult )
+{
+ Cudd2_bddAnd( pCudd, Aig_Not(pArg0), Aig_Not(pArg1), pResult );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Performs BDD operation.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Cudd2_bddXor( void * pCudd, void * pArg0, void * pArg1, void * pResult )
+{
+ Aig_Obj_t * pNode0, * pNode1, * pNode;
+ pNode0 = Cudd2_GetArg( pArg0 );
+ pNode1 = Cudd2_GetArg( pArg1 );
+ pNode = Aig_Exor( s_pCuddMan->pAig, pNode0, pNode1 );
+ Cudd2_SetArg( pNode, pResult );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Performs BDD operation.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Cudd2_bddXnor( void * pCudd, void * pArg0, void * pArg1, void * pResult )
+{
+ Cudd2_bddXor( pCudd, pArg0, pArg1, Aig_Not(pResult) );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Performs BDD operation.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Cudd2_bddIte( void * pCudd, void * pArg0, void * pArg1, void * pArg2, void * pResult )
+{
+ Aig_Obj_t * pNode0, * pNode1, * pNode2, * pNode;
+ pNode0 = Cudd2_GetArg( pArg0 );
+ pNode1 = Cudd2_GetArg( pArg1 );
+ pNode2 = Cudd2_GetArg( pArg2 );
+ pNode = Aig_Mux( s_pCuddMan->pAig, pNode0, pNode1, pNode2 );
+ Cudd2_SetArg( pNode, pResult );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Performs BDD operation.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Cudd2_bddCompose( void * pCudd, void * pArg0, void * pArg1, int v, void * pResult )
+{
+ Aig_Obj_t * pNode0, * pNode1, * pNode;
+ pNode0 = Cudd2_GetArg( pArg0 );
+ pNode1 = Cudd2_GetArg( pArg1 );
+ pNode = Aig_Compose( s_pCuddMan->pAig, pNode0, pNode1, v );
+ Cudd2_SetArg( pNode, pResult );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Should be called after each containment check.]
+
+ Description [Result should be 1 if Cudd2_bddLeq returned 1.]
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Cudd2_bddLeq( void * pCudd, void * pArg0, void * pArg1, int Result )
+{
+ Aig_Obj_t * pNode0, * pNode1, * pNode;
+ pNode0 = Cudd2_GetArg( pArg0 );
+ pNode1 = Cudd2_GetArg( pArg1 );
+ pNode = Aig_And( s_pCuddMan->pAig, pNode0, Aig_Not(pNode1) );
+ Aig_ObjCreatePo( s_pCuddMan->pAig, pNode );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Should be called after each equality check.]
+
+ Description [Result should be 1 if they are equal.]
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Cudd2_bddEqual( void * pCudd, void * pArg0, void * pArg1, int Result )
+{
+ Aig_Obj_t * pNode0, * pNode1, * pNode;
+ pNode0 = Cudd2_GetArg( pArg0 );
+ pNode1 = Cudd2_GetArg( pArg1 );
+ pNode = Aig_Exor( s_pCuddMan->pAig, pNode0, pNode1 );
+ Aig_ObjCreatePo( s_pCuddMan->pAig, pNode );
+}
+
+////////////////////////////////////////////////////////////////////////
+/// END OF FILE ///
+////////////////////////////////////////////////////////////////////////
+
+
diff --git a/src/aig/hop/cudd2.h b/src/aig/hop/cudd2.h
new file mode 100644
index 00000000..69711c11
--- /dev/null
+++ b/src/aig/hop/cudd2.h
@@ -0,0 +1,82 @@
+/**CFile****************************************************************
+
+ FileName [cudd2.h]
+
+ SystemName [ABC: Logic synthesis and verification system.]
+
+ PackageName [Minimalistic And-Inverter Graph package.]
+
+ Synopsis [External declarations.]
+
+ Author [Alan Mishchenko]
+
+ Affiliation [UC Berkeley]
+
+ Date [Ver. 1.0. Started - October 3, 2006.]
+
+ Revision [$Id: cudd2.h,v 1.00 2006/05/11 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#ifndef __CUDD2_H__
+#define __CUDD2_H__
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+// HA: Added for printing messages
+#ifndef MSG
+#define MSG(msg) (printf("%s = \n",(msg)));
+#endif
+
+////////////////////////////////////////////////////////////////////////
+/// INCLUDES ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+/// PARAMETERS ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+/// BASIC TYPES ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+/// MACRO DEFINITIONS ///
+////////////////////////////////////////////////////////////////////////
+
+
+////////////////////////////////////////////////////////////////////////
+/// ITERATORS ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+/// FUNCTION DECLARATIONS ///
+////////////////////////////////////////////////////////////////////////
+
+extern void Cudd2_Init ( unsigned int numVars, unsigned int numVarsZ, unsigned int numSlots, unsigned int cacheSize, unsigned long maxMemory, void * pCudd );
+extern void Cudd2_Quit ( void * pCudd );
+extern void Cudd2_bddOne ( void * pCudd, void * pResult );
+extern void Cudd2_bddIthVar ( void * pCudd, int iVar, void * pResult );
+extern void Cudd2_bddAnd ( void * pCudd, void * pArg0, void * pArg1, void * pResult );
+extern void Cudd2_bddOr ( void * pCudd, void * pArg0, void * pArg1, void * pResult );
+extern void Cudd2_bddNand ( void * pCudd, void * pArg0, void * pArg1, void * pResult );
+extern void Cudd2_bddNor ( void * pCudd, void * pArg0, void * pArg1, void * pResult );
+extern void Cudd2_bddXor ( void * pCudd, void * pArg0, void * pArg1, void * pResult );
+extern void Cudd2_bddXnor ( void * pCudd, void * pArg0, void * pArg1, void * pResult );
+extern void Cudd2_bddIte ( void * pCudd, void * pArg0, void * pArg1, void * pArg2, void * pResult );
+extern void Cudd2_bddCompose( void * pCudd, void * pArg0, void * pArg1, int v, void * pResult );
+extern void Cudd2_bddLeq ( void * pCudd, void * pArg0, void * pArg1, int Result );
+extern void Cudd2_bddEqual ( void * pCudd, void * pArg0, void * pArg1, int Result );
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
+
+////////////////////////////////////////////////////////////////////////
+/// END OF FILE ///
+////////////////////////////////////////////////////////////////////////
+
diff --git a/src/misc/hop/hop.h b/src/aig/hop/hop.h
index 37096473..af1d9cd3 100644
--- a/src/misc/hop/hop.h
+++ b/src/aig/hop/hop.h
@@ -67,11 +67,11 @@ struct Hop_Obj_t_ // 6 words
Hop_Obj_t * pNext; // strashing table
Hop_Obj_t * pFanin0; // fanin
Hop_Obj_t * pFanin1; // fanin
- unsigned long Type : 3; // object type
- unsigned long fPhase : 1; // value under 000...0 pattern
- unsigned long fMarkA : 1; // multipurpose mask
- unsigned long fMarkB : 1; // multipurpose mask
- unsigned long nRefs : 26; // reference count (level)
+ unsigned int Type : 3; // object type
+ unsigned int fPhase : 1; // value under 000...0 pattern
+ unsigned int fMarkA : 1; // multipurpose mask
+ unsigned int fMarkB : 1; // multipurpose mask
+ unsigned int nRefs : 26; // reference count (level)
int Id; // unique ID of the node
};
@@ -121,11 +121,13 @@ static inline int Hop_TruthWordNum( int nVars ) { return nVars
static inline int Hop_InfoHasBit( unsigned * p, int i ) { return (p[(i)>>5] & (1<<((i) & 31))) > 0; }
static inline void Hop_InfoSetBit( unsigned * p, int i ) { p[(i)>>5] |= (1<<((i) & 31)); }
static inline void Hop_InfoXorBit( unsigned * p, int i ) { p[(i)>>5] ^= (1<<((i) & 31)); }
+static inline int Hop_Base2Log( unsigned n ) { int r; assert( n >= 0 ); if ( n < 2 ) return n; for ( r = 0, n--; n; n >>= 1, r++ ); return r; }
+static inline int Hop_Base10Log( unsigned n ) { int r; assert( n >= 0 ); if ( n < 2 ) return n; for ( r = 0, n--; n; n /= 10, r++ ); return r; }
-static inline Hop_Obj_t * Hop_Regular( Hop_Obj_t * p ) { return (Hop_Obj_t *)((unsigned long)(p) & ~01); }
-static inline Hop_Obj_t * Hop_Not( Hop_Obj_t * p ) { return (Hop_Obj_t *)((unsigned long)(p) ^ 01); }
-static inline Hop_Obj_t * Hop_NotCond( Hop_Obj_t * p, int c ) { return (Hop_Obj_t *)((unsigned long)(p) ^ (c)); }
-static inline int Hop_IsComplement( Hop_Obj_t * p ) { return (int )(((unsigned long)p) & 01); }
+static inline Hop_Obj_t * Hop_Regular( Hop_Obj_t * p ) { return (Hop_Obj_t *)((unsigned long)(p) & ~01); }
+static inline Hop_Obj_t * Hop_Not( Hop_Obj_t * p ) { return (Hop_Obj_t *)((unsigned long)(p) ^ 01); }
+static inline Hop_Obj_t * Hop_NotCond( Hop_Obj_t * p, int c ) { return (Hop_Obj_t *)((unsigned long)(p) ^ (c)); }
+static inline int Hop_IsComplement( Hop_Obj_t * p ) { return (int)((unsigned long)(p) & 01); }
static inline Hop_Obj_t * Hop_ManConst0( Hop_Man_t * p ) { return Hop_Not(p->pConst1); }
static inline Hop_Obj_t * Hop_ManConst1( Hop_Man_t * p ) { return p->pConst1; }
@@ -268,12 +270,12 @@ static inline void Hop_ManRecycleMemory( Hop_Man_t * p, Hop_Obj_t * pEntry )
/// FUNCTION DECLARATIONS ///
////////////////////////////////////////////////////////////////////////
-/*=== aigBalance.c ========================================================*/
+/*=== hopBalance.c ========================================================*/
extern Hop_Man_t * Hop_ManBalance( Hop_Man_t * p, int fUpdateLevel );
extern Hop_Obj_t * Hop_NodeBalanceBuildSuper( Hop_Man_t * p, Vec_Ptr_t * vSuper, Hop_Type_t Type, int fUpdateLevel );
-/*=== aigCheck.c ========================================================*/
+/*=== hopCheck.c ========================================================*/
extern int Hop_ManCheck( Hop_Man_t * p );
-/*=== aigDfs.c ==========================================================*/
+/*=== hopDfs.c ==========================================================*/
extern Vec_Ptr_t * Hop_ManDfs( Hop_Man_t * p );
extern Vec_Ptr_t * Hop_ManDfsNode( Hop_Man_t * p, Hop_Obj_t * pNode );
extern int Hop_ManCountLevels( Hop_Man_t * p );
@@ -282,16 +284,16 @@ extern int Hop_DagSize( Hop_Obj_t * pObj );
extern void Hop_ConeUnmark_rec( Hop_Obj_t * pObj );
extern Hop_Obj_t * Hop_Transfer( Hop_Man_t * pSour, Hop_Man_t * pDest, Hop_Obj_t * pObj, int nVars );
extern Hop_Obj_t * Hop_Compose( Hop_Man_t * p, Hop_Obj_t * pRoot, Hop_Obj_t * pFunc, int iVar );
-/*=== aigMan.c ==========================================================*/
+/*=== hopMan.c ==========================================================*/
extern Hop_Man_t * Hop_ManStart();
extern Hop_Man_t * Hop_ManDup( Hop_Man_t * p );
extern void Hop_ManStop( Hop_Man_t * p );
extern int Hop_ManCleanup( Hop_Man_t * p );
extern void Hop_ManPrintStats( Hop_Man_t * p );
-/*=== aigMem.c ==========================================================*/
+/*=== hopMem.c ==========================================================*/
extern void Hop_ManStartMemory( Hop_Man_t * p );
extern void Hop_ManStopMemory( Hop_Man_t * p );
-/*=== aigObj.c ==========================================================*/
+/*=== hopObj.c ==========================================================*/
extern Hop_Obj_t * Hop_ObjCreatePi( Hop_Man_t * p );
extern Hop_Obj_t * Hop_ObjCreatePo( Hop_Man_t * p, Hop_Obj_t * pDriver );
extern Hop_Obj_t * Hop_ObjCreate( Hop_Man_t * p, Hop_Obj_t * pGhost );
@@ -301,7 +303,7 @@ extern void Hop_ObjDelete( Hop_Man_t * p, Hop_Obj_t * pObj );
extern void Hop_ObjDelete_rec( Hop_Man_t * p, Hop_Obj_t * pObj );
extern Hop_Obj_t * Hop_ObjRepr( Hop_Obj_t * pObj );
extern void Hop_ObjCreateChoice( Hop_Obj_t * pOld, Hop_Obj_t * pNew );
-/*=== aigOper.c =========================================================*/
+/*=== hopOper.c =========================================================*/
extern Hop_Obj_t * Hop_IthVar( Hop_Man_t * p, int i );
extern Hop_Obj_t * Hop_Oper( Hop_Man_t * p, Hop_Obj_t * p0, Hop_Obj_t * p1, Hop_Type_t Type );
extern Hop_Obj_t * Hop_And( Hop_Man_t * p, Hop_Obj_t * p0, Hop_Obj_t * p1 );
@@ -313,13 +315,13 @@ extern Hop_Obj_t * Hop_Miter( Hop_Man_t * p, Vec_Ptr_t * vPairs );
extern Hop_Obj_t * Hop_CreateAnd( Hop_Man_t * p, int nVars );
extern Hop_Obj_t * Hop_CreateOr( Hop_Man_t * p, int nVars );
extern Hop_Obj_t * Hop_CreateExor( Hop_Man_t * p, int nVars );
-/*=== aigTable.c ========================================================*/
+/*=== hopTable.c ========================================================*/
extern Hop_Obj_t * Hop_TableLookup( Hop_Man_t * p, Hop_Obj_t * pGhost );
extern void Hop_TableInsert( Hop_Man_t * p, Hop_Obj_t * pObj );
extern void Hop_TableDelete( Hop_Man_t * p, Hop_Obj_t * pObj );
extern int Hop_TableCountEntries( Hop_Man_t * p );
extern void Hop_TableProfile( Hop_Man_t * p );
-/*=== aigUtil.c =========================================================*/
+/*=== hopUtil.c =========================================================*/
extern void Hop_ManIncrementTravId( Hop_Man_t * p );
extern void Hop_ManCleanData( Hop_Man_t * p );
extern void Hop_ObjCleanData_rec( Hop_Obj_t * pObj );
diff --git a/src/misc/hop/hopBalance.c b/src/aig/hop/hopBalance.c
index 73c90685..73c90685 100644
--- a/src/misc/hop/hopBalance.c
+++ b/src/aig/hop/hopBalance.c
diff --git a/src/misc/hop/hopCheck.c b/src/aig/hop/hopCheck.c
index 9120906f..9120906f 100644
--- a/src/misc/hop/hopCheck.c
+++ b/src/aig/hop/hopCheck.c
diff --git a/src/misc/hop/hopDfs.c b/src/aig/hop/hopDfs.c
index 49e5f221..49e5f221 100644
--- a/src/misc/hop/hopDfs.c
+++ b/src/aig/hop/hopDfs.c
diff --git a/src/misc/hop/hopMan.c b/src/aig/hop/hopMan.c
index 99f5d316..99f5d316 100644
--- a/src/misc/hop/hopMan.c
+++ b/src/aig/hop/hopMan.c
diff --git a/src/misc/hop/hopMem.c b/src/aig/hop/hopMem.c
index 0665470a..0665470a 100644
--- a/src/misc/hop/hopMem.c
+++ b/src/aig/hop/hopMem.c
diff --git a/src/misc/hop/hopObj.c b/src/aig/hop/hopObj.c
index c8e70dd3..c8e70dd3 100644
--- a/src/misc/hop/hopObj.c
+++ b/src/aig/hop/hopObj.c
diff --git a/src/misc/hop/hopOper.c b/src/aig/hop/hopOper.c
index a31ca0f2..a31ca0f2 100644
--- a/src/misc/hop/hopOper.c
+++ b/src/aig/hop/hopOper.c
diff --git a/src/misc/hop/hopTable.c b/src/aig/hop/hopTable.c
index 8e61ef36..76390054 100644
--- a/src/misc/hop/hopTable.c
+++ b/src/aig/hop/hopTable.c
@@ -28,8 +28,8 @@
static unsigned long Hop_Hash( Hop_Obj_t * pObj, int TableSize )
{
unsigned long Key = Hop_ObjIsExor(pObj) * 1699;
- Key ^= (long)Hop_ObjFanin0(pObj) * 7937;
- Key ^= (long)Hop_ObjFanin1(pObj) * 2971;
+ Key ^= Hop_ObjFanin0(pObj)->Id * 7937;
+ Key ^= Hop_ObjFanin1(pObj)->Id * 2971;
Key ^= Hop_ObjFaninC0(pObj) * 911;
Key ^= Hop_ObjFaninC1(pObj) * 353;
return Key % TableSize;
diff --git a/src/misc/hop/hopUtil.c b/src/aig/hop/hopUtil.c
index 2fb595cd..87fdb15e 100644
--- a/src/misc/hop/hopUtil.c
+++ b/src/aig/hop/hopUtil.c
@@ -318,7 +318,6 @@ Hop_Obj_t * Hop_ObjRecognizeMux( Hop_Obj_t * pNode, Hop_Obj_t ** ppNodeT, Hop_Ob
***********************************************************************/
void Hop_ObjPrintEqn( FILE * pFile, Hop_Obj_t * pObj, Vec_Vec_t * vLevels, int Level )
{
-/*
Vec_Ptr_t * vSuper;
Hop_Obj_t * pFanin;
int fCompl, i;
@@ -350,7 +349,6 @@ void Hop_ObjPrintEqn( FILE * pFile, Hop_Obj_t * pObj, Vec_Vec_t * vLevels, int L
}
fprintf( pFile, "%s", (Level==0? "" : ")") );
return;
-*/
}
/**Function*************************************************************
@@ -367,7 +365,6 @@ void Hop_ObjPrintEqn( FILE * pFile, Hop_Obj_t * pObj, Vec_Vec_t * vLevels, int L
***********************************************************************/
void Hop_ObjPrintVerilog( FILE * pFile, Hop_Obj_t * pObj, Vec_Vec_t * vLevels, int Level )
{
-/*
Vec_Ptr_t * vSuper;
Hop_Obj_t * pFanin, * pFanin0, * pFanin1, * pFaninC;
int fCompl, i;
@@ -439,7 +436,6 @@ void Hop_ObjPrintVerilog( FILE * pFile, Hop_Obj_t * pObj, Vec_Vec_t * vLevels, i
}
fprintf( pFile, "%s", (Level==0? "" : ")") );
return;
-*/
}
@@ -527,7 +523,7 @@ void Hop_ManDumpBlif( Hop_Man_t * p, char * pFileName )
pObj->pData = (void *)Counter++;
Vec_PtrForEachEntry( vNodes, pObj, i )
pObj->pData = (void *)Counter++;
- nDigits = Extra_Base10Log( Counter );
+ nDigits = Hop_Base10Log( Counter );
// write the file
pFile = fopen( pFileName, "w" );
fprintf( pFile, "# BLIF file written by procedure Hop_ManDumpBlif() in ABC\n" );
diff --git a/src/misc/hop/hop_.c b/src/aig/hop/hop_.c
index 468413fa..468413fa 100644
--- a/src/misc/hop/hop_.c
+++ b/src/aig/hop/hop_.c
diff --git a/src/misc/hop/module.make b/src/aig/hop/module.make
index b06d91fd..b06d91fd 100644
--- a/src/misc/hop/module.make
+++ b/src/aig/hop/module.make
diff --git a/src/abc8/ioa/ioa.h b/src/aig/ioa/ioa.h
index 2d7499cd..e697a729 100644
--- a/src/abc8/ioa/ioa.h
+++ b/src/aig/ioa/ioa.h
@@ -35,7 +35,7 @@ extern "C" {
#include <assert.h>
#include <time.h>
-#include "vec2.h"
+#include "vec.h"
//#include "bar.h"
#include "aig.h"
diff --git a/src/abc8/ioa/ioaReadAig.c b/src/aig/ioa/ioaReadAig.c
index 498cdd30..498cdd30 100644
--- a/src/abc8/ioa/ioaReadAig.c
+++ b/src/aig/ioa/ioaReadAig.c
diff --git a/src/abc8/ioa/ioaUtil.c b/src/aig/ioa/ioaUtil.c
index 79dcca1e..79dcca1e 100644
--- a/src/abc8/ioa/ioaUtil.c
+++ b/src/aig/ioa/ioaUtil.c
diff --git a/src/abc8/ioa/ioaWriteAig.c b/src/aig/ioa/ioaWriteAig.c
index 166dca4b..166dca4b 100644
--- a/src/abc8/ioa/ioaWriteAig.c
+++ b/src/aig/ioa/ioaWriteAig.c
diff --git a/src/abc8/ioa/module.make b/src/aig/ioa/module.make
index 66b4a0d5..66b4a0d5 100644
--- a/src/abc8/ioa/module.make
+++ b/src/aig/ioa/module.make
diff --git a/src/aig/ivy/attr.h b/src/aig/ivy/attr.h
new file mode 100644
index 00000000..16cf0b84
--- /dev/null
+++ b/src/aig/ivy/attr.h
@@ -0,0 +1,414 @@
+/**CFile****************************************************************
+
+ FileName [attr.h]
+
+ SystemName [ABC: Logic synthesis and verification system.]
+
+ PackageName [Network attributes.]
+
+ Synopsis [External declarations.]
+
+ Author [Alan Mishchenko]
+
+ Affiliation [UC Berkeley]
+
+ Date [Ver. 1.0. Started - June 20, 2005.]
+
+ Revision [$Id: attr.h,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#ifndef __ATTR_H__
+#define __ATTR_H__
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+////////////////////////////////////////////////////////////////////////
+/// INCLUDES ///
+////////////////////////////////////////////////////////////////////////
+
+#include "extra.h"
+
+////////////////////////////////////////////////////////////////////////
+/// PARAMETERS ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+/// BASIC TYPES ///
+////////////////////////////////////////////////////////////////////////
+
+typedef struct Attr_ManStruct_t_ Attr_Man_t;
+struct Attr_ManStruct_t_
+{
+ // attribute info
+ int nAttrSize; // the size of each attribute in bytes
+ Extra_MmFixed_t * pManMem; // memory manager for attributes
+ int nAttrs; // the number of attributes allocated
+ void ** pAttrs; // the array of attributes
+ int fUseInt; // uses integer attributes
+ // attribute specific info
+ void * pManAttr; // the manager for this attribute
+ void (*pFuncFreeMan) (void *); // the procedure to call to free attribute-specific manager
+ void (*pFuncFreeObj) (void *, void *); // the procedure to call to free attribute-specific data
+};
+
+// at any time, an attribute of the given ID can be
+// - not available (p->nAttrs < Id)
+// - available but not allocated (p->nAttrs >= Id && p->pAttrs[Id] == NULL)
+// - available and allocated (p->nAttrs >= Id && p->pAttrs[Id] != NULL)
+
+////////////////////////////////////////////////////////////////////////
+/// MACRO DEFINITIONS ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+/// FUNCTION DECLARATIONS ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+ Synopsis [Allocates the attribute manager.]
+
+ Description [The manager is simple if it does not need memory manager.]
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+static inline Attr_Man_t * Attr_ManAlloc( int nAttrSize, int fManMem )
+{
+ Attr_Man_t * p;
+ p = ALLOC( Attr_Man_t, 1 );
+ memset( p, 0, sizeof(Attr_Man_t) );
+ p->nAttrSize = nAttrSize;
+ if ( fManMem )
+ p->pManMem = Extra_MmFixedStart( nAttrSize );
+ return p;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Start the attribute manager for integers.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+static inline Attr_Man_t * Attr_ManStartInt( int nAttrs )
+{
+ Attr_Man_t * p;
+ p = Attr_ManAlloc( sizeof(int), 0 );
+ p->nAttrs = nAttrs;
+ p->pAttrs = (void **)ALLOC( int, nAttrs );
+ memset( (int *)p->pAttrs, 0, sizeof(int) * nAttrs );
+ p->fUseInt = 1;
+ return p;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Start the attribute manager for pointers.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+static inline Attr_Man_t * Attr_ManStartPtr( int nAttrs )
+{
+ Attr_Man_t * p;
+ p = Attr_ManAlloc( sizeof(void *), 0 );
+ p->nAttrs = nAttrs;
+ p->pAttrs = ALLOC( void *, nAttrs );
+ memset( p->pAttrs, 0, sizeof(void *) * nAttrs );
+ return p;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Start the attribute manager for the fixed entry size.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+static inline Attr_Man_t * Attr_ManStartPtrMem( int nAttrs, int nAttrSize )
+{
+ Attr_Man_t * p;
+ int i;
+ p = Attr_ManAlloc( nAttrSize, 1 );
+ p->nAttrs = nAttrs;
+ p->pAttrs = ALLOC( void *, nAttrs );
+ for ( i = 0; i < p->nAttrs; i++ )
+ {
+ p->pAttrs[i] = Extra_MmFixedEntryFetch( p->pManMem );
+ memset( p->pAttrs[i], 0, nAttrSize );
+ }
+ return p;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Stop the attribute manager.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+static inline void Attr_ManStop( Attr_Man_t * p )
+{
+ // free the attributes of objects
+ if ( p->pFuncFreeObj )
+ {
+ int i;
+ if ( p->fUseInt )
+ {
+ for ( i = 0; i < p->nAttrs; i++ )
+ if ( ((int *)p->pAttrs)[i] )
+ p->pFuncFreeObj( p->pManAttr, (void *)((int *)p->pAttrs)[i] );
+ }
+ else
+ {
+ for ( i = 0; i < p->nAttrs; i++ )
+ if ( p->pAttrs[i] )
+ p->pFuncFreeObj( p->pManAttr, p->pAttrs[i] );
+ }
+ }
+ // free the attribute manager
+ if ( p->pManAttr && p->pFuncFreeMan )
+ p->pFuncFreeMan( p->pManAttr );
+ // free the memory manager
+ if ( p->pManMem )
+ Extra_MmFixedStop( p->pManMem);
+ // free the attribute manager
+ FREE( p->pAttrs );
+ free( p );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Reads the attribute of the given object.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+static inline int Attr_ManReadAttrInt( Attr_Man_t * p, int Id )
+{
+ assert( p->fUseInt );
+ if ( Id >= p->nAttrs )
+ return 0;
+ return ((int *)p->pAttrs)[Id];
+}
+
+/**Function*************************************************************
+
+ Synopsis [Reads the attribute of the given object.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+static inline void * Attr_ManReadAttrPtr( Attr_Man_t * p, int Id )
+{
+ assert( !p->fUseInt );
+ if ( Id >= p->nAttrs )
+ return NULL;
+ return p->pAttrs[Id];
+}
+
+/**Function*************************************************************
+
+ Synopsis [Writes the attribute of the given object.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+static inline void Attr_ManWriteAttrInt( Attr_Man_t * p, int Id, int Attr )
+{
+ assert( p->fUseInt );
+ ((int *)p->pAttrs)[Id] = Attr;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Writes the attribute of the given object.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+static inline void Attr_ManWriteAttrPtr( Attr_Man_t * p, int Id, void * pAttr )
+{
+ assert( !p->fUseInt );
+ assert( p->pManMem == NULL );
+ p->pAttrs[Id] = pAttr;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Returns or creates the pointer to the attribute of the given object.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+static inline int * Attr_ManFetchSpotInt( Attr_Man_t * p, int Id )
+{
+ assert( p->fUseInt );
+ if ( Id >= p->nAttrs )
+ {
+ // save the old size
+ int i, nAttrsOld = p->nAttrs;
+ // get the new size
+ p->nAttrs = p->nAttrs? 2*p->nAttrs : 1024;
+ p->pAttrs = realloc( p->pAttrs, sizeof(int) * p->nAttrs );
+ // fill in the empty spots
+ for ( i = nAttrsOld; i < p->nAttrs; i++ )
+ ((int *)p->pAttrs)[Id] = 0;
+ }
+ return ((int *)p->pAttrs) + Id;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Returns or creates the pointer to the attribute of the given object.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+static inline void ** Attr_ManFetchSpotPtr( Attr_Man_t * p, int Id )
+{
+ assert( !p->fUseInt );
+ if ( Id >= p->nAttrs )
+ {
+ // save the old size
+ int i, nAttrsOld = p->nAttrs;
+ // get the new size
+ p->nAttrs = p->nAttrs? 2*p->nAttrs : 1024;
+ p->pAttrs = realloc( p->pAttrs, sizeof(void *) * p->nAttrs );
+ // fill in the empty spots
+ for ( i = nAttrsOld; i < p->nAttrs; i++ )
+ p->pAttrs[Id] = NULL;
+ }
+ // if memory manager is available but entry is not created, create it
+ if ( p->pManMem && p->pAttrs[Id] != NULL )
+ {
+ p->pAttrs[Id] = Extra_MmFixedEntryFetch( p->pManMem );
+ memset( p->pAttrs[Id], 0, p->nAttrSize );
+ }
+ return p->pAttrs + Id;
+}
+
+
+/**Function*************************************************************
+
+ Synopsis [Returns or creates the attribute of the given object.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+static inline int Attr_ManFetchAttrInt( Attr_Man_t * p, int Id )
+{
+ return *Attr_ManFetchSpotInt( p, Id );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Returns or creates the attribute of the given object.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+static inline void * Attr_ManFetchAttrPtr( Attr_Man_t * p, int Id )
+{
+ return *Attr_ManFetchSpotPtr( p, Id );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Sets the attribute of the given object.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+static inline void Attr_ManSetAttrInt( Attr_Man_t * p, int Id, int Attr )
+{
+ *Attr_ManFetchSpotInt( p, Id ) = Attr;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Sets the attribute of the given object.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+static inline void Attr_ManSetAttrPtr( Attr_Man_t * p, int Id, void * pAttr )
+{
+ assert( p->pManMem == NULL );
+ *Attr_ManFetchSpotPtr( p, Id ) = pAttr;
+}
+
+
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
+
+////////////////////////////////////////////////////////////////////////
+/// END OF FILE ///
+////////////////////////////////////////////////////////////////////////
+
diff --git a/src/aig/ivy/ivy.h b/src/aig/ivy/ivy.h
new file mode 100644
index 00000000..c7435a63
--- /dev/null
+++ b/src/aig/ivy/ivy.h
@@ -0,0 +1,557 @@
+/**CFile****************************************************************
+
+ FileName [ivy.h]
+
+ SystemName [ABC: Logic synthesis and verification system.]
+
+ PackageName [And-Inverter Graph package.]
+
+ Synopsis [External declarations.]
+
+ Author [Alan Mishchenko]
+
+ Affiliation [UC Berkeley]
+
+ Date [Ver. 1.0. Started - May 11, 2006.]
+
+ Revision [$Id: ivy.c,v 1.00 2006/05/11 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#ifndef __IVY_H__
+#define __IVY_H__
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+////////////////////////////////////////////////////////////////////////
+/// INCLUDES ///
+////////////////////////////////////////////////////////////////////////
+
+#include <stdio.h>
+#include "extra.h"
+#include "vec.h"
+
+////////////////////////////////////////////////////////////////////////
+/// PARAMETERS ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+/// BASIC TYPES ///
+////////////////////////////////////////////////////////////////////////
+
+typedef struct Ivy_Man_t_ Ivy_Man_t;
+typedef struct Ivy_Obj_t_ Ivy_Obj_t;
+typedef int Ivy_Edge_t;
+typedef struct Ivy_FraigParams_t_ Ivy_FraigParams_t;
+
+// object types
+typedef enum {
+ IVY_NONE, // 0: non-existent object
+ IVY_PI, // 1: primary input (and constant 1 node)
+ IVY_PO, // 2: primary output
+ IVY_ASSERT, // 3: assertion
+ IVY_LATCH, // 4: sequential element
+ IVY_AND, // 5: AND node
+ IVY_EXOR, // 6: EXOR node
+ IVY_BUF, // 7: buffer (temporary)
+ IVY_VOID // 8: unused object
+} Ivy_Type_t;
+
+// latch initial values
+typedef enum {
+ IVY_INIT_NONE, // 0: not a latch
+ IVY_INIT_0, // 1: zero
+ IVY_INIT_1, // 2: one
+ IVY_INIT_DC // 3: don't-care
+} Ivy_Init_t;
+
+// the AIG node
+struct Ivy_Obj_t_ // 24 bytes (32-bit) or 32 bytes (64-bit) // 10 words - 16 words
+{
+ int Id; // integer ID
+ int TravId; // traversal ID
+ unsigned Type : 4; // object type
+ unsigned fMarkA : 1; // multipurpose mask
+ unsigned fMarkB : 1; // multipurpose mask
+ unsigned fExFan : 1; // set to 1 if last fanout added is EXOR
+ unsigned fPhase : 1; // value under 000...0 pattern
+ unsigned fFailTfo : 1; // the TFO of the failed node
+ unsigned Init : 2; // latch initial value
+ unsigned Level : 21; // logic level
+ int nRefs; // reference counter
+ Ivy_Obj_t * pFanin0; // fanin
+ Ivy_Obj_t * pFanin1; // fanin
+ Ivy_Obj_t * pFanout; // fanout
+ Ivy_Obj_t * pNextFan0; // next fanout of the first fanin
+ Ivy_Obj_t * pNextFan1; // next fanout of the second fanin
+ Ivy_Obj_t * pPrevFan0; // prev fanout of the first fanin
+ Ivy_Obj_t * pPrevFan1; // prev fanout of the second fanin
+ Ivy_Obj_t * pEquiv; // equivalent node
+};
+
+// the AIG manager
+struct Ivy_Man_t_
+{
+ // AIG nodes
+ Vec_Ptr_t * vPis; // the array of PIs
+ Vec_Ptr_t * vPos; // the array of POs
+ Vec_Ptr_t * vBufs; // the array of buffers
+ Vec_Ptr_t * vObjs; // the array of objects
+ Ivy_Obj_t * pConst1; // the constant 1 node
+ Ivy_Obj_t Ghost; // the ghost node
+ // AIG node counters
+ int nObjs[IVY_VOID];// the number of objects by type
+ int nCreated; // the number of created objects
+ int nDeleted; // the number of deleted objects
+ // stuctural hash table
+ int * pTable; // structural hash table
+ int nTableSize; // structural hash table size
+ // various data members
+ int fCatchExor; // set to 1 to detect EXORs
+ int nTravIds; // the traversal ID
+ int nLevelMax; // the maximum level
+ Vec_Int_t * vRequired; // required times
+ int fFanout; // fanout is allocated
+ void * pData; // the temporary data
+ void * pCopy; // the temporary data
+ Ivy_Man_t * pHaig; // history AIG if present
+ int nClassesSkip; // the number of skipped classes
+ // memory management
+ Vec_Ptr_t * vChunks; // allocated memory pieces
+ Vec_Ptr_t * vPages; // memory pages used by nodes
+ Ivy_Obj_t * pListFree; // the list of free nodes
+ // timing statistics
+ int time1;
+ int time2;
+};
+
+struct Ivy_FraigParams_t_
+{
+ int nSimWords; // the number of words in the simulation info
+ double dSimSatur; // the ratio of refined classes when saturation is reached
+ int fPatScores; // enables simulation pattern scoring
+ int MaxScore; // max score after which resimulation is used
+ double dActConeRatio; // the ratio of cone to be bumped
+ double dActConeBumpMax; // the largest bump in activity
+ int fProve; // prove the miter outputs
+ int fVerbose; // verbose output
+ int fDoSparse; // skip sparse functions
+ int nBTLimitNode; // conflict limit at a node
+ int nBTLimitMiter; // conflict limit at an output
+// int nBTLimitGlobal; // conflict limit global
+// int nInsLimitNode; // inspection limit at a node
+// int nInsLimitMiter; // inspection limit at an output
+// int nInsLimitGlobal; // inspection limit global
+};
+
+
+#define IVY_CUT_LIMIT 256
+#define IVY_CUT_INPUT 6
+
+typedef struct Ivy_Cut_t_ Ivy_Cut_t;
+struct Ivy_Cut_t_
+{
+ int nLatches;
+ short nSize;
+ short nSizeMax;
+ int pArray[IVY_CUT_INPUT];
+ unsigned uHash;
+};
+
+typedef struct Ivy_Store_t_ Ivy_Store_t;
+struct Ivy_Store_t_
+{
+ int nCuts;
+ int nCutsM;
+ int nCutsMax;
+ int fSatur;
+ Ivy_Cut_t pCuts[IVY_CUT_LIMIT]; // storage for cuts
+};
+
+#define IVY_LEAF_MASK 255
+#define IVY_LEAF_BITS 8
+
+////////////////////////////////////////////////////////////////////////
+/// MACRO DEFINITIONS ///
+////////////////////////////////////////////////////////////////////////
+
+#define IVY_MIN(a,b) (((a) < (b))? (a) : (b))
+#define IVY_MAX(a,b) (((a) > (b))? (a) : (b))
+
+static inline int Ivy_BitWordNum( int nBits ) { return (nBits>>5) + ((nBits&31) > 0); }
+static inline int Ivy_TruthWordNum( int nVars ) { return nVars <= 5 ? 1 : (1 << (nVars - 5)); }
+static inline int Ivy_InfoHasBit( unsigned * p, int i ) { return (p[(i)>>5] & (1<<((i) & 31))) > 0; }
+static inline void Ivy_InfoSetBit( unsigned * p, int i ) { p[(i)>>5] |= (1<<((i) & 31)); }
+static inline void Ivy_InfoXorBit( unsigned * p, int i ) { p[(i)>>5] ^= (1<<((i) & 31)); }
+
+static inline Ivy_Obj_t * Ivy_Regular( Ivy_Obj_t * p ) { return (Ivy_Obj_t *)((unsigned long)(p) & ~01); }
+static inline Ivy_Obj_t * Ivy_Not( Ivy_Obj_t * p ) { return (Ivy_Obj_t *)((unsigned long)(p) ^ 01); }
+static inline Ivy_Obj_t * Ivy_NotCond( Ivy_Obj_t * p, int c ) { return (Ivy_Obj_t *)((unsigned long)(p) ^ (c)); }
+static inline int Ivy_IsComplement( Ivy_Obj_t * p ) { return (int)((unsigned long)(p) & 01); }
+
+static inline Ivy_Obj_t * Ivy_ManConst0( Ivy_Man_t * p ) { return Ivy_Not(p->pConst1); }
+static inline Ivy_Obj_t * Ivy_ManConst1( Ivy_Man_t * p ) { return p->pConst1; }
+static inline Ivy_Obj_t * Ivy_ManGhost( Ivy_Man_t * p ) { return &p->Ghost; }
+static inline Ivy_Obj_t * Ivy_ManPi( Ivy_Man_t * p, int i ) { return (Ivy_Obj_t *)Vec_PtrEntry(p->vPis, i); }
+static inline Ivy_Obj_t * Ivy_ManPo( Ivy_Man_t * p, int i ) { return (Ivy_Obj_t *)Vec_PtrEntry(p->vPos, i); }
+static inline Ivy_Obj_t * Ivy_ManObj( Ivy_Man_t * p, int i ) { return (Ivy_Obj_t *)Vec_PtrEntry(p->vObjs, i); }
+
+static inline Ivy_Edge_t Ivy_EdgeCreate( int Id, int fCompl ) { return (Id << 1) | fCompl; }
+static inline int Ivy_EdgeId( Ivy_Edge_t Edge ) { return Edge >> 1; }
+static inline int Ivy_EdgeIsComplement( Ivy_Edge_t Edge ) { return Edge & 1; }
+static inline Ivy_Edge_t Ivy_EdgeRegular( Ivy_Edge_t Edge ) { return (Edge >> 1) << 1; }
+static inline Ivy_Edge_t Ivy_EdgeNot( Ivy_Edge_t Edge ) { return Edge ^ 1; }
+static inline Ivy_Edge_t Ivy_EdgeNotCond( Ivy_Edge_t Edge, int fCond ) { return Edge ^ fCond; }
+static inline Ivy_Edge_t Ivy_EdgeFromNode( Ivy_Obj_t * pNode ) { return Ivy_EdgeCreate( Ivy_Regular(pNode)->Id, Ivy_IsComplement(pNode) ); }
+static inline Ivy_Obj_t * Ivy_EdgeToNode( Ivy_Man_t * p, Ivy_Edge_t Edge ){ return Ivy_NotCond( Ivy_ManObj(p, Ivy_EdgeId(Edge)), Ivy_EdgeIsComplement(Edge) ); }
+
+static inline int Ivy_LeafCreate( int Id, int Lat ) { return (Id << IVY_LEAF_BITS) | Lat; }
+static inline int Ivy_LeafId( int Leaf ) { return Leaf >> IVY_LEAF_BITS; }
+static inline int Ivy_LeafLat( int Leaf ) { return Leaf & IVY_LEAF_MASK; }
+
+static inline int Ivy_ManPiNum( Ivy_Man_t * p ) { return p->nObjs[IVY_PI]; }
+static inline int Ivy_ManPoNum( Ivy_Man_t * p ) { return p->nObjs[IVY_PO]; }
+static inline int Ivy_ManAssertNum( Ivy_Man_t * p ) { return p->nObjs[IVY_ASSERT]; }
+static inline int Ivy_ManLatchNum( Ivy_Man_t * p ) { return p->nObjs[IVY_LATCH]; }
+static inline int Ivy_ManAndNum( Ivy_Man_t * p ) { return p->nObjs[IVY_AND]; }
+static inline int Ivy_ManExorNum( Ivy_Man_t * p ) { return p->nObjs[IVY_EXOR]; }
+static inline int Ivy_ManBufNum( Ivy_Man_t * p ) { return p->nObjs[IVY_BUF]; }
+static inline int Ivy_ManObjNum( Ivy_Man_t * p ) { return p->nCreated - p->nDeleted; }
+static inline int Ivy_ManObjIdMax( Ivy_Man_t * p ) { return Vec_PtrSize(p->vObjs)-1; }
+static inline int Ivy_ManNodeNum( Ivy_Man_t * p ) { return p->nObjs[IVY_AND]+p->nObjs[IVY_EXOR];}
+static inline int Ivy_ManHashObjNum( Ivy_Man_t * p ) { return p->nObjs[IVY_AND]+p->nObjs[IVY_EXOR]+p->nObjs[IVY_LATCH]; }
+static inline int Ivy_ManGetCost( Ivy_Man_t * p ) { return p->nObjs[IVY_AND]+3*p->nObjs[IVY_EXOR]+8*p->nObjs[IVY_LATCH]; }
+
+static inline Ivy_Type_t Ivy_ObjType( Ivy_Obj_t * pObj ) { return pObj->Type; }
+static inline Ivy_Init_t Ivy_ObjInit( Ivy_Obj_t * pObj ) { return pObj->Init; }
+static inline int Ivy_ObjIsConst1( Ivy_Obj_t * pObj ) { return pObj->Id == 0; }
+static inline int Ivy_ObjIsGhost( Ivy_Obj_t * pObj ) { return pObj->Id < 0; }
+static inline int Ivy_ObjIsNone( Ivy_Obj_t * pObj ) { return pObj->Type == IVY_NONE; }
+static inline int Ivy_ObjIsPi( Ivy_Obj_t * pObj ) { return pObj->Type == IVY_PI; }
+static inline int Ivy_ObjIsPo( Ivy_Obj_t * pObj ) { return pObj->Type == IVY_PO; }
+static inline int Ivy_ObjIsCi( Ivy_Obj_t * pObj ) { return pObj->Type == IVY_PI || pObj->Type == IVY_LATCH; }
+static inline int Ivy_ObjIsCo( Ivy_Obj_t * pObj ) { return pObj->Type == IVY_PO || pObj->Type == IVY_LATCH; }
+static inline int Ivy_ObjIsAssert( Ivy_Obj_t * pObj ) { return pObj->Type == IVY_ASSERT; }
+static inline int Ivy_ObjIsLatch( Ivy_Obj_t * pObj ) { return pObj->Type == IVY_LATCH; }
+static inline int Ivy_ObjIsAnd( Ivy_Obj_t * pObj ) { return pObj->Type == IVY_AND; }
+static inline int Ivy_ObjIsExor( Ivy_Obj_t * pObj ) { return pObj->Type == IVY_EXOR; }
+static inline int Ivy_ObjIsBuf( Ivy_Obj_t * pObj ) { return pObj->Type == IVY_BUF; }
+static inline int Ivy_ObjIsNode( Ivy_Obj_t * pObj ) { return pObj->Type == IVY_AND || pObj->Type == IVY_EXOR; }
+static inline int Ivy_ObjIsTerm( Ivy_Obj_t * pObj ) { return pObj->Type == IVY_PI || pObj->Type == IVY_PO || pObj->Type == IVY_ASSERT; }
+static inline int Ivy_ObjIsHash( Ivy_Obj_t * pObj ) { return pObj->Type == IVY_AND || pObj->Type == IVY_EXOR || pObj->Type == IVY_LATCH; }
+static inline int Ivy_ObjIsOneFanin( Ivy_Obj_t * pObj ) { return pObj->Type == IVY_PO || pObj->Type == IVY_ASSERT || pObj->Type == IVY_BUF || pObj->Type == IVY_LATCH; }
+
+static inline int Ivy_ObjIsMarkA( Ivy_Obj_t * pObj ) { return pObj->fMarkA; }
+static inline void Ivy_ObjSetMarkA( Ivy_Obj_t * pObj ) { pObj->fMarkA = 1; }
+static inline void Ivy_ObjClearMarkA( Ivy_Obj_t * pObj ) { pObj->fMarkA = 0; }
+
+static inline void Ivy_ObjSetTravId( Ivy_Obj_t * pObj, int TravId ) { pObj->TravId = TravId; }
+static inline void Ivy_ObjSetTravIdCurrent( Ivy_Man_t * p, Ivy_Obj_t * pObj ) { pObj->TravId = p->nTravIds; }
+static inline void Ivy_ObjSetTravIdPrevious( Ivy_Man_t * p, Ivy_Obj_t * pObj ) { pObj->TravId = p->nTravIds - 1; }
+static inline int Ivy_ObjIsTravIdCurrent( Ivy_Man_t * p, Ivy_Obj_t * pObj ) { return (int )((int)pObj->TravId == p->nTravIds); }
+static inline int Ivy_ObjIsTravIdPrevious( Ivy_Man_t * p, Ivy_Obj_t * pObj ) { return (int )((int)pObj->TravId == p->nTravIds - 1); }
+
+static inline int Ivy_ObjId( Ivy_Obj_t * pObj ) { return pObj->Id; }
+static inline int Ivy_ObjTravId( Ivy_Obj_t * pObj ) { return pObj->TravId; }
+static inline int Ivy_ObjPhase( Ivy_Obj_t * pObj ) { return pObj->fPhase; }
+static inline int Ivy_ObjExorFanout( Ivy_Obj_t * pObj ) { return pObj->fExFan; }
+static inline int Ivy_ObjRefs( Ivy_Obj_t * pObj ) { return pObj->nRefs; }
+static inline void Ivy_ObjRefsInc( Ivy_Obj_t * pObj ) { pObj->nRefs++; }
+static inline void Ivy_ObjRefsDec( Ivy_Obj_t * pObj ) { assert( pObj->nRefs > 0 ); pObj->nRefs--; }
+static inline int Ivy_ObjFaninId0( Ivy_Obj_t * pObj ) { return pObj->pFanin0? Ivy_ObjId(Ivy_Regular(pObj->pFanin0)) : 0; }
+static inline int Ivy_ObjFaninId1( Ivy_Obj_t * pObj ) { return pObj->pFanin1? Ivy_ObjId(Ivy_Regular(pObj->pFanin1)) : 0; }
+static inline int Ivy_ObjFaninC0( Ivy_Obj_t * pObj ) { return Ivy_IsComplement(pObj->pFanin0); }
+static inline int Ivy_ObjFaninC1( Ivy_Obj_t * pObj ) { return Ivy_IsComplement(pObj->pFanin1); }
+static inline Ivy_Obj_t * Ivy_ObjFanin0( Ivy_Obj_t * pObj ) { return Ivy_Regular(pObj->pFanin0); }
+static inline Ivy_Obj_t * Ivy_ObjFanin1( Ivy_Obj_t * pObj ) { return Ivy_Regular(pObj->pFanin1); }
+static inline Ivy_Obj_t * Ivy_ObjChild0( Ivy_Obj_t * pObj ) { return pObj->pFanin0; }
+static inline Ivy_Obj_t * Ivy_ObjChild1( Ivy_Obj_t * pObj ) { return pObj->pFanin1; }
+static inline Ivy_Obj_t * Ivy_ObjChild0Equiv( Ivy_Obj_t * pObj ) { assert( !Ivy_IsComplement(pObj) ); return Ivy_ObjFanin0(pObj)? Ivy_NotCond(Ivy_ObjFanin0(pObj)->pEquiv, Ivy_ObjFaninC0(pObj)) : NULL; }
+static inline Ivy_Obj_t * Ivy_ObjChild1Equiv( Ivy_Obj_t * pObj ) { assert( !Ivy_IsComplement(pObj) ); return Ivy_ObjFanin1(pObj)? Ivy_NotCond(Ivy_ObjFanin1(pObj)->pEquiv, Ivy_ObjFaninC1(pObj)) : NULL; }
+static inline Ivy_Obj_t * Ivy_ObjEquiv( Ivy_Obj_t * pObj ) { return Ivy_Regular(pObj)->pEquiv? Ivy_NotCond(Ivy_Regular(pObj)->pEquiv, Ivy_IsComplement(pObj)) : NULL; }
+static inline int Ivy_ObjLevel( Ivy_Obj_t * pObj ) { return pObj->Level; }
+static inline int Ivy_ObjLevelNew( Ivy_Obj_t * pObj ) { return 1 + Ivy_ObjIsExor(pObj) + IVY_MAX(Ivy_ObjFanin0(pObj)->Level, Ivy_ObjFanin1(pObj)->Level); }
+static inline int Ivy_ObjFaninPhase( Ivy_Obj_t * pObj ) { return Ivy_IsComplement(pObj)? !Ivy_Regular(pObj)->fPhase : pObj->fPhase; }
+
+static inline void Ivy_ObjClean( Ivy_Obj_t * pObj )
+{
+ int IdSaved = pObj->Id;
+ memset( pObj, 0, sizeof(Ivy_Obj_t) );
+ pObj->Id = IdSaved;
+}
+static inline void Ivy_ObjOverwrite( Ivy_Obj_t * pBase, Ivy_Obj_t * pData )
+{
+ int IdSaved = pBase->Id;
+ memcpy( pBase, pData, sizeof(Ivy_Obj_t) );
+ pBase->Id = IdSaved;
+}
+static inline int Ivy_ObjWhatFanin( Ivy_Obj_t * pObj, Ivy_Obj_t * pFanin )
+{
+ if ( Ivy_ObjFanin0(pObj) == pFanin ) return 0;
+ if ( Ivy_ObjFanin1(pObj) == pFanin ) return 1;
+ assert(0); return -1;
+}
+static inline int Ivy_ObjFanoutC( Ivy_Obj_t * pObj, Ivy_Obj_t * pFanout )
+{
+ if ( Ivy_ObjFanin0(pFanout) == pObj ) return Ivy_ObjFaninC0(pObj);
+ if ( Ivy_ObjFanin1(pFanout) == pObj ) return Ivy_ObjFaninC1(pObj);
+ assert(0); return -1;
+}
+
+// create the ghost of the new node
+static inline Ivy_Obj_t * Ivy_ObjCreateGhost( Ivy_Man_t * p, Ivy_Obj_t * p0, Ivy_Obj_t * p1, Ivy_Type_t Type, Ivy_Init_t Init )
+{
+ Ivy_Obj_t * pGhost, * pTemp;
+ assert( Type != IVY_AND || !Ivy_ObjIsConst1(Ivy_Regular(p0)) );
+ assert( p1 == NULL || !Ivy_ObjIsConst1(Ivy_Regular(p1)) );
+ assert( Type == IVY_PI || Ivy_Regular(p0) != Ivy_Regular(p1) );
+ assert( Type != IVY_LATCH || !Ivy_IsComplement(p0) );
+// assert( p1 == NULL || (!Ivy_ObjIsLatch(Ivy_Regular(p0)) || !Ivy_ObjIsLatch(Ivy_Regular(p1))) );
+ pGhost = Ivy_ManGhost(p);
+ pGhost->Type = Type;
+ pGhost->Init = Init;
+ pGhost->pFanin0 = p0;
+ pGhost->pFanin1 = p1;
+ if ( p1 && Ivy_ObjFaninId0(pGhost) > Ivy_ObjFaninId1(pGhost) )
+ pTemp = pGhost->pFanin0, pGhost->pFanin0 = pGhost->pFanin1, pGhost->pFanin1 = pTemp;
+ return pGhost;
+}
+
+// get the complemented initial state
+static Ivy_Init_t Ivy_InitNotCond( Ivy_Init_t Init, int fCompl )
+{
+ assert( Init != IVY_INIT_NONE );
+ if ( fCompl == 0 )
+ return Init;
+ if ( Init == IVY_INIT_0 )
+ return IVY_INIT_1;
+ if ( Init == IVY_INIT_1 )
+ return IVY_INIT_0;
+ return IVY_INIT_DC;
+}
+
+// get the initial state after forward retiming over AND gate
+static Ivy_Init_t Ivy_InitAnd( Ivy_Init_t InitA, Ivy_Init_t InitB )
+{
+ assert( InitA != IVY_INIT_NONE && InitB != IVY_INIT_NONE );
+ if ( InitA == IVY_INIT_0 || InitB == IVY_INIT_0 )
+ return IVY_INIT_0;
+ if ( InitA == IVY_INIT_DC || InitB == IVY_INIT_DC )
+ return IVY_INIT_DC;
+ return IVY_INIT_1;
+}
+
+// get the initial state after forward retiming over EXOR gate
+static Ivy_Init_t Ivy_InitExor( Ivy_Init_t InitA, Ivy_Init_t InitB )
+{
+ assert( InitA != IVY_INIT_NONE && InitB != IVY_INIT_NONE );
+ if ( InitA == IVY_INIT_DC || InitB == IVY_INIT_DC )
+ return IVY_INIT_DC;
+ if ( InitA == IVY_INIT_0 && InitB == IVY_INIT_1 )
+ return IVY_INIT_1;
+ if ( InitA == IVY_INIT_1 && InitB == IVY_INIT_0 )
+ return IVY_INIT_1;
+ return IVY_INIT_0;
+}
+
+// internal memory manager
+static inline Ivy_Obj_t * Ivy_ManFetchMemory( Ivy_Man_t * p )
+{
+ extern void Ivy_ManAddMemory( Ivy_Man_t * p );
+ Ivy_Obj_t * pTemp;
+ if ( p->pListFree == NULL )
+ Ivy_ManAddMemory( p );
+ pTemp = p->pListFree;
+ p->pListFree = *((Ivy_Obj_t **)pTemp);
+ memset( pTemp, 0, sizeof(Ivy_Obj_t) );
+ return pTemp;
+}
+static inline void Ivy_ManRecycleMemory( Ivy_Man_t * p, Ivy_Obj_t * pEntry )
+{
+ pEntry->Type = IVY_NONE; // distinquishes dead node from live node
+ *((Ivy_Obj_t **)pEntry) = p->pListFree;
+ p->pListFree = pEntry;
+}
+
+
+////////////////////////////////////////////////////////////////////////
+/// ITERATORS ///
+////////////////////////////////////////////////////////////////////////
+
+// iterator over the primary inputs
+#define Ivy_ManForEachPi( p, pObj, i ) \
+ Vec_PtrForEachEntry( p->vPis, pObj, i )
+// iterator over the primary outputs
+#define Ivy_ManForEachPo( p, pObj, i ) \
+ Vec_PtrForEachEntry( p->vPos, pObj, i )
+// iterator over all objects, including those currently not used
+#define Ivy_ManForEachObj( p, pObj, i ) \
+ Vec_PtrForEachEntry( p->vObjs, pObj, i ) if ( (pObj) == NULL ) {} else
+// iterator over the combinational inputs
+#define Ivy_ManForEachCi( p, pObj, i ) \
+ Ivy_ManForEachObj( p, pObj, i ) if ( !Ivy_ObjIsCi(pObj) ) {} else
+// iterator over the combinational outputs
+#define Ivy_ManForEachCo( p, pObj, i ) \
+ Ivy_ManForEachObj( p, pObj, i ) if ( !Ivy_ObjIsCo(pObj) ) {} else
+// iterator over logic nodes (AND and EXOR gates)
+#define Ivy_ManForEachNode( p, pObj, i ) \
+ Ivy_ManForEachObj( p, pObj, i ) if ( !Ivy_ObjIsNode(pObj) ) {} else
+// iterator over logic latches
+#define Ivy_ManForEachLatch( p, pObj, i ) \
+ Ivy_ManForEachObj( p, pObj, i ) if ( !Ivy_ObjIsLatch(pObj) ) {} else
+// iterator over the nodes whose IDs are stored in the array
+#define Ivy_ManForEachNodeVec( p, vIds, pObj, i ) \
+ for ( i = 0; i < Vec_IntSize(vIds) && ((pObj) = Ivy_ManObj(p, Vec_IntEntry(vIds,i))); i++ )
+// iterator over the fanouts of an object
+#define Ivy_ObjForEachFanout( p, pObj, vArray, pFanout, i ) \
+ for ( i = 0, Ivy_ObjCollectFanouts(p, pObj, vArray); \
+ i < Vec_PtrSize(vArray) && ((pFanout) = Vec_PtrEntry(vArray,i)); i++ )
+
+////////////////////////////////////////////////////////////////////////
+/// FUNCTION DECLARATIONS ///
+////////////////////////////////////////////////////////////////////////
+
+/*=== ivyBalance.c ========================================================*/
+extern Ivy_Man_t * Ivy_ManBalance( Ivy_Man_t * p, int fUpdateLevel );
+extern Ivy_Obj_t * Ivy_NodeBalanceBuildSuper( Ivy_Man_t * p, Vec_Ptr_t * vSuper, Ivy_Type_t Type, int fUpdateLevel );
+/*=== ivyCanon.c ========================================================*/
+extern Ivy_Obj_t * Ivy_CanonAnd( Ivy_Man_t * p, Ivy_Obj_t * p0, Ivy_Obj_t * p1 );
+extern Ivy_Obj_t * Ivy_CanonExor( Ivy_Man_t * p, Ivy_Obj_t * p0, Ivy_Obj_t * p1 );
+extern Ivy_Obj_t * Ivy_CanonLatch( Ivy_Man_t * p, Ivy_Obj_t * pObj, Ivy_Init_t Init );
+/*=== ivyCheck.c ========================================================*/
+extern int Ivy_ManCheck( Ivy_Man_t * p );
+extern int Ivy_ManCheckFanoutNums( Ivy_Man_t * p );
+extern int Ivy_ManCheckFanouts( Ivy_Man_t * p );
+extern int Ivy_ManCheckChoices( Ivy_Man_t * p );
+/*=== ivyCut.c ==========================================================*/
+extern void Ivy_ManSeqFindCut( Ivy_Man_t * p, Ivy_Obj_t * pNode, Vec_Int_t * vFront, Vec_Int_t * vInside, int nSize );
+extern Ivy_Store_t * Ivy_NodeFindCutsAll( Ivy_Man_t * p, Ivy_Obj_t * pObj, int nLeaves );
+/*=== ivyDfs.c ==========================================================*/
+extern Vec_Int_t * Ivy_ManDfs( Ivy_Man_t * p );
+extern Vec_Int_t * Ivy_ManDfsSeq( Ivy_Man_t * p, Vec_Int_t ** pvLatches );
+extern void Ivy_ManCollectCone( Ivy_Obj_t * pObj, Vec_Ptr_t * vFront, Vec_Ptr_t * vCone );
+extern Vec_Vec_t * Ivy_ManLevelize( Ivy_Man_t * p );
+extern Vec_Int_t * Ivy_ManRequiredLevels( Ivy_Man_t * p );
+extern int Ivy_ManIsAcyclic( Ivy_Man_t * p );
+extern int Ivy_ManSetLevels( Ivy_Man_t * p, int fHaig );
+/*=== ivyDsd.c ==========================================================*/
+extern int Ivy_TruthDsd( unsigned uTruth, Vec_Int_t * vTree );
+extern void Ivy_TruthDsdPrint( FILE * pFile, Vec_Int_t * vTree );
+extern unsigned Ivy_TruthDsdCompute( Vec_Int_t * vTree );
+extern void Ivy_TruthDsdComputePrint( unsigned uTruth );
+extern Ivy_Obj_t * Ivy_ManDsdConstruct( Ivy_Man_t * p, Vec_Int_t * vFront, Vec_Int_t * vTree );
+/*=== ivyFanout.c ==========================================================*/
+extern void Ivy_ManStartFanout( Ivy_Man_t * p );
+extern void Ivy_ManStopFanout( Ivy_Man_t * p );
+extern void Ivy_ObjAddFanout( Ivy_Man_t * p, Ivy_Obj_t * pObj, Ivy_Obj_t * pFanout );
+extern void Ivy_ObjDeleteFanout( Ivy_Man_t * p, Ivy_Obj_t * pObj, Ivy_Obj_t * pFanout );
+extern void Ivy_ObjPatchFanout( Ivy_Man_t * p, Ivy_Obj_t * pObj, Ivy_Obj_t * pFanoutOld, Ivy_Obj_t * pFanoutNew );
+extern void Ivy_ObjCollectFanouts( Ivy_Man_t * p, Ivy_Obj_t * pObj, Vec_Ptr_t * vArray );
+extern Ivy_Obj_t * Ivy_ObjReadFirstFanout( Ivy_Man_t * p, Ivy_Obj_t * pObj );
+extern int Ivy_ObjFanoutNum( Ivy_Man_t * p, Ivy_Obj_t * pObj );
+/*=== ivyFastMap.c =============================================================*/
+extern void Ivy_FastMapPerform( Ivy_Man_t * pAig, int nLimit, int fRecovery, int fVerbose );
+extern void Ivy_FastMapStop( Ivy_Man_t * pAig );
+extern void Ivy_FastMapReadSupp( Ivy_Man_t * pAig, Ivy_Obj_t * pObj, Vec_Int_t * vLeaves );
+extern void Ivy_FastMapReverseLevel( Ivy_Man_t * pAig );
+/*=== ivyFraig.c ==========================================================*/
+extern int Ivy_FraigProve( Ivy_Man_t ** ppManAig, void * pPars );
+extern Ivy_Man_t * Ivy_FraigPerform( Ivy_Man_t * pManAig, Ivy_FraigParams_t * pParams );
+extern Ivy_Man_t * Ivy_FraigMiter( Ivy_Man_t * pManAig, Ivy_FraigParams_t * pParams );
+extern void Ivy_FraigParamsDefault( Ivy_FraigParams_t * pParams );
+/*=== ivyHaig.c ==========================================================*/
+extern void Ivy_ManHaigStart( Ivy_Man_t * p, int fVerbose );
+extern void Ivy_ManHaigTrasfer( Ivy_Man_t * p, Ivy_Man_t * pNew );
+extern void Ivy_ManHaigStop( Ivy_Man_t * p );
+extern void Ivy_ManHaigPostprocess( Ivy_Man_t * p, int fVerbose );
+extern void Ivy_ManHaigCreateObj( Ivy_Man_t * p, Ivy_Obj_t * pObj );
+extern void Ivy_ManHaigCreateChoice( Ivy_Man_t * p, Ivy_Obj_t * pObjOld, Ivy_Obj_t * pObjNew );
+extern void Ivy_ManHaigSimulate( Ivy_Man_t * p );
+/*=== ivyMan.c ==========================================================*/
+extern Ivy_Man_t * Ivy_ManStart();
+extern Ivy_Man_t * Ivy_ManStartFrom( Ivy_Man_t * p );
+extern Ivy_Man_t * Ivy_ManDup( Ivy_Man_t * p );
+extern Ivy_Man_t * Ivy_ManFrames( Ivy_Man_t * pMan, int nLatches, int nFrames, int fInit, Vec_Ptr_t ** pvMapping );
+extern void Ivy_ManStop( Ivy_Man_t * p );
+extern int Ivy_ManCleanup( Ivy_Man_t * p );
+extern int Ivy_ManPropagateBuffers( Ivy_Man_t * p, int fUpdateLevel );
+extern void Ivy_ManPrintStats( Ivy_Man_t * p );
+extern void Ivy_ManMakeSeq( Ivy_Man_t * p, int nLatches, int * pInits );
+/*=== ivyMem.c ==========================================================*/
+extern void Ivy_ManStartMemory( Ivy_Man_t * p );
+extern void Ivy_ManStopMemory( Ivy_Man_t * p );
+/*=== ivyMulti.c ==========================================================*/
+extern Ivy_Obj_t * Ivy_Multi( Ivy_Man_t * p, Ivy_Obj_t ** pArgs, int nArgs, Ivy_Type_t Type );
+extern Ivy_Obj_t * Ivy_Multi1( Ivy_Man_t * p, Ivy_Obj_t ** pArgs, int nArgs, Ivy_Type_t Type );
+extern Ivy_Obj_t * Ivy_Multi_rec( Ivy_Man_t * p, Ivy_Obj_t ** ppObjs, int nObjs, Ivy_Type_t Type );
+extern Ivy_Obj_t * Ivy_MultiBalance_rec( Ivy_Man_t * p, Ivy_Obj_t ** pArgs, int nArgs, Ivy_Type_t Type );
+extern int Ivy_MultiPlus( Ivy_Man_t * p, Vec_Ptr_t * vLeaves, Vec_Ptr_t * vCone, Ivy_Type_t Type, int nLimit, Vec_Ptr_t * vSol );
+/*=== ivyObj.c ==========================================================*/
+extern Ivy_Obj_t * Ivy_ObjCreatePi( Ivy_Man_t * p );
+extern Ivy_Obj_t * Ivy_ObjCreatePo( Ivy_Man_t * p, Ivy_Obj_t * pDriver );
+extern Ivy_Obj_t * Ivy_ObjCreate( Ivy_Man_t * p, Ivy_Obj_t * pGhost );
+extern void Ivy_ObjConnect( Ivy_Man_t * p, Ivy_Obj_t * pObj, Ivy_Obj_t * pFan0, Ivy_Obj_t * pFan1 );
+extern void Ivy_ObjDisconnect( Ivy_Man_t * p, Ivy_Obj_t * pObj );
+extern void Ivy_ObjPatchFanin0( Ivy_Man_t * p, Ivy_Obj_t * pObj, Ivy_Obj_t * pFaninNew );
+extern void Ivy_ObjDelete( Ivy_Man_t * p, Ivy_Obj_t * pObj, int fFreeTop );
+extern void Ivy_ObjDelete_rec( Ivy_Man_t * p, Ivy_Obj_t * pObj, int fFreeTop );
+extern void Ivy_ObjReplace( Ivy_Man_t * p, Ivy_Obj_t * pObjOld, Ivy_Obj_t * pObjNew, int fDeleteOld, int fFreeTop, int fUpdateLevel );
+extern void Ivy_NodeFixBufferFanins( Ivy_Man_t * p, Ivy_Obj_t * pNode, int fUpdateLevel );
+/*=== ivyOper.c =========================================================*/
+extern Ivy_Obj_t * Ivy_Oper( Ivy_Man_t * p, Ivy_Obj_t * p0, Ivy_Obj_t * p1, Ivy_Type_t Type );
+extern Ivy_Obj_t * Ivy_And( Ivy_Man_t * p, Ivy_Obj_t * p0, Ivy_Obj_t * p1 );
+extern Ivy_Obj_t * Ivy_Or( Ivy_Man_t * p, Ivy_Obj_t * p0, Ivy_Obj_t * p1 );
+extern Ivy_Obj_t * Ivy_Exor( Ivy_Man_t * p, Ivy_Obj_t * p0, Ivy_Obj_t * p1 );
+extern Ivy_Obj_t * Ivy_Mux( Ivy_Man_t * p, Ivy_Obj_t * pC, Ivy_Obj_t * p1, Ivy_Obj_t * p0 );
+extern Ivy_Obj_t * Ivy_Maj( Ivy_Man_t * p, Ivy_Obj_t * pA, Ivy_Obj_t * pB, Ivy_Obj_t * pC );
+extern Ivy_Obj_t * Ivy_Miter( Ivy_Man_t * p, Vec_Ptr_t * vPairs );
+extern Ivy_Obj_t * Ivy_Latch( Ivy_Man_t * p, Ivy_Obj_t * pObj, Ivy_Init_t Init );
+/*=== ivyResyn.c =========================================================*/
+extern Ivy_Man_t * Ivy_ManResyn0( Ivy_Man_t * p, int fUpdateLevel, int fVerbose );
+extern Ivy_Man_t * Ivy_ManResyn( Ivy_Man_t * p, int fUpdateLevel, int fVerbose );
+extern Ivy_Man_t * Ivy_ManRwsat( Ivy_Man_t * pMan, int fVerbose );
+/*=== ivyRewrite.c =========================================================*/
+extern int Ivy_ManSeqRewrite( Ivy_Man_t * p, int fUpdateLevel, int fUseZeroCost );
+extern int Ivy_ManRewriteAlg( Ivy_Man_t * p, int fUpdateLevel, int fUseZeroCost );
+extern int Ivy_ManRewritePre( Ivy_Man_t * p, int fUpdateLevel, int fUseZeroCost, int fVerbose );
+/*=== ivySeq.c =========================================================*/
+extern int Ivy_ManRewriteSeq( Ivy_Man_t * p, int fUseZeroCost, int fVerbose );
+/*=== ivyShow.c =========================================================*/
+extern void Ivy_ManShow( Ivy_Man_t * pMan, int fHaig, Vec_Ptr_t * vBold );
+/*=== ivyTable.c ========================================================*/
+extern Ivy_Obj_t * Ivy_TableLookup( Ivy_Man_t * p, Ivy_Obj_t * pObj );
+extern void Ivy_TableInsert( Ivy_Man_t * p, Ivy_Obj_t * pObj );
+extern void Ivy_TableDelete( Ivy_Man_t * p, Ivy_Obj_t * pObj );
+extern void Ivy_TableUpdate( Ivy_Man_t * p, Ivy_Obj_t * pObj, int ObjIdNew );
+extern int Ivy_TableCountEntries( Ivy_Man_t * p );
+extern void Ivy_TableProfile( Ivy_Man_t * p );
+/*=== ivyUtil.c =========================================================*/
+extern void Ivy_ManIncrementTravId( Ivy_Man_t * p );
+extern void Ivy_ManCleanTravId( Ivy_Man_t * p );
+extern unsigned * Ivy_ManCutTruth( Ivy_Man_t * p, Ivy_Obj_t * pRoot, Vec_Int_t * vLeaves, Vec_Int_t * vNodes, Vec_Int_t * vTruth );
+extern void Ivy_ManCollectCut( Ivy_Man_t * p, Ivy_Obj_t * pRoot, Vec_Int_t * vLeaves, Vec_Int_t * vNodes );
+extern Vec_Int_t * Ivy_ManLatches( Ivy_Man_t * p );
+extern int Ivy_ManLevels( Ivy_Man_t * p );
+extern void Ivy_ManResetLevels( Ivy_Man_t * p );
+extern int Ivy_ObjMffcLabel( Ivy_Man_t * p, Ivy_Obj_t * pObj );
+extern void Ivy_ObjUpdateLevel_rec( Ivy_Man_t * p, Ivy_Obj_t * pObj );
+extern void Ivy_ObjUpdateLevelR_rec( Ivy_Man_t * p, Ivy_Obj_t * pObj, int ReqNew );
+extern int Ivy_ObjIsMuxType( Ivy_Obj_t * pObj );
+extern Ivy_Obj_t * Ivy_ObjRecognizeMux( Ivy_Obj_t * pObj, Ivy_Obj_t ** ppObjT, Ivy_Obj_t ** ppObjE );
+extern Ivy_Obj_t * Ivy_ObjReal( Ivy_Obj_t * pObj );
+extern void Ivy_ObjPrintVerbose( Ivy_Man_t * p, Ivy_Obj_t * pObj, int fHaig );
+extern void Ivy_ManPrintVerbose( Ivy_Man_t * p, int fHaig );
+extern int Ivy_CutTruthPrint( Ivy_Man_t * p, Ivy_Cut_t * pCut, unsigned uTruth );
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
+
+////////////////////////////////////////////////////////////////////////
+/// END OF FILE ///
+////////////////////////////////////////////////////////////////////////
+
diff --git a/src/aig/ivy/ivyBalance.c b/src/aig/ivy/ivyBalance.c
new file mode 100644
index 00000000..5627039a
--- /dev/null
+++ b/src/aig/ivy/ivyBalance.c
@@ -0,0 +1,404 @@
+/**CFile****************************************************************
+
+ FileName [ivyBalance.c]
+
+ SystemName [ABC: Logic synthesis and verification system.]
+
+ PackageName [And-Inverter Graph package.]
+
+ Synopsis [Algebraic AIG balancing.]
+
+ Author [Alan Mishchenko]
+
+ Affiliation [UC Berkeley]
+
+ Date [Ver. 1.0. Started - May 11, 2006.]
+
+ Revision [$Id: ivyBalance.c,v 1.00 2006/05/11 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "ivy.h"
+
+////////////////////////////////////////////////////////////////////////
+/// DECLARATIONS ///
+////////////////////////////////////////////////////////////////////////
+
+static int Ivy_NodeBalance_rec( Ivy_Man_t * pNew, Ivy_Obj_t * pObj, Vec_Vec_t * vStore, int Level, int fUpdateLevel );
+static Vec_Ptr_t * Ivy_NodeBalanceCone( Ivy_Obj_t * pObj, Vec_Vec_t * vStore, int Level );
+static int Ivy_NodeBalanceFindLeft( Vec_Ptr_t * vSuper );
+static void Ivy_NodeBalancePermute( Ivy_Man_t * p, Vec_Ptr_t * vSuper, int LeftBound, int fExor );
+static void Ivy_NodeBalancePushUniqueOrderByLevel( Vec_Ptr_t * vStore, Ivy_Obj_t * pObj );
+
+////////////////////////////////////////////////////////////////////////
+/// FUNCTION DEFINITIONS ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+ Synopsis [Performs algebraic balancing of the AIG.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Ivy_Man_t * Ivy_ManBalance( Ivy_Man_t * p, int fUpdateLevel )
+{
+ Ivy_Man_t * pNew;
+ Ivy_Obj_t * pObj, * pDriver;
+ Vec_Vec_t * vStore;
+ int i, NewNodeId;
+ // clean the old manager
+ Ivy_ManCleanTravId( p );
+ // create the new manager
+ pNew = Ivy_ManStart();
+ // map the nodes
+ Ivy_ManConst1(p)->TravId = Ivy_EdgeFromNode( Ivy_ManConst1(pNew) );
+ Ivy_ManForEachPi( p, pObj, i )
+ pObj->TravId = Ivy_EdgeFromNode( Ivy_ObjCreatePi(pNew) );
+ // if HAIG is defined, trasfer the pointers to the PIs/latches
+// if ( p->pHaig )
+// Ivy_ManHaigTrasfer( p, pNew );
+ // balance the AIG
+ vStore = Vec_VecAlloc( 50 );
+ Ivy_ManForEachPo( p, pObj, i )
+ {
+ pDriver = Ivy_ObjReal( Ivy_ObjChild0(pObj) );
+ NewNodeId = Ivy_NodeBalance_rec( pNew, Ivy_Regular(pDriver), vStore, 0, fUpdateLevel );
+ NewNodeId = Ivy_EdgeNotCond( NewNodeId, Ivy_IsComplement(pDriver) );
+ Ivy_ObjCreatePo( pNew, Ivy_EdgeToNode(pNew, NewNodeId) );
+ }
+ Vec_VecFree( vStore );
+ if ( i = Ivy_ManCleanup( pNew ) )
+ {
+// printf( "Cleanup after balancing removed %d dangling nodes.\n", i );
+ }
+ // check the resulting AIG
+ if ( !Ivy_ManCheck(pNew) )
+ printf( "Ivy_ManBalance(): The check has failed.\n" );
+ return pNew;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Procedure used for sorting the nodes in decreasing order of levels.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Ivy_NodeCompareLevelsDecrease( Ivy_Obj_t ** pp1, Ivy_Obj_t ** pp2 )
+{
+ int Diff = Ivy_Regular(*pp1)->Level - Ivy_Regular(*pp2)->Level;
+ if ( Diff > 0 )
+ return -1;
+ if ( Diff < 0 )
+ return 1;
+ return 0;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Returns the ID of new node constructed.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Ivy_NodeBalance_rec( Ivy_Man_t * pNew, Ivy_Obj_t * pObjOld, Vec_Vec_t * vStore, int Level, int fUpdateLevel )
+{
+ Ivy_Obj_t * pObjNew;
+ Vec_Ptr_t * vSuper;
+ int i, NewNodeId;
+ assert( !Ivy_IsComplement(pObjOld) );
+ assert( !Ivy_ObjIsBuf(pObjOld) );
+ // return if the result is known
+ if ( Ivy_ObjIsConst1(pObjOld) )
+ return pObjOld->TravId;
+ if ( pObjOld->TravId )
+ return pObjOld->TravId;
+ assert( Ivy_ObjIsNode(pObjOld) );
+ // get the implication supergate
+ vSuper = Ivy_NodeBalanceCone( pObjOld, vStore, Level );
+ if ( vSuper->nSize == 0 )
+ { // it means that the supergate contains two nodes in the opposite polarity
+ pObjOld->TravId = Ivy_EdgeFromNode( Ivy_ManConst0(pNew) );
+ return pObjOld->TravId;
+ }
+ if ( vSuper->nSize < 2 )
+ printf( "BUG!\n" );
+ // for each old node, derive the new well-balanced node
+ for ( i = 0; i < vSuper->nSize; i++ )
+ {
+ NewNodeId = Ivy_NodeBalance_rec( pNew, Ivy_Regular(vSuper->pArray[i]), vStore, Level + 1, fUpdateLevel );
+ NewNodeId = Ivy_EdgeNotCond( NewNodeId, Ivy_IsComplement(vSuper->pArray[i]) );
+ vSuper->pArray[i] = Ivy_EdgeToNode( pNew, NewNodeId );
+ }
+ // build the supergate
+ pObjNew = Ivy_NodeBalanceBuildSuper( pNew, vSuper, Ivy_ObjType(pObjOld), fUpdateLevel );
+ vSuper->nSize = 0;
+ // make sure the balanced node is not assigned
+ assert( pObjOld->TravId == 0 );
+ pObjOld->TravId = Ivy_EdgeFromNode( pObjNew );
+// assert( pObjOld->Level >= Ivy_Regular(pObjNew)->Level );
+ return pObjOld->TravId;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Builds implication supergate.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Ivy_Obj_t * Ivy_NodeBalanceBuildSuper( Ivy_Man_t * p, Vec_Ptr_t * vSuper, Ivy_Type_t Type, int fUpdateLevel )
+{
+ Ivy_Obj_t * pObj1, * pObj2;
+ int LeftBound;
+ assert( vSuper->nSize > 1 );
+ // sort the new nodes by level in the decreasing order
+ Vec_PtrSort( vSuper, Ivy_NodeCompareLevelsDecrease );
+ // balance the nodes
+ while ( vSuper->nSize > 1 )
+ {
+ // find the left bound on the node to be paired
+ LeftBound = (!fUpdateLevel)? 0 : Ivy_NodeBalanceFindLeft( vSuper );
+ // find the node that can be shared (if no such node, randomize choice)
+ Ivy_NodeBalancePermute( p, vSuper, LeftBound, Type == IVY_EXOR );
+ // pull out the last two nodes
+ pObj1 = Vec_PtrPop(vSuper);
+ pObj2 = Vec_PtrPop(vSuper);
+ Ivy_NodeBalancePushUniqueOrderByLevel( vSuper, Ivy_Oper(p, pObj1, pObj2, Type) );
+ }
+ return Vec_PtrEntry(vSuper, 0);
+}
+
+/**Function*************************************************************
+
+ Synopsis [Collects the nodes of the supergate.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Ivy_NodeBalanceCone_rec( Ivy_Obj_t * pRoot, Ivy_Obj_t * pObj, Vec_Ptr_t * vSuper )
+{
+ int RetValue1, RetValue2, i;
+ // check if the node is visited
+ if ( Ivy_Regular(pObj)->fMarkB )
+ {
+ // check if the node occurs in the same polarity
+ for ( i = 0; i < vSuper->nSize; i++ )
+ if ( vSuper->pArray[i] == pObj )
+ return 1;
+ // check if the node is present in the opposite polarity
+ for ( i = 0; i < vSuper->nSize; i++ )
+ if ( vSuper->pArray[i] == Ivy_Not(pObj) )
+ return -1;
+ assert( 0 );
+ return 0;
+ }
+ // if the new node is complemented or a PI, another gate begins
+ if ( pObj != pRoot && (Ivy_IsComplement(pObj) || Ivy_ObjType(pObj) != Ivy_ObjType(pRoot) || Ivy_ObjRefs(pObj) > 1) )
+ {
+ Vec_PtrPush( vSuper, pObj );
+ Ivy_Regular(pObj)->fMarkB = 1;
+ return 0;
+ }
+ assert( !Ivy_IsComplement(pObj) );
+ assert( Ivy_ObjIsNode(pObj) );
+ // go through the branches
+ RetValue1 = Ivy_NodeBalanceCone_rec( pRoot, Ivy_ObjReal( Ivy_ObjChild0(pObj) ), vSuper );
+ RetValue2 = Ivy_NodeBalanceCone_rec( pRoot, Ivy_ObjReal( Ivy_ObjChild1(pObj) ), vSuper );
+ if ( RetValue1 == -1 || RetValue2 == -1 )
+ return -1;
+ // return 1 if at least one branch has a duplicate
+ return RetValue1 || RetValue2;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Collects the nodes of the supergate.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Vec_Ptr_t * Ivy_NodeBalanceCone( Ivy_Obj_t * pObj, Vec_Vec_t * vStore, int Level )
+{
+ Vec_Ptr_t * vNodes;
+ int RetValue, i;
+ assert( !Ivy_IsComplement(pObj) );
+ // extend the storage
+ if ( Vec_VecSize( vStore ) <= Level )
+ Vec_VecPush( vStore, Level, 0 );
+ // get the temporary array of nodes
+ vNodes = Vec_VecEntry( vStore, Level );
+ Vec_PtrClear( vNodes );
+ // collect the nodes in the implication supergate
+ RetValue = Ivy_NodeBalanceCone_rec( pObj, pObj, vNodes );
+ assert( vNodes->nSize > 1 );
+ // unmark the visited nodes
+ Vec_PtrForEachEntry( vNodes, pObj, i )
+ Ivy_Regular(pObj)->fMarkB = 0;
+ // if we found the node and its complement in the same implication supergate,
+ // return empty set of nodes (meaning that we should use constant-0 node)
+ if ( RetValue == -1 )
+ vNodes->nSize = 0;
+ return vNodes;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Finds the left bound on the next candidate to be paired.]
+
+ Description [The nodes in the array are in the decreasing order of levels.
+ The last node in the array has the smallest level. By default it would be paired
+ with the next node on the left. However, it may be possible to pair it with some
+ other node on the left, in such a way that the new node is shared. This procedure
+ finds the index of the left-most node, which can be paired with the last node.]
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Ivy_NodeBalanceFindLeft( Vec_Ptr_t * vSuper )
+{
+ Ivy_Obj_t * pObjRight, * pObjLeft;
+ int Current;
+ // if two or less nodes, pair with the first
+ if ( Vec_PtrSize(vSuper) < 3 )
+ return 0;
+ // set the pointer to the one before the last
+ Current = Vec_PtrSize(vSuper) - 2;
+ pObjRight = Vec_PtrEntry( vSuper, Current );
+ // go through the nodes to the left of this one
+ for ( Current--; Current >= 0; Current-- )
+ {
+ // get the next node on the left
+ pObjLeft = Vec_PtrEntry( vSuper, Current );
+ // if the level of this node is different, quit the loop
+ if ( Ivy_Regular(pObjLeft)->Level != Ivy_Regular(pObjRight)->Level )
+ break;
+ }
+ Current++;
+ // get the node, for which the equality holds
+ pObjLeft = Vec_PtrEntry( vSuper, Current );
+ assert( Ivy_Regular(pObjLeft)->Level == Ivy_Regular(pObjRight)->Level );
+ return Current;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Moves closer to the end the node that is best for sharing.]
+
+ Description [If there is no node with sharing, randomly chooses one of
+ the legal nodes.]
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Ivy_NodeBalancePermute( Ivy_Man_t * p, Vec_Ptr_t * vSuper, int LeftBound, int fExor )
+{
+ Ivy_Obj_t * pObj1, * pObj2, * pObj3, * pGhost;
+ int RightBound, i;
+ // get the right bound
+ RightBound = Vec_PtrSize(vSuper) - 2;
+ assert( LeftBound <= RightBound );
+ if ( LeftBound == RightBound )
+ return;
+ // get the two last nodes
+ pObj1 = Vec_PtrEntry( vSuper, RightBound + 1 );
+ pObj2 = Vec_PtrEntry( vSuper, RightBound );
+ if ( Ivy_Regular(pObj1) == p->pConst1 || Ivy_Regular(pObj2) == p->pConst1 )
+ return;
+ // find the first node that can be shared
+ for ( i = RightBound; i >= LeftBound; i-- )
+ {
+ pObj3 = Vec_PtrEntry( vSuper, i );
+ if ( Ivy_Regular(pObj3) == p->pConst1 )
+ {
+ Vec_PtrWriteEntry( vSuper, i, pObj2 );
+ Vec_PtrWriteEntry( vSuper, RightBound, pObj3 );
+ return;
+ }
+ pGhost = Ivy_ObjCreateGhost( p, pObj1, pObj3, fExor? IVY_EXOR : IVY_AND, IVY_INIT_NONE );
+ if ( Ivy_TableLookup( p, pGhost ) )
+ {
+ if ( pObj3 == pObj2 )
+ return;
+ Vec_PtrWriteEntry( vSuper, i, pObj2 );
+ Vec_PtrWriteEntry( vSuper, RightBound, pObj3 );
+ return;
+ }
+ }
+/*
+ // we did not find the node to share, randomize choice
+ {
+ int Choice = rand() % (RightBound - LeftBound + 1);
+ pObj3 = Vec_PtrEntry( vSuper, LeftBound + Choice );
+ if ( pObj3 == pObj2 )
+ return;
+ Vec_PtrWriteEntry( vSuper, LeftBound + Choice, pObj2 );
+ Vec_PtrWriteEntry( vSuper, RightBound, pObj3 );
+ }
+*/
+}
+
+/**Function*************************************************************
+
+ Synopsis [Inserts a new node in the order by levels.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Ivy_NodeBalancePushUniqueOrderByLevel( Vec_Ptr_t * vStore, Ivy_Obj_t * pObj )
+{
+ Ivy_Obj_t * pObj1, * pObj2;
+ int i;
+ if ( Vec_PtrPushUnique(vStore, pObj) )
+ return;
+ // find the p of the node
+ for ( i = vStore->nSize-1; i > 0; i-- )
+ {
+ pObj1 = vStore->pArray[i ];
+ pObj2 = vStore->pArray[i-1];
+ if ( Ivy_Regular(pObj1)->Level <= Ivy_Regular(pObj2)->Level )
+ break;
+ vStore->pArray[i ] = pObj2;
+ vStore->pArray[i-1] = pObj1;
+ }
+}
+
+
+////////////////////////////////////////////////////////////////////////
+/// END OF FILE ///
+////////////////////////////////////////////////////////////////////////
+
+
diff --git a/src/aig/ivy/ivyCanon.c b/src/aig/ivy/ivyCanon.c
new file mode 100644
index 00000000..5768b87e
--- /dev/null
+++ b/src/aig/ivy/ivyCanon.c
@@ -0,0 +1,144 @@
+/**CFile****************************************************************
+
+ FileName [ivyCanon.c]
+
+ SystemName [ABC: Logic synthesis and verification system.]
+
+ PackageName [And-Inverter Graph package.]
+
+ Synopsis [Finding canonical form of objects.]
+
+ Author [Alan Mishchenko]
+
+ Affiliation [UC Berkeley]
+
+ Date [Ver. 1.0. Started - May 11, 2006.]
+
+ Revision [$Id: ivyCanon.c,v 1.00 2006/05/11 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "ivy.h"
+
+////////////////////////////////////////////////////////////////////////
+/// DECLARATIONS ///
+////////////////////////////////////////////////////////////////////////
+
+static Ivy_Obj_t * Ivy_TableLookupPair_rec( Ivy_Man_t * p, Ivy_Obj_t * pObj0, Ivy_Obj_t * pObj1, int fCompl0, int fCompl1, Ivy_Type_t Type );
+
+////////////////////////////////////////////////////////////////////////
+/// FUNCTION DEFINITIONS ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+ Synopsis [Creates the canonical form of the node.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Ivy_Obj_t * Ivy_CanonPair_rec( Ivy_Man_t * p, Ivy_Obj_t * pGhost )
+{
+ Ivy_Obj_t * pResult, * pLat0, * pLat1;
+ Ivy_Init_t Init, Init0, Init1;
+ int fCompl0, fCompl1;
+ Ivy_Type_t Type;
+ assert( Ivy_ObjIsNode(pGhost) );
+ assert( Ivy_ObjIsAnd(pGhost) || (!Ivy_ObjFaninC0(pGhost) && !Ivy_ObjFaninC1(pGhost)) );
+ assert( Ivy_ObjFaninId0(pGhost) != 0 && Ivy_ObjFaninId1(pGhost) != 0 );
+ // consider the case when the pair is canonical
+ if ( !Ivy_ObjIsLatch(Ivy_ObjFanin0(pGhost)) || !Ivy_ObjIsLatch(Ivy_ObjFanin1(pGhost)) )
+ {
+ if ( pResult = Ivy_TableLookup( p, pGhost ) )
+ return pResult;
+ return Ivy_ObjCreate( p, pGhost );
+ }
+ /// remember the latches
+ pLat0 = Ivy_ObjFanin0(pGhost);
+ pLat1 = Ivy_ObjFanin1(pGhost);
+ // remember type and compls
+ Type = Ivy_ObjType(pGhost);
+ fCompl0 = Ivy_ObjFaninC0(pGhost);
+ fCompl1 = Ivy_ObjFaninC1(pGhost);
+ // call recursively
+ pResult = Ivy_Oper( p, Ivy_NotCond(Ivy_ObjFanin0(pLat0), fCompl0), Ivy_NotCond(Ivy_ObjFanin0(pLat1), fCompl1), Type );
+ // build latch on top of this
+ Init0 = Ivy_InitNotCond( Ivy_ObjInit(pLat0), fCompl0 );
+ Init1 = Ivy_InitNotCond( Ivy_ObjInit(pLat1), fCompl1 );
+ Init = (Type == IVY_AND)? Ivy_InitAnd(Init0, Init1) : Ivy_InitExor(Init0, Init1);
+ return Ivy_Latch( p, pResult, Init );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Creates the canonical form of the node.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Ivy_Obj_t * Ivy_CanonAnd( Ivy_Man_t * p, Ivy_Obj_t * pObj0, Ivy_Obj_t * pObj1 )
+{
+ Ivy_Obj_t * pGhost, * pResult;
+ pGhost = Ivy_ObjCreateGhost( p, pObj0, pObj1, IVY_AND, IVY_INIT_NONE );
+ pResult = Ivy_CanonPair_rec( p, pGhost );
+ return pResult;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Creates the canonical form of the node.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Ivy_Obj_t * Ivy_CanonExor( Ivy_Man_t * p, Ivy_Obj_t * pObj0, Ivy_Obj_t * pObj1 )
+{
+ Ivy_Obj_t * pGhost, * pResult;
+ int fCompl = Ivy_IsComplement(pObj0) ^ Ivy_IsComplement(pObj1);
+ pObj0 = Ivy_Regular(pObj0);
+ pObj1 = Ivy_Regular(pObj1);
+ pGhost = Ivy_ObjCreateGhost( p, pObj0, pObj1, IVY_EXOR, IVY_INIT_NONE );
+ pResult = Ivy_CanonPair_rec( p, pGhost );
+ return Ivy_NotCond( pResult, fCompl );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Creates the canonical form of the node.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Ivy_Obj_t * Ivy_CanonLatch( Ivy_Man_t * p, Ivy_Obj_t * pObj, Ivy_Init_t Init )
+{
+ Ivy_Obj_t * pGhost, * pResult;
+ int fCompl = Ivy_IsComplement(pObj);
+ pObj = Ivy_Regular(pObj);
+ pGhost = Ivy_ObjCreateGhost( p, pObj, NULL, IVY_LATCH, Ivy_InitNotCond(Init, fCompl) );
+ pResult = Ivy_TableLookup( p, pGhost );
+ if ( pResult == NULL )
+ pResult = Ivy_ObjCreate( p, pGhost );
+ return Ivy_NotCond( pResult, fCompl );
+}
+
+////////////////////////////////////////////////////////////////////////
+/// END OF FILE ///
+////////////////////////////////////////////////////////////////////////
+
+
diff --git a/src/aig/ivy/ivyCheck.c b/src/aig/ivy/ivyCheck.c
new file mode 100644
index 00000000..55448f19
--- /dev/null
+++ b/src/aig/ivy/ivyCheck.c
@@ -0,0 +1,273 @@
+/**CFile****************************************************************
+
+ FileName [ivyCheck.c]
+
+ SystemName [ABC: Logic synthesis and verification system.]
+
+ PackageName [And-Inverter Graph package.]
+
+ Synopsis [AIG checking procedures.]
+
+ Author [Alan Mishchenko]
+
+ Affiliation [UC Berkeley]
+
+ Date [Ver. 1.0. Started - May 11, 2006.]
+
+ Revision [$Id: ivyCheck.c,v 1.00 2006/05/11 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "ivy.h"
+
+////////////////////////////////////////////////////////////////////////
+/// DECLARATIONS ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+/// FUNCTION DEFINITIONS ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+ Synopsis [Checks the consistency of the AIG manager.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Ivy_ManCheck( Ivy_Man_t * p )
+{
+ Ivy_Obj_t * pObj, * pObj2;
+ int i;
+ Ivy_ManForEachObj( p, pObj, i )
+ {
+ // skip deleted nodes
+ if ( Ivy_ObjId(pObj) != i )
+ {
+ printf( "Ivy_ManCheck: Node with ID %d is listed as number %d in the array of objects.\n", pObj->Id, i );
+ return 0;
+ }
+ // consider the constant node and PIs
+ if ( i == 0 || Ivy_ObjIsPi(pObj) )
+ {
+ if ( Ivy_ObjFaninId0(pObj) || Ivy_ObjFaninId1(pObj) || Ivy_ObjLevel(pObj) )
+ {
+ printf( "Ivy_ManCheck: The AIG has non-standard constant or PI node with ID \"%d\".\n", pObj->Id );
+ return 0;
+ }
+ continue;
+ }
+ if ( Ivy_ObjIsPo(pObj) )
+ {
+ if ( Ivy_ObjFaninId1(pObj) )
+ {
+ printf( "Ivy_ManCheck: The AIG has non-standard PO node with ID \"%d\".\n", pObj->Id );
+ return 0;
+ }
+ continue;
+ }
+ if ( Ivy_ObjIsBuf(pObj) )
+ {
+ if ( Ivy_ObjFanin1(pObj) )
+ {
+ printf( "Ivy_ManCheck: The buffer with ID \"%d\" contains second fanin.\n", pObj->Id );
+ return 0;
+ }
+ continue;
+ }
+ if ( Ivy_ObjIsLatch(pObj) )
+ {
+ if ( Ivy_ObjFanin1(pObj) )
+ {
+ printf( "Ivy_ManCheck: The latch with ID \"%d\" contains second fanin.\n", pObj->Id );
+ return 0;
+ }
+ if ( Ivy_ObjInit(pObj) == IVY_INIT_NONE )
+ {
+ printf( "Ivy_ManCheck: The latch with ID \"%d\" does not have initial state.\n", pObj->Id );
+ return 0;
+ }
+ pObj2 = Ivy_TableLookup( p, pObj );
+ if ( pObj2 != pObj )
+ printf( "Ivy_ManCheck: Latch with ID \"%d\" is not in the structural hashing table.\n", pObj->Id );
+ continue;
+ }
+ // consider the AND node
+ if ( !Ivy_ObjFanin0(pObj) || !Ivy_ObjFanin1(pObj) )
+ {
+ printf( "Ivy_ManCheck: The AIG has internal node \"%d\" with a NULL fanin.\n", pObj->Id );
+ return 0;
+ }
+ if ( Ivy_ObjFaninId0(pObj) >= Ivy_ObjFaninId1(pObj) )
+ {
+ printf( "Ivy_ManCheck: The AIG has node \"%d\" with a wrong ordering of fanins.\n", pObj->Id );
+ return 0;
+ }
+ if ( Ivy_ObjLevel(pObj) != Ivy_ObjLevelNew(pObj) )
+ printf( "Ivy_ManCheck: Node with ID \"%d\" has level %d but should have level %d.\n", pObj->Id, Ivy_ObjLevel(pObj), Ivy_ObjLevelNew(pObj) );
+ pObj2 = Ivy_TableLookup( p, pObj );
+ if ( pObj2 != pObj )
+ printf( "Ivy_ManCheck: Node with ID \"%d\" is not in the structural hashing table.\n", pObj->Id );
+ if ( Ivy_ObjRefs(pObj) == 0 )
+ printf( "Ivy_ManCheck: Node with ID \"%d\" has no fanouts.\n", pObj->Id );
+ // check fanouts
+ if ( p->fFanout && Ivy_ObjRefs(pObj) != Ivy_ObjFanoutNum(p, pObj) )
+ printf( "Ivy_ManCheck: Node with ID \"%d\" has mismatch between the number of fanouts and refs.\n", pObj->Id );
+ }
+ // count the number of nodes in the table
+ if ( Ivy_TableCountEntries(p) != Ivy_ManAndNum(p) + Ivy_ManExorNum(p) + Ivy_ManLatchNum(p) )
+ {
+ printf( "Ivy_ManCheck: The number of nodes in the structural hashing table is wrong.\n" );
+ return 0;
+ }
+// if ( !Ivy_ManCheckFanouts(p) )
+// return 0;
+ if ( !Ivy_ManIsAcyclic(p) )
+ return 0;
+ return 1;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Verifies the fanouts.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Ivy_ManCheckFanoutNums( Ivy_Man_t * p )
+{
+ Ivy_Obj_t * pObj;
+ int i, Counter = 0;
+ Ivy_ManForEachObj( p, pObj, i )
+ if ( Ivy_ObjIsNode(pObj) )
+ Counter += (Ivy_ObjRefs(pObj) == 0);
+ if ( Counter )
+ printf( "Sequential AIG has %d dangling nodes.\n", Counter );
+ return Counter;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Verifies the fanouts.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Ivy_ManCheckFanouts( Ivy_Man_t * p )
+{
+ Vec_Ptr_t * vFanouts;
+ Ivy_Obj_t * pObj, * pFanout, * pFanin;
+ int i, k, RetValue = 1;
+ if ( !p->fFanout )
+ return 1;
+ vFanouts = Vec_PtrAlloc( 100 );
+ // make sure every fanin is a fanout
+ Ivy_ManForEachObj( p, pObj, i )
+ {
+ pFanin = Ivy_ObjFanin0(pObj);
+ if ( pFanin == NULL )
+ continue;
+ Ivy_ObjForEachFanout( p, pFanin, vFanouts, pFanout, k )
+ if ( pFanout == pObj )
+ break;
+ if ( k == Vec_PtrSize(vFanouts) )
+ {
+ printf( "Node %d is a fanin of node %d but the fanout is not there.\n", pFanin->Id, pObj->Id );
+ RetValue = 0;
+ }
+
+ pFanin = Ivy_ObjFanin1(pObj);
+ if ( pFanin == NULL )
+ continue;
+ Ivy_ObjForEachFanout( p, pFanin, vFanouts, pFanout, k )
+ if ( pFanout == pObj )
+ break;
+ if ( k == Vec_PtrSize(vFanouts) )
+ {
+ printf( "Node %d is a fanin of node %d but the fanout is not there.\n", pFanin->Id, pObj->Id );
+ RetValue = 0;
+ }
+ // check that the previous fanout has the same fanin
+ if ( pObj->pPrevFan0 )
+ {
+ if ( Ivy_ObjFanin0(pObj->pPrevFan0) != Ivy_ObjFanin0(pObj) &&
+ Ivy_ObjFanin0(pObj->pPrevFan0) != Ivy_ObjFanin1(pObj) &&
+ Ivy_ObjFanin1(pObj->pPrevFan0) != Ivy_ObjFanin0(pObj) &&
+ Ivy_ObjFanin1(pObj->pPrevFan0) != Ivy_ObjFanin1(pObj) )
+ {
+ printf( "Node %d has prev %d without common fanin.\n", pObj->Id, pObj->pPrevFan0->Id );
+ RetValue = 0;
+ }
+ }
+ // check that the previous fanout has the same fanin
+ if ( pObj->pPrevFan1 )
+ {
+ if ( Ivy_ObjFanin0(pObj->pPrevFan1) != Ivy_ObjFanin0(pObj) &&
+ Ivy_ObjFanin0(pObj->pPrevFan1) != Ivy_ObjFanin1(pObj) &&
+ Ivy_ObjFanin1(pObj->pPrevFan1) != Ivy_ObjFanin0(pObj) &&
+ Ivy_ObjFanin1(pObj->pPrevFan1) != Ivy_ObjFanin1(pObj) )
+ {
+ printf( "Node %d has prev %d without common fanin.\n", pObj->Id, pObj->pPrevFan1->Id );
+ RetValue = 0;
+ }
+ }
+ }
+ // make sure every fanout is a fanin
+ Ivy_ManForEachObj( p, pObj, i )
+ {
+ Ivy_ObjForEachFanout( p, pObj, vFanouts, pFanout, k )
+ if ( Ivy_ObjFanin0(pFanout) != pObj && Ivy_ObjFanin1(pFanout) != pObj )
+ {
+ printf( "Node %d is a fanout of node %d but the fanin is not there.\n", pFanout->Id, pObj->Id );
+ RetValue = 0;
+ }
+ }
+ Vec_PtrFree( vFanouts );
+ return RetValue;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Checks that each choice node has exactly one node with fanouts.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Ivy_ManCheckChoices( Ivy_Man_t * p )
+{
+ Ivy_Obj_t * pObj, * pTemp;
+ int i;
+ Ivy_ManForEachObj( p->pHaig, pObj, i )
+ {
+ if ( Ivy_ObjRefs(pObj) == 0 )
+ continue;
+ // count the number of nodes in the loop
+ assert( !Ivy_IsComplement(pObj->pEquiv) );
+ for ( pTemp = pObj->pEquiv; pTemp && pTemp != pObj; pTemp = Ivy_Regular(pTemp->pEquiv) )
+ if ( Ivy_ObjRefs(pTemp) > 1 )
+ printf( "Node %d has member %d in its equiv class with %d fanouts.\n", pObj->Id, pTemp->Id, Ivy_ObjRefs(pTemp) );
+ }
+ return 1;
+}
+
+////////////////////////////////////////////////////////////////////////
+/// END OF FILE ///
+////////////////////////////////////////////////////////////////////////
+
+
diff --git a/src/aig/ivy/ivyCut.c b/src/aig/ivy/ivyCut.c
new file mode 100644
index 00000000..e257d8a6
--- /dev/null
+++ b/src/aig/ivy/ivyCut.c
@@ -0,0 +1,989 @@
+/**CFile****************************************************************
+
+ FileName [ivyCut.c]
+
+ SystemName [ABC: Logic synthesis and verification system.]
+
+ PackageName [And-Inverter Graph package.]
+
+ Synopsis [Computes reconvergence driven sequential cut.]
+
+ Author [Alan Mishchenko]
+
+ Affiliation [UC Berkeley]
+
+ Date [Ver. 1.0. Started - May 11, 2006.]
+
+ Revision [$Id: ivyCut.c,v 1.00 2006/05/11 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "ivy.h"
+
+////////////////////////////////////////////////////////////////////////
+/// DECLARATIONS ///
+////////////////////////////////////////////////////////////////////////
+
+static inline int Ivy_NodeCutHashValue( int NodeId ) { return 1 << (NodeId % 31); }
+
+////////////////////////////////////////////////////////////////////////
+/// FUNCTION DEFINITIONS ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+ Synopsis [Evaluate the cost of removing the node from the set of leaves.]
+
+ Description [Returns the number of new leaves that will be brought in.
+ Returns large number if the node cannot be removed from the set of leaves.]
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+static inline int Ivy_NodeGetLeafCostOne( Ivy_Man_t * p, int Leaf, Vec_Int_t * vInside )
+{
+ Ivy_Obj_t * pNode;
+ int nLatches, FaninLeaf, Cost;
+ // make sure leaf is not a contant node
+ assert( Leaf > 0 );
+ // get the node
+ pNode = Ivy_ManObj( p, Ivy_LeafId(Leaf) );
+ // cannot expand over the PI node
+ if ( Ivy_ObjIsPi(pNode) || Ivy_ObjIsConst1(pNode) )
+ return 999;
+ // get the number of latches
+ nLatches = Ivy_LeafLat(Leaf) + Ivy_ObjIsLatch(pNode);
+ if ( nLatches > 15 )
+ return 999;
+ // get the first fanin
+ FaninLeaf = Ivy_LeafCreate( Ivy_ObjFaninId0(pNode), nLatches );
+ Cost = FaninLeaf && (Vec_IntFind(vInside, FaninLeaf) == -1);
+ // quit if this is the one fanin node
+ if ( Ivy_ObjIsLatch(pNode) || Ivy_ObjIsBuf(pNode) )
+ return Cost;
+ assert( Ivy_ObjIsNode(pNode) );
+ // get the second fanin
+ FaninLeaf = Ivy_LeafCreate( Ivy_ObjFaninId1(pNode), nLatches );
+ Cost += FaninLeaf && (Vec_IntFind(vInside, FaninLeaf) == -1);
+ return Cost;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Builds reconvergence-driven cut by changing one leaf at a time.]
+
+ Description [This procedure looks at the current leaves and tries to change
+ one leaf at a time in such a way that the cut grows as little as possible.
+ In evaluating the fanins, this procedure looks only at their immediate
+ predecessors (this is why it is called a one-level construction procedure).]
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Ivy_ManSeqFindCut_int( Ivy_Man_t * p, Vec_Int_t * vFront, Vec_Int_t * vInside, int nSizeLimit )
+{
+ Ivy_Obj_t * pNode;
+ int CostBest, CostCur, Leaf, LeafBest, Next, nLatches, i;
+ int LeavesBest[10];
+ int Counter;
+
+ // add random selection of the best fanin!!!
+
+ // find the best fanin
+ CostBest = 99;
+ LeafBest = -1;
+ Counter = -1;
+//printf( "Evaluating fanins of the cut:\n" );
+ Vec_IntForEachEntry( vFront, Leaf, i )
+ {
+ CostCur = Ivy_NodeGetLeafCostOne( p, Leaf, vInside );
+//printf( " Fanin %s has cost %d.\n", Ivy_ObjName(pNode), CostCur );
+ if ( CostBest > CostCur )
+ {
+ CostBest = CostCur;
+ LeafBest = Leaf;
+ LeavesBest[0] = Leaf;
+ Counter = 1;
+ }
+ else if ( CostBest == CostCur )
+ LeavesBest[Counter++] = Leaf;
+
+ if ( CostBest <= 1 ) // can be if ( CostBest <= 1 )
+ break;
+ }
+ if ( CostBest == 99 )
+ return 0;
+// return Ivy_NodeBuildCutLevelTwo_int( vInside, vFront, nFaninLimit );
+
+ assert( CostBest < 3 );
+ if ( Vec_IntSize(vFront) - 1 + CostBest > nSizeLimit )
+ return 0;
+// return Ivy_NodeBuildCutLevelTwo_int( vInside, vFront, nFaninLimit );
+
+ assert( Counter > 0 );
+printf( "%d", Counter );
+
+ LeafBest = LeavesBest[rand() % Counter];
+
+ // remove the node from the array
+ assert( LeafBest >= 0 );
+ Vec_IntRemove( vFront, LeafBest );
+//printf( "Removing fanin %s.\n", Ivy_ObjName(pNode) );
+
+ // get the node and its latches
+ pNode = Ivy_ManObj( p, Ivy_LeafId(LeafBest) );
+ nLatches = Ivy_LeafLat(LeafBest) + Ivy_ObjIsLatch(pNode);
+ assert( Ivy_ObjIsNode(pNode) || Ivy_ObjIsLatch(pNode) || Ivy_ObjIsBuf(pNode) );
+
+ // add the left child to the fanins
+ Next = Ivy_LeafCreate( Ivy_ObjFaninId0(pNode), nLatches );
+ if ( Next && Vec_IntFind(vInside, Next) == -1 )
+ {
+//printf( "Adding fanin %s.\n", Ivy_ObjName(pNext) );
+ Vec_IntPush( vFront, Next );
+ Vec_IntPush( vInside, Next );
+ }
+
+ // quit if this is the one fanin node
+ if ( Ivy_ObjIsLatch(pNode) || Ivy_ObjIsBuf(pNode) )
+ return 1;
+ assert( Ivy_ObjIsNode(pNode) );
+
+ // add the right child to the fanins
+ Next = Ivy_LeafCreate( Ivy_ObjFaninId1(pNode), nLatches );
+ if ( Next && Vec_IntFind(vInside, Next) == -1 )
+ {
+//printf( "Adding fanin %s.\n", Ivy_ObjName(pNext) );
+ Vec_IntPush( vFront, Next );
+ Vec_IntPush( vInside, Next );
+ }
+ assert( Vec_IntSize(vFront) <= nSizeLimit );
+ // keep doing this
+ return 1;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Computes one sequential cut of the given size.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Ivy_ManSeqFindCut( Ivy_Man_t * p, Ivy_Obj_t * pRoot, Vec_Int_t * vFront, Vec_Int_t * vInside, int nSize )
+{
+ assert( !Ivy_IsComplement(pRoot) );
+ assert( Ivy_ObjIsNode(pRoot) );
+ assert( Ivy_ObjFaninId0(pRoot) );
+ assert( Ivy_ObjFaninId1(pRoot) );
+
+ // start the cut
+ Vec_IntClear( vFront );
+ Vec_IntPush( vFront, Ivy_LeafCreate(Ivy_ObjFaninId0(pRoot), 0) );
+ Vec_IntPush( vFront, Ivy_LeafCreate(Ivy_ObjFaninId1(pRoot), 0) );
+
+ // start the visited nodes
+ Vec_IntClear( vInside );
+ Vec_IntPush( vInside, Ivy_LeafCreate(pRoot->Id, 0) );
+ Vec_IntPush( vInside, Ivy_LeafCreate(Ivy_ObjFaninId0(pRoot), 0) );
+ Vec_IntPush( vInside, Ivy_LeafCreate(Ivy_ObjFaninId1(pRoot), 0) );
+
+ // compute the cut
+ while ( Ivy_ManSeqFindCut_int( p, vFront, vInside, nSize ) );
+ assert( Vec_IntSize(vFront) <= nSize );
+}
+
+
+
+
+
+/**Function*************************************************************
+
+ Synopsis [Computing Boolean cut.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Ivy_ManFindBoolCut_rec( Ivy_Man_t * p, Ivy_Obj_t * pObj, Vec_Ptr_t * vLeaves, Vec_Ptr_t * vVolume, Ivy_Obj_t * pPivot )
+{
+ int RetValue0, RetValue1;
+ if ( pObj == pPivot )
+ {
+ Vec_PtrPushUnique( vLeaves, pObj );
+ Vec_PtrPushUnique( vVolume, pObj );
+ return 1;
+ }
+ if ( pObj->fMarkA )
+ return 0;
+
+// assert( !Ivy_ObjIsCi(pObj) );
+ if ( Ivy_ObjIsCi(pObj) )
+ return 0;
+
+ if ( Ivy_ObjIsBuf(pObj) )
+ {
+ RetValue0 = Ivy_ManFindBoolCut_rec( p, Ivy_ObjFanin0(pObj), vLeaves, vVolume, pPivot );
+ if ( !RetValue0 )
+ return 0;
+ Vec_PtrPushUnique( vVolume, pObj );
+ return 1;
+ }
+ assert( Ivy_ObjIsNode(pObj) );
+ RetValue0 = Ivy_ManFindBoolCut_rec( p, Ivy_ObjFanin0(pObj), vLeaves, vVolume, pPivot );
+ RetValue1 = Ivy_ManFindBoolCut_rec( p, Ivy_ObjFanin1(pObj), vLeaves, vVolume, pPivot );
+ if ( !RetValue0 && !RetValue1 )
+ return 0;
+ // add new leaves
+ if ( !RetValue0 )
+ {
+ Vec_PtrPushUnique( vLeaves, Ivy_ObjFanin0(pObj) );
+ Vec_PtrPushUnique( vVolume, Ivy_ObjFanin0(pObj) );
+ }
+ if ( !RetValue1 )
+ {
+ Vec_PtrPushUnique( vLeaves, Ivy_ObjFanin1(pObj) );
+ Vec_PtrPushUnique( vVolume, Ivy_ObjFanin1(pObj) );
+ }
+ Vec_PtrPushUnique( vVolume, pObj );
+ return 1;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Returns the cost of one node (how many new nodes are added.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Ivy_ManFindBoolCutCost( Ivy_Obj_t * pObj )
+{
+ int Cost;
+ // make sure the node is in the construction zone
+ assert( pObj->fMarkA == 1 );
+ // cannot expand over the PI node
+ if ( Ivy_ObjIsCi(pObj) )
+ return 999;
+ // always expand over the buffer
+ if ( Ivy_ObjIsBuf(pObj) )
+ return !Ivy_ObjFanin0(pObj)->fMarkA;
+ // get the cost of the cone
+ Cost = (!Ivy_ObjFanin0(pObj)->fMarkA) + (!Ivy_ObjFanin1(pObj)->fMarkA);
+ // return the number of nodes to be added to the leaves if this node is removed
+ return Cost;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Computing Boolean cut.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Ivy_ManFindBoolCut( Ivy_Man_t * p, Ivy_Obj_t * pRoot, Vec_Ptr_t * vFront, Vec_Ptr_t * vVolume, Vec_Ptr_t * vLeaves )
+{
+ Ivy_Obj_t * pObj, * pFaninC, * pFanin0, * pFanin1, * pPivot;
+ int RetValue, LevelLimit, Lev, k;
+ assert( !Ivy_IsComplement(pRoot) );
+ // clear the frontier and collect the nodes
+ Vec_PtrClear( vFront );
+ Vec_PtrClear( vVolume );
+ if ( Ivy_ObjIsMuxType(pRoot) )
+ pFaninC = Ivy_ObjRecognizeMux( pRoot, &pFanin0, &pFanin1 );
+ else
+ {
+ pFaninC = NULL;
+ pFanin0 = Ivy_ObjFanin0(pRoot);
+ pFanin1 = Ivy_ObjFanin1(pRoot);
+ }
+ // start cone A
+ pFanin0->fMarkA = 1;
+ Vec_PtrPush( vFront, pFanin0 );
+ Vec_PtrPush( vVolume, pFanin0 );
+ // start cone B
+ pFanin1->fMarkB = 1;
+ Vec_PtrPush( vFront, pFanin1 );
+ Vec_PtrPush( vVolume, pFanin1 );
+ // iteratively expand until the common node (pPivot) is found or limit is reached
+ assert( Ivy_ObjLevel(pRoot) == Ivy_ObjLevelNew(pRoot) );
+ pPivot = NULL;
+ LevelLimit = IVY_MAX( Ivy_ObjLevel(pRoot) - 10, 1 );
+ for ( Lev = Ivy_ObjLevel(pRoot) - 1; Lev >= LevelLimit; Lev-- )
+ {
+ while ( 1 )
+ {
+ // find the next node to expand on this level
+ Vec_PtrForEachEntry( vFront, pObj, k )
+ if ( (int)pObj->Level == Lev )
+ break;
+ if ( k == Vec_PtrSize(vFront) )
+ break;
+ assert( (int)pObj->Level <= Lev );
+ assert( pObj->fMarkA ^ pObj->fMarkB );
+ // remove the old node
+ Vec_PtrRemove( vFront, pObj );
+
+ // expand this node
+ pFanin0 = Ivy_ObjFanin0(pObj);
+ if ( !pFanin0->fMarkA && !pFanin0->fMarkB )
+ {
+ Vec_PtrPush( vFront, pFanin0 );
+ Vec_PtrPush( vVolume, pFanin0 );
+ }
+ // mark the new nodes
+ if ( pObj->fMarkA )
+ pFanin0->fMarkA = 1;
+ if ( pObj->fMarkB )
+ pFanin0->fMarkB = 1;
+
+ if ( Ivy_ObjIsBuf(pObj) )
+ {
+ if ( pFanin0->fMarkA && pFanin0->fMarkB )
+ {
+ pPivot = pFanin0;
+ break;
+ }
+ continue;
+ }
+
+ // expand this node
+ pFanin1 = Ivy_ObjFanin1(pObj);
+ if ( !pFanin1->fMarkA && !pFanin1->fMarkB )
+ {
+ Vec_PtrPush( vFront, pFanin1 );
+ Vec_PtrPush( vVolume, pFanin1 );
+ }
+ // mark the new nodes
+ if ( pObj->fMarkA )
+ pFanin1->fMarkA = 1;
+ if ( pObj->fMarkB )
+ pFanin1->fMarkB = 1;
+
+ // consider if it is time to quit
+ if ( pFanin0->fMarkA && pFanin0->fMarkB )
+ {
+ pPivot = pFanin0;
+ break;
+ }
+ if ( pFanin1->fMarkA && pFanin1->fMarkB )
+ {
+ pPivot = pFanin1;
+ break;
+ }
+ }
+ if ( pPivot != NULL )
+ break;
+ }
+ if ( pPivot == NULL )
+ return 0;
+ // if the MUX control is defined, it should not be
+ if ( pFaninC && !pFaninC->fMarkA && !pFaninC->fMarkB )
+ Vec_PtrPush( vFront, pFaninC );
+ // clean the markings
+ Vec_PtrForEachEntry( vVolume, pObj, k )
+ pObj->fMarkA = pObj->fMarkB = 0;
+
+ // mark the nodes on the frontier (including the pivot)
+ Vec_PtrForEachEntry( vFront, pObj, k )
+ pObj->fMarkA = 1;
+ // cut exists, collect all the nodes on the shortest path to the pivot
+ Vec_PtrClear( vLeaves );
+ Vec_PtrClear( vVolume );
+ RetValue = Ivy_ManFindBoolCut_rec( p, pRoot, vLeaves, vVolume, pPivot );
+ assert( RetValue == 1 );
+ // unmark the nodes on the frontier (including the pivot)
+ Vec_PtrForEachEntry( vFront, pObj, k )
+ pObj->fMarkA = 0;
+
+ // mark the nodes in the volume
+ Vec_PtrForEachEntry( vVolume, pObj, k )
+ pObj->fMarkA = 1;
+ // expand the cut without increasing its size
+ while ( 1 )
+ {
+ Vec_PtrForEachEntry( vLeaves, pObj, k )
+ if ( Ivy_ManFindBoolCutCost(pObj) < 2 )
+ break;
+ if ( k == Vec_PtrSize(vLeaves) )
+ break;
+ // the node can be expanded
+ // remove the old node
+ Vec_PtrRemove( vLeaves, pObj );
+ // expand this node
+ pFanin0 = Ivy_ObjFanin0(pObj);
+ if ( !pFanin0->fMarkA )
+ {
+ pFanin0->fMarkA = 1;
+ Vec_PtrPush( vVolume, pFanin0 );
+ Vec_PtrPush( vLeaves, pFanin0 );
+ }
+ if ( Ivy_ObjIsBuf(pObj) )
+ continue;
+ // expand this node
+ pFanin1 = Ivy_ObjFanin1(pObj);
+ if ( !pFanin1->fMarkA )
+ {
+ pFanin1->fMarkA = 1;
+ Vec_PtrPush( vVolume, pFanin1 );
+ Vec_PtrPush( vLeaves, pFanin1 );
+ }
+ }
+ // unmark the nodes in the volume
+ Vec_PtrForEachEntry( vVolume, pObj, k )
+ pObj->fMarkA = 0;
+ return 1;
+}
+
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Ivy_ManTestCutsBool( Ivy_Man_t * p )
+{
+ Vec_Ptr_t * vFront, * vVolume, * vLeaves;
+ Ivy_Obj_t * pObj;//, * pTemp;
+ int i, RetValue;//, k;
+ vFront = Vec_PtrAlloc( 100 );
+ vVolume = Vec_PtrAlloc( 100 );
+ vLeaves = Vec_PtrAlloc( 100 );
+ Ivy_ManForEachObj( p, pObj, i )
+ {
+ if ( !Ivy_ObjIsNode(pObj) )
+ continue;
+ if ( Ivy_ObjIsMuxType(pObj) )
+ {
+ printf( "m" );
+ continue;
+ }
+ if ( Ivy_ObjIsExor(pObj) )
+ printf( "x" );
+ RetValue = Ivy_ManFindBoolCut( p, pObj, vFront, vVolume, vLeaves );
+ if ( RetValue == 0 )
+ printf( "- " );
+ else
+ printf( "%d ", Vec_PtrSize(vLeaves) );
+/*
+ printf( "( " );
+ Vec_PtrForEachEntry( vFront, pTemp, k )
+ printf( "%d ", Ivy_ObjRefs(Ivy_Regular(pTemp)) );
+ printf( ")\n" );
+*/
+ }
+ printf( "\n" );
+ Vec_PtrFree( vFront );
+ Vec_PtrFree( vVolume );
+ Vec_PtrFree( vLeaves );
+}
+
+
+
+/**Function*************************************************************
+
+ Synopsis [Find the hash value of the cut.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+static inline unsigned Ivy_NodeCutHash( Ivy_Cut_t * pCut )
+{
+ int i;
+// for ( i = 1; i < pCut->nSize; i++ )
+// assert( pCut->pArray[i-1] < pCut->pArray[i] );
+ pCut->uHash = 0;
+ for ( i = 0; i < pCut->nSize; i++ )
+ pCut->uHash |= (1 << (pCut->pArray[i] % 31));
+ return pCut->uHash;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Removes one node to the cut.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+static inline void Ivy_NodeCutShrink( Ivy_Cut_t * pCut, int iOld )
+{
+ int i, k;
+ for ( i = k = 0; i < pCut->nSize; i++ )
+ if ( pCut->pArray[i] != iOld )
+ pCut->pArray[k++] = pCut->pArray[i];
+ assert( k == pCut->nSize - 1 );
+ pCut->nSize--;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Adds one node to the cut.]
+
+ Description [Returns 1 if the cuts is still okay.]
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+static inline int Ivy_NodeCutExtend( Ivy_Cut_t * pCut, int iNew )
+{
+ int i;
+ for ( i = 0; i < pCut->nSize; i++ )
+ if ( pCut->pArray[i] == iNew )
+ return 1;
+ // check if there is room
+ if ( pCut->nSize == pCut->nSizeMax )
+ return 0;
+ // add the new one
+ for ( i = pCut->nSize - 1; i >= 0; i-- )
+ if ( pCut->pArray[i] > iNew )
+ pCut->pArray[i+1] = pCut->pArray[i];
+ else
+ {
+ assert( pCut->pArray[i] < iNew );
+ break;
+ }
+ pCut->pArray[i+1] = iNew;
+ pCut->nSize++;
+ return 1;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Returns 1 if the cut can be constructed; 0 otherwise.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+static inline int Ivy_NodeCutPrescreen( Ivy_Cut_t * pCut, int Id0, int Id1 )
+{
+ int i;
+ if ( pCut->nSize < pCut->nSizeMax )
+ return 1;
+ for ( i = 0; i < pCut->nSize; i++ )
+ if ( pCut->pArray[i] == Id0 || pCut->pArray[i] == Id1 )
+ return 1;
+ return 0;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Derives new cut.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+static inline int Ivy_NodeCutDeriveNew( Ivy_Cut_t * pCut, Ivy_Cut_t * pCutNew, int IdOld, int IdNew0, int IdNew1 )
+{
+ unsigned uHash = 0;
+ int i, k;
+ assert( pCut->nSize > 0 );
+ assert( IdNew0 < IdNew1 );
+ for ( i = k = 0; i < pCut->nSize; i++ )
+ {
+ if ( pCut->pArray[i] == IdOld )
+ continue;
+ if ( IdNew0 <= pCut->pArray[i] )
+ {
+ if ( IdNew0 < pCut->pArray[i] )
+ {
+ pCutNew->pArray[ k++ ] = IdNew0;
+ uHash |= Ivy_NodeCutHashValue( IdNew0 );
+ }
+ IdNew0 = 0x7FFFFFFF;
+ }
+ if ( IdNew1 <= pCut->pArray[i] )
+ {
+ if ( IdNew1 < pCut->pArray[i] )
+ {
+ pCutNew->pArray[ k++ ] = IdNew1;
+ uHash |= Ivy_NodeCutHashValue( IdNew1 );
+ }
+ IdNew1 = 0x7FFFFFFF;
+ }
+ pCutNew->pArray[ k++ ] = pCut->pArray[i];
+ uHash |= Ivy_NodeCutHashValue( pCut->pArray[i] );
+ }
+ if ( IdNew0 < 0x7FFFFFFF )
+ {
+ pCutNew->pArray[ k++ ] = IdNew0;
+ uHash |= Ivy_NodeCutHashValue( IdNew0 );
+ }
+ if ( IdNew1 < 0x7FFFFFFF )
+ {
+ pCutNew->pArray[ k++ ] = IdNew1;
+ uHash |= Ivy_NodeCutHashValue( IdNew1 );
+ }
+ pCutNew->nSize = k;
+ pCutNew->uHash = uHash;
+ assert( pCutNew->nSize <= pCut->nSizeMax );
+// for ( i = 1; i < pCutNew->nSize; i++ )
+// assert( pCutNew->pArray[i-1] < pCutNew->pArray[i] );
+ return 1;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Check if the cut exists.]
+
+ Description [Returns 1 if the cut exists.]
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Ivy_NodeCutFindOrAdd( Ivy_Store_t * pCutStore, Ivy_Cut_t * pCutNew )
+{
+ Ivy_Cut_t * pCut;
+ int i, k;
+ assert( pCutNew->uHash );
+ // try to find the cut
+ for ( i = 0; i < pCutStore->nCuts; i++ )
+ {
+ pCut = pCutStore->pCuts + i;
+ if ( pCut->uHash == pCutNew->uHash && pCut->nSize == pCutNew->nSize )
+ {
+ for ( k = 0; k < pCutNew->nSize; k++ )
+ if ( pCut->pArray[k] != pCutNew->pArray[k] )
+ break;
+ if ( k == pCutNew->nSize )
+ return 1;
+ }
+ }
+ assert( pCutStore->nCuts < pCutStore->nCutsMax );
+ // add the cut
+ pCut = pCutStore->pCuts + pCutStore->nCuts++;
+ *pCut = *pCutNew;
+ return 0;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Returns 1 if pDom is contained in pCut.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+static inline int Ivy_CutCheckDominance( Ivy_Cut_t * pDom, Ivy_Cut_t * pCut )
+{
+ int i, k;
+ for ( i = 0; i < pDom->nSize; i++ )
+ {
+ for ( k = 0; k < pCut->nSize; k++ )
+ if ( pDom->pArray[i] == pCut->pArray[k] )
+ break;
+ if ( k == pCut->nSize ) // node i in pDom is not contained in pCut
+ return 0;
+ }
+ // every node in pDom is contained in pCut
+ return 1;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Check if the cut exists.]
+
+ Description [Returns 1 if the cut exists.]
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Ivy_NodeCutFindOrAddFilter( Ivy_Store_t * pCutStore, Ivy_Cut_t * pCutNew )
+{
+ Ivy_Cut_t * pCut;
+ int i, k;
+ assert( pCutNew->uHash );
+ // try to find the cut
+ for ( i = 0; i < pCutStore->nCuts; i++ )
+ {
+ pCut = pCutStore->pCuts + i;
+ if ( pCut->nSize == 0 )
+ continue;
+ if ( pCut->nSize == pCutNew->nSize )
+ {
+ if ( pCut->uHash == pCutNew->uHash )
+ {
+ for ( k = 0; k < pCutNew->nSize; k++ )
+ if ( pCut->pArray[k] != pCutNew->pArray[k] )
+ break;
+ if ( k == pCutNew->nSize )
+ return 1;
+ }
+ continue;
+ }
+ if ( pCut->nSize < pCutNew->nSize )
+ {
+ // skip the non-contained cuts
+ if ( (pCut->uHash & pCutNew->uHash) != pCut->uHash )
+ continue;
+ // check containment seriously
+ if ( Ivy_CutCheckDominance( pCut, pCutNew ) )
+ return 1;
+ continue;
+ }
+ // check potential containment of other cut
+
+ // skip the non-contained cuts
+ if ( (pCut->uHash & pCutNew->uHash) != pCutNew->uHash )
+ continue;
+ // check containment seriously
+ if ( Ivy_CutCheckDominance( pCutNew, pCut ) )
+ {
+ // remove the current cut
+// --pCutStore->nCuts;
+// for ( k = i; k < pCutStore->nCuts; k++ )
+// pCutStore->pCuts[k] = pCutStore->pCuts[k+1];
+// i--;
+ pCut->nSize = 0;
+ }
+ }
+ assert( pCutStore->nCuts < pCutStore->nCutsMax );
+ // add the cut
+ pCut = pCutStore->pCuts + pCutStore->nCuts++;
+ *pCut = *pCutNew;
+ return 0;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Print the cut.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Ivy_NodeCompactCuts( Ivy_Store_t * pCutStore )
+{
+ Ivy_Cut_t * pCut;
+ int i, k;
+ for ( i = k = 0; i < pCutStore->nCuts; i++ )
+ {
+ pCut = pCutStore->pCuts + i;
+ if ( pCut->nSize == 0 )
+ continue;
+ pCutStore->pCuts[k++] = *pCut;
+ }
+ pCutStore->nCuts = k;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Print the cut.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Ivy_NodePrintCut( Ivy_Cut_t * pCut )
+{
+ int i;
+ assert( pCut->nSize > 0 );
+ printf( "%d : {", pCut->nSize );
+ for ( i = 0; i < pCut->nSize; i++ )
+ printf( " %d", pCut->pArray[i] );
+ printf( " }\n" );
+}
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Ivy_NodePrintCuts( Ivy_Store_t * pCutStore )
+{
+ int i;
+ printf( "Node %d\n", pCutStore->pCuts[0].pArray[0] );
+ for ( i = 0; i < pCutStore->nCuts; i++ )
+ Ivy_NodePrintCut( pCutStore->pCuts + i );
+}
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+static inline Ivy_Obj_t * Ivy_ObjRealFanin( Ivy_Obj_t * pObj )
+{
+ if ( !Ivy_ObjIsBuf(pObj) )
+ return pObj;
+ return Ivy_ObjRealFanin( Ivy_ObjFanin0(pObj) );
+}
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Ivy_Store_t * Ivy_NodeFindCutsAll( Ivy_Man_t * p, Ivy_Obj_t * pObj, int nLeaves )
+{
+ static Ivy_Store_t CutStore, * pCutStore = &CutStore;
+ Ivy_Cut_t CutNew, * pCutNew = &CutNew, * pCut;
+ Ivy_Obj_t * pLeaf;
+ int i, k, iLeaf0, iLeaf1;
+
+ assert( nLeaves <= IVY_CUT_INPUT );
+
+ // start the structure
+ pCutStore->nCuts = 0;
+ pCutStore->nCutsMax = IVY_CUT_LIMIT;
+ // start the trivial cut
+ pCutNew->uHash = 0;
+ pCutNew->nSize = 1;
+ pCutNew->nSizeMax = nLeaves;
+ pCutNew->pArray[0] = pObj->Id;
+ Ivy_NodeCutHash( pCutNew );
+ // add the trivial cut
+ Ivy_NodeCutFindOrAdd( pCutStore, pCutNew );
+ assert( pCutStore->nCuts == 1 );
+
+ // explore the cuts
+ for ( i = 0; i < pCutStore->nCuts; i++ )
+ {
+ // expand this cut
+ pCut = pCutStore->pCuts + i;
+ if ( pCut->nSize == 0 )
+ continue;
+ for ( k = 0; k < pCut->nSize; k++ )
+ {
+ pLeaf = Ivy_ManObj( p, pCut->pArray[k] );
+ if ( Ivy_ObjIsCi(pLeaf) )
+ continue;
+/*
+ *pCutNew = *pCut;
+ Ivy_NodeCutShrink( pCutNew, pLeaf->Id );
+ if ( !Ivy_NodeCutExtend( pCutNew, Ivy_ObjFaninId0(pLeaf) ) )
+ continue;
+ if ( Ivy_ObjIsNode(pLeaf) && !Ivy_NodeCutExtend( pCutNew, Ivy_ObjFaninId1(pLeaf) ) )
+ continue;
+ Ivy_NodeCutHash( pCutNew );
+*/
+ iLeaf0 = Ivy_ObjId( Ivy_ObjRealFanin(Ivy_ObjFanin0(pLeaf)) );
+ iLeaf1 = Ivy_ObjId( Ivy_ObjRealFanin(Ivy_ObjFanin1(pLeaf)) );
+// if ( iLeaf0 == iLeaf1 ) // strange situation observed on Jan 18, 2007
+// continue;
+ if ( !Ivy_NodeCutPrescreen( pCut, iLeaf0, iLeaf1 ) )
+ continue;
+ if ( iLeaf0 > iLeaf1 )
+ Ivy_NodeCutDeriveNew( pCut, pCutNew, pCut->pArray[k], iLeaf1, iLeaf0 );
+ else
+ Ivy_NodeCutDeriveNew( pCut, pCutNew, pCut->pArray[k], iLeaf0, iLeaf1 );
+ Ivy_NodeCutFindOrAddFilter( pCutStore, pCutNew );
+ if ( pCutStore->nCuts == IVY_CUT_LIMIT )
+ break;
+ }
+ if ( pCutStore->nCuts == IVY_CUT_LIMIT )
+ break;
+ }
+ Ivy_NodeCompactCuts( pCutStore );
+// Ivy_NodePrintCuts( pCutStore );
+ return pCutStore;
+}
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Ivy_ManTestCutsAll( Ivy_Man_t * p )
+{
+ Ivy_Obj_t * pObj;
+ int i, nCutsCut, nCutsTotal, nNodeTotal, nNodeOver;
+ int clk = clock();
+ nNodeTotal = nNodeOver = 0;
+ nCutsTotal = -Ivy_ManNodeNum(p);
+ Ivy_ManForEachObj( p, pObj, i )
+ {
+ if ( !Ivy_ObjIsNode(pObj) )
+ continue;
+ nCutsCut = Ivy_NodeFindCutsAll( p, pObj, 5 )->nCuts;
+ nCutsTotal += nCutsCut;
+ nNodeOver += (nCutsCut == IVY_CUT_LIMIT);
+ nNodeTotal++;
+ }
+ printf( "Total cuts = %6d. Trivial = %6d. Nodes = %6d. Satur = %6d. ",
+ nCutsTotal, Ivy_ManPiNum(p) + Ivy_ManNodeNum(p), nNodeTotal, nNodeOver );
+ PRT( "Time", clock() - clk );
+}
+
+////////////////////////////////////////////////////////////////////////
+/// END OF FILE ///
+////////////////////////////////////////////////////////////////////////
+
+
diff --git a/src/aig/ivy/ivyCutTrav.c b/src/aig/ivy/ivyCutTrav.c
new file mode 100644
index 00000000..ea57c9f5
--- /dev/null
+++ b/src/aig/ivy/ivyCutTrav.c
@@ -0,0 +1,473 @@
+/**CFile****************************************************************
+
+ FileName [ivyCutTrav.c]
+
+ SystemName [ABC: Logic synthesis and verification system.]
+
+ PackageName [And-Inverter Graph package.]
+
+ Synopsis []
+
+ Author [Alan Mishchenko]
+
+ Affiliation [UC Berkeley]
+
+ Date [Ver. 1.0. Started - May 11, 2006.]
+
+ Revision [$Id: ivyCutTrav.c,v 1.00 2006/05/11 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "ivy.h"
+
+////////////////////////////////////////////////////////////////////////
+/// DECLARATIONS ///
+////////////////////////////////////////////////////////////////////////
+
+static unsigned * Ivy_NodeCutElementary( Vec_Int_t * vStore, int nWords, int NodeId );
+static void Ivy_NodeComputeVolume( Ivy_Obj_t * pObj, int nNodeLimit, Vec_Ptr_t * vNodes, Vec_Ptr_t * vFront );
+static void Ivy_NodeFindCutsMerge( Vec_Ptr_t * vCuts0, Vec_Ptr_t * vCuts1, Vec_Ptr_t * vCuts, int nLeaves, int nWords, Vec_Int_t * vStore );
+
+////////////////////////////////////////////////////////////////////////
+/// FUNCTION DEFINITIONS ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+ Synopsis [Computes cuts for one node.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Ivy_Store_t * Ivy_NodeFindCutsTravAll( Ivy_Man_t * p, Ivy_Obj_t * pObj, int nLeaves, int nNodeLimit,
+ Vec_Ptr_t * vNodes, Vec_Ptr_t * vFront, Vec_Int_t * vStore, Vec_Vec_t * vBitCuts )
+{
+ static Ivy_Store_t CutStore, * pCutStore = &CutStore;
+ Vec_Ptr_t * vCuts, * vCuts0, * vCuts1;
+ unsigned * pBitCut;
+ Ivy_Obj_t * pLeaf;
+ Ivy_Cut_t * pCut;
+ int i, k, nWords, nNodes;
+
+ assert( nLeaves <= IVY_CUT_INPUT );
+
+ // find the given number of nodes in the TFI
+ Ivy_NodeComputeVolume( pObj, nNodeLimit - 1, vNodes, vFront );
+ nNodes = Vec_PtrSize(vNodes);
+// assert( nNodes <= nNodeLimit );
+
+ // make sure vBitCuts has enough room
+ Vec_VecExpand( vBitCuts, nNodes-1 );
+ Vec_VecClear( vBitCuts );
+
+ // prepare the memory manager
+ Vec_IntClear( vStore );
+ Vec_IntGrow( vStore, 64000 );
+
+ // set elementary cuts for the leaves
+ nWords = Extra_BitWordNum( nNodes );
+ Vec_PtrForEachEntry( vFront, pLeaf, i )
+ {
+ assert( Ivy_ObjTravId(pLeaf) < nNodes );
+ // get the new bitcut
+ pBitCut = Ivy_NodeCutElementary( vStore, nWords, Ivy_ObjTravId(pLeaf) );
+ // set it as the cut of this leaf
+ Vec_VecPush( vBitCuts, Ivy_ObjTravId(pLeaf), pBitCut );
+ }
+
+ // compute the cuts for each node
+ Vec_PtrForEachEntry( vNodes, pLeaf, i )
+ {
+ // skip the leaves
+ vCuts = Vec_VecEntry( vBitCuts, Ivy_ObjTravId(pLeaf) );
+ if ( Vec_PtrSize(vCuts) > 0 )
+ continue;
+ // add elementary cut
+ pBitCut = Ivy_NodeCutElementary( vStore, nWords, Ivy_ObjTravId(pLeaf) );
+ // set it as the cut of this leaf
+ Vec_VecPush( vBitCuts, Ivy_ObjTravId(pLeaf), pBitCut );
+ // get the fanin cuts
+ vCuts0 = Vec_VecEntry( vBitCuts, Ivy_ObjTravId( Ivy_ObjFanin0(pLeaf) ) );
+ vCuts1 = Vec_VecEntry( vBitCuts, Ivy_ObjTravId( Ivy_ObjFanin1(pLeaf) ) );
+ assert( Vec_PtrSize(vCuts0) > 0 );
+ assert( Vec_PtrSize(vCuts1) > 0 );
+ // merge the cuts
+ Ivy_NodeFindCutsMerge( vCuts0, vCuts1, vCuts, nLeaves, nWords, vStore );
+ }
+
+ // start the structure
+ pCutStore->nCuts = 0;
+ pCutStore->nCutsMax = IVY_CUT_LIMIT;
+ // collect the cuts of the root node
+ vCuts = Vec_VecEntry( vBitCuts, Ivy_ObjTravId(pObj) );
+ Vec_PtrForEachEntry( vCuts, pBitCut, i )
+ {
+ pCut = pCutStore->pCuts + pCutStore->nCuts++;
+ pCut->nSize = 0;
+ pCut->nSizeMax = nLeaves;
+ pCut->uHash = 0;
+ for ( k = 0; k < nNodes; k++ )
+ if ( Extra_TruthHasBit(pBitCut, k) )
+ pCut->pArray[ pCut->nSize++ ] = Ivy_ObjId( Vec_PtrEntry(vNodes, k) );
+ assert( pCut->nSize <= nLeaves );
+ if ( pCutStore->nCuts == pCutStore->nCutsMax )
+ break;
+ }
+
+ // clean the travIds
+ Vec_PtrForEachEntry( vNodes, pLeaf, i )
+ pLeaf->TravId = 0;
+ return pCutStore;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Creates elementary bit-cut.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+unsigned * Ivy_NodeCutElementary( Vec_Int_t * vStore, int nWords, int NodeId )
+{
+ unsigned * pBitCut;
+ pBitCut = Vec_IntFetch( vStore, nWords );
+ memset( pBitCut, 0, 4 * nWords );
+ Extra_TruthSetBit( pBitCut, NodeId );
+ return pBitCut;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Compares the node by level.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Ivy_CompareNodesByLevel( Ivy_Obj_t ** ppObj1, Ivy_Obj_t ** ppObj2 )
+{
+ Ivy_Obj_t * pObj1 = *ppObj1;
+ Ivy_Obj_t * pObj2 = *ppObj2;
+ if ( pObj1->Level < pObj2->Level )
+ return -1;
+ if ( pObj1->Level > pObj2->Level )
+ return 1;
+ return 0;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Mark all nodes up to the given depth.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Ivy_NodeComputeVolumeTrav1_rec( Ivy_Obj_t * pObj, int Depth )
+{
+ if ( Ivy_ObjIsCi(pObj) || Depth == 0 )
+ return;
+ Ivy_NodeComputeVolumeTrav1_rec( Ivy_ObjFanin0(pObj), Depth - 1 );
+ Ivy_NodeComputeVolumeTrav1_rec( Ivy_ObjFanin1(pObj), Depth - 1 );
+ pObj->fMarkA = 1;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Collect the marked nodes.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Ivy_NodeComputeVolumeTrav2_rec( Ivy_Obj_t * pObj, Vec_Ptr_t * vNodes )
+{
+ if ( !pObj->fMarkA )
+ return;
+ Ivy_NodeComputeVolumeTrav2_rec( Ivy_ObjFanin0(pObj), vNodes );
+ Ivy_NodeComputeVolumeTrav2_rec( Ivy_ObjFanin1(pObj), vNodes );
+ Vec_PtrPush( vNodes, pObj );
+}
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Ivy_NodeComputeVolume( Ivy_Obj_t * pObj, int nNodeLimit, Vec_Ptr_t * vNodes, Vec_Ptr_t * vFront )
+{
+ Ivy_Obj_t * pTemp, * pFanin;
+ int i, nNodes;
+ // mark nodes up to the given depth
+ Ivy_NodeComputeVolumeTrav1_rec( pObj, 6 );
+ // collect the marked nodes
+ Vec_PtrClear( vFront );
+ Ivy_NodeComputeVolumeTrav2_rec( pObj, vFront );
+ // find the fanins that are not marked
+ Vec_PtrClear( vNodes );
+ Vec_PtrForEachEntry( vFront, pTemp, i )
+ {
+ pFanin = Ivy_ObjFanin0(pTemp);
+ if ( !pFanin->fMarkA )
+ {
+ pFanin->fMarkA = 1;
+ Vec_PtrPush( vNodes, pFanin );
+ }
+ pFanin = Ivy_ObjFanin1(pTemp);
+ if ( !pFanin->fMarkA )
+ {
+ pFanin->fMarkA = 1;
+ Vec_PtrPush( vNodes, pFanin );
+ }
+ }
+ // remember the number of nodes in the frontier
+ nNodes = Vec_PtrSize( vNodes );
+ // add the remaining nodes
+ Vec_PtrForEachEntry( vFront, pTemp, i )
+ Vec_PtrPush( vNodes, pTemp );
+ // unmark the nodes
+ Vec_PtrForEachEntry( vNodes, pTemp, i )
+ {
+ pTemp->fMarkA = 0;
+ pTemp->TravId = i;
+ }
+ // collect the frontier nodes
+ Vec_PtrClear( vFront );
+ Vec_PtrForEachEntryStop( vNodes, pTemp, i, nNodes )
+ Vec_PtrPush( vFront, pTemp );
+// printf( "%d ", Vec_PtrSize(vNodes) );
+}
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Ivy_NodeComputeVolume2( Ivy_Obj_t * pObj, int nNodeLimit, Vec_Ptr_t * vNodes, Vec_Ptr_t * vFront )
+{
+ Ivy_Obj_t * pLeaf, * pPivot, * pFanin;
+ int LevelMax, i;
+ assert( Ivy_ObjIsNode(pObj) );
+ // clear arrays
+ Vec_PtrClear( vNodes );
+ Vec_PtrClear( vFront );
+ // add the root
+ pObj->fMarkA = 1;
+ Vec_PtrPush( vNodes, pObj );
+ Vec_PtrPush( vFront, pObj );
+ // expand node with maximum level
+ LevelMax = pObj->Level;
+ do {
+ // get the node to expand
+ pPivot = NULL;
+ Vec_PtrForEachEntryReverse( vFront, pLeaf, i )
+ {
+ if ( (int)pLeaf->Level == LevelMax )
+ {
+ pPivot = pLeaf;
+ break;
+ }
+ }
+ // decrease level if we did not find the node
+ if ( pPivot == NULL )
+ {
+ if ( --LevelMax == 0 )
+ break;
+ continue;
+ }
+ // the node to expand is found
+ // remove it from frontier
+ Vec_PtrRemove( vFront, pPivot );
+ // add fanins
+ pFanin = Ivy_ObjFanin0(pPivot);
+ if ( !pFanin->fMarkA )
+ {
+ pFanin->fMarkA = 1;
+ Vec_PtrPush( vNodes, pFanin );
+ Vec_PtrPush( vFront, pFanin );
+ }
+ pFanin = Ivy_ObjFanin1(pPivot);
+ if ( pFanin && !pFanin->fMarkA )
+ {
+ pFanin->fMarkA = 1;
+ Vec_PtrPush( vNodes, pFanin );
+ Vec_PtrPush( vFront, pFanin );
+ }
+ // quit if we collected enough nodes
+ } while ( Vec_PtrSize(vNodes) < nNodeLimit );
+
+ // sort nodes by level
+ Vec_PtrSort( vNodes, Ivy_CompareNodesByLevel );
+ // make sure the nodes are ordered in the increasing number of levels
+ pFanin = Vec_PtrEntry( vNodes, 0 );
+ pPivot = Vec_PtrEntryLast( vNodes );
+ assert( pFanin->Level <= pPivot->Level );
+
+ // clean the marks and remember node numbers in the TravId
+ Vec_PtrForEachEntry( vNodes, pFanin, i )
+ {
+ pFanin->fMarkA = 0;
+ pFanin->TravId = i;
+ }
+}
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+static inline void Extra_TruthOrWords( unsigned * pOut, unsigned * pIn0, unsigned * pIn1, int nWords )
+{
+ int w;
+ for ( w = nWords-1; w >= 0; w-- )
+ pOut[w] = pIn0[w] | pIn1[w];
+}
+static inline int Extra_TruthIsImplyWords( unsigned * pIn1, unsigned * pIn2, int nWords )
+{
+ int w;
+ for ( w = nWords-1; w >= 0; w-- )
+ if ( pIn1[w] & ~pIn2[w] )
+ return 0;
+ return 1;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Merges two sets of bit-cuts at a node.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Ivy_NodeFindCutsMerge( Vec_Ptr_t * vCuts0, Vec_Ptr_t * vCuts1, Vec_Ptr_t * vCuts,
+ int nLeaves, int nWords, Vec_Int_t * vStore )
+{
+ unsigned * pBitCut, * pBitCut0, * pBitCut1, * pBitCutTest;
+ int i, k, c, w, Counter;
+ // iterate through the cut pairs
+ Vec_PtrForEachEntry( vCuts0, pBitCut0, i )
+ Vec_PtrForEachEntry( vCuts1, pBitCut1, k )
+ {
+ // skip infeasible cuts
+ Counter = 0;
+ for ( w = 0; w < nWords; w++ )
+ {
+ Counter += Extra_WordCountOnes( pBitCut0[w] | pBitCut1[w] );
+ if ( Counter > nLeaves )
+ break;
+ }
+ if ( Counter > nLeaves )
+ continue;
+ // the new cut is feasible - create it
+ pBitCutTest = Vec_IntFetch( vStore, nWords );
+ Extra_TruthOrWords( pBitCutTest, pBitCut0, pBitCut1, nWords );
+ // filter contained cuts; try to find containing cut
+ w = 0;
+ Vec_PtrForEachEntry( vCuts, pBitCut, c )
+ {
+ if ( Extra_TruthIsImplyWords( pBitCut, pBitCutTest, nWords ) )
+ break;
+ if ( Extra_TruthIsImplyWords( pBitCutTest, pBitCut, nWords ) )
+ continue;
+ Vec_PtrWriteEntry( vCuts, w++, pBitCut );
+ }
+ if ( c != Vec_PtrSize(vCuts) )
+ continue;
+ Vec_PtrShrink( vCuts, w );
+ // add the cut
+ Vec_PtrPush( vCuts, pBitCutTest );
+ }
+}
+
+/**Function*************************************************************
+
+ Synopsis [Compute the set of all cuts.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Ivy_ManTestCutsTravAll( Ivy_Man_t * p )
+{
+ Ivy_Store_t * pStore;
+ Ivy_Obj_t * pObj;
+ Vec_Ptr_t * vNodes, * vFront;
+ Vec_Int_t * vStore;
+ Vec_Vec_t * vBitCuts;
+ int i, nCutsCut, nCutsTotal, nNodeTotal, nNodeOver;
+ int clk = clock();
+
+ vNodes = Vec_PtrAlloc( 100 );
+ vFront = Vec_PtrAlloc( 100 );
+ vStore = Vec_IntAlloc( 100 );
+ vBitCuts = Vec_VecAlloc( 100 );
+
+ nNodeTotal = nNodeOver = 0;
+ nCutsTotal = -Ivy_ManNodeNum(p);
+ Ivy_ManForEachObj( p, pObj, i )
+ {
+ if ( !Ivy_ObjIsNode(pObj) )
+ continue;
+ pStore = Ivy_NodeFindCutsTravAll( p, pObj, 4, 60, vNodes, vFront, vStore, vBitCuts );
+ nCutsCut = pStore->nCuts;
+ nCutsTotal += nCutsCut;
+ nNodeOver += (nCutsCut == IVY_CUT_LIMIT);
+ nNodeTotal++;
+ }
+ printf( "Total cuts = %6d. Trivial = %6d. Nodes = %6d. Satur = %6d. ",
+ nCutsTotal, Ivy_ManPiNum(p) + Ivy_ManNodeNum(p), nNodeTotal, nNodeOver );
+ PRT( "Time", clock() - clk );
+
+ Vec_PtrFree( vNodes );
+ Vec_PtrFree( vFront );
+ Vec_IntFree( vStore );
+ Vec_VecFree( vBitCuts );
+
+}
+
+////////////////////////////////////////////////////////////////////////
+/// END OF FILE ///
+////////////////////////////////////////////////////////////////////////
+
+
diff --git a/src/aig/ivy/ivyDfs.c b/src/aig/ivy/ivyDfs.c
new file mode 100644
index 00000000..c27cba31
--- /dev/null
+++ b/src/aig/ivy/ivyDfs.c
@@ -0,0 +1,493 @@
+/**CFile****************************************************************
+
+ FileName [ivyDfs.c]
+
+ SystemName [ABC: Logic synthesis and verification system.]
+
+ PackageName [And-Inverter Graph package.]
+
+ Synopsis [DFS collection procedures.]
+
+ Author [Alan Mishchenko]
+
+ Affiliation [UC Berkeley]
+
+ Date [Ver. 1.0. Started - May 11, 2006.]
+
+ Revision [$Id: ivyDfs.c,v 1.00 2006/05/11 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "ivy.h"
+
+////////////////////////////////////////////////////////////////////////
+/// DECLARATIONS ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+/// FUNCTION DEFINITIONS ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+ Synopsis [Collects nodes in the DFS order.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Ivy_ManDfs_rec( Ivy_Man_t * p, Ivy_Obj_t * pObj, Vec_Int_t * vNodes )
+{
+ if ( Ivy_ObjIsMarkA(pObj) )
+ return;
+ Ivy_ObjSetMarkA(pObj);
+ if ( Ivy_ObjIsConst1(pObj) || Ivy_ObjIsCi(pObj) )
+ {
+ if ( p->pHaig == NULL && pObj->pEquiv )
+ Ivy_ManDfs_rec( p, Ivy_Regular(pObj->pEquiv), vNodes );
+ return;
+ }
+//printf( "visiting node %d\n", pObj->Id );
+/*
+ if ( pObj->Id == 87 || pObj->Id == 90 )
+ {
+ int y = 0;
+ }
+*/
+ assert( Ivy_ObjIsBuf(pObj) || Ivy_ObjIsAnd(pObj) || Ivy_ObjIsExor(pObj) );
+ Ivy_ManDfs_rec( p, Ivy_ObjFanin0(pObj), vNodes );
+ if ( !Ivy_ObjIsBuf(pObj) )
+ Ivy_ManDfs_rec( p, Ivy_ObjFanin1(pObj), vNodes );
+ if ( p->pHaig == NULL && pObj->pEquiv )
+ Ivy_ManDfs_rec( p, Ivy_Regular(pObj->pEquiv), vNodes );
+ Vec_IntPush( vNodes, pObj->Id );
+
+//printf( "adding node %d with fanins %d and %d and equiv %d (refs = %d)\n",
+// pObj->Id, Ivy_ObjFanin0(pObj)->Id, Ivy_ObjFanin1(pObj)->Id,
+// pObj->pEquiv? Ivy_Regular(pObj->pEquiv)->Id: -1, Ivy_ObjRefs(pObj) );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Collects AND/EXOR nodes in the DFS order from CIs to COs.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Vec_Int_t * Ivy_ManDfs( Ivy_Man_t * p )
+{
+ Vec_Int_t * vNodes;
+ Ivy_Obj_t * pObj;
+ int i;
+ assert( Ivy_ManLatchNum(p) == 0 );
+ // make sure the nodes are not marked
+ Ivy_ManForEachObj( p, pObj, i )
+ assert( !pObj->fMarkA && !pObj->fMarkB );
+ // collect the nodes
+ vNodes = Vec_IntAlloc( Ivy_ManNodeNum(p) );
+ Ivy_ManForEachPo( p, pObj, i )
+ Ivy_ManDfs_rec( p, Ivy_ObjFanin0(pObj), vNodes );
+ // unmark the collected nodes
+// Ivy_ManForEachNodeVec( p, vNodes, pObj, i )
+// Ivy_ObjClearMarkA(pObj);
+ Ivy_ManForEachObj( p, pObj, i )
+ Ivy_ObjClearMarkA(pObj);
+ // make sure network does not have dangling nodes
+ assert( Vec_IntSize(vNodes) == Ivy_ManNodeNum(p) + Ivy_ManBufNum(p) );
+ return vNodes;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Collects AND/EXOR nodes in the DFS order from CIs to COs.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Vec_Int_t * Ivy_ManDfsSeq( Ivy_Man_t * p, Vec_Int_t ** pvLatches )
+{
+ Vec_Int_t * vNodes, * vLatches;
+ Ivy_Obj_t * pObj;
+ int i;
+// assert( Ivy_ManLatchNum(p) > 0 );
+ // make sure the nodes are not marked
+ Ivy_ManForEachObj( p, pObj, i )
+ assert( !pObj->fMarkA && !pObj->fMarkB );
+ // collect the latches
+ vLatches = Vec_IntAlloc( Ivy_ManLatchNum(p) );
+ Ivy_ManForEachLatch( p, pObj, i )
+ Vec_IntPush( vLatches, pObj->Id );
+ // collect the nodes
+ vNodes = Vec_IntAlloc( Ivy_ManNodeNum(p) );
+ Ivy_ManForEachPo( p, pObj, i )
+ Ivy_ManDfs_rec( p, Ivy_ObjFanin0(pObj), vNodes );
+ Ivy_ManForEachNodeVec( p, vLatches, pObj, i )
+ Ivy_ManDfs_rec( p, Ivy_ObjFanin0(pObj), vNodes );
+ // unmark the collected nodes
+// Ivy_ManForEachNodeVec( p, vNodes, pObj, i )
+// Ivy_ObjClearMarkA(pObj);
+ Ivy_ManForEachObj( p, pObj, i )
+ Ivy_ObjClearMarkA(pObj);
+ // make sure network does not have dangling nodes
+// assert( Vec_IntSize(vNodes) == Ivy_ManNodeNum(p) + Ivy_ManBufNum(p) );
+
+// temporary!!!
+
+ if ( pvLatches == NULL )
+ Vec_IntFree( vLatches );
+ else
+ *pvLatches = vLatches;
+ return vNodes;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Collects nodes in the cone.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Ivy_ManCollectCone_rec( Ivy_Obj_t * pObj, Vec_Ptr_t * vCone )
+{
+ if ( pObj->fMarkA )
+ return;
+ if ( Ivy_ObjIsBuf(pObj) )
+ {
+ Ivy_ManCollectCone_rec( Ivy_ObjFanin0(pObj), vCone );
+ Vec_PtrPush( vCone, pObj );
+ return;
+ }
+ assert( Ivy_ObjIsNode(pObj) );
+ Ivy_ManCollectCone_rec( Ivy_ObjFanin0(pObj), vCone );
+ Ivy_ManCollectCone_rec( Ivy_ObjFanin1(pObj), vCone );
+ Vec_PtrPushUnique( vCone, pObj );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Collects nodes in the cone.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Ivy_ManCollectCone( Ivy_Obj_t * pObj, Vec_Ptr_t * vFront, Vec_Ptr_t * vCone )
+{
+ Ivy_Obj_t * pTemp;
+ int i;
+ assert( !Ivy_IsComplement(pObj) );
+ assert( Ivy_ObjIsNode(pObj) );
+ // mark the nodes
+ Vec_PtrForEachEntry( vFront, pTemp, i )
+ Ivy_Regular(pTemp)->fMarkA = 1;
+ assert( pObj->fMarkA == 0 );
+ // collect the cone
+ Vec_PtrClear( vCone );
+ Ivy_ManCollectCone_rec( pObj, vCone );
+ // unmark the nodes
+ Vec_PtrForEachEntry( vFront, pTemp, i )
+ Ivy_Regular(pTemp)->fMarkA = 0;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Returns the nodes by level.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Vec_Vec_t * Ivy_ManLevelize( Ivy_Man_t * p )
+{
+ Vec_Vec_t * vNodes;
+ Ivy_Obj_t * pObj;
+ int i;
+ vNodes = Vec_VecAlloc( 100 );
+ Ivy_ManForEachObj( p, pObj, i )
+ {
+ assert( !Ivy_ObjIsBuf(pObj) );
+ if ( Ivy_ObjIsNode(pObj) )
+ Vec_VecPush( vNodes, pObj->Level, pObj );
+ }
+ return vNodes;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Computes required levels for each node.]
+
+ Description [Assumes topological ordering of the nodes.]
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Vec_Int_t * Ivy_ManRequiredLevels( Ivy_Man_t * p )
+{
+ Ivy_Obj_t * pObj;
+ Vec_Int_t * vLevelsR;
+ Vec_Vec_t * vNodes;
+ int i, k, Level, LevelMax;
+ assert( p->vRequired == NULL );
+ // start the required times
+ vLevelsR = Vec_IntStart( Ivy_ManObjIdMax(p) + 1 );
+ // iterate through the nodes in the reverse order
+ vNodes = Ivy_ManLevelize( p );
+ Vec_VecForEachEntryReverseReverse( vNodes, pObj, i, k )
+ {
+ Level = Vec_IntEntry( vLevelsR, pObj->Id ) + 1 + Ivy_ObjIsExor(pObj);
+ if ( Vec_IntEntry( vLevelsR, Ivy_ObjFaninId0(pObj) ) < Level )
+ Vec_IntWriteEntry( vLevelsR, Ivy_ObjFaninId0(pObj), Level );
+ if ( Vec_IntEntry( vLevelsR, Ivy_ObjFaninId1(pObj) ) < Level )
+ Vec_IntWriteEntry( vLevelsR, Ivy_ObjFaninId1(pObj), Level );
+ }
+ Vec_VecFree( vNodes );
+ // convert it into the required times
+ LevelMax = Ivy_ManLevels( p );
+//printf( "max %5d\n",LevelMax );
+ Ivy_ManForEachObj( p, pObj, i )
+ {
+ Level = Vec_IntEntry( vLevelsR, pObj->Id );
+ Vec_IntWriteEntry( vLevelsR, pObj->Id, LevelMax - Level );
+//printf( "%5d : %5d %5d\n", pObj->Id, Level, LevelMax - Level );
+ }
+ p->vRequired = vLevelsR;
+ return vLevelsR;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Recursively detects combinational loops.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Ivy_ManIsAcyclic_rec( Ivy_Man_t * p, Ivy_Obj_t * pObj )
+{
+ // skip the node if it is already visited
+ if ( Ivy_ObjIsTravIdPrevious(p, pObj) )
+ return 1;
+ // check if the node is part of the combinational loop
+ if ( Ivy_ObjIsTravIdCurrent(p, pObj) )
+ {
+ fprintf( stdout, "Manager contains combinational loop!\n" );
+ fprintf( stdout, "Node \"%d\" is encountered twice on the following path:\n", Ivy_ObjId(pObj) );
+ fprintf( stdout, " %d", Ivy_ObjId(pObj) );
+ return 0;
+ }
+ // mark this node as a node on the current path
+ Ivy_ObjSetTravIdCurrent( p, pObj );
+ // explore equivalent nodes if pObj is the main node
+ if ( p->pHaig == NULL && pObj->pEquiv && Ivy_ObjRefs(pObj) > 0 )
+ {
+ Ivy_Obj_t * pTemp;
+ assert( !Ivy_IsComplement(pObj->pEquiv) );
+ for ( pTemp = pObj->pEquiv; pTemp != pObj; pTemp = Ivy_Regular(pTemp->pEquiv) )
+ {
+ // traverse the fanin's cone searching for the loop
+ if ( !Ivy_ManIsAcyclic_rec(p, pTemp) )
+ {
+ // return as soon as the loop is detected
+ fprintf( stdout, " -> (%d", Ivy_ObjId(pObj) );
+ for ( pTemp = pObj->pEquiv; pTemp != pObj; pTemp = Ivy_Regular(pTemp->pEquiv) )
+ fprintf( stdout, " %d", Ivy_ObjId(pTemp) );
+ fprintf( stdout, ")" );
+ return 0;
+ }
+ }
+ }
+ // quite if it is a CI node
+ if ( Ivy_ObjIsCi(pObj) || Ivy_ObjIsConst1(pObj) )
+ {
+ // mark this node as a visited node
+ Ivy_ObjSetTravIdPrevious( p, pObj );
+ return 1;
+ }
+ assert( Ivy_ObjIsNode(pObj) || Ivy_ObjIsBuf(pObj) );
+ // traverse the fanin's cone searching for the loop
+ if ( !Ivy_ManIsAcyclic_rec(p, Ivy_ObjFanin0(pObj)) )
+ {
+ // return as soon as the loop is detected
+ fprintf( stdout, " -> %d", Ivy_ObjId(pObj) );
+ return 0;
+ }
+ // traverse the fanin's cone searching for the loop
+ if ( Ivy_ObjIsNode(pObj) && !Ivy_ManIsAcyclic_rec(p, Ivy_ObjFanin1(pObj)) )
+ {
+ // return as soon as the loop is detected
+ fprintf( stdout, " -> %d", Ivy_ObjId(pObj) );
+ return 0;
+ }
+ // mark this node as a visited node
+ Ivy_ObjSetTravIdPrevious( p, pObj );
+ return 1;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Detects combinational loops.]
+
+ Description [This procedure is based on the idea suggested by Donald Chai.
+ As we traverse the network and visit the nodes, we need to distinquish
+ three types of nodes: (1) those that are visited for the first time,
+ (2) those that have been visited in this traversal but are currently not
+ on the traversal path, (3) those that have been visited and are currently
+ on the travesal path. When the node of type (3) is encountered, it means
+ that there is a combinational loop. To mark the three types of nodes,
+ two new values of the traversal IDs are used.]
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Ivy_ManIsAcyclic( Ivy_Man_t * p )
+{
+ Ivy_Obj_t * pObj;
+ int fAcyclic, i;
+ // set the traversal ID for this DFS ordering
+ Ivy_ManIncrementTravId( p );
+ Ivy_ManIncrementTravId( p );
+ // pObj->TravId == pNet->nTravIds means "pObj is on the path"
+ // pObj->TravId == pNet->nTravIds - 1 means "pObj is visited but is not on the path"
+ // pObj->TravId < pNet->nTravIds - 1 means "pObj is not visited"
+ // traverse the network to detect cycles
+ fAcyclic = 1;
+ Ivy_ManForEachCo( p, pObj, i )
+ {
+ // traverse the output logic cone
+ if ( fAcyclic = Ivy_ManIsAcyclic_rec(p, Ivy_ObjFanin0(pObj)) )
+ continue;
+ // stop as soon as the first loop is detected
+ fprintf( stdout, " (cone of %s \"%d\")\n", Ivy_ObjIsLatch(pObj)? "latch" : "PO", Ivy_ObjId(pObj) );
+ break;
+ }
+ return fAcyclic;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Sets the levels of the nodes.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Ivy_ManSetLevels_rec( Ivy_Obj_t * pObj, int fHaig )
+{
+ // quit if the node is visited
+ if ( Ivy_ObjIsMarkA(pObj) )
+ return pObj->Level;
+ Ivy_ObjSetMarkA(pObj);
+ // quit if this is a CI
+ if ( Ivy_ObjIsConst1(pObj) || Ivy_ObjIsCi(pObj) )
+ return 0;
+ assert( Ivy_ObjIsBuf(pObj) || Ivy_ObjIsAnd(pObj) || Ivy_ObjIsExor(pObj) );
+ // get levels of the fanins
+ Ivy_ManSetLevels_rec( Ivy_ObjFanin0(pObj), fHaig );
+ if ( !Ivy_ObjIsBuf(pObj) )
+ Ivy_ManSetLevels_rec( Ivy_ObjFanin1(pObj), fHaig );
+ // get level of the node
+ if ( Ivy_ObjIsBuf(pObj) )
+ pObj->Level = 1 + Ivy_ObjFanin0(pObj)->Level;
+ else if ( Ivy_ObjIsNode(pObj) )
+ pObj->Level = Ivy_ObjLevelNew( pObj );
+ else assert( 0 );
+ // get level of other choices
+ if ( fHaig && pObj->pEquiv && Ivy_ObjRefs(pObj) > 0 )
+ {
+ Ivy_Obj_t * pTemp;
+ unsigned LevelMax = pObj->Level;
+ for ( pTemp = pObj->pEquiv; pTemp != pObj; pTemp = Ivy_Regular(pTemp->pEquiv) )
+ {
+ Ivy_ManSetLevels_rec( pTemp, fHaig );
+ LevelMax = IVY_MAX( LevelMax, pTemp->Level );
+ }
+ // get this level
+ pObj->Level = LevelMax;
+ for ( pTemp = pObj->pEquiv; pTemp != pObj; pTemp = Ivy_Regular(pTemp->pEquiv) )
+ pTemp->Level = LevelMax;
+ }
+ return pObj->Level;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Sets the levels of the nodes.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Ivy_ManSetLevels( Ivy_Man_t * p, int fHaig )
+{
+ Ivy_Obj_t * pObj;
+ int i, LevelMax;
+ // check if CIs have choices
+ if ( fHaig )
+ {
+ Ivy_ManForEachCi( p, pObj, i )
+ if ( pObj->pEquiv )
+ printf( "CI %d has a choice, which will not be visualized.\n", pObj->Id );
+ }
+ // clean the levels
+ Ivy_ManForEachObj( p, pObj, i )
+ pObj->Level = 0;
+ // compute the levels
+ LevelMax = 0;
+ Ivy_ManForEachCo( p, pObj, i )
+ {
+ Ivy_ManSetLevels_rec( Ivy_ObjFanin0(pObj), fHaig );
+ LevelMax = IVY_MAX( LevelMax, (int)Ivy_ObjFanin0(pObj)->Level );
+ }
+ // compute levels of nodes without fanout
+ Ivy_ManForEachObj( p, pObj, i )
+ if ( (Ivy_ObjIsNode(pObj) || Ivy_ObjIsBuf(pObj)) && Ivy_ObjRefs(pObj) == 0 )
+ {
+ Ivy_ManSetLevels_rec( pObj, fHaig );
+ LevelMax = IVY_MAX( LevelMax, (int)pObj->Level );
+ }
+ // clean the marks
+ Ivy_ManForEachObj( p, pObj, i )
+ Ivy_ObjClearMarkA(pObj);
+ return LevelMax;
+}
+
+
+////////////////////////////////////////////////////////////////////////
+/// END OF FILE ///
+////////////////////////////////////////////////////////////////////////
+
+
diff --git a/src/aig/ivy/ivyDsd.c b/src/aig/ivy/ivyDsd.c
new file mode 100644
index 00000000..3b8a2e68
--- /dev/null
+++ b/src/aig/ivy/ivyDsd.c
@@ -0,0 +1,819 @@
+/**CFile****************************************************************
+
+ FileName [ivyDsd.c]
+
+ SystemName [ABC: Logic synthesis and verification system.]
+
+ PackageName [And-Inverter Graph package.]
+
+ Synopsis [Disjoint-support decomposition.]
+
+ Author [Alan Mishchenko]
+
+ Affiliation [UC Berkeley]
+
+ Date [Ver. 1.0. Started - May 11, 2006.]
+
+ Revision [$Id: ivyDsd.c,v 1.00 2006/05/11 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "ivy.h"
+
+////////////////////////////////////////////////////////////////////////
+/// DECLARATIONS ///
+////////////////////////////////////////////////////////////////////////
+
+// decomposition types
+typedef enum {
+ IVY_DEC_PI, // 0: var
+ IVY_DEC_CONST1, // 1: CONST1
+ IVY_DEC_BUF, // 2: BUF
+ IVY_DEC_AND, // 3: AND
+ IVY_DEC_EXOR, // 4: EXOR
+ IVY_DEC_MUX, // 5: MUX
+ IVY_DEC_MAJ, // 6: MAJ
+ IVY_DEC_PRIME // 7: undecomposable
+} Ivy_DecType_t;
+
+typedef struct Ivy_Dec_t_ Ivy_Dec_t;
+struct Ivy_Dec_t_
+{
+ unsigned Type : 4; // the node type (PI, CONST1, AND, EXOR, MUX, PRIME)
+ unsigned fCompl : 1; // shows if node is complemented (root node only)
+ unsigned nFans : 3; // the number of fanins
+ unsigned Fan0 : 4; // fanin 0
+ unsigned Fan1 : 4; // fanin 1
+ unsigned Fan2 : 4; // fanin 2
+ unsigned Fan3 : 4; // fanin 3
+ unsigned Fan4 : 4; // fanin 4
+ unsigned Fan5 : 4; // fanin 5
+};
+
+static inline int Ivy_DecToInt( Ivy_Dec_t Node ) { return *((int *)&Node); }
+static inline Ivy_Dec_t Ivy_IntToDec( int Node ) { return *((Ivy_Dec_t *)&Node); }
+static inline void Ivy_DecClear( Ivy_Dec_t * pNode ) { *((int *)pNode) = 0; }
+
+
+static unsigned s_Masks[6][2] = {
+ { 0x55555555, 0xAAAAAAAA },
+ { 0x33333333, 0xCCCCCCCC },
+ { 0x0F0F0F0F, 0xF0F0F0F0 },
+ { 0x00FF00FF, 0xFF00FF00 },
+ { 0x0000FFFF, 0xFFFF0000 },
+ { 0x00000000, 0xFFFFFFFF }
+};
+
+static inline int Ivy_TruthWordCountOnes( unsigned uWord )
+{
+ uWord = (uWord & 0x55555555) + ((uWord>>1) & 0x55555555);
+ uWord = (uWord & 0x33333333) + ((uWord>>2) & 0x33333333);
+ uWord = (uWord & 0x0F0F0F0F) + ((uWord>>4) & 0x0F0F0F0F);
+ uWord = (uWord & 0x00FF00FF) + ((uWord>>8) & 0x00FF00FF);
+ return (uWord & 0x0000FFFF) + (uWord>>16);
+}
+
+static inline int Ivy_TruthCofactorIsConst( unsigned uTruth, int Var, int Cof, int Const )
+{
+ if ( Const == 0 )
+ return (uTruth & s_Masks[Var][Cof]) == 0;
+ else
+ return (uTruth & s_Masks[Var][Cof]) == s_Masks[Var][Cof];
+}
+
+static inline int Ivy_TruthCofactorIsOne( unsigned uTruth, int Var )
+{
+ return (uTruth & s_Masks[Var][0]) == 0;
+}
+
+static inline unsigned Ivy_TruthCofactor( unsigned uTruth, int Var )
+{
+ unsigned uCofactor = uTruth & s_Masks[Var >> 1][(Var & 1) == 0];
+ int Shift = (1 << (Var >> 1));
+ if ( Var & 1 )
+ return uCofactor | (uCofactor << Shift);
+ return uCofactor | (uCofactor >> Shift);
+}
+
+static inline unsigned Ivy_TruthCofactor2( unsigned uTruth, int Var0, int Var1 )
+{
+ return Ivy_TruthCofactor( Ivy_TruthCofactor(uTruth, Var0), Var1 );
+}
+
+// returns 1 if the truth table depends on this var (var is regular interger var)
+static inline int Ivy_TruthDepends( unsigned uTruth, int Var )
+{
+ return Ivy_TruthCofactor(uTruth, Var << 1) != Ivy_TruthCofactor(uTruth, (Var << 1) | 1);
+}
+
+static inline void Ivy_DecSetVar( Ivy_Dec_t * pNode, int iNum, unsigned Var )
+{
+ assert( iNum >= 0 && iNum <= 5 );
+ switch( iNum )
+ {
+ case 0: pNode->Fan0 = Var; break;
+ case 1: pNode->Fan1 = Var; break;
+ case 2: pNode->Fan2 = Var; break;
+ case 3: pNode->Fan3 = Var; break;
+ case 4: pNode->Fan4 = Var; break;
+ case 5: pNode->Fan5 = Var; break;
+ }
+}
+
+static inline unsigned Ivy_DecGetVar( Ivy_Dec_t * pNode, int iNum )
+{
+ assert( iNum >= 0 && iNum <= 5 );
+ switch( iNum )
+ {
+ case 0: return pNode->Fan0;
+ case 1: return pNode->Fan1;
+ case 2: return pNode->Fan2;
+ case 3: return pNode->Fan3;
+ case 4: return pNode->Fan4;
+ case 5: return pNode->Fan5;
+ }
+ return ~0;
+}
+
+static int Ivy_TruthDecompose_rec( unsigned uTruth, Vec_Int_t * vTree );
+static int Ivy_TruthRecognizeMuxMaj( unsigned uTruth, int * pSupp, int nSupp, Vec_Int_t * vTree );
+
+//int nTruthDsd;
+
+////////////////////////////////////////////////////////////////////////
+/// FUNCTION DEFINITIONS ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+ Synopsis [Computes DSD of truth table of 5 variables or less.]
+
+ Description [Returns 1 if the function is a constant or is fully
+ DSD decomposable using AND/EXOR/MUX gates.]
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Ivy_TruthDsd( unsigned uTruth, Vec_Int_t * vTree )
+{
+ Ivy_Dec_t Node;
+ int i, RetValue;
+ // set the PI variables
+ Vec_IntClear( vTree );
+ for ( i = 0; i < 5; i++ )
+ Vec_IntPush( vTree, 0 );
+ // check if it is a constant
+ if ( uTruth == 0 || ~uTruth == 0 )
+ {
+ Ivy_DecClear( &Node );
+ Node.Type = IVY_DEC_CONST1;
+ Node.fCompl = (uTruth == 0);
+ Vec_IntPush( vTree, Ivy_DecToInt(Node) );
+ return 1;
+ }
+ // perform the decomposition
+ RetValue = Ivy_TruthDecompose_rec( uTruth, vTree );
+ if ( RetValue == -1 )
+ return 0;
+ // get the topmost node
+ if ( (RetValue >> 1) < 5 )
+ { // add buffer
+ Ivy_DecClear( &Node );
+ Node.Type = IVY_DEC_BUF;
+ Node.fCompl = (RetValue & 1);
+ Node.Fan0 = ((RetValue >> 1) << 1);
+ Vec_IntPush( vTree, Ivy_DecToInt(Node) );
+ }
+ else if ( RetValue & 1 )
+ { // check if the topmost node has to be complemented
+ Node = Ivy_IntToDec( Vec_IntPop(vTree) );
+ assert( Node.fCompl == 0 );
+ Node.fCompl = (RetValue & 1);
+ Vec_IntPush( vTree, Ivy_DecToInt(Node) );
+ }
+ if ( uTruth != Ivy_TruthDsdCompute(vTree) )
+ printf( "Verification failed.\n" );
+ return 1;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Computes DSD of truth table.]
+
+ Description [Returns the number of topmost decomposition node.]
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Ivy_TruthDecompose_rec( unsigned uTruth, Vec_Int_t * vTree )
+{
+ Ivy_Dec_t Node;
+ int Supp[5], Vars0[5], Vars1[5], Vars2[5], * pVars;
+ int nSupp, Count0, Count1, Count2, nVars, RetValue, fCompl, i;
+ unsigned uTruthCof, uCof0, uCof1;
+
+ // get constant confactors
+ Count0 = Count1 = Count2 = nSupp = 0;
+ for ( i = 0; i < 5; i++ )
+ {
+ if ( Ivy_TruthCofactorIsConst(uTruth, i, 0, 0) )
+ Vars0[Count0++] = (i << 1) | 0;
+ else if ( Ivy_TruthCofactorIsConst(uTruth, i, 1, 0) )
+ Vars0[Count0++] = (i << 1) | 1;
+ else if ( Ivy_TruthCofactorIsConst(uTruth, i, 0, 1) )
+ Vars1[Count1++] = (i << 1) | 0;
+ else if ( Ivy_TruthCofactorIsConst(uTruth, i, 1, 1) )
+ Vars1[Count1++] = (i << 1) | 1;
+ else
+ {
+ uCof0 = Ivy_TruthCofactor( uTruth, (i << 1) | 1 );
+ uCof1 = Ivy_TruthCofactor( uTruth, (i << 1) | 0 );
+ if ( uCof0 == ~uCof1 )
+ Vars2[Count2++] = (i << 1) | 0;
+ else if ( uCof0 != uCof1 )
+ Supp[nSupp++] = i;
+ }
+ }
+ assert( Count0 == 0 || Count1 == 0 );
+ assert( Count0 == 0 || Count2 == 0 );
+ assert( Count1 == 0 || Count2 == 0 );
+
+ // consider the case of a single variable
+ if ( Count0 == 1 && nSupp == 0 )
+ return Vars0[0];
+
+ // consider more complex decompositions
+ if ( Count0 == 0 && Count1 == 0 && Count2 == 0 )
+ return Ivy_TruthRecognizeMuxMaj( uTruth, Supp, nSupp, vTree );
+
+ // extract the nodes
+ Ivy_DecClear( &Node );
+ if ( Count0 > 0 )
+ nVars = Count0, pVars = Vars0, Node.Type = IVY_DEC_AND, fCompl = 0;
+ else if ( Count1 > 0 )
+ nVars = Count1, pVars = Vars1, Node.Type = IVY_DEC_AND, fCompl = 1, uTruth = ~uTruth;
+ else if ( Count2 > 0 )
+ nVars = Count2, pVars = Vars2, Node.Type = IVY_DEC_EXOR, fCompl = 0;
+ else
+ assert( 0 );
+ Node.nFans = nVars+(nSupp>0);
+
+ // compute cofactor
+ uTruthCof = uTruth;
+ for ( i = 0; i < nVars; i++ )
+ {
+ uTruthCof = Ivy_TruthCofactor( uTruthCof, pVars[i] );
+ Ivy_DecSetVar( &Node, i, pVars[i] );
+ }
+
+ if ( Node.Type == IVY_DEC_EXOR )
+ fCompl ^= ((Node.nFans & 1) == 0);
+
+ if ( nSupp > 0 )
+ {
+ assert( uTruthCof != 0 && ~uTruthCof != 0 );
+ // call recursively
+ RetValue = Ivy_TruthDecompose_rec( uTruthCof, vTree );
+ // quit if non-decomposable
+ if ( RetValue == -1 )
+ return -1;
+ // remove the complement from the child if the node is EXOR
+ if ( Node.Type == IVY_DEC_EXOR && (RetValue & 1) )
+ {
+ fCompl ^= 1;
+ RetValue ^= 1;
+ }
+ // set the new decomposition
+ Ivy_DecSetVar( &Node, nVars, RetValue );
+ }
+ else if ( Node.Type == IVY_DEC_EXOR )
+ fCompl ^= (uTruthCof == 0);
+
+ Vec_IntPush( vTree, Ivy_DecToInt(Node) );
+ return ((Vec_IntSize(vTree)-1) << 1) | fCompl;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Returns a non-negative number if the truth table is a MUX.]
+
+ Description [If the truth table is a MUX, returns the variable as follows:
+ first, control variable; second, positive cofactor; third, negative cofactor.]
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Ivy_TruthRecognizeMuxMaj( unsigned uTruth, int * pSupp, int nSupp, Vec_Int_t * vTree )
+{
+ Ivy_Dec_t Node;
+ int i, k, RetValue0, RetValue1;
+ unsigned uCof0, uCof1, Num;
+ char Count[3];
+ assert( nSupp >= 3 );
+ // start the node
+ Ivy_DecClear( &Node );
+ Node.Type = IVY_DEC_MUX;
+ Node.nFans = 3;
+ // try each of the variables
+ for ( i = 0; i < nSupp; i++ )
+ {
+ // get the cofactors with respect to these variables
+ uCof0 = Ivy_TruthCofactor( uTruth, (pSupp[i] << 1) | 1 );
+ uCof1 = Ivy_TruthCofactor( uTruth, pSupp[i] << 1 );
+ // go through all other variables and make sure
+ // each of them belongs to the support of one cofactor
+ for ( k = 0; k < nSupp; k++ )
+ {
+ if ( k == i )
+ continue;
+ if ( Ivy_TruthDepends(uCof0, pSupp[k]) && Ivy_TruthDepends(uCof1, pSupp[k]) )
+ break;
+ }
+ if ( k < nSupp )
+ continue;
+ // MUX decomposition exists
+ RetValue0 = Ivy_TruthDecompose_rec( uCof0, vTree );
+ if ( RetValue0 == -1 )
+ break;
+ RetValue1 = Ivy_TruthDecompose_rec( uCof1, vTree );
+ if ( RetValue1 == -1 )
+ break;
+ // both of them exist; create the node
+ Ivy_DecSetVar( &Node, 0, pSupp[i] << 1 );
+ Ivy_DecSetVar( &Node, 1, RetValue1 );
+ Ivy_DecSetVar( &Node, 2, RetValue0 );
+ Vec_IntPush( vTree, Ivy_DecToInt(Node) );
+ return ((Vec_IntSize(vTree)-1) << 1) | 0;
+ }
+ // check majority gate
+ if ( nSupp > 3 )
+ return -1;
+ if ( Ivy_TruthWordCountOnes(uTruth) != 16 )
+ return -1;
+ // this is a majority gate; determine polarity
+ Node.Type = IVY_DEC_MAJ;
+ Count[0] = Count[1] = Count[2] = 0;
+ for ( i = 0; i < 8; i++ )
+ {
+ Num = 0;
+ for ( k = 0; k < 3; k++ )
+ if ( i & (1 << k) )
+ Num |= (1 << pSupp[k]);
+ assert( Num < 32 );
+ if ( (uTruth & (1 << Num)) == 0 )
+ continue;
+ for ( k = 0; k < 3; k++ )
+ if ( i & (1 << k) )
+ Count[k]++;
+ }
+ assert( Count[0] == 1 || Count[0] == 3 );
+ assert( Count[1] == 1 || Count[1] == 3 );
+ assert( Count[2] == 1 || Count[2] == 3 );
+ Ivy_DecSetVar( &Node, 0, (pSupp[0] << 1)|(Count[0] == 1) );
+ Ivy_DecSetVar( &Node, 1, (pSupp[1] << 1)|(Count[1] == 1) );
+ Ivy_DecSetVar( &Node, 2, (pSupp[2] << 1)|(Count[2] == 1) );
+ Vec_IntPush( vTree, Ivy_DecToInt(Node) );
+ return ((Vec_IntSize(vTree)-1) << 1) | 0;
+}
+
+
+/**Function*************************************************************
+
+ Synopsis [Computes truth table of decomposition tree for verification.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+unsigned Ivy_TruthDsdCompute_rec( int iNode, Vec_Int_t * vTree )
+{
+ unsigned uTruthChild, uTruthTotal;
+ int Var, i;
+ // get the node
+ Ivy_Dec_t Node = Ivy_IntToDec( Vec_IntEntry(vTree, iNode) );
+ // compute the node function
+ if ( Node.Type == IVY_DEC_CONST1 )
+ return s_Masks[5][ !Node.fCompl ];
+ if ( Node.Type == IVY_DEC_PI )
+ return s_Masks[iNode][ !Node.fCompl ];
+ if ( Node.Type == IVY_DEC_BUF )
+ {
+ uTruthTotal = Ivy_TruthDsdCompute_rec( Node.Fan0 >> 1, vTree );
+ return Node.fCompl? ~uTruthTotal : uTruthTotal;
+ }
+ if ( Node.Type == IVY_DEC_AND )
+ {
+ uTruthTotal = s_Masks[5][1];
+ for ( i = 0; i < (int)Node.nFans; i++ )
+ {
+ Var = Ivy_DecGetVar( &Node, i );
+ uTruthChild = Ivy_TruthDsdCompute_rec( Var >> 1, vTree );
+ uTruthTotal = (Var & 1)? uTruthTotal & ~uTruthChild : uTruthTotal & uTruthChild;
+ }
+ return Node.fCompl? ~uTruthTotal : uTruthTotal;
+ }
+ if ( Node.Type == IVY_DEC_EXOR )
+ {
+ uTruthTotal = 0;
+ for ( i = 0; i < (int)Node.nFans; i++ )
+ {
+ Var = Ivy_DecGetVar( &Node, i );
+ uTruthTotal ^= Ivy_TruthDsdCompute_rec( Var >> 1, vTree );
+ assert( (Var & 1) == 0 );
+ }
+ return Node.fCompl? ~uTruthTotal : uTruthTotal;
+ }
+ assert( Node.fCompl == 0 );
+ if ( Node.Type == IVY_DEC_MUX || Node.Type == IVY_DEC_MAJ )
+ {
+ unsigned uTruthChildC, uTruthChild1, uTruthChild0;
+ int VarC, Var1, Var0;
+ VarC = Ivy_DecGetVar( &Node, 0 );
+ Var1 = Ivy_DecGetVar( &Node, 1 );
+ Var0 = Ivy_DecGetVar( &Node, 2 );
+ uTruthChildC = Ivy_TruthDsdCompute_rec( VarC >> 1, vTree );
+ uTruthChild1 = Ivy_TruthDsdCompute_rec( Var1 >> 1, vTree );
+ uTruthChild0 = Ivy_TruthDsdCompute_rec( Var0 >> 1, vTree );
+ assert( Node.Type == IVY_DEC_MAJ || (VarC & 1) == 0 );
+ uTruthChildC = (VarC & 1)? ~uTruthChildC : uTruthChildC;
+ uTruthChild1 = (Var1 & 1)? ~uTruthChild1 : uTruthChild1;
+ uTruthChild0 = (Var0 & 1)? ~uTruthChild0 : uTruthChild0;
+ if ( Node.Type == IVY_DEC_MUX )
+ return (uTruthChildC & uTruthChild1) | (~uTruthChildC & uTruthChild0);
+ else
+ return (uTruthChildC & uTruthChild1) | (uTruthChildC & uTruthChild0) | (uTruthChild1 & uTruthChild0);
+ }
+ assert( 0 );
+ return 0;
+}
+
+
+/**Function*************************************************************
+
+ Synopsis [Computes truth table of decomposition tree for verification.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+unsigned Ivy_TruthDsdCompute( Vec_Int_t * vTree )
+{
+ return Ivy_TruthDsdCompute_rec( Vec_IntSize(vTree)-1, vTree );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Prints the decomposition tree.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Ivy_TruthDsdPrint_rec( FILE * pFile, int iNode, Vec_Int_t * vTree )
+{
+ int Var, i;
+ // get the node
+ Ivy_Dec_t Node = Ivy_IntToDec( Vec_IntEntry(vTree, iNode) );
+ // compute the node function
+ if ( Node.Type == IVY_DEC_CONST1 )
+ fprintf( pFile, "Const1%s", (Node.fCompl? "\'" : "") );
+ else if ( Node.Type == IVY_DEC_PI )
+ fprintf( pFile, "%c%s", 'a' + iNode, (Node.fCompl? "\'" : "") );
+ else if ( Node.Type == IVY_DEC_BUF )
+ {
+ Ivy_TruthDsdPrint_rec( pFile, Node.Fan0 >> 1, vTree );
+ fprintf( pFile, "%s", (Node.fCompl? "\'" : "") );
+ }
+ else if ( Node.Type == IVY_DEC_AND )
+ {
+ fprintf( pFile, "AND(" );
+ for ( i = 0; i < (int)Node.nFans; i++ )
+ {
+ Var = Ivy_DecGetVar( &Node, i );
+ Ivy_TruthDsdPrint_rec( pFile, Var >> 1, vTree );
+ fprintf( pFile, "%s", (Var & 1)? "\'" : "" );
+ if ( i != (int)Node.nFans-1 )
+ fprintf( pFile, "," );
+ }
+ fprintf( pFile, ")%s", (Node.fCompl? "\'" : "") );
+ }
+ else if ( Node.Type == IVY_DEC_EXOR )
+ {
+ fprintf( pFile, "EXOR(" );
+ for ( i = 0; i < (int)Node.nFans; i++ )
+ {
+ Var = Ivy_DecGetVar( &Node, i );
+ Ivy_TruthDsdPrint_rec( pFile, Var >> 1, vTree );
+ if ( i != (int)Node.nFans-1 )
+ fprintf( pFile, "," );
+ assert( (Var & 1) == 0 );
+ }
+ fprintf( pFile, ")%s", (Node.fCompl? "\'" : "") );
+ }
+ else if ( Node.Type == IVY_DEC_MUX || Node.Type == IVY_DEC_MAJ )
+ {
+ int VarC, Var1, Var0;
+ assert( Node.fCompl == 0 );
+ VarC = Ivy_DecGetVar( &Node, 0 );
+ Var1 = Ivy_DecGetVar( &Node, 1 );
+ Var0 = Ivy_DecGetVar( &Node, 2 );
+ fprintf( pFile, "%s", (Node.Type == IVY_DEC_MUX)? "MUX(" : "MAJ(" );
+ Ivy_TruthDsdPrint_rec( pFile, VarC >> 1, vTree );
+ fprintf( pFile, "%s", (VarC & 1)? "\'" : "" );
+ fprintf( pFile, "," );
+ Ivy_TruthDsdPrint_rec( pFile, Var1 >> 1, vTree );
+ fprintf( pFile, "%s", (Var1 & 1)? "\'" : "" );
+ fprintf( pFile, "," );
+ Ivy_TruthDsdPrint_rec( pFile, Var0 >> 1, vTree );
+ fprintf( pFile, "%s", (Var0 & 1)? "\'" : "" );
+ fprintf( pFile, ")" );
+ }
+ else assert( 0 );
+}
+
+
+/**Function*************************************************************
+
+ Synopsis [Prints the decomposition tree.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Ivy_TruthDsdPrint( FILE * pFile, Vec_Int_t * vTree )
+{
+ fprintf( pFile, "F = " );
+ Ivy_TruthDsdPrint_rec( pFile, Vec_IntSize(vTree)-1, vTree );
+ fprintf( pFile, "\n" );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Implement DSD in the AIG.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Ivy_Obj_t * Ivy_ManDsdConstruct_rec( Ivy_Man_t * p, Vec_Int_t * vFront, int iNode, Vec_Int_t * vTree )
+{
+ Ivy_Obj_t * pResult, * pChild, * pNodes[16];
+ int Var, i;
+ // get the node
+ Ivy_Dec_t Node = Ivy_IntToDec( Vec_IntEntry(vTree, iNode) );
+ // compute the node function
+ if ( Node.Type == IVY_DEC_CONST1 )
+ return Ivy_NotCond( Ivy_ManConst1(p), Node.fCompl );
+ if ( Node.Type == IVY_DEC_PI )
+ {
+ pResult = Ivy_ManObj( p, Vec_IntEntry(vFront, iNode) );
+ return Ivy_NotCond( pResult, Node.fCompl );
+ }
+ if ( Node.Type == IVY_DEC_BUF )
+ {
+ pResult = Ivy_ManDsdConstruct_rec( p, vFront, Node.Fan0 >> 1, vTree );
+ return Ivy_NotCond( pResult, Node.fCompl );
+ }
+ if ( Node.Type == IVY_DEC_AND || Node.Type == IVY_DEC_EXOR )
+ {
+ for ( i = 0; i < (int)Node.nFans; i++ )
+ {
+ Var = Ivy_DecGetVar( &Node, i );
+ assert( Node.Type == IVY_DEC_AND || (Var & 1) == 0 );
+ pChild = Ivy_ManDsdConstruct_rec( p, vFront, Var >> 1, vTree );
+ pChild = Ivy_NotCond( pChild, (Var & 1) );
+ pNodes[i] = pChild;
+ }
+
+// Ivy_MultiEval( pNodes, Node.nFans, Node.Type == IVY_DEC_AND ? IVY_AND : IVY_EXOR );
+
+ pResult = Ivy_Multi( p, pNodes, Node.nFans, Node.Type == IVY_DEC_AND ? IVY_AND : IVY_EXOR );
+ return Ivy_NotCond( pResult, Node.fCompl );
+ }
+ assert( Node.fCompl == 0 );
+ if ( Node.Type == IVY_DEC_MUX || Node.Type == IVY_DEC_MAJ )
+ {
+ int VarC, Var1, Var0;
+ VarC = Ivy_DecGetVar( &Node, 0 );
+ Var1 = Ivy_DecGetVar( &Node, 1 );
+ Var0 = Ivy_DecGetVar( &Node, 2 );
+ pNodes[0] = Ivy_ManDsdConstruct_rec( p, vFront, VarC >> 1, vTree );
+ pNodes[1] = Ivy_ManDsdConstruct_rec( p, vFront, Var1 >> 1, vTree );
+ pNodes[2] = Ivy_ManDsdConstruct_rec( p, vFront, Var0 >> 1, vTree );
+ assert( Node.Type == IVY_DEC_MAJ || (VarC & 1) == 0 );
+ pNodes[0] = Ivy_NotCond( pNodes[0], (VarC & 1) );
+ pNodes[1] = Ivy_NotCond( pNodes[1], (Var1 & 1) );
+ pNodes[2] = Ivy_NotCond( pNodes[2], (Var0 & 1) );
+ if ( Node.Type == IVY_DEC_MUX )
+ return Ivy_Mux( p, pNodes[0], pNodes[1], pNodes[2] );
+ else
+ return Ivy_Maj( p, pNodes[0], pNodes[1], pNodes[2] );
+ }
+ assert( 0 );
+ return 0;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Implement DSD in the AIG.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Ivy_Obj_t * Ivy_ManDsdConstruct( Ivy_Man_t * p, Vec_Int_t * vFront, Vec_Int_t * vTree )
+{
+ int Entry, i;
+ // implement latches on the frontier (TEMPORARY!!!)
+ Vec_IntForEachEntry( vFront, Entry, i )
+ Vec_IntWriteEntry( vFront, i, Ivy_LeafId(Entry) );
+ // recursively construct the tree
+ return Ivy_ManDsdConstruct_rec( p, vFront, Vec_IntSize(vTree)-1, vTree );
+}
+
+
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Ivy_TruthDsdComputePrint( unsigned uTruth )
+{
+ static Vec_Int_t * vTree = NULL;
+ if ( vTree == NULL )
+ vTree = Vec_IntAlloc( 12 );
+ if ( Ivy_TruthDsd( uTruth, vTree ) )
+ Ivy_TruthDsdPrint( stdout, vTree );
+ else
+ printf( "Undecomposable\n" );
+}
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Ivy_TruthTestOne( unsigned uTruth )
+{
+ static int Counter = 0;
+ static Vec_Int_t * vTree = NULL;
+ // decompose
+ if ( vTree == NULL )
+ vTree = Vec_IntAlloc( 12 );
+
+ if ( !Ivy_TruthDsd( uTruth, vTree ) )
+ {
+// printf( "Undecomposable\n" );
+ }
+ else
+ {
+// nTruthDsd++;
+ printf( "%5d : ", Counter++ );
+ Extra_PrintBinary( stdout, &uTruth, 32 );
+ printf( " " );
+ Ivy_TruthDsdPrint( stdout, vTree );
+ if ( uTruth != Ivy_TruthDsdCompute(vTree) )
+ printf( "Verification failed.\n" );
+ }
+// Vec_IntFree( vTree );
+}
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Ivy_TruthTest()
+{
+ FILE * pFile;
+ char Buffer[100];
+ unsigned uTruth;
+ int i;
+
+ pFile = fopen( "npn4.txt", "r" );
+ for ( i = 0; i < 222; i++ )
+// pFile = fopen( "npn5.txt", "r" );
+// for ( i = 0; i < 616126; i++ )
+ {
+ fscanf( pFile, "%s", Buffer );
+ Extra_ReadHexadecimal( &uTruth, Buffer+2, 4 );
+// Extra_ReadHexadecimal( &uTruth, Buffer+2, 5 );
+ uTruth |= (uTruth << 16);
+// uTruth = ~uTruth;
+ Ivy_TruthTestOne( uTruth );
+ }
+ fclose( pFile );
+}
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Ivy_TruthTest3()
+{
+ FILE * pFile;
+ char Buffer[100];
+ unsigned uTruth;
+ int i;
+
+ pFile = fopen( "npn3.txt", "r" );
+ for ( i = 0; i < 14; i++ )
+ {
+ fscanf( pFile, "%s", Buffer );
+ Extra_ReadHexadecimal( &uTruth, Buffer+2, 3 );
+ uTruth = uTruth | (uTruth << 8) | (uTruth << 16) | (uTruth << 24);
+ Ivy_TruthTestOne( uTruth );
+ }
+ fclose( pFile );
+}
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Ivy_TruthTest5()
+{
+ FILE * pFile;
+ char Buffer[100];
+ unsigned uTruth;
+ int i;
+
+// pFile = fopen( "npn4.txt", "r" );
+// for ( i = 0; i < 222; i++ )
+ pFile = fopen( "npn5.txt", "r" );
+ for ( i = 0; i < 616126; i++ )
+ {
+ fscanf( pFile, "%s", Buffer );
+// Extra_ReadHexadecimal( &uTruth, Buffer+2, 4 );
+ Extra_ReadHexadecimal( &uTruth, Buffer+2, 5 );
+// uTruth |= (uTruth << 16);
+// uTruth = ~uTruth;
+ Ivy_TruthTestOne( uTruth );
+ }
+ fclose( pFile );
+}
+
+
+
+////////////////////////////////////////////////////////////////////////
+/// END OF FILE ///
+////////////////////////////////////////////////////////////////////////
+
+
diff --git a/src/aig/ivy/ivyFanout.c b/src/aig/ivy/ivyFanout.c
new file mode 100644
index 00000000..3930186a
--- /dev/null
+++ b/src/aig/ivy/ivyFanout.c
@@ -0,0 +1,309 @@
+/**CFile****************************************************************
+
+ FileName [ivyFanout.c]
+
+ SystemName [ABC: Logic synthesis and verification system.]
+
+ PackageName [And-Inverter Graph package.]
+
+ Synopsis [Representation of the fanouts.]
+
+ Author [Alan Mishchenko]
+
+ Affiliation [UC Berkeley]
+
+ Date [Ver. 1.0. Started - May 11, 2006.]
+
+ Revision [$Id: ivyFanout.c,v 1.00 2006/05/11 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "ivy.h"
+
+////////////////////////////////////////////////////////////////////////
+/// DECLARATIONS ///
+////////////////////////////////////////////////////////////////////////
+
+// getting hold of the next fanout of the node
+static inline Ivy_Obj_t * Ivy_ObjNextFanout( Ivy_Obj_t * pObj, Ivy_Obj_t * pFanout )
+{
+ assert( !Ivy_IsComplement(pObj) );
+ assert( !Ivy_IsComplement(pFanout) );
+ if ( pFanout == NULL )
+ return NULL;
+ if ( Ivy_ObjFanin0(pFanout) == pObj )
+ return pFanout->pNextFan0;
+ assert( Ivy_ObjFanin1(pFanout) == pObj );
+ return pFanout->pNextFan1;
+}
+
+// getting hold of the previous fanout of the node
+static inline Ivy_Obj_t * Ivy_ObjPrevFanout( Ivy_Obj_t * pObj, Ivy_Obj_t * pFanout )
+{
+ assert( !Ivy_IsComplement(pObj) );
+ assert( !Ivy_IsComplement(pFanout) );
+ if ( pFanout == NULL )
+ return NULL;
+ if ( Ivy_ObjFanin0(pFanout) == pObj )
+ return pFanout->pPrevFan0;
+ assert( Ivy_ObjFanin1(pFanout) == pObj );
+ return pFanout->pPrevFan1;
+}
+
+// getting hold of the place where the next fanout will be attached
+static inline Ivy_Obj_t ** Ivy_ObjNextFanoutPlace( Ivy_Obj_t * pObj, Ivy_Obj_t * pFanout )
+{
+ assert( !Ivy_IsComplement(pObj) );
+ assert( !Ivy_IsComplement(pFanout) );
+ if ( Ivy_ObjFanin0(pFanout) == pObj )
+ return &pFanout->pNextFan0;
+ assert( Ivy_ObjFanin1(pFanout) == pObj );
+ return &pFanout->pNextFan1;
+}
+
+// getting hold of the place where the next fanout will be attached
+static inline Ivy_Obj_t ** Ivy_ObjPrevFanoutPlace( Ivy_Obj_t * pObj, Ivy_Obj_t * pFanout )
+{
+ assert( !Ivy_IsComplement(pObj) );
+ assert( !Ivy_IsComplement(pFanout) );
+ if ( Ivy_ObjFanin0(pFanout) == pObj )
+ return &pFanout->pPrevFan0;
+ assert( Ivy_ObjFanin1(pFanout) == pObj );
+ return &pFanout->pPrevFan1;
+}
+
+// getting hold of the place where the next fanout will be attached
+static inline Ivy_Obj_t ** Ivy_ObjPrevNextFanoutPlace( Ivy_Obj_t * pObj, Ivy_Obj_t * pFanout )
+{
+ Ivy_Obj_t * pTemp;
+ assert( !Ivy_IsComplement(pObj) );
+ assert( !Ivy_IsComplement(pFanout) );
+ pTemp = Ivy_ObjPrevFanout(pObj, pFanout);
+ if ( pTemp == NULL )
+ return &pObj->pFanout;
+ if ( Ivy_ObjFanin0(pTemp) == pObj )
+ return &pTemp->pNextFan0;
+ assert( Ivy_ObjFanin1(pTemp) == pObj );
+ return &pTemp->pNextFan1;
+}
+
+// getting hold of the place where the next fanout will be attached
+static inline Ivy_Obj_t ** Ivy_ObjNextPrevFanoutPlace( Ivy_Obj_t * pObj, Ivy_Obj_t * pFanout )
+{
+ Ivy_Obj_t * pTemp;
+ assert( !Ivy_IsComplement(pObj) );
+ assert( !Ivy_IsComplement(pFanout) );
+ pTemp = Ivy_ObjNextFanout(pObj, pFanout);
+ if ( pTemp == NULL )
+ return NULL;
+ if ( Ivy_ObjFanin0(pTemp) == pObj )
+ return &pTemp->pPrevFan0;
+ assert( Ivy_ObjFanin1(pTemp) == pObj );
+ return &pTemp->pPrevFan1;
+}
+
+// iterator through the fanouts of the node
+#define Ivy_ObjForEachFanoutInt( pObj, pFanout ) \
+ for ( pFanout = (pObj)->pFanout; pFanout; \
+ pFanout = Ivy_ObjNextFanout(pObj, pFanout) )
+
+// safe iterator through the fanouts of the node
+#define Ivy_ObjForEachFanoutIntSafe( pObj, pFanout, pFanout2 ) \
+ for ( pFanout = (pObj)->pFanout, \
+ pFanout2 = Ivy_ObjNextFanout(pObj, pFanout); \
+ pFanout; \
+ pFanout = pFanout2, \
+ pFanout2 = Ivy_ObjNextFanout(pObj, pFanout) )
+
+////////////////////////////////////////////////////////////////////////
+/// FUNCTION DEFINITIONS ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+ Synopsis [Starts the fanout representation.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Ivy_ManStartFanout( Ivy_Man_t * p )
+{
+ Ivy_Obj_t * pObj;
+ int i;
+ assert( !p->fFanout );
+ p->fFanout = 1;
+ Ivy_ManForEachObj( p, pObj, i )
+ {
+ if ( Ivy_ObjFanin0(pObj) )
+ Ivy_ObjAddFanout( p, Ivy_ObjFanin0(pObj), pObj );
+ if ( Ivy_ObjFanin1(pObj) )
+ Ivy_ObjAddFanout( p, Ivy_ObjFanin1(pObj), pObj );
+ }
+}
+
+/**Function*************************************************************
+
+ Synopsis [Stops the fanout representation.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Ivy_ManStopFanout( Ivy_Man_t * p )
+{
+ Ivy_Obj_t * pObj;
+ int i;
+ assert( p->fFanout );
+ p->fFanout = 0;
+ Ivy_ManForEachObj( p, pObj, i )
+ pObj->pFanout = pObj->pNextFan0 = pObj->pNextFan1 = pObj->pPrevFan0 = pObj->pPrevFan1 = NULL;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Add the fanout.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Ivy_ObjAddFanout( Ivy_Man_t * p, Ivy_Obj_t * pFanin, Ivy_Obj_t * pFanout )
+{
+ assert( p->fFanout );
+ if ( pFanin->pFanout )
+ {
+ *Ivy_ObjNextFanoutPlace(pFanin, pFanout) = pFanin->pFanout;
+ *Ivy_ObjPrevFanoutPlace(pFanin, pFanin->pFanout) = pFanout;
+ }
+ pFanin->pFanout = pFanout;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Removes the fanout.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Ivy_ObjDeleteFanout( Ivy_Man_t * p, Ivy_Obj_t * pFanin, Ivy_Obj_t * pFanout )
+{
+ Ivy_Obj_t ** ppPlace1, ** ppPlace2, ** ppPlaceN;
+ assert( pFanin->pFanout != NULL );
+
+ ppPlace1 = Ivy_ObjNextFanoutPlace(pFanin, pFanout);
+ ppPlaceN = Ivy_ObjPrevNextFanoutPlace(pFanin, pFanout);
+ assert( *ppPlaceN == pFanout );
+ if ( ppPlaceN )
+ *ppPlaceN = *ppPlace1;
+
+ ppPlace2 = Ivy_ObjPrevFanoutPlace(pFanin, pFanout);
+ ppPlaceN = Ivy_ObjNextPrevFanoutPlace(pFanin, pFanout);
+ assert( ppPlaceN == NULL || *ppPlaceN == pFanout );
+ if ( ppPlaceN )
+ *ppPlaceN = *ppPlace2;
+
+ *ppPlace1 = NULL;
+ *ppPlace2 = NULL;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Replaces the fanout of pOld to be pFanoutNew.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Ivy_ObjPatchFanout( Ivy_Man_t * p, Ivy_Obj_t * pFanin, Ivy_Obj_t * pFanoutOld, Ivy_Obj_t * pFanoutNew )
+{
+ Ivy_Obj_t ** ppPlace;
+ ppPlace = Ivy_ObjPrevNextFanoutPlace(pFanin, pFanoutOld);
+ assert( *ppPlace == pFanoutOld );
+ if ( ppPlace )
+ *ppPlace = pFanoutNew;
+ ppPlace = Ivy_ObjNextPrevFanoutPlace(pFanin, pFanoutOld);
+ assert( ppPlace == NULL || *ppPlace == pFanoutOld );
+ if ( ppPlace )
+ *ppPlace = pFanoutNew;
+ // assuming that pFanoutNew already points to the next fanout
+}
+
+/**Function*************************************************************
+
+ Synopsis [Starts iteration through the fanouts.]
+
+ Description [Copies the currently available fanouts into the array.]
+
+ SideEffects [Can be used while the fanouts are being removed.]
+
+ SeeAlso []
+
+***********************************************************************/
+void Ivy_ObjCollectFanouts( Ivy_Man_t * p, Ivy_Obj_t * pObj, Vec_Ptr_t * vArray )
+{
+ Ivy_Obj_t * pFanout;
+ assert( p->fFanout );
+ assert( !Ivy_IsComplement(pObj) );
+ Vec_PtrClear( vArray );
+ Ivy_ObjForEachFanoutInt( pObj, pFanout )
+ Vec_PtrPush( vArray, pFanout );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Reads one fanout.]
+
+ Description [Returns fanout if there is only one fanout.]
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Ivy_Obj_t * Ivy_ObjReadFirstFanout( Ivy_Man_t * p, Ivy_Obj_t * pObj )
+{
+ return pObj->pFanout;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Reads one fanout.]
+
+ Description [Returns fanout if there is only one fanout.]
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Ivy_ObjFanoutNum( Ivy_Man_t * p, Ivy_Obj_t * pObj )
+{
+ Ivy_Obj_t * pFanout;
+ int Counter = 0;
+ Ivy_ObjForEachFanoutInt( pObj, pFanout )
+ Counter++;
+ return Counter;
+}
+
+////////////////////////////////////////////////////////////////////////
+/// END OF FILE ///
+////////////////////////////////////////////////////////////////////////
+
+
diff --git a/src/aig/ivy/ivyFastMap.c b/src/aig/ivy/ivyFastMap.c
new file mode 100644
index 00000000..c4a043f2
--- /dev/null
+++ b/src/aig/ivy/ivyFastMap.c
@@ -0,0 +1,1593 @@
+/**CFile****************************************************************
+
+ FileName [ivyFastMap.c]
+
+ SystemName [ABC: Logic synthesis and verification system.]
+
+ PackageName [And-Inverter Graph package.]
+
+ Synopsis [Fast FPGA mapping.]
+
+ Author [Alan Mishchenko]
+
+ Affiliation [UC Berkeley]
+
+ Date [Ver. 1.0. Started - May 11, 2006.]
+
+ Revision [$Id: ivyFastMap.c,v 1.00 2006/05/11 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "ivy.h"
+
+////////////////////////////////////////////////////////////////////////
+/// DECLARATIONS ///
+////////////////////////////////////////////////////////////////////////
+
+#define IVY_INFINITY 10000
+
+typedef struct Ivy_SuppMan_t_ Ivy_SuppMan_t;
+struct Ivy_SuppMan_t_
+{
+ int nLimit; // the limit on the number of inputs
+ int nObjs; // the number of entries
+ int nSize; // size of each entry in bytes
+ char * pMem; // memory allocated
+ Vec_Vec_t * vLuts; // the array of nodes used in the mapping
+};
+
+typedef struct Ivy_Supp_t_ Ivy_Supp_t;
+struct Ivy_Supp_t_
+{
+ char nSize; // the number of support nodes
+ char fMark; // multipurpose mask
+ char fMark2; // multipurpose mask
+ char fMark3; // multipurpose mask
+ int nRefs; // the number of references
+ short Delay; // the delay of the node
+ short DelayR; // the reverse delay of the node
+ int pArray[0]; // the support nodes
+};
+
+static inline Ivy_Supp_t * Ivy_ObjSupp( Ivy_Man_t * pAig, Ivy_Obj_t * pObj )
+{
+ return (Ivy_Supp_t *)(((Ivy_SuppMan_t*)pAig->pData)->pMem + pObj->Id * ((Ivy_SuppMan_t*)pAig->pData)->nSize);
+}
+static inline Ivy_Supp_t * Ivy_ObjSuppStart( Ivy_Man_t * pAig, Ivy_Obj_t * pObj )
+{
+ Ivy_Supp_t * pSupp;
+ pSupp = Ivy_ObjSupp( pAig, pObj );
+ pSupp->fMark = 0;
+ pSupp->Delay = 0;
+ pSupp->nSize = 1;
+ pSupp->pArray[0] = pObj->Id;
+ return pSupp;
+}
+
+static void Ivy_FastMapPrint( Ivy_Man_t * pAig, int Delay, int Area, int Time, char * pStr );
+static int Ivy_FastMapDelay( Ivy_Man_t * pAig );
+static int Ivy_FastMapArea( Ivy_Man_t * pAig );
+static void Ivy_FastMapNode( Ivy_Man_t * pAig, Ivy_Obj_t * pObj, int nLimit );
+static void Ivy_FastMapNodeArea( Ivy_Man_t * pAig, Ivy_Obj_t * pObj, int nLimit );
+static int Ivy_FastMapMerge( Ivy_Supp_t * pSupp0, Ivy_Supp_t * pSupp1, Ivy_Supp_t * pSupp, int nLimit );
+static void Ivy_FastMapRequired( Ivy_Man_t * pAig, int Delay, int fSetInter );
+static void Ivy_FastMapRecover( Ivy_Man_t * pAig, int nLimit );
+static int Ivy_FastMapNodeDelay( Ivy_Man_t * pAig, Ivy_Obj_t * pObj );
+static int Ivy_FastMapNodeAreaRefed( Ivy_Man_t * pAig, Ivy_Obj_t * pObj );
+static int Ivy_FastMapNodeAreaDerefed( Ivy_Man_t * pAig, Ivy_Obj_t * pObj );
+static void Ivy_FastMapNodeRecover( Ivy_Man_t * pAig, Ivy_Obj_t * pObj, int nLimit, Vec_Ptr_t * vFront, Vec_Ptr_t * vFrontOld );
+static int Ivy_FastMapNodeRef( Ivy_Man_t * pAig, Ivy_Obj_t * pObj );
+static int Ivy_FastMapNodeDeref( Ivy_Man_t * pAig, Ivy_Obj_t * pObj );
+
+
+extern int s_MappingTime;
+extern int s_MappingMem;
+
+
+////////////////////////////////////////////////////////////////////////
+/// FUNCTION DEFINITIONS ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+ Synopsis [Performs fast K-LUT mapping of the AIG.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Ivy_FastMapPerform( Ivy_Man_t * pAig, int nLimit, int fRecovery, int fVerbose )
+{
+ Ivy_SuppMan_t * pMan;
+ Ivy_Obj_t * pObj;
+ int i, Delay, Area, clk, clkTotal = clock();
+ // start the memory for supports
+ pMan = ALLOC( Ivy_SuppMan_t, 1 );
+ memset( pMan, 0, sizeof(Ivy_SuppMan_t) );
+ pMan->nLimit = nLimit;
+ pMan->nObjs = Ivy_ManObjIdMax(pAig) + 1;
+ pMan->nSize = sizeof(Ivy_Supp_t) + nLimit * sizeof(int);
+ pMan->pMem = (char *)malloc( pMan->nObjs * pMan->nSize );
+ memset( pMan->pMem, 0, pMan->nObjs * pMan->nSize );
+ pMan->vLuts = Vec_VecAlloc( 100 );
+ pAig->pData = pMan;
+clk = clock();
+ // set the PI mapping
+ Ivy_ObjSuppStart( pAig, Ivy_ManConst1(pAig) );
+ Ivy_ManForEachPi( pAig, pObj, i )
+ Ivy_ObjSuppStart( pAig, pObj );
+ // iterate through all nodes in the topological order
+ Ivy_ManForEachNode( pAig, pObj, i )
+ Ivy_FastMapNode( pAig, pObj, nLimit );
+ // find the best arrival time and area
+ Delay = Ivy_FastMapDelay( pAig );
+ Area = Ivy_FastMapArea(pAig);
+ if ( fVerbose )
+ Ivy_FastMapPrint( pAig, Delay, Area, clock() - clk, "Delay oriented mapping: " );
+
+// 2-1-2 (doing 2-1-2-1-2 improves 0.5%)
+
+ if ( fRecovery )
+ {
+clk = clock();
+ Ivy_FastMapRequired( pAig, Delay, 0 );
+ // remap the nodes
+ Ivy_FastMapRecover( pAig, nLimit );
+ Delay = Ivy_FastMapDelay( pAig );
+ Area = Ivy_FastMapArea(pAig);
+ if ( fVerbose )
+ Ivy_FastMapPrint( pAig, Delay, Area, clock() - clk, "Area recovery 2 : " );
+
+clk = clock();
+ Ivy_FastMapRequired( pAig, Delay, 0 );
+ // iterate through all nodes in the topological order
+ Ivy_ManForEachNode( pAig, pObj, i )
+ Ivy_FastMapNodeArea( pAig, pObj, nLimit );
+ Delay = Ivy_FastMapDelay( pAig );
+ Area = Ivy_FastMapArea(pAig);
+ if ( fVerbose )
+ Ivy_FastMapPrint( pAig, Delay, Area, clock() - clk, "Area recovery 1 : " );
+
+clk = clock();
+ Ivy_FastMapRequired( pAig, Delay, 0 );
+ // remap the nodes
+ Ivy_FastMapRecover( pAig, nLimit );
+ Delay = Ivy_FastMapDelay( pAig );
+ Area = Ivy_FastMapArea(pAig);
+ if ( fVerbose )
+ Ivy_FastMapPrint( pAig, Delay, Area, clock() - clk, "Area recovery 2 : " );
+ }
+
+
+ s_MappingTime = clock() - clkTotal;
+ s_MappingMem = pMan->nObjs * pMan->nSize;
+/*
+ {
+ Vec_Ptr_t * vNodes;
+ vNodes = Vec_PtrAlloc( 100 );
+ Vec_VecForEachEntry( pMan->vLuts, pObj, i, k )
+ Vec_PtrPush( vNodes, pObj );
+ Ivy_ManShow( pAig, 0, vNodes );
+ Vec_PtrFree( vNodes );
+ }
+*/
+}
+
+/**Function*************************************************************
+
+ Synopsis [Cleans memory used for decomposition.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Ivy_FastMapStop( Ivy_Man_t * pAig )
+{
+ Ivy_SuppMan_t * p = pAig->pData;
+ Vec_VecFree( p->vLuts );
+ free( p->pMem );
+ free( p );
+ pAig->pData = NULL;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Prints statistics.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Ivy_FastMapPrint( Ivy_Man_t * pAig, int Delay, int Area, int Time, char * pStr )
+{
+ printf( "%s : Delay = %3d. Area = %6d. ", pStr, Delay, Area );
+ PRT( "Time", Time );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Computes delay after LUT mapping.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Ivy_FastMapDelay( Ivy_Man_t * pAig )
+{
+ Ivy_Supp_t * pSupp;
+ Ivy_Obj_t * pObj;
+ int i, DelayMax = 0;
+ Ivy_ManForEachPo( pAig, pObj, i )
+ {
+ pObj = Ivy_ObjFanin0(pObj);
+ if ( !Ivy_ObjIsNode(pObj) )
+ continue;
+ pSupp = Ivy_ObjSupp( pAig, pObj );
+ if ( DelayMax < pSupp->Delay )
+ DelayMax = pSupp->Delay;
+ }
+ return DelayMax;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Computes area after mapping.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Ivy_FastMapArea_rec( Ivy_Man_t * pAig, Ivy_Obj_t * pObj, Vec_Vec_t * vLuts )
+{
+ Ivy_Supp_t * pSupp;
+ int i, Counter;
+ pSupp = Ivy_ObjSupp( pAig, pObj );
+ // skip visited nodes and PIs
+ if ( pSupp->fMark || pSupp->nSize == 1 )
+ return 0;
+ pSupp->fMark = 1;
+ // compute the area of this node
+ Counter = 0;
+ for ( i = 0; i < pSupp->nSize; i++ )
+ Counter += Ivy_FastMapArea_rec( pAig, Ivy_ManObj(pAig, pSupp->pArray[i]), vLuts );
+ // add the node to the array of LUTs
+ Vec_VecPush( vLuts, pSupp->Delay, pObj );
+ return 1 + Counter;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Computes area after mapping.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Ivy_FastMapArea( Ivy_Man_t * pAig )
+{
+ Vec_Vec_t * vLuts;
+ Ivy_Obj_t * pObj;
+ int i, Counter = 0;
+ // get the array to store the nodes
+ vLuts = ((Ivy_SuppMan_t *)pAig->pData)->vLuts;
+ Vec_VecClear( vLuts );
+ // explore starting from each node
+ Ivy_ManForEachPo( pAig, pObj, i )
+ Counter += Ivy_FastMapArea_rec( pAig, Ivy_ObjFanin0(pObj), vLuts );
+ // clean the marks
+ Ivy_ManForEachNode( pAig, pObj, i )
+ Ivy_ObjSupp( pAig, pObj )->fMark = 0;
+ return Counter;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Performs fast mapping for one node.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+static inline Ivy_ObjIsNodeInt1( Ivy_Obj_t * pObj )
+{
+ return Ivy_ObjIsNode(pObj) && Ivy_ObjRefs(pObj) == 1;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Performs fast mapping for one node.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+static inline Ivy_ObjIsNodeInt2( Ivy_Obj_t * pObj )
+{
+ return Ivy_ObjIsNode(pObj) && Ivy_ObjRefs(pObj) <= 2;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Performs fast mapping for one node.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+static inline void Vec_IntSelectSort( int * pArray, int nSize )
+{
+ int temp, i, j, best_i;
+ for ( i = 0; i < nSize-1; i++ )
+ {
+ best_i = i;
+ for ( j = i+1; j < nSize; j++ )
+ if ( pArray[j] < pArray[best_i] )
+ best_i = j;
+ temp = pArray[i];
+ pArray[i] = pArray[best_i];
+ pArray[best_i] = temp;
+ }
+}
+
+/**Function*************************************************************
+
+ Synopsis [Performs fast mapping for one node.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+static inline int Vec_IntRemoveDup( int * pArray, int nSize )
+{
+ int i, k;
+ if ( nSize < 2 )
+ return nSize;
+ for ( i = k = 1; i < nSize; i++ )
+ if ( pArray[i] != pArray[i-1] )
+ pArray[k++] = pArray[i];
+ return k;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Performs fast mapping for one node.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Ivy_FastMapNodeArea2( Ivy_Man_t * pAig, Ivy_Obj_t * pObj, int nLimit )
+{
+ static int Store[32], StoreSize;
+ static char Supp0[16], Supp1[16];
+ static Ivy_Supp_t * pTemp0 = (Ivy_Supp_t *)Supp0;
+ static Ivy_Supp_t * pTemp1 = (Ivy_Supp_t *)Supp1;
+ Ivy_Obj_t * pFanin0, * pFanin1;
+ Ivy_Supp_t * pSupp0, * pSupp1, * pSupp;
+ int RetValue, DelayOld;
+ assert( nLimit <= 32 );
+ assert( Ivy_ObjIsNode(pObj) );
+ // get the fanins
+ pFanin0 = Ivy_ObjFanin0(pObj);
+ pFanin1 = Ivy_ObjFanin1(pObj);
+ // get the supports
+ pSupp0 = Ivy_ObjSupp( pAig, pFanin0 );
+ pSupp1 = Ivy_ObjSupp( pAig, pFanin1 );
+ pSupp = Ivy_ObjSupp( pAig, pObj );
+ assert( pSupp->fMark == 0 );
+ // get the old delay of the node
+ DelayOld = Ivy_FastMapNodeDelay(pAig, pObj);
+ assert( DelayOld <= pSupp->DelayR );
+ // copy the current cut
+ memcpy( Store, pSupp->pArray, sizeof(int) * pSupp->nSize );
+ StoreSize = pSupp->nSize;
+ // get the fanin support
+ if ( Ivy_ObjRefs(pFanin0) > 1 && pSupp0->Delay < pSupp->DelayR )
+ {
+ pSupp0 = pTemp0;
+ pSupp0->nSize = 1;
+ pSupp0->pArray[0] = Ivy_ObjFaninId0(pObj);
+ }
+ // get the fanin support
+ if ( Ivy_ObjRefs(pFanin1) > 1 && pSupp1->Delay < pSupp->DelayR )
+ {
+ pSupp1 = pTemp1;
+ pSupp1->nSize = 1;
+ pSupp1->pArray[0] = Ivy_ObjFaninId1(pObj);
+ }
+ // merge the cuts
+ if ( pSupp0->nSize < pSupp1->nSize )
+ RetValue = Ivy_FastMapMerge( pSupp1, pSupp0, pSupp, nLimit );
+ else
+ RetValue = Ivy_FastMapMerge( pSupp0, pSupp1, pSupp, nLimit );
+ if ( !RetValue )
+ {
+ pSupp->nSize = 2;
+ pSupp->pArray[0] = Ivy_ObjFaninId0(pObj);
+ pSupp->pArray[1] = Ivy_ObjFaninId1(pObj);
+ }
+ // check the resulting delay
+ pSupp->Delay = Ivy_FastMapNodeDelay(pAig, pObj);
+ if ( pSupp->Delay > pSupp->DelayR )
+ {
+ pSupp->nSize = StoreSize;
+ memcpy( pSupp->pArray, Store, sizeof(int) * pSupp->nSize );
+ pSupp->Delay = DelayOld;
+ }
+}
+
+/**Function*************************************************************
+
+ Synopsis [Performs fast mapping for one node.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Ivy_FastMapNodeArea( Ivy_Man_t * pAig, Ivy_Obj_t * pObj, int nLimit )
+{
+ static int Store[32], StoreSize;
+ static char Supp0[16], Supp1[16];
+ static Ivy_Supp_t * pTemp0 = (Ivy_Supp_t *)Supp0;
+ static Ivy_Supp_t * pTemp1 = (Ivy_Supp_t *)Supp1;
+ Ivy_Obj_t * pFanin0, * pFanin1;
+ Ivy_Supp_t * pSupp0, * pSupp1, * pSupp;
+ int RetValue, DelayOld, RefsOld;
+ int AreaBef, AreaAft;
+ assert( nLimit <= 32 );
+ assert( Ivy_ObjIsNode(pObj) );
+ // get the fanins
+ pFanin0 = Ivy_ObjFanin0(pObj);
+ pFanin1 = Ivy_ObjFanin1(pObj);
+ // get the supports
+ pSupp0 = Ivy_ObjSupp( pAig, pFanin0 );
+ pSupp1 = Ivy_ObjSupp( pAig, pFanin1 );
+ pSupp = Ivy_ObjSupp( pAig, pObj );
+ assert( pSupp->fMark == 0 );
+
+ // get the area
+ if ( pSupp->nRefs == 0 )
+ AreaBef = Ivy_FastMapNodeAreaDerefed( pAig, pObj );
+ else
+ AreaBef = Ivy_FastMapNodeAreaRefed( pAig, pObj );
+// if ( AreaBef == 1 )
+// return;
+
+ // deref the cut if the node is refed
+ if ( pSupp->nRefs != 0 )
+ Ivy_FastMapNodeDeref( pAig, pObj );
+
+ // get the old delay of the node
+ DelayOld = Ivy_FastMapNodeDelay(pAig, pObj);
+ assert( DelayOld <= pSupp->DelayR );
+ // copy the current cut
+ memcpy( Store, pSupp->pArray, sizeof(int) * pSupp->nSize );
+ StoreSize = pSupp->nSize;
+ // get the fanin support
+ if ( Ivy_ObjRefs(pFanin0) > 2 && pSupp0->Delay < pSupp->DelayR )
+// if ( pSupp0->nRefs > 0 && pSupp0->Delay < pSupp->DelayR ) // this leads to 2% worse results
+ {
+ pSupp0 = pTemp0;
+ pSupp0->nSize = 1;
+ pSupp0->pArray[0] = Ivy_ObjFaninId0(pObj);
+ }
+ // get the fanin support
+ if ( Ivy_ObjRefs(pFanin1) > 2 && pSupp1->Delay < pSupp->DelayR )
+// if ( pSupp1->nRefs > 0 && pSupp1->Delay < pSupp->DelayR )
+ {
+ pSupp1 = pTemp1;
+ pSupp1->nSize = 1;
+ pSupp1->pArray[0] = Ivy_ObjFaninId1(pObj);
+ }
+ // merge the cuts
+ if ( pSupp0->nSize < pSupp1->nSize )
+ RetValue = Ivy_FastMapMerge( pSupp1, pSupp0, pSupp, nLimit );
+ else
+ RetValue = Ivy_FastMapMerge( pSupp0, pSupp1, pSupp, nLimit );
+ if ( !RetValue )
+ {
+ pSupp->nSize = 2;
+ pSupp->pArray[0] = Ivy_ObjFaninId0(pObj);
+ pSupp->pArray[1] = Ivy_ObjFaninId1(pObj);
+ }
+
+ // check the resulting delay
+ pSupp->Delay = Ivy_FastMapNodeDelay(pAig, pObj);
+
+ RefsOld = pSupp->nRefs; pSupp->nRefs = 0;
+ AreaAft = Ivy_FastMapNodeAreaDerefed( pAig, pObj );
+ pSupp->nRefs = RefsOld;
+
+ if ( AreaAft > AreaBef || pSupp->Delay > pSupp->DelayR )
+// if ( pSupp->Delay > pSupp->DelayR )
+ {
+ pSupp->nSize = StoreSize;
+ memcpy( pSupp->pArray, Store, sizeof(int) * pSupp->nSize );
+ pSupp->Delay = DelayOld;
+// printf( "-" );
+ }
+// else
+// printf( "+" );
+
+ if ( pSupp->nRefs != 0 )
+ Ivy_FastMapNodeRef( pAig, pObj );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Performs fast mapping for one node.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Ivy_FastMapNode( Ivy_Man_t * pAig, Ivy_Obj_t * pObj, int nLimit )
+{
+ Ivy_Supp_t * pSupp0, * pSupp1, * pSupp;
+ int fFaninParam = 2;
+ int RetValue;
+ assert( Ivy_ObjIsNode(pObj) );
+ // get the supports
+ pSupp0 = Ivy_ObjSupp( pAig, Ivy_ObjFanin0(pObj) );
+ pSupp1 = Ivy_ObjSupp( pAig, Ivy_ObjFanin1(pObj) );
+ pSupp = Ivy_ObjSupp( pAig, pObj );
+ pSupp->fMark = 0;
+ // get the delays
+ if ( pSupp0->Delay == pSupp1->Delay )
+ pSupp->Delay = (pSupp0->Delay == 0) ? pSupp0->Delay + 1: pSupp0->Delay;
+ else if ( pSupp0->Delay > pSupp1->Delay )
+ {
+ pSupp->Delay = pSupp0->Delay;
+ pSupp1 = Ivy_ObjSupp( pAig, Ivy_ManConst1(pAig) );
+ pSupp1->pArray[0] = Ivy_ObjFaninId1(pObj);
+ }
+ else // if ( pSupp0->Delay < pSupp1->Delay )
+ {
+ pSupp->Delay = pSupp1->Delay;
+ pSupp0 = Ivy_ObjSupp( pAig, Ivy_ManConst1(pAig) );
+ pSupp0->pArray[0] = Ivy_ObjFaninId0(pObj);
+ }
+ // merge the cuts
+ if ( pSupp0->nSize < pSupp1->nSize )
+ RetValue = Ivy_FastMapMerge( pSupp1, pSupp0, pSupp, nLimit );
+ else
+ RetValue = Ivy_FastMapMerge( pSupp0, pSupp1, pSupp, nLimit );
+ if ( !RetValue )
+ {
+ pSupp->Delay++;
+ if ( fFaninParam == 2 )
+ {
+ pSupp->nSize = 2;
+ pSupp->pArray[0] = Ivy_ObjFaninId0(pObj);
+ pSupp->pArray[1] = Ivy_ObjFaninId1(pObj);
+ }
+ else if ( fFaninParam == 3 )
+ {
+ Ivy_Obj_t * pFanin0, * pFanin1, * pFaninA, * pFaninB;
+ pFanin0 = Ivy_ObjFanin0(pObj);
+ pFanin1 = Ivy_ObjFanin1(pObj);
+ pSupp->nSize = 0;
+ // process the first fanin
+ if ( Ivy_ObjIsNodeInt1(pFanin0) )
+ {
+ pFaninA = Ivy_ObjFanin0(pFanin0);
+ pFaninB = Ivy_ObjFanin1(pFanin0);
+ if ( Ivy_ObjIsNodeInt1(pFaninA) && Ivy_ObjIsNodeInt1(pFaninB) )
+ pSupp->pArray[pSupp->nSize++] = Ivy_ObjId(pFanin0);
+ else
+ {
+ pSupp->pArray[pSupp->nSize++] = Ivy_ObjId(pFaninA);
+ pSupp->pArray[pSupp->nSize++] = Ivy_ObjId(pFaninB);
+ }
+ }
+ else
+ pSupp->pArray[pSupp->nSize++] = Ivy_ObjId(pFanin0);
+ // process the second fanin
+ if ( Ivy_ObjIsNodeInt1(pFanin1) )
+ {
+ pFaninA = Ivy_ObjFanin0(pFanin1);
+ pFaninB = Ivy_ObjFanin1(pFanin1);
+ if ( Ivy_ObjIsNodeInt1(pFaninA) && Ivy_ObjIsNodeInt1(pFaninB) )
+ pSupp->pArray[pSupp->nSize++] = Ivy_ObjId(pFanin1);
+ else
+ {
+ pSupp->pArray[pSupp->nSize++] = Ivy_ObjId(pFaninA);
+ pSupp->pArray[pSupp->nSize++] = Ivy_ObjId(pFaninB);
+ }
+ }
+ else
+ pSupp->pArray[pSupp->nSize++] = Ivy_ObjId(pFanin1);
+ // sort the fanins
+ Vec_IntSelectSort( pSupp->pArray, pSupp->nSize );
+ pSupp->nSize = Vec_IntRemoveDup( pSupp->pArray, pSupp->nSize );
+ assert( pSupp->pArray[0] < pSupp->pArray[1] );
+ }
+ else if ( fFaninParam == 4 )
+ {
+ Ivy_Obj_t * pFanin0, * pFanin1, * pFaninA, * pFaninB;
+ pFanin0 = Ivy_ObjFanin0(pObj);
+ pFanin1 = Ivy_ObjFanin1(pObj);
+ pSupp->nSize = 0;
+ // consider the case when exactly one of them is internal
+ if ( Ivy_ObjIsNodeInt1(pFanin0) ^ Ivy_ObjIsNodeInt1(pFanin1) )
+ {
+ pSupp0 = Ivy_ObjSupp( pAig, Ivy_ObjFanin0(pObj) );
+ pSupp1 = Ivy_ObjSupp( pAig, Ivy_ObjFanin1(pObj) );
+ if ( Ivy_ObjIsNodeInt1(pFanin0) && pSupp0->nSize < nLimit )
+ {
+ pSupp->Delay = IVY_MAX( pSupp0->Delay, pSupp1->Delay + 1 );
+ pSupp1 = Ivy_ObjSupp( pAig, Ivy_ManConst1(pAig) );
+ pSupp1->pArray[0] = Ivy_ObjId(pFanin1);
+ // merge the cuts
+ RetValue = Ivy_FastMapMerge( pSupp0, pSupp1, pSupp, nLimit );
+ assert( RetValue );
+ assert( pSupp->nSize > 1 );
+ return;
+ }
+ if ( Ivy_ObjIsNodeInt1(pFanin1) && pSupp1->nSize < nLimit )
+ {
+ pSupp->Delay = IVY_MAX( pSupp1->Delay, pSupp0->Delay + 1 );
+ pSupp0 = Ivy_ObjSupp( pAig, Ivy_ManConst1(pAig) );
+ pSupp0->pArray[0] = Ivy_ObjId(pFanin0);
+ // merge the cuts
+ RetValue = Ivy_FastMapMerge( pSupp1, pSupp0, pSupp, nLimit );
+ assert( RetValue );
+ assert( pSupp->nSize > 1 );
+ return;
+ }
+ }
+ // process the first fanin
+ if ( Ivy_ObjIsNodeInt1(pFanin0) )
+ {
+ pFaninA = Ivy_ObjFanin0(pFanin0);
+ pFaninB = Ivy_ObjFanin1(pFanin0);
+ if ( Ivy_ObjIsNodeInt1(pFaninA) && Ivy_ObjIsNodeInt1(pFaninB) )
+ pSupp->pArray[pSupp->nSize++] = Ivy_ObjId(pFanin0);
+ else
+ {
+ pSupp->pArray[pSupp->nSize++] = Ivy_ObjId(pFaninA);
+ pSupp->pArray[pSupp->nSize++] = Ivy_ObjId(pFaninB);
+ }
+ }
+ else
+ pSupp->pArray[pSupp->nSize++] = Ivy_ObjId(pFanin0);
+ // process the second fanin
+ if ( Ivy_ObjIsNodeInt1(pFanin1) )
+ {
+ pFaninA = Ivy_ObjFanin0(pFanin1);
+ pFaninB = Ivy_ObjFanin1(pFanin1);
+ if ( Ivy_ObjIsNodeInt1(pFaninA) && Ivy_ObjIsNodeInt1(pFaninB) )
+ pSupp->pArray[pSupp->nSize++] = Ivy_ObjId(pFanin1);
+ else
+ {
+ pSupp->pArray[pSupp->nSize++] = Ivy_ObjId(pFaninA);
+ pSupp->pArray[pSupp->nSize++] = Ivy_ObjId(pFaninB);
+ }
+ }
+ else
+ pSupp->pArray[pSupp->nSize++] = Ivy_ObjId(pFanin1);
+ // sort the fanins
+ Vec_IntSelectSort( pSupp->pArray, pSupp->nSize );
+ pSupp->nSize = Vec_IntRemoveDup( pSupp->pArray, pSupp->nSize );
+ assert( pSupp->pArray[0] < pSupp->pArray[1] );
+ assert( pSupp->nSize > 1 );
+ }
+ }
+ assert( pSupp->Delay > 0 );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Merges two supports]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Ivy_FastMapMerge( Ivy_Supp_t * pSupp0, Ivy_Supp_t * pSupp1, Ivy_Supp_t * pSupp, int nLimit )
+{
+ int i, k, c;
+ assert( pSupp0->nSize >= pSupp1->nSize );
+ // the case of the largest cut sizes
+ if ( pSupp0->nSize == nLimit && pSupp1->nSize == nLimit )
+ {
+ for ( i = 0; i < pSupp0->nSize; i++ )
+ if ( pSupp0->pArray[i] != pSupp1->pArray[i] )
+ return 0;
+ for ( i = 0; i < pSupp0->nSize; i++ )
+ pSupp->pArray[i] = pSupp0->pArray[i];
+ pSupp->nSize = pSupp0->nSize;
+ return 1;
+ }
+ // the case when one of the cuts is the largest
+ if ( pSupp0->nSize == nLimit )
+ {
+ for ( i = 0; i < pSupp1->nSize; i++ )
+ {
+ for ( k = pSupp0->nSize - 1; k >= 0; k-- )
+ if ( pSupp0->pArray[k] == pSupp1->pArray[i] )
+ break;
+ if ( k == -1 ) // did not find
+ return 0;
+ }
+ for ( i = 0; i < pSupp0->nSize; i++ )
+ pSupp->pArray[i] = pSupp0->pArray[i];
+ pSupp->nSize = pSupp0->nSize;
+ return 1;
+ }
+
+ // compare two cuts with different numbers
+ i = k = 0;
+ for ( c = 0; c < nLimit; c++ )
+ {
+ if ( k == pSupp1->nSize )
+ {
+ if ( i == pSupp0->nSize )
+ {
+ pSupp->nSize = c;
+ return 1;
+ }
+ pSupp->pArray[c] = pSupp0->pArray[i++];
+ continue;
+ }
+ if ( i == pSupp0->nSize )
+ {
+ if ( k == pSupp1->nSize )
+ {
+ pSupp->nSize = c;
+ return 1;
+ }
+ pSupp->pArray[c] = pSupp1->pArray[k++];
+ continue;
+ }
+ if ( pSupp0->pArray[i] < pSupp1->pArray[k] )
+ {
+ pSupp->pArray[c] = pSupp0->pArray[i++];
+ continue;
+ }
+ if ( pSupp0->pArray[i] > pSupp1->pArray[k] )
+ {
+ pSupp->pArray[c] = pSupp1->pArray[k++];
+ continue;
+ }
+ pSupp->pArray[c] = pSupp0->pArray[i++];
+ k++;
+ }
+ if ( i < pSupp0->nSize || k < pSupp1->nSize )
+ return 0;
+ pSupp->nSize = c;
+ return 1;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Creates integer vector with the support of the node.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Ivy_FastMapReadSupp( Ivy_Man_t * pAig, Ivy_Obj_t * pObj, Vec_Int_t * vLeaves )
+{
+ Ivy_Supp_t * pSupp;
+ pSupp = Ivy_ObjSupp( pAig, pObj );
+ vLeaves->nCap = 8;
+ vLeaves->nSize = pSupp->nSize;
+ vLeaves->pArray = pSupp->pArray;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Sets the required times of the intermediate nodes.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Ivy_FastMapRequired_rec( Ivy_Man_t * pAig, Ivy_Obj_t * pObj, Ivy_Obj_t * pRoot, int DelayR )
+{
+ Ivy_Supp_t * pSupp;
+ pSupp = Ivy_ObjSupp( pAig, pObj );
+ if ( pObj != pRoot && (pSupp->nRefs > 0 || Ivy_ObjIsCi(pObj)) )
+ return;
+ Ivy_FastMapRequired_rec( pAig, Ivy_ObjFanin0(pObj), pRoot, DelayR );
+ Ivy_FastMapRequired_rec( pAig, Ivy_ObjFanin1(pObj), pRoot, DelayR );
+// assert( pObj == pRoot || pSupp->DelayR == IVY_INFINITY );
+ pSupp->DelayR = DelayR;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Computes the required times for each node.]
+
+ Description [Sets reference counters for each node.]
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Ivy_FastMapRequired( Ivy_Man_t * pAig, int Delay, int fSetInter )
+{
+ Vec_Vec_t * vLuts;
+ Vec_Ptr_t * vNodes;
+ Ivy_Obj_t * pObj;
+ Ivy_Supp_t * pSupp, * pSuppF;
+ int i, k, c;
+ // clean the required times
+ Ivy_ManForEachPi( pAig, pObj, i )
+ {
+ pSupp = Ivy_ObjSupp( pAig, pObj );
+ pSupp->DelayR = IVY_INFINITY;
+ pSupp->nRefs = 0;
+ }
+ Ivy_ManForEachNode( pAig, pObj, i )
+ {
+ pSupp = Ivy_ObjSupp( pAig, pObj );
+ pSupp->DelayR = IVY_INFINITY;
+ pSupp->nRefs = 0;
+ }
+ // set the required times of the POs
+ Ivy_ManForEachPo( pAig, pObj, i )
+ {
+ pSupp = Ivy_ObjSupp( pAig, Ivy_ObjFanin0(pObj) );
+ pSupp->DelayR = Delay;
+ pSupp->nRefs++;
+ }
+ // get the levelized nodes used in the mapping
+ vLuts = ((Ivy_SuppMan_t *)pAig->pData)->vLuts;
+ // propagate the required times
+ Vec_VecForEachLevelReverse( vLuts, vNodes, i )
+ Vec_PtrForEachEntry( vNodes, pObj, k )
+ {
+ pSupp = Ivy_ObjSupp( pAig, pObj );
+ assert( pSupp->nRefs > 0 );
+ for ( c = 0; c < pSupp->nSize; c++ )
+ {
+ pSuppF = Ivy_ObjSupp( pAig, Ivy_ManObj(pAig, pSupp->pArray[c]) );
+ pSuppF->DelayR = IVY_MIN( pSuppF->DelayR, pSupp->DelayR - 1 );
+ pSuppF->nRefs++;
+ }
+ }
+/*
+ // print out some of the required times
+ Ivy_ManForEachPi( pAig, pObj, i )
+ {
+ pSupp = Ivy_ObjSupp( pAig, pObj );
+ printf( "%d ", pSupp->DelayR );
+ }
+ printf( "\n" );
+*/
+
+ if ( fSetInter )
+ {
+ // set the required times of the intermediate nodes
+ Vec_VecForEachLevelReverse( vLuts, vNodes, i )
+ Vec_PtrForEachEntry( vNodes, pObj, k )
+ {
+ pSupp = Ivy_ObjSupp( pAig, pObj );
+ Ivy_FastMapRequired_rec( pAig, pObj, pObj, pSupp->DelayR );
+ }
+ // make sure that all required times are assigned
+ Ivy_ManForEachNode( pAig, pObj, i )
+ {
+ pSupp = Ivy_ObjSupp( pAig, pObj );
+ assert( pSupp->DelayR < IVY_INFINITY );
+ }
+ }
+}
+
+/**Function*************************************************************
+
+ Synopsis [Performs area recovery for each node.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Ivy_FastMapRecover( Ivy_Man_t * pAig, int nLimit )
+{
+ Vec_Ptr_t * vFront, * vFrontOld;
+ Ivy_Obj_t * pObj;
+ int i;
+ vFront = Vec_PtrAlloc( nLimit );
+ vFrontOld = Vec_PtrAlloc( nLimit );
+ Ivy_ManCleanTravId( pAig );
+ // iterate through all nodes in the topological order
+ Ivy_ManForEachNode( pAig, pObj, i )
+ Ivy_FastMapNodeRecover( pAig, pObj, nLimit, vFront, vFrontOld );
+ Vec_PtrFree( vFrontOld );
+ Vec_PtrFree( vFront );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Computes the delay of the cut rooted at this node.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Ivy_FastMapNodeDelay( Ivy_Man_t * pAig, Ivy_Obj_t * pObj )
+{
+ Ivy_Supp_t * pSupp, * pSuppF;
+ int c, Delay = 0;
+ pSupp = Ivy_ObjSupp( pAig, pObj );
+ for ( c = 0; c < pSupp->nSize; c++ )
+ {
+ pSuppF = Ivy_ObjSupp( pAig, Ivy_ManObj(pAig, pSupp->pArray[c]) );
+ Delay = IVY_MAX( Delay, pSuppF->Delay );
+ }
+ return 1 + Delay;
+}
+
+
+/**function*************************************************************
+
+ synopsis [References the cut.]
+
+ description [This procedure is similar to the procedure NodeReclaim.]
+
+ sideeffects []
+
+ seealso []
+
+***********************************************************************/
+int Ivy_FastMapNodeRef( Ivy_Man_t * pAig, Ivy_Obj_t * pObj )
+{
+ Ivy_Supp_t * pSupp, * pSuppF;
+ Ivy_Obj_t * pNodeChild;
+ int aArea, i;
+ // start the area of this cut
+ aArea = 1;
+ // go through the children
+ pSupp = Ivy_ObjSupp( pAig, pObj );
+ assert( pSupp->nSize > 1 );
+ for ( i = 0; i < pSupp->nSize; i++ )
+ {
+ pNodeChild = Ivy_ManObj(pAig, pSupp->pArray[i]);
+ pSuppF = Ivy_ObjSupp( pAig, pNodeChild );
+ assert( pSuppF->nRefs >= 0 );
+ if ( pSuppF->nRefs++ > 0 )
+ continue;
+ if ( pSuppF->nSize == 1 )
+ continue;
+ aArea += Ivy_FastMapNodeRef( pAig, pNodeChild );
+ }
+ return aArea;
+}
+
+/**function*************************************************************
+
+ synopsis [Dereferences the cut.]
+
+ description [This procedure is similar to the procedure NodeRecusiveDeref.]
+
+ sideeffects []
+
+ seealso []
+
+***********************************************************************/
+int Ivy_FastMapNodeDeref( Ivy_Man_t * pAig, Ivy_Obj_t * pObj )
+{
+ Ivy_Supp_t * pSupp, * pSuppF;
+ Ivy_Obj_t * pNodeChild;
+ int aArea, i;
+ // start the area of this cut
+ aArea = 1;
+ // go through the children
+ pSupp = Ivy_ObjSupp( pAig, pObj );
+ assert( pSupp->nSize > 1 );
+ for ( i = 0; i < pSupp->nSize; i++ )
+ {
+ pNodeChild = Ivy_ManObj(pAig, pSupp->pArray[i]);
+ pSuppF = Ivy_ObjSupp( pAig, pNodeChild );
+ assert( pSuppF->nRefs > 0 );
+ if ( --pSuppF->nRefs > 0 )
+ continue;
+ if ( pSuppF->nSize == 1 )
+ continue;
+ aArea += Ivy_FastMapNodeDeref( pAig, pNodeChild );
+ }
+ return aArea;
+}
+
+/**function*************************************************************
+
+ synopsis [Computes the exact area associated with the cut.]
+
+ description []
+
+ sideeffects []
+
+ seealso []
+
+***********************************************************************/
+int Ivy_FastMapNodeAreaRefed( Ivy_Man_t * pAig, Ivy_Obj_t * pObj )
+{
+ Ivy_Supp_t * pSupp;
+ int aResult, aResult2;
+ if ( Ivy_ObjIsCi(pObj) )
+ return 0;
+ assert( Ivy_ObjIsNode(pObj) );
+ pSupp = Ivy_ObjSupp( pAig, pObj );
+ assert( pSupp->nRefs > 0 );
+ aResult = Ivy_FastMapNodeDeref( pAig, pObj );
+ aResult2 = Ivy_FastMapNodeRef( pAig, pObj );
+ assert( aResult == aResult2 );
+ return aResult;
+}
+
+/**function*************************************************************
+
+ synopsis [Computes the exact area associated with the cut.]
+
+ description []
+
+ sideeffects []
+
+ seealso []
+
+***********************************************************************/
+int Ivy_FastMapNodeAreaDerefed( Ivy_Man_t * pAig, Ivy_Obj_t * pObj )
+{
+ Ivy_Supp_t * pSupp;
+ int aResult, aResult2;
+ if ( Ivy_ObjIsCi(pObj) )
+ return 0;
+ assert( Ivy_ObjIsNode(pObj) );
+ pSupp = Ivy_ObjSupp( pAig, pObj );
+ assert( pSupp->nRefs == 0 );
+ aResult2 = Ivy_FastMapNodeRef( pAig, pObj );
+ aResult = Ivy_FastMapNodeDeref( pAig, pObj );
+ assert( aResult == aResult2 );
+ return aResult;
+}
+
+
+
+
+/**Function*************************************************************
+
+ Synopsis [Counts the number of nodes with no external fanout.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Ivy_FastMapCutCost( Ivy_Man_t * pAig, Vec_Ptr_t * vFront )
+{
+ Ivy_Supp_t * pSuppF;
+ Ivy_Obj_t * pFanin;
+ int i, Counter = 0;
+ Vec_PtrForEachEntry( vFront, pFanin, i )
+ {
+ pSuppF = Ivy_ObjSupp( pAig, pFanin );
+ if ( pSuppF->nRefs == 0 )
+ Counter++;
+ }
+ return Counter;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Performs area recovery for each node.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Ivy_FastMapMark_rec( Ivy_Man_t * pAig, Ivy_Obj_t * pObj )
+{
+ if ( Ivy_ObjIsTravIdCurrent(pAig, pObj) )
+ return;
+ assert( Ivy_ObjIsNode(pObj) );
+ Ivy_FastMapMark_rec( pAig, Ivy_ObjFanin0(pObj) );
+ Ivy_FastMapMark_rec( pAig, Ivy_ObjFanin1(pObj) );
+ Ivy_ObjSetTravIdCurrent(pAig, pObj);
+}
+
+/**Function*************************************************************
+
+ Synopsis [Returns 1 if the number of fanins will grow.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Ivy_FastMapNodeWillGrow( Ivy_Man_t * pAig, Ivy_Obj_t * pObj )
+{
+ Ivy_Obj_t * pFanin0, * pFanin1;
+ assert( Ivy_ObjIsNode(pObj) );
+ pFanin0 = Ivy_ObjFanin0(pObj);
+ pFanin1 = Ivy_ObjFanin1(pObj);
+ return !Ivy_ObjIsTravIdCurrent(pAig, pFanin0) && !Ivy_ObjIsTravIdCurrent(pAig, pFanin1);
+}
+
+/**Function*************************************************************
+
+ Synopsis [Returns the increase in the number of fanins with no external refs.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Ivy_FastMapNodeFaninCost( Ivy_Man_t * pAig, Ivy_Obj_t * pObj )
+{
+ Ivy_Supp_t * pSuppF;
+ Ivy_Obj_t * pFanin;
+ int Counter = 0;
+ assert( Ivy_ObjIsNode(pObj) );
+ // check if the node has external refs
+ pSuppF = Ivy_ObjSupp( pAig, pObj );
+ if ( pSuppF->nRefs == 0 )
+ Counter--;
+ // increment the number of fanins without external refs
+ pFanin = Ivy_ObjFanin0(pObj);
+ pSuppF = Ivy_ObjSupp( pAig, pFanin );
+ if ( !Ivy_ObjIsTravIdCurrent(pAig, pFanin) && pSuppF->nRefs == 0 )
+ Counter++;
+ // increment the number of fanins without external refs
+ pFanin = Ivy_ObjFanin1(pObj);
+ pSuppF = Ivy_ObjSupp( pAig, pFanin );
+ if ( !Ivy_ObjIsTravIdCurrent(pAig, pFanin) && pSuppF->nRefs == 0 )
+ Counter++;
+ return Counter;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Updates the frontier.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Ivy_FastMapNodeFaninUpdate( Ivy_Man_t * pAig, Ivy_Obj_t * pObj, Vec_Ptr_t * vFront )
+{
+ Ivy_Obj_t * pFanin;
+ assert( Ivy_ObjIsNode(pObj) );
+ Vec_PtrRemove( vFront, pObj );
+ pFanin = Ivy_ObjFanin0(pObj);
+ if ( !Ivy_ObjIsTravIdCurrent(pAig, pFanin) )
+ {
+ Ivy_ObjSetTravIdCurrent(pAig, pFanin);
+ Vec_PtrPush( vFront, pFanin );
+ }
+ pFanin = Ivy_ObjFanin1(pObj);
+ if ( !Ivy_ObjIsTravIdCurrent(pAig, pFanin) )
+ {
+ Ivy_ObjSetTravIdCurrent(pAig, pFanin);
+ Vec_PtrPush( vFront, pFanin );
+ }
+}
+
+/**Function*************************************************************
+
+ Synopsis [Compacts the number of external refs.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Ivy_FastMapNodeFaninCompact0( Ivy_Man_t * pAig, Ivy_Obj_t * pObj, int nLimit, Vec_Ptr_t * vFront )
+{
+ Ivy_Obj_t * pFanin;
+ int i;
+ Vec_PtrForEachEntry( vFront, pFanin, i )
+ {
+ if ( Ivy_ObjIsCi(pFanin) )
+ continue;
+ if ( Ivy_FastMapNodeWillGrow(pAig, pFanin) )
+ continue;
+ if ( Ivy_FastMapNodeFaninCost(pAig, pFanin) <= 0 )
+ {
+ Ivy_FastMapNodeFaninUpdate( pAig, pFanin, vFront );
+ return 1;
+ }
+ }
+ return 0;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Compacts the number of external refs.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Ivy_FastMapNodeFaninCompact1( Ivy_Man_t * pAig, Ivy_Obj_t * pObj, int nLimit, Vec_Ptr_t * vFront )
+{
+ Ivy_Obj_t * pFanin;
+ int i;
+ Vec_PtrForEachEntry( vFront, pFanin, i )
+ {
+ if ( Ivy_ObjIsCi(pFanin) )
+ continue;
+ if ( Ivy_FastMapNodeFaninCost(pAig, pFanin) < 0 )
+ {
+ Ivy_FastMapNodeFaninUpdate( pAig, pFanin, vFront );
+ return 1;
+ }
+ }
+ return 0;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Compacts the number of external refs.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Ivy_FastMapNodeFaninCompact2( Ivy_Man_t * pAig, Ivy_Obj_t * pObj, int nLimit, Vec_Ptr_t * vFront )
+{
+ Ivy_Obj_t * pFanin;
+ int i;
+ Vec_PtrForEachEntry( vFront, pFanin, i )
+ {
+ if ( Ivy_ObjIsCi(pFanin) )
+ continue;
+ if ( Ivy_FastMapNodeFaninCost(pAig, pFanin) <= 0 )
+ {
+ Ivy_FastMapNodeFaninUpdate( pAig, pFanin, vFront );
+ return 1;
+ }
+ }
+ return 0;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Compacts the number of external refs.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Ivy_FastMapNodeFaninCompact_int( Ivy_Man_t * pAig, Ivy_Obj_t * pObj, int nLimit, Vec_Ptr_t * vFront )
+{
+ if ( Ivy_FastMapNodeFaninCompact0(pAig, pObj, nLimit, vFront) )
+ return 1;
+ if ( Vec_PtrSize(vFront) < nLimit && Ivy_FastMapNodeFaninCompact1(pAig, pObj, nLimit, vFront) )
+ return 1;
+ if ( Vec_PtrSize(vFront) < nLimit && Ivy_FastMapNodeFaninCompact2(pAig, pObj, nLimit, vFront) )
+ return 1;
+ assert( Vec_PtrSize(vFront) <= nLimit );
+ return 0;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Compacts the number of external refs.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Ivy_FastMapNodeFaninCompact( Ivy_Man_t * pAig, Ivy_Obj_t * pObj, int nLimit, Vec_Ptr_t * vFront )
+{
+ while ( Ivy_FastMapNodeFaninCompact_int( pAig, pObj, nLimit, vFront ) );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Prepares node mapping.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Ivy_FastMapNodePrepare( Ivy_Man_t * pAig, Ivy_Obj_t * pObj, int nLimit, Vec_Ptr_t * vFront, Vec_Ptr_t * vFrontOld )
+{
+ Ivy_Supp_t * pSupp;
+ Ivy_Obj_t * pFanin;
+ int i;
+ pSupp = Ivy_ObjSupp( pAig, pObj );
+ // expand the cut downwards from the given place
+ Vec_PtrClear( vFront );
+ Vec_PtrClear( vFrontOld );
+ Ivy_ManIncrementTravId( pAig );
+ for ( i = 0; i < pSupp->nSize; i++ )
+ {
+ pFanin = Ivy_ManObj(pAig, pSupp->pArray[i]);
+ Vec_PtrPush( vFront, pFanin );
+ Vec_PtrPush( vFrontOld, pFanin );
+ Ivy_ObjSetTravIdCurrent( pAig, pFanin );
+ }
+ // mark the nodes in the cone
+ Ivy_FastMapMark_rec( pAig, pObj );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Updates the frontier.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Ivy_FastMapNodeUpdate( Ivy_Man_t * pAig, Ivy_Obj_t * pObj, Vec_Ptr_t * vFront )
+{
+ Ivy_Supp_t * pSupp;
+ Ivy_Obj_t * pFanin;
+ int i;
+ pSupp = Ivy_ObjSupp( pAig, pObj );
+ // deref node's cut
+ Ivy_FastMapNodeDeref( pAig, pObj );
+ // update the node's cut
+ pSupp->nSize = Vec_PtrSize(vFront);
+ Vec_PtrForEachEntry( vFront, pFanin, i )
+ pSupp->pArray[i] = pFanin->Id;
+ // ref the new cut
+ Ivy_FastMapNodeRef( pAig, pObj );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Performs area recovery for each node.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Ivy_FastMapNodeRecover2( Ivy_Man_t * pAig, Ivy_Obj_t * pObj, int nLimit, Vec_Ptr_t * vFront, Vec_Ptr_t * vFrontOld )
+{
+ Ivy_Supp_t * pSupp;
+ int CostBef, CostAft;
+ int AreaBef, AreaAft;
+ pSupp = Ivy_ObjSupp( pAig, pObj );
+// if ( pSupp->nRefs == 0 )
+// return;
+ if ( pSupp->nRefs == 0 )
+ AreaBef = Ivy_FastMapNodeAreaDerefed( pAig, pObj );
+ else
+ AreaBef = Ivy_FastMapNodeAreaRefed( pAig, pObj );
+ // get the area
+ if ( AreaBef == 1 )
+ return;
+
+ if ( pSupp->nRefs == 0 )
+ {
+ pSupp->nRefs = 1000000;
+ Ivy_FastMapNodeRef( pAig, pObj );
+ }
+ // the cut is non-trivial
+ Ivy_FastMapNodePrepare( pAig, pObj, nLimit, vFront, vFrontOld );
+ // iteratively modify the cut
+ CostBef = Ivy_FastMapCutCost( pAig, vFront );
+ Ivy_FastMapNodeFaninCompact( pAig, pObj, nLimit, vFront );
+ CostAft = Ivy_FastMapCutCost( pAig, vFront );
+ assert( CostBef >= CostAft );
+ // update the node
+ Ivy_FastMapNodeUpdate( pAig, pObj, vFront );
+ // get the new area
+ AreaAft = Ivy_FastMapNodeAreaRefed( pAig, pObj );
+ if ( AreaAft > AreaBef )
+ {
+ Ivy_FastMapNodeUpdate( pAig, pObj, vFrontOld );
+ AreaAft = Ivy_FastMapNodeAreaRefed( pAig, pObj );
+ assert( AreaAft == AreaBef );
+ }
+ if ( pSupp->nRefs == 1000000 )
+ {
+ pSupp->nRefs = 0;
+ Ivy_FastMapNodeDeref( pAig, pObj );
+ }
+}
+
+/**Function*************************************************************
+
+ Synopsis [Performs area recovery for each node.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Ivy_FastMapNodeRecover( Ivy_Man_t * pAig, Ivy_Obj_t * pObj, int nLimit, Vec_Ptr_t * vFront, Vec_Ptr_t * vFrontOld )
+{
+ Ivy_Supp_t * pSupp;
+ int CostBef, CostAft;
+ int AreaBef, AreaAft;
+ int DelayOld;
+ pSupp = Ivy_ObjSupp( pAig, pObj );
+ DelayOld = pSupp->Delay = Ivy_FastMapNodeDelay( pAig, pObj );
+ assert( pSupp->Delay <= pSupp->DelayR );
+ if ( pSupp->nRefs == 0 )
+ return;
+ // get the area
+ AreaBef = Ivy_FastMapNodeAreaRefed( pAig, pObj );
+// if ( AreaBef == 1 )
+// return;
+ if ( pObj->Id == 102 )
+ {
+ int x = 0;
+ }
+ // the cut is non-trivial
+ Ivy_FastMapNodePrepare( pAig, pObj, nLimit, vFront, vFrontOld );
+ // iteratively modify the cut
+ Ivy_FastMapNodeDeref( pAig, pObj );
+ CostBef = Ivy_FastMapCutCost( pAig, vFront );
+ Ivy_FastMapNodeFaninCompact( pAig, pObj, nLimit, vFront );
+ CostAft = Ivy_FastMapCutCost( pAig, vFront );
+ Ivy_FastMapNodeRef( pAig, pObj );
+ assert( CostBef >= CostAft );
+ // update the node
+ Ivy_FastMapNodeUpdate( pAig, pObj, vFront );
+ pSupp->Delay = Ivy_FastMapNodeDelay( pAig, pObj );
+ // get the new area
+ AreaAft = Ivy_FastMapNodeAreaRefed( pAig, pObj );
+ if ( AreaAft > AreaBef || pSupp->Delay > pSupp->DelayR )
+ {
+ Ivy_FastMapNodeUpdate( pAig, pObj, vFrontOld );
+ AreaAft = Ivy_FastMapNodeAreaRefed( pAig, pObj );
+ assert( AreaAft == AreaBef );
+ pSupp->Delay = DelayOld;
+ }
+}
+
+/**Function*************************************************************
+
+ Synopsis [Performs area recovery for each node.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Ivy_FastMapNodeRecover4( Ivy_Man_t * pAig, Ivy_Obj_t * pObj, int nLimit, Vec_Ptr_t * vFront, Vec_Ptr_t * vFrontOld )
+{
+ Ivy_Supp_t * pSupp;
+ int CostBef, CostAft;
+ int AreaBef, AreaAft;
+ int DelayOld;
+ pSupp = Ivy_ObjSupp( pAig, pObj );
+ DelayOld = pSupp->Delay = Ivy_FastMapNodeDelay( pAig, pObj );
+ assert( pSupp->Delay <= pSupp->DelayR );
+// if ( pSupp->nRefs == 0 )
+// return;
+// AreaBef = Ivy_FastMapNodeAreaRefed( pAig, pObj );
+ // get the area
+ if ( pSupp->nRefs == 0 )
+ AreaBef = Ivy_FastMapNodeAreaDerefed( pAig, pObj );
+ else
+ AreaBef = Ivy_FastMapNodeAreaRefed( pAig, pObj );
+ if ( AreaBef == 1 )
+ return;
+
+ if ( pSupp->nRefs == 0 )
+ {
+ pSupp->nRefs = 1000000;
+ Ivy_FastMapNodeRef( pAig, pObj );
+ }
+ // the cut is non-trivial
+ Ivy_FastMapNodePrepare( pAig, pObj, nLimit, vFront, vFrontOld );
+ // iteratively modify the cut
+ CostBef = Ivy_FastMapCutCost( pAig, vFront );
+ Ivy_FastMapNodeFaninCompact( pAig, pObj, nLimit, vFront );
+ CostAft = Ivy_FastMapCutCost( pAig, vFront );
+ assert( CostBef >= CostAft );
+ // update the node
+ Ivy_FastMapNodeUpdate( pAig, pObj, vFront );
+ pSupp->Delay = Ivy_FastMapNodeDelay( pAig, pObj );
+ // get the new area
+ AreaAft = Ivy_FastMapNodeAreaRefed( pAig, pObj );
+ if ( AreaAft > AreaBef || pSupp->Delay > pSupp->DelayR )
+ {
+ Ivy_FastMapNodeUpdate( pAig, pObj, vFrontOld );
+ AreaAft = Ivy_FastMapNodeAreaRefed( pAig, pObj );
+ assert( AreaAft == AreaBef );
+ pSupp->Delay = DelayOld;
+ }
+ if ( pSupp->nRefs == 1000000 )
+ {
+ pSupp->nRefs = 0;
+ Ivy_FastMapNodeDeref( pAig, pObj );
+ }
+}
+
+////////////////////////////////////////////////////////////////////////
+/// END OF FILE ///
+////////////////////////////////////////////////////////////////////////
+
+
diff --git a/src/aig/ivy/ivyFraig.c b/src/aig/ivy/ivyFraig.c
new file mode 100644
index 00000000..4079b6ed
--- /dev/null
+++ b/src/aig/ivy/ivyFraig.c
@@ -0,0 +1,2760 @@
+/**CFile****************************************************************
+
+ FileName [ivyFraig.c]
+
+ SystemName [ABC: Logic synthesis and verification system.]
+
+ PackageName [And-Inverter Graph package.]
+
+ Synopsis [Functional reduction of AIGs]
+
+ Author [Alan Mishchenko]
+
+ Affiliation [UC Berkeley]
+
+ Date [Ver. 1.0. Started - May 11, 2006.]
+
+ Revision [$Id: ivyFraig.c,v 1.00 2006/05/11 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "satSolver.h"
+#include "extra.h"
+#include "ivy.h"
+
+////////////////////////////////////////////////////////////////////////
+/// DECLARATIONS ///
+////////////////////////////////////////////////////////////////////////
+
+typedef struct Ivy_FraigMan_t_ Ivy_FraigMan_t;
+typedef struct Ivy_FraigSim_t_ Ivy_FraigSim_t;
+typedef struct Ivy_FraigList_t_ Ivy_FraigList_t;
+
+struct Ivy_FraigList_t_
+{
+ Ivy_Obj_t * pHead;
+ Ivy_Obj_t * pTail;
+ int nItems;
+};
+
+struct Ivy_FraigSim_t_
+{
+ int Type;
+ Ivy_FraigSim_t * pNext;
+ Ivy_FraigSim_t * pFanin0;
+ Ivy_FraigSim_t * pFanin1;
+ unsigned pData[0];
+};
+
+struct Ivy_FraigMan_t_
+{
+ // general info
+ Ivy_FraigParams_t * pParams; // various parameters
+ // temporary backtrack limits because "sint64" cannot be defined in Ivy_FraigParams_t ...
+ sint64 nBTLimitGlobal; // global limit on the number of backtracks
+ sint64 nInsLimitGlobal;// global limit on the number of clause inspects
+ // AIG manager
+ Ivy_Man_t * pManAig; // the starting AIG manager
+ Ivy_Man_t * pManFraig; // the final AIG manager
+ // simulation information
+ int nSimWords; // the number of words
+ char * pSimWords; // the simulation info
+ Ivy_FraigSim_t * pSimStart; // the list of simulation info for internal nodes
+ // counter example storage
+ int nPatWords; // the number of words in the counter example
+ unsigned * pPatWords; // the counter example
+ int * pPatScores; // the scores of each pattern
+ // equivalence classes
+ Ivy_FraigList_t lClasses; // equivalence classes
+ Ivy_FraigList_t lCand; // candidatates
+ int nPairs; // the number of pairs of nodes
+ // equivalence checking
+ sat_solver * pSat; // SAT solver
+ int nSatVars; // the number of variables currently used
+ Vec_Ptr_t * vPiVars; // the PIs of the cone used
+ // other
+ ProgressBar * pProgress;
+ // statistics
+ int nSimRounds;
+ int nNodesMiter;
+ int nClassesZero;
+ int nClassesBeg;
+ int nClassesEnd;
+ int nPairsBeg;
+ int nPairsEnd;
+ int nSatCalls;
+ int nSatCallsSat;
+ int nSatCallsUnsat;
+ int nSatProof;
+ int nSatFails;
+ int nSatFailsReal;
+ // runtime
+ int timeSim;
+ int timeTrav;
+ int timeSat;
+ int timeSatUnsat;
+ int timeSatSat;
+ int timeSatFail;
+ int timeRef;
+ int timeTotal;
+ int time1;
+ int time2;
+};
+
+typedef struct Prove_ParamsStruct_t_ Prove_Params_t;
+struct Prove_ParamsStruct_t_
+{
+ // general parameters
+ int fUseFraiging; // enables fraiging
+ int fUseRewriting; // enables rewriting
+ int fUseBdds; // enables BDD construction when other methods fail
+ int fVerbose; // prints verbose stats
+ // iterations
+ int nItersMax; // the number of iterations
+ // mitering
+ int nMiteringLimitStart; // starting mitering limit
+ float nMiteringLimitMulti; // multiplicative coefficient to increase the limit in each iteration
+ // rewriting
+ int nRewritingLimitStart; // the number of rewriting iterations
+ float nRewritingLimitMulti; // multiplicative coefficient to increase the limit in each iteration
+ // fraiging
+ int nFraigingLimitStart; // starting backtrack(conflict) limit
+ float nFraigingLimitMulti; // multiplicative coefficient to increase the limit in each iteration
+ // last-gasp BDD construction
+ int nBddSizeLimit; // the number of BDD nodes when construction is aborted
+ int fBddReorder; // enables dynamic BDD variable reordering
+ // last-gasp mitering
+ int nMiteringLimitLast; // final mitering limit
+ // global SAT solver limits
+ sint64 nTotalBacktrackLimit; // global limit on the number of backtracks
+ sint64 nTotalInspectLimit; // global limit on the number of clause inspects
+ // global resources applied
+ sint64 nTotalBacktracksMade; // the total number of backtracks made
+ sint64 nTotalInspectsMade; // the total number of inspects made
+};
+
+static inline Ivy_FraigSim_t * Ivy_ObjSim( Ivy_Obj_t * pObj ) { return (Ivy_FraigSim_t *)pObj->pFanout; }
+static inline Ivy_Obj_t * Ivy_ObjClassNodeLast( Ivy_Obj_t * pObj ) { return pObj->pNextFan0; }
+static inline Ivy_Obj_t * Ivy_ObjClassNodeRepr( Ivy_Obj_t * pObj ) { return pObj->pNextFan0; }
+static inline Ivy_Obj_t * Ivy_ObjClassNodeNext( Ivy_Obj_t * pObj ) { return pObj->pNextFan1; }
+static inline Ivy_Obj_t * Ivy_ObjNodeHashNext( Ivy_Obj_t * pObj ) { return pObj->pPrevFan0; }
+static inline Ivy_Obj_t * Ivy_ObjEquivListNext( Ivy_Obj_t * pObj ) { return pObj->pPrevFan0; }
+static inline Ivy_Obj_t * Ivy_ObjEquivListPrev( Ivy_Obj_t * pObj ) { return pObj->pPrevFan1; }
+static inline Ivy_Obj_t * Ivy_ObjFraig( Ivy_Obj_t * pObj ) { return pObj->pEquiv; }
+static inline int Ivy_ObjSatNum( Ivy_Obj_t * pObj ) { return (int)pObj->pNextFan0; }
+static inline Vec_Ptr_t * Ivy_ObjFaninVec( Ivy_Obj_t * pObj ) { return (Vec_Ptr_t *)pObj->pNextFan1; }
+
+static inline void Ivy_ObjSetSim( Ivy_Obj_t * pObj, Ivy_FraigSim_t * pSim ) { pObj->pFanout = (Ivy_Obj_t *)pSim; }
+static inline void Ivy_ObjSetClassNodeLast( Ivy_Obj_t * pObj, Ivy_Obj_t * pLast ) { pObj->pNextFan0 = pLast; }
+static inline void Ivy_ObjSetClassNodeRepr( Ivy_Obj_t * pObj, Ivy_Obj_t * pRepr ) { pObj->pNextFan0 = pRepr; }
+static inline void Ivy_ObjSetClassNodeNext( Ivy_Obj_t * pObj, Ivy_Obj_t * pNext ) { pObj->pNextFan1 = pNext; }
+static inline void Ivy_ObjSetNodeHashNext( Ivy_Obj_t * pObj, Ivy_Obj_t * pNext ) { pObj->pPrevFan0 = pNext; }
+static inline void Ivy_ObjSetEquivListNext( Ivy_Obj_t * pObj, Ivy_Obj_t * pNext ) { pObj->pPrevFan0 = pNext; }
+static inline void Ivy_ObjSetEquivListPrev( Ivy_Obj_t * pObj, Ivy_Obj_t * pPrev ) { pObj->pPrevFan1 = pPrev; }
+static inline void Ivy_ObjSetFraig( Ivy_Obj_t * pObj, Ivy_Obj_t * pNode ) { pObj->pEquiv = pNode; }
+static inline void Ivy_ObjSetSatNum( Ivy_Obj_t * pObj, int Num ) { pObj->pNextFan0 = (Ivy_Obj_t *)Num; }
+static inline void Ivy_ObjSetFaninVec( Ivy_Obj_t * pObj, Vec_Ptr_t * vFanins ) { pObj->pNextFan1 = (Ivy_Obj_t *)vFanins; }
+
+static inline unsigned Ivy_ObjRandomSim() { return (rand() << 24) ^ (rand() << 12) ^ rand(); }
+
+// iterate through equivalence classes
+#define Ivy_FraigForEachEquivClass( pList, pEnt ) \
+ for ( pEnt = pList; \
+ pEnt; \
+ pEnt = Ivy_ObjEquivListNext(pEnt) )
+#define Ivy_FraigForEachEquivClassSafe( pList, pEnt, pEnt2 ) \
+ for ( pEnt = pList, \
+ pEnt2 = pEnt? Ivy_ObjEquivListNext(pEnt): NULL; \
+ pEnt; \
+ pEnt = pEnt2, \
+ pEnt2 = pEnt? Ivy_ObjEquivListNext(pEnt): NULL )
+// iterate through nodes in one class
+#define Ivy_FraigForEachClassNode( pClass, pEnt ) \
+ for ( pEnt = pClass; \
+ pEnt; \
+ pEnt = Ivy_ObjClassNodeNext(pEnt) )
+// iterate through nodes in the hash table
+#define Ivy_FraigForEachBinNode( pBin, pEnt ) \
+ for ( pEnt = pBin; \
+ pEnt; \
+ pEnt = Ivy_ObjNodeHashNext(pEnt) )
+
+static Ivy_FraigMan_t * Ivy_FraigStart( Ivy_Man_t * pManAig, Ivy_FraigParams_t * pParams );
+static Ivy_FraigMan_t * Ivy_FraigStartSimple( Ivy_Man_t * pManAig, Ivy_FraigParams_t * pParams );
+static Ivy_Man_t * Ivy_FraigPerform_int( Ivy_Man_t * pManAig, Ivy_FraigParams_t * pParams, sint64 nBTLimitGlobal, sint64 nInsLimitGlobal, sint64 * pnSatConfs, sint64 * pnSatInspects );
+static void Ivy_FraigPrint( Ivy_FraigMan_t * p );
+static void Ivy_FraigStop( Ivy_FraigMan_t * p );
+static void Ivy_FraigSimulate( Ivy_FraigMan_t * p );
+static void Ivy_FraigSweep( Ivy_FraigMan_t * p );
+static Ivy_Obj_t * Ivy_FraigAnd( Ivy_FraigMan_t * p, Ivy_Obj_t * pObjOld );
+static int Ivy_FraigNodesAreEquiv( Ivy_FraigMan_t * p, Ivy_Obj_t * pObj0, Ivy_Obj_t * pObj1 );
+static int Ivy_FraigNodeIsConst( Ivy_FraigMan_t * p, Ivy_Obj_t * pObj );
+static void Ivy_FraigNodeAddToSolver( Ivy_FraigMan_t * p, Ivy_Obj_t * pObj0, Ivy_Obj_t * pObj1 );
+static int Ivy_FraigSetActivityFactors( Ivy_FraigMan_t * p, Ivy_Obj_t * pOld, Ivy_Obj_t * pNew );
+static void Ivy_FraigAddToPatScores( Ivy_FraigMan_t * p, Ivy_Obj_t * pClass, Ivy_Obj_t * pClassNew );
+static int Ivy_FraigMiterStatus( Ivy_Man_t * pMan );
+static void Ivy_FraigMiterProve( Ivy_FraigMan_t * p );
+static void Ivy_FraigMiterPrint( Ivy_Man_t * pNtk, char * pString, int clk, int fVerbose );
+static int * Ivy_FraigCreateModel( Ivy_FraigMan_t * p );
+
+static int Ivy_FraigNodesAreEquivBdd( Ivy_Obj_t * pObj1, Ivy_Obj_t * pObj2 );
+
+static sint64 s_nBTLimitGlobal = 0;
+static sint64 s_nInsLimitGlobal = 0;
+
+////////////////////////////////////////////////////////////////////////
+/// FUNCTION DEFINITIONS ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+ Synopsis [Sets the default solving parameters.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Ivy_FraigParamsDefault( Ivy_FraigParams_t * pParams )
+{
+ memset( pParams, 0, sizeof(Ivy_FraigParams_t) );
+ pParams->nSimWords = 32; // the number of words in the simulation info
+ pParams->dSimSatur = 0.005; // the ratio of refined classes when saturation is reached
+ pParams->fPatScores = 0; // enables simulation pattern scoring
+ pParams->MaxScore = 25; // max score after which resimulation is used
+ pParams->fDoSparse = 1; // skips sparse functions
+// pParams->dActConeRatio = 0.05; // the ratio of cone to be bumped
+// pParams->dActConeBumpMax = 5.0; // the largest bump of activity
+ pParams->dActConeRatio = 0.3; // the ratio of cone to be bumped
+ pParams->dActConeBumpMax = 10.0; // the largest bump of activity
+
+ pParams->nBTLimitNode = 100; // conflict limit at a node
+ pParams->nBTLimitMiter = 500000; // conflict limit at an output
+// pParams->nBTLimitGlobal = 0; // conflict limit global
+// pParams->nInsLimitGlobal = 0; // inspection limit global
+}
+
+/**Function*************************************************************
+
+ Synopsis [Performs combinational equivalence checking for the miter.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Ivy_FraigProve( Ivy_Man_t ** ppManAig, void * pPars )
+{
+ Prove_Params_t * pParams = pPars;
+ Ivy_FraigParams_t Params, * pIvyParams = &Params;
+ Ivy_Man_t * pManAig, * pManTemp;
+ int RetValue, nIter, clk, timeStart = clock();//, Counter;
+ sint64 nSatConfs, nSatInspects;
+
+ // start the network and parameters
+ pManAig = *ppManAig;
+ Ivy_FraigParamsDefault( pIvyParams );
+ pIvyParams->fVerbose = pParams->fVerbose;
+ pIvyParams->fProve = 1;
+
+ if ( pParams->fVerbose )
+ {
+ printf( "RESOURCE LIMITS: Iterations = %d. Rewriting = %s. Fraiging = %s.\n",
+ pParams->nItersMax, pParams->fUseRewriting? "yes":"no", pParams->fUseFraiging? "yes":"no" );
+ printf( "Miter = %d (%3.1f). Rwr = %d (%3.1f). Fraig = %d (%3.1f). Last = %d.\n",
+ pParams->nMiteringLimitStart, pParams->nMiteringLimitMulti,
+ pParams->nRewritingLimitStart, pParams->nRewritingLimitMulti,
+ pParams->nFraigingLimitStart, pParams->nFraigingLimitMulti, pParams->nMiteringLimitLast );
+ }
+
+ // if SAT only, solve without iteration
+ if ( !pParams->fUseRewriting && !pParams->fUseFraiging )
+ {
+ clk = clock();
+ pIvyParams->nBTLimitMiter = pParams->nMiteringLimitLast / Ivy_ManPoNum(pManAig);
+ pManAig = Ivy_FraigMiter( pManTemp = pManAig, pIvyParams ); Ivy_ManStop( pManTemp );
+ RetValue = Ivy_FraigMiterStatus( pManAig );
+ Ivy_FraigMiterPrint( pManAig, "SAT solving", clk, pParams->fVerbose );
+ *ppManAig = pManAig;
+ return RetValue;
+ }
+
+ if ( Ivy_ManNodeNum(pManAig) < 500 )
+ {
+ // run the first mitering
+ clk = clock();
+ pIvyParams->nBTLimitMiter = pParams->nMiteringLimitStart / Ivy_ManPoNum(pManAig);
+ pManAig = Ivy_FraigMiter( pManTemp = pManAig, pIvyParams ); Ivy_ManStop( pManTemp );
+ RetValue = Ivy_FraigMiterStatus( pManAig );
+ Ivy_FraigMiterPrint( pManAig, "SAT solving", clk, pParams->fVerbose );
+ if ( RetValue >= 0 )
+ {
+ *ppManAig = pManAig;
+ return RetValue;
+ }
+ }
+
+ // check the current resource limits
+ RetValue = -1;
+ for ( nIter = 0; nIter < pParams->nItersMax; nIter++ )
+ {
+ if ( pParams->fVerbose )
+ {
+ printf( "ITERATION %2d : Confs = %6d. FraigBTL = %3d. \n", nIter+1,
+ (int)(pParams->nMiteringLimitStart * pow(pParams->nMiteringLimitMulti,nIter)),
+ (int)(pParams->nFraigingLimitStart * pow(pParams->nFraigingLimitMulti,nIter)) );
+ fflush( stdout );
+ }
+
+ // try rewriting
+ if ( pParams->fUseRewriting )
+ { // bug in Ivy_NodeFindCutsAll() when leaves are identical!
+/*
+ clk = clock();
+ Counter = (int)(pParams->nRewritingLimitStart * pow(pParams->nRewritingLimitMulti,nIter));
+ pManAig = Ivy_ManRwsat( pManAig, 0 );
+ RetValue = Ivy_FraigMiterStatus( pManAig );
+ Ivy_FraigMiterPrint( pManAig, "Rewriting ", clk, pParams->fVerbose );
+*/
+ }
+ if ( RetValue >= 0 )
+ break;
+
+ // try fraiging followed by mitering
+ if ( pParams->fUseFraiging )
+ {
+ clk = clock();
+ pIvyParams->nBTLimitNode = (int)(pParams->nFraigingLimitStart * pow(pParams->nFraigingLimitMulti,nIter));
+ pIvyParams->nBTLimitMiter = (int)(pParams->nMiteringLimitStart * pow(pParams->nMiteringLimitMulti,nIter)) / Ivy_ManPoNum(pManAig);
+ pManAig = Ivy_FraigPerform_int( pManTemp = pManAig, pIvyParams, pParams->nTotalBacktrackLimit, pParams->nTotalInspectLimit, &nSatConfs, &nSatInspects ); Ivy_ManStop( pManTemp );
+ RetValue = Ivy_FraigMiterStatus( pManAig );
+ Ivy_FraigMiterPrint( pManAig, "Fraiging ", clk, pParams->fVerbose );
+ }
+ if ( RetValue >= 0 )
+ break;
+
+ // add to the number of backtracks and inspects
+ pParams->nTotalBacktracksMade += nSatConfs;
+ pParams->nTotalInspectsMade += nSatInspects;
+ // check if global resource limit is reached
+ if ( (pParams->nTotalBacktrackLimit && pParams->nTotalBacktracksMade >= pParams->nTotalBacktrackLimit) ||
+ (pParams->nTotalInspectLimit && pParams->nTotalInspectsMade >= pParams->nTotalInspectLimit) )
+ {
+ printf( "Reached global limit on conflicts/inspects. Quitting.\n" );
+ *ppManAig = pManAig;
+ return -1;
+ }
+ }
+
+ if ( RetValue < 0 )
+ {
+ if ( pParams->fVerbose )
+ {
+ printf( "Attempting SAT with conflict limit %d ...\n", pParams->nMiteringLimitLast );
+ fflush( stdout );
+ }
+ clk = clock();
+ pIvyParams->nBTLimitMiter = pParams->nMiteringLimitLast / Ivy_ManPoNum(pManAig);
+ if ( pParams->nTotalBacktrackLimit )
+ s_nBTLimitGlobal = pParams->nTotalBacktrackLimit - pParams->nTotalBacktracksMade;
+ if ( pParams->nTotalInspectLimit )
+ s_nInsLimitGlobal = pParams->nTotalInspectLimit - pParams->nTotalInspectsMade;
+ pManAig = Ivy_FraigMiter( pManTemp = pManAig, pIvyParams ); Ivy_ManStop( pManTemp );
+ s_nBTLimitGlobal = 0;
+ s_nInsLimitGlobal = 0;
+ RetValue = Ivy_FraigMiterStatus( pManAig );
+ Ivy_FraigMiterPrint( pManAig, "SAT solving", clk, pParams->fVerbose );
+ // make sure that the sover never returns "undecided" when infinite resource limits are set
+ if( RetValue == -1 && pParams->nTotalInspectLimit == 0 &&
+ pParams->nTotalBacktrackLimit == 0 )
+ {
+ extern void Prove_ParamsPrint( Prove_Params_t * pParams );
+ Prove_ParamsPrint( pParams );
+ printf("ERROR: ABC has returned \"undecided\" in spite of no limits...\n");
+ exit(1);
+ }
+ }
+
+ // assign the model if it was proved by rewriting (const 1 miter)
+ if ( RetValue == 0 && pManAig->pData == NULL )
+ {
+ pManAig->pData = ALLOC( int, Ivy_ManPiNum(pManAig) );
+ memset( pManAig->pData, 0, sizeof(int) * Ivy_ManPiNum(pManAig) );
+ }
+ *ppManAig = pManAig;
+ return RetValue;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Performs fraiging of the AIG.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Ivy_Man_t * Ivy_FraigPerform_int( Ivy_Man_t * pManAig, Ivy_FraigParams_t * pParams, sint64 nBTLimitGlobal, sint64 nInsLimitGlobal, sint64 * pnSatConfs, sint64 * pnSatInspects )
+{
+ Ivy_FraigMan_t * p;
+ Ivy_Man_t * pManAigNew;
+ int clk;
+ if ( Ivy_ManNodeNum(pManAig) == 0 )
+ return Ivy_ManDup(pManAig);
+clk = clock();
+ assert( Ivy_ManLatchNum(pManAig) == 0 );
+ p = Ivy_FraigStart( pManAig, pParams );
+ // set global limits
+ p->nBTLimitGlobal = nBTLimitGlobal;
+ p->nInsLimitGlobal = nInsLimitGlobal;
+
+ Ivy_FraigSimulate( p );
+ Ivy_FraigSweep( p );
+ pManAigNew = p->pManFraig;
+p->timeTotal = clock() - clk;
+ if ( pnSatConfs )
+ *pnSatConfs = p->pSat? p->pSat->stats.conflicts : 0;
+ if ( pnSatInspects )
+ *pnSatInspects = p->pSat? p->pSat->stats.inspects : 0;
+ Ivy_FraigStop( p );
+ return pManAigNew;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Performs fraiging of the AIG.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Ivy_Man_t * Ivy_FraigPerform( Ivy_Man_t * pManAig, Ivy_FraigParams_t * pParams )
+{
+ Ivy_FraigMan_t * p;
+ Ivy_Man_t * pManAigNew;
+ int clk;
+ if ( Ivy_ManNodeNum(pManAig) == 0 )
+ return Ivy_ManDup(pManAig);
+clk = clock();
+ assert( Ivy_ManLatchNum(pManAig) == 0 );
+ p = Ivy_FraigStart( pManAig, pParams );
+ Ivy_FraigSimulate( p );
+ Ivy_FraigSweep( p );
+ pManAigNew = p->pManFraig;
+p->timeTotal = clock() - clk;
+ Ivy_FraigStop( p );
+ return pManAigNew;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Applies brute-force SAT to the miter.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Ivy_Man_t * Ivy_FraigMiter( Ivy_Man_t * pManAig, Ivy_FraigParams_t * pParams )
+{
+ Ivy_FraigMan_t * p;
+ Ivy_Man_t * pManAigNew;
+ Ivy_Obj_t * pObj;
+ int i, clk;
+clk = clock();
+ assert( Ivy_ManLatchNum(pManAig) == 0 );
+ p = Ivy_FraigStartSimple( pManAig, pParams );
+ // set global limits
+ p->nBTLimitGlobal = s_nBTLimitGlobal;
+ p->nInsLimitGlobal = s_nInsLimitGlobal;
+ // duplicate internal nodes
+ Ivy_ManForEachNode( p->pManAig, pObj, i )
+ pObj->pEquiv = Ivy_And( p->pManFraig, Ivy_ObjChild0Equiv(pObj), Ivy_ObjChild1Equiv(pObj) );
+ // try to prove each output of the miter
+ Ivy_FraigMiterProve( p );
+ // add the POs
+ Ivy_ManForEachPo( p->pManAig, pObj, i )
+ Ivy_ObjCreatePo( p->pManFraig, Ivy_ObjChild0Equiv(pObj) );
+ // clean the new manager
+ Ivy_ManForEachObj( p->pManFraig, pObj, i )
+ {
+ if ( Ivy_ObjFaninVec(pObj) )
+ Vec_PtrFree( Ivy_ObjFaninVec(pObj) );
+ pObj->pNextFan0 = pObj->pNextFan1 = NULL;
+ }
+ // remove dangling nodes
+ Ivy_ManCleanup( p->pManFraig );
+ pManAigNew = p->pManFraig;
+p->timeTotal = clock() - clk;
+
+//printf( "Final nodes = %6d. ", Ivy_ManNodeNum(pManAigNew) );
+//PRT( "Time", p->timeTotal );
+ Ivy_FraigStop( p );
+ return pManAigNew;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Starts the fraiging manager without simulation info.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Ivy_FraigMan_t * Ivy_FraigStartSimple( Ivy_Man_t * pManAig, Ivy_FraigParams_t * pParams )
+{
+ Ivy_FraigMan_t * p;
+ // allocat the fraiging manager
+ p = ALLOC( Ivy_FraigMan_t, 1 );
+ memset( p, 0, sizeof(Ivy_FraigMan_t) );
+ p->pParams = pParams;
+ p->pManAig = pManAig;
+ p->pManFraig = Ivy_ManStartFrom( pManAig );
+ p->vPiVars = Vec_PtrAlloc( 100 );
+ return p;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Starts the fraiging manager.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Ivy_FraigMan_t * Ivy_FraigStart( Ivy_Man_t * pManAig, Ivy_FraigParams_t * pParams )
+{
+ Ivy_FraigMan_t * p;
+ Ivy_FraigSim_t * pSims;
+ Ivy_Obj_t * pObj;
+ int i, k, EntrySize;
+ // clean the fanout representation
+ Ivy_ManForEachObj( pManAig, pObj, i )
+// pObj->pEquiv = pObj->pFanout = pObj->pNextFan0 = pObj->pNextFan1 = pObj->pPrevFan0 = pObj->pPrevFan1 = NULL;
+ assert( !pObj->pEquiv && !pObj->pFanout );
+ // allocat the fraiging manager
+ p = ALLOC( Ivy_FraigMan_t, 1 );
+ memset( p, 0, sizeof(Ivy_FraigMan_t) );
+ p->pParams = pParams;
+ p->pManAig = pManAig;
+ p->pManFraig = Ivy_ManStartFrom( pManAig );
+ // allocate simulation info
+ p->nSimWords = pParams->nSimWords;
+// p->pSimWords = ALLOC( unsigned, Ivy_ManObjNum(pManAig) * p->nSimWords );
+ EntrySize = sizeof(Ivy_FraigSim_t) + sizeof(unsigned) * p->nSimWords;
+ p->pSimWords = (char *)malloc( Ivy_ManObjNum(pManAig) * EntrySize );
+ memset( p->pSimWords, 0, EntrySize );
+ k = 0;
+ Ivy_ManForEachObj( pManAig, pObj, i )
+ {
+ pSims = (Ivy_FraigSim_t *)(p->pSimWords + EntrySize * k++);
+ pSims->pNext = NULL;
+ if ( Ivy_ObjIsNode(pObj) )
+ {
+ if ( p->pSimStart == NULL )
+ p->pSimStart = pSims;
+ else
+ ((Ivy_FraigSim_t *)(p->pSimWords + EntrySize * (k-2)))->pNext = pSims;
+ pSims->pFanin0 = Ivy_ObjSim( Ivy_ObjFanin0(pObj) );
+ pSims->pFanin1 = Ivy_ObjSim( Ivy_ObjFanin1(pObj) );
+ pSims->Type = (Ivy_ObjFaninPhase(Ivy_ObjChild0(pObj)) << 2) | (Ivy_ObjFaninPhase(Ivy_ObjChild1(pObj)) << 1) | pObj->fPhase;
+ }
+ else
+ {
+ pSims->pFanin0 = NULL;
+ pSims->pFanin1 = NULL;
+ pSims->Type = 0;
+ }
+ Ivy_ObjSetSim( pObj, pSims );
+ }
+ assert( k == Ivy_ManObjNum(pManAig) );
+ // allocate storage for sim pattern
+ p->nPatWords = Ivy_BitWordNum( Ivy_ManPiNum(pManAig) );
+ p->pPatWords = ALLOC( unsigned, p->nPatWords );
+ p->pPatScores = ALLOC( int, 32 * p->nSimWords );
+ p->vPiVars = Vec_PtrAlloc( 100 );
+ // set random number generator
+ srand( 0xABCABC );
+ return p;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Stops the fraiging manager.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Ivy_FraigStop( Ivy_FraigMan_t * p )
+{
+ if ( p->pParams->fVerbose )
+ Ivy_FraigPrint( p );
+ if ( p->vPiVars ) Vec_PtrFree( p->vPiVars );
+ if ( p->pSat ) sat_solver_delete( p->pSat );
+ FREE( p->pPatScores );
+ FREE( p->pPatWords );
+ FREE( p->pSimWords );
+ free( p );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Prints stats for the fraiging manager.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Ivy_FraigPrint( Ivy_FraigMan_t * p )
+{
+ double nMemory;
+ nMemory = (double)Ivy_ManObjNum(p->pManAig)*p->nSimWords*sizeof(unsigned)/(1<<20);
+ printf( "SimWords = %d. Rounds = %d. Mem = %0.2f Mb. ", p->nSimWords, p->nSimRounds, nMemory );
+ printf( "Classes: Beg = %d. End = %d.\n", p->nClassesBeg, p->nClassesEnd );
+// printf( "Limits: BTNode = %d. BTMiter = %d.\n", p->pParams->nBTLimitNode, p->pParams->nBTLimitMiter );
+ printf( "Proof = %d. Counter-example = %d. Fail = %d. FailReal = %d. Zero = %d.\n",
+ p->nSatProof, p->nSatCallsSat, p->nSatFails, p->nSatFailsReal, p->nClassesZero );
+ printf( "Final = %d. Miter = %d. Total = %d. Mux = %d. (Exor = %d.) SatVars = %d.\n",
+ Ivy_ManNodeNum(p->pManFraig), p->nNodesMiter, Ivy_ManNodeNum(p->pManAig), 0, 0, p->nSatVars );
+ if ( p->pSat ) Sat_SolverPrintStats( stdout, p->pSat );
+ PRT( "AIG simulation ", p->timeSim );
+ PRT( "AIG traversal ", p->timeTrav );
+ PRT( "SAT solving ", p->timeSat );
+ PRT( " Unsat ", p->timeSatUnsat );
+ PRT( " Sat ", p->timeSatSat );
+ PRT( " Fail ", p->timeSatFail );
+ PRT( "Class refining ", p->timeRef );
+ PRT( "TOTAL RUNTIME ", p->timeTotal );
+ if ( p->time1 ) { PRT( "time1 ", p->time1 ); }
+}
+
+
+
+/**Function*************************************************************
+
+ Synopsis [Assigns random patterns to the PI node.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Ivy_NodeAssignRandom( Ivy_FraigMan_t * p, Ivy_Obj_t * pObj )
+{
+ Ivy_FraigSim_t * pSims;
+ int i;
+ assert( Ivy_ObjIsPi(pObj) );
+ pSims = Ivy_ObjSim(pObj);
+ for ( i = 0; i < p->nSimWords; i++ )
+ pSims->pData[i] = Ivy_ObjRandomSim();
+}
+
+/**Function*************************************************************
+
+ Synopsis [Assigns constant patterns to the PI node.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Ivy_NodeAssignConst( Ivy_FraigMan_t * p, Ivy_Obj_t * pObj, int fConst1 )
+{
+ Ivy_FraigSim_t * pSims;
+ int i;
+ assert( Ivy_ObjIsPi(pObj) );
+ pSims = Ivy_ObjSim(pObj);
+ for ( i = 0; i < p->nSimWords; i++ )
+ pSims->pData[i] = fConst1? ~(unsigned)0 : 0;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Assings random simulation info for the PIs.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Ivy_FraigAssignRandom( Ivy_FraigMan_t * p )
+{
+ Ivy_Obj_t * pObj;
+ int i;
+ Ivy_ManForEachPi( p->pManAig, pObj, i )
+ Ivy_NodeAssignRandom( p, pObj );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Assings distance-1 simulation info for the PIs.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Ivy_FraigAssignDist1( Ivy_FraigMan_t * p, unsigned * pPat )
+{
+ Ivy_Obj_t * pObj;
+ int i, Limit;
+ Ivy_ManForEachPi( p->pManAig, pObj, i )
+ {
+ Ivy_NodeAssignConst( p, pObj, Ivy_InfoHasBit(pPat, i) );
+// printf( "%d", Ivy_InfoHasBit(pPat, i) );
+ }
+// printf( "\n" );
+
+ Limit = IVY_MIN( Ivy_ManPiNum(p->pManAig), p->nSimWords * 32 - 1 );
+ for ( i = 0; i < Limit; i++ )
+ Ivy_InfoXorBit( Ivy_ObjSim( Ivy_ManPi(p->pManAig,i) )->pData, i+1 );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Returns 1 if simulation info is composed of all zeros.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Ivy_NodeHasZeroSim( Ivy_FraigMan_t * p, Ivy_Obj_t * pObj )
+{
+ Ivy_FraigSim_t * pSims;
+ int i;
+ pSims = Ivy_ObjSim(pObj);
+ for ( i = 0; i < p->nSimWords; i++ )
+ if ( pSims->pData[i] )
+ return 0;
+ return 1;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Returns 1 if simulation info is composed of all zeros.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Ivy_NodeComplementSim( Ivy_FraigMan_t * p, Ivy_Obj_t * pObj )
+{
+ Ivy_FraigSim_t * pSims;
+ int i;
+ pSims = Ivy_ObjSim(pObj);
+ for ( i = 0; i < p->nSimWords; i++ )
+ pSims->pData[i] = ~pSims->pData[i];
+}
+
+/**Function*************************************************************
+
+ Synopsis [Returns 1 if simulation infos are equal.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Ivy_NodeCompareSims( Ivy_FraigMan_t * p, Ivy_Obj_t * pObj0, Ivy_Obj_t * pObj1 )
+{
+ Ivy_FraigSim_t * pSims0, * pSims1;
+ int i;
+ pSims0 = Ivy_ObjSim(pObj0);
+ pSims1 = Ivy_ObjSim(pObj1);
+ for ( i = 0; i < p->nSimWords; i++ )
+ if ( pSims0->pData[i] != pSims1->pData[i] )
+ return 0;
+ return 1;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Simulates one node.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Ivy_NodeSimulateSim( Ivy_FraigMan_t * p, Ivy_FraigSim_t * pSims )
+{
+ unsigned * pData, * pData0, * pData1;
+ int i;
+ pData = pSims->pData;
+ pData0 = pSims->pFanin0->pData;
+ pData1 = pSims->pFanin1->pData;
+ switch( pSims->Type )
+ {
+ case 0:
+ for ( i = 0; i < p->nSimWords; i++ )
+ pData[i] = (pData0[i] & pData1[i]);
+ break;
+ case 1:
+ for ( i = 0; i < p->nSimWords; i++ )
+ pData[i] = ~(pData0[i] & pData1[i]);
+ break;
+ case 2:
+ for ( i = 0; i < p->nSimWords; i++ )
+ pData[i] = (pData0[i] & ~pData1[i]);
+ break;
+ case 3:
+ for ( i = 0; i < p->nSimWords; i++ )
+ pData[i] = (~pData0[i] | pData1[i]);
+ break;
+ case 4:
+ for ( i = 0; i < p->nSimWords; i++ )
+ pData[i] = (~pData0[i] & pData1[i]);
+ break;
+ case 5:
+ for ( i = 0; i < p->nSimWords; i++ )
+ pData[i] = (pData0[i] | ~pData1[i]);
+ break;
+ case 6:
+ for ( i = 0; i < p->nSimWords; i++ )
+ pData[i] = ~(pData0[i] | pData1[i]);
+ break;
+ case 7:
+ for ( i = 0; i < p->nSimWords; i++ )
+ pData[i] = (pData0[i] | pData1[i]);
+ break;
+ }
+}
+
+/**Function*************************************************************
+
+ Synopsis [Simulates one node.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Ivy_NodeSimulate( Ivy_FraigMan_t * p, Ivy_Obj_t * pObj )
+{
+ Ivy_FraigSim_t * pSims, * pSims0, * pSims1;
+ int fCompl, fCompl0, fCompl1, i;
+ assert( !Ivy_IsComplement(pObj) );
+ // get hold of the simulation information
+ pSims = Ivy_ObjSim(pObj);
+ pSims0 = Ivy_ObjSim(Ivy_ObjFanin0(pObj));
+ pSims1 = Ivy_ObjSim(Ivy_ObjFanin1(pObj));
+ // get complemented attributes of the children using their random info
+ fCompl = pObj->fPhase;
+ fCompl0 = Ivy_ObjFaninPhase(Ivy_ObjChild0(pObj));
+ fCompl1 = Ivy_ObjFaninPhase(Ivy_ObjChild1(pObj));
+ // simulate
+ if ( fCompl0 && fCompl1 )
+ {
+ if ( fCompl )
+ for ( i = 0; i < p->nSimWords; i++ )
+ pSims->pData[i] = (pSims0->pData[i] | pSims1->pData[i]);
+ else
+ for ( i = 0; i < p->nSimWords; i++ )
+ pSims->pData[i] = ~(pSims0->pData[i] | pSims1->pData[i]);
+ }
+ else if ( fCompl0 && !fCompl1 )
+ {
+ if ( fCompl )
+ for ( i = 0; i < p->nSimWords; i++ )
+ pSims->pData[i] = (pSims0->pData[i] | ~pSims1->pData[i]);
+ else
+ for ( i = 0; i < p->nSimWords; i++ )
+ pSims->pData[i] = (~pSims0->pData[i] & pSims1->pData[i]);
+ }
+ else if ( !fCompl0 && fCompl1 )
+ {
+ if ( fCompl )
+ for ( i = 0; i < p->nSimWords; i++ )
+ pSims->pData[i] = (~pSims0->pData[i] | pSims1->pData[i]);
+ else
+ for ( i = 0; i < p->nSimWords; i++ )
+ pSims->pData[i] = (pSims0->pData[i] & ~pSims1->pData[i]);
+ }
+ else // if ( !fCompl0 && !fCompl1 )
+ {
+ if ( fCompl )
+ for ( i = 0; i < p->nSimWords; i++ )
+ pSims->pData[i] = ~(pSims0->pData[i] & pSims1->pData[i]);
+ else
+ for ( i = 0; i < p->nSimWords; i++ )
+ pSims->pData[i] = (pSims0->pData[i] & pSims1->pData[i]);
+ }
+}
+
+/**Function*************************************************************
+
+ Synopsis [Computes hash value using simulation info.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+unsigned Ivy_NodeHash( Ivy_FraigMan_t * p, Ivy_Obj_t * pObj )
+{
+ static int s_FPrimes[128] = {
+ 1009, 1049, 1093, 1151, 1201, 1249, 1297, 1361, 1427, 1459,
+ 1499, 1559, 1607, 1657, 1709, 1759, 1823, 1877, 1933, 1997,
+ 2039, 2089, 2141, 2213, 2269, 2311, 2371, 2411, 2467, 2543,
+ 2609, 2663, 2699, 2741, 2797, 2851, 2909, 2969, 3037, 3089,
+ 3169, 3221, 3299, 3331, 3389, 3461, 3517, 3557, 3613, 3671,
+ 3719, 3779, 3847, 3907, 3943, 4013, 4073, 4129, 4201, 4243,
+ 4289, 4363, 4441, 4493, 4549, 4621, 4663, 4729, 4793, 4871,
+ 4933, 4973, 5021, 5087, 5153, 5227, 5281, 5351, 5417, 5471,
+ 5519, 5573, 5651, 5693, 5749, 5821, 5861, 5923, 6011, 6073,
+ 6131, 6199, 6257, 6301, 6353, 6397, 6481, 6563, 6619, 6689,
+ 6737, 6803, 6863, 6917, 6977, 7027, 7109, 7187, 7237, 7309,
+ 7393, 7477, 7523, 7561, 7607, 7681, 7727, 7817, 7877, 7933,
+ 8011, 8039, 8059, 8081, 8093, 8111, 8123, 8147
+ };
+ Ivy_FraigSim_t * pSims;
+ unsigned uHash;
+ int i;
+ assert( p->nSimWords <= 128 );
+ uHash = 0;
+ pSims = Ivy_ObjSim(pObj);
+ for ( i = 0; i < p->nSimWords; i++ )
+ uHash ^= pSims->pData[i] * s_FPrimes[i];
+ return uHash;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Simulates AIG manager.]
+
+ Description [Assumes that the PI simulation info is attached.]
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Ivy_FraigSimulateOne( Ivy_FraigMan_t * p )
+{
+ Ivy_Obj_t * pObj;
+ int i, clk;
+clk = clock();
+ Ivy_ManForEachNode( p->pManAig, pObj, i )
+ {
+ Ivy_NodeSimulate( p, pObj );
+/*
+ if ( Ivy_ObjFraig(pObj) == NULL )
+ printf( "%3d --- -- %d : ", pObj->Id, pObj->fPhase );
+ else
+ printf( "%3d %3d %2d %d : ", pObj->Id, Ivy_Regular(Ivy_ObjFraig(pObj))->Id, Ivy_ObjSatNum(Ivy_Regular(Ivy_ObjFraig(pObj))), pObj->fPhase );
+ Extra_PrintBinary( stdout, Ivy_ObjSim(pObj), 30 );
+ printf( "\n" );
+*/
+ }
+p->timeSim += clock() - clk;
+p->nSimRounds++;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Simulates AIG manager.]
+
+ Description [Assumes that the PI simulation info is attached.]
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Ivy_FraigSimulateOneSim( Ivy_FraigMan_t * p )
+{
+ Ivy_FraigSim_t * pSims;
+ int clk;
+clk = clock();
+ for ( pSims = p->pSimStart; pSims; pSims = pSims->pNext )
+ Ivy_NodeSimulateSim( p, pSims );
+p->timeSim += clock() - clk;
+p->nSimRounds++;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Adds one node to the equivalence class.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Ivy_NodeAddToClass( Ivy_Obj_t * pClass, Ivy_Obj_t * pObj )
+{
+ if ( Ivy_ObjClassNodeNext(pClass) == NULL )
+ Ivy_ObjSetClassNodeNext( pClass, pObj );
+ else
+ Ivy_ObjSetClassNodeNext( Ivy_ObjClassNodeLast(pClass), pObj );
+ Ivy_ObjSetClassNodeLast( pClass, pObj );
+ Ivy_ObjSetClassNodeRepr( pObj, pClass );
+ Ivy_ObjSetClassNodeNext( pObj, NULL );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Adds equivalence class to the list of classes.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Ivy_FraigAddClass( Ivy_FraigList_t * pList, Ivy_Obj_t * pClass )
+{
+ if ( pList->pHead == NULL )
+ {
+ pList->pHead = pClass;
+ pList->pTail = pClass;
+ Ivy_ObjSetEquivListPrev( pClass, NULL );
+ Ivy_ObjSetEquivListNext( pClass, NULL );
+ }
+ else
+ {
+ Ivy_ObjSetEquivListNext( pList->pTail, pClass );
+ Ivy_ObjSetEquivListPrev( pClass, pList->pTail );
+ Ivy_ObjSetEquivListNext( pClass, NULL );
+ pList->pTail = pClass;
+ }
+ pList->nItems++;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Updates the list of classes after base class has split.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Ivy_FraigInsertClass( Ivy_FraigList_t * pList, Ivy_Obj_t * pBase, Ivy_Obj_t * pClass )
+{
+ Ivy_ObjSetEquivListPrev( pClass, pBase );
+ Ivy_ObjSetEquivListNext( pClass, Ivy_ObjEquivListNext(pBase) );
+ if ( Ivy_ObjEquivListNext(pBase) )
+ Ivy_ObjSetEquivListPrev( Ivy_ObjEquivListNext(pBase), pClass );
+ Ivy_ObjSetEquivListNext( pBase, pClass );
+ if ( pList->pTail == pBase )
+ pList->pTail = pClass;
+ pList->nItems++;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Removes equivalence class from the list of classes.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Ivy_FraigRemoveClass( Ivy_FraigList_t * pList, Ivy_Obj_t * pClass )
+{
+ if ( pList->pHead == pClass )
+ pList->pHead = Ivy_ObjEquivListNext(pClass);
+ if ( pList->pTail == pClass )
+ pList->pTail = Ivy_ObjEquivListPrev(pClass);
+ if ( Ivy_ObjEquivListPrev(pClass) )
+ Ivy_ObjSetEquivListNext( Ivy_ObjEquivListPrev(pClass), Ivy_ObjEquivListNext(pClass) );
+ if ( Ivy_ObjEquivListNext(pClass) )
+ Ivy_ObjSetEquivListPrev( Ivy_ObjEquivListNext(pClass), Ivy_ObjEquivListPrev(pClass) );
+ Ivy_ObjSetEquivListNext( pClass, NULL );
+ Ivy_ObjSetEquivListPrev( pClass, NULL );
+ pClass->fMarkA = 0;
+ pList->nItems--;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Count the number of pairs.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Ivy_FraigCountPairsClasses( Ivy_FraigMan_t * p )
+{
+ Ivy_Obj_t * pClass, * pNode;
+ int nPairs = 0, nNodes;
+ return nPairs;
+
+ Ivy_FraigForEachEquivClass( p->lClasses.pHead, pClass )
+ {
+ nNodes = 0;
+ Ivy_FraigForEachClassNode( pClass, pNode )
+ nNodes++;
+ nPairs += nNodes * (nNodes - 1) / 2;
+ }
+ return nPairs;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Creates initial simulation classes.]
+
+ Description [Assumes that simulation info is assigned.]
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Ivy_FraigCreateClasses( Ivy_FraigMan_t * p )
+{
+ Ivy_Obj_t ** pTable;
+ Ivy_Obj_t * pObj, * pConst1, * pBin, * pEntry;
+ int i, nTableSize;
+ unsigned Hash;
+ pConst1 = Ivy_ManConst1(p->pManAig);
+ // allocate the table
+ nTableSize = Ivy_ManObjNum(p->pManAig) / 2 + 13;
+ pTable = ALLOC( Ivy_Obj_t *, nTableSize );
+ memset( pTable, 0, sizeof(Ivy_Obj_t *) * nTableSize );
+ // collect nodes into the table
+ Ivy_ManForEachObj( p->pManAig, pObj, i )
+ {
+ if ( !Ivy_ObjIsPi(pObj) && !Ivy_ObjIsNode(pObj) )
+ continue;
+ Hash = Ivy_NodeHash( p, pObj );
+ if ( Hash == 0 && Ivy_NodeHasZeroSim( p, pObj ) )
+ {
+ Ivy_NodeAddToClass( pConst1, pObj );
+ continue;
+ }
+ // add the node to the table
+ pBin = pTable[Hash % nTableSize];
+ Ivy_FraigForEachBinNode( pBin, pEntry )
+ if ( Ivy_NodeCompareSims( p, pEntry, pObj ) )
+ {
+ Ivy_NodeAddToClass( pEntry, pObj );
+ break;
+ }
+ // check if the entry was added
+ if ( pEntry )
+ continue;
+ Ivy_ObjSetNodeHashNext( pObj, pBin );
+ pTable[Hash % nTableSize] = pObj;
+ }
+ // collect non-trivial classes
+ assert( p->lClasses.pHead == NULL );
+ Ivy_ManForEachObj( p->pManAig, pObj, i )
+ {
+ if ( !Ivy_ObjIsConst1(pObj) && !Ivy_ObjIsPi(pObj) && !Ivy_ObjIsNode(pObj) )
+ continue;
+ Ivy_ObjSetNodeHashNext( pObj, NULL );
+ if ( Ivy_ObjClassNodeRepr(pObj) == NULL )
+ {
+ assert( Ivy_ObjClassNodeNext(pObj) == NULL );
+ continue;
+ }
+ // recognize the head of the class
+ if ( Ivy_ObjClassNodeNext( Ivy_ObjClassNodeRepr(pObj) ) != NULL )
+ continue;
+ // clean the class representative and add it to the list
+ Ivy_ObjSetClassNodeRepr( pObj, NULL );
+ Ivy_FraigAddClass( &p->lClasses, pObj );
+ }
+ // free the table
+ free( pTable );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Recursively refines the class after simulation.]
+
+ Description [Returns 1 if the class has changed.]
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Ivy_FraigRefineClass_rec( Ivy_FraigMan_t * p, Ivy_Obj_t * pClass )
+{
+ Ivy_Obj_t * pClassNew, * pListOld, * pListNew, * pNode;
+ int RetValue = 0;
+ // check if there is refinement
+ pListOld = pClass;
+ Ivy_FraigForEachClassNode( Ivy_ObjClassNodeNext(pClass), pClassNew )
+ {
+ if ( !Ivy_NodeCompareSims(p, pClass, pClassNew) )
+ {
+ if ( p->pParams->fPatScores )
+ Ivy_FraigAddToPatScores( p, pClass, pClassNew );
+ break;
+ }
+ pListOld = pClassNew;
+ }
+ if ( pClassNew == NULL )
+ return 0;
+ // set representative of the new class
+ Ivy_ObjSetClassNodeRepr( pClassNew, NULL );
+ // start the new list
+ pListNew = pClassNew;
+ // go through the remaining nodes and sort them into two groups:
+ // (1) matches of the old node; (2) non-matches of the old node
+ Ivy_FraigForEachClassNode( Ivy_ObjClassNodeNext(pClassNew), pNode )
+ if ( Ivy_NodeCompareSims( p, pClass, pNode ) )
+ {
+ Ivy_ObjSetClassNodeNext( pListOld, pNode );
+ pListOld = pNode;
+ }
+ else
+ {
+ Ivy_ObjSetClassNodeNext( pListNew, pNode );
+ Ivy_ObjSetClassNodeRepr( pNode, pClassNew );
+ pListNew = pNode;
+ }
+ // finish both lists
+ Ivy_ObjSetClassNodeNext( pListNew, NULL );
+ Ivy_ObjSetClassNodeNext( pListOld, NULL );
+ // update the list of classes
+ Ivy_FraigInsertClass( &p->lClasses, pClass, pClassNew );
+ // if the old class is trivial, remove it
+ if ( Ivy_ObjClassNodeNext(pClass) == NULL )
+ Ivy_FraigRemoveClass( &p->lClasses, pClass );
+ // if the new class is trivial, remove it; otherwise, try to refine it
+ if ( Ivy_ObjClassNodeNext(pClassNew) == NULL )
+ Ivy_FraigRemoveClass( &p->lClasses, pClassNew );
+ else
+ RetValue = Ivy_FraigRefineClass_rec( p, pClassNew );
+ return RetValue + 1;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Creates the counter-example from the successful pattern.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Ivy_FraigCheckOutputSimsSavePattern( Ivy_FraigMan_t * p, Ivy_Obj_t * pObj )
+{
+ Ivy_FraigSim_t * pSims;
+ int i, k, BestPat, * pModel;
+ // find the word of the pattern
+ pSims = Ivy_ObjSim(pObj);
+ for ( i = 0; i < p->nSimWords; i++ )
+ if ( pSims->pData[i] )
+ break;
+ assert( i < p->nSimWords );
+ // find the bit of the pattern
+ for ( k = 0; k < 32; k++ )
+ if ( pSims->pData[i] & (1 << k) )
+ break;
+ assert( k < 32 );
+ // determine the best pattern
+ BestPat = i * 32 + k;
+ // fill in the counter-example data
+ pModel = ALLOC( int, Ivy_ManPiNum(p->pManFraig) );
+ Ivy_ManForEachPi( p->pManAig, pObj, i )
+ {
+ pModel[i] = Ivy_InfoHasBit(Ivy_ObjSim(pObj)->pData, BestPat);
+// printf( "%d", pModel[i] );
+ }
+// printf( "\n" );
+ // set the model
+ assert( p->pManFraig->pData == NULL );
+ p->pManFraig->pData = pModel;
+ return;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Returns 1 if the one of the output is already non-constant 0.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Ivy_FraigCheckOutputSims( Ivy_FraigMan_t * p )
+{
+ Ivy_Obj_t * pObj;
+ int i;
+ // make sure the reference simulation pattern does not detect the bug
+ pObj = Ivy_ManPo( p->pManAig, 0 );
+ assert( Ivy_ObjFanin0(pObj)->fPhase == (unsigned)Ivy_ObjFaninC0(pObj) ); // Ivy_ObjFaninPhase(Ivy_ObjChild0(pObj)) == 0
+ Ivy_ManForEachPo( p->pManAig, pObj, i )
+ {
+ // complement simulation info
+// if ( Ivy_ObjFanin0(pObj)->fPhase ^ Ivy_ObjFaninC0(pObj) ) // Ivy_ObjFaninPhase(Ivy_ObjChild0(pObj))
+// Ivy_NodeComplementSim( p, Ivy_ObjFanin0(pObj) );
+ // check
+ if ( !Ivy_NodeHasZeroSim( p, Ivy_ObjFanin0(pObj) ) )
+ {
+ // create the counter-example from this pattern
+ Ivy_FraigCheckOutputSimsSavePattern( p, Ivy_ObjFanin0(pObj) );
+ return 1;
+ }
+ // complement simulation info
+// if ( Ivy_ObjFanin0(pObj)->fPhase ^ Ivy_ObjFaninC0(pObj) )
+// Ivy_NodeComplementSim( p, Ivy_ObjFanin0(pObj) );
+ }
+ return 0;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Refines the classes after simulation.]
+
+ Description [Assumes that simulation info is assigned. Returns the
+ number of classes refined.]
+
+ SideEffects [Large equivalence class of constant 0 may cause problems.]
+
+ SeeAlso []
+
+***********************************************************************/
+int Ivy_FraigRefineClasses( Ivy_FraigMan_t * p )
+{
+ Ivy_Obj_t * pClass, * pClass2;
+ int clk, RetValue, Counter = 0;
+ // check if some outputs already became non-constant
+ // this is a special case when computation can be stopped!!!
+ if ( p->pParams->fProve )
+ Ivy_FraigCheckOutputSims( p );
+ if ( p->pManFraig->pData )
+ return 0;
+ // refine the classed
+clk = clock();
+ Ivy_FraigForEachEquivClassSafe( p->lClasses.pHead, pClass, pClass2 )
+ {
+ if ( pClass->fMarkA )
+ continue;
+ RetValue = Ivy_FraigRefineClass_rec( p, pClass );
+ Counter += ( RetValue > 0 );
+//if ( Ivy_ObjIsConst1(pClass) )
+//printf( "%d ", RetValue );
+//if ( Ivy_ObjIsConst1(pClass) )
+// p->time1 += clock() - clk;
+ }
+p->timeRef += clock() - clk;
+ return Counter;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Print the class.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Ivy_FraigPrintClass( Ivy_Obj_t * pClass )
+{
+ Ivy_Obj_t * pObj;
+ printf( "Class {" );
+ Ivy_FraigForEachClassNode( pClass, pObj )
+ printf( " %d(%d)%c", pObj->Id, pObj->Level, pObj->fPhase? '+' : '-' );
+ printf( " }\n" );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Count the number of elements in the class.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Ivy_FraigCountClassNodes( Ivy_Obj_t * pClass )
+{
+ Ivy_Obj_t * pObj;
+ int Counter = 0;
+ Ivy_FraigForEachClassNode( pClass, pObj )
+ Counter++;
+ return Counter;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Prints simulation classes.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Ivy_FraigPrintSimClasses( Ivy_FraigMan_t * p )
+{
+ Ivy_Obj_t * pClass;
+ Ivy_FraigForEachEquivClass( p->lClasses.pHead, pClass )
+ {
+// Ivy_FraigPrintClass( pClass );
+ printf( "%d ", Ivy_FraigCountClassNodes( pClass ) );
+ }
+// printf( "\n" );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Generated const 0 pattern.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Ivy_FraigSavePattern0( Ivy_FraigMan_t * p )
+{
+ memset( p->pPatWords, 0, sizeof(unsigned) * p->nPatWords );
+}
+
+/**Function*************************************************************
+
+ Synopsis [[Generated const 1 pattern.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Ivy_FraigSavePattern1( Ivy_FraigMan_t * p )
+{
+ memset( p->pPatWords, 0xff, sizeof(unsigned) * p->nPatWords );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Generates the counter-example satisfying the miter.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int * Ivy_FraigCreateModel( Ivy_FraigMan_t * p )
+{
+ int * pModel;
+ Ivy_Obj_t * pObj;
+ int i;
+ pModel = ALLOC( int, Ivy_ManPiNum(p->pManFraig) );
+ Ivy_ManForEachPi( p->pManFraig, pObj, i )
+ pModel[i] = ( p->pSat->model.ptr[Ivy_ObjSatNum(pObj)] == l_True );
+ return pModel;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Copy pattern from the solver into the internal storage.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Ivy_FraigSavePattern( Ivy_FraigMan_t * p )
+{
+ Ivy_Obj_t * pObj;
+ int i;
+ memset( p->pPatWords, 0, sizeof(unsigned) * p->nPatWords );
+ Ivy_ManForEachPi( p->pManFraig, pObj, i )
+// Vec_PtrForEachEntry( p->vPiVars, pObj, i )
+ if ( p->pSat->model.ptr[Ivy_ObjSatNum(pObj)] == l_True )
+ Ivy_InfoSetBit( p->pPatWords, i );
+// Ivy_InfoSetBit( p->pPatWords, pObj->Id - 1 );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Copy pattern from the solver into the internal storage.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Ivy_FraigSavePattern2( Ivy_FraigMan_t * p )
+{
+ Ivy_Obj_t * pObj;
+ int i;
+ memset( p->pPatWords, 0, sizeof(unsigned) * p->nPatWords );
+// Ivy_ManForEachPi( p->pManFraig, pObj, i )
+ Vec_PtrForEachEntry( p->vPiVars, pObj, i )
+ if ( p->pSat->model.ptr[Ivy_ObjSatNum(pObj)] == l_True )
+// Ivy_InfoSetBit( p->pPatWords, i );
+ Ivy_InfoSetBit( p->pPatWords, pObj->Id - 1 );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Copy pattern from the solver into the internal storage.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Ivy_FraigSavePattern3( Ivy_FraigMan_t * p )
+{
+ Ivy_Obj_t * pObj;
+ int i;
+ for ( i = 0; i < p->nPatWords; i++ )
+ p->pPatWords[i] = Ivy_ObjRandomSim();
+ Vec_PtrForEachEntry( p->vPiVars, pObj, i )
+ if ( Ivy_InfoHasBit( p->pPatWords, pObj->Id - 1 ) ^ (p->pSat->model.ptr[Ivy_ObjSatNum(pObj)] == l_True) )
+ Ivy_InfoXorBit( p->pPatWords, pObj->Id - 1 );
+}
+
+
+/**Function*************************************************************
+
+ Synopsis [Performs simulation of the manager.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Ivy_FraigSimulate( Ivy_FraigMan_t * p )
+{
+ int nChanges, nClasses;
+ // start the classes
+ Ivy_FraigAssignRandom( p );
+ Ivy_FraigSimulateOne( p );
+ Ivy_FraigCreateClasses( p );
+//printf( "Starting classes = %5d. Pairs = %6d.\n", p->lClasses.nItems, Ivy_FraigCountPairsClasses(p) );
+ // refine classes by walking 0/1 patterns
+ Ivy_FraigSavePattern0( p );
+ Ivy_FraigAssignDist1( p, p->pPatWords );
+ Ivy_FraigSimulateOne( p );
+ nChanges = Ivy_FraigRefineClasses( p );
+ if ( p->pManFraig->pData )
+ return;
+//printf( "Refined classes = %5d. Changes = %4d. Pairs = %6d.\n", p->lClasses.nItems, nChanges, Ivy_FraigCountPairsClasses(p) );
+ Ivy_FraigSavePattern1( p );
+ Ivy_FraigAssignDist1( p, p->pPatWords );
+ Ivy_FraigSimulateOne( p );
+ nChanges = Ivy_FraigRefineClasses( p );
+ if ( p->pManFraig->pData )
+ return;
+//printf( "Refined classes = %5d. Changes = %4d. Pairs = %6d.\n", p->lClasses.nItems, nChanges, Ivy_FraigCountPairsClasses(p) );
+ // refine classes by random simulation
+ do {
+ Ivy_FraigAssignRandom( p );
+ Ivy_FraigSimulateOne( p );
+ nClasses = p->lClasses.nItems;
+ nChanges = Ivy_FraigRefineClasses( p );
+ if ( p->pManFraig->pData )
+ return;
+//printf( "Refined classes = %5d. Changes = %4d. Pairs = %6d.\n", p->lClasses.nItems, nChanges, Ivy_FraigCountPairsClasses(p) );
+ } while ( (double)nChanges / nClasses > p->pParams->dSimSatur );
+// Ivy_FraigPrintSimClasses( p );
+}
+
+
+
+/**Function*************************************************************
+
+ Synopsis [Cleans pattern scores.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Ivy_FraigCleanPatScores( Ivy_FraigMan_t * p )
+{
+ int i, nLimit = p->nSimWords * 32;
+ for ( i = 0; i < nLimit; i++ )
+ p->pPatScores[i] = 0;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Adds to pattern scores.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Ivy_FraigAddToPatScores( Ivy_FraigMan_t * p, Ivy_Obj_t * pClass, Ivy_Obj_t * pClassNew )
+{
+ Ivy_FraigSim_t * pSims0, * pSims1;
+ unsigned uDiff;
+ int i, w;
+ // get hold of the simulation information
+ pSims0 = Ivy_ObjSim(pClass);
+ pSims1 = Ivy_ObjSim(pClassNew);
+ // iterate through the differences and record the score
+ for ( w = 0; w < p->nSimWords; w++ )
+ {
+ uDiff = pSims0->pData[w] ^ pSims1->pData[w];
+ if ( uDiff == 0 )
+ continue;
+ for ( i = 0; i < 32; i++ )
+ if ( uDiff & ( 1 << i ) )
+ p->pPatScores[w*32+i]++;
+ }
+}
+
+/**Function*************************************************************
+
+ Synopsis [Selects the best pattern.]
+
+ Description [Returns 1 if such pattern is found.]
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Ivy_FraigSelectBestPat( Ivy_FraigMan_t * p )
+{
+ Ivy_FraigSim_t * pSims;
+ Ivy_Obj_t * pObj;
+ int i, nLimit = p->nSimWords * 32, MaxScore = 0, BestPat = -1;
+ for ( i = 1; i < nLimit; i++ )
+ {
+ if ( MaxScore < p->pPatScores[i] )
+ {
+ MaxScore = p->pPatScores[i];
+ BestPat = i;
+ }
+ }
+ if ( MaxScore == 0 )
+ return 0;
+// if ( MaxScore > p->pParams->MaxScore )
+// printf( "Max score is %3d. ", MaxScore );
+ // copy the best pattern into the selected pattern
+ memset( p->pPatWords, 0, sizeof(unsigned) * p->nPatWords );
+ Ivy_ManForEachPi( p->pManAig, pObj, i )
+ {
+ pSims = Ivy_ObjSim(pObj);
+ if ( Ivy_InfoHasBit(pSims->pData, BestPat) )
+ Ivy_InfoSetBit(p->pPatWords, i);
+ }
+ return MaxScore;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Resimulates fraiging manager after finding a counter-example.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Ivy_FraigResimulate( Ivy_FraigMan_t * p )
+{
+ int nChanges;
+ Ivy_FraigAssignDist1( p, p->pPatWords );
+ Ivy_FraigSimulateOne( p );
+ if ( p->pParams->fPatScores )
+ Ivy_FraigCleanPatScores( p );
+ nChanges = Ivy_FraigRefineClasses( p );
+ if ( p->pManFraig->pData )
+ return;
+ if ( nChanges < 1 )
+ printf( "Error: A counter-example did not refine classes!\n" );
+ assert( nChanges >= 1 );
+//printf( "Refined classes! = %5d. Changes = %4d.\n", p->lClasses.nItems, nChanges );
+ if ( !p->pParams->fPatScores )
+ return;
+
+ // perform additional simulation using dist1 patterns derived from successful patterns
+ while ( Ivy_FraigSelectBestPat(p) > p->pParams->MaxScore )
+ {
+ Ivy_FraigAssignDist1( p, p->pPatWords );
+ Ivy_FraigSimulateOne( p );
+ Ivy_FraigCleanPatScores( p );
+ nChanges = Ivy_FraigRefineClasses( p );
+ if ( p->pManFraig->pData )
+ return;
+//printf( "Refined class!!! = %5d. Changes = %4d. Pairs = %6d.\n", p->lClasses.nItems, nChanges, Ivy_FraigCountPairsClasses(p) );
+ if ( nChanges == 0 )
+ break;
+ }
+}
+
+
+/**Function*************************************************************
+
+ Synopsis [Prints the status of the miter.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Ivy_FraigMiterPrint( Ivy_Man_t * pNtk, char * pString, int clk, int fVerbose )
+{
+ if ( !fVerbose )
+ return;
+ printf( "Nodes = %7d. Levels = %4d. ", Ivy_ManNodeNum(pNtk), Ivy_ManLevels(pNtk) );
+ PRT( pString, clock() - clk );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Reports the status of the miter.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Ivy_FraigMiterStatus( Ivy_Man_t * pMan )
+{
+ Ivy_Obj_t * pObj, * pObjNew;
+ int i, CountConst0 = 0, CountNonConst0 = 0, CountUndecided = 0;
+ if ( pMan->pData )
+ return 0;
+ Ivy_ManForEachPo( pMan, pObj, i )
+ {
+ pObjNew = Ivy_ObjChild0(pObj);
+ // check if the output is constant 1
+ if ( pObjNew == pMan->pConst1 )
+ {
+ CountNonConst0++;
+ continue;
+ }
+ // check if the output is constant 0
+ if ( pObjNew == Ivy_Not(pMan->pConst1) )
+ {
+ CountConst0++;
+ continue;
+ }
+ // check if the output can be constant 0
+ if ( Ivy_Regular(pObjNew)->fPhase != (unsigned)Ivy_IsComplement(pObjNew) )
+ {
+ CountNonConst0++;
+ continue;
+ }
+ CountUndecided++;
+ }
+/*
+ if ( p->pParams->fVerbose )
+ {
+ printf( "Miter has %d outputs. ", Ivy_ManPoNum(p->pManAig) );
+ printf( "Const0 = %d. ", CountConst0 );
+ printf( "NonConst0 = %d. ", CountNonConst0 );
+ printf( "Undecided = %d. ", CountUndecided );
+ printf( "\n" );
+ }
+*/
+ if ( CountNonConst0 )
+ return 0;
+ if ( CountUndecided )
+ return -1;
+ return 1;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Tries to prove each output of the miter until encountering a sat output.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Ivy_FraigMiterProve( Ivy_FraigMan_t * p )
+{
+ Ivy_Obj_t * pObj, * pObjNew;
+ int i, RetValue, clk = clock();
+ int fVerbose = 0;
+ Ivy_ManForEachPo( p->pManAig, pObj, i )
+ {
+ if ( i && fVerbose )
+ {
+ PRT( "Time", clock() -clk );
+ }
+ pObjNew = Ivy_ObjChild0Equiv(pObj);
+ // check if the output is constant 1
+ if ( pObjNew == p->pManFraig->pConst1 )
+ {
+ if ( fVerbose )
+ printf( "Output %2d (out of %2d) is constant 1. ", i, Ivy_ManPoNum(p->pManAig) );
+ // assing constant 0 model
+ p->pManFraig->pData = ALLOC( int, Ivy_ManPiNum(p->pManFraig) );
+ memset( p->pManFraig->pData, 0, sizeof(int) * Ivy_ManPiNum(p->pManFraig) );
+ break;
+ }
+ // check if the output is constant 0
+ if ( pObjNew == Ivy_Not(p->pManFraig->pConst1) )
+ {
+ if ( fVerbose )
+ printf( "Output %2d (out of %2d) is already constant 0. ", i, Ivy_ManPoNum(p->pManAig) );
+ continue;
+ }
+ // check if the output can be constant 0
+ if ( Ivy_Regular(pObjNew)->fPhase != (unsigned)Ivy_IsComplement(pObjNew) )
+ {
+ if ( fVerbose )
+ printf( "Output %2d (out of %2d) cannot be constant 0. ", i, Ivy_ManPoNum(p->pManAig) );
+ // assing constant 0 model
+ p->pManFraig->pData = ALLOC( int, Ivy_ManPiNum(p->pManFraig) );
+ memset( p->pManFraig->pData, 0, sizeof(int) * Ivy_ManPiNum(p->pManFraig) );
+ break;
+ }
+/*
+ // check the representative of this node
+ pRepr = Ivy_ObjClassNodeRepr(Ivy_ObjFanin0(pObj));
+ if ( Ivy_Regular(pRepr) != p->pManAig->pConst1 )
+ printf( "Representative is not constant 1.\n" );
+ else
+ printf( "Representative is constant 1.\n" );
+*/
+ // try to prove the output constant 0
+ RetValue = Ivy_FraigNodeIsConst( p, Ivy_Regular(pObjNew) );
+ if ( RetValue == 1 ) // proved equivalent
+ {
+ if ( fVerbose )
+ printf( "Output %2d (out of %2d) was proved constant 0. ", i, Ivy_ManPoNum(p->pManAig) );
+ // set the constant miter
+ Ivy_ObjFanin0(pObj)->pEquiv = Ivy_NotCond( p->pManFraig->pConst1, !Ivy_ObjFaninC0(pObj) );
+ continue;
+ }
+ if ( RetValue == -1 ) // failed
+ {
+ if ( fVerbose )
+ printf( "Output %2d (out of %2d) has timed out at %d backtracks. ", i, Ivy_ManPoNum(p->pManAig), p->pParams->nBTLimitMiter );
+ continue;
+ }
+ // proved satisfiable
+ if ( fVerbose )
+ printf( "Output %2d (out of %2d) was proved NOT a constant 0. ", i, Ivy_ManPoNum(p->pManAig) );
+ // create the model
+ p->pManFraig->pData = Ivy_FraigCreateModel(p);
+ break;
+ }
+ if ( fVerbose )
+ {
+ PRT( "Time", clock() -clk );
+ }
+}
+
+/**Function*************************************************************
+
+ Synopsis [Performs fraiging for the internal nodes.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Ivy_FraigSweep( Ivy_FraigMan_t * p )
+{
+ Ivy_Obj_t * pObj;//, * pTemp;
+ int i, k = 0;
+p->nClassesZero = p->lClasses.pHead? (Ivy_ObjIsConst1(p->lClasses.pHead) ? Ivy_FraigCountClassNodes(p->lClasses.pHead) : 0) : 0;
+p->nClassesBeg = p->lClasses.nItems;
+ // duplicate internal nodes
+ p->pProgress = Extra_ProgressBarStart( stdout, Ivy_ManNodeNum(p->pManAig) );
+ Ivy_ManForEachNode( p->pManAig, pObj, i )
+ {
+ Extra_ProgressBarUpdate( p->pProgress, k++, NULL );
+ // default to simple strashing if simulation detected a counter-example for a PO
+ if ( p->pManFraig->pData )
+ pObj->pEquiv = Ivy_And( p->pManFraig, Ivy_ObjChild0Equiv(pObj), Ivy_ObjChild1Equiv(pObj) );
+ else
+ pObj->pEquiv = Ivy_FraigAnd( p, pObj );
+ assert( pObj->pEquiv != NULL );
+// pTemp = Ivy_Regular(pObj->pEquiv);
+// assert( Ivy_Regular(pObj->pEquiv)->Type );
+ }
+ Extra_ProgressBarStop( p->pProgress );
+p->nClassesEnd = p->lClasses.nItems;
+ // try to prove the outputs of the miter
+ p->nNodesMiter = Ivy_ManNodeNum(p->pManFraig);
+// Ivy_FraigMiterStatus( p->pManFraig );
+ if ( p->pParams->fProve && p->pManFraig->pData == NULL )
+ Ivy_FraigMiterProve( p );
+ // add the POs
+ Ivy_ManForEachPo( p->pManAig, pObj, i )
+ Ivy_ObjCreatePo( p->pManFraig, Ivy_ObjChild0Equiv(pObj) );
+ // clean the old manager
+ Ivy_ManForEachObj( p->pManAig, pObj, i )
+ pObj->pFanout = pObj->pNextFan0 = pObj->pNextFan1 = pObj->pPrevFan0 = pObj->pPrevFan1 = NULL;
+ // clean the new manager
+ Ivy_ManForEachObj( p->pManFraig, pObj, i )
+ {
+ if ( Ivy_ObjFaninVec(pObj) )
+ Vec_PtrFree( Ivy_ObjFaninVec(pObj) );
+ pObj->pNextFan0 = pObj->pNextFan1 = NULL;
+ }
+ // remove dangling nodes
+ Ivy_ManCleanup( p->pManFraig );
+ // clean up the class marks
+ Ivy_FraigForEachEquivClass( p->lClasses.pHead, pObj )
+ pObj->fMarkA = 0;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Performs fraiging for one node.]
+
+ Description [Returns the fraiged node.]
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Ivy_Obj_t * Ivy_FraigAnd( Ivy_FraigMan_t * p, Ivy_Obj_t * pObjOld )
+{
+ Ivy_Obj_t * pObjNew, * pFanin0New, * pFanin1New, * pObjReprNew;
+ int RetValue;
+ // get the fraiged fanins
+ pFanin0New = Ivy_ObjChild0Equiv(pObjOld);
+ pFanin1New = Ivy_ObjChild1Equiv(pObjOld);
+ // get the candidate fraig node
+ pObjNew = Ivy_And( p->pManFraig, pFanin0New, pFanin1New );
+ // get representative of this class
+ if ( Ivy_ObjClassNodeRepr(pObjOld) == NULL || // this is a unique node
+ (!p->pParams->fDoSparse && Ivy_ObjClassNodeRepr(pObjOld) == p->pManAig->pConst1) ) // this is a sparse node
+ {
+ assert( Ivy_Regular(pFanin0New) != Ivy_Regular(pFanin1New) );
+ assert( pObjNew != Ivy_Regular(pFanin0New) );
+ assert( pObjNew != Ivy_Regular(pFanin1New) );
+ return pObjNew;
+ }
+ // get the fraiged representative
+ pObjReprNew = Ivy_ObjFraig(Ivy_ObjClassNodeRepr(pObjOld));
+ // if the fraiged nodes are the same return
+ if ( Ivy_Regular(pObjNew) == Ivy_Regular(pObjReprNew) )
+ return pObjNew;
+ assert( Ivy_Regular(pObjNew) != Ivy_ManConst1(p->pManFraig) );
+// printf( "Node = %d. Repr = %d.\n", pObjOld->Id, Ivy_ObjClassNodeRepr(pObjOld)->Id );
+
+ // they are different (the counter-example is in p->pPatWords)
+ RetValue = Ivy_FraigNodesAreEquiv( p, Ivy_Regular(pObjReprNew), Ivy_Regular(pObjNew) );
+ if ( RetValue == 1 ) // proved equivalent
+ {
+ // mark the class as proved
+ if ( Ivy_ObjClassNodeNext(pObjOld) == NULL )
+ Ivy_ObjClassNodeRepr(pObjOld)->fMarkA = 1;
+ return Ivy_NotCond( pObjReprNew, pObjOld->fPhase ^ Ivy_ObjClassNodeRepr(pObjOld)->fPhase );
+ }
+ if ( RetValue == -1 ) // failed
+ return pObjNew;
+ // simulate the counter-example and return the new node
+ Ivy_FraigResimulate( p );
+ return pObjNew;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Prints variable activity.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Ivy_FraigPrintActivity( Ivy_FraigMan_t * p )
+{
+ int i;
+ for ( i = 0; i < p->nSatVars; i++ )
+ printf( "%d %.3f ", i, p->pSat->activity[i] );
+ printf( "\n" );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Runs equivalence test for the two nodes.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Ivy_FraigNodesAreEquiv( Ivy_FraigMan_t * p, Ivy_Obj_t * pOld, Ivy_Obj_t * pNew )
+{
+ int pLits[4], RetValue, RetValue1, nBTLimit, clk, clk2 = clock();
+
+ // make sure the nodes are not complemented
+ assert( !Ivy_IsComplement(pNew) );
+ assert( !Ivy_IsComplement(pOld) );
+ assert( pNew != pOld );
+
+ // if at least one of the nodes is a failed node, perform adjustments:
+ // if the backtrack limit is small, simply skip this node
+ // if the backtrack limit is > 10, take the quare root of the limit
+ nBTLimit = p->pParams->nBTLimitNode;
+ if ( nBTLimit > 0 && (pOld->fFailTfo || pNew->fFailTfo) )
+ {
+ p->nSatFails++;
+ // fail immediately
+// return -1;
+ if ( nBTLimit <= 10 )
+ return -1;
+ nBTLimit = (int)pow(nBTLimit, 0.7);
+ }
+ p->nSatCalls++;
+
+ // make sure the solver is allocated and has enough variables
+ if ( p->pSat == NULL )
+ {
+ p->pSat = sat_solver_new();
+ p->nSatVars = 1;
+ sat_solver_setnvars( p->pSat, 1000 );
+ // var 0 is reserved for const1 node - add the clause
+// pLits[0] = toLit( 0 );
+// sat_solver_addclause( p->pSat, pLits, pLits + 1 );
+ }
+
+ // if the nodes do not have SAT variables, allocate them
+ Ivy_FraigNodeAddToSolver( p, pOld, pNew );
+
+ // prepare variable activity
+ Ivy_FraigSetActivityFactors( p, pOld, pNew );
+
+ // solve under assumptions
+ // A = 1; B = 0 OR A = 1; B = 1
+clk = clock();
+ pLits[0] = toLitCond( Ivy_ObjSatNum(pOld), 0 );
+ pLits[1] = toLitCond( Ivy_ObjSatNum(pNew), pOld->fPhase == pNew->fPhase );
+//Sat_SolverWriteDimacs( p->pSat, "temp.cnf", pLits, pLits + 2, 1 );
+ RetValue1 = sat_solver_solve( p->pSat, pLits, pLits + 2,
+ (sint64)nBTLimit, (sint64)0,
+ p->nBTLimitGlobal, p->nInsLimitGlobal );
+p->timeSat += clock() - clk;
+ if ( RetValue1 == l_False )
+ {
+p->timeSatUnsat += clock() - clk;
+ pLits[0] = lit_neg( pLits[0] );
+ pLits[1] = lit_neg( pLits[1] );
+ RetValue = sat_solver_addclause( p->pSat, pLits, pLits + 2 );
+ assert( RetValue );
+ // continue solving the other implication
+ p->nSatCallsUnsat++;
+ }
+ else if ( RetValue1 == l_True )
+ {
+p->timeSatSat += clock() - clk;
+ Ivy_FraigSavePattern( p );
+ p->nSatCallsSat++;
+ return 0;
+ }
+ else // if ( RetValue1 == l_Undef )
+ {
+p->timeSatFail += clock() - clk;
+ // mark the node as the failed node
+ if ( pOld != p->pManFraig->pConst1 )
+ pOld->fFailTfo = 1;
+ pNew->fFailTfo = 1;
+ p->nSatFailsReal++;
+ return -1;
+ }
+
+ // if the old node was constant 0, we already know the answer
+ if ( pOld == p->pManFraig->pConst1 )
+ {
+ p->nSatProof++;
+ return 1;
+ }
+
+ // solve under assumptions
+ // A = 0; B = 1 OR A = 0; B = 0
+clk = clock();
+ pLits[0] = toLitCond( Ivy_ObjSatNum(pOld), 1 );
+ pLits[1] = toLitCond( Ivy_ObjSatNum(pNew), pOld->fPhase ^ pNew->fPhase );
+ RetValue1 = sat_solver_solve( p->pSat, pLits, pLits + 2,
+ (sint64)nBTLimit, (sint64)0,
+ p->nBTLimitGlobal, p->nInsLimitGlobal );
+p->timeSat += clock() - clk;
+ if ( RetValue1 == l_False )
+ {
+p->timeSatUnsat += clock() - clk;
+ pLits[0] = lit_neg( pLits[0] );
+ pLits[1] = lit_neg( pLits[1] );
+ RetValue = sat_solver_addclause( p->pSat, pLits, pLits + 2 );
+ assert( RetValue );
+ p->nSatCallsUnsat++;
+ }
+ else if ( RetValue1 == l_True )
+ {
+p->timeSatSat += clock() - clk;
+ Ivy_FraigSavePattern( p );
+ p->nSatCallsSat++;
+ return 0;
+ }
+ else // if ( RetValue1 == l_Undef )
+ {
+p->timeSatFail += clock() - clk;
+ // mark the node as the failed node
+ pOld->fFailTfo = 1;
+ pNew->fFailTfo = 1;
+ p->nSatFailsReal++;
+ return -1;
+ }
+/*
+ // check BDD proof
+ {
+ int RetVal;
+ PRT( "Sat", clock() - clk2 );
+ clk2 = clock();
+ RetVal = Ivy_FraigNodesAreEquivBdd( pOld, pNew );
+// printf( "%d ", RetVal );
+ assert( RetVal );
+ PRT( "Bdd", clock() - clk2 );
+ printf( "\n" );
+ }
+*/
+ // return SAT proof
+ p->nSatProof++;
+ return 1;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Runs equivalence test for one node.]
+
+ Description [Returns the fraiged node.]
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Ivy_FraigNodeIsConst( Ivy_FraigMan_t * p, Ivy_Obj_t * pNew )
+{
+ int pLits[2], RetValue1, RetValue, clk;
+
+ // make sure the nodes are not complemented
+ assert( !Ivy_IsComplement(pNew) );
+ assert( pNew != p->pManFraig->pConst1 );
+ p->nSatCalls++;
+
+ // make sure the solver is allocated and has enough variables
+ if ( p->pSat == NULL )
+ {
+ p->pSat = sat_solver_new();
+ p->nSatVars = 1;
+ sat_solver_setnvars( p->pSat, 1000 );
+ // var 0 is reserved for const1 node - add the clause
+// pLits[0] = toLit( 0 );
+// sat_solver_addclause( p->pSat, pLits, pLits + 1 );
+ }
+
+ // if the nodes do not have SAT variables, allocate them
+ Ivy_FraigNodeAddToSolver( p, NULL, pNew );
+
+ // prepare variable activity
+ Ivy_FraigSetActivityFactors( p, NULL, pNew );
+
+ // solve under assumptions
+clk = clock();
+ pLits[0] = toLitCond( Ivy_ObjSatNum(pNew), pNew->fPhase );
+ RetValue1 = sat_solver_solve( p->pSat, pLits, pLits + 1,
+ (sint64)p->pParams->nBTLimitMiter, (sint64)0,
+ p->nBTLimitGlobal, p->nInsLimitGlobal );
+p->timeSat += clock() - clk;
+ if ( RetValue1 == l_False )
+ {
+p->timeSatUnsat += clock() - clk;
+ pLits[0] = lit_neg( pLits[0] );
+ RetValue = sat_solver_addclause( p->pSat, pLits, pLits + 1 );
+ assert( RetValue );
+ // continue solving the other implication
+ p->nSatCallsUnsat++;
+ }
+ else if ( RetValue1 == l_True )
+ {
+p->timeSatSat += clock() - clk;
+ if ( p->pPatWords )
+ Ivy_FraigSavePattern( p );
+ p->nSatCallsSat++;
+ return 0;
+ }
+ else // if ( RetValue1 == l_Undef )
+ {
+p->timeSatFail += clock() - clk;
+ // mark the node as the failed node
+ pNew->fFailTfo = 1;
+ p->nSatFailsReal++;
+ return -1;
+ }
+
+ // return SAT proof
+ p->nSatProof++;
+ return 1;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Addes clauses to the solver.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Ivy_FraigAddClausesMux( Ivy_FraigMan_t * p, Ivy_Obj_t * pNode )
+{
+ Ivy_Obj_t * pNodeI, * pNodeT, * pNodeE;
+ int pLits[4], RetValue, VarF, VarI, VarT, VarE, fCompT, fCompE;
+
+ assert( !Ivy_IsComplement( pNode ) );
+ assert( Ivy_ObjIsMuxType( pNode ) );
+ // get nodes (I = if, T = then, E = else)
+ pNodeI = Ivy_ObjRecognizeMux( pNode, &pNodeT, &pNodeE );
+ // get the variable numbers
+ VarF = Ivy_ObjSatNum(pNode);
+ VarI = Ivy_ObjSatNum(pNodeI);
+ VarT = Ivy_ObjSatNum(Ivy_Regular(pNodeT));
+ VarE = Ivy_ObjSatNum(Ivy_Regular(pNodeE));
+ // get the complementation flags
+ fCompT = Ivy_IsComplement(pNodeT);
+ fCompE = Ivy_IsComplement(pNodeE);
+
+ // f = ITE(i, t, e)
+
+ // i' + t' + f
+ // i' + t + f'
+ // i + e' + f
+ // i + e + f'
+
+ // create four clauses
+ pLits[0] = toLitCond(VarI, 1);
+ pLits[1] = toLitCond(VarT, 1^fCompT);
+ pLits[2] = toLitCond(VarF, 0);
+ RetValue = sat_solver_addclause( p->pSat, pLits, pLits + 3 );
+ assert( RetValue );
+ pLits[0] = toLitCond(VarI, 1);
+ pLits[1] = toLitCond(VarT, 0^fCompT);
+ pLits[2] = toLitCond(VarF, 1);
+ RetValue = sat_solver_addclause( p->pSat, pLits, pLits + 3 );
+ assert( RetValue );
+ pLits[0] = toLitCond(VarI, 0);
+ pLits[1] = toLitCond(VarE, 1^fCompE);
+ pLits[2] = toLitCond(VarF, 0);
+ RetValue = sat_solver_addclause( p->pSat, pLits, pLits + 3 );
+ assert( RetValue );
+ pLits[0] = toLitCond(VarI, 0);
+ pLits[1] = toLitCond(VarE, 0^fCompE);
+ pLits[2] = toLitCond(VarF, 1);
+ RetValue = sat_solver_addclause( p->pSat, pLits, pLits + 3 );
+ assert( RetValue );
+
+ // two additional clauses
+ // t' & e' -> f'
+ // t & e -> f
+
+ // t + e + f'
+ // t' + e' + f
+
+ if ( VarT == VarE )
+ {
+// assert( fCompT == !fCompE );
+ return;
+ }
+
+ pLits[0] = toLitCond(VarT, 0^fCompT);
+ pLits[1] = toLitCond(VarE, 0^fCompE);
+ pLits[2] = toLitCond(VarF, 1);
+ RetValue = sat_solver_addclause( p->pSat, pLits, pLits + 3 );
+ assert( RetValue );
+ pLits[0] = toLitCond(VarT, 1^fCompT);
+ pLits[1] = toLitCond(VarE, 1^fCompE);
+ pLits[2] = toLitCond(VarF, 0);
+ RetValue = sat_solver_addclause( p->pSat, pLits, pLits + 3 );
+ assert( RetValue );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Addes clauses to the solver.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Ivy_FraigAddClausesSuper( Ivy_FraigMan_t * p, Ivy_Obj_t * pNode, Vec_Ptr_t * vSuper )
+{
+ Ivy_Obj_t * pFanin;
+ int * pLits, nLits, RetValue, i;
+ assert( !Ivy_IsComplement(pNode) );
+ assert( Ivy_ObjIsNode( pNode ) );
+ // create storage for literals
+ nLits = Vec_PtrSize(vSuper) + 1;
+ pLits = ALLOC( int, nLits );
+ // suppose AND-gate is A & B = C
+ // add !A => !C or A + !C
+ Vec_PtrForEachEntry( vSuper, pFanin, i )
+ {
+ pLits[0] = toLitCond(Ivy_ObjSatNum(Ivy_Regular(pFanin)), Ivy_IsComplement(pFanin));
+ pLits[1] = toLitCond(Ivy_ObjSatNum(pNode), 1);
+ RetValue = sat_solver_addclause( p->pSat, pLits, pLits + 2 );
+ assert( RetValue );
+ }
+ // add A & B => C or !A + !B + C
+ Vec_PtrForEachEntry( vSuper, pFanin, i )
+ pLits[i] = toLitCond(Ivy_ObjSatNum(Ivy_Regular(pFanin)), !Ivy_IsComplement(pFanin));
+ pLits[nLits-1] = toLitCond(Ivy_ObjSatNum(pNode), 0);
+ RetValue = sat_solver_addclause( p->pSat, pLits, pLits + nLits );
+ assert( RetValue );
+ free( pLits );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Collects the supergate.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Ivy_FraigCollectSuper_rec( Ivy_Obj_t * pObj, Vec_Ptr_t * vSuper, int fFirst, int fUseMuxes )
+{
+ // if the new node is complemented or a PI, another gate begins
+ if ( Ivy_IsComplement(pObj) || Ivy_ObjIsPi(pObj) || (!fFirst && Ivy_ObjRefs(pObj) > 1) ||
+ (fUseMuxes && Ivy_ObjIsMuxType(pObj)) )
+ {
+ Vec_PtrPushUnique( vSuper, pObj );
+ return;
+ }
+ // go through the branches
+ Ivy_FraigCollectSuper_rec( Ivy_ObjChild0(pObj), vSuper, 0, fUseMuxes );
+ Ivy_FraigCollectSuper_rec( Ivy_ObjChild1(pObj), vSuper, 0, fUseMuxes );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Collects the supergate.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Vec_Ptr_t * Ivy_FraigCollectSuper( Ivy_Obj_t * pObj, int fUseMuxes )
+{
+ Vec_Ptr_t * vSuper;
+ assert( !Ivy_IsComplement(pObj) );
+ assert( !Ivy_ObjIsPi(pObj) );
+ vSuper = Vec_PtrAlloc( 4 );
+ Ivy_FraigCollectSuper_rec( pObj, vSuper, 1, fUseMuxes );
+ return vSuper;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Updates the solver clause database.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Ivy_FraigObjAddToFrontier( Ivy_FraigMan_t * p, Ivy_Obj_t * pObj, Vec_Ptr_t * vFrontier )
+{
+ assert( !Ivy_IsComplement(pObj) );
+ if ( Ivy_ObjSatNum(pObj) )
+ return;
+ assert( Ivy_ObjSatNum(pObj) == 0 );
+ assert( Ivy_ObjFaninVec(pObj) == NULL );
+ if ( Ivy_ObjIsConst1(pObj) )
+ return;
+//printf( "Assigning node %d number %d\n", pObj->Id, p->nSatVars );
+ Ivy_ObjSetSatNum( pObj, p->nSatVars++ );
+ if ( Ivy_ObjIsNode(pObj) )
+ Vec_PtrPush( vFrontier, pObj );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Updates the solver clause database.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Ivy_FraigNodeAddToSolver( Ivy_FraigMan_t * p, Ivy_Obj_t * pOld, Ivy_Obj_t * pNew )
+{
+ Vec_Ptr_t * vFrontier, * vFanins;
+ Ivy_Obj_t * pNode, * pFanin;
+ int i, k, fUseMuxes = 1;
+ assert( pOld || pNew );
+ // quit if CNF is ready
+ if ( (!pOld || Ivy_ObjFaninVec(pOld)) && (!pNew || Ivy_ObjFaninVec(pNew)) )
+ return;
+ // start the frontier
+ vFrontier = Vec_PtrAlloc( 100 );
+ if ( pOld ) Ivy_FraigObjAddToFrontier( p, pOld, vFrontier );
+ if ( pNew ) Ivy_FraigObjAddToFrontier( p, pNew, vFrontier );
+ // explore nodes in the frontier
+ Vec_PtrForEachEntry( vFrontier, pNode, i )
+ {
+ // create the supergate
+ assert( Ivy_ObjSatNum(pNode) );
+ assert( Ivy_ObjFaninVec(pNode) == NULL );
+ if ( fUseMuxes && Ivy_ObjIsMuxType(pNode) )
+ {
+ vFanins = Vec_PtrAlloc( 4 );
+ Vec_PtrPushUnique( vFanins, Ivy_ObjFanin0( Ivy_ObjFanin0(pNode) ) );
+ Vec_PtrPushUnique( vFanins, Ivy_ObjFanin0( Ivy_ObjFanin1(pNode) ) );
+ Vec_PtrPushUnique( vFanins, Ivy_ObjFanin1( Ivy_ObjFanin0(pNode) ) );
+ Vec_PtrPushUnique( vFanins, Ivy_ObjFanin1( Ivy_ObjFanin1(pNode) ) );
+ Vec_PtrForEachEntry( vFanins, pFanin, k )
+ Ivy_FraigObjAddToFrontier( p, Ivy_Regular(pFanin), vFrontier );
+ Ivy_FraigAddClausesMux( p, pNode );
+ }
+ else
+ {
+ vFanins = Ivy_FraigCollectSuper( pNode, fUseMuxes );
+ Vec_PtrForEachEntry( vFanins, pFanin, k )
+ Ivy_FraigObjAddToFrontier( p, Ivy_Regular(pFanin), vFrontier );
+ Ivy_FraigAddClausesSuper( p, pNode, vFanins );
+ }
+ assert( Vec_PtrSize(vFanins) > 1 );
+ Ivy_ObjSetFaninVec( pNode, vFanins );
+ }
+ Vec_PtrFree( vFrontier );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Sets variable activities in the cone.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Ivy_FraigSetActivityFactors_rec( Ivy_FraigMan_t * p, Ivy_Obj_t * pObj, int LevelMin, int LevelMax )
+{
+ Vec_Ptr_t * vFanins;
+ Ivy_Obj_t * pFanin;
+ int i, Counter = 0;
+ assert( !Ivy_IsComplement(pObj) );
+ assert( Ivy_ObjSatNum(pObj) );
+ // skip visited variables
+ if ( Ivy_ObjIsTravIdCurrent(p->pManFraig, pObj) )
+ return 0;
+ Ivy_ObjSetTravIdCurrent(p->pManFraig, pObj);
+ // add the PI to the list
+ if ( pObj->Level <= (unsigned)LevelMin || Ivy_ObjIsPi(pObj) )
+ return 0;
+ // set the factor of this variable
+ // (LevelMax-LevelMin) / (pObj->Level-LevelMin) = p->pParams->dActConeBumpMax / ThisBump
+ p->pSat->factors[Ivy_ObjSatNum(pObj)] = p->pParams->dActConeBumpMax * (pObj->Level - LevelMin)/(LevelMax - LevelMin);
+ veci_push(&p->pSat->act_vars, Ivy_ObjSatNum(pObj));
+ // explore the fanins
+ vFanins = Ivy_ObjFaninVec( pObj );
+ Vec_PtrForEachEntry( vFanins, pFanin, i )
+ Counter += Ivy_FraigSetActivityFactors_rec( p, Ivy_Regular(pFanin), LevelMin, LevelMax );
+ return 1 + Counter;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Sets variable activities in the cone.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Ivy_FraigSetActivityFactors( Ivy_FraigMan_t * p, Ivy_Obj_t * pOld, Ivy_Obj_t * pNew )
+{
+ int clk, LevelMin, LevelMax;
+ assert( pOld || pNew );
+clk = clock();
+ // reset the active variables
+ veci_resize(&p->pSat->act_vars, 0);
+ // prepare for traversal
+ Ivy_ManIncrementTravId( p->pManFraig );
+ // determine the min and max level to visit
+ assert( p->pParams->dActConeRatio > 0 && p->pParams->dActConeRatio < 1 );
+ LevelMax = IVY_MAX( (pNew ? pNew->Level : 0), (pOld ? pOld->Level : 0) );
+ LevelMin = (int)(LevelMax * (1.0 - p->pParams->dActConeRatio));
+ // traverse
+ if ( pOld && !Ivy_ObjIsConst1(pOld) )
+ Ivy_FraigSetActivityFactors_rec( p, pOld, LevelMin, LevelMax );
+ if ( pNew && !Ivy_ObjIsConst1(pNew) )
+ Ivy_FraigSetActivityFactors_rec( p, pNew, LevelMin, LevelMax );
+//Ivy_FraigPrintActivity( p );
+p->timeTrav += clock() - clk;
+ return 1;
+}
+
+
+
+#include "cuddInt.h"
+
+/**Function*************************************************************
+
+ Synopsis [Checks equivalence using BDDs.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+DdNode * Ivy_FraigNodesAreEquivBdd_int( DdManager * dd, DdNode * bFunc, Vec_Ptr_t * vFront, int Level )
+{
+ DdNode ** pFuncs;
+ DdNode * bFuncNew;
+ Vec_Ptr_t * vTemp;
+ Ivy_Obj_t * pObj, * pFanin;
+ int i, NewSize;
+ // create new frontier
+ vTemp = Vec_PtrAlloc( 100 );
+ Vec_PtrForEachEntry( vFront, pObj, i )
+ {
+ if ( (int)pObj->Level != Level )
+ {
+ pObj->fMarkB = 1;
+ pObj->TravId = Vec_PtrSize(vTemp);
+ Vec_PtrPush( vTemp, pObj );
+ continue;
+ }
+
+ pFanin = Ivy_ObjFanin0(pObj);
+ if ( pFanin->fMarkB == 0 )
+ {
+ pFanin->fMarkB = 1;
+ pFanin->TravId = Vec_PtrSize(vTemp);
+ Vec_PtrPush( vTemp, pFanin );
+ }
+
+ pFanin = Ivy_ObjFanin1(pObj);
+ if ( pFanin->fMarkB == 0 )
+ {
+ pFanin->fMarkB = 1;
+ pFanin->TravId = Vec_PtrSize(vTemp);
+ Vec_PtrPush( vTemp, pFanin );
+ }
+ }
+ // collect the permutation
+ NewSize = IVY_MAX(dd->size, Vec_PtrSize(vTemp));
+ pFuncs = ALLOC( DdNode *, NewSize );
+ Vec_PtrForEachEntry( vFront, pObj, i )
+ {
+ if ( (int)pObj->Level != Level )
+ pFuncs[i] = Cudd_bddIthVar( dd, pObj->TravId );
+ else
+ pFuncs[i] = Cudd_bddAnd( dd,
+ Cudd_NotCond( Cudd_bddIthVar(dd, Ivy_ObjFanin0(pObj)->TravId), Ivy_ObjFaninC0(pObj) ),
+ Cudd_NotCond( Cudd_bddIthVar(dd, Ivy_ObjFanin1(pObj)->TravId), Ivy_ObjFaninC1(pObj) ) );
+ Cudd_Ref( pFuncs[i] );
+ }
+ // add the remaining vars
+ assert( NewSize == dd->size );
+ for ( i = Vec_PtrSize(vFront); i < dd->size; i++ )
+ {
+ pFuncs[i] = Cudd_bddIthVar( dd, i );
+ Cudd_Ref( pFuncs[i] );
+ }
+
+ // create new
+ bFuncNew = Cudd_bddVectorCompose( dd, bFunc, pFuncs ); Cudd_Ref( bFuncNew );
+ // clean trav Id
+ Vec_PtrForEachEntry( vTemp, pObj, i )
+ {
+ pObj->fMarkB = 0;
+ pObj->TravId = 0;
+ }
+ // deref
+ for ( i = 0; i < dd->size; i++ )
+ Cudd_RecursiveDeref( dd, pFuncs[i] );
+ free( pFuncs );
+
+ free( vFront->pArray );
+ *vFront = *vTemp;
+
+ vTemp->nCap = vTemp->nSize = 0;
+ vTemp->pArray = NULL;
+ Vec_PtrFree( vTemp );
+
+ Cudd_Deref( bFuncNew );
+ return bFuncNew;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Checks equivalence using BDDs.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Ivy_FraigNodesAreEquivBdd( Ivy_Obj_t * pObj1, Ivy_Obj_t * pObj2 )
+{
+ static DdManager * dd = NULL;
+ DdNode * bFunc, * bTemp;
+ Vec_Ptr_t * vFront;
+ Ivy_Obj_t * pObj;
+ int i, RetValue, Iter, Level;
+ // start the manager
+ if ( dd == NULL )
+ dd = Cudd_Init( 50, 0, CUDD_UNIQUE_SLOTS, CUDD_CACHE_SLOTS, 0 );
+ // create front
+ vFront = Vec_PtrAlloc( 100 );
+ Vec_PtrPush( vFront, pObj1 );
+ Vec_PtrPush( vFront, pObj2 );
+ // get the function
+ bFunc = Cudd_bddXor( dd, Cudd_bddIthVar(dd,0), Cudd_bddIthVar(dd,1) ); Cudd_Ref( bFunc );
+ bFunc = Cudd_NotCond( bFunc, pObj1->fPhase != pObj2->fPhase );
+ // try running BDDs
+ for ( Iter = 0; ; Iter++ )
+ {
+ // find max level
+ Level = 0;
+ Vec_PtrForEachEntry( vFront, pObj, i )
+ if ( Level < (int)pObj->Level )
+ Level = (int)pObj->Level;
+ if ( Level == 0 )
+ break;
+ bFunc = Ivy_FraigNodesAreEquivBdd_int( dd, bTemp = bFunc, vFront, Level ); Cudd_Ref( bFunc );
+ Cudd_RecursiveDeref( dd, bTemp );
+ if ( bFunc == Cudd_ReadLogicZero(dd) ) // proved
+ {printf( "%d", Iter ); break;}
+ if ( Cudd_DagSize(bFunc) > 1000 )
+ {printf( "b" ); break;}
+ if ( dd->size > 120 )
+ {printf( "s" ); break;}
+ if ( Iter > 50 )
+ {printf( "i" ); break;}
+ }
+ if ( bFunc == Cudd_ReadLogicZero(dd) ) // unsat
+ RetValue = 1;
+ else if ( Level == 0 ) // sat
+ RetValue = 0;
+ else
+ RetValue = -1; // spaceout/timeout
+ Cudd_RecursiveDeref( dd, bFunc );
+ Vec_PtrFree( vFront );
+ return RetValue;
+}
+
+////////////////////////////////////////////////////////////////////////
+/// END OF FILE ///
+////////////////////////////////////////////////////////////////////////
+
+
diff --git a/src/aig/ivy/ivyHaig.c b/src/aig/ivy/ivyHaig.c
new file mode 100644
index 00000000..87021600
--- /dev/null
+++ b/src/aig/ivy/ivyHaig.c
@@ -0,0 +1,530 @@
+/**CFile****************************************************************
+
+ FileName [ivyHaig.c]
+
+ SystemName [ABC: Logic synthesis and verification system.]
+
+ PackageName [And-Inverter Graph package.]
+
+ Synopsis [HAIG management procedures.]
+
+ Author [Alan Mishchenko]
+
+ Affiliation [UC Berkeley]
+
+ Date [Ver. 1.0. Started - May 11, 2006.]
+
+ Revision [$Id: ivyHaig.c,v 1.00 2006/05/11 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "ivy.h"
+
+////////////////////////////////////////////////////////////////////////
+/// DECLARATIONS ///
+////////////////////////////////////////////////////////////////////////
+
+/*
+ HAIGing rules in working AIG:
+ - Each node in the working AIG has a pointer to the corresponding node in HAIG
+ (this node is not necessarily the representative of the equivalence class of HAIG nodes)
+ - This pointer is complemented if the AIG node and its corresponding HAIG node have different phase
+
+ Choice node rules in HAIG:
+ - Equivalent nodes are linked into a ring
+ - Exactly one node in the ring has fanouts (this node is called the representative)
+ - The pointer going from a node to the next node in the ring is complemented
+ if the first node is complemented, compared to the representative node of the equivalence class
+ - (consequence of the above) The representative node always has non-complemented pointer to the next node
+ - New nodes are inserted into the ring immediately after the representative node
+*/
+
+// returns the representative node of the given HAIG node
+static inline Ivy_Obj_t * Ivy_HaigObjRepr( Ivy_Obj_t * pObj )
+{
+ Ivy_Obj_t * pTemp;
+ assert( !Ivy_IsComplement(pObj) );
+ // if the node has no equivalent node or has fanout, it is representative
+ if ( pObj->pEquiv == NULL || Ivy_ObjRefs(pObj) > 0 )
+ return pObj;
+ // the node belongs to a class and is not a representative
+ // complemented edge (pObj->pEquiv) tells if it is complemented w.r.t. the repr
+ for ( pTemp = Ivy_Regular(pObj->pEquiv); pTemp != pObj; pTemp = Ivy_Regular(pTemp->pEquiv) )
+ if ( Ivy_ObjRefs(pTemp) > 0 )
+ break;
+ // return the representative node
+ assert( Ivy_ObjRefs(pTemp) > 0 );
+ return Ivy_NotCond( pTemp, Ivy_IsComplement(pObj->pEquiv) );
+}
+
+// counts the number of nodes in the equivalence class
+static inline int Ivy_HaigObjCountClass( Ivy_Obj_t * pObj )
+{
+ Ivy_Obj_t * pTemp;
+ int Counter;
+ assert( !Ivy_IsComplement(pObj) );
+ assert( Ivy_ObjRefs(pObj) > 0 );
+ if ( pObj->pEquiv == NULL )
+ return 1;
+ assert( !Ivy_IsComplement(pObj->pEquiv) );
+ Counter = 1;
+ for ( pTemp = pObj->pEquiv; pTemp != pObj; pTemp = Ivy_Regular(pTemp->pEquiv) )
+ Counter++;
+ return Counter;
+}
+
+////////////////////////////////////////////////////////////////////////
+/// FUNCTION DEFINITIONS ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+ Synopsis [Starts HAIG for the manager.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Ivy_ManHaigStart( Ivy_Man_t * p, int fVerbose )
+{
+ Vec_Int_t * vLatches;
+ Ivy_Obj_t * pObj;
+ int i;
+ assert( p->pHaig == NULL );
+ p->pHaig = Ivy_ManDup( p );
+
+ if ( fVerbose )
+ {
+ printf( "Starting : " );
+ Ivy_ManPrintStats( p->pHaig );
+ }
+
+ // collect latches of design D and set their values to be DC
+ vLatches = Vec_IntAlloc( 100 );
+ Ivy_ManForEachLatch( p->pHaig, pObj, i )
+ {
+ pObj->Init = IVY_INIT_DC;
+ Vec_IntPush( vLatches, pObj->Id );
+ }
+ p->pHaig->pData = vLatches;
+/*
+ {
+ int x;
+ Ivy_ManShow( p, 0, NULL );
+ Ivy_ManShow( p->pHaig, 1, NULL );
+ x = 0;
+ }
+*/
+}
+
+/**Function*************************************************************
+
+ Synopsis [Transfers the HAIG to the newly created manager.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Ivy_ManHaigTrasfer( Ivy_Man_t * p, Ivy_Man_t * pNew )
+{
+ Ivy_Obj_t * pObj;
+ int i;
+ assert( p->pHaig != NULL );
+ Ivy_ManConst1(pNew)->pEquiv = Ivy_ManConst1(p)->pEquiv;
+ Ivy_ManForEachPi( pNew, pObj, i )
+ pObj->pEquiv = Ivy_ManPi( p, i )->pEquiv;
+ pNew->pHaig = p->pHaig;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Stops HAIG for the manager.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Ivy_ManHaigStop( Ivy_Man_t * p )
+{
+ Ivy_Obj_t * pObj;
+ int i;
+ assert( p->pHaig != NULL );
+ Vec_IntFree( p->pHaig->pData );
+ Ivy_ManStop( p->pHaig );
+ p->pHaig = NULL;
+ // remove dangling pointers to the HAIG objects
+ Ivy_ManForEachObj( p, pObj, i )
+ pObj->pEquiv = NULL;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Creates a new node in HAIG.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Ivy_ManHaigCreateObj( Ivy_Man_t * p, Ivy_Obj_t * pObj )
+{
+ Ivy_Obj_t * pEquiv0, * pEquiv1;
+ assert( p->pHaig != NULL );
+ assert( !Ivy_IsComplement(pObj) );
+ if ( Ivy_ObjType(pObj) == IVY_BUF )
+ pObj->pEquiv = Ivy_ObjChild0Equiv(pObj);
+ else if ( Ivy_ObjType(pObj) == IVY_LATCH )
+ {
+// pObj->pEquiv = Ivy_Latch( p->pHaig, Ivy_ObjChild0Equiv(pObj), pObj->Init );
+ pEquiv0 = Ivy_ObjChild0Equiv(pObj);
+ pEquiv0 = Ivy_NotCond( Ivy_HaigObjRepr(Ivy_Regular(pEquiv0)), Ivy_IsComplement(pEquiv0) );
+ pObj->pEquiv = Ivy_Latch( p->pHaig, pEquiv0, pObj->Init );
+ }
+ else if ( Ivy_ObjType(pObj) == IVY_AND )
+ {
+// pObj->pEquiv = Ivy_And( p->pHaig, Ivy_ObjChild0Equiv(pObj), Ivy_ObjChild1Equiv(pObj) );
+ pEquiv0 = Ivy_ObjChild0Equiv(pObj);
+ pEquiv0 = Ivy_NotCond( Ivy_HaigObjRepr(Ivy_Regular(pEquiv0)), Ivy_IsComplement(pEquiv0) );
+ pEquiv1 = Ivy_ObjChild1Equiv(pObj);
+ pEquiv1 = Ivy_NotCond( Ivy_HaigObjRepr(Ivy_Regular(pEquiv1)), Ivy_IsComplement(pEquiv1) );
+ pObj->pEquiv = Ivy_And( p->pHaig, pEquiv0, pEquiv1 );
+ }
+ else assert( 0 );
+ // make sure the node points to the representative
+// pObj->pEquiv = Ivy_NotCond( Ivy_HaigObjRepr(Ivy_Regular(pObj->pEquiv)), Ivy_IsComplement(pObj->pEquiv) );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Checks if the old node is in the TFI of the new node.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Ivy_ObjIsInTfi_rec( Ivy_Obj_t * pObjNew, Ivy_Obj_t * pObjOld, int Levels )
+{
+ if ( pObjNew == pObjOld )
+ return 1;
+ if ( Levels == 0 || Ivy_ObjIsCi(pObjNew) || Ivy_ObjIsConst1(pObjNew) )
+ return 0;
+ if ( Ivy_ObjIsInTfi_rec( Ivy_ObjFanin0(pObjNew), pObjOld, Levels - 1 ) )
+ return 1;
+ if ( Ivy_ObjIsNode(pObjNew) && Ivy_ObjIsInTfi_rec( Ivy_ObjFanin1(pObjNew), pObjOld, Levels - 1 ) )
+ return 1;
+ return 0;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Sets the pair of equivalent nodes in HAIG.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Ivy_ManHaigCreateChoice( Ivy_Man_t * p, Ivy_Obj_t * pObjOld, Ivy_Obj_t * pObjNew )
+{
+ Ivy_Obj_t * pObjOldHaig, * pObjNewHaig;
+ Ivy_Obj_t * pObjOldHaigR, * pObjNewHaigR;
+ int fCompl;
+//printf( "\nCreating choice for %d and %d in AIG\n", pObjOld->Id, Ivy_Regular(pObjNew)->Id );
+
+ assert( p->pHaig != NULL );
+ assert( !Ivy_IsComplement(pObjOld) );
+ // get pointers to the representatives of pObjOld and pObjNew
+ pObjOldHaig = pObjOld->pEquiv;
+ pObjNewHaig = Ivy_NotCond( Ivy_Regular(pObjNew)->pEquiv, Ivy_IsComplement(pObjNew) );
+ // get the classes
+ pObjOldHaig = Ivy_NotCond( Ivy_HaigObjRepr(Ivy_Regular(pObjOldHaig)), Ivy_IsComplement(pObjOldHaig) );
+ pObjNewHaig = Ivy_NotCond( Ivy_HaigObjRepr(Ivy_Regular(pObjNewHaig)), Ivy_IsComplement(pObjNewHaig) );
+ // get regular pointers
+ pObjOldHaigR = Ivy_Regular(pObjOldHaig);
+ pObjNewHaigR = Ivy_Regular(pObjNewHaig);
+ // check if there is phase difference between them
+ fCompl = (Ivy_IsComplement(pObjOldHaig) != Ivy_IsComplement(pObjNewHaig));
+ // if the class is the same, nothing to do
+ if ( pObjOldHaigR == pObjNewHaigR )
+ return;
+ // if the second node belongs to a class, do not merge classes (for the time being)
+ if ( Ivy_ObjRefs(pObjOldHaigR) == 0 || pObjNewHaigR->pEquiv != NULL ||
+ Ivy_ObjRefs(pObjNewHaigR) > 0 ) //|| Ivy_ObjIsInTfi_rec(pObjNewHaigR, pObjOldHaigR, 10) )
+ {
+/*
+ if ( pObjNewHaigR->pEquiv != NULL )
+ printf( "c" );
+ if ( Ivy_ObjRefs(pObjNewHaigR) > 0 )
+ printf( "f" );
+ printf( " " );
+*/
+ p->pHaig->nClassesSkip++;
+ return;
+ }
+
+ // add this node to the class of pObjOldHaig
+ assert( Ivy_ObjRefs(pObjOldHaigR) > 0 );
+ assert( !Ivy_IsComplement(pObjOldHaigR->pEquiv) );
+ if ( pObjOldHaigR->pEquiv == NULL )
+ pObjNewHaigR->pEquiv = Ivy_NotCond( pObjOldHaigR, fCompl );
+ else
+ pObjNewHaigR->pEquiv = Ivy_NotCond( pObjOldHaigR->pEquiv, fCompl );
+ pObjOldHaigR->pEquiv = pObjNewHaigR;
+//printf( "Setting choice node %d -> %d.\n", pObjOldHaigR->Id, pObjNewHaigR->Id );
+ // update the class of the new node
+// Ivy_Regular(pObjNew)->pEquiv = Ivy_NotCond( pObjOldHaigR, fCompl ^ Ivy_IsComplement(pObjNew) );
+//printf( "Creating choice for %d and %d in HAIG\n", pObjOldHaigR->Id, pObjNewHaigR->Id );
+
+// if ( pObjOldHaigR->Id == 13 )
+// {
+// Ivy_ManShow( p, 0 );
+// Ivy_ManShow( p->pHaig, 1 );
+// }
+// if ( !Ivy_ManIsAcyclic( p->pHaig ) )
+// printf( "HAIG contains a cycle\n" );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Count the number of choices and choice nodes in HAIG.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Ivy_ManHaigCountChoices( Ivy_Man_t * p, int * pnChoices )
+{
+ Ivy_Obj_t * pObj;
+ int nChoices, nChoiceNodes, Counter, i;
+ assert( p->pHaig != NULL );
+ nChoices = nChoiceNodes = 0;
+ Ivy_ManForEachObj( p->pHaig, pObj, i )
+ {
+ if ( Ivy_ObjIsTerm(pObj) || i == 0 )
+ continue;
+ if ( Ivy_ObjRefs(pObj) == 0 )
+ continue;
+ Counter = Ivy_HaigObjCountClass( pObj );
+ nChoiceNodes += (int)(Counter > 1);
+ nChoices += Counter - 1;
+// if ( Counter > 1 )
+// printf( "Choice node %d %s\n", pObj->Id, Ivy_ObjIsLatch(pObj)? "(latch)": "" );
+ }
+ *pnChoices = nChoices;
+ return nChoiceNodes;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Prints statistics of the HAIG.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Ivy_ManHaigPostprocess( Ivy_Man_t * p, int fVerbose )
+{
+ int nChoices, nChoiceNodes;
+
+ assert( p->pHaig != NULL );
+
+ if ( fVerbose )
+ {
+ printf( "Final : " );
+ Ivy_ManPrintStats( p );
+ printf( "HAIG : " );
+ Ivy_ManPrintStats( p->pHaig );
+
+ // print choice node stats
+ nChoiceNodes = Ivy_ManHaigCountChoices( p, &nChoices );
+ printf( "Total choice nodes = %d. Total choices = %d. Skipped classes = %d.\n",
+ nChoiceNodes, nChoices, p->pHaig->nClassesSkip );
+ }
+
+ if ( Ivy_ManIsAcyclic( p->pHaig ) )
+ {
+ if ( fVerbose )
+ printf( "HAIG is acyclic\n" );
+ }
+ else
+ printf( "HAIG contains a cycle\n" );
+
+// if ( fVerbose )
+// Ivy_ManHaigSimulate( p );
+}
+
+
+/**Function*************************************************************
+
+ Synopsis [Applies the simulation rules.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+static inline Ivy_Init_t Ivy_ManHaigSimulateAnd( Ivy_Init_t In0, Ivy_Init_t In1 )
+{
+ assert( In0 != IVY_INIT_NONE && In1 != IVY_INIT_NONE );
+ if ( In0 == IVY_INIT_DC || In1 == IVY_INIT_DC )
+ return IVY_INIT_DC;
+ if ( In0 == IVY_INIT_1 && In1 == IVY_INIT_1 )
+ return IVY_INIT_1;
+ return IVY_INIT_0;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Applies the simulation rules.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+static inline Ivy_Init_t Ivy_ManHaigSimulateChoice( Ivy_Init_t In0, Ivy_Init_t In1 )
+{
+ assert( In0 != IVY_INIT_NONE && In1 != IVY_INIT_NONE );
+ if ( (In0 == IVY_INIT_0 && In1 == IVY_INIT_1) || (In0 == IVY_INIT_1 && In1 == IVY_INIT_0) )
+ {
+ printf( "Compatibility fails.\n" );
+ return IVY_INIT_0;
+ }
+ if ( In0 == IVY_INIT_DC && In1 == IVY_INIT_DC )
+ return IVY_INIT_DC;
+ if ( In0 != IVY_INIT_DC )
+ return In0;
+ return In1;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Simulate HAIG using modified 3-valued simulation.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Ivy_ManHaigSimulate( Ivy_Man_t * p )
+{
+ Vec_Int_t * vNodes, * vLatches, * vLatchesD;
+ Ivy_Obj_t * pObj, * pTemp;
+ Ivy_Init_t In0, In1;
+ int i, k, Counter;
+ int fVerbose = 0;
+
+ // check choices
+ Ivy_ManCheckChoices( p );
+
+ // switch to HAIG
+ assert( p->pHaig != NULL );
+ p = p->pHaig;
+
+if ( fVerbose )
+Ivy_ManForEachPi( p, pObj, i )
+printf( "Setting PI %d\n", pObj->Id );
+
+ // collect latches and nodes in the DFS order
+ vNodes = Ivy_ManDfsSeq( p, &vLatches );
+
+if ( fVerbose )
+Ivy_ManForEachNodeVec( p, vNodes, pObj, i )
+printf( "Collected node %d with fanins %d and %d\n", pObj->Id, Ivy_ObjFanin0(pObj)->Id, Ivy_ObjFanin1(pObj)->Id );
+
+ // set the PI values
+ Ivy_ManConst1(p)->Init = IVY_INIT_1;
+ Ivy_ManForEachPi( p, pObj, i )
+ pObj->Init = IVY_INIT_0;
+
+ // set the latch values
+ Ivy_ManForEachNodeVec( p, vLatches, pObj, i )
+ pObj->Init = IVY_INIT_DC;
+ // set the latches of D to be determinate
+ vLatchesD = p->pData;
+ Ivy_ManForEachNodeVec( p, vLatchesD, pObj, i )
+ pObj->Init = IVY_INIT_0;
+
+ // perform several rounds of simulation
+ for ( k = 0; k < 10; k++ )
+ {
+ // count the number of non-determinate values
+ Counter = 0;
+ Ivy_ManForEachNodeVec( p, vLatches, pObj, i )
+ Counter += ( pObj->Init == IVY_INIT_DC );
+ printf( "Iter %d : Non-determinate = %d\n", k, Counter );
+
+ // simulate the internal nodes
+ Ivy_ManForEachNodeVec( p, vNodes, pObj, i )
+ {
+if ( fVerbose )
+printf( "Processing node %d with fanins %d and %d\n", pObj->Id, Ivy_ObjFanin0(pObj)->Id, Ivy_ObjFanin1(pObj)->Id );
+ In0 = Ivy_InitNotCond( Ivy_ObjFanin0(pObj)->Init, Ivy_ObjFaninC0(pObj) );
+ In1 = Ivy_InitNotCond( Ivy_ObjFanin1(pObj)->Init, Ivy_ObjFaninC1(pObj) );
+ pObj->Init = Ivy_ManHaigSimulateAnd( In0, In1 );
+ // simulate the equivalence class if the node is a representative
+ if ( pObj->pEquiv && Ivy_ObjRefs(pObj) > 0 )
+ {
+if ( fVerbose )
+printf( "Processing choice node %d\n", pObj->Id );
+ In0 = pObj->Init;
+ assert( !Ivy_IsComplement(pObj->pEquiv) );
+ for ( pTemp = pObj->pEquiv; pTemp != pObj; pTemp = Ivy_Regular(pTemp->pEquiv) )
+ {
+if ( fVerbose )
+printf( "Processing secondary node %d\n", pTemp->Id );
+ In1 = Ivy_InitNotCond( pTemp->Init, Ivy_IsComplement(pTemp->pEquiv) );
+ In0 = Ivy_ManHaigSimulateChoice( In0, In1 );
+ }
+ pObj->Init = In0;
+ }
+ }
+
+ // simulate the latches
+ Ivy_ManForEachNodeVec( p, vLatches, pObj, i )
+ {
+ pObj->Level = Ivy_ObjFanin0(pObj)->Init;
+if ( fVerbose )
+printf( "Using latch %d with fanin %d\n", pObj->Id, Ivy_ObjFanin0(pObj)->Id );
+ }
+ Ivy_ManForEachNodeVec( p, vLatches, pObj, i )
+ pObj->Init = pObj->Level, pObj->Level = 0;
+ }
+ // free arrays
+ Vec_IntFree( vNodes );
+ Vec_IntFree( vLatches );
+}
+
+////////////////////////////////////////////////////////////////////////
+/// END OF FILE ///
+////////////////////////////////////////////////////////////////////////
+
+
diff --git a/src/aig/ivy/ivyMan.c b/src/aig/ivy/ivyMan.c
new file mode 100644
index 00000000..07faef85
--- /dev/null
+++ b/src/aig/ivy/ivyMan.c
@@ -0,0 +1,546 @@
+/**CFile****************************************************************
+
+ FileName [ivyMan.c]
+
+ SystemName [ABC: Logic synthesis and verification system.]
+
+ PackageName [And-Inverter Graph package.]
+
+ Synopsis [AIG manager.]
+
+ Author [Alan Mishchenko]
+
+ Affiliation [UC Berkeley]
+
+ Date [Ver. 1.0. Started - May 11, 2006.]
+
+ Revision [$Id: ivy_.c,v 1.00 2006/05/11 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "ivy.h"
+
+////////////////////////////////////////////////////////////////////////
+/// DECLARATIONS ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+/// FUNCTION DEFINITIONS ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+ Synopsis [Starts the AIG manager.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Ivy_Man_t * Ivy_ManStart()
+{
+ Ivy_Man_t * p;
+ // start the manager
+ p = ALLOC( Ivy_Man_t, 1 );
+ memset( p, 0, sizeof(Ivy_Man_t) );
+ // perform initializations
+ p->Ghost.Id = -1;
+ p->nTravIds = 1;
+ p->fCatchExor = 1;
+ // allocate arrays for nodes
+ p->vPis = Vec_PtrAlloc( 100 );
+ p->vPos = Vec_PtrAlloc( 100 );
+ p->vBufs = Vec_PtrAlloc( 100 );
+ p->vObjs = Vec_PtrAlloc( 100 );
+ // prepare the internal memory manager
+ Ivy_ManStartMemory( p );
+ // create the constant node
+ p->pConst1 = Ivy_ManFetchMemory( p );
+ p->pConst1->fPhase = 1;
+ Vec_PtrPush( p->vObjs, p->pConst1 );
+ p->nCreated = 1;
+ // start the table
+ p->nTableSize = 10007;
+ p->pTable = ALLOC( int, p->nTableSize );
+ memset( p->pTable, 0, sizeof(int) * p->nTableSize );
+ return p;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Duplicates the AIG manager.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Ivy_Man_t * Ivy_ManStartFrom( Ivy_Man_t * p )
+{
+ Ivy_Man_t * pNew;
+ Ivy_Obj_t * pObj;
+ int i;
+ // create the new manager
+ pNew = Ivy_ManStart();
+ // create the PIs
+ Ivy_ManConst1(p)->pEquiv = Ivy_ManConst1(pNew);
+ Ivy_ManForEachPi( p, pObj, i )
+ pObj->pEquiv = Ivy_ObjCreatePi(pNew);
+ return pNew;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Duplicates the AIG manager.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Ivy_Man_t * Ivy_ManDup( Ivy_Man_t * p )
+{
+ Vec_Int_t * vNodes, * vLatches;
+ Ivy_Man_t * pNew;
+ Ivy_Obj_t * pObj;
+ int i;
+ // collect latches and nodes in the DFS order
+ vNodes = Ivy_ManDfsSeq( p, &vLatches );
+ // create the new manager
+ pNew = Ivy_ManStart();
+ // create the PIs
+ Ivy_ManConst1(p)->pEquiv = Ivy_ManConst1(pNew);
+ Ivy_ManForEachPi( p, pObj, i )
+ pObj->pEquiv = Ivy_ObjCreatePi(pNew);
+ // create the fake PIs for latches
+ Ivy_ManForEachNodeVec( p, vLatches, pObj, i )
+ pObj->pEquiv = Ivy_ObjCreatePi(pNew);
+ // duplicate internal nodes
+ Ivy_ManForEachNodeVec( p, vNodes, pObj, i )
+ if ( Ivy_ObjIsBuf(pObj) )
+ pObj->pEquiv = Ivy_ObjChild0Equiv(pObj);
+ else
+ pObj->pEquiv = Ivy_And( pNew, Ivy_ObjChild0Equiv(pObj), Ivy_ObjChild1Equiv(pObj) );
+ // add the POs
+ Ivy_ManForEachPo( p, pObj, i )
+ Ivy_ObjCreatePo( pNew, Ivy_ObjChild0Equiv(pObj) );
+ // transform additional PI nodes into latches and connect them
+ Ivy_ManForEachNodeVec( p, vLatches, pObj, i )
+ {
+ assert( !Ivy_ObjFaninC0(pObj) );
+ pObj->pEquiv->Type = IVY_LATCH;
+ pObj->pEquiv->Init = pObj->Init;
+ Ivy_ObjConnect( pNew, pObj->pEquiv, Ivy_ObjChild0Equiv(pObj), NULL );
+ }
+ // shrink the arrays
+ Vec_PtrShrink( pNew->vPis, Ivy_ManPiNum(p) );
+ // update the counters of different objects
+ pNew->nObjs[IVY_PI] -= Ivy_ManLatchNum(p);
+ pNew->nObjs[IVY_LATCH] += Ivy_ManLatchNum(p);
+ // free arrays
+ Vec_IntFree( vNodes );
+ Vec_IntFree( vLatches );
+ // make sure structural hashing did not change anything
+ assert( Ivy_ManNodeNum(p) == Ivy_ManNodeNum(pNew) );
+ assert( Ivy_ManLatchNum(p) == Ivy_ManLatchNum(pNew) );
+ // check the resulting network
+ if ( !Ivy_ManCheck(pNew) )
+ printf( "Ivy_ManMakeSeq(): The check has failed.\n" );
+ return pNew;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Stops the AIG manager.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Ivy_Man_t * Ivy_ManFrames( Ivy_Man_t * pMan, int nLatches, int nFrames, int fInit, Vec_Ptr_t ** pvMapping )
+{
+ Vec_Ptr_t * vMapping;
+ Ivy_Man_t * pNew;
+ Ivy_Obj_t * pObj;
+ int i, f, nPis, nPos, nIdMax;
+ assert( Ivy_ManLatchNum(pMan) == 0 );
+ assert( nFrames > 0 );
+ // prepare the mapping
+ nPis = Ivy_ManPiNum(pMan) - nLatches;
+ nPos = Ivy_ManPoNum(pMan) - nLatches;
+ nIdMax = Ivy_ManObjIdMax(pMan);
+ // create the new manager
+ pNew = Ivy_ManStart();
+ // set the starting values of latch inputs
+ for ( i = 0; i < nLatches; i++ )
+ Ivy_ManPo(pMan, nPos+i)->pEquiv = fInit? Ivy_Not(Ivy_ManConst1(pNew)) : Ivy_ObjCreatePi(pNew);
+ // add timeframes
+ vMapping = Vec_PtrStart( nIdMax * nFrames + 1 );
+ for ( f = 0; f < nFrames; f++ )
+ {
+ // create PIs
+ Ivy_ManConst1(pMan)->pEquiv = Ivy_ManConst1(pNew);
+ for ( i = 0; i < nPis; i++ )
+ Ivy_ManPi(pMan, i)->pEquiv = Ivy_ObjCreatePi(pNew);
+ // transfer values to latch outputs
+ for ( i = 0; i < nLatches; i++ )
+ Ivy_ManPi(pMan, nPis+i)->pEquiv = Ivy_ManPo(pMan, nPos+i)->pEquiv;
+ // perform strashing
+ Ivy_ManForEachNode( pMan, pObj, i )
+ pObj->pEquiv = Ivy_And( pNew, Ivy_ObjChild0Equiv(pObj), Ivy_ObjChild1Equiv(pObj) );
+ // create POs
+ for ( i = 0; i < nPos; i++ )
+ Ivy_ManPo(pMan, i)->pEquiv = Ivy_ObjCreatePo( pNew, Ivy_ObjChild0Equiv(Ivy_ManPo(pMan, i)) );
+ // set the results of latch inputs
+ for ( i = 0; i < nLatches; i++ )
+ Ivy_ManPo(pMan, nPos+i)->pEquiv = Ivy_ObjChild0Equiv(Ivy_ManPo(pMan, nPos+i));
+ // save the pointers in this frame
+ Ivy_ManForEachObj( pMan, pObj, i )
+ Vec_PtrWriteEntry( vMapping, f * nIdMax + i, pObj->pEquiv );
+ }
+ // connect latches
+ if ( !fInit )
+ for ( i = 0; i < nLatches; i++ )
+ Ivy_ObjCreatePo( pNew, Ivy_ManPo(pMan, nPos+i)->pEquiv );
+ // remove dangling nodes
+ Ivy_ManCleanup(pNew);
+ *pvMapping = vMapping;
+ // check the resulting network
+ if ( !Ivy_ManCheck(pNew) )
+ printf( "Ivy_ManFrames(): The check has failed.\n" );
+ return pNew;
+}
+
+
+/**Function*************************************************************
+
+ Synopsis [Stops the AIG manager.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Ivy_ManStop( Ivy_Man_t * p )
+{
+ if ( p->time1 ) { PRT( "Update lev ", p->time1 ); }
+ if ( p->time2 ) { PRT( "Update levR ", p->time2 ); }
+// Ivy_TableProfile( p );
+// if ( p->vFanouts ) Ivy_ManStopFanout( p );
+ if ( p->vChunks ) Ivy_ManStopMemory( p );
+ if ( p->vRequired ) Vec_IntFree( p->vRequired );
+ if ( p->vPis ) Vec_PtrFree( p->vPis );
+ if ( p->vPos ) Vec_PtrFree( p->vPos );
+ if ( p->vBufs ) Vec_PtrFree( p->vBufs );
+ if ( p->vObjs ) Vec_PtrFree( p->vObjs );
+ free( p->pTable );
+ free( p );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Removes nodes without fanout.]
+
+ Description [Returns the number of dangling nodes removed.]
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Ivy_ManCleanup( Ivy_Man_t * p )
+{
+ Ivy_Obj_t * pNode;
+ int i, nNodesOld;
+ nNodesOld = Ivy_ManNodeNum(p);
+ Ivy_ManForEachObj( p, pNode, i )
+ if ( Ivy_ObjIsNode(pNode) || Ivy_ObjIsLatch(pNode) || Ivy_ObjIsBuf(pNode) )
+ if ( Ivy_ObjRefs(pNode) == 0 )
+ Ivy_ObjDelete_rec( p, pNode, 1 );
+//printf( "Cleanup removed %d nodes.\n", nNodesOld - Ivy_ManNodeNum(p) );
+ return nNodesOld - Ivy_ManNodeNum(p);
+}
+
+/**Function*************************************************************
+
+ Synopsis [Marks nodes reachable from the given one.]
+
+ Description [Returns the number of dangling nodes removed.]
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Ivy_ManCleanupSeq_rec( Ivy_Obj_t * pObj )
+{
+ if ( Ivy_ObjIsMarkA(pObj) )
+ return;
+ Ivy_ObjSetMarkA(pObj);
+ if ( pObj->pFanin0 != NULL )
+ Ivy_ManCleanupSeq_rec( Ivy_ObjFanin0(pObj) );
+ if ( pObj->pFanin1 != NULL )
+ Ivy_ManCleanupSeq_rec( Ivy_ObjFanin1(pObj) );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Removes logic that does not feed into POs.]
+
+ Description [Returns the number of dangling nodes removed.]
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Ivy_ManCleanupSeq( Ivy_Man_t * p )
+{
+ Vec_Ptr_t * vNodes;
+ Ivy_Obj_t * pObj;
+ int i, RetValue;
+ // mark the constant and PIs
+ Ivy_ObjSetMarkA( Ivy_ManConst1(p) );
+ Ivy_ManForEachPi( p, pObj, i )
+ Ivy_ObjSetMarkA( pObj );
+ // mark nodes visited from POs
+ Ivy_ManForEachPo( p, pObj, i )
+ Ivy_ManCleanupSeq_rec( pObj );
+ // collect unmarked nodes
+ vNodes = Vec_PtrAlloc( 100 );
+ Ivy_ManForEachObj( p, pObj, i )
+ {
+ if ( Ivy_ObjIsMarkA(pObj) )
+ Ivy_ObjClearMarkA(pObj);
+ else
+ Vec_PtrPush( vNodes, pObj );
+ }
+ if ( Vec_PtrSize(vNodes) == 0 )
+ {
+ Vec_PtrFree( vNodes );
+//printf( "Sequential sweep cleaned out %d nodes.\n", 0 );
+ return 0;
+ }
+ // disconnect the marked objects
+ Vec_PtrForEachEntry( vNodes, pObj, i )
+ Ivy_ObjDisconnect( p, pObj );
+ // remove the dangling objects
+ Vec_PtrForEachEntry( vNodes, pObj, i )
+ {
+ assert( Ivy_ObjIsNode(pObj) || Ivy_ObjIsLatch(pObj) || Ivy_ObjIsBuf(pObj) );
+ assert( Ivy_ObjRefs(pObj) == 0 );
+ // update node counters of the manager
+ p->nObjs[pObj->Type]--;
+ p->nDeleted++;
+ // delete buffer from the array of buffers
+ if ( p->fFanout && Ivy_ObjIsBuf(pObj) )
+ Vec_PtrRemove( p->vBufs, pObj );
+ // free the node
+ Vec_PtrWriteEntry( p->vObjs, pObj->Id, NULL );
+ Ivy_ManRecycleMemory( p, pObj );
+ }
+ // return the number of nodes freed
+ RetValue = Vec_PtrSize(vNodes);
+ Vec_PtrFree( vNodes );
+//printf( "Sequential sweep cleaned out %d nodes.\n", RetValue );
+ return RetValue;
+}
+
+
+/**Function*************************************************************
+
+ Synopsis [Checks if latches form self-loop.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Ivy_ManLatchIsSelfFeed_rec( Ivy_Obj_t * pLatch, Ivy_Obj_t * pLatchRoot )
+{
+ if ( !Ivy_ObjIsLatch(pLatch) && !Ivy_ObjIsBuf(pLatch) )
+ return 0;
+ if ( pLatch == pLatchRoot )
+ return 1;
+ return Ivy_ManLatchIsSelfFeed_rec( Ivy_ObjFanin0(pLatch), pLatchRoot );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Checks if latches form self-loop.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Ivy_ManLatchIsSelfFeed( Ivy_Obj_t * pLatch )
+{
+ if ( !Ivy_ObjIsLatch(pLatch) )
+ return 0;
+ return Ivy_ManLatchIsSelfFeed_rec( Ivy_ObjFanin0(pLatch), pLatch );
+}
+
+
+/**Function*************************************************************
+
+ Synopsis [Returns the number of dangling nodes removed.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Ivy_ManPropagateBuffers( Ivy_Man_t * p, int fUpdateLevel )
+{
+ Ivy_Obj_t * pNode;
+ int LimitFactor = 100;
+ int NodeBeg = Ivy_ManNodeNum(p);
+ int nSteps;
+ for ( nSteps = 0; Vec_PtrSize(p->vBufs) > 0; nSteps++ )
+ {
+ pNode = Vec_PtrEntryLast(p->vBufs);
+ while ( Ivy_ObjIsBuf(pNode) )
+ pNode = Ivy_ObjReadFirstFanout( p, pNode );
+ // check if this buffer should remain
+ if ( Ivy_ManLatchIsSelfFeed(pNode) )
+ {
+ Vec_PtrPop(p->vBufs);
+ continue;
+ }
+//printf( "Propagating buffer %d with input %d and output %d\n", Ivy_ObjFaninId0(pNode), Ivy_ObjFaninId0(Ivy_ObjFanin0(pNode)), pNode->Id );
+//printf( "Latch num %d\n", Ivy_ManLatchNum(p) );
+ Ivy_NodeFixBufferFanins( p, pNode, fUpdateLevel );
+ if ( nSteps > NodeBeg * LimitFactor )
+ {
+ printf( "Structural hashing is not finished after %d forward latch moves.\n", NodeBeg * LimitFactor );
+ printf( "This circuit cannot be forward-retimed completely. Quitting.\n" );
+ break;
+ }
+ }
+// printf( "Number of steps = %d. Nodes beg = %d. Nodes end = %d.\n", nSteps, NodeBeg, Ivy_ManNodeNum(p) );
+ return nSteps;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Stops the AIG manager.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Ivy_ManPrintStats( Ivy_Man_t * p )
+{
+ printf( "PI/PO = %d/%d ", Ivy_ManPiNum(p), Ivy_ManPoNum(p) );
+ printf( "A = %7d. ", Ivy_ManAndNum(p) );
+ printf( "L = %5d. ", Ivy_ManLatchNum(p) );
+// printf( "X = %d. ", Ivy_ManExorNum(p) );
+// printf( "B = %3d. ", Ivy_ManBufNum(p) );
+ printf( "MaxID = %7d. ", Ivy_ManObjIdMax(p) );
+// printf( "Cre = %d. ", p->nCreated );
+// printf( "Del = %d. ", p->nDeleted );
+ printf( "Lev = %3d. ", Ivy_ManLatchNum(p)? -1 : Ivy_ManLevels(p) );
+ printf( "\n" );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Converts a combinational AIG manager into a sequential one.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Ivy_ManMakeSeq( Ivy_Man_t * p, int nLatches, int * pInits )
+{
+ Ivy_Obj_t * pObj, * pLatch;
+ Ivy_Init_t Init;
+ int i;
+ if ( nLatches == 0 )
+ return;
+ assert( nLatches < Ivy_ManPiNum(p) && nLatches < Ivy_ManPoNum(p) );
+ assert( Ivy_ManPiNum(p) == Vec_PtrSize(p->vPis) );
+ assert( Ivy_ManPoNum(p) == Vec_PtrSize(p->vPos) );
+ assert( Vec_PtrSize( p->vBufs ) == 0 );
+ // create fanouts
+ if ( p->fFanout == 0 )
+ Ivy_ManStartFanout( p );
+ // collect the POs to be converted into latches
+ for ( i = 0; i < nLatches; i++ )
+ {
+ // get the latch value
+ Init = pInits? pInits[i] : IVY_INIT_0;
+ // create latch
+ pObj = Ivy_ManPo( p, Ivy_ManPoNum(p) - nLatches + i );
+ pLatch = Ivy_Latch( p, Ivy_ObjChild0(pObj), Init );
+ Ivy_ObjDisconnect( p, pObj );
+ // recycle the old PO object
+ Vec_PtrWriteEntry( p->vObjs, pObj->Id, NULL );
+ Ivy_ManRecycleMemory( p, pObj );
+ // convert the corresponding PI to a buffer and connect it to the latch
+ pObj = Ivy_ManPi( p, Ivy_ManPiNum(p) - nLatches + i );
+ pObj->Type = IVY_BUF;
+ Ivy_ObjConnect( p, pObj, pLatch, NULL );
+ // save the buffer
+ Vec_PtrPush( p->vBufs, pObj );
+ }
+ // shrink the arrays
+ Vec_PtrShrink( p->vPis, Ivy_ManPiNum(p) - nLatches );
+ Vec_PtrShrink( p->vPos, Ivy_ManPoNum(p) - nLatches );
+ // update the counters of different objects
+ p->nObjs[IVY_PI] -= nLatches;
+ p->nObjs[IVY_PO] -= nLatches;
+ p->nObjs[IVY_BUF] += nLatches;
+ p->nDeleted -= 2 * nLatches;
+ // remove dangling nodes
+ Ivy_ManCleanup(p);
+ Ivy_ManCleanupSeq(p);
+/*
+ // check for dangling nodes
+ Ivy_ManForEachObj( p, pObj, i )
+ if ( !Ivy_ObjIsPi(pObj) && !Ivy_ObjIsPo(pObj) && !Ivy_ObjIsConst1(pObj) )
+ {
+ assert( Ivy_ObjRefs(pObj) > 0 );
+ assert( Ivy_ObjRefs(pObj) == Ivy_ObjFanoutNum(p, pObj) );
+ }
+*/
+ // perform hashing by propagating the buffers
+ Ivy_ManPropagateBuffers( p, 0 );
+ if ( Ivy_ManBufNum(p) )
+ printf( "The number of remaining buffers is %d.\n", Ivy_ManBufNum(p) );
+ // fix the levels
+ Ivy_ManResetLevels( p );
+ // check the resulting network
+ if ( !Ivy_ManCheck(p) )
+ printf( "Ivy_ManMakeSeq(): The check has failed.\n" );
+}
+
+////////////////////////////////////////////////////////////////////////
+/// END OF FILE ///
+////////////////////////////////////////////////////////////////////////
+
+
diff --git a/src/aig/ivy/ivyMem.c b/src/aig/ivy/ivyMem.c
new file mode 100644
index 00000000..2a96857c
--- /dev/null
+++ b/src/aig/ivy/ivyMem.c
@@ -0,0 +1,116 @@
+/**CFile****************************************************************
+
+ FileName [ivyMem.c]
+
+ SystemName [ABC: Logic synthesis and verification system.]
+
+ PackageName [And-Inverter Graph package.]
+
+ Synopsis [Memory management for the AIG nodes.]
+
+ Author [Alan Mishchenko]
+
+ Affiliation [UC Berkeley]
+
+ Date [Ver. 1.0. Started - May 11, 2006.]
+
+ Revision [$Id: ivyMem.c,v 1.00 2006/05/11 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "ivy.h"
+
+////////////////////////////////////////////////////////////////////////
+/// DECLARATIONS ///
+////////////////////////////////////////////////////////////////////////
+
+// memory management
+#define IVY_PAGE_SIZE 12 // page size containing 2^IVY_PAGE_SIZE nodes
+#define IVY_PAGE_MASK 4095 // page bitmask (2^IVY_PAGE_SIZE)-1
+
+////////////////////////////////////////////////////////////////////////
+/// FUNCTION DEFINITIONS ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+ Synopsis [Starts the internal memory manager.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Ivy_ManStartMemory( Ivy_Man_t * p )
+{
+ p->vChunks = Vec_PtrAlloc( 128 );
+ p->vPages = Vec_PtrAlloc( 128 );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Stops the internal memory manager.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Ivy_ManStopMemory( Ivy_Man_t * p )
+{
+ void * pMemory;
+ int i;
+ Vec_PtrForEachEntry( p->vChunks, pMemory, i )
+ free( pMemory );
+ Vec_PtrFree( p->vChunks );
+ Vec_PtrFree( p->vPages );
+ p->pListFree = NULL;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Allocates additional memory for the nodes.]
+
+ Description [Allocates IVY_PAGE_SIZE nodes. Aligns memory by 32 bytes.
+ Records the pointer to the AIG manager in the -1 entry.]
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Ivy_ManAddMemory( Ivy_Man_t * p )
+{
+ char * pMemory;
+ int i, nBytes;
+ int EntrySizeMax = 128;
+ assert( sizeof(Ivy_Obj_t) <= EntrySizeMax );
+ assert( p->pListFree == NULL );
+// assert( (Ivy_ManObjNum(p) & IVY_PAGE_MASK) == 0 );
+ // allocate new memory page
+ nBytes = sizeof(Ivy_Obj_t) * (1<<IVY_PAGE_SIZE) + EntrySizeMax;
+ pMemory = ALLOC( char, nBytes );
+ Vec_PtrPush( p->vChunks, pMemory );
+ // align memory at the 32-byte boundary
+ pMemory = pMemory + EntrySizeMax - (((int)pMemory) & (EntrySizeMax-1));
+ // remember the manager in the first entry
+ Vec_PtrPush( p->vPages, pMemory );
+ // break the memory down into nodes
+ p->pListFree = (Ivy_Obj_t *)pMemory;
+ for ( i = 1; i <= IVY_PAGE_MASK; i++ )
+ {
+ *((char **)pMemory) = pMemory + sizeof(Ivy_Obj_t);
+ pMemory += sizeof(Ivy_Obj_t);
+ }
+ *((char **)pMemory) = NULL;
+}
+
+////////////////////////////////////////////////////////////////////////
+/// END OF FILE ///
+////////////////////////////////////////////////////////////////////////
+
+
diff --git a/src/aig/ivy/ivyMulti.c b/src/aig/ivy/ivyMulti.c
new file mode 100644
index 00000000..a7970156
--- /dev/null
+++ b/src/aig/ivy/ivyMulti.c
@@ -0,0 +1,301 @@
+/**CFile****************************************************************
+
+ FileName [ivyMulti.c]
+
+ SystemName [ABC: Logic synthesis and verification system.]
+
+ PackageName [And-Inverter Graph package.]
+
+ Synopsis [Constructing multi-input AND/EXOR gates.]
+
+ Author [Alan Mishchenko]
+
+ Affiliation [UC Berkeley]
+
+ Date [Ver. 1.0. Started - May 11, 2006.]
+
+ Revision [$Id: ivyMulti.c,v 1.00 2006/05/11 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "ivy.h"
+
+////////////////////////////////////////////////////////////////////////
+/// DECLARATIONS ///
+////////////////////////////////////////////////////////////////////////
+
+#define IVY_EVAL_LIMIT 128
+
+typedef struct Ivy_Eva_t_ Ivy_Eva_t;
+struct Ivy_Eva_t_
+{
+ Ivy_Obj_t * pArg; // the argument node
+ unsigned Mask; // the mask of covered nodes
+ int Weight; // the number of covered nodes
+};
+
+static void Ivy_MultiPrint( Ivy_Man_t * p, Ivy_Eva_t * pEvals, int nLeaves, int nEvals );
+static int Ivy_MultiCover( Ivy_Man_t * p, Ivy_Eva_t * pEvals, int nLeaves, int nEvals, int nLimit, Vec_Ptr_t * vSols );
+
+////////////////////////////////////////////////////////////////////////
+/// FUNCTION DEFINITIONS ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+ Synopsis [Constructs a balanced tree while taking sharing into account.]
+
+ Description [Returns 1 if the implementation exists.]
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Ivy_MultiPlus( Ivy_Man_t * p, Vec_Ptr_t * vLeaves, Vec_Ptr_t * vCone, Ivy_Type_t Type, int nLimit, Vec_Ptr_t * vSols )
+{
+ static Ivy_Eva_t pEvals[IVY_EVAL_LIMIT];
+ Ivy_Eva_t * pEval, * pFan0, * pFan1;
+ Ivy_Obj_t * pObj, * pTemp;
+ int nEvals, nEvalsOld, i, k, x, nLeaves;
+ unsigned uMaskAll;
+
+ // consider special cases
+ nLeaves = Vec_PtrSize(vLeaves);
+ assert( nLeaves > 2 );
+ if ( nLeaves > 32 || nLeaves + Vec_PtrSize(vCone) > IVY_EVAL_LIMIT )
+ return 0;
+// if ( nLeaves == 1 )
+// return Vec_PtrEntry( vLeaves, 0 );
+// if ( nLeaves == 2 )
+// return Ivy_Oper( Vec_PtrEntry(vLeaves, 0), Vec_PtrEntry(vLeaves, 1), Type );
+
+ // set the leaf entries
+ uMaskAll = ((1 << nLeaves) - 1);
+ nEvals = 0;
+ Vec_PtrForEachEntry( vLeaves, pObj, i )
+ {
+ pEval = pEvals + nEvals;
+ pEval->pArg = pObj;
+ pEval->Mask = (1 << nEvals);
+ pEval->Weight = 1;
+ // mark the leaf
+ Ivy_Regular(pObj)->TravId = nEvals;
+ nEvals++;
+ }
+
+ // propagate masks through the cone
+ Vec_PtrForEachEntry( vCone, pObj, i )
+ {
+ pObj->TravId = nEvals + i;
+ if ( Ivy_ObjIsBuf(pObj) )
+ pEvals[pObj->TravId].Mask = pEvals[Ivy_ObjFanin0(pObj)->TravId].Mask;
+ else
+ pEvals[pObj->TravId].Mask = pEvals[Ivy_ObjFanin0(pObj)->TravId].Mask | pEvals[Ivy_ObjFanin1(pObj)->TravId].Mask;
+ }
+
+ // set the internal entries
+ Vec_PtrForEachEntry( vCone, pObj, i )
+ {
+ if ( i == Vec_PtrSize(vCone) - 1 )
+ break;
+ // skip buffers
+ if ( Ivy_ObjIsBuf(pObj) )
+ continue;
+ // skip nodes without external fanout
+ if ( Ivy_ObjRefs(pObj) == 0 )
+ continue;
+ assert( !Ivy_IsComplement(pObj) );
+ pEval = pEvals + nEvals;
+ pEval->pArg = pObj;
+ pEval->Mask = pEvals[pObj->TravId].Mask;
+ pEval->Weight = Extra_WordCountOnes(pEval->Mask);
+ // mark the node
+ pObj->TravId = nEvals;
+ nEvals++;
+ }
+
+ // find the available nodes
+ nEvalsOld = nEvals;
+ for ( i = 1; i < nEvals; i++ )
+ for ( k = 0; k < i; k++ )
+ {
+ pFan0 = pEvals + i;
+ pFan1 = pEvals + k;
+ pTemp = Ivy_TableLookup(p, Ivy_ObjCreateGhost(p, pFan0->pArg, pFan1->pArg, Type, IVY_INIT_NONE));
+ // skip nodes in the cone
+ if ( pTemp == NULL || pTemp->fMarkB )
+ continue;
+ // skip the leaves
+ for ( x = 0; x < nLeaves; x++ )
+ if ( pTemp == Ivy_Regular(vLeaves->pArray[x]) )
+ break;
+ if ( x < nLeaves )
+ continue;
+ pEval = pEvals + nEvals;
+ pEval->pArg = pTemp;
+ pEval->Mask = pFan0->Mask | pFan1->Mask;
+ pEval->Weight = (pFan0->Mask & pFan1->Mask) ? Extra_WordCountOnes(pEval->Mask) : pFan0->Weight + pFan1->Weight;
+ // save the argument
+ pObj->TravId = nEvals;
+ nEvals++;
+ // quit if the number of entries exceeded the limit
+ if ( nEvals == IVY_EVAL_LIMIT )
+ goto Outside;
+ // quit if we found an acceptable implementation
+ if ( pEval->Mask == uMaskAll )
+ goto Outside;
+ }
+Outside:
+
+// Ivy_MultiPrint( pEvals, nLeaves, nEvals );
+ if ( !Ivy_MultiCover( p, pEvals, nLeaves, nEvals, nLimit, vSols ) )
+ return 0;
+ assert( Vec_PtrSize( vSols ) > 0 );
+ return 1;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Computes how many uncovered ones this one covers.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Ivy_MultiPrint( Ivy_Man_t * p, Ivy_Eva_t * pEvals, int nLeaves, int nEvals )
+{
+ Ivy_Eva_t * pEval;
+ int i, k;
+ for ( i = nLeaves; i < nEvals; i++ )
+ {
+ pEval = pEvals + i;
+ printf( "%2d (id = %5d) : |", i-nLeaves, Ivy_ObjId(pEval->pArg) );
+ for ( k = 0; k < nLeaves; k++ )
+ {
+ if ( pEval->Mask & (1 << k) )
+ printf( "+" );
+ else
+ printf( " " );
+ }
+ printf( "| Lev = %d.\n", Ivy_ObjLevel(pEval->pArg) );
+ }
+}
+
+/**Function*************************************************************
+
+ Synopsis [Computes how many uncovered ones this one covers.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+static inline int Ivy_MultiWeight( unsigned uMask, int nMaskOnes, unsigned uFound )
+{
+ assert( uMask & ~uFound );
+ if ( (uMask & uFound) == 0 )
+ return nMaskOnes;
+ return Extra_WordCountOnes( uMask & ~uFound );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Finds the cover.]
+
+ Description [Returns 1 if the cover is found.]
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Ivy_MultiCover( Ivy_Man_t * p, Ivy_Eva_t * pEvals, int nLeaves, int nEvals, int nLimit, Vec_Ptr_t * vSols )
+{
+ int fVerbose = 0;
+ Ivy_Eva_t * pEval, * pEvalBest;
+ unsigned uMaskAll, uFound, uTemp;
+ int i, k, BestK, WeightBest, WeightCur, LevelBest, LevelCur;
+ uMaskAll = (nLeaves == 32)? (~(unsigned)0) : ((1 << nLeaves) - 1);
+ uFound = 0;
+ // solve the covering problem
+ if ( fVerbose )
+ printf( "Solution: " );
+ Vec_PtrClear( vSols );
+ for ( i = 0; i < nLimit; i++ )
+ {
+ BestK = -1;
+ for ( k = nEvals - 1; k >= 0; k-- )
+ {
+ pEval = pEvals + k;
+ if ( (pEval->Mask & ~uFound) == 0 )
+ continue;
+ if ( BestK == -1 )
+ {
+ BestK = k;
+ pEvalBest = pEval;
+ WeightBest = Ivy_MultiWeight( pEvalBest->Mask, pEvalBest->Weight, uFound );
+ LevelBest = Ivy_ObjLevel( Ivy_Regular(pEvalBest->pArg) );
+ continue;
+ }
+ // compare BestK and the new one (k)
+ WeightCur = Ivy_MultiWeight( pEval->Mask, pEval->Weight, uFound );
+ LevelCur = Ivy_ObjLevel( Ivy_Regular(pEval->pArg) );
+ if ( WeightBest < WeightCur ||
+ (WeightBest == WeightCur && LevelBest > LevelCur) )
+ {
+ BestK = k;
+ pEvalBest = pEval;
+ WeightBest = WeightCur;
+ LevelBest = LevelCur;
+ }
+ }
+ assert( BestK != -1 );
+ // if the cost is only 1, take the leaf
+ if ( WeightBest == 1 && BestK >= nLeaves )
+ {
+ uTemp = (pEvalBest->Mask & ~uFound);
+ for ( k = 0; k < nLeaves; k++ )
+ if ( uTemp & (1 << k) )
+ break;
+ assert( k < nLeaves );
+ BestK = k;
+ pEvalBest = pEvals + BestK;
+ }
+ if ( fVerbose )
+ {
+ if ( BestK < nLeaves )
+ printf( "L(%d) ", BestK );
+ else
+ printf( "%d ", BestK - nLeaves );
+ }
+ // update the found set
+ Vec_PtrPush( vSols, pEvalBest->pArg );
+ uFound |= pEvalBest->Mask;
+ if ( uFound == uMaskAll )
+ break;
+ }
+ if ( uFound == uMaskAll )
+ {
+ if ( fVerbose )
+ printf( " Found \n\n" );
+ return 1;
+ }
+ else
+ {
+ if ( fVerbose )
+ printf( " Not found \n\n" );
+ return 0;
+ }
+}
+
+////////////////////////////////////////////////////////////////////////
+/// END OF FILE ///
+////////////////////////////////////////////////////////////////////////
+
+
diff --git a/src/aig/ivy/ivyMulti8.c b/src/aig/ivy/ivyMulti8.c
new file mode 100644
index 00000000..059d1500
--- /dev/null
+++ b/src/aig/ivy/ivyMulti8.c
@@ -0,0 +1,427 @@
+/**CFile****************************************************************
+
+ FileName [ivyMulti.c]
+
+ SystemName [ABC: Logic synthesis and verification system.]
+
+ PackageName [And-Inverter Graph package.]
+
+ Synopsis [Constructing multi-input AND/EXOR gates.]
+
+ Author [Alan Mishchenko]
+
+ Affiliation [UC Berkeley]
+
+ Date [Ver. 1.0. Started - May 11, 2006.]
+
+ Revision [$Id: ivyMulti.c,v 1.00 2006/05/11 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "ivy.h"
+
+////////////////////////////////////////////////////////////////////////
+/// DECLARATIONS ///
+////////////////////////////////////////////////////////////////////////
+
+typedef struct Ivy_Eval_t_ Ivy_Eval_t;
+struct Ivy_Eval_t_
+{
+ unsigned Mask : 5; // the mask of covered nodes
+ unsigned Weight : 3; // the number of covered nodes
+ unsigned Cost : 4; // the number of overlapping nodes
+ unsigned Level : 12; // the level of this node
+ unsigned Fan0 : 4; // the first fanin
+ unsigned Fan1 : 4; // the second fanin
+};
+
+static Ivy_Obj_t * Ivy_MultiBuild_rec( Ivy_Eval_t * pEvals, int iNum, Ivy_Obj_t ** pArgs, int nArgs, Ivy_Type_t Type );
+static void Ivy_MultiSort( Ivy_Obj_t ** pArgs, int nArgs );
+static int Ivy_MultiPushUniqueOrderByLevel( Ivy_Obj_t ** pArray, int nArgs, Ivy_Obj_t * pNode );
+static Ivy_Obj_t * Ivy_MultiEval( Ivy_Obj_t ** pArgs, int nArgs, Ivy_Type_t Type );
+
+
+////////////////////////////////////////////////////////////////////////
+/// FUNCTION DEFINITIONS ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+ Synopsis [Constructs the well-balanced tree of gates.]
+
+ Description [Disregards levels and possible logic sharing.]
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Ivy_Obj_t * Ivy_Multi_rec( Ivy_Obj_t ** ppObjs, int nObjs, Ivy_Type_t Type )
+{
+ Ivy_Obj_t * pObj1, * pObj2;
+ if ( nObjs == 1 )
+ return ppObjs[0];
+ pObj1 = Ivy_Multi_rec( ppObjs, nObjs/2, Type );
+ pObj2 = Ivy_Multi_rec( ppObjs + nObjs/2, nObjs - nObjs/2, Type );
+ return Ivy_Oper( pObj1, pObj2, Type );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Constructs a balanced tree while taking sharing into account.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Ivy_Obj_t * Ivy_Multi( Ivy_Obj_t ** pArgsInit, int nArgs, Ivy_Type_t Type )
+{
+ static char NumBits[32] = {0,1,1,2,1,2,2,3,1,2,2,3,2,3,3,4,1,2,2,3,2,3,3,4,2,3,3,4,3,4,4,5};
+ static Ivy_Eval_t pEvals[15+15*14/2];
+ static Ivy_Obj_t * pArgs[16];
+ Ivy_Eval_t * pEva, * pEvaBest;
+ int nArgsNew, nEvals, i, k;
+ Ivy_Obj_t * pTemp;
+
+ // consider the case of one argument
+ assert( nArgs > 0 );
+ if ( nArgs == 1 )
+ return pArgsInit[0];
+ // consider the case of two arguments
+ if ( nArgs == 2 )
+ return Ivy_Oper( pArgsInit[0], pArgsInit[1], Type );
+
+//Ivy_MultiEval( pArgsInit, nArgs, Type ); printf( "\n" );
+
+ // set the initial ones
+ for ( i = 0; i < nArgs; i++ )
+ {
+ pArgs[i] = pArgsInit[i];
+ pEva = pEvals + i;
+ pEva->Mask = (1 << i);
+ pEva->Weight = 1;
+ pEva->Cost = 0;
+ pEva->Level = Ivy_Regular(pArgs[i])->Level;
+ pEva->Fan0 = 0;
+ pEva->Fan1 = 0;
+ }
+
+ // find the available nodes
+ pEvaBest = pEvals;
+ nArgsNew = nArgs;
+ for ( i = 1; i < nArgsNew; i++ )
+ for ( k = 0; k < i; k++ )
+ if ( pTemp = Ivy_TableLookup(Ivy_ObjCreateGhost(pArgs[k], pArgs[i], Type, IVY_INIT_NONE)) )
+ {
+ pEva = pEvals + nArgsNew;
+ pEva->Mask = pEvals[k].Mask | pEvals[i].Mask;
+ pEva->Weight = NumBits[pEva->Mask];
+ pEva->Cost = pEvals[k].Cost + pEvals[i].Cost + NumBits[pEvals[k].Mask & pEvals[i].Mask];
+ pEva->Level = 1 + IVY_MAX(pEvals[k].Level, pEvals[i].Level);
+ pEva->Fan0 = k;
+ pEva->Fan1 = i;
+// assert( pEva->Level == (unsigned)Ivy_ObjLevel(pTemp) );
+ // compare
+ if ( pEvaBest->Weight < pEva->Weight ||
+ pEvaBest->Weight == pEva->Weight && pEvaBest->Cost > pEva->Cost ||
+ pEvaBest->Weight == pEva->Weight && pEvaBest->Cost == pEva->Cost && pEvaBest->Level > pEva->Level )
+ pEvaBest = pEva;
+ // save the argument
+ pArgs[nArgsNew++] = pTemp;
+ if ( nArgsNew == 15 )
+ goto Outside;
+ }
+Outside:
+
+// printf( "Best = %d.\n", pEvaBest - pEvals );
+
+ // the case of no common nodes
+ if ( nArgsNew == nArgs )
+ {
+ Ivy_MultiSort( pArgs, nArgs );
+ return Ivy_MultiBalance_rec( pArgs, nArgs, Type );
+ }
+ // the case of one common node
+ if ( nArgsNew == nArgs + 1 )
+ {
+ assert( pEvaBest - pEvals == nArgs );
+ k = 0;
+ for ( i = 0; i < nArgs; i++ )
+ if ( i != (int)pEvaBest->Fan0 && i != (int)pEvaBest->Fan1 )
+ pArgs[k++] = pArgs[i];
+ pArgs[k++] = pArgs[nArgs];
+ assert( k == nArgs - 1 );
+ nArgs = k;
+ Ivy_MultiSort( pArgs, nArgs );
+ return Ivy_MultiBalance_rec( pArgs, nArgs, Type );
+ }
+ // the case when there is a node that covers everything
+ if ( (int)pEvaBest->Mask == ((1 << nArgs) - 1) )
+ return Ivy_MultiBuild_rec( pEvals, pEvaBest - pEvals, pArgs, nArgsNew, Type );
+
+ // evaluate node pairs
+ nEvals = nArgsNew;
+ for ( i = 1; i < nArgsNew; i++ )
+ for ( k = 0; k < i; k++ )
+ {
+ pEva = pEvals + nEvals;
+ pEva->Mask = pEvals[k].Mask | pEvals[i].Mask;
+ pEva->Weight = NumBits[pEva->Mask];
+ pEva->Cost = pEvals[k].Cost + pEvals[i].Cost + NumBits[pEvals[k].Mask & pEvals[i].Mask];
+ pEva->Level = 1 + IVY_MAX(pEvals[k].Level, pEvals[i].Level);
+ pEva->Fan0 = k;
+ pEva->Fan1 = i;
+ // compare
+ if ( pEvaBest->Weight < pEva->Weight ||
+ pEvaBest->Weight == pEva->Weight && pEvaBest->Cost > pEva->Cost ||
+ pEvaBest->Weight == pEva->Weight && pEvaBest->Cost == pEva->Cost && pEvaBest->Level > pEva->Level )
+ pEvaBest = pEva;
+ // save the argument
+ nEvals++;
+ }
+ assert( pEvaBest - pEvals >= nArgsNew );
+
+// printf( "Used (%d, %d).\n", pEvaBest->Fan0, pEvaBest->Fan1 );
+
+ // get the best implementation
+ pTemp = Ivy_MultiBuild_rec( pEvals, pEvaBest - pEvals, pArgs, nArgsNew, Type );
+
+ // collect those not covered by EvaBest
+ k = 0;
+ for ( i = 0; i < nArgs; i++ )
+ if ( (pEvaBest->Mask & (1 << i)) == 0 )
+ pArgs[k++] = pArgs[i];
+ pArgs[k++] = pTemp;
+ assert( k == nArgs - (int)pEvaBest->Weight + 1 );
+ nArgs = k;
+ Ivy_MultiSort( pArgs, nArgs );
+ return Ivy_MultiBalance_rec( pArgs, nArgs, Type );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Implements multi-input AND/EXOR operation.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Ivy_Obj_t * Ivy_MultiBuild_rec( Ivy_Eval_t * pEvals, int iNum, Ivy_Obj_t ** pArgs, int nArgs, Ivy_Type_t Type )
+{
+ Ivy_Obj_t * pNode0, * pNode1;
+ if ( iNum < nArgs )
+ return pArgs[iNum];
+ pNode0 = Ivy_MultiBuild_rec( pEvals, pEvals[iNum].Fan0, pArgs, nArgs, Type );
+ pNode1 = Ivy_MultiBuild_rec( pEvals, pEvals[iNum].Fan1, pArgs, nArgs, Type );
+ return Ivy_Oper( pNode0, pNode1, Type );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Selection-sorts the nodes in the decreasing over of level.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Ivy_MultiSort( Ivy_Obj_t ** pArgs, int nArgs )
+{
+ Ivy_Obj_t * pTemp;
+ int i, j, iBest;
+
+ for ( i = 0; i < nArgs-1; i++ )
+ {
+ iBest = i;
+ for ( j = i+1; j < nArgs; j++ )
+ if ( Ivy_Regular(pArgs[j])->Level > Ivy_Regular(pArgs[iBest])->Level )
+ iBest = j;
+ pTemp = pArgs[i];
+ pArgs[i] = pArgs[iBest];
+ pArgs[iBest] = pTemp;
+ }
+}
+
+/**Function*************************************************************
+
+ Synopsis [Inserts a new node in the order by levels.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Ivy_MultiPushUniqueOrderByLevel( Ivy_Obj_t ** pArray, int nArgs, Ivy_Obj_t * pNode )
+{
+ Ivy_Obj_t * pNode1, * pNode2;
+ int i;
+ // try to find the node in the array
+ for ( i = 0; i < nArgs; i++ )
+ if ( pArray[i] == pNode )
+ return nArgs;
+ // put the node last
+ pArray[nArgs++] = pNode;
+ // find the place to put the new node
+ for ( i = nArgs-1; i > 0; i-- )
+ {
+ pNode1 = pArray[i ];
+ pNode2 = pArray[i-1];
+ if ( Ivy_Regular(pNode1)->Level <= Ivy_Regular(pNode2)->Level )
+ break;
+ pArray[i ] = pNode2;
+ pArray[i-1] = pNode1;
+ }
+ return nArgs;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Balances the array recursively.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Ivy_Obj_t * Ivy_MultiBalance_rec( Ivy_Obj_t ** pArgs, int nArgs, Ivy_Type_t Type )
+{
+ Ivy_Obj_t * pNodeNew;
+ // consider the case of one argument
+ assert( nArgs > 0 );
+ if ( nArgs == 1 )
+ return pArgs[0];
+ // consider the case of two arguments
+ if ( nArgs == 2 )
+ return Ivy_Oper( pArgs[0], pArgs[1], Type );
+ // get the last two nodes
+ pNodeNew = Ivy_Oper( pArgs[nArgs-1], pArgs[nArgs-2], Type );
+ // add the new node
+ nArgs = Ivy_MultiPushUniqueOrderByLevel( pArgs, nArgs - 2, pNodeNew );
+ return Ivy_MultiBalance_rec( pArgs, nArgs, Type );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Implements multi-input AND/EXOR operation.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Ivy_Obj_t * Ivy_MultiEval( Ivy_Obj_t ** pArgs, int nArgs, Ivy_Type_t Type )
+{
+ Ivy_Obj_t * pTemp;
+ int i, k;
+ int nArgsOld = nArgs;
+ for ( i = 0; i < nArgs; i++ )
+ printf( "%d[%d] ", i, Ivy_Regular(pArgs[i])->Level );
+ for ( i = 1; i < nArgs; i++ )
+ for ( k = 0; k < i; k++ )
+ {
+ pTemp = Ivy_TableLookup(Ivy_ObjCreateGhost(pArgs[k], pArgs[i], Type, IVY_INIT_NONE));
+ if ( pTemp != NULL )
+ {
+ printf( "%d[%d]=(%d,%d) ", nArgs, Ivy_Regular(pTemp)->Level, k, i );
+ pArgs[nArgs++] = pTemp;
+ }
+ }
+ printf( " ((%d/%d)) ", nArgsOld, nArgs-nArgsOld );
+ return NULL;
+}
+
+
+
+/**Function*************************************************************
+
+ Synopsis [Old code.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Ivy_Obj_t * Ivy_Multi1( Ivy_Obj_t ** pArgs, int nArgs, Ivy_Type_t Type )
+{
+ Ivy_Obj_t * pArgsRef[5], * pTemp;
+ int i, k, m, nArgsNew, Counter = 0;
+
+
+//Ivy_MultiEval( pArgs, nArgs, Type ); printf( "\n" );
+
+
+ assert( Type == IVY_AND || Type == IVY_EXOR );
+ assert( nArgs > 0 );
+ if ( nArgs == 1 )
+ return pArgs[0];
+
+ // find the nodes with more than one fanout
+ nArgsNew = 0;
+ for ( i = 0; i < nArgs; i++ )
+ if ( Ivy_ObjRefs( Ivy_Regular(pArgs[i]) ) > 0 )
+ pArgsRef[nArgsNew++] = pArgs[i];
+
+ // go through pairs
+ if ( nArgsNew >= 2 )
+ for ( i = 0; i < nArgsNew; i++ )
+ for ( k = i + 1; k < nArgsNew; k++ )
+ if ( pTemp = Ivy_TableLookup(Ivy_ObjCreateGhost(pArgsRef[i], pArgsRef[k], Type, IVY_INIT_NONE)) )
+ Counter++;
+// printf( "%d", Counter );
+
+ // go through pairs
+ if ( nArgsNew >= 2 )
+ for ( i = 0; i < nArgsNew; i++ )
+ for ( k = i + 1; k < nArgsNew; k++ )
+ if ( pTemp = Ivy_TableLookup(Ivy_ObjCreateGhost(pArgsRef[i], pArgsRef[k], Type, IVY_INIT_NONE)) )
+ {
+ nArgsNew = 0;
+ for ( m = 0; m < nArgs; m++ )
+ if ( pArgs[m] != pArgsRef[i] && pArgs[m] != pArgsRef[k] )
+ pArgs[nArgsNew++] = pArgs[m];
+ pArgs[nArgsNew++] = pTemp;
+ assert( nArgsNew == nArgs - 1 );
+ return Ivy_Multi1( pArgs, nArgsNew, Type );
+ }
+ return Ivy_Multi_rec( pArgs, nArgs, Type );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Old code.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Ivy_Obj_t * Ivy_Multi2( Ivy_Obj_t ** pArgs, int nArgs, Ivy_Type_t Type )
+{
+ assert( Type == IVY_AND || Type == IVY_EXOR );
+ assert( nArgs > 0 );
+ return Ivy_Multi_rec( pArgs, nArgs, Type );
+}
+
+////////////////////////////////////////////////////////////////////////
+/// END OF FILE ///
+////////////////////////////////////////////////////////////////////////
+
+
diff --git a/src/aig/ivy/ivyObj.c b/src/aig/ivy/ivyObj.c
new file mode 100644
index 00000000..59dda19c
--- /dev/null
+++ b/src/aig/ivy/ivyObj.c
@@ -0,0 +1,476 @@
+/**CFile****************************************************************
+
+ FileName [ivyObj.c]
+
+ SystemName [ABC: Logic synthesis and verification system.]
+
+ PackageName [And-Inverter Graph package.]
+
+ Synopsis [Adding/removing objects.]
+
+ Author [Alan Mishchenko]
+
+ Affiliation [UC Berkeley]
+
+ Date [Ver. 1.0. Started - May 11, 2006.]
+
+ Revision [$Id: ivyObj.c,v 1.00 2006/05/11 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "ivy.h"
+
+////////////////////////////////////////////////////////////////////////
+/// DECLARATIONS ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+/// FUNCTION DEFINITIONS ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+ Synopsis [Create the new node assuming it does not exist.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Ivy_Obj_t * Ivy_ObjCreatePi( Ivy_Man_t * p )
+{
+ return Ivy_ObjCreate( p, Ivy_ObjCreateGhost(p, NULL, NULL, IVY_PI, IVY_INIT_NONE) );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Create the new node assuming it does not exist.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Ivy_Obj_t * Ivy_ObjCreatePo( Ivy_Man_t * p, Ivy_Obj_t * pDriver )
+{
+ return Ivy_ObjCreate( p, Ivy_ObjCreateGhost(p, pDriver, NULL, IVY_PO, IVY_INIT_NONE) );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Create the new node assuming it does not exist.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Ivy_Obj_t * Ivy_ObjCreate( Ivy_Man_t * p, Ivy_Obj_t * pGhost )
+{
+ Ivy_Obj_t * pObj;
+ assert( !Ivy_IsComplement(pGhost) );
+ assert( Ivy_ObjIsGhost(pGhost) );
+ assert( Ivy_TableLookup(p, pGhost) == NULL );
+ // get memory for the new object
+ pObj = Ivy_ManFetchMemory( p );
+ assert( Ivy_ObjIsNone(pObj) );
+ pObj->Id = Vec_PtrSize(p->vObjs);
+ Vec_PtrPush( p->vObjs, pObj );
+ // add basic info (fanins, compls, type, init)
+ pObj->Type = pGhost->Type;
+ pObj->Init = pGhost->Init;
+ // add connections
+ Ivy_ObjConnect( p, pObj, pGhost->pFanin0, pGhost->pFanin1 );
+ // compute level
+ if ( Ivy_ObjIsNode(pObj) )
+ pObj->Level = Ivy_ObjLevelNew(pObj);
+ else if ( Ivy_ObjIsLatch(pObj) )
+ pObj->Level = 0;
+ else if ( Ivy_ObjIsOneFanin(pObj) )
+ pObj->Level = Ivy_ObjFanin0(pObj)->Level;
+ else if ( !Ivy_ObjIsPi(pObj) )
+ assert( 0 );
+ // create phase
+ if ( Ivy_ObjIsNode(pObj) )
+ pObj->fPhase = Ivy_ObjFaninPhase(Ivy_ObjChild0(pObj)) & Ivy_ObjFaninPhase(Ivy_ObjChild1(pObj));
+ else if ( Ivy_ObjIsOneFanin(pObj) )
+ pObj->fPhase = Ivy_ObjFaninPhase(Ivy_ObjChild0(pObj));
+ // set the fail TFO flag
+ if ( Ivy_ObjIsNode(pObj) )
+ pObj->fFailTfo = Ivy_ObjFanin0(pObj)->fFailTfo | Ivy_ObjFanin1(pObj)->fFailTfo;
+ // mark the fanins in a special way if the node is EXOR
+ if ( Ivy_ObjIsExor(pObj) )
+ {
+ Ivy_ObjFanin0(pObj)->fExFan = 1;
+ Ivy_ObjFanin1(pObj)->fExFan = 1;
+ }
+ // add PIs/POs to the arrays
+ if ( Ivy_ObjIsPi(pObj) )
+ Vec_PtrPush( p->vPis, pObj );
+ else if ( Ivy_ObjIsPo(pObj) )
+ Vec_PtrPush( p->vPos, pObj );
+// else if ( Ivy_ObjIsBuf(pObj) )
+// Vec_PtrPush( p->vBufs, pObj );
+ if ( p->vRequired && Vec_IntSize(p->vRequired) <= pObj->Id )
+ Vec_IntFillExtra( p->vRequired, 2 * Vec_IntSize(p->vRequired), 1000000 );
+ // update node counters of the manager
+ p->nObjs[Ivy_ObjType(pObj)]++;
+ p->nCreated++;
+
+// printf( "Adding %sAIG node: ", p->pHaig==NULL? "H":" " );
+// Ivy_ObjPrintVerbose( p, pObj, p->pHaig==NULL );
+// printf( "\n" );
+
+ // if HAIG is defined, create a corresponding node
+ if ( p->pHaig )
+ Ivy_ManHaigCreateObj( p, pObj );
+ return pObj;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Connect the object to the fanin.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Ivy_ObjConnect( Ivy_Man_t * p, Ivy_Obj_t * pObj, Ivy_Obj_t * pFan0, Ivy_Obj_t * pFan1 )
+{
+ assert( !Ivy_IsComplement(pObj) );
+ assert( Ivy_ObjIsPi(pObj) || Ivy_ObjIsOneFanin(pObj) || pFan1 != NULL );
+ // add the first fanin
+ pObj->pFanin0 = pFan0;
+ pObj->pFanin1 = pFan1;
+ // increment references of the fanins and add their fanouts
+ if ( Ivy_ObjFanin0(pObj) != NULL )
+ {
+ Ivy_ObjRefsInc( Ivy_ObjFanin0(pObj) );
+ if ( p->fFanout )
+ Ivy_ObjAddFanout( p, Ivy_ObjFanin0(pObj), pObj );
+ }
+ if ( Ivy_ObjFanin1(pObj) != NULL )
+ {
+ Ivy_ObjRefsInc( Ivy_ObjFanin1(pObj) );
+ if ( p->fFanout )
+ Ivy_ObjAddFanout( p, Ivy_ObjFanin1(pObj), pObj );
+ }
+ // add the node to the structural hash table
+ Ivy_TableInsert( p, pObj );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Connect the object to the fanin.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Ivy_ObjDisconnect( Ivy_Man_t * p, Ivy_Obj_t * pObj )
+{
+ assert( !Ivy_IsComplement(pObj) );
+ assert( Ivy_ObjIsPi(pObj) || Ivy_ObjIsOneFanin(pObj) || Ivy_ObjFanin1(pObj) != NULL );
+ // remove connections
+ if ( pObj->pFanin0 != NULL )
+ {
+ Ivy_ObjRefsDec(Ivy_ObjFanin0(pObj));
+ if ( p->fFanout )
+ Ivy_ObjDeleteFanout( p, Ivy_ObjFanin0(pObj), pObj );
+ }
+ if ( pObj->pFanin1 != NULL )
+ {
+ Ivy_ObjRefsDec(Ivy_ObjFanin1(pObj));
+ if ( p->fFanout )
+ Ivy_ObjDeleteFanout( p, Ivy_ObjFanin1(pObj), pObj );
+ }
+ assert( pObj->pNextFan0 == NULL );
+ assert( pObj->pNextFan1 == NULL );
+ assert( pObj->pPrevFan0 == NULL );
+ assert( pObj->pPrevFan1 == NULL );
+ // remove the node from the structural hash table
+ Ivy_TableDelete( p, pObj );
+ // add the first fanin
+ pObj->pFanin0 = NULL;
+ pObj->pFanin1 = NULL;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Replaces the first fanin of the node by the new fanin.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Ivy_ObjPatchFanin0( Ivy_Man_t * p, Ivy_Obj_t * pObj, Ivy_Obj_t * pFaninNew )
+{
+ Ivy_Obj_t * pFaninOld;
+ assert( !Ivy_IsComplement(pObj) );
+ pFaninOld = Ivy_ObjFanin0(pObj);
+ // decrement ref and remove fanout
+ Ivy_ObjRefsDec( pFaninOld );
+ if ( p->fFanout )
+ Ivy_ObjDeleteFanout( p, pFaninOld, pObj );
+ // update the fanin
+ pObj->pFanin0 = pFaninNew;
+ // increment ref and add fanout
+ Ivy_ObjRefsInc( Ivy_Regular(pFaninNew) );
+ if ( p->fFanout )
+ Ivy_ObjAddFanout( p, Ivy_Regular(pFaninNew), pObj );
+ // get rid of old fanin
+ if ( !Ivy_ObjIsPi(pFaninOld) && !Ivy_ObjIsConst1(pFaninOld) && Ivy_ObjRefs(pFaninOld) == 0 )
+ Ivy_ObjDelete_rec( p, pFaninOld, 1 );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Deletes the node.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Ivy_ObjDelete( Ivy_Man_t * p, Ivy_Obj_t * pObj, int fFreeTop )
+{
+ assert( !Ivy_IsComplement(pObj) );
+ assert( Ivy_ObjRefs(pObj) == 0 || !fFreeTop );
+ // update node counters of the manager
+ p->nObjs[pObj->Type]--;
+ p->nDeleted++;
+ // remove connections
+ Ivy_ObjDisconnect( p, pObj );
+ // remove PIs/POs from the arrays
+ if ( Ivy_ObjIsPi(pObj) )
+ Vec_PtrRemove( p->vPis, pObj );
+ else if ( Ivy_ObjIsPo(pObj) )
+ Vec_PtrRemove( p->vPos, pObj );
+ else if ( p->fFanout && Ivy_ObjIsBuf(pObj) )
+ Vec_PtrRemove( p->vBufs, pObj );
+ // clean and recycle the entry
+ if ( fFreeTop )
+ {
+ // free the node
+ Vec_PtrWriteEntry( p->vObjs, pObj->Id, NULL );
+ Ivy_ManRecycleMemory( p, pObj );
+ }
+ else
+ {
+ int nRefsOld = pObj->nRefs;
+ Ivy_Obj_t * pFanout = pObj->pFanout;
+ Ivy_ObjClean( pObj );
+ pObj->pFanout = pFanout;
+ pObj->nRefs = nRefsOld;
+ }
+}
+
+/**Function*************************************************************
+
+ Synopsis [Deletes the MFFC of the node.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Ivy_ObjDelete_rec( Ivy_Man_t * p, Ivy_Obj_t * pObj, int fFreeTop )
+{
+ Ivy_Obj_t * pFanin0, * pFanin1;
+ assert( !Ivy_IsComplement(pObj) );
+ assert( !Ivy_ObjIsNone(pObj) );
+ if ( Ivy_ObjIsConst1(pObj) || Ivy_ObjIsPi(pObj) )
+ return;
+ pFanin0 = Ivy_ObjFanin0(pObj);
+ pFanin1 = Ivy_ObjFanin1(pObj);
+ Ivy_ObjDelete( p, pObj, fFreeTop );
+ if ( pFanin0 && !Ivy_ObjIsNone(pFanin0) && Ivy_ObjRefs(pFanin0) == 0 )
+ Ivy_ObjDelete_rec( p, pFanin0, 1 );
+ if ( pFanin1 && !Ivy_ObjIsNone(pFanin1) && Ivy_ObjRefs(pFanin1) == 0 )
+ Ivy_ObjDelete_rec( p, pFanin1, 1 );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Replaces one object by another.]
+
+ Description [Both objects are currently in the manager. The new object
+ (pObjNew) should be used instead of the old object (pObjOld). If the
+ new object is complemented or used, the buffer is added.]
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Ivy_ObjReplace( Ivy_Man_t * p, Ivy_Obj_t * pObjOld, Ivy_Obj_t * pObjNew, int fDeleteOld, int fFreeTop, int fUpdateLevel )
+{
+ int nRefsOld;//, clk;
+ // the object to be replaced cannot be complemented
+ assert( !Ivy_IsComplement(pObjOld) );
+ // the object to be replaced cannot be a terminal
+ assert( Ivy_ObjIsNone(pObjOld) || !Ivy_ObjIsPi(pObjOld) );
+ // the object to be used cannot be a PO or assert
+ assert( !Ivy_ObjIsBuf(Ivy_Regular(pObjNew)) );
+ // the object cannot be the same
+ assert( pObjOld != Ivy_Regular(pObjNew) );
+//printf( "Replacing %d by %d.\n", Ivy_Regular(pObjOld)->Id, Ivy_Regular(pObjNew)->Id );
+
+ // if HAIG is defined, create the choice node
+ if ( p->pHaig )
+ {
+// if ( pObjOld->Id == 31 )
+// {
+// Ivy_ManShow( p, 0 );
+// Ivy_ManShow( p->pHaig, 1 );
+// }
+ Ivy_ManHaigCreateChoice( p, pObjOld, pObjNew );
+ }
+ // if the new object is complemented or already used, add the buffer
+ if ( Ivy_IsComplement(pObjNew) || Ivy_ObjIsLatch(pObjNew) || Ivy_ObjRefs(pObjNew) > 0 || Ivy_ObjIsPi(pObjNew) || Ivy_ObjIsConst1(pObjNew) )
+ pObjNew = Ivy_ObjCreate( p, Ivy_ObjCreateGhost(p, pObjNew, NULL, IVY_BUF, IVY_INIT_NONE) );
+ assert( !Ivy_IsComplement(pObjNew) );
+ if ( fUpdateLevel )
+ {
+//clk = clock();
+ // if the new node's arrival time is different, recursively update arrival time of the fanouts
+ if ( p->fFanout && !Ivy_ObjIsBuf(pObjNew) && pObjOld->Level != pObjNew->Level )
+ {
+ assert( Ivy_ObjIsNode(pObjOld) );
+ pObjOld->Level = pObjNew->Level;
+ Ivy_ObjUpdateLevel_rec( p, pObjOld );
+ }
+//p->time1 += clock() - clk;
+ // if the new node's required time has changed, recursively update required time of the fanins
+//clk = clock();
+ if ( p->vRequired )
+ {
+ int ReqNew = Vec_IntEntry(p->vRequired, pObjOld->Id);
+ if ( ReqNew < Vec_IntEntry(p->vRequired, pObjNew->Id) )
+ {
+ Vec_IntWriteEntry( p->vRequired, pObjNew->Id, ReqNew );
+ Ivy_ObjUpdateLevelR_rec( p, pObjNew, ReqNew );
+ }
+ }
+//p->time2 += clock() - clk;
+ }
+ // delete the old object
+ if ( fDeleteOld )
+ Ivy_ObjDelete_rec( p, pObjOld, fFreeTop );
+ // make sure object is not pointing to itself
+ assert( Ivy_ObjFanin0(pObjNew) == NULL || pObjOld != Ivy_ObjFanin0(pObjNew) );
+ assert( Ivy_ObjFanin1(pObjNew) == NULL || pObjOld != Ivy_ObjFanin1(pObjNew) );
+ // make sure the old node has no fanin fanout pointers
+ if ( p->fFanout )
+ {
+ assert( pObjOld->pFanout != NULL );
+ assert( pObjNew->pFanout == NULL );
+ pObjNew->pFanout = pObjOld->pFanout;
+ }
+ // transfer the old object
+ assert( Ivy_ObjRefs(pObjNew) == 0 );
+ nRefsOld = pObjOld->nRefs;
+ Ivy_ObjOverwrite( pObjOld, pObjNew );
+ pObjOld->nRefs = nRefsOld;
+ // patch the fanout of the fanins
+ if ( p->fFanout )
+ {
+ Ivy_ObjPatchFanout( p, Ivy_ObjFanin0(pObjOld), pObjNew, pObjOld );
+ if ( Ivy_ObjFanin1(pObjOld) )
+ Ivy_ObjPatchFanout( p, Ivy_ObjFanin1(pObjOld), pObjNew, pObjOld );
+ }
+ // update the hash table
+ Ivy_TableUpdate( p, pObjNew, pObjOld->Id );
+ // recycle the object that was taken over by pObjOld
+ Vec_PtrWriteEntry( p->vObjs, pObjNew->Id, NULL );
+ Ivy_ManRecycleMemory( p, pObjNew );
+ // if the new node is the buffer propagate it
+ if ( p->fFanout && Ivy_ObjIsBuf(pObjOld) )
+ Vec_PtrPush( p->vBufs, pObjOld );
+// Ivy_ManCheckFanouts( p );
+// printf( "\n" );
+/*
+ if ( p->pHaig )
+ {
+ int x;
+ Ivy_ManShow( p, 0, NULL );
+ Ivy_ManShow( p->pHaig, 1, NULL );
+ x = 0;
+ }
+*/
+// if ( Ivy_ManCheckFanoutNums(p) )
+// {
+// int x = 0;
+// }
+}
+
+/**Function*************************************************************
+
+ Synopsis [Fixes buffer fanins.]
+
+ Description [This situation happens because NodeReplace is a lazy
+ procedure, which does not propagate the change to the fanouts but
+ instead records the change in the form of a buf/inv node.]
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Ivy_NodeFixBufferFanins( Ivy_Man_t * p, Ivy_Obj_t * pNode, int fUpdateLevel )
+{
+ Ivy_Obj_t * pFanReal0, * pFanReal1, * pResult;
+ if ( Ivy_ObjIsPo(pNode) )
+ {
+ if ( !Ivy_ObjIsBuf(Ivy_ObjFanin0(pNode)) )
+ return;
+ pFanReal0 = Ivy_ObjReal( Ivy_ObjChild0(pNode) );
+ Ivy_ObjPatchFanin0( p, pNode, pFanReal0 );
+// Ivy_ManCheckFanouts( p );
+ return;
+ }
+ if ( !Ivy_ObjIsBuf(Ivy_ObjFanin0(pNode)) && !Ivy_ObjIsBuf(Ivy_ObjFanin1(pNode)) )
+ return;
+ // get the real fanins
+ pFanReal0 = Ivy_ObjReal( Ivy_ObjChild0(pNode) );
+ pFanReal1 = Ivy_ObjReal( Ivy_ObjChild1(pNode) );
+ // get the new node
+ if ( Ivy_ObjIsNode(pNode) )
+ pResult = Ivy_Oper( p, pFanReal0, pFanReal1, Ivy_ObjType(pNode) );
+ else if ( Ivy_ObjIsLatch(pNode) )
+ pResult = Ivy_Latch( p, pFanReal0, Ivy_ObjInit(pNode) );
+ else
+ assert( 0 );
+
+//printf( "===== Replacing %d by %d.\n", pNode->Id, pResult->Id );
+//Ivy_ObjPrintVerbose( p, pNode, 0 ); printf( "\n" );
+//Ivy_ObjPrintVerbose( p, pResult, 0 ); printf( "\n" );
+
+ // perform the replacement
+ Ivy_ObjReplace( p, pNode, pResult, 1, 0, fUpdateLevel );
+}
+
+////////////////////////////////////////////////////////////////////////
+/// END OF FILE ///
+////////////////////////////////////////////////////////////////////////
+
+
diff --git a/src/aig/ivy/ivyOper.c b/src/aig/ivy/ivyOper.c
new file mode 100644
index 00000000..8115ce4f
--- /dev/null
+++ b/src/aig/ivy/ivyOper.c
@@ -0,0 +1,293 @@
+/**CFile****************************************************************
+
+ FileName [ivyOper.c]
+
+ SystemName [ABC: Logic synthesis and verification system.]
+
+ PackageName [And-Inverter Graph package.]
+
+ Synopsis [AIG operations.]
+
+ Author [Alan Mishchenko]
+
+ Affiliation [UC Berkeley]
+
+ Date [Ver. 1.0. Started - May 11, 2006.]
+
+ Revision [$Id: ivyOper.c,v 1.00 2006/05/11 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "ivy.h"
+
+////////////////////////////////////////////////////////////////////////
+/// DECLARATIONS ///
+////////////////////////////////////////////////////////////////////////
+
+// procedure to detect an EXOR gate
+static inline int Ivy_ObjIsExorType( Ivy_Obj_t * p0, Ivy_Obj_t * p1, Ivy_Obj_t ** ppFan0, Ivy_Obj_t ** ppFan1 )
+{
+ if ( !Ivy_IsComplement(p0) || !Ivy_IsComplement(p1) )
+ return 0;
+ p0 = Ivy_Regular(p0);
+ p1 = Ivy_Regular(p1);
+ if ( !Ivy_ObjIsAnd(p0) || !Ivy_ObjIsAnd(p1) )
+ return 0;
+ if ( Ivy_ObjFanin0(p0) != Ivy_ObjFanin0(p1) || Ivy_ObjFanin1(p0) != Ivy_ObjFanin1(p1) )
+ return 0;
+ if ( Ivy_ObjFaninC0(p0) == Ivy_ObjFaninC0(p1) || Ivy_ObjFaninC1(p0) == Ivy_ObjFaninC1(p1) )
+ return 0;
+ *ppFan0 = Ivy_ObjChild0(p0);
+ *ppFan1 = Ivy_ObjChild1(p0);
+ return 1;
+}
+
+////////////////////////////////////////////////////////////////////////
+/// FUNCTION DEFINITIONS ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+ Synopsis [Perform one operation.]
+
+ Description [The argument nodes can be complemented.]
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Ivy_Obj_t * Ivy_Oper( Ivy_Man_t * p, Ivy_Obj_t * p0, Ivy_Obj_t * p1, Ivy_Type_t Type )
+{
+ if ( Type == IVY_AND )
+ return Ivy_And( p, p0, p1 );
+ if ( Type == IVY_EXOR )
+ return Ivy_Exor( p, p0, p1 );
+ assert( 0 );
+ return NULL;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Performs canonicization step.]
+
+ Description [The argument nodes can be complemented.]
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Ivy_Obj_t * Ivy_And( Ivy_Man_t * p, Ivy_Obj_t * p0, Ivy_Obj_t * p1 )
+{
+// Ivy_Obj_t * pFan0, * pFan1;
+ // check trivial cases
+ if ( p0 == p1 )
+ return p0;
+ if ( p0 == Ivy_Not(p1) )
+ return Ivy_Not(p->pConst1);
+ if ( Ivy_Regular(p0) == p->pConst1 )
+ return p0 == p->pConst1 ? p1 : Ivy_Not(p->pConst1);
+ if ( Ivy_Regular(p1) == p->pConst1 )
+ return p1 == p->pConst1 ? p0 : Ivy_Not(p->pConst1);
+ // check if it can be an EXOR gate
+// if ( Ivy_ObjIsExorType( p0, p1, &pFan0, &pFan1 ) )
+// return Ivy_CanonExor( pFan0, pFan1 );
+ return Ivy_CanonAnd( p, p0, p1 );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Performs canonicization step.]
+
+ Description [The argument nodes can be complemented.]
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Ivy_Obj_t * Ivy_Exor( Ivy_Man_t * p, Ivy_Obj_t * p0, Ivy_Obj_t * p1 )
+{
+/*
+ // check trivial cases
+ if ( p0 == p1 )
+ return Ivy_Not(p->pConst1);
+ if ( p0 == Ivy_Not(p1) )
+ return p->pConst1;
+ if ( Ivy_Regular(p0) == p->pConst1 )
+ return Ivy_NotCond( p1, p0 == p->pConst1 );
+ if ( Ivy_Regular(p1) == p->pConst1 )
+ return Ivy_NotCond( p0, p1 == p->pConst1 );
+ // check the table
+ return Ivy_CanonExor( p, p0, p1 );
+*/
+ return Ivy_Or( p, Ivy_And(p, p0, Ivy_Not(p1)), Ivy_And(p, Ivy_Not(p0), p1) );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Implements Boolean OR.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Ivy_Obj_t * Ivy_Or( Ivy_Man_t * p, Ivy_Obj_t * p0, Ivy_Obj_t * p1 )
+{
+ return Ivy_Not( Ivy_And( p, Ivy_Not(p0), Ivy_Not(p1) ) );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Implements ITE operation.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Ivy_Obj_t * Ivy_Mux( Ivy_Man_t * p, Ivy_Obj_t * pC, Ivy_Obj_t * p1, Ivy_Obj_t * p0 )
+{
+ Ivy_Obj_t * pTempA1, * pTempA2, * pTempB1, * pTempB2, * pTemp;
+ int Count0, Count1;
+ // consider trivial cases
+ if ( p0 == Ivy_Not(p1) )
+ return Ivy_Exor( p, pC, p0 );
+ // other cases can be added
+ // implement the first MUX (F = C * x1 + C' * x0)
+ pTempA1 = Ivy_TableLookup( p, Ivy_ObjCreateGhost(p, pC, p1, IVY_AND, IVY_INIT_NONE) );
+ pTempA2 = Ivy_TableLookup( p, Ivy_ObjCreateGhost(p, Ivy_Not(pC), p0, IVY_AND, IVY_INIT_NONE) );
+ if ( pTempA1 && pTempA2 )
+ {
+ pTemp = Ivy_TableLookup( p, Ivy_ObjCreateGhost(p, Ivy_Not(pTempA1), Ivy_Not(pTempA2), IVY_AND, IVY_INIT_NONE) );
+ if ( pTemp ) return Ivy_Not(pTemp);
+ }
+ Count0 = (pTempA1 != NULL) + (pTempA2 != NULL);
+ // implement the second MUX (F' = C * x1' + C' * x0')
+ pTempB1 = Ivy_TableLookup( p, Ivy_ObjCreateGhost(p, pC, Ivy_Not(p1), IVY_AND, IVY_INIT_NONE) );
+ pTempB2 = Ivy_TableLookup( p, Ivy_ObjCreateGhost(p, Ivy_Not(pC), Ivy_Not(p0), IVY_AND, IVY_INIT_NONE) );
+ if ( pTempB1 && pTempB2 )
+ {
+ pTemp = Ivy_TableLookup( p, Ivy_ObjCreateGhost(p, Ivy_Not(pTempB1), Ivy_Not(pTempB2), IVY_AND, IVY_INIT_NONE) );
+ if ( pTemp ) return pTemp;
+ }
+ Count1 = (pTempB1 != NULL) + (pTempB2 != NULL);
+ // compare and decide which one to implement
+ if ( Count0 >= Count1 )
+ {
+ pTempA1 = pTempA1? pTempA1 : Ivy_And(p, pC, p1);
+ pTempA2 = pTempA2? pTempA2 : Ivy_And(p, Ivy_Not(pC), p0);
+ return Ivy_Or( p, pTempA1, pTempA2 );
+ }
+ pTempB1 = pTempB1? pTempB1 : Ivy_And(p, pC, Ivy_Not(p1));
+ pTempB2 = pTempB2? pTempB2 : Ivy_And(p, Ivy_Not(pC), Ivy_Not(p0));
+ return Ivy_Not( Ivy_Or( p, pTempB1, pTempB2 ) );
+
+// return Ivy_Or( Ivy_And(pC, p1), Ivy_And(Ivy_Not(pC), p0) );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Implements ITE operation.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Ivy_Obj_t * Ivy_Maj( Ivy_Man_t * p, Ivy_Obj_t * pA, Ivy_Obj_t * pB, Ivy_Obj_t * pC )
+{
+ return Ivy_Or( p, Ivy_Or(p, Ivy_And(p, pA, pB), Ivy_And(p, pA, pC)), Ivy_And(p, pB, pC) );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Constructs the well-balanced tree of gates.]
+
+ Description [Disregards levels and possible logic sharing.]
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Ivy_Obj_t * Ivy_Multi_rec( Ivy_Man_t * p, Ivy_Obj_t ** ppObjs, int nObjs, Ivy_Type_t Type )
+{
+ Ivy_Obj_t * pObj1, * pObj2;
+ if ( nObjs == 1 )
+ return ppObjs[0];
+ pObj1 = Ivy_Multi_rec( p, ppObjs, nObjs/2, Type );
+ pObj2 = Ivy_Multi_rec( p, ppObjs + nObjs/2, nObjs - nObjs/2, Type );
+ return Ivy_Oper( p, pObj1, pObj2, Type );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Old code.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Ivy_Obj_t * Ivy_Multi( Ivy_Man_t * p, Ivy_Obj_t ** pArgs, int nArgs, Ivy_Type_t Type )
+{
+ assert( Type == IVY_AND || Type == IVY_EXOR );
+ assert( nArgs > 0 );
+ return Ivy_Multi_rec( p, pArgs, nArgs, Type );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Implements the miter.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Ivy_Obj_t * Ivy_Miter( Ivy_Man_t * p, Vec_Ptr_t * vPairs )
+{
+ int i;
+ assert( vPairs->nSize > 0 );
+ assert( vPairs->nSize % 2 == 0 );
+ // go through the cubes of the node's SOP
+ for ( i = 0; i < vPairs->nSize; i += 2 )
+ vPairs->pArray[i/2] = Ivy_Not( Ivy_Exor( p, vPairs->pArray[i], vPairs->pArray[i+1] ) );
+ vPairs->nSize = vPairs->nSize/2;
+ return Ivy_Not( Ivy_Multi_rec( p, (Ivy_Obj_t **)vPairs->pArray, vPairs->nSize, IVY_AND ) );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Performs canonicization step.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Ivy_Obj_t * Ivy_Latch( Ivy_Man_t * p, Ivy_Obj_t * pObj, Ivy_Init_t Init )
+{
+ return Ivy_CanonLatch( p, pObj, Init );
+}
+
+////////////////////////////////////////////////////////////////////////
+/// END OF FILE ///
+////////////////////////////////////////////////////////////////////////
+
+
diff --git a/src/aig/ivy/ivyResyn.c b/src/aig/ivy/ivyResyn.c
new file mode 100644
index 00000000..f42d7464
--- /dev/null
+++ b/src/aig/ivy/ivyResyn.c
@@ -0,0 +1,196 @@
+/**CFile****************************************************************
+
+ FileName [ivyResyn.c]
+
+ SystemName [ABC: Logic synthesis and verification system.]
+
+ PackageName [And-Inverter Graph package.]
+
+ Synopsis [AIG rewriting script.]
+
+ Author [Alan Mishchenko]
+
+ Affiliation [UC Berkeley]
+
+ Date [Ver. 1.0. Started - May 11, 2006.]
+
+ Revision [$Id: ivyResyn.c,v 1.00 2006/05/11 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "ivy.h"
+
+////////////////////////////////////////////////////////////////////////
+/// DECLARATIONS ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+/// FUNCTION DEFINITIONS ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+ Synopsis [Performs several passes of rewriting on the AIG.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Ivy_Man_t * Ivy_ManResyn0( Ivy_Man_t * pMan, int fUpdateLevel, int fVerbose )
+{
+ int clk;
+ Ivy_Man_t * pTemp;
+
+if ( fVerbose ) { printf( "Original:\n" ); }
+if ( fVerbose ) Ivy_ManPrintStats( pMan );
+
+clk = clock();
+ pMan = Ivy_ManBalance( pMan, fUpdateLevel );
+if ( fVerbose ) { printf( "\n" ); }
+if ( fVerbose ) { PRT( "Balance", clock() - clk ); }
+if ( fVerbose ) Ivy_ManPrintStats( pMan );
+
+// Ivy_ManRewriteAlg( pMan, fUpdateLevel, 0 );
+clk = clock();
+ Ivy_ManRewritePre( pMan, fUpdateLevel, 0, 0 );
+if ( fVerbose ) { printf( "\n" ); }
+if ( fVerbose ) { PRT( "Rewrite", clock() - clk ); }
+if ( fVerbose ) Ivy_ManPrintStats( pMan );
+
+clk = clock();
+ pMan = Ivy_ManBalance( pTemp = pMan, fUpdateLevel );
+ Ivy_ManStop( pTemp );
+if ( fVerbose ) { printf( "\n" ); }
+if ( fVerbose ) { PRT( "Balance", clock() - clk ); }
+if ( fVerbose ) Ivy_ManPrintStats( pMan );
+ return pMan;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Performs several passes of rewriting on the AIG.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Ivy_Man_t * Ivy_ManResyn( Ivy_Man_t * pMan, int fUpdateLevel, int fVerbose )
+{
+ int clk;
+ Ivy_Man_t * pTemp;
+
+if ( fVerbose ) { printf( "Original:\n" ); }
+if ( fVerbose ) Ivy_ManPrintStats( pMan );
+
+clk = clock();
+ pMan = Ivy_ManBalance( pMan, fUpdateLevel );
+if ( fVerbose ) { printf( "\n" ); }
+if ( fVerbose ) { PRT( "Balance", clock() - clk ); }
+if ( fVerbose ) Ivy_ManPrintStats( pMan );
+
+// Ivy_ManRewriteAlg( pMan, fUpdateLevel, 0 );
+clk = clock();
+ Ivy_ManRewritePre( pMan, fUpdateLevel, 0, 0 );
+if ( fVerbose ) { printf( "\n" ); }
+if ( fVerbose ) { PRT( "Rewrite", clock() - clk ); }
+if ( fVerbose ) Ivy_ManPrintStats( pMan );
+
+clk = clock();
+ pMan = Ivy_ManBalance( pTemp = pMan, fUpdateLevel );
+ Ivy_ManStop( pTemp );
+if ( fVerbose ) { printf( "\n" ); }
+if ( fVerbose ) { PRT( "Balance", clock() - clk ); }
+if ( fVerbose ) Ivy_ManPrintStats( pMan );
+
+// Ivy_ManRewriteAlg( pMan, fUpdateLevel, 1 );
+clk = clock();
+ Ivy_ManRewritePre( pMan, fUpdateLevel, 1, 0 );
+if ( fVerbose ) { printf( "\n" ); }
+if ( fVerbose ) { PRT( "Rewrite", clock() - clk ); }
+if ( fVerbose ) Ivy_ManPrintStats( pMan );
+
+clk = clock();
+ pMan = Ivy_ManBalance( pTemp = pMan, fUpdateLevel );
+ Ivy_ManStop( pTemp );
+if ( fVerbose ) { printf( "\n" ); }
+if ( fVerbose ) { PRT( "Balance", clock() - clk ); }
+if ( fVerbose ) Ivy_ManPrintStats( pMan );
+
+// Ivy_ManRewriteAlg( pMan, fUpdateLevel, 1 );
+clk = clock();
+ Ivy_ManRewritePre( pMan, fUpdateLevel, 1, 0 );
+if ( fVerbose ) { printf( "\n" ); }
+if ( fVerbose ) { PRT( "Rewrite", clock() - clk ); }
+if ( fVerbose ) Ivy_ManPrintStats( pMan );
+
+clk = clock();
+ pMan = Ivy_ManBalance( pTemp = pMan, fUpdateLevel );
+ Ivy_ManStop( pTemp );
+if ( fVerbose ) { printf( "\n" ); }
+if ( fVerbose ) { PRT( "Balance", clock() - clk ); }
+if ( fVerbose ) Ivy_ManPrintStats( pMan );
+ return pMan;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Performs several passes of rewriting on the AIG.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Ivy_Man_t * Ivy_ManRwsat( Ivy_Man_t * pMan, int fVerbose )
+{
+ int clk;
+ Ivy_Man_t * pTemp;
+
+if ( fVerbose ) { printf( "Original:\n" ); }
+if ( fVerbose ) Ivy_ManPrintStats( pMan );
+
+clk = clock();
+ Ivy_ManRewritePre( pMan, 0, 0, 0 );
+if ( fVerbose ) { printf( "\n" ); }
+if ( fVerbose ) { PRT( "Rewrite", clock() - clk ); }
+if ( fVerbose ) Ivy_ManPrintStats( pMan );
+
+clk = clock();
+ pMan = Ivy_ManBalance( pTemp = pMan, 0 );
+// pMan = Ivy_ManDup( pTemp = pMan );
+ Ivy_ManStop( pTemp );
+if ( fVerbose ) { printf( "\n" ); }
+if ( fVerbose ) { PRT( "Balance", clock() - clk ); }
+if ( fVerbose ) Ivy_ManPrintStats( pMan );
+
+/*
+clk = clock();
+ Ivy_ManRewritePre( pMan, 0, 0, 0 );
+if ( fVerbose ) { printf( "\n" ); }
+if ( fVerbose ) { PRT( "Rewrite", clock() - clk ); }
+if ( fVerbose ) Ivy_ManPrintStats( pMan );
+
+clk = clock();
+ pMan = Ivy_ManBalance( pTemp = pMan, 0 );
+ Ivy_ManStop( pTemp );
+if ( fVerbose ) { printf( "\n" ); }
+if ( fVerbose ) { PRT( "Balance", clock() - clk ); }
+if ( fVerbose ) Ivy_ManPrintStats( pMan );
+*/
+ return pMan;
+}
+
+
+////////////////////////////////////////////////////////////////////////
+/// END OF FILE ///
+////////////////////////////////////////////////////////////////////////
+
+
diff --git a/src/aig/ivy/ivyRwr.c b/src/aig/ivy/ivyRwr.c
new file mode 100644
index 00000000..3f8720ba
--- /dev/null
+++ b/src/aig/ivy/ivyRwr.c
@@ -0,0 +1,609 @@
+/**CFile****************************************************************
+
+ FileName [ivyRwt.c]
+
+ SystemName [ABC: Logic synthesis and verification system.]
+
+ PackageName [And-Inverter Graph package.]
+
+ Synopsis [Rewriting based on precomputation.]
+
+ Author [Alan Mishchenko]
+
+ Affiliation [UC Berkeley]
+
+ Date [Ver. 1.0. Started - May 11, 2006.]
+
+ Revision [$Id: ivyRwt.c,v 1.00 2006/05/11 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "ivy.h"
+#include "deco.h"
+#include "rwt.h"
+
+////////////////////////////////////////////////////////////////////////
+/// DECLARATIONS ///
+////////////////////////////////////////////////////////////////////////
+
+static unsigned Ivy_NodeGetTruth( Ivy_Obj_t * pObj, int * pNums, int nNums );
+static int Ivy_NodeRewrite( Ivy_Man_t * pMan, Rwt_Man_t * p, Ivy_Obj_t * pNode, int fUpdateLevel, int fUseZeroCost );
+static Dec_Graph_t * Rwt_CutEvaluate( Ivy_Man_t * pMan, Rwt_Man_t * p, Ivy_Obj_t * pRoot,
+ Vec_Ptr_t * vFaninsCur, int nNodesSaved, int LevelMax, int * pGainBest, unsigned uTruth );
+
+static int Ivy_GraphToNetworkCount( Ivy_Man_t * p, Ivy_Obj_t * pRoot, Dec_Graph_t * pGraph, int NodeMax, int LevelMax );
+static void Ivy_GraphUpdateNetwork( Ivy_Man_t * p, Ivy_Obj_t * pRoot, Dec_Graph_t * pGraph, int fUpdateLevel, int nGain );
+
+////////////////////////////////////////////////////////////////////////
+/// FUNCTION DEFINITIONS ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+ Synopsis [Performs incremental rewriting of the AIG.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Ivy_ManRewritePre( Ivy_Man_t * p, int fUpdateLevel, int fUseZeroCost, int fVerbose )
+{
+ Rwt_Man_t * pManRwt;
+ Ivy_Obj_t * pNode;
+ int i, nNodes, nGain;
+ int clk, clkStart = clock();
+ // start the rewriting manager
+ pManRwt = Rwt_ManStart( 0 );
+ p->pData = pManRwt;
+ if ( pManRwt == NULL )
+ return 0;
+ // create fanouts
+ if ( fUpdateLevel && p->fFanout == 0 )
+ Ivy_ManStartFanout( p );
+ // compute the reverse levels if level update is requested
+ if ( fUpdateLevel )
+ Ivy_ManRequiredLevels( p );
+ // set the number of levels
+// p->nLevelMax = Ivy_ManLevels( p );
+ // resynthesize each node once
+ nNodes = Ivy_ManObjIdMax(p);
+ Ivy_ManForEachNode( p, pNode, i )
+ {
+ // fix the fanin buffer problem
+ Ivy_NodeFixBufferFanins( p, pNode, 1 );
+ if ( Ivy_ObjIsBuf(pNode) )
+ continue;
+ // stop if all nodes have been tried once
+ if ( i > nNodes )
+ break;
+ // for each cut, try to resynthesize it
+ nGain = Ivy_NodeRewrite( p, pManRwt, pNode, fUpdateLevel, fUseZeroCost );
+ if ( nGain > 0 || nGain == 0 && fUseZeroCost )
+ {
+ Dec_Graph_t * pGraph = Rwt_ManReadDecs(pManRwt);
+ int fCompl = Rwt_ManReadCompl(pManRwt);
+/*
+ {
+ Ivy_Obj_t * pObj;
+ int i;
+ printf( "USING: (" );
+ Vec_PtrForEachEntry( Rwt_ManReadLeaves(pManRwt), pObj, i )
+ printf( "%d ", Ivy_ObjFanoutNum(Ivy_Regular(pObj)) );
+ printf( ") Gain = %d.\n", nGain );
+ }
+ if ( nGain > 0 )
+ { // print stats on the MFFC
+ extern void Ivy_NodeMffsConeSuppPrint( Ivy_Obj_t * pNode );
+ printf( "Node %6d : Gain = %4d ", pNode->Id, nGain );
+ Ivy_NodeMffsConeSuppPrint( pNode );
+ }
+*/
+ // complement the FF if needed
+clk = clock();
+ if ( fCompl ) Dec_GraphComplement( pGraph );
+ Ivy_GraphUpdateNetwork( p, pNode, pGraph, fUpdateLevel, nGain );
+ if ( fCompl ) Dec_GraphComplement( pGraph );
+Rwt_ManAddTimeUpdate( pManRwt, clock() - clk );
+ }
+ }
+Rwt_ManAddTimeTotal( pManRwt, clock() - clkStart );
+ // print stats
+ if ( fVerbose )
+ Rwt_ManPrintStats( pManRwt );
+ // delete the managers
+ Rwt_ManStop( pManRwt );
+ p->pData = NULL;
+ // fix the levels
+ if ( fUpdateLevel )
+ Vec_IntFree( p->vRequired ), p->vRequired = NULL;
+ else
+ Ivy_ManResetLevels( p );
+ // check
+ if ( i = Ivy_ManCleanup(p) )
+ printf( "Cleanup after rewriting removed %d dangling nodes.\n", i );
+ if ( !Ivy_ManCheck(p) )
+ printf( "Ivy_ManRewritePre(): The check has failed.\n" );
+ return 1;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Performs rewriting for one node.]
+
+ Description [This procedure considers all the cuts computed for the node
+ and tries to rewrite each of them using the "forest" of different AIG
+ structures precomputed and stored in the RWR manager.
+ Determines the best rewriting and computes the gain in the number of AIG
+ nodes in the final network. In the end, p->vFanins contains information
+ about the best cut that can be used for rewriting, while p->pGraph gives
+ the decomposition dag (represented using decomposition graph data structure).
+ Returns gain in the number of nodes or -1 if node cannot be rewritten.]
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Ivy_NodeRewrite( Ivy_Man_t * pMan, Rwt_Man_t * p, Ivy_Obj_t * pNode, int fUpdateLevel, int fUseZeroCost )
+{
+ int fVeryVerbose = 0;
+ Dec_Graph_t * pGraph;
+ Ivy_Store_t * pStore;
+ Ivy_Cut_t * pCut;
+ Ivy_Obj_t * pFanin;
+ unsigned uPhase, uTruthBest, uTruth;
+ char * pPerm;
+ int Required, nNodesSaved, nNodesSaveCur;
+ int i, c, GainCur, GainBest = -1;
+ int clk, clk2;
+
+ p->nNodesConsidered++;
+ // get the required times
+ Required = fUpdateLevel? Vec_IntEntry( pMan->vRequired, pNode->Id ) : 1000000;
+ // get the node's cuts
+clk = clock();
+ pStore = Ivy_NodeFindCutsAll( pMan, pNode, 5 );
+p->timeCut += clock() - clk;
+
+ // go through the cuts
+clk = clock();
+ for ( c = 1; c < pStore->nCuts; c++ )
+ {
+ pCut = pStore->pCuts + c;
+ // consider only 4-input cuts
+ if ( pCut->nSize != 4 )
+ continue;
+ // skip the cuts with buffers
+ for ( i = 0; i < (int)pCut->nSize; i++ )
+ if ( Ivy_ObjIsBuf( Ivy_ManObj(pMan, pCut->pArray[i]) ) )
+ break;
+ if ( i != pCut->nSize )
+ {
+ p->nCutsBad++;
+ continue;
+ }
+ p->nCutsGood++;
+ // get the fanin permutation
+clk2 = clock();
+ uTruth = 0xFFFF & Ivy_NodeGetTruth( pNode, pCut->pArray, pCut->nSize ); // truth table
+p->timeTruth += clock() - clk2;
+ pPerm = p->pPerms4[ p->pPerms[uTruth] ];
+ uPhase = p->pPhases[uTruth];
+ // collect fanins with the corresponding permutation/phase
+ Vec_PtrClear( p->vFaninsCur );
+ Vec_PtrFill( p->vFaninsCur, (int)pCut->nSize, 0 );
+ for ( i = 0; i < (int)pCut->nSize; i++ )
+ {
+ pFanin = Ivy_ManObj( pMan, pCut->pArray[pPerm[i]] );
+ assert( Ivy_ObjIsNode(pFanin) || Ivy_ObjIsCi(pFanin) );
+ pFanin = Ivy_NotCond(pFanin, ((uPhase & (1<<i)) > 0) );
+ Vec_PtrWriteEntry( p->vFaninsCur, i, pFanin );
+ }
+clk2 = clock();
+/*
+ printf( "Considering: (" );
+ Vec_PtrForEachEntry( p->vFaninsCur, pFanin, i )
+ printf( "%d ", Ivy_ObjFanoutNum(Ivy_Regular(pFanin)) );
+ printf( ")\n" );
+*/
+ // mark the fanin boundary
+ Vec_PtrForEachEntry( p->vFaninsCur, pFanin, i )
+ Ivy_ObjRefsInc( Ivy_Regular(pFanin) );
+ // label MFFC with current ID
+ Ivy_ManIncrementTravId( pMan );
+ nNodesSaved = Ivy_ObjMffcLabel( pMan, pNode );
+ // unmark the fanin boundary
+ Vec_PtrForEachEntry( p->vFaninsCur, pFanin, i )
+ Ivy_ObjRefsDec( Ivy_Regular(pFanin) );
+p->timeMffc += clock() - clk2;
+
+ // evaluate the cut
+clk2 = clock();
+ pGraph = Rwt_CutEvaluate( pMan, p, pNode, p->vFaninsCur, nNodesSaved, Required, &GainCur, uTruth );
+p->timeEval += clock() - clk2;
+
+ // check if the cut is better than the current best one
+ if ( pGraph != NULL && GainBest < GainCur )
+ {
+ // save this form
+ nNodesSaveCur = nNodesSaved;
+ GainBest = GainCur;
+ p->pGraph = pGraph;
+ p->fCompl = ((uPhase & (1<<4)) > 0);
+ uTruthBest = uTruth;
+ // collect fanins in the
+ Vec_PtrClear( p->vFanins );
+ Vec_PtrForEachEntry( p->vFaninsCur, pFanin, i )
+ Vec_PtrPush( p->vFanins, pFanin );
+ }
+ }
+p->timeRes += clock() - clk;
+
+ if ( GainBest == -1 )
+ return -1;
+
+// printf( "%d", nNodesSaveCur - GainBest );
+/*
+ if ( GainBest > 0 )
+ {
+ if ( Rwt_CutIsintean( pNode, p->vFanins ) )
+ printf( "b" );
+ else
+ {
+ printf( "Node %d : ", pNode->Id );
+ Vec_PtrForEachEntry( p->vFanins, pFanin, i )
+ printf( "%d ", Ivy_Regular(pFanin)->Id );
+ printf( "a" );
+ }
+ }
+*/
+/*
+ if ( GainBest > 0 )
+ if ( p->fCompl )
+ printf( "c" );
+ else
+ printf( "." );
+*/
+
+ // copy the leaves
+ Vec_PtrForEachEntry( p->vFanins, pFanin, i )
+ Dec_GraphNode(p->pGraph, i)->pFunc = pFanin;
+
+ p->nScores[p->pMap[uTruthBest]]++;
+ p->nNodesGained += GainBest;
+ if ( fUseZeroCost || GainBest > 0 )
+ p->nNodesRewritten++;
+
+ // report the progress
+ if ( fVeryVerbose && GainBest > 0 )
+ {
+ printf( "Node %6d : ", Ivy_ObjId(pNode) );
+ printf( "Fanins = %d. ", p->vFanins->nSize );
+ printf( "Save = %d. ", nNodesSaveCur );
+ printf( "Add = %d. ", nNodesSaveCur-GainBest );
+ printf( "GAIN = %d. ", GainBest );
+ printf( "Cone = %d. ", p->pGraph? Dec_GraphNodeNum(p->pGraph) : 0 );
+ printf( "Class = %d. ", p->pMap[uTruthBest] );
+ printf( "\n" );
+ }
+ return GainBest;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Computes the truth table.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+unsigned Ivy_NodeGetTruth_rec( Ivy_Obj_t * pObj, int * pNums, int nNums )
+{
+ static unsigned uMasks[5] = { 0xAAAAAAAA, 0xCCCCCCCC, 0xF0F0F0F0, 0xFF00FF00, 0xFFFF0000 };
+ unsigned uTruth0, uTruth1;
+ int i;
+ for ( i = 0; i < nNums; i++ )
+ if ( pObj->Id == pNums[i] )
+ return uMasks[i];
+ assert( Ivy_ObjIsNode(pObj) || Ivy_ObjIsBuf(pObj) );
+ uTruth0 = Ivy_NodeGetTruth_rec( Ivy_ObjFanin0(pObj), pNums, nNums );
+ if ( Ivy_ObjFaninC0(pObj) )
+ uTruth0 = ~uTruth0;
+ if ( Ivy_ObjIsBuf(pObj) )
+ return uTruth0;
+ uTruth1 = Ivy_NodeGetTruth_rec( Ivy_ObjFanin1(pObj), pNums, nNums );
+ if ( Ivy_ObjFaninC1(pObj) )
+ uTruth1 = ~uTruth1;
+ return uTruth0 & uTruth1;
+}
+
+
+/**Function*************************************************************
+
+ Synopsis [Computes the truth table.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+unsigned Ivy_NodeGetTruth( Ivy_Obj_t * pObj, int * pNums, int nNums )
+{
+ assert( nNums < 6 );
+ return Ivy_NodeGetTruth_rec( pObj, pNums, nNums );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Evaluates the cut.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Dec_Graph_t * Rwt_CutEvaluate( Ivy_Man_t * pMan, Rwt_Man_t * p, Ivy_Obj_t * pRoot, Vec_Ptr_t * vFaninsCur, int nNodesSaved, int LevelMax, int * pGainBest, unsigned uTruth )
+{
+ Vec_Ptr_t * vSubgraphs;
+ Dec_Graph_t * pGraphBest, * pGraphCur;
+ Rwt_Node_t * pNode, * pFanin;
+ int nNodesAdded, GainBest, i, k;
+ // find the matching class of subgraphs
+ vSubgraphs = Vec_VecEntry( p->vClasses, p->pMap[uTruth] );
+ p->nSubgraphs += vSubgraphs->nSize;
+ // determine the best subgraph
+ GainBest = -1;
+ Vec_PtrForEachEntry( vSubgraphs, pNode, i )
+ {
+ // get the current graph
+ pGraphCur = (Dec_Graph_t *)pNode->pNext;
+ // copy the leaves
+ Vec_PtrForEachEntry( vFaninsCur, pFanin, k )
+ Dec_GraphNode(pGraphCur, k)->pFunc = pFanin;
+ // detect how many unlabeled nodes will be reused
+ nNodesAdded = Ivy_GraphToNetworkCount( pMan, pRoot, pGraphCur, nNodesSaved, LevelMax );
+ if ( nNodesAdded == -1 )
+ continue;
+ assert( nNodesSaved >= nNodesAdded );
+ // count the gain at this node
+ if ( GainBest < nNodesSaved - nNodesAdded )
+ {
+ GainBest = nNodesSaved - nNodesAdded;
+ pGraphBest = pGraphCur;
+ }
+ }
+ if ( GainBest == -1 )
+ return NULL;
+ *pGainBest = GainBest;
+ return pGraphBest;
+}
+
+
+/**Function*************************************************************
+
+ Synopsis [Counts the number of new nodes added when using this graph.]
+
+ Description [AIG nodes for the fanins should be assigned to pNode->pFunc
+ of the leaves of the graph before calling this procedure.
+ Returns -1 if the number of nodes and levels exceeded the given limit or
+ the number of levels exceeded the maximum allowed level.]
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Ivy_GraphToNetworkCount( Ivy_Man_t * p, Ivy_Obj_t * pRoot, Dec_Graph_t * pGraph, int NodeMax, int LevelMax )
+{
+ Dec_Node_t * pNode, * pNode0, * pNode1;
+ Ivy_Obj_t * pAnd, * pAnd0, * pAnd1;
+ int i, Counter, LevelNew, LevelOld;
+ // check for constant function or a literal
+ if ( Dec_GraphIsConst(pGraph) || Dec_GraphIsVar(pGraph) )
+ return 0;
+ // set the levels of the leaves
+ Dec_GraphForEachLeaf( pGraph, pNode, i )
+ pNode->Level = Ivy_Regular(pNode->pFunc)->Level;
+ // compute the AIG size after adding the internal nodes
+ Counter = 0;
+ Dec_GraphForEachNode( pGraph, pNode, i )
+ {
+ // get the children of this node
+ pNode0 = Dec_GraphNode( pGraph, pNode->eEdge0.Node );
+ pNode1 = Dec_GraphNode( pGraph, pNode->eEdge1.Node );
+ // get the AIG nodes corresponding to the children
+ pAnd0 = pNode0->pFunc;
+ pAnd1 = pNode1->pFunc;
+ if ( pAnd0 && pAnd1 )
+ {
+ // if they are both present, find the resulting node
+ pAnd0 = Ivy_NotCond( pAnd0, pNode->eEdge0.fCompl );
+ pAnd1 = Ivy_NotCond( pAnd1, pNode->eEdge1.fCompl );
+ pAnd = Ivy_TableLookup( p, Ivy_ObjCreateGhost(p, pAnd0, pAnd1, IVY_AND, IVY_INIT_NONE) );
+ // return -1 if the node is the same as the original root
+ if ( Ivy_Regular(pAnd) == pRoot )
+ return -1;
+ }
+ else
+ pAnd = NULL;
+ // count the number of added nodes
+ if ( pAnd == NULL || Ivy_ObjIsTravIdCurrent(p, Ivy_Regular(pAnd)) )
+ {
+ if ( ++Counter > NodeMax )
+ return -1;
+ }
+ // count the number of new levels
+ LevelNew = 1 + RWT_MAX( pNode0->Level, pNode1->Level );
+ if ( pAnd )
+ {
+ if ( Ivy_Regular(pAnd) == p->pConst1 )
+ LevelNew = 0;
+ else if ( Ivy_Regular(pAnd) == Ivy_Regular(pAnd0) )
+ LevelNew = (int)Ivy_Regular(pAnd0)->Level;
+ else if ( Ivy_Regular(pAnd) == Ivy_Regular(pAnd1) )
+ LevelNew = (int)Ivy_Regular(pAnd1)->Level;
+ LevelOld = (int)Ivy_Regular(pAnd)->Level;
+// assert( LevelNew == LevelOld );
+ }
+ if ( LevelNew > LevelMax )
+ return -1;
+ pNode->pFunc = pAnd;
+ pNode->Level = LevelNew;
+ }
+ return Counter;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Transforms the decomposition graph into the AIG.]
+
+ Description [AIG nodes for the fanins should be assigned to pNode->pFunc
+ of the leaves of the graph before calling this procedure.]
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Ivy_Obj_t * Ivy_GraphToNetwork( Ivy_Man_t * p, Dec_Graph_t * pGraph )
+{
+ Ivy_Obj_t * pAnd0, * pAnd1;
+ Dec_Node_t * pNode;
+ int i;
+ // check for constant function
+ if ( Dec_GraphIsConst(pGraph) )
+ return Ivy_NotCond( Ivy_ManConst1(p), Dec_GraphIsComplement(pGraph) );
+ // check for a literal
+ if ( Dec_GraphIsVar(pGraph) )
+ return Ivy_NotCond( Dec_GraphVar(pGraph)->pFunc, Dec_GraphIsComplement(pGraph) );
+ // build the AIG nodes corresponding to the AND gates of the graph
+ Dec_GraphForEachNode( pGraph, pNode, i )
+ {
+ pAnd0 = Ivy_NotCond( Dec_GraphNode(pGraph, pNode->eEdge0.Node)->pFunc, pNode->eEdge0.fCompl );
+ pAnd1 = Ivy_NotCond( Dec_GraphNode(pGraph, pNode->eEdge1.Node)->pFunc, pNode->eEdge1.fCompl );
+ pNode->pFunc = Ivy_And( p, pAnd0, pAnd1 );
+ }
+ // complement the result if necessary
+ return Ivy_NotCond( pNode->pFunc, Dec_GraphIsComplement(pGraph) );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Replaces MFFC of the node by the new factored form.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Ivy_GraphUpdateNetwork( Ivy_Man_t * p, Ivy_Obj_t * pRoot, Dec_Graph_t * pGraph, int fUpdateLevel, int nGain )
+{
+ Ivy_Obj_t * pRootNew;
+ int nNodesNew, nNodesOld, Required;
+ Required = fUpdateLevel? Vec_IntEntry( p->vRequired, pRoot->Id ) : 1000000;
+ nNodesOld = Ivy_ManNodeNum(p);
+ // create the new structure of nodes
+ pRootNew = Ivy_GraphToNetwork( p, pGraph );
+ assert( (int)Ivy_Regular(pRootNew)->Level <= Required );
+// if ( Ivy_Regular(pRootNew)->Level == Required )
+// printf( "Difference %d.\n", Ivy_Regular(pRootNew)->Level - Required );
+ // remove the old nodes
+// Ivy_AigReplace( pMan->pManFunc, pRoot, pRootNew, fUpdateLevel );
+/*
+ if ( Ivy_IsComplement(pRootNew) )
+ printf( "c" );
+ else
+ printf( "d" );
+ if ( Ivy_ObjRefs(Ivy_Regular(pRootNew)) > 0 )
+ printf( "%d", Ivy_ObjRefs(Ivy_Regular(pRootNew)) );
+ printf( " " );
+*/
+ Ivy_ObjReplace( p, pRoot, pRootNew, 1, 0, 1 );
+ // compare the gains
+ nNodesNew = Ivy_ManNodeNum(p);
+ assert( nGain <= nNodesOld - nNodesNew );
+ // propagate the buffer
+ Ivy_ManPropagateBuffers( p, 1 );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Replaces MFFC of the node by the new factored form.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Ivy_GraphUpdateNetwork3( Ivy_Man_t * p, Ivy_Obj_t * pRoot, Dec_Graph_t * pGraph, int fUpdateLevel, int nGain )
+{
+ Ivy_Obj_t * pRootNew, * pFanin;
+ int nNodesNew, nNodesOld, i, nRefsOld;
+ nNodesOld = Ivy_ManNodeNum(p);
+
+//printf( "Before = %d. ", Ivy_ManNodeNum(p) );
+ // mark the cut
+ Vec_PtrForEachEntry( ((Rwt_Man_t *)p->pData)->vFanins, pFanin, i )
+ Ivy_ObjRefsInc( Ivy_Regular(pFanin) );
+ // deref the old cone
+ nRefsOld = pRoot->nRefs;
+ pRoot->nRefs = 0;
+ Ivy_ObjDelete_rec( p, pRoot, 0 );
+ pRoot->nRefs = nRefsOld;
+ // unmark the cut
+ Vec_PtrForEachEntry( ((Rwt_Man_t *)p->pData)->vFanins, pFanin, i )
+ Ivy_ObjRefsDec( Ivy_Regular(pFanin) );
+//printf( "Deref = %d. ", Ivy_ManNodeNum(p) );
+
+ // create the new structure of nodes
+ pRootNew = Ivy_GraphToNetwork( p, pGraph );
+//printf( "Create = %d. ", Ivy_ManNodeNum(p) );
+ // remove the old nodes
+// Ivy_AigReplace( pMan->pManFunc, pRoot, pRootNew, fUpdateLevel );
+/*
+ if ( Ivy_IsComplement(pRootNew) )
+ printf( "c" );
+ else
+ printf( "d" );
+ if ( Ivy_ObjRefs(Ivy_Regular(pRootNew)) > 0 )
+ printf( "%d", Ivy_ObjRefs(Ivy_Regular(pRootNew)) );
+ printf( " " );
+*/
+ Ivy_ObjReplace( p, pRoot, pRootNew, 0, 0, 1 );
+//printf( "Replace = %d. ", Ivy_ManNodeNum(p) );
+
+ // delete remaining dangling nodes
+ Vec_PtrForEachEntry( ((Rwt_Man_t *)p->pData)->vFanins, pFanin, i )
+ {
+ pFanin = Ivy_Regular(pFanin);
+ if ( !Ivy_ObjIsNone(pFanin) && Ivy_ObjRefs(pFanin) == 0 )
+ Ivy_ObjDelete_rec( p, pFanin, 1 );
+ }
+//printf( "Deref = %d. ", Ivy_ManNodeNum(p) );
+//printf( "\n" );
+
+ // compare the gains
+ nNodesNew = Ivy_ManNodeNum(p);
+ assert( nGain <= nNodesOld - nNodesNew );
+}
+
+
+////////////////////////////////////////////////////////////////////////
+/// END OF FILE ///
+////////////////////////////////////////////////////////////////////////
+
+
diff --git a/src/aig/ivy/ivyRwrAlg.c b/src/aig/ivy/ivyRwrAlg.c
new file mode 100644
index 00000000..fc48deb0
--- /dev/null
+++ b/src/aig/ivy/ivyRwrAlg.c
@@ -0,0 +1,408 @@
+/**CFile****************************************************************
+
+ FileName [ivyRwrAlg.c]
+
+ SystemName [ABC: Logic synthesis and verification system.]
+
+ PackageName [And-Inverter Graph package.]
+
+ Synopsis [Algebraic AIG rewriting.]
+
+ Author [Alan Mishchenko]
+
+ Affiliation [UC Berkeley]
+
+ Date [Ver. 1.0. Started - May 11, 2006.]
+
+ Revision [$Id: ivyRwrAlg.c,v 1.00 2006/05/11 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "ivy.h"
+
+////////////////////////////////////////////////////////////////////////
+/// DECLARATIONS ///
+////////////////////////////////////////////////////////////////////////
+
+static int Ivy_ManFindAlgCut( Ivy_Obj_t * pRoot, Vec_Ptr_t * vFront, Vec_Ptr_t * vLeaves, Vec_Ptr_t * vCone );
+static Ivy_Obj_t * Ivy_NodeRewriteAlg( Ivy_Obj_t * pObj, Vec_Ptr_t * vFront, Vec_Ptr_t * vLeaves, Vec_Ptr_t * vCone, Vec_Ptr_t * vSols, int LevelR, int fUseZeroCost );
+static int Ivy_NodeCountMffc( Ivy_Obj_t * pNode );
+
+////////////////////////////////////////////////////////////////////////
+/// FUNCTION DEFINITIONS ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+ Synopsis [Algebraic AIG rewriting.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Ivy_ManRewriteAlg( Ivy_Man_t * p, int fUpdateLevel, int fUseZeroCost )
+{
+ Vec_Int_t * vRequired;
+ Vec_Ptr_t * vFront, * vLeaves, * vCone, * vSol;
+ Ivy_Obj_t * pObj, * pResult;
+ int i, RetValue, LevelR, nNodesOld;
+ int CountUsed, CountUndo;
+ vRequired = fUpdateLevel? Ivy_ManRequiredLevels( p ) : NULL;
+ vFront = Vec_PtrAlloc( 100 );
+ vLeaves = Vec_PtrAlloc( 100 );
+ vCone = Vec_PtrAlloc( 100 );
+ vSol = Vec_PtrAlloc( 100 );
+ // go through the nodes in the topological order
+ CountUsed = CountUndo = 0;
+ nNodesOld = Ivy_ManObjIdNext(p);
+ Ivy_ManForEachObj( p, pObj, i )
+ {
+ assert( !Ivy_ObjIsBuf(pObj) );
+ if ( i >= nNodesOld )
+ break;
+ // skip no-nodes and MUX roots
+ if ( !Ivy_ObjIsNode(pObj) || Ivy_ObjIsExor(pObj) || Ivy_ObjIsMuxType(pObj) )
+ continue;
+// if ( pObj->Id > 297 ) // 296 --- 297
+// break;
+ if ( pObj->Id == 297 )
+ {
+ int x = 0;
+ }
+ // get the largest algebraic cut
+ RetValue = Ivy_ManFindAlgCut( pObj, vFront, vLeaves, vCone );
+ // the case of a trivial tree cut
+ if ( RetValue == 1 )
+ continue;
+ // the case of constant 0 cone
+ if ( RetValue == -1 )
+ {
+ Ivy_ObjReplace( pObj, Ivy_ManConst0(p), 1, 0, 1 );
+ continue;
+ }
+ assert( Vec_PtrSize(vLeaves) > 2 );
+ // get the required level for this node
+ LevelR = vRequired? Vec_IntEntry(vRequired, pObj->Id) : 1000000;
+ // create a new cone
+ pResult = Ivy_NodeRewriteAlg( pObj, vFront, vLeaves, vCone, vSol, LevelR, fUseZeroCost );
+ if ( pResult == NULL || pResult == pObj )
+ continue;
+ assert( Vec_PtrSize(vSol) == 1 || !Ivy_IsComplement(pResult) );
+ if ( Ivy_ObjLevel(Ivy_Regular(pResult)) > LevelR && Ivy_ObjRefs(Ivy_Regular(pResult)) == 0 )
+ Ivy_ObjDelete_rec(Ivy_Regular(pResult), 1), CountUndo++;
+ else
+ Ivy_ObjReplace( pObj, pResult, 1, 0, 1 ), CountUsed++;
+ }
+ printf( "Used = %d. Undo = %d.\n", CountUsed, CountUndo );
+ Vec_PtrFree( vFront );
+ Vec_PtrFree( vCone );
+ Vec_PtrFree( vSol );
+ if ( vRequired ) Vec_IntFree( vRequired );
+ if ( i = Ivy_ManCleanup(p) )
+ printf( "Cleanup after rewriting removed %d dangling nodes.\n", i );
+ if ( !Ivy_ManCheck(p) )
+ printf( "Ivy_ManRewriteAlg(): The check has failed.\n" );
+ return 1;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Analizes one node.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Ivy_Obj_t * Ivy_NodeRewriteAlg( Ivy_Obj_t * pObj, Vec_Ptr_t * vFront, Vec_Ptr_t * vLeaves, Vec_Ptr_t * vCone, Vec_Ptr_t * vSols, int LevelR, int fUseZeroCost )
+{
+ int fVerbose = 0;
+ Ivy_Obj_t * pTemp;
+ int k, Counter, nMffc, RetValue;
+
+ if ( fVerbose )
+ {
+ if ( Ivy_ObjIsExor(pObj) )
+ printf( "x " );
+ else
+ printf( " " );
+ }
+
+/*
+ printf( "%d ", Vec_PtrSize(vFront) );
+ printf( "( " );
+ Vec_PtrForEachEntry( vFront, pTemp, k )
+ printf( "%d ", Ivy_ObjRefs(Ivy_Regular(pTemp)) );
+ printf( ")\n" );
+*/
+ // collect nodes in the cone
+ if ( Ivy_ObjIsExor(pObj) )
+ Ivy_ManCollectCone( pObj, vFront, vCone );
+ else
+ Ivy_ManCollectCone( pObj, vLeaves, vCone );
+
+ // deref nodes in the cone
+ Vec_PtrForEachEntry( vCone, pTemp, k )
+ {
+ Ivy_ObjRefsDec( Ivy_ObjFanin0(pTemp) );
+ Ivy_ObjRefsDec( Ivy_ObjFanin1(pTemp) );
+ pTemp->fMarkB = 1;
+ }
+
+ // count the MFFC size
+ Vec_PtrForEachEntry( vFront, pTemp, k )
+ Ivy_Regular(pTemp)->fMarkA = 1;
+ nMffc = Ivy_NodeCountMffc( pObj );
+ Vec_PtrForEachEntry( vFront, pTemp, k )
+ Ivy_Regular(pTemp)->fMarkA = 0;
+
+ if ( fVerbose )
+ {
+ Counter = 0;
+ Vec_PtrForEachEntry( vCone, pTemp, k )
+ Counter += (Ivy_ObjRefs(pTemp) > 0);
+ printf( "%5d : Leaves = %2d. Cone = %2d. ConeRef = %2d. Mffc = %d. Lev = %d. LevR = %d.\n",
+ pObj->Id, Vec_PtrSize(vFront), Vec_PtrSize(vCone), Counter-1, nMffc, Ivy_ObjLevel(pObj), LevelR );
+ }
+/*
+ printf( "Leaves:" );
+ Vec_PtrForEachEntry( vLeaves, pTemp, k )
+ printf( " %d%s", Ivy_Regular(pTemp)->Id, Ivy_IsComplement(pTemp)? "\'" : "" );
+ printf( "\n" );
+ printf( "Cone:\n" );
+ Vec_PtrForEachEntry( vCone, pTemp, k )
+ printf( " %5d = %d%s %d%s\n", pTemp->Id,
+ Ivy_ObjFaninId0(pTemp), Ivy_ObjFaninC0(pTemp)? "\'" : "",
+ Ivy_ObjFaninId1(pTemp), Ivy_ObjFaninC1(pTemp)? "\'" : "" );
+*/
+
+ RetValue = Ivy_MultiPlus( vLeaves, vCone, Ivy_ObjType(pObj), nMffc + fUseZeroCost, vSols );
+
+ // ref nodes in the cone
+ Vec_PtrForEachEntry( vCone, pTemp, k )
+ {
+ Ivy_ObjRefsInc( Ivy_ObjFanin0(pTemp) );
+ Ivy_ObjRefsInc( Ivy_ObjFanin1(pTemp) );
+ pTemp->fMarkA = 0;
+ pTemp->fMarkB = 0;
+ }
+
+ if ( !RetValue )
+ return NULL;
+
+ if ( Vec_PtrSize( vSols ) == 1 )
+ return Vec_PtrEntry( vSols, 0 );
+ return Ivy_NodeBalanceBuildSuper( vSols, Ivy_ObjType(pObj), 1 );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Comparison for node pointers.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Ivy_NodeCountMffc_rec( Ivy_Obj_t * pNode )
+{
+ if ( Ivy_ObjRefs(pNode) > 0 || Ivy_ObjIsCi(pNode) || pNode->fMarkA )
+ return 0;
+ assert( pNode->fMarkB );
+ pNode->fMarkA = 1;
+// printf( "%d ", pNode->Id );
+ if ( Ivy_ObjIsBuf(pNode) )
+ return Ivy_NodeCountMffc_rec( Ivy_ObjFanin0(pNode) );
+ return 1 + Ivy_NodeCountMffc_rec( Ivy_ObjFanin0(pNode) ) + Ivy_NodeCountMffc_rec( Ivy_ObjFanin1(pNode) );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Comparison for node pointers.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Ivy_NodeCountMffc( Ivy_Obj_t * pNode )
+{
+ assert( pNode->fMarkB );
+ return 1 + Ivy_NodeCountMffc_rec( Ivy_ObjFanin0(pNode) ) + Ivy_NodeCountMffc_rec( Ivy_ObjFanin1(pNode) );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Comparison for node pointers.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Ivy_ManFindAlgCutCompare( Ivy_Obj_t ** pp1, Ivy_Obj_t ** pp2 )
+{
+ if ( *pp1 < *pp2 )
+ return -1;
+ if ( *pp1 > *pp2 )
+ return 1;
+ return 0;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Computing one algebraic cut.]
+
+ Description [Returns 1 if the tree-leaves of this node where traversed
+ and found to have no external references (and have not been collected).
+ Returns 0 if the tree-leaves have external references and are collected.]
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Ivy_ManFindAlgCut_rec( Ivy_Obj_t * pObj, Ivy_Type_t Type, Vec_Ptr_t * vFront, Vec_Ptr_t * vCone )
+{
+ int RetValue0, RetValue1;
+ Ivy_Obj_t * pObjR = Ivy_Regular(pObj);
+ assert( !Ivy_ObjIsBuf(pObjR) );
+ assert( Type != IVY_EXOR || !Ivy_IsComplement(pObj) );
+
+ // make sure the node is not visited twice in different polarities
+ if ( Ivy_IsComplement(pObj) )
+ { // if complemented, mark B
+ if ( pObjR->fMarkA )
+ return -1;
+ pObjR->fMarkB = 1;
+ }
+ else
+ { // if non-complicated, mark A
+ if ( pObjR->fMarkB )
+ return -1;
+ pObjR->fMarkA = 1;
+ }
+ Vec_PtrPush( vCone, pObjR );
+
+ // if the node is the end of the tree, return
+ if ( Ivy_IsComplement(pObj) || Ivy_ObjType(pObj) != Type )
+ {
+ if ( Ivy_ObjRefs(pObjR) == 1 )
+ return 1;
+ assert( Ivy_ObjRefs(pObjR) > 1 );
+ Vec_PtrPush( vFront, pObj );
+ return 0;
+ }
+
+ // branch on the node
+ assert( !Ivy_IsComplement(pObj) );
+ assert( Ivy_ObjIsNode(pObj) );
+ // what if buffer has more than one fanout???
+ RetValue0 = Ivy_ManFindAlgCut_rec( Ivy_ObjReal( Ivy_ObjChild0(pObj) ), Type, vFront, vCone );
+ RetValue1 = Ivy_ManFindAlgCut_rec( Ivy_ObjReal( Ivy_ObjChild1(pObj) ), Type, vFront, vCone );
+ if ( RetValue0 == -1 || RetValue1 == -1 )
+ return -1;
+
+ // the case when both have no external references
+ if ( RetValue0 && RetValue1 )
+ {
+ if ( Ivy_ObjRefs(pObj) == 1 )
+ return 1;
+ assert( Ivy_ObjRefs(pObj) > 1 );
+ Vec_PtrPush( vFront, pObj );
+ return 0;
+ }
+ // the case when one of them has external references
+ if ( RetValue0 )
+ Vec_PtrPush( vFront, Ivy_ObjReal( Ivy_ObjChild0(pObj) ) );
+ if ( RetValue1 )
+ Vec_PtrPush( vFront, Ivy_ObjReal( Ivy_ObjChild1(pObj) ) );
+ return 0;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Computing one algebraic cut.]
+
+ Description [Algebraic cut stops when we hit (a) CI, (b) complemented edge,
+ (c) boundary of different gates. Returns 1 if this is a pure tree.
+ Returns -1 if the contant 0 is detected. Return 0 if the array can be used.]
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Ivy_ManFindAlgCut( Ivy_Obj_t * pRoot, Vec_Ptr_t * vFront, Vec_Ptr_t * vLeaves, Vec_Ptr_t * vCone )
+{
+ Ivy_Obj_t * pObj, * pPrev;
+ int RetValue, i;
+ assert( !Ivy_IsComplement(pRoot) );
+ assert( Ivy_ObjIsNode(pRoot) );
+ // clear the frontier and collect the nodes
+ Vec_PtrClear( vCone );
+ Vec_PtrClear( vFront );
+ Vec_PtrClear( vLeaves );
+ RetValue = Ivy_ManFindAlgCut_rec( pRoot, Ivy_ObjType(pRoot), vFront, vCone );
+ // clean the marks
+ Vec_PtrForEachEntry( vCone, pObj, i )
+ pObj->fMarkA = pObj->fMarkB = 0;
+ // quit if the same node is found in both polarities
+ if ( RetValue == -1 )
+ return -1;
+ // return if the node is the root of a tree
+ if ( RetValue == 1 )
+ return 1;
+ // return if the cut is composed of two nodes
+ if ( Vec_PtrSize(vFront) <= 2 )
+ return 1;
+ // sort the entries in increasing order
+ Vec_PtrSort( vFront, Ivy_ManFindAlgCutCompare );
+ // remove duplicates from vFront and save the nodes in vLeaves
+ pPrev = Vec_PtrEntry(vFront, 0);
+ Vec_PtrPush( vLeaves, pPrev );
+ Vec_PtrForEachEntryStart( vFront, pObj, i, 1 )
+ {
+ // compare current entry and the previous entry
+ if ( pObj == pPrev )
+ {
+ if ( Ivy_ObjIsExor(pRoot) ) // A <+> A = 0
+ {
+ // vLeaves are no longer structural support of pRoot!!!
+ Vec_PtrPop(vLeaves);
+ pPrev = Vec_PtrSize(vLeaves) == 0 ? NULL : Vec_PtrEntryLast(vLeaves);
+ }
+ continue;
+ }
+ if ( pObj == Ivy_Not(pPrev) )
+ {
+ assert( Ivy_ObjIsAnd(pRoot) );
+ return -1;
+ }
+ pPrev = pObj;
+ Vec_PtrPush( vLeaves, pObj );
+ }
+ if ( Vec_PtrSize(vLeaves) == 0 )
+ return -1;
+ if ( Vec_PtrSize(vLeaves) <= 2 )
+ return 1;
+ return 0;
+}
+
+
+////////////////////////////////////////////////////////////////////////
+/// END OF FILE ///
+////////////////////////////////////////////////////////////////////////
+
+
diff --git a/src/aig/ivy/ivySeq.c b/src/aig/ivy/ivySeq.c
new file mode 100644
index 00000000..0ee29fee
--- /dev/null
+++ b/src/aig/ivy/ivySeq.c
@@ -0,0 +1,1134 @@
+/**CFile****************************************************************
+
+ FileName [ivySeq.c]
+
+ SystemName [ABC: Logic synthesis and verification system.]
+
+ PackageName [And-Inverter Graph package.]
+
+ Synopsis []
+
+ Author [Alan Mishchenko]
+
+ Affiliation [UC Berkeley]
+
+ Date [Ver. 1.0. Started - May 11, 2006.]
+
+ Revision [$Id: ivySeq.c,v 1.00 2006/05/11 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "ivy.h"
+#include "deco.h"
+#include "rwt.h"
+
+////////////////////////////////////////////////////////////////////////
+/// DECLARATIONS ///
+////////////////////////////////////////////////////////////////////////
+
+static int Ivy_NodeRewriteSeq( Ivy_Man_t * pMan, Rwt_Man_t * p, Ivy_Obj_t * pNode, int fUseZeroCost );
+static void Ivy_GraphPrepare( Dec_Graph_t * pGraph, Ivy_Cut_t * pCut, Vec_Ptr_t * vFanins, char * pPerm );
+static unsigned Ivy_CutGetTruth( Ivy_Man_t * p, Ivy_Obj_t * pObj, int * pNums, int nNums );
+static Dec_Graph_t * Rwt_CutEvaluateSeq( Ivy_Man_t * pMan, Rwt_Man_t * p, Ivy_Obj_t * pRoot, Ivy_Cut_t * pCut, char * pPerm, Vec_Ptr_t * vFaninsCur, int nNodesSaved, int * pGainBest, unsigned uTruth );
+static int Ivy_GraphToNetworkSeqCountSeq( Ivy_Man_t * p, Ivy_Obj_t * pRoot, Dec_Graph_t * pGraph, int NodeMax );
+static Ivy_Obj_t * Ivy_GraphToNetworkSeq( Ivy_Man_t * p, Dec_Graph_t * pGraph );
+static void Ivy_GraphUpdateNetworkSeq( Ivy_Man_t * p, Ivy_Obj_t * pRoot, Dec_Graph_t * pGraph, int nGain );
+static Ivy_Store_t * Ivy_CutComputeForNode( Ivy_Man_t * p, Ivy_Obj_t * pObj, int nLeaves );
+
+static inline int Ivy_CutHashValue( int NodeId ) { return 1 << (NodeId % 31); }
+
+////////////////////////////////////////////////////////////////////////
+/// FUNCTION DEFINITIONS ///
+////////////////////////////////////////////////////////////////////////
+
+//int nMoves;
+//int nMovesS;
+//int nClauses;
+//int timeInv;
+
+/**Function*************************************************************
+
+ Synopsis [Performs incremental rewriting of the AIG.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Ivy_ManRewriteSeq( Ivy_Man_t * p, int fUseZeroCost, int fVerbose )
+{
+ Rwt_Man_t * pManRwt;
+ Ivy_Obj_t * pNode;
+ int i, nNodes, nGain;
+ int clk, clkStart = clock();
+
+ // set the DC latch values
+ Ivy_ManForEachLatch( p, pNode, i )
+ pNode->Init = IVY_INIT_DC;
+ // start the rewriting manager
+ pManRwt = Rwt_ManStart( 0 );
+ p->pData = pManRwt;
+ if ( pManRwt == NULL )
+ return 0;
+ // create fanouts
+ if ( p->fFanout == 0 )
+ Ivy_ManStartFanout( p );
+ // resynthesize each node once
+ nNodes = Ivy_ManObjIdMax(p);
+ Ivy_ManForEachNode( p, pNode, i )
+ {
+ assert( !Ivy_ObjIsBuf(pNode) );
+ assert( !Ivy_ObjIsBuf(Ivy_ObjFanin0(pNode)) );
+ assert( !Ivy_ObjIsBuf(Ivy_ObjFanin1(pNode)) );
+ // fix the fanin buffer problem
+// Ivy_NodeFixBufferFanins( p, pNode );
+// if ( Ivy_ObjIsBuf(pNode) )
+// continue;
+ // stop if all nodes have been tried once
+ if ( i > nNodes )
+ break;
+ // for each cut, try to resynthesize it
+ nGain = Ivy_NodeRewriteSeq( p, pManRwt, pNode, fUseZeroCost );
+ if ( nGain > 0 || nGain == 0 && fUseZeroCost )
+ {
+ Dec_Graph_t * pGraph = Rwt_ManReadDecs(pManRwt);
+ int fCompl = Rwt_ManReadCompl(pManRwt);
+ // complement the FF if needed
+clk = clock();
+ if ( fCompl ) Dec_GraphComplement( pGraph );
+ Ivy_GraphUpdateNetworkSeq( p, pNode, pGraph, nGain );
+ if ( fCompl ) Dec_GraphComplement( pGraph );
+Rwt_ManAddTimeUpdate( pManRwt, clock() - clk );
+ }
+ }
+Rwt_ManAddTimeTotal( pManRwt, clock() - clkStart );
+ // print stats
+ if ( fVerbose )
+ Rwt_ManPrintStats( pManRwt );
+ // delete the managers
+ Rwt_ManStop( pManRwt );
+ p->pData = NULL;
+ // fix the levels
+ Ivy_ManResetLevels( p );
+// if ( Ivy_ManCheckFanoutNums(p) )
+// printf( "Ivy_ManRewritePre(): The check has failed.\n" );
+ // check
+ if ( !Ivy_ManCheck(p) )
+ printf( "Ivy_ManRewritePre(): The check has failed.\n" );
+ return 1;
+}
+
+
+/**Function*************************************************************
+
+ Synopsis [Performs rewriting for one node.]
+
+ Description [This procedure considers all the cuts computed for the node
+ and tries to rewrite each of them using the "forest" of different AIG
+ structures precomputed and stored in the RWR manager.
+ Determines the best rewriting and computes the gain in the number of AIG
+ nodes in the final network. In the end, p->vFanins contains information
+ about the best cut that can be used for rewriting, while p->pGraph gives
+ the decomposition dag (represented using decomposition graph data structure).
+ Returns gain in the number of nodes or -1 if node cannot be rewritten.]
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Ivy_NodeRewriteSeq( Ivy_Man_t * pMan, Rwt_Man_t * p, Ivy_Obj_t * pNode, int fUseZeroCost )
+{
+ int fVeryVerbose = 0;
+ Dec_Graph_t * pGraph;
+ Ivy_Store_t * pStore;
+ Ivy_Cut_t * pCut;
+ Ivy_Obj_t * pFanin;//, * pFanout;
+ Vec_Ptr_t * vFanout;
+ unsigned uPhase, uTruthBest, uTruth;//, nNewClauses;
+ char * pPerm;
+ int nNodesSaved, nNodesSaveCur;
+ int i, c, GainCur, GainBest = -1;
+ int clk, clk2;//, clk3;
+
+ p->nNodesConsidered++;
+ // get the node's cuts
+clk = clock();
+ pStore = Ivy_CutComputeForNode( pMan, pNode, 5 );
+p->timeCut += clock() - clk;
+
+ // go through the cuts
+clk = clock();
+ vFanout = Vec_PtrAlloc( 100 );
+ for ( c = 1; c < pStore->nCuts; c++ )
+ {
+ pCut = pStore->pCuts + c;
+ // consider only 4-input cuts
+ if ( pCut->nSize != 4 )
+ continue;
+ // skip the cuts with buffers
+ for ( i = 0; i < (int)pCut->nSize; i++ )
+ if ( Ivy_ObjIsBuf( Ivy_ManObj(pMan, Ivy_LeafId(pCut->pArray[i])) ) )
+ break;
+ if ( i != pCut->nSize )
+ {
+ p->nCutsBad++;
+ continue;
+ }
+ p->nCutsGood++;
+ // get the fanin permutation
+clk2 = clock();
+ uTruth = 0xFFFF & Ivy_CutGetTruth( pMan, pNode, pCut->pArray, pCut->nSize ); // truth table
+p->timeTruth += clock() - clk2;
+ pPerm = p->pPerms4[ p->pPerms[uTruth] ];
+ uPhase = p->pPhases[uTruth];
+ // collect fanins with the corresponding permutation/phase
+ Vec_PtrClear( p->vFaninsCur );
+ Vec_PtrFill( p->vFaninsCur, (int)pCut->nSize, 0 );
+ for ( i = 0; i < (int)pCut->nSize; i++ )
+ {
+ pFanin = Ivy_ManObj( pMan, Ivy_LeafId( pCut->pArray[pPerm[i]] ) );
+ assert( Ivy_ObjIsNode(pFanin) || Ivy_ObjIsCi(pFanin) || Ivy_ObjIsConst1(pFanin) );
+ pFanin = Ivy_NotCond(pFanin, ((uPhase & (1<<i)) > 0) );
+ Vec_PtrWriteEntry( p->vFaninsCur, i, pFanin );
+ }
+clk2 = clock();
+ // mark the fanin boundary
+ Vec_PtrForEachEntry( p->vFaninsCur, pFanin, i )
+ Ivy_ObjRefsInc( Ivy_Regular(pFanin) );
+ // label MFFC with current ID
+ Ivy_ManIncrementTravId( pMan );
+ nNodesSaved = Ivy_ObjMffcLabel( pMan, pNode );
+ // label fanouts with the current ID
+// Ivy_ObjForEachFanout( pMan, pNode, vFanout, pFanout, i )
+// Ivy_ObjSetTravIdCurrent( pMan, pFanout );
+ // unmark the fanin boundary
+ Vec_PtrForEachEntry( p->vFaninsCur, pFanin, i )
+ Ivy_ObjRefsDec( Ivy_Regular(pFanin) );
+p->timeMffc += clock() - clk2;
+
+ // evaluate the cut
+clk2 = clock();
+ pGraph = Rwt_CutEvaluateSeq( pMan, p, pNode, pCut, pPerm, p->vFaninsCur, nNodesSaved, &GainCur, uTruth );
+p->timeEval += clock() - clk2;
+
+
+ // check if the cut is better than the current best one
+ if ( pGraph != NULL && GainBest < GainCur )
+ {
+ // save this form
+ nNodesSaveCur = nNodesSaved;
+ GainBest = GainCur;
+ p->pGraph = pGraph;
+ p->pCut = pCut;
+ p->pPerm = pPerm;
+ p->fCompl = ((uPhase & (1<<4)) > 0);
+ uTruthBest = uTruth;
+ // collect fanins in the
+ Vec_PtrClear( p->vFanins );
+ Vec_PtrForEachEntry( p->vFaninsCur, pFanin, i )
+ Vec_PtrPush( p->vFanins, pFanin );
+ }
+ }
+ Vec_PtrFree( vFanout );
+p->timeRes += clock() - clk;
+
+ if ( GainBest == -1 )
+ return -1;
+/*
+ {
+ Ivy_Cut_t * pCut = p->pCut;
+ printf( "Node %5d. Using cut : {", Ivy_ObjId(pNode) );
+ for ( i = 0; i < pCut->nSize; i++ )
+ printf( " %d(%d)", Ivy_LeafId(pCut->pArray[i]), Ivy_LeafLat(pCut->pArray[i]) );
+ printf( " }\n" );
+ }
+*/
+
+//clk3 = clock();
+//nNewClauses = Ivy_CutTruthPrint( pMan, p->pCut, uTruth );
+//timeInv += clock() - clk;
+
+// nClauses += nNewClauses;
+// nMoves++;
+// if ( nNewClauses > 0 )
+// nMovesS++;
+
+ // copy the leaves
+ Ivy_GraphPrepare( p->pGraph, p->pCut, p->vFanins, p->pPerm );
+
+ p->nScores[p->pMap[uTruthBest]]++;
+ p->nNodesGained += GainBest;
+ if ( fUseZeroCost || GainBest > 0 )
+ p->nNodesRewritten++;
+
+/*
+ if ( GainBest > 0 )
+ {
+ Ivy_Cut_t * pCut = p->pCut;
+ printf( "Node %5d. Using cut : {", Ivy_ObjId(pNode) );
+ for ( i = 0; i < pCut->nSize; i++ )
+ printf( " %5d(%2d)", Ivy_LeafId(pCut->pArray[i]), Ivy_LeafLat(pCut->pArray[i]) );
+ printf( " }\n" );
+ }
+*/
+
+ // report the progress
+ if ( fVeryVerbose && GainBest > 0 )
+ {
+ printf( "Node %6d : ", Ivy_ObjId(pNode) );
+ printf( "Fanins = %d. ", p->vFanins->nSize );
+ printf( "Save = %d. ", nNodesSaveCur );
+ printf( "Add = %d. ", nNodesSaveCur-GainBest );
+ printf( "GAIN = %d. ", GainBest );
+ printf( "Cone = %d. ", p->pGraph? Dec_GraphNodeNum(p->pGraph) : 0 );
+ printf( "Class = %d. ", p->pMap[uTruthBest] );
+ printf( "\n" );
+ }
+ return GainBest;
+}
+
+
+/**Function*************************************************************
+
+ Synopsis [Evaluates the cut.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Dec_Graph_t * Rwt_CutEvaluateSeq( Ivy_Man_t * pMan, Rwt_Man_t * p, Ivy_Obj_t * pRoot, Ivy_Cut_t * pCut, char * pPerm, Vec_Ptr_t * vFaninsCur, int nNodesSaved, int * pGainBest, unsigned uTruth )
+{
+ Vec_Ptr_t * vSubgraphs;
+ Dec_Graph_t * pGraphBest, * pGraphCur;
+ Rwt_Node_t * pNode;
+ int nNodesAdded, GainBest, i;
+ // find the matching class of subgraphs
+ vSubgraphs = Vec_VecEntry( p->vClasses, p->pMap[uTruth] );
+ p->nSubgraphs += vSubgraphs->nSize;
+ // determine the best subgraph
+ GainBest = -1;
+ Vec_PtrForEachEntry( vSubgraphs, pNode, i )
+ {
+ // get the current graph
+ pGraphCur = (Dec_Graph_t *)pNode->pNext;
+
+// if ( pRoot->Id == 8648 )
+// Dec_GraphPrint( stdout, pGraphCur, NULL, NULL );
+ // copy the leaves
+// Vec_PtrForEachEntry( vFaninsCur, pFanin, k )
+// Dec_GraphNode(pGraphCur, k)->pFunc = pFanin;
+ Ivy_GraphPrepare( pGraphCur, pCut, vFaninsCur, pPerm );
+
+ // detect how many unlabeled nodes will be reused
+ nNodesAdded = Ivy_GraphToNetworkSeqCountSeq( pMan, pRoot, pGraphCur, nNodesSaved );
+ if ( nNodesAdded == -1 )
+ continue;
+ assert( nNodesSaved >= nNodesAdded );
+ // count the gain at this node
+ if ( GainBest < nNodesSaved - nNodesAdded )
+ {
+ GainBest = nNodesSaved - nNodesAdded;
+ pGraphBest = pGraphCur;
+ }
+ }
+ if ( GainBest == -1 )
+ return NULL;
+ *pGainBest = GainBest;
+ return pGraphBest;
+}
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Ivy_GraphPrepare( Dec_Graph_t * pGraph, Ivy_Cut_t * pCut, Vec_Ptr_t * vFanins, char * pPerm )
+{
+ Dec_Node_t * pNode, * pNode0, * pNode1;
+ int i;
+ assert( Dec_GraphLeaveNum(pGraph) == pCut->nSize );
+ assert( Vec_PtrSize(vFanins) == pCut->nSize );
+ // label the leaves with latch numbers
+ Dec_GraphForEachLeaf( pGraph, pNode, i )
+ {
+ pNode->pFunc = Vec_PtrEntry( vFanins, i );
+ pNode->nLat2 = Ivy_LeafLat( pCut->pArray[pPerm[i]] );
+ }
+ // propagate latches through the nodes
+ Dec_GraphForEachNode( pGraph, pNode, i )
+ {
+ // get the children of this node
+ pNode0 = Dec_GraphNode( pGraph, pNode->eEdge0.Node );
+ pNode1 = Dec_GraphNode( pGraph, pNode->eEdge1.Node );
+ // distribute the latches
+ pNode->nLat2 = IVY_MIN( pNode0->nLat2, pNode1->nLat2 );
+ pNode->nLat0 = pNode0->nLat2 - pNode->nLat2;
+ pNode->nLat1 = pNode1->nLat2 - pNode->nLat2;
+ }
+}
+
+/**Function*************************************************************
+
+ Synopsis [Counts the number of new nodes added when using this graph.]
+
+ Description [AIG nodes for the fanins should be assigned to pNode->pFunc
+ of the leaves of the graph before calling this procedure.
+ Returns -1 if the number of nodes and levels exceeded the given limit or
+ the number of levels exceeded the maximum allowed level.]
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Ivy_GraphToNetworkSeqCountSeq( Ivy_Man_t * p, Ivy_Obj_t * pRoot, Dec_Graph_t * pGraph, int NodeMax )
+{
+ Dec_Node_t * pNode, * pNode0, * pNode1;
+ Ivy_Obj_t * pAnd, * pAnd0, * pAnd1;
+ int i, k, Counter, fCompl;
+ // check for constant function or a literal
+ if ( Dec_GraphIsConst(pGraph) || Dec_GraphIsVar(pGraph) )
+ return 0;
+ // compute the AIG size after adding the internal nodes
+ Counter = 0;
+ Dec_GraphForEachNode( pGraph, pNode, i )
+ {
+ // get the children of this node
+ pNode0 = Dec_GraphNode( pGraph, pNode->eEdge0.Node );
+ pNode1 = Dec_GraphNode( pGraph, pNode->eEdge1.Node );
+ // get the AIG nodes corresponding to the children
+ pAnd0 = pNode0->pFunc;
+ pAnd1 = pNode1->pFunc;
+ // skip the latches
+ for ( k = 0; pAnd0 && k < (int)pNode->nLat0; k++ )
+ {
+ fCompl = Ivy_IsComplement(pAnd0);
+ pAnd0 = Ivy_TableLookup( p, Ivy_ObjCreateGhost(p, Ivy_Regular(pAnd0), NULL, IVY_LATCH, IVY_INIT_DC) );
+ if ( pAnd0 )
+ pAnd0 = Ivy_NotCond( pAnd0, fCompl );
+ }
+ for ( k = 0; pAnd1 && k < (int)pNode->nLat1; k++ )
+ {
+ fCompl = Ivy_IsComplement(pAnd1);
+ pAnd1 = Ivy_TableLookup( p, Ivy_ObjCreateGhost(p, Ivy_Regular(pAnd1), NULL, IVY_LATCH, IVY_INIT_DC) );
+ if ( pAnd1 )
+ pAnd1 = Ivy_NotCond( pAnd1, fCompl );
+ }
+ // get the new node
+ if ( pAnd0 && pAnd1 )
+ {
+ // if they are both present, find the resulting node
+ pAnd0 = Ivy_NotCond( pAnd0, pNode->eEdge0.fCompl );
+ pAnd1 = Ivy_NotCond( pAnd1, pNode->eEdge1.fCompl );
+ assert( !Ivy_ObjIsLatch(Ivy_Regular(pAnd0)) || !Ivy_ObjIsLatch(Ivy_Regular(pAnd1)) );
+ if ( Ivy_Regular(pAnd0) == Ivy_Regular(pAnd1) || Ivy_ObjIsConst1(Ivy_Regular(pAnd0)) || Ivy_ObjIsConst1(Ivy_Regular(pAnd1)) )
+ pAnd = Ivy_And( p, pAnd0, pAnd1 );
+ else
+ pAnd = Ivy_TableLookup( p, Ivy_ObjCreateGhost(p, pAnd0, pAnd1, IVY_AND, IVY_INIT_NONE) );
+ // return -1 if the node is the same as the original root
+ if ( Ivy_Regular(pAnd) == pRoot )
+ return -1;
+ }
+ else
+ pAnd = NULL;
+ // count the number of added nodes
+ if ( pAnd == NULL || Ivy_ObjIsTravIdCurrent(p, Ivy_Regular(pAnd)) )
+ {
+ if ( ++Counter > NodeMax )
+ return -1;
+ }
+ pNode->pFunc = pAnd;
+ }
+ return Counter;
+}
+
+
+/**Function*************************************************************
+
+ Synopsis [Transforms the decomposition graph into the AIG.]
+
+ Description [AIG nodes for the fanins should be assigned to pNode->pFunc
+ of the leaves of the graph before calling this procedure.]
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Ivy_Obj_t * Ivy_GraphToNetworkSeq( Ivy_Man_t * p, Dec_Graph_t * pGraph )
+{
+ Ivy_Obj_t * pAnd0, * pAnd1;
+ Dec_Node_t * pNode;
+ int i, k;
+ // check for constant function
+ if ( Dec_GraphIsConst(pGraph) )
+ return Ivy_NotCond( Ivy_ManConst1(p), Dec_GraphIsComplement(pGraph) );
+ // check for a literal
+ if ( Dec_GraphIsVar(pGraph) )
+ {
+ // get the variable node
+ pNode = Dec_GraphVar(pGraph);
+ // add the remaining latches
+ for ( k = 0; k < (int)pNode->nLat2; k++ )
+ pNode->pFunc = Ivy_Latch( p, pNode->pFunc, IVY_INIT_DC );
+ return Ivy_NotCond( pNode->pFunc, Dec_GraphIsComplement(pGraph) );
+ }
+ // build the AIG nodes corresponding to the AND gates of the graph
+ Dec_GraphForEachNode( pGraph, pNode, i )
+ {
+ pAnd0 = Ivy_NotCond( Dec_GraphNode(pGraph, pNode->eEdge0.Node)->pFunc, pNode->eEdge0.fCompl );
+ pAnd1 = Ivy_NotCond( Dec_GraphNode(pGraph, pNode->eEdge1.Node)->pFunc, pNode->eEdge1.fCompl );
+ // add the latches
+ for ( k = 0; k < (int)pNode->nLat0; k++ )
+ pAnd0 = Ivy_Latch( p, pAnd0, IVY_INIT_DC );
+ for ( k = 0; k < (int)pNode->nLat1; k++ )
+ pAnd1 = Ivy_Latch( p, pAnd1, IVY_INIT_DC );
+ // create the node
+ pNode->pFunc = Ivy_And( p, pAnd0, pAnd1 );
+ }
+ // add the remaining latches
+ for ( k = 0; k < (int)pNode->nLat2; k++ )
+ pNode->pFunc = Ivy_Latch( p, pNode->pFunc, IVY_INIT_DC );
+ // complement the result if necessary
+ return Ivy_NotCond( pNode->pFunc, Dec_GraphIsComplement(pGraph) );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Replaces MFFC of the node by the new factored form.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Ivy_GraphUpdateNetworkSeq( Ivy_Man_t * p, Ivy_Obj_t * pRoot, Dec_Graph_t * pGraph, int nGain )
+{
+ Ivy_Obj_t * pRootNew;
+ int nNodesNew, nNodesOld;
+ nNodesOld = Ivy_ManNodeNum(p);
+ // create the new structure of nodes
+ pRootNew = Ivy_GraphToNetworkSeq( p, pGraph );
+ Ivy_ObjReplace( p, pRoot, pRootNew, 1, 0, 0 );
+ // compare the gains
+ nNodesNew = Ivy_ManNodeNum(p);
+ assert( nGain <= nNodesOld - nNodesNew );
+ // propagate the buffer
+ Ivy_ManPropagateBuffers( p, 0 );
+}
+
+
+
+
+
+
+
+
+
+/**Function*************************************************************
+
+ Synopsis [Computes the truth table.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+unsigned Ivy_CutGetTruth_rec( Ivy_Man_t * p, int Leaf, int * pNums, int nNums )
+{
+ static unsigned uMasks[5] = { 0xAAAAAAAA, 0xCCCCCCCC, 0xF0F0F0F0, 0xFF00FF00, 0xFFFF0000 };
+ unsigned uTruth0, uTruth1;
+ Ivy_Obj_t * pObj;
+ int i;
+ for ( i = 0; i < nNums; i++ )
+ if ( Leaf == pNums[i] )
+ return uMasks[i];
+ pObj = Ivy_ManObj( p, Ivy_LeafId(Leaf) );
+ if ( Ivy_ObjIsLatch(pObj) )
+ {
+ assert( !Ivy_ObjFaninC0(pObj) );
+ Leaf = Ivy_LeafCreate( Ivy_ObjFaninId0(pObj), Ivy_LeafLat(Leaf) + 1 );
+ return Ivy_CutGetTruth_rec( p, Leaf, pNums, nNums );
+ }
+ assert( Ivy_ObjIsNode(pObj) || Ivy_ObjIsBuf(pObj) );
+ Leaf = Ivy_LeafCreate( Ivy_ObjFaninId0(pObj), Ivy_LeafLat(Leaf) );
+ uTruth0 = Ivy_CutGetTruth_rec( p, Leaf, pNums, nNums );
+ if ( Ivy_ObjFaninC0(pObj) )
+ uTruth0 = ~uTruth0;
+ if ( Ivy_ObjIsBuf(pObj) )
+ return uTruth0;
+ Leaf = Ivy_LeafCreate( Ivy_ObjFaninId1(pObj), Ivy_LeafLat(Leaf) );
+ uTruth1 = Ivy_CutGetTruth_rec( p, Leaf, pNums, nNums );
+ if ( Ivy_ObjFaninC1(pObj) )
+ uTruth1 = ~uTruth1;
+ return uTruth0 & uTruth1;
+}
+
+
+/**Function*************************************************************
+
+ Synopsis [Computes the truth table.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+unsigned Ivy_CutGetTruth( Ivy_Man_t * p, Ivy_Obj_t * pObj, int * pNums, int nNums )
+{
+ assert( Ivy_ObjIsNode(pObj) );
+ assert( nNums < 6 );
+ return Ivy_CutGetTruth_rec( p, Ivy_LeafCreate(pObj->Id, 0), pNums, nNums );
+}
+
+
+
+
+
+/**Function*************************************************************
+
+ Synopsis [Returns 1 if the cut can be constructed; 0 otherwise.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+static inline int Ivy_CutPrescreen( Ivy_Cut_t * pCut, int Id0, int Id1 )
+{
+ int i;
+ if ( pCut->nSize < pCut->nSizeMax )
+ return 1;
+ for ( i = 0; i < pCut->nSize; i++ )
+ if ( pCut->pArray[i] == Id0 || pCut->pArray[i] == Id1 )
+ return 1;
+ return 0;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Derives new cut.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+static inline int Ivy_CutDeriveNew2( Ivy_Cut_t * pCut, Ivy_Cut_t * pCutNew, int IdOld, int IdNew0, int IdNew1 )
+{
+ unsigned uHash = 0;
+ int i, k;
+ assert( pCut->nSize > 0 );
+ assert( IdNew0 < IdNew1 );
+ for ( i = k = 0; i < pCut->nSize; i++ )
+ {
+ if ( pCut->pArray[i] == IdOld )
+ continue;
+ if ( IdNew0 >= 0 )
+ {
+ if ( IdNew0 <= pCut->pArray[i] )
+ {
+ if ( IdNew0 < pCut->pArray[i] )
+ {
+ if ( k == pCut->nSizeMax )
+ return 0;
+ pCutNew->pArray[ k++ ] = IdNew0;
+ uHash |= Ivy_CutHashValue( IdNew0 );
+ }
+ IdNew0 = -1;
+ }
+ }
+ if ( IdNew1 >= 0 )
+ {
+ if ( IdNew1 <= pCut->pArray[i] )
+ {
+ if ( IdNew1 < pCut->pArray[i] )
+ {
+ if ( k == pCut->nSizeMax )
+ return 0;
+ pCutNew->pArray[ k++ ] = IdNew1;
+ uHash |= Ivy_CutHashValue( IdNew1 );
+ }
+ IdNew1 = -1;
+ }
+ }
+ if ( k == pCut->nSizeMax )
+ return 0;
+ pCutNew->pArray[ k++ ] = pCut->pArray[i];
+ uHash |= Ivy_CutHashValue( pCut->pArray[i] );
+ }
+ if ( IdNew0 >= 0 )
+ {
+ if ( k == pCut->nSizeMax )
+ return 0;
+ pCutNew->pArray[ k++ ] = IdNew0;
+ uHash |= Ivy_CutHashValue( IdNew0 );
+ }
+ if ( IdNew1 >= 0 )
+ {
+ if ( k == pCut->nSizeMax )
+ return 0;
+ pCutNew->pArray[ k++ ] = IdNew1;
+ uHash |= Ivy_CutHashValue( IdNew1 );
+ }
+ pCutNew->nSize = k;
+ pCutNew->uHash = uHash;
+ assert( pCutNew->nSize <= pCut->nSizeMax );
+ for ( i = 1; i < pCutNew->nSize; i++ )
+ assert( pCutNew->pArray[i-1] < pCutNew->pArray[i] );
+ return 1;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Derives new cut.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+static inline int Ivy_CutDeriveNew( Ivy_Cut_t * pCut, Ivy_Cut_t * pCutNew, int IdOld, int IdNew0, int IdNew1 )
+{
+ unsigned uHash = 0;
+ int i, k;
+ assert( pCut->nSize > 0 );
+ assert( IdNew0 < IdNew1 );
+ for ( i = k = 0; i < pCut->nSize; i++ )
+ {
+ if ( pCut->pArray[i] == IdOld )
+ continue;
+ if ( IdNew0 <= pCut->pArray[i] )
+ {
+ if ( IdNew0 < pCut->pArray[i] )
+ {
+ pCutNew->pArray[ k++ ] = IdNew0;
+ uHash |= Ivy_CutHashValue( IdNew0 );
+ }
+ IdNew0 = 0x7FFFFFFF;
+ }
+ if ( IdNew1 <= pCut->pArray[i] )
+ {
+ if ( IdNew1 < pCut->pArray[i] )
+ {
+ pCutNew->pArray[ k++ ] = IdNew1;
+ uHash |= Ivy_CutHashValue( IdNew1 );
+ }
+ IdNew1 = 0x7FFFFFFF;
+ }
+ pCutNew->pArray[ k++ ] = pCut->pArray[i];
+ uHash |= Ivy_CutHashValue( pCut->pArray[i] );
+ }
+ if ( IdNew0 < 0x7FFFFFFF )
+ {
+ pCutNew->pArray[ k++ ] = IdNew0;
+ uHash |= Ivy_CutHashValue( IdNew0 );
+ }
+ if ( IdNew1 < 0x7FFFFFFF )
+ {
+ pCutNew->pArray[ k++ ] = IdNew1;
+ uHash |= Ivy_CutHashValue( IdNew1 );
+ }
+ pCutNew->nSize = k;
+ pCutNew->uHash = uHash;
+ assert( pCutNew->nSize <= pCut->nSizeMax );
+// for ( i = 1; i < pCutNew->nSize; i++ )
+// assert( pCutNew->pArray[i-1] < pCutNew->pArray[i] );
+ return 1;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Find the hash value of the cut.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+static inline unsigned Ivy_NodeCutHash( Ivy_Cut_t * pCut )
+{
+ int i;
+ pCut->uHash = 0;
+ for ( i = 0; i < pCut->nSize; i++ )
+ pCut->uHash |= (1 << (pCut->pArray[i] % 31));
+ return pCut->uHash;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Derives new cut.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+static inline int Ivy_CutDeriveNew3( Ivy_Cut_t * pCut, Ivy_Cut_t * pCutNew, int IdOld, int IdNew0, int IdNew1 )
+{
+ int i, k;
+ assert( pCut->nSize > 0 );
+ assert( IdNew0 < IdNew1 );
+ for ( i = k = 0; i < pCut->nSize; i++ )
+ {
+ if ( pCut->pArray[i] == IdOld )
+ continue;
+ if ( IdNew0 <= pCut->pArray[i] )
+ {
+ if ( IdNew0 < pCut->pArray[i] )
+ pCutNew->pArray[ k++ ] = IdNew0;
+ IdNew0 = 0x7FFFFFFF;
+ }
+ if ( IdNew1 <= pCut->pArray[i] )
+ {
+ if ( IdNew1 < pCut->pArray[i] )
+ pCutNew->pArray[ k++ ] = IdNew1;
+ IdNew1 = 0x7FFFFFFF;
+ }
+ pCutNew->pArray[ k++ ] = pCut->pArray[i];
+ }
+ if ( IdNew0 < 0x7FFFFFFF )
+ pCutNew->pArray[ k++ ] = IdNew0;
+ if ( IdNew1 < 0x7FFFFFFF )
+ pCutNew->pArray[ k++ ] = IdNew1;
+ pCutNew->nSize = k;
+ assert( pCutNew->nSize <= pCut->nSizeMax );
+ Ivy_NodeCutHash( pCutNew );
+ return 1;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Returns 1 if pDom is contained in pCut.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+static inline int Ivy_CutCheckDominance( Ivy_Cut_t * pDom, Ivy_Cut_t * pCut )
+{
+ int i, k;
+ for ( i = 0; i < pDom->nSize; i++ )
+ {
+ assert( i==0 || pDom->pArray[i-1] < pDom->pArray[i] );
+ for ( k = 0; k < pCut->nSize; k++ )
+ if ( pDom->pArray[i] == pCut->pArray[k] )
+ break;
+ if ( k == pCut->nSize ) // node i in pDom is not contained in pCut
+ return 0;
+ }
+ // every node in pDom is contained in pCut
+ return 1;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Check if the cut exists.]
+
+ Description [Returns 1 if the cut exists.]
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Ivy_CutFindOrAddFilter( Ivy_Store_t * pCutStore, Ivy_Cut_t * pCutNew )
+{
+ Ivy_Cut_t * pCut;
+ int i, k;
+ assert( pCutNew->uHash );
+ // try to find the cut
+ for ( i = 0; i < pCutStore->nCuts; i++ )
+ {
+ pCut = pCutStore->pCuts + i;
+ if ( pCut->nSize == 0 )
+ continue;
+ if ( pCut->nSize == pCutNew->nSize )
+ {
+ if ( pCut->uHash == pCutNew->uHash )
+ {
+ for ( k = 0; k < pCutNew->nSize; k++ )
+ if ( pCut->pArray[k] != pCutNew->pArray[k] )
+ break;
+ if ( k == pCutNew->nSize )
+ return 1;
+ }
+ continue;
+ }
+ if ( pCut->nSize < pCutNew->nSize )
+ {
+ // skip the non-contained cuts
+ if ( (pCut->uHash & pCutNew->uHash) != pCut->uHash )
+ continue;
+ // check containment seriously
+ if ( Ivy_CutCheckDominance( pCut, pCutNew ) )
+ return 1;
+ continue;
+ }
+ // check potential containment of other cut
+
+ // skip the non-contained cuts
+ if ( (pCut->uHash & pCutNew->uHash) != pCutNew->uHash )
+ continue;
+ // check containment seriously
+ if ( Ivy_CutCheckDominance( pCutNew, pCut ) )
+ {
+ // remove the current cut
+ pCut->nSize = 0;
+ }
+ }
+ assert( pCutStore->nCuts < pCutStore->nCutsMax );
+ // add the cut
+ pCut = pCutStore->pCuts + pCutStore->nCuts++;
+ *pCut = *pCutNew;
+ return 0;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Compresses the cut representation.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Ivy_CutCompactAll( Ivy_Store_t * pCutStore )
+{
+ Ivy_Cut_t * pCut;
+ int i, k;
+ pCutStore->nCutsM = 0;
+ for ( i = k = 0; i < pCutStore->nCuts; i++ )
+ {
+ pCut = pCutStore->pCuts + i;
+ if ( pCut->nSize == 0 )
+ continue;
+ if ( pCut->nSize < pCut->nSizeMax )
+ pCutStore->nCutsM++;
+ pCutStore->pCuts[k++] = *pCut;
+ }
+ pCutStore->nCuts = k;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Print the cut.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Ivy_CutPrintForNode( Ivy_Cut_t * pCut )
+{
+ int i;
+ assert( pCut->nSize > 0 );
+ printf( "%d : {", pCut->nSize );
+ for ( i = 0; i < pCut->nSize; i++ )
+ printf( " %d", pCut->pArray[i] );
+ printf( " }\n" );
+}
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Ivy_CutPrintForNodes( Ivy_Store_t * pCutStore )
+{
+ int i;
+ printf( "Node %d\n", pCutStore->pCuts[0].pArray[0] );
+ for ( i = 0; i < pCutStore->nCuts; i++ )
+ Ivy_CutPrintForNode( pCutStore->pCuts + i );
+}
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+static inline int Ivy_CutReadLeaf( Ivy_Obj_t * pFanin )
+{
+ int nLats, iLeaf;
+ assert( !Ivy_IsComplement(pFanin) );
+ if ( !Ivy_ObjIsLatch(pFanin) )
+ return Ivy_LeafCreate( pFanin->Id, 0 );
+ iLeaf = Ivy_CutReadLeaf(Ivy_ObjFanin0(pFanin));
+ nLats = Ivy_LeafLat(iLeaf);
+ assert( nLats < IVY_LEAF_MASK );
+ return 1 + iLeaf;
+}
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Ivy_Store_t * Ivy_CutComputeForNode( Ivy_Man_t * p, Ivy_Obj_t * pObj, int nLeaves )
+{
+ static Ivy_Store_t CutStore, * pCutStore = &CutStore;
+ Ivy_Cut_t CutNew, * pCutNew = &CutNew, * pCut;
+ Ivy_Man_t * pMan = p;
+ Ivy_Obj_t * pLeaf;
+ int i, k, Temp, nLats, iLeaf0, iLeaf1;
+
+ assert( nLeaves <= IVY_CUT_INPUT );
+
+ // start the structure
+ pCutStore->nCuts = 0;
+ pCutStore->nCutsMax = IVY_CUT_LIMIT;
+ // start the trivial cut
+ pCutNew->uHash = 0;
+ pCutNew->nSize = 1;
+ pCutNew->nSizeMax = nLeaves;
+ pCutNew->pArray[0] = Ivy_LeafCreate( pObj->Id, 0 );
+ pCutNew->uHash = Ivy_CutHashValue( pCutNew->pArray[0] );
+ // add the trivial cut
+ pCutStore->pCuts[pCutStore->nCuts++] = *pCutNew;
+ assert( pCutStore->nCuts == 1 );
+
+ // explore the cuts
+ for ( i = 0; i < pCutStore->nCuts; i++ )
+ {
+ // expand this cut
+ pCut = pCutStore->pCuts + i;
+ if ( pCut->nSize == 0 )
+ continue;
+ for ( k = 0; k < pCut->nSize; k++ )
+ {
+ pLeaf = Ivy_ManObj( p, Ivy_LeafId(pCut->pArray[k]) );
+ if ( Ivy_ObjIsCi(pLeaf) || Ivy_ObjIsConst1(pLeaf) )
+ continue;
+ assert( Ivy_ObjIsNode(pLeaf) );
+ nLats = Ivy_LeafLat(pCut->pArray[k]);
+
+ // get the fanins fanins
+ iLeaf0 = Ivy_CutReadLeaf( Ivy_ObjFanin0(pLeaf) );
+ iLeaf1 = Ivy_CutReadLeaf( Ivy_ObjFanin1(pLeaf) );
+ assert( nLats + Ivy_LeafLat(iLeaf0) < IVY_LEAF_MASK && nLats + Ivy_LeafLat(iLeaf1) < IVY_LEAF_MASK );
+ iLeaf0 = nLats + iLeaf0;
+ iLeaf1 = nLats + iLeaf1;
+ if ( !Ivy_CutPrescreen( pCut, iLeaf0, iLeaf1 ) )
+ continue;
+ // the given cut exist
+ if ( iLeaf0 > iLeaf1 )
+ Temp = iLeaf0, iLeaf0 = iLeaf1, iLeaf1 = Temp;
+ // create the new cut
+ if ( !Ivy_CutDeriveNew( pCut, pCutNew, pCut->pArray[k], iLeaf0, iLeaf1 ) )
+ continue;
+ // add the cut
+ Ivy_CutFindOrAddFilter( pCutStore, pCutNew );
+ if ( pCutStore->nCuts == IVY_CUT_LIMIT )
+ break;
+ }
+ if ( pCutStore->nCuts == IVY_CUT_LIMIT )
+ break;
+ }
+ if ( pCutStore->nCuts == IVY_CUT_LIMIT )
+ pCutStore->fSatur = 1;
+ else
+ pCutStore->fSatur = 0;
+// printf( "%d ", pCutStore->nCuts );
+ Ivy_CutCompactAll( pCutStore );
+// printf( "%d \n", pCutStore->nCuts );
+// Ivy_CutPrintForNodes( pCutStore );
+ return pCutStore;
+}
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Ivy_CutComputeAll( Ivy_Man_t * p, int nInputs )
+{
+ Ivy_Store_t * pStore;
+ Ivy_Obj_t * pObj;
+ int i, nCutsTotal, nCutsTotalM, nNodeTotal, nNodeOver;
+ int clk = clock();
+ if ( nInputs > IVY_CUT_INPUT )
+ {
+ printf( "Cannot compute cuts for more than %d inputs.\n", IVY_CUT_INPUT );
+ return;
+ }
+ nNodeTotal = nNodeOver = 0;
+ nCutsTotal = nCutsTotalM = -Ivy_ManNodeNum(p);
+ Ivy_ManForEachObj( p, pObj, i )
+ {
+ if ( !Ivy_ObjIsNode(pObj) )
+ continue;
+ pStore = Ivy_CutComputeForNode( p, pObj, nInputs );
+ nCutsTotal += pStore->nCuts;
+ nCutsTotalM += pStore->nCutsM;
+ nNodeOver += pStore->fSatur;
+ nNodeTotal++;
+ }
+ printf( "All = %6d. Minus = %6d. Triv = %6d. Node = %6d. Satur = %6d. ",
+ nCutsTotal, nCutsTotalM, Ivy_ManPiNum(p) + Ivy_ManNodeNum(p), nNodeTotal, nNodeOver );
+ PRT( "Time", clock() - clk );
+}
+
+////////////////////////////////////////////////////////////////////////
+/// END OF FILE ///
+////////////////////////////////////////////////////////////////////////
+
+
diff --git a/src/aig/ivy/ivyShow.c b/src/aig/ivy/ivyShow.c
new file mode 100644
index 00000000..cd726e43
--- /dev/null
+++ b/src/aig/ivy/ivyShow.c
@@ -0,0 +1,338 @@
+/**CFile****************************************************************
+
+ FileName [ivyShow.c]
+
+ SystemName [ABC: Logic synthesis and verification system.]
+
+ PackageName [And-Inverter Graph package.]
+
+ Synopsis [Visualization of HAIG.]
+
+ Author [Alan Mishchenko]
+
+ Affiliation [UC Berkeley]
+
+ Date [Ver. 1.0. Started - May 11, 2006.]
+
+ Revision [$Id: ivyShow.c,v 1.00 2006/05/11 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "ivy.h"
+
+////////////////////////////////////////////////////////////////////////
+/// DECLARATIONS ///
+////////////////////////////////////////////////////////////////////////
+
+static void Ivy_WriteDotAig( Ivy_Man_t * pMan, char * pFileName, int fHaig, Vec_Ptr_t * vBold );
+
+////////////////////////////////////////////////////////////////////////
+/// FUNCTION DEFINITIONS ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Ivy_ManShow( Ivy_Man_t * pMan, int fHaig, Vec_Ptr_t * vBold )
+{
+ extern void Abc_ShowFile( char * FileNameDot );
+ static Counter = 0;
+ char FileNameDot[200];
+ FILE * pFile;
+ // create the file name
+// Ivy_ShowGetFileName( pMan->pName, FileNameDot );
+ sprintf( FileNameDot, "temp%02d.dot", Counter++ );
+ // check that the file can be opened
+ if ( (pFile = fopen( FileNameDot, "w" )) == NULL )
+ {
+ fprintf( stdout, "Cannot open the intermediate file \"%s\".\n", FileNameDot );
+ return;
+ }
+ fclose( pFile );
+ // generate the file
+ Ivy_WriteDotAig( pMan, FileNameDot, fHaig, vBold );
+ // visualize the file
+ Abc_ShowFile( FileNameDot );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Writes the graph structure of AIG for DOT.]
+
+ Description [Useful for graph visualization using tools such as GraphViz:
+ http://www.graphviz.org/]
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Ivy_WriteDotAig( Ivy_Man_t * pMan, char * pFileName, int fHaig, Vec_Ptr_t * vBold )
+{
+ FILE * pFile;
+ Ivy_Obj_t * pNode, * pTemp, * pPrev;
+ int LevelMax, Level, i;
+
+ if ( Ivy_ManNodeNum(pMan) > 200 )
+ {
+ fprintf( stdout, "Cannot visualize AIG with more than 200 nodes.\n" );
+ return;
+ }
+ if ( (pFile = fopen( pFileName, "w" )) == NULL )
+ {
+ fprintf( stdout, "Cannot open the intermediate file \"%s\".\n", pFileName );
+ return;
+ }
+
+ // mark the nodes
+ if ( vBold )
+ Vec_PtrForEachEntry( vBold, pNode, i )
+ pNode->fMarkB = 1;
+
+ // compute levels
+ LevelMax = 1 + Ivy_ManSetLevels( pMan, fHaig );
+
+ // write the DOT header
+ fprintf( pFile, "# %s\n", "AIG structure generated by IVY package" );
+ fprintf( pFile, "\n" );
+ fprintf( pFile, "digraph AIG {\n" );
+ fprintf( pFile, "size = \"7.5,10\";\n" );
+// fprintf( pFile, "ranksep = 0.5;\n" );
+// fprintf( pFile, "nodesep = 0.5;\n" );
+ fprintf( pFile, "center = true;\n" );
+// fprintf( pFile, "orientation = landscape;\n" );
+// fprintf( pFile, "edge [fontsize = 10];\n" );
+// fprintf( pFile, "edge [dir = none];\n" );
+ fprintf( pFile, "edge [dir = back];\n" );
+ fprintf( pFile, "\n" );
+
+ // labels on the left of the picture
+ fprintf( pFile, "{\n" );
+ fprintf( pFile, " node [shape = plaintext];\n" );
+ fprintf( pFile, " edge [style = invis];\n" );
+ fprintf( pFile, " LevelTitle1 [label=\"\"];\n" );
+ fprintf( pFile, " LevelTitle2 [label=\"\"];\n" );
+ // generate node names with labels
+ for ( Level = LevelMax; Level >= 0; Level-- )
+ {
+ // the visible node name
+ fprintf( pFile, " Level%d", Level );
+ fprintf( pFile, " [label = " );
+ // label name
+ fprintf( pFile, "\"" );
+ fprintf( pFile, "\"" );
+ fprintf( pFile, "];\n" );
+ }
+
+ // genetate the sequence of visible/invisible nodes to mark levels
+ fprintf( pFile, " LevelTitle1 -> LevelTitle2 ->" );
+ for ( Level = LevelMax; Level >= 0; Level-- )
+ {
+ // the visible node name
+ fprintf( pFile, " Level%d", Level );
+ // the connector
+ if ( Level != 0 )
+ fprintf( pFile, " ->" );
+ else
+ fprintf( pFile, ";" );
+ }
+ fprintf( pFile, "\n" );
+ fprintf( pFile, "}" );
+ fprintf( pFile, "\n" );
+ fprintf( pFile, "\n" );
+
+ // generate title box on top
+ fprintf( pFile, "{\n" );
+ fprintf( pFile, " rank = same;\n" );
+ fprintf( pFile, " LevelTitle1;\n" );
+ fprintf( pFile, " title1 [shape=plaintext,\n" );
+ fprintf( pFile, " fontsize=20,\n" );
+ fprintf( pFile, " fontname = \"Times-Roman\",\n" );
+ fprintf( pFile, " label=\"" );
+ fprintf( pFile, "%s", "AIG structure visualized by ABC" );
+ fprintf( pFile, "\\n" );
+ fprintf( pFile, "Benchmark \\\"%s\\\". ", "aig" );
+ fprintf( pFile, "Time was %s. ", Extra_TimeStamp() );
+ fprintf( pFile, "\"\n" );
+ fprintf( pFile, " ];\n" );
+ fprintf( pFile, "}" );
+ fprintf( pFile, "\n" );
+ fprintf( pFile, "\n" );
+
+ // generate statistics box
+ fprintf( pFile, "{\n" );
+ fprintf( pFile, " rank = same;\n" );
+ fprintf( pFile, " LevelTitle2;\n" );
+ fprintf( pFile, " title2 [shape=plaintext,\n" );
+ fprintf( pFile, " fontsize=18,\n" );
+ fprintf( pFile, " fontname = \"Times-Roman\",\n" );
+ fprintf( pFile, " label=\"" );
+ fprintf( pFile, "The set contains %d logic nodes and spans %d levels.", Ivy_ManNodeNum(pMan), LevelMax );
+ fprintf( pFile, "\\n" );
+ fprintf( pFile, "\"\n" );
+ fprintf( pFile, " ];\n" );
+ fprintf( pFile, "}" );
+ fprintf( pFile, "\n" );
+ fprintf( pFile, "\n" );
+
+ // generate the COs
+ fprintf( pFile, "{\n" );
+ fprintf( pFile, " rank = same;\n" );
+ // the labeling node of this level
+ fprintf( pFile, " Level%d;\n", LevelMax );
+ // generate the CO nodes
+ Ivy_ManForEachCo( pMan, pNode, i )
+ {
+ if ( fHaig || pNode->pEquiv == NULL )
+ fprintf( pFile, " Node%d%s [label = \"%d%s\"", pNode->Id,
+ (Ivy_ObjIsLatch(pNode)? "_in":""), pNode->Id, (Ivy_ObjIsLatch(pNode)? "_in":"") );
+ else
+ fprintf( pFile, " Node%d%s [label = \"%d%s(%d%s)\"", pNode->Id,
+ (Ivy_ObjIsLatch(pNode)? "_in":""), pNode->Id, (Ivy_ObjIsLatch(pNode)? "_in":""),
+ Ivy_Regular(pNode->pEquiv)->Id, Ivy_IsComplement(pNode->pEquiv)? "\'":"" );
+ fprintf( pFile, ", shape = %s", (Ivy_ObjIsLatch(pNode)? "box":"invtriangle") );
+ fprintf( pFile, ", color = coral, fillcolor = coral" );
+ fprintf( pFile, "];\n" );
+ }
+ fprintf( pFile, "}" );
+ fprintf( pFile, "\n" );
+ fprintf( pFile, "\n" );
+
+ // generate nodes of each rank
+ for ( Level = LevelMax - 1; Level > 0; Level-- )
+ {
+ fprintf( pFile, "{\n" );
+ fprintf( pFile, " rank = same;\n" );
+ // the labeling node of this level
+ fprintf( pFile, " Level%d;\n", Level );
+ Ivy_ManForEachObj( pMan, pNode, i )
+ {
+ if ( (int)pNode->Level != Level )
+ continue;
+ if ( fHaig || pNode->pEquiv == NULL )
+ fprintf( pFile, " Node%d [label = \"%d\"", pNode->Id, pNode->Id );
+ else
+ fprintf( pFile, " Node%d [label = \"%d(%d%s)\"", pNode->Id, pNode->Id,
+ Ivy_Regular(pNode->pEquiv)->Id, Ivy_IsComplement(pNode->pEquiv)? "\'":"" );
+ fprintf( pFile, ", shape = ellipse" );
+ if ( vBold && pNode->fMarkB )
+ fprintf( pFile, ", style = filled" );
+ fprintf( pFile, "];\n" );
+ }
+ fprintf( pFile, "}" );
+ fprintf( pFile, "\n" );
+ fprintf( pFile, "\n" );
+ }
+
+ // generate the CI nodes
+ fprintf( pFile, "{\n" );
+ fprintf( pFile, " rank = same;\n" );
+ // the labeling node of this level
+ fprintf( pFile, " Level%d;\n", 0 );
+ // generate constant node
+ if ( Ivy_ObjRefs(Ivy_ManConst1(pMan)) > 0 )
+ {
+ pNode = Ivy_ManConst1(pMan);
+ // check if the costant node is present
+ fprintf( pFile, " Node%d [label = \"Const1\"", pNode->Id );
+ fprintf( pFile, ", shape = ellipse" );
+ fprintf( pFile, ", color = coral, fillcolor = coral" );
+ fprintf( pFile, "];\n" );
+ }
+ // generate the CI nodes
+ Ivy_ManForEachCi( pMan, pNode, i )
+ {
+ if ( fHaig || pNode->pEquiv == NULL )
+ fprintf( pFile, " Node%d%s [label = \"%d%s\"", pNode->Id,
+ (Ivy_ObjIsLatch(pNode)? "_out":""), pNode->Id, (Ivy_ObjIsLatch(pNode)? "_out":"") );
+ else
+ fprintf( pFile, " Node%d%s [label = \"%d%s(%d%s)\"", pNode->Id,
+ (Ivy_ObjIsLatch(pNode)? "_out":""), pNode->Id, (Ivy_ObjIsLatch(pNode)? "_out":""),
+ Ivy_Regular(pNode->pEquiv)->Id, Ivy_IsComplement(pNode->pEquiv)? "\'":"" );
+ fprintf( pFile, ", shape = %s", (Ivy_ObjIsLatch(pNode)? "box":"triangle") );
+ fprintf( pFile, ", color = coral, fillcolor = coral" );
+ fprintf( pFile, "];\n" );
+ }
+ fprintf( pFile, "}" );
+ fprintf( pFile, "\n" );
+ fprintf( pFile, "\n" );
+
+ // generate invisible edges from the square down
+ fprintf( pFile, "title1 -> title2 [style = invis];\n" );
+ Ivy_ManForEachCo( pMan, pNode, i )
+ fprintf( pFile, "title2 -> Node%d%s [style = invis];\n", pNode->Id, (Ivy_ObjIsLatch(pNode)? "_in":"") );
+
+ // generate edges
+ Ivy_ManForEachObj( pMan, pNode, i )
+ {
+ if ( !Ivy_ObjIsNode(pNode) && !Ivy_ObjIsCo(pNode) && !Ivy_ObjIsBuf(pNode) )
+ continue;
+ // generate the edge from this node to the next
+ fprintf( pFile, "Node%d%s", pNode->Id, (Ivy_ObjIsLatch(pNode)? "_in":"") );
+ fprintf( pFile, " -> " );
+ fprintf( pFile, "Node%d%s", Ivy_ObjFaninId0(pNode), (Ivy_ObjIsLatch(Ivy_ObjFanin0(pNode))? "_out":"") );
+ fprintf( pFile, " [" );
+ fprintf( pFile, "style = %s", Ivy_ObjFaninC0(pNode)? "dotted" : "bold" );
+// if ( Ivy_NtkIsSeq(pNode->pMan) && Seq_ObjFaninL0(pNode) > 0 )
+// fprintf( pFile, ", label = \"%s\"", Seq_ObjFaninGetInitPrintable(pNode,0) );
+ fprintf( pFile, "]" );
+ fprintf( pFile, ";\n" );
+ if ( !Ivy_ObjIsNode(pNode) )
+ continue;
+ // generate the edge from this node to the next
+ fprintf( pFile, "Node%d", pNode->Id );
+ fprintf( pFile, " -> " );
+ fprintf( pFile, "Node%d%s", Ivy_ObjFaninId1(pNode), (Ivy_ObjIsLatch(Ivy_ObjFanin1(pNode))? "_out":"") );
+ fprintf( pFile, " [" );
+ fprintf( pFile, "style = %s", Ivy_ObjFaninC1(pNode)? "dotted" : "bold" );
+// if ( Ivy_NtkIsSeq(pNode->pMan) && Seq_ObjFaninL1(pNode) > 0 )
+// fprintf( pFile, ", label = \"%s\"", Seq_ObjFaninGetInitPrintable(pNode,1) );
+ fprintf( pFile, "]" );
+ fprintf( pFile, ";\n" );
+ // generate the edges between the equivalent nodes
+ if ( fHaig && pNode->pEquiv && Ivy_ObjRefs(pNode) > 0 )
+ {
+ pPrev = pNode;
+ for ( pTemp = pNode->pEquiv; pTemp != pNode; pTemp = Ivy_Regular(pTemp->pEquiv) )
+ {
+ fprintf( pFile, "Node%d", pPrev->Id );
+ fprintf( pFile, " -> " );
+ fprintf( pFile, "Node%d", pTemp->Id );
+ fprintf( pFile, " [style = %s]", Ivy_IsComplement(pTemp->pEquiv)? "dotted" : "bold" );
+ fprintf( pFile, ";\n" );
+ pPrev = pTemp;
+ }
+ // connect the last node with the first
+ fprintf( pFile, "Node%d", pPrev->Id );
+ fprintf( pFile, " -> " );
+ fprintf( pFile, "Node%d", pNode->Id );
+ fprintf( pFile, " [style = %s]", Ivy_IsComplement(pPrev->pEquiv)? "dotted" : "bold" );
+ fprintf( pFile, ";\n" );
+ }
+ }
+
+ fprintf( pFile, "}" );
+ fprintf( pFile, "\n" );
+ fprintf( pFile, "\n" );
+ fclose( pFile );
+
+ // unmark nodes
+ if ( vBold )
+ Vec_PtrForEachEntry( vBold, pNode, i )
+ pNode->fMarkB = 0;
+}
+
+
+////////////////////////////////////////////////////////////////////////
+/// END OF FILE ///
+////////////////////////////////////////////////////////////////////////
+
+
diff --git a/src/aig/ivy/ivyTable.c b/src/aig/ivy/ivyTable.c
new file mode 100644
index 00000000..2ac0ae49
--- /dev/null
+++ b/src/aig/ivy/ivyTable.c
@@ -0,0 +1,301 @@
+/**CFile****************************************************************
+
+ FileName [ivyTable.c]
+
+ SystemName [ABC: Logic synthesis and verification system.]
+
+ PackageName [And-Inverter Graph package.]
+
+ Synopsis [Structural hashing table.]
+
+ Author [Alan Mishchenko]
+
+ Affiliation [UC Berkeley]
+
+ Date [Ver. 1.0. Started - May 11, 2006. ]
+
+ Revision [$Id: ivyTable.c,v 1.00 2006/05/11 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "ivy.h"
+
+////////////////////////////////////////////////////////////////////////
+/// DECLARATIONS ///
+////////////////////////////////////////////////////////////////////////
+
+// hashing the node
+static unsigned Ivy_Hash( Ivy_Obj_t * pObj, int TableSize )
+{
+ unsigned Key = Ivy_ObjIsExor(pObj) * 1699;
+ Key ^= Ivy_ObjFaninId0(pObj) * 7937;
+ Key ^= Ivy_ObjFaninId1(pObj) * 2971;
+ Key ^= Ivy_ObjFaninC0(pObj) * 911;
+ Key ^= Ivy_ObjFaninC1(pObj) * 353;
+ Key ^= Ivy_ObjInit(pObj) * 911;
+ return Key % TableSize;
+}
+
+// returns the place where this node is stored (or should be stored)
+static int * Ivy_TableFind( Ivy_Man_t * p, Ivy_Obj_t * pObj )
+{
+ int i;
+ assert( Ivy_ObjIsHash(pObj) );
+ for ( i = Ivy_Hash(pObj, p->nTableSize); p->pTable[i]; i = (i+1) % p->nTableSize )
+ if ( p->pTable[i] == pObj->Id )
+ break;
+ return p->pTable + i;
+}
+
+static void Ivy_TableResize( Ivy_Man_t * p );
+static unsigned int Cudd_PrimeAig( unsigned int p );
+
+////////////////////////////////////////////////////////////////////////
+/// FUNCTION DEFINITIONS ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+ Synopsis [Checks if node with the given attributes is in the hash table.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Ivy_Obj_t * Ivy_TableLookup( Ivy_Man_t * p, Ivy_Obj_t * pObj )
+{
+ Ivy_Obj_t * pEntry;
+ int i;
+ assert( !Ivy_IsComplement(pObj) );
+ if ( !Ivy_ObjIsHash(pObj) )
+ return NULL;
+ assert( Ivy_ObjIsLatch(pObj) || Ivy_ObjFaninId0(pObj) > 0 );
+ assert( Ivy_ObjFaninId1(pObj) == 0 || Ivy_ObjFaninId0(pObj) < Ivy_ObjFaninId1(pObj) );
+ if ( Ivy_ObjFanin0(pObj)->nRefs == 0 || (Ivy_ObjChild1(pObj) && Ivy_ObjFanin1(pObj)->nRefs == 0) )
+ return NULL;
+ for ( i = Ivy_Hash(pObj, p->nTableSize); p->pTable[i]; i = (i+1) % p->nTableSize )
+ {
+ pEntry = Ivy_ManObj( p, p->pTable[i] );
+ if ( Ivy_ObjChild0(pEntry) == Ivy_ObjChild0(pObj) &&
+ Ivy_ObjChild1(pEntry) == Ivy_ObjChild1(pObj) &&
+ Ivy_ObjInit(pEntry) == Ivy_ObjInit(pObj) &&
+ Ivy_ObjType(pEntry) == Ivy_ObjType(pObj) )
+ return pEntry;
+ }
+ return NULL;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Adds the node to the hash table.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Ivy_TableInsert( Ivy_Man_t * p, Ivy_Obj_t * pObj )
+{
+ int * pPlace;
+ assert( !Ivy_IsComplement(pObj) );
+ if ( !Ivy_ObjIsHash(pObj) )
+ return;
+ if ( (pObj->Id & 63) == 0 )
+ {
+ if ( p->nTableSize < 2 * Ivy_ManHashObjNum(p) )
+ Ivy_TableResize( p );
+ }
+ pPlace = Ivy_TableFind( p, pObj );
+ assert( *pPlace == 0 );
+ *pPlace = pObj->Id;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Deletes the node from the hash table.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Ivy_TableDelete( Ivy_Man_t * p, Ivy_Obj_t * pObj )
+{
+ Ivy_Obj_t * pEntry;
+ int i, * pPlace;
+ assert( !Ivy_IsComplement(pObj) );
+ if ( !Ivy_ObjIsHash(pObj) )
+ return;
+ pPlace = Ivy_TableFind( p, pObj );
+ assert( *pPlace == pObj->Id ); // node should be in the table
+ *pPlace = 0;
+ // rehash the adjacent entries
+ i = pPlace - p->pTable;
+ for ( i = (i+1) % p->nTableSize; p->pTable[i]; i = (i+1) % p->nTableSize )
+ {
+ pEntry = Ivy_ManObj( p, p->pTable[i] );
+ p->pTable[i] = 0;
+ Ivy_TableInsert( p, pEntry );
+ }
+}
+
+/**Function*************************************************************
+
+ Synopsis [Updates the table to point to the new node.]
+
+ Description [If the old node (pObj) is in the table, updates the table
+ to point to an object with different ID (ObjIdNew). The table should
+ not contain an object with ObjIdNew (this is currently not checked).]
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Ivy_TableUpdate( Ivy_Man_t * p, Ivy_Obj_t * pObj, int ObjIdNew )
+{
+ int * pPlace;
+ assert( !Ivy_IsComplement(pObj) );
+ if ( !Ivy_ObjIsHash(pObj) )
+ return;
+ pPlace = Ivy_TableFind( p, pObj );
+ assert( *pPlace == pObj->Id ); // node should be in the table
+ *pPlace = ObjIdNew;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Count the number of nodes in the table.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Ivy_TableCountEntries( Ivy_Man_t * p )
+{
+ int i, Counter = 0;
+ for ( i = 0; i < p->nTableSize; i++ )
+ Counter += (p->pTable[i] != 0);
+ return Counter;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Resizes the table.]
+
+ Description [Typically this procedure should not be called.]
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Ivy_TableResize( Ivy_Man_t * p )
+{
+ int * pTableOld, * pPlace;
+ int nTableSizeOld, Counter, nEntries, e, clk;
+clk = clock();
+ // save the old table
+ pTableOld = p->pTable;
+ nTableSizeOld = p->nTableSize;
+ // get the new table
+ p->nTableSize = Cudd_PrimeAig( 5 * Ivy_ManHashObjNum(p) );
+ p->pTable = ALLOC( int, p->nTableSize );
+ memset( p->pTable, 0, sizeof(int) * p->nTableSize );
+ // rehash the entries from the old table
+ Counter = 0;
+ for ( e = 0; e < nTableSizeOld; e++ )
+ {
+ if ( pTableOld[e] == 0 )
+ continue;
+ Counter++;
+ // get the place where this entry goes in the table table
+ pPlace = Ivy_TableFind( p, Ivy_ManObj(p, pTableOld[e]) );
+ assert( *pPlace == 0 ); // should not be in the table
+ *pPlace = pTableOld[e];
+ }
+ nEntries = Ivy_ManHashObjNum(p);
+// assert( Counter == nEntries );
+// printf( "Increasing the structural table size from %6d to %6d. ", nTableSizeOld, p->nTableSize );
+// PRT( "Time", clock() - clk );
+ // replace the table and the parameters
+ free( pTableOld );
+}
+
+/**Function********************************************************************
+
+ Synopsis [Profiles the hash table.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+******************************************************************************/
+void Ivy_TableProfile( Ivy_Man_t * p )
+{
+ int i, Counter = 0;
+ for ( i = 0; i < p->nTableSize; i++ )
+ {
+ if ( p->pTable[i] )
+ Counter++;
+ else if ( Counter )
+ {
+ printf( "%d ", Counter );
+ Counter = 0;
+ }
+ }
+}
+
+/**Function********************************************************************
+
+ Synopsis [Returns the next prime &gt;= p.]
+
+ Description [Copied from CUDD, for stand-aloneness.]
+
+ SideEffects [None]
+
+ SeeAlso []
+
+******************************************************************************/
+unsigned int Cudd_PrimeAig( unsigned int p)
+{
+ int i,pn;
+
+ p--;
+ do {
+ p++;
+ if (p&1) {
+ pn = 1;
+ i = 3;
+ while ((unsigned) (i * i) <= p) {
+ if (p % i == 0) {
+ pn = 0;
+ break;
+ }
+ i += 2;
+ }
+ } else {
+ pn = 0;
+ }
+ } while (!pn);
+ return(p);
+
+} /* end of Cudd_Prime */
+
+////////////////////////////////////////////////////////////////////////
+/// END OF FILE ///
+////////////////////////////////////////////////////////////////////////
+
+
diff --git a/src/aig/ivy/ivyUtil.c b/src/aig/ivy/ivyUtil.c
new file mode 100644
index 00000000..ab62a276
--- /dev/null
+++ b/src/aig/ivy/ivyUtil.c
@@ -0,0 +1,818 @@
+/**CFile****************************************************************
+
+ FileName [ivyUtil.c]
+
+ SystemName [ABC: Logic synthesis and verification system.]
+
+ PackageName [And-Inverter Graph package.]
+
+ Synopsis [Various procedures.]
+
+ Author [Alan Mishchenko]
+
+ Affiliation [UC Berkeley]
+
+ Date [Ver. 1.0. Started - May 11, 2006.]
+
+ Revision [$Id: ivyUtil.c,v 1.00 2006/05/11 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "ivy.h"
+
+////////////////////////////////////////////////////////////////////////
+/// DECLARATIONS ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+/// FUNCTION DEFINITIONS ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+ Synopsis [Increments the current traversal ID of the network.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Ivy_ManIncrementTravId( Ivy_Man_t * p )
+{
+ if ( p->nTravIds >= (1<<30)-1 - 1000 )
+ Ivy_ManCleanTravId( p );
+ p->nTravIds++;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Sets the DFS ordering of the nodes.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Ivy_ManCleanTravId( Ivy_Man_t * p )
+{
+ Ivy_Obj_t * pObj;
+ int i;
+ p->nTravIds = 1;
+ Ivy_ManForEachObj( p, pObj, i )
+ pObj->TravId = 0;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Computes truth table of the cut.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Ivy_ManCollectCut_rec( Ivy_Man_t * p, Ivy_Obj_t * pNode, Vec_Int_t * vNodes )
+{
+ if ( pNode->fMarkA )
+ return;
+ pNode->fMarkA = 1;
+ assert( Ivy_ObjIsAnd(pNode) || Ivy_ObjIsExor(pNode) );
+ Ivy_ManCollectCut_rec( p, Ivy_ObjFanin0(pNode), vNodes );
+ Ivy_ManCollectCut_rec( p, Ivy_ObjFanin1(pNode), vNodes );
+ Vec_IntPush( vNodes, pNode->Id );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Computes truth table of the cut.]
+
+ Description [Does not modify the array of leaves. Uses array vTruth to store
+ temporary truth tables. The returned pointer should be used immediately.]
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Ivy_ManCollectCut( Ivy_Man_t * p, Ivy_Obj_t * pRoot, Vec_Int_t * vLeaves, Vec_Int_t * vNodes )
+{
+ int i, Leaf;
+ // collect and mark the leaves
+ Vec_IntClear( vNodes );
+ Vec_IntForEachEntry( vLeaves, Leaf, i )
+ {
+ Vec_IntPush( vNodes, Leaf );
+ Ivy_ManObj(p, Leaf)->fMarkA = 1;
+ }
+ // collect and mark the nodes
+ Ivy_ManCollectCut_rec( p, pRoot, vNodes );
+ // clean the nodes
+ Vec_IntForEachEntry( vNodes, Leaf, i )
+ Ivy_ManObj(p, Leaf)->fMarkA = 0;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Returns the pointer to the truth table.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+unsigned * Ivy_ObjGetTruthStore( int ObjNum, Vec_Int_t * vTruth )
+{
+ return ((unsigned *)Vec_IntArray(vTruth)) + 8 * ObjNum;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Computes truth table of the cut.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Ivy_ManCutTruthOne( Ivy_Man_t * p, Ivy_Obj_t * pNode, Vec_Int_t * vTruth, int nWords )
+{
+ unsigned * pTruth, * pTruth0, * pTruth1;
+ int i;
+ pTruth = Ivy_ObjGetTruthStore( pNode->TravId, vTruth );
+ pTruth0 = Ivy_ObjGetTruthStore( Ivy_ObjFanin0(pNode)->TravId, vTruth );
+ pTruth1 = Ivy_ObjGetTruthStore( Ivy_ObjFanin1(pNode)->TravId, vTruth );
+ if ( Ivy_ObjIsExor(pNode) )
+ for ( i = 0; i < nWords; i++ )
+ pTruth[i] = pTruth0[i] ^ pTruth1[i];
+ else if ( !Ivy_ObjFaninC0(pNode) && !Ivy_ObjFaninC1(pNode) )
+ for ( i = 0; i < nWords; i++ )
+ pTruth[i] = pTruth0[i] & pTruth1[i];
+ else if ( !Ivy_ObjFaninC0(pNode) && Ivy_ObjFaninC1(pNode) )
+ for ( i = 0; i < nWords; i++ )
+ pTruth[i] = pTruth0[i] & ~pTruth1[i];
+ else if ( Ivy_ObjFaninC0(pNode) && !Ivy_ObjFaninC1(pNode) )
+ for ( i = 0; i < nWords; i++ )
+ pTruth[i] = ~pTruth0[i] & pTruth1[i];
+ else // if ( Ivy_ObjFaninC0(pNode) && Ivy_ObjFaninC1(pNode) )
+ for ( i = 0; i < nWords; i++ )
+ pTruth[i] = ~pTruth0[i] & ~pTruth1[i];
+}
+
+/**Function*************************************************************
+
+ Synopsis [Computes truth table of the cut.]
+
+ Description [Does not modify the array of leaves. Uses array vTruth to store
+ temporary truth tables. The returned pointer should be used immediately.]
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+unsigned * Ivy_ManCutTruth( Ivy_Man_t * p, Ivy_Obj_t * pRoot, Vec_Int_t * vLeaves, Vec_Int_t * vNodes, Vec_Int_t * vTruth )
+{
+ static unsigned uTruths[8][8] = { // elementary truth tables
+ { 0xAAAAAAAA,0xAAAAAAAA,0xAAAAAAAA,0xAAAAAAAA,0xAAAAAAAA,0xAAAAAAAA,0xAAAAAAAA,0xAAAAAAAA },
+ { 0xCCCCCCCC,0xCCCCCCCC,0xCCCCCCCC,0xCCCCCCCC,0xCCCCCCCC,0xCCCCCCCC,0xCCCCCCCC,0xCCCCCCCC },
+ { 0xF0F0F0F0,0xF0F0F0F0,0xF0F0F0F0,0xF0F0F0F0,0xF0F0F0F0,0xF0F0F0F0,0xF0F0F0F0,0xF0F0F0F0 },
+ { 0xFF00FF00,0xFF00FF00,0xFF00FF00,0xFF00FF00,0xFF00FF00,0xFF00FF00,0xFF00FF00,0xFF00FF00 },
+ { 0xFFFF0000,0xFFFF0000,0xFFFF0000,0xFFFF0000,0xFFFF0000,0xFFFF0000,0xFFFF0000,0xFFFF0000 },
+ { 0x00000000,0xFFFFFFFF,0x00000000,0xFFFFFFFF,0x00000000,0xFFFFFFFF,0x00000000,0xFFFFFFFF },
+ { 0x00000000,0x00000000,0xFFFFFFFF,0xFFFFFFFF,0x00000000,0x00000000,0xFFFFFFFF,0xFFFFFFFF },
+ { 0x00000000,0x00000000,0x00000000,0x00000000,0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF }
+ };
+ int i, Leaf;
+ // collect the cut
+ Ivy_ManCollectCut( p, pRoot, vLeaves, vNodes );
+ // set the node numbers
+ Vec_IntForEachEntry( vNodes, Leaf, i )
+ Ivy_ManObj(p, Leaf)->TravId = i;
+ // alloc enough memory
+ Vec_IntClear( vTruth );
+ Vec_IntGrow( vTruth, 8 * Vec_IntSize(vNodes) );
+ // set the elementary truth tables
+ Vec_IntForEachEntry( vLeaves, Leaf, i )
+ memcpy( Ivy_ObjGetTruthStore(i, vTruth), uTruths[i], 8 * sizeof(unsigned) );
+ // compute truths for other nodes
+ Vec_IntForEachEntryStart( vNodes, Leaf, i, Vec_IntSize(vLeaves) )
+ Ivy_ManCutTruthOne( p, Ivy_ManObj(p, Leaf), vTruth, 8 );
+ return Ivy_ObjGetTruthStore( pRoot->TravId, vTruth );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Collect the latches.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Vec_Int_t * Ivy_ManLatches( Ivy_Man_t * p )
+{
+ Vec_Int_t * vLatches;
+ Ivy_Obj_t * pObj;
+ int i;
+ vLatches = Vec_IntAlloc( Ivy_ManLatchNum(p) );
+ Ivy_ManForEachLatch( p, pObj, i )
+ Vec_IntPush( vLatches, pObj->Id );
+ return vLatches;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Collect the latches.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Ivy_ManLevels( Ivy_Man_t * p )
+{
+ Ivy_Obj_t * pObj;
+ int i, LevelMax = 0;
+ Ivy_ManForEachPo( p, pObj, i )
+ LevelMax = IVY_MAX( LevelMax, (int)Ivy_ObjFanin0(pObj)->Level );
+ return LevelMax;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Collect the latches.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Ivy_ManResetLevels_rec( Ivy_Obj_t * pObj )
+{
+ if ( pObj->Level || Ivy_ObjIsCi(pObj) || Ivy_ObjIsConst1(pObj) )
+ return pObj->Level;
+ if ( Ivy_ObjIsBuf(pObj) )
+ return pObj->Level = Ivy_ManResetLevels_rec( Ivy_ObjFanin0(pObj) );
+ assert( Ivy_ObjIsNode(pObj) );
+ Ivy_ManResetLevels_rec( Ivy_ObjFanin0(pObj) );
+ Ivy_ManResetLevels_rec( Ivy_ObjFanin1(pObj) );
+ return pObj->Level = Ivy_ObjLevelNew( pObj );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Collect the latches.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Ivy_ManResetLevels( Ivy_Man_t * p )
+{
+ Ivy_Obj_t * pObj;
+ int i;
+ Ivy_ManForEachObj( p, pObj, i )
+ pObj->Level = 0;
+ Ivy_ManForEachCo( p, pObj, i )
+ Ivy_ManResetLevels_rec( Ivy_ObjFanin0(pObj) );
+}
+
+/**Function*************************************************************
+
+ Synopsis [References/references the node and returns MFFC size.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Ivy_ObjRefDeref( Ivy_Man_t * p, Ivy_Obj_t * pNode, int fReference, int fLabel )
+{
+ Ivy_Obj_t * pNode0, * pNode1;
+ int Counter;
+ // label visited nodes
+ if ( fLabel )
+ Ivy_ObjSetTravIdCurrent( p, pNode );
+ // skip the CI
+ if ( Ivy_ObjIsPi(pNode) )
+ return 0;
+ assert( Ivy_ObjIsNode(pNode) || Ivy_ObjIsBuf(pNode) || Ivy_ObjIsLatch(pNode) );
+ // process the internal node
+ pNode0 = Ivy_ObjFanin0(pNode);
+ pNode1 = Ivy_ObjFanin1(pNode);
+ Counter = Ivy_ObjIsNode(pNode);
+ if ( fReference )
+ {
+ if ( pNode0->nRefs++ == 0 )
+ Counter += Ivy_ObjRefDeref( p, pNode0, fReference, fLabel );
+ if ( pNode1 && pNode1->nRefs++ == 0 )
+ Counter += Ivy_ObjRefDeref( p, pNode1, fReference, fLabel );
+ }
+ else
+ {
+ assert( pNode0->nRefs > 0 );
+ assert( pNode1 == NULL || pNode1->nRefs > 0 );
+ if ( --pNode0->nRefs == 0 )
+ Counter += Ivy_ObjRefDeref( p, pNode0, fReference, fLabel );
+ if ( pNode1 && --pNode1->nRefs == 0 )
+ Counter += Ivy_ObjRefDeref( p, pNode1, fReference, fLabel );
+ }
+ return Counter;
+}
+
+
+/**Function*************************************************************
+
+ Synopsis [Labels MFFC with the current label.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Ivy_ObjMffcLabel( Ivy_Man_t * p, Ivy_Obj_t * pNode )
+{
+ int nConeSize1, nConeSize2;
+ assert( !Ivy_IsComplement( pNode ) );
+ assert( Ivy_ObjIsNode( pNode ) );
+ nConeSize1 = Ivy_ObjRefDeref( p, pNode, 0, 1 ); // dereference
+ nConeSize2 = Ivy_ObjRefDeref( p, pNode, 1, 0 ); // reference
+ assert( nConeSize1 == nConeSize2 );
+ assert( nConeSize1 > 0 );
+ return nConeSize1;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Recursively updates fanout levels.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Ivy_ObjUpdateLevel_rec( Ivy_Man_t * p, Ivy_Obj_t * pObj )
+{
+ Ivy_Obj_t * pFanout;
+ Vec_Ptr_t * vFanouts;
+ int i, LevelNew;
+ assert( p->fFanout );
+ assert( Ivy_ObjIsNode(pObj) );
+ vFanouts = Vec_PtrAlloc( 10 );
+ Ivy_ObjForEachFanout( p, pObj, vFanouts, pFanout, i )
+ {
+ if ( Ivy_ObjIsCo(pFanout) )
+ {
+// assert( (int)Ivy_ObjFanin0(pFanout)->Level <= p->nLevelMax );
+ continue;
+ }
+ LevelNew = Ivy_ObjLevelNew( pFanout );
+ if ( (int)pFanout->Level == LevelNew )
+ continue;
+ pFanout->Level = LevelNew;
+ Ivy_ObjUpdateLevel_rec( p, pFanout );
+ }
+ Vec_PtrFree( vFanouts );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Compute the new required level.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Ivy_ObjLevelRNew( Ivy_Man_t * p, Ivy_Obj_t * pObj )
+{
+ Ivy_Obj_t * pFanout;
+ Vec_Ptr_t * vFanouts;
+ int i, Required, LevelNew = 1000000;
+ assert( p->fFanout && p->vRequired );
+ vFanouts = Vec_PtrAlloc( 10 );
+ Ivy_ObjForEachFanout( p, pObj, vFanouts, pFanout, i )
+ {
+ Required = Vec_IntEntry(p->vRequired, pFanout->Id);
+ LevelNew = IVY_MIN( LevelNew, Required );
+ }
+ Vec_PtrFree( vFanouts );
+ return LevelNew - 1;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Recursively updates fanout levels.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Ivy_ObjUpdateLevelR_rec( Ivy_Man_t * p, Ivy_Obj_t * pObj, int ReqNew )
+{
+ Ivy_Obj_t * pFanin;
+ if ( Ivy_ObjIsConst1(pObj) || Ivy_ObjIsCi(pObj) )
+ return;
+ assert( Ivy_ObjIsNode(pObj) || Ivy_ObjIsBuf(pObj) );
+ // process the first fanin
+ pFanin = Ivy_ObjFanin0(pObj);
+ if ( Vec_IntEntry(p->vRequired, pFanin->Id) > ReqNew - 1 )
+ {
+ Vec_IntWriteEntry( p->vRequired, pFanin->Id, ReqNew - 1 );
+ Ivy_ObjUpdateLevelR_rec( p, pFanin, ReqNew - 1 );
+ }
+ if ( Ivy_ObjIsBuf(pObj) )
+ return;
+ // process the second fanin
+ pFanin = Ivy_ObjFanin1(pObj);
+ if ( Vec_IntEntry(p->vRequired, pFanin->Id) > ReqNew - 1 )
+ {
+ Vec_IntWriteEntry( p->vRequired, pFanin->Id, ReqNew - 1 );
+ Ivy_ObjUpdateLevelR_rec( p, pFanin, ReqNew - 1 );
+ }
+}
+
+/**Function*************************************************************
+
+ Synopsis [Returns 1 if the node is the root of MUX or EXOR/NEXOR.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Ivy_ObjIsMuxType( Ivy_Obj_t * pNode )
+{
+ Ivy_Obj_t * pNode0, * pNode1;
+ // check that the node is regular
+ assert( !Ivy_IsComplement(pNode) );
+ // if the node is not AND, this is not MUX
+ if ( !Ivy_ObjIsAnd(pNode) )
+ return 0;
+ // if the children are not complemented, this is not MUX
+ if ( !Ivy_ObjFaninC0(pNode) || !Ivy_ObjFaninC1(pNode) )
+ return 0;
+ // get children
+ pNode0 = Ivy_ObjFanin0(pNode);
+ pNode1 = Ivy_ObjFanin1(pNode);
+ // if the children are not ANDs, this is not MUX
+ if ( !Ivy_ObjIsAnd(pNode0) || !Ivy_ObjIsAnd(pNode1) )
+ return 0;
+ // otherwise the node is MUX iff it has a pair of equal grandchildren
+ return (Ivy_ObjFaninId0(pNode0) == Ivy_ObjFaninId0(pNode1) && (Ivy_ObjFaninC0(pNode0) ^ Ivy_ObjFaninC0(pNode1))) ||
+ (Ivy_ObjFaninId0(pNode0) == Ivy_ObjFaninId1(pNode1) && (Ivy_ObjFaninC0(pNode0) ^ Ivy_ObjFaninC1(pNode1))) ||
+ (Ivy_ObjFaninId1(pNode0) == Ivy_ObjFaninId0(pNode1) && (Ivy_ObjFaninC1(pNode0) ^ Ivy_ObjFaninC0(pNode1))) ||
+ (Ivy_ObjFaninId1(pNode0) == Ivy_ObjFaninId1(pNode1) && (Ivy_ObjFaninC1(pNode0) ^ Ivy_ObjFaninC1(pNode1)));
+}
+
+/**Function*************************************************************
+
+ Synopsis [Recognizes what nodes are control and data inputs of a MUX.]
+
+ Description [If the node is a MUX, returns the control variable C.
+ Assigns nodes T and E to be the then and else variables of the MUX.
+ Node C is never complemented. Nodes T and E can be complemented.
+ This function also recognizes EXOR/NEXOR gates as MUXes.]
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Ivy_Obj_t * Ivy_ObjRecognizeMux( Ivy_Obj_t * pNode, Ivy_Obj_t ** ppNodeT, Ivy_Obj_t ** ppNodeE )
+{
+ Ivy_Obj_t * pNode0, * pNode1;
+ assert( !Ivy_IsComplement(pNode) );
+ assert( Ivy_ObjIsMuxType(pNode) );
+ // get children
+ pNode0 = Ivy_ObjFanin0(pNode);
+ pNode1 = Ivy_ObjFanin1(pNode);
+ // find the control variable
+// if ( pNode1->p1 == Fraig_Not(pNode2->p1) )
+ if ( Ivy_ObjFaninId0(pNode0) == Ivy_ObjFaninId0(pNode1) && (Ivy_ObjFaninC0(pNode0) ^ Ivy_ObjFaninC0(pNode1)) )
+ {
+// if ( Fraig_IsComplement(pNode1->p1) )
+ if ( Ivy_ObjFaninC0(pNode0) )
+ { // pNode2->p1 is positive phase of C
+ *ppNodeT = Ivy_Not(Ivy_ObjChild1(pNode1));//pNode2->p2);
+ *ppNodeE = Ivy_Not(Ivy_ObjChild1(pNode0));//pNode1->p2);
+ return Ivy_ObjChild0(pNode1);//pNode2->p1;
+ }
+ else
+ { // pNode1->p1 is positive phase of C
+ *ppNodeT = Ivy_Not(Ivy_ObjChild1(pNode0));//pNode1->p2);
+ *ppNodeE = Ivy_Not(Ivy_ObjChild1(pNode1));//pNode2->p2);
+ return Ivy_ObjChild0(pNode0);//pNode1->p1;
+ }
+ }
+// else if ( pNode1->p1 == Fraig_Not(pNode2->p2) )
+ else if ( Ivy_ObjFaninId0(pNode0) == Ivy_ObjFaninId1(pNode1) && (Ivy_ObjFaninC0(pNode0) ^ Ivy_ObjFaninC1(pNode1)) )
+ {
+// if ( Fraig_IsComplement(pNode1->p1) )
+ if ( Ivy_ObjFaninC0(pNode0) )
+ { // pNode2->p2 is positive phase of C
+ *ppNodeT = Ivy_Not(Ivy_ObjChild0(pNode1));//pNode2->p1);
+ *ppNodeE = Ivy_Not(Ivy_ObjChild1(pNode0));//pNode1->p2);
+ return Ivy_ObjChild1(pNode1);//pNode2->p2;
+ }
+ else
+ { // pNode1->p1 is positive phase of C
+ *ppNodeT = Ivy_Not(Ivy_ObjChild1(pNode0));//pNode1->p2);
+ *ppNodeE = Ivy_Not(Ivy_ObjChild0(pNode1));//pNode2->p1);
+ return Ivy_ObjChild0(pNode0);//pNode1->p1;
+ }
+ }
+// else if ( pNode1->p2 == Fraig_Not(pNode2->p1) )
+ else if ( Ivy_ObjFaninId1(pNode0) == Ivy_ObjFaninId0(pNode1) && (Ivy_ObjFaninC1(pNode0) ^ Ivy_ObjFaninC0(pNode1)) )
+ {
+// if ( Fraig_IsComplement(pNode1->p2) )
+ if ( Ivy_ObjFaninC1(pNode0) )
+ { // pNode2->p1 is positive phase of C
+ *ppNodeT = Ivy_Not(Ivy_ObjChild1(pNode1));//pNode2->p2);
+ *ppNodeE = Ivy_Not(Ivy_ObjChild0(pNode0));//pNode1->p1);
+ return Ivy_ObjChild0(pNode1);//pNode2->p1;
+ }
+ else
+ { // pNode1->p2 is positive phase of C
+ *ppNodeT = Ivy_Not(Ivy_ObjChild0(pNode0));//pNode1->p1);
+ *ppNodeE = Ivy_Not(Ivy_ObjChild1(pNode1));//pNode2->p2);
+ return Ivy_ObjChild1(pNode0);//pNode1->p2;
+ }
+ }
+// else if ( pNode1->p2 == Fraig_Not(pNode2->p2) )
+ else if ( Ivy_ObjFaninId1(pNode0) == Ivy_ObjFaninId1(pNode1) && (Ivy_ObjFaninC1(pNode0) ^ Ivy_ObjFaninC1(pNode1)) )
+ {
+// if ( Fraig_IsComplement(pNode1->p2) )
+ if ( Ivy_ObjFaninC1(pNode0) )
+ { // pNode2->p2 is positive phase of C
+ *ppNodeT = Ivy_Not(Ivy_ObjChild0(pNode1));//pNode2->p1);
+ *ppNodeE = Ivy_Not(Ivy_ObjChild0(pNode0));//pNode1->p1);
+ return Ivy_ObjChild1(pNode1);//pNode2->p2;
+ }
+ else
+ { // pNode1->p2 is positive phase of C
+ *ppNodeT = Ivy_Not(Ivy_ObjChild0(pNode0));//pNode1->p1);
+ *ppNodeE = Ivy_Not(Ivy_ObjChild0(pNode1));//pNode2->p1);
+ return Ivy_ObjChild1(pNode0);//pNode1->p2;
+ }
+ }
+ assert( 0 ); // this is not MUX
+ return NULL;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Returns the real fanin.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Ivy_Obj_t * Ivy_ObjReal( Ivy_Obj_t * pObj )
+{
+ Ivy_Obj_t * pFanin;
+ if ( pObj == NULL || !Ivy_ObjIsBuf( Ivy_Regular(pObj) ) )
+ return pObj;
+ pFanin = Ivy_ObjReal( Ivy_ObjChild0(Ivy_Regular(pObj)) );
+ return Ivy_NotCond( pFanin, Ivy_IsComplement(pObj) );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Prints node in HAIG.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Ivy_ObjPrintVerbose( Ivy_Man_t * p, Ivy_Obj_t * pObj, int fHaig )
+{
+ Ivy_Obj_t * pTemp;
+ int fShowFanouts = 0;
+ assert( !Ivy_IsComplement(pObj) );
+ printf( "Node %5d : ", Ivy_ObjId(pObj) );
+ if ( Ivy_ObjIsConst1(pObj) )
+ printf( "constant 1" );
+ else if ( Ivy_ObjIsPi(pObj) )
+ printf( "PI" );
+ else if ( Ivy_ObjIsPo(pObj) )
+ printf( "PO" );
+ else if ( Ivy_ObjIsLatch(pObj) )
+ printf( "latch (%d%s)", Ivy_ObjFanin0(pObj)->Id, (Ivy_ObjFaninC0(pObj)? "\'" : " ") );
+ else if ( Ivy_ObjIsBuf(pObj) )
+ printf( "buffer (%d%s)", Ivy_ObjFanin0(pObj)->Id, (Ivy_ObjFaninC0(pObj)? "\'" : " ") );
+ else
+ printf( "AND( %5d%s, %5d%s )",
+ Ivy_ObjFanin0(pObj)->Id, (Ivy_ObjFaninC0(pObj)? "\'" : " "),
+ Ivy_ObjFanin1(pObj)->Id, (Ivy_ObjFaninC1(pObj)? "\'" : " ") );
+ printf( " (refs = %3d)", Ivy_ObjRefs(pObj) );
+ if ( fShowFanouts )
+ {
+ Vec_Ptr_t * vFanouts;
+ Ivy_Obj_t * pFanout;
+ int i;
+ vFanouts = Vec_PtrAlloc( 10 );
+ printf( "\nFanouts:\n" );
+ Ivy_ObjForEachFanout( p, pObj, vFanouts, pFanout, i )
+ {
+ printf( " " );
+ printf( "Node %5d : ", Ivy_ObjId(pFanout) );
+ if ( Ivy_ObjIsPo(pFanout) )
+ printf( "PO" );
+ else if ( Ivy_ObjIsLatch(pFanout) )
+ printf( "latch (%d%s)", Ivy_ObjFanin0(pFanout)->Id, (Ivy_ObjFaninC0(pFanout)? "\'" : " ") );
+ else if ( Ivy_ObjIsBuf(pFanout) )
+ printf( "buffer (%d%s)", Ivy_ObjFanin0(pFanout)->Id, (Ivy_ObjFaninC0(pFanout)? "\'" : " ") );
+ else
+ printf( "AND( %5d%s, %5d%s )",
+ Ivy_ObjFanin0(pFanout)->Id, (Ivy_ObjFaninC0(pFanout)? "\'" : " "),
+ Ivy_ObjFanin1(pFanout)->Id, (Ivy_ObjFaninC1(pFanout)? "\'" : " ") );
+ printf( "\n" );
+ }
+ Vec_PtrFree( vFanouts );
+ return;
+ }
+ if ( !fHaig )
+ {
+ if ( pObj->pEquiv == NULL )
+ printf( " HAIG node not given" );
+ else
+ printf( " HAIG node = %d%s", Ivy_Regular(pObj->pEquiv)->Id, (Ivy_IsComplement(pObj->pEquiv)? "\'" : " ") );
+ return;
+ }
+ if ( pObj->pEquiv == NULL )
+ return;
+ // there are choices
+ if ( Ivy_ObjRefs(pObj) > 0 )
+ {
+ // print equivalence class
+ printf( " { %5d ", pObj->Id );
+ assert( !Ivy_IsComplement(pObj->pEquiv) );
+ for ( pTemp = pObj->pEquiv; pTemp != pObj; pTemp = Ivy_Regular(pTemp->pEquiv) )
+ printf( " %5d%s", pTemp->Id, (Ivy_IsComplement(pTemp->pEquiv)? "\'" : " ") );
+ printf( " }" );
+ return;
+ }
+ // this is a secondary node
+ for ( pTemp = Ivy_Regular(pObj->pEquiv); Ivy_ObjRefs(pTemp) == 0; pTemp = Ivy_Regular(pTemp->pEquiv) );
+ assert( Ivy_ObjRefs(pTemp) > 0 );
+ printf( " class of %d", pTemp->Id );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Prints node in HAIG.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Ivy_ManPrintVerbose( Ivy_Man_t * p, int fHaig )
+{
+ Vec_Int_t * vNodes;
+ Ivy_Obj_t * pObj;
+ int i;
+ printf( "PIs: " );
+ Ivy_ManForEachPi( p, pObj, i )
+ printf( " %d", pObj->Id );
+ printf( "\n" );
+ printf( "POs: " );
+ Ivy_ManForEachPo( p, pObj, i )
+ printf( " %d", pObj->Id );
+ printf( "\n" );
+ printf( "Latches: " );
+ Ivy_ManForEachLatch( p, pObj, i )
+ printf( " %d=%d%s", pObj->Id, Ivy_ObjFanin0(pObj)->Id, (Ivy_ObjFaninC0(pObj)? "\'" : " ") );
+ printf( "\n" );
+ vNodes = Ivy_ManDfsSeq( p, NULL );
+ Ivy_ManForEachNodeVec( p, vNodes, pObj, i )
+ Ivy_ObjPrintVerbose( p, pObj, fHaig ), printf( "\n" );
+ printf( "\n" );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Performs incremental rewriting of the AIG.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Ivy_CutTruthPrint2( Ivy_Man_t * p, Ivy_Cut_t * pCut, unsigned uTruth )
+{
+ int i;
+ printf( "Trying cut : {" );
+ for ( i = 0; i < pCut->nSize; i++ )
+ printf( " %6d(%d)", Ivy_LeafId(pCut->pArray[i]), Ivy_LeafLat(pCut->pArray[i]) );
+ printf( " } " );
+ Extra_PrintBinary( stdout, &uTruth, 16 ); printf( "\n" );
+ return 0;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Performs incremental rewriting of the AIG.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Ivy_CutTruthPrint( Ivy_Man_t * p, Ivy_Cut_t * pCut, unsigned uTruth )
+{
+ Vec_Ptr_t * vArray;
+ Ivy_Obj_t * pObj, * pFanout;
+ int nLatches = 0;
+ int nPresent = 0;
+ int i, k;
+ int fVerbose = 0;
+
+ if ( fVerbose )
+ printf( "Trying cut : {" );
+ for ( i = 0; i < pCut->nSize; i++ )
+ {
+ if ( fVerbose )
+ printf( " %6d(%d)", Ivy_LeafId(pCut->pArray[i]), Ivy_LeafLat(pCut->pArray[i]) );
+ nLatches += Ivy_LeafLat(pCut->pArray[i]);
+ }
+ if ( fVerbose )
+ printf( " } " );
+ if ( fVerbose )
+ printf( "Latches = %d. ", nLatches );
+
+ // check if there are latches on the fanout edges
+ vArray = Vec_PtrAlloc( 100 );
+ for ( i = 0; i < pCut->nSize; i++ )
+ {
+ pObj = Ivy_ManObj( p, Ivy_LeafId(pCut->pArray[i]) );
+ Ivy_ObjForEachFanout( p, pObj, vArray, pFanout, k )
+ {
+ if ( Ivy_ObjIsLatch(pFanout) )
+ {
+ nPresent++;
+ break;
+ }
+ }
+ }
+ Vec_PtrSize( vArray );
+ if ( fVerbose )
+ {
+ printf( "Present = %d. ", nPresent );
+ if ( nLatches > nPresent )
+ printf( "Clauses = %d. ", 2*(nLatches - nPresent) );
+ printf( "\n" );
+ }
+ return ( nLatches > nPresent ) ? 2*(nLatches - nPresent) : 0;
+}
+
+////////////////////////////////////////////////////////////////////////
+/// END OF FILE ///
+////////////////////////////////////////////////////////////////////////
+
+
diff --git a/src/aig/ivy/ivy_.c b/src/aig/ivy/ivy_.c
new file mode 100644
index 00000000..65689689
--- /dev/null
+++ b/src/aig/ivy/ivy_.c
@@ -0,0 +1,48 @@
+/**CFile****************************************************************
+
+ FileName [ivy_.c]
+
+ SystemName [ABC: Logic synthesis and verification system.]
+
+ PackageName [And-Inverter Graph package.]
+
+ Synopsis []
+
+ Author [Alan Mishchenko]
+
+ Affiliation [UC Berkeley]
+
+ Date [Ver. 1.0. Started - May 11, 2006.]
+
+ Revision [$Id: ivy_.c,v 1.00 2006/05/11 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "ivy.h"
+
+////////////////////////////////////////////////////////////////////////
+/// DECLARATIONS ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+/// FUNCTION DEFINITIONS ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+
+
+////////////////////////////////////////////////////////////////////////
+/// END OF FILE ///
+////////////////////////////////////////////////////////////////////////
+
+
diff --git a/src/aig/ivy/module.make b/src/aig/ivy/module.make
new file mode 100644
index 00000000..daef43df
--- /dev/null
+++ b/src/aig/ivy/module.make
@@ -0,0 +1,22 @@
+SRC += src/aig/ivy/ivyBalance.c \
+ src/aig/ivy/ivyCanon.c \
+ src/aig/ivy/ivyCheck.c \
+ src/aig/ivy/ivyCut.c \
+ src/aig/ivy/ivyCutTrav.c \
+ src/aig/ivy/ivyDfs.c \
+ src/aig/ivy/ivyDsd.c \
+ src/aig/ivy/ivyFanout.c \
+ src/aig/ivy/ivyFastMap.c \
+ src/aig/ivy/ivyFraig.c \
+ src/aig/ivy/ivyHaig.c \
+ src/aig/ivy/ivyMan.c \
+ src/aig/ivy/ivyMem.c \
+ src/aig/ivy/ivyMulti.c \
+ src/aig/ivy/ivyObj.c \
+ src/aig/ivy/ivyOper.c \
+ src/aig/ivy/ivyResyn.c \
+ src/aig/ivy/ivyRwr.c \
+ src/aig/ivy/ivySeq.c \
+ src/aig/ivy/ivyShow.c \
+ src/aig/ivy/ivyTable.c \
+ src/aig/ivy/ivyUtil.c
diff --git a/src/abc8/kit/cloud.c b/src/aig/kit/cloud.c
index 6e6691f0..6e6691f0 100644
--- a/src/abc8/kit/cloud.c
+++ b/src/aig/kit/cloud.c
diff --git a/src/abc8/kit/cloud.h b/src/aig/kit/cloud.h
index ac9d45f4..ac9d45f4 100644
--- a/src/abc8/kit/cloud.h
+++ b/src/aig/kit/cloud.h
diff --git a/src/abc8/kit/kit.h b/src/aig/kit/kit.h
index 2a19a5ac..06a93cf0 100644
--- a/src/abc8/kit/kit.h
+++ b/src/aig/kit/kit.h
@@ -34,8 +34,8 @@ extern "C" {
#include <string.h>
#include <assert.h>
#include <time.h>
-#include "vec2.h"
-//#include "extra.h"
+#include "vec.h"
+#include "extra.h"
#include "cloud.h"
////////////////////////////////////////////////////////////////////////
@@ -485,11 +485,9 @@ static inline void Kit_TruthIthVar( unsigned * pTruth, int nVars, int iVar )
////////////////////////////////////////////////////////////////////////
/*=== 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 );
diff --git a/src/abc8/kit/kitAig.c b/src/aig/kit/kitAig.c
index 83012a8c..83012a8c 100644
--- a/src/abc8/kit/kitAig.c
+++ b/src/aig/kit/kitAig.c
diff --git a/src/abc8/kit/kitBdd.c b/src/aig/kit/kitBdd.c
index 9c8d4f7a..9c8d4f7a 100644
--- a/src/abc8/kit/kitBdd.c
+++ b/src/aig/kit/kitBdd.c
diff --git a/src/abc8/kit/kitCloud.c b/src/aig/kit/kitCloud.c
index 7b160fea..7b160fea 100644
--- a/src/abc8/kit/kitCloud.c
+++ b/src/aig/kit/kitCloud.c
diff --git a/src/abc8/kit/kitDsd.c b/src/aig/kit/kitDsd.c
index e24a9964..e24a9964 100644
--- a/src/abc8/kit/kitDsd.c
+++ b/src/aig/kit/kitDsd.c
diff --git a/src/abc8/kit/kitFactor.c b/src/aig/kit/kitFactor.c
index f596d9a8..f596d9a8 100644
--- a/src/abc8/kit/kitFactor.c
+++ b/src/aig/kit/kitFactor.c
diff --git a/src/abc8/kit/kitGraph.c b/src/aig/kit/kitGraph.c
index 80dcbdc0..80dcbdc0 100644
--- a/src/abc8/kit/kitGraph.c
+++ b/src/aig/kit/kitGraph.c
diff --git a/src/abc8/kit/kitHop.c b/src/aig/kit/kitHop.c
index 86ec5a88..86ec5a88 100644
--- a/src/abc8/kit/kitHop.c
+++ b/src/aig/kit/kitHop.c
diff --git a/src/abc8/kit/kitIsop.c b/src/aig/kit/kitIsop.c
index 42fae2ea..42fae2ea 100644
--- a/src/abc8/kit/kitIsop.c
+++ b/src/aig/kit/kitIsop.c
diff --git a/src/abc8/kit/kitSop.c b/src/aig/kit/kitSop.c
index 20ad0651..20ad0651 100644
--- a/src/abc8/kit/kitSop.c
+++ b/src/aig/kit/kitSop.c
diff --git a/src/abc8/kit/kitTruth.c b/src/aig/kit/kitTruth.c
index dab60132..dab60132 100644
--- a/src/abc8/kit/kitTruth.c
+++ b/src/aig/kit/kitTruth.c
diff --git a/src/abc8/kit/kit_.c b/src/aig/kit/kit_.c
index 5c68ee3c..5c68ee3c 100644
--- a/src/abc8/kit/kit_.c
+++ b/src/aig/kit/kit_.c
diff --git a/src/abc8/kit/module.make b/src/aig/kit/module.make
index 3df3aa1c..ea62381b 100644
--- a/src/abc8/kit/module.make
+++ b/src/aig/kit/module.make
@@ -1,5 +1,7 @@
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 \
diff --git a/src/aig/mem/mem.c b/src/aig/mem/mem.c
new file mode 100644
index 00000000..f5bfbfd8
--- /dev/null
+++ b/src/aig/mem/mem.c
@@ -0,0 +1,604 @@
+/**CFile****************************************************************
+
+ FileName [esopMem.c]
+
+ SystemName [ABC: Logic synthesis and verification system.]
+
+ PackageName [Cover manipulation package.]
+
+ Synopsis [Memory managers.]
+
+ Author [Alan Mishchenko]
+
+ Affiliation [UC Berkeley]
+
+ Date [Ver. 1.0. Started - June 20, 2005.]
+
+ Revision [$Id: esopMem.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <assert.h>
+#include "mem.h"
+
+////////////////////////////////////////////////////////////////////////
+/// DECLARATIONS ///
+////////////////////////////////////////////////////////////////////////
+
+struct Mem_Fixed_t_
+{
+ // information about individual entries
+ int nEntrySize; // the size of one entry
+ int nEntriesAlloc; // the total number of entries allocated
+ int nEntriesUsed; // the number of entries in use
+ int nEntriesMax; // the max number of entries in use
+ char * pEntriesFree; // the linked list of free entries
+
+ // this is where the memory is stored
+ int nChunkSize; // the size of one chunk
+ int nChunksAlloc; // the maximum number of memory chunks
+ int nChunks; // the current number of memory chunks
+ char ** pChunks; // the allocated memory
+
+ // statistics
+ int nMemoryUsed; // memory used in the allocated entries
+ int nMemoryAlloc; // memory allocated
+};
+
+struct Mem_Flex_t_
+{
+ // information about individual entries
+ int nEntriesUsed; // the number of entries allocated
+ char * pCurrent; // the current pointer to free memory
+ char * pEnd; // the first entry outside the free memory
+
+ // this is where the memory is stored
+ int nChunkSize; // the size of one chunk
+ int nChunksAlloc; // the maximum number of memory chunks
+ int nChunks; // the current number of memory chunks
+ char ** pChunks; // the allocated memory
+
+ // statistics
+ int nMemoryUsed; // memory used in the allocated entries
+ int nMemoryAlloc; // memory allocated
+};
+
+struct Mem_Step_t_
+{
+ int nMems; // the number of fixed memory managers employed
+ Mem_Fixed_t ** pMems; // memory managers: 2^1 words, 2^2 words, etc
+ int nMapSize; // the size of the memory array
+ Mem_Fixed_t ** pMap; // maps the number of bytes into its memory manager
+};
+
+#define ALLOC(type, num) ((type *) malloc(sizeof(type) * (num)))
+#define FREE(obj) ((obj) ? (free((char *) (obj)), (obj) = 0) : 0)
+#define REALLOC(type, obj, num) \
+ ((obj) ? ((type *) realloc((char *)(obj), sizeof(type) * (num))) : \
+ ((type *) malloc(sizeof(type) * (num))))
+
+////////////////////////////////////////////////////////////////////////
+/// FUNCTION DEFINITIONS ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+ Synopsis [Allocates memory pieces of fixed size.]
+
+ Description [The size of the chunk is computed as the minimum of
+ 1024 entries and 64K. Can only work with entry size at least 4 byte long.]
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Mem_Fixed_t * Mem_FixedStart( int nEntrySize )
+{
+ Mem_Fixed_t * p;
+
+ p = ALLOC( Mem_Fixed_t, 1 );
+ memset( p, 0, sizeof(Mem_Fixed_t) );
+
+ p->nEntrySize = nEntrySize;
+ p->nEntriesAlloc = 0;
+ p->nEntriesUsed = 0;
+ p->pEntriesFree = NULL;
+
+ if ( nEntrySize * (1 << 10) < (1<<16) )
+ p->nChunkSize = (1 << 10);
+ else
+ p->nChunkSize = (1<<16) / nEntrySize;
+ if ( p->nChunkSize < 8 )
+ p->nChunkSize = 8;
+
+ p->nChunksAlloc = 64;
+ p->nChunks = 0;
+ p->pChunks = ALLOC( char *, p->nChunksAlloc );
+
+ p->nMemoryUsed = 0;
+ p->nMemoryAlloc = 0;
+ return p;
+}
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Mem_FixedStop( Mem_Fixed_t * p, int fVerbose )
+{
+ int i;
+ if ( p == NULL )
+ return;
+ if ( fVerbose )
+ {
+ printf( "Fixed memory manager: Entry = %5d. Chunk = %5d. Chunks used = %5d.\n",
+ p->nEntrySize, p->nChunkSize, p->nChunks );
+ printf( " Entries used = %8d. Entries peak = %8d. Memory used = %8d. Memory alloc = %8d.\n",
+ p->nEntriesUsed, p->nEntriesMax, p->nEntrySize * p->nEntriesUsed, p->nMemoryAlloc );
+ }
+ for ( i = 0; i < p->nChunks; i++ )
+ free( p->pChunks[i] );
+ free( p->pChunks );
+ free( p );
+}
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+char * Mem_FixedEntryFetch( Mem_Fixed_t * p )
+{
+ char * pTemp;
+ int i;
+
+ // check if there are still free entries
+ if ( p->nEntriesUsed == p->nEntriesAlloc )
+ { // need to allocate more entries
+ assert( p->pEntriesFree == NULL );
+ if ( p->nChunks == p->nChunksAlloc )
+ {
+ p->nChunksAlloc *= 2;
+ p->pChunks = REALLOC( char *, p->pChunks, p->nChunksAlloc );
+ }
+ p->pEntriesFree = ALLOC( char, p->nEntrySize * p->nChunkSize );
+ p->nMemoryAlloc += p->nEntrySize * p->nChunkSize;
+ // transform these entries into a linked list
+ pTemp = p->pEntriesFree;
+ for ( i = 1; i < p->nChunkSize; i++ )
+ {
+ *((char **)pTemp) = pTemp + p->nEntrySize;
+ pTemp += p->nEntrySize;
+ }
+ // set the last link
+ *((char **)pTemp) = NULL;
+ // add the chunk to the chunk storage
+ p->pChunks[ p->nChunks++ ] = p->pEntriesFree;
+ // add to the number of entries allocated
+ p->nEntriesAlloc += p->nChunkSize;
+ }
+ // incrememt the counter of used entries
+ p->nEntriesUsed++;
+ if ( p->nEntriesMax < p->nEntriesUsed )
+ p->nEntriesMax = p->nEntriesUsed;
+ // return the first entry in the free entry list
+ pTemp = p->pEntriesFree;
+ p->pEntriesFree = *((char **)pTemp);
+ return pTemp;
+}
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Mem_FixedEntryRecycle( Mem_Fixed_t * p, char * pEntry )
+{
+ // decrement the counter of used entries
+ p->nEntriesUsed--;
+ // add the entry to the linked list of free entries
+ *((char **)pEntry) = p->pEntriesFree;
+ p->pEntriesFree = pEntry;
+}
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description [Relocates all the memory except the first chunk.]
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Mem_FixedRestart( Mem_Fixed_t * p )
+{
+ int i;
+ char * pTemp;
+
+ // deallocate all chunks except the first one
+ for ( i = 1; i < p->nChunks; i++ )
+ free( p->pChunks[i] );
+ p->nChunks = 1;
+ // transform these entries into a linked list
+ pTemp = p->pChunks[0];
+ for ( i = 1; i < p->nChunkSize; i++ )
+ {
+ *((char **)pTemp) = pTemp + p->nEntrySize;
+ pTemp += p->nEntrySize;
+ }
+ // set the last link
+ *((char **)pTemp) = NULL;
+ // set the free entry list
+ p->pEntriesFree = p->pChunks[0];
+ // set the correct statistics
+ p->nMemoryAlloc = p->nEntrySize * p->nChunkSize;
+ p->nMemoryUsed = 0;
+ p->nEntriesAlloc = p->nChunkSize;
+ p->nEntriesUsed = 0;
+}
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Mem_FixedReadMemUsage( Mem_Fixed_t * p )
+{
+ return p->nMemoryAlloc;
+}
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Mem_FixedReadMaxEntriesUsed( Mem_Fixed_t * p )
+{
+ return p->nEntriesMax;
+}
+
+
+
+/**Function*************************************************************
+
+ Synopsis [Allocates entries of flexible size.]
+
+ Description [Can only work with entry size at least 4 byte long.]
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Mem_Flex_t * Mem_FlexStart()
+{
+ Mem_Flex_t * p;
+
+ p = ALLOC( Mem_Flex_t, 1 );
+ memset( p, 0, sizeof(Mem_Flex_t) );
+
+ p->nEntriesUsed = 0;
+ p->pCurrent = NULL;
+ p->pEnd = NULL;
+
+ p->nChunkSize = (1 << 14);
+ p->nChunksAlloc = 64;
+ p->nChunks = 0;
+ p->pChunks = ALLOC( char *, p->nChunksAlloc );
+
+ p->nMemoryUsed = 0;
+ p->nMemoryAlloc = 0;
+ return p;
+}
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Mem_FlexStop( Mem_Flex_t * p, int fVerbose )
+{
+ int i;
+ if ( p == NULL )
+ return;
+ if ( fVerbose )
+ {
+ printf( "Flexible memory manager: Chunk size = %d. Chunks used = %d.\n",
+ p->nChunkSize, p->nChunks );
+ printf( " Entries used = %d. Memory used = %d. Memory alloc = %d.\n",
+ p->nEntriesUsed, p->nMemoryUsed, p->nMemoryAlloc );
+ }
+ for ( i = 0; i < p->nChunks; i++ )
+ free( p->pChunks[i] );
+ free( p->pChunks );
+ free( p );
+}
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+char * Mem_FlexEntryFetch( Mem_Flex_t * p, int nBytes )
+{
+ char * pTemp;
+ // check if there are still free entries
+ if ( p->pCurrent == NULL || p->pCurrent + nBytes > p->pEnd )
+ { // need to allocate more entries
+ if ( p->nChunks == p->nChunksAlloc )
+ {
+ p->nChunksAlloc *= 2;
+ p->pChunks = REALLOC( char *, p->pChunks, p->nChunksAlloc );
+ }
+ if ( nBytes > p->nChunkSize )
+ {
+ // resize the chunk size if more memory is requested than it can give
+ // (ideally, this should never happen)
+ p->nChunkSize = 2 * nBytes;
+ }
+ p->pCurrent = ALLOC( char, p->nChunkSize );
+ p->pEnd = p->pCurrent + p->nChunkSize;
+ p->nMemoryAlloc += p->nChunkSize;
+ // add the chunk to the chunk storage
+ p->pChunks[ p->nChunks++ ] = p->pCurrent;
+ }
+ assert( p->pCurrent + nBytes <= p->pEnd );
+ // increment the counter of used entries
+ p->nEntriesUsed++;
+ // keep track of the memory used
+ p->nMemoryUsed += nBytes;
+ // return the next entry
+ pTemp = p->pCurrent;
+ p->pCurrent += nBytes;
+ return pTemp;
+}
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description [Relocates all the memory except the first chunk.]
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Mem_FlexRestart( Mem_Flex_t * p )
+{
+ int i;
+ if ( p->nChunks == 0 )
+ return;
+ // deallocate all chunks except the first one
+ for ( i = 1; i < p->nChunks; i++ )
+ free( p->pChunks[i] );
+ p->nChunks = 1;
+ p->nMemoryAlloc = p->nChunkSize;
+ // transform these entries into a linked list
+ p->pCurrent = p->pChunks[0];
+ p->pEnd = p->pCurrent + p->nChunkSize;
+ p->nEntriesUsed = 0;
+ p->nMemoryUsed = 0;
+}
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Mem_FlexReadMemUsage( Mem_Flex_t * p )
+{
+ return p->nMemoryUsed;
+}
+
+
+
+
+
+/**Function*************************************************************
+
+ Synopsis [Starts the hierarchical memory manager.]
+
+ Description [This manager can allocate entries of any size.
+ Iternally they are mapped into the entries with the number of bytes
+ equal to the power of 2. The smallest entry size is 8 bytes. The
+ next one is 16 bytes etc. So, if the user requests 6 bytes, he gets
+ 8 byte entry. If we asks for 25 bytes, he gets 32 byte entry etc.
+ The input parameters "nSteps" says how many fixed memory managers
+ are employed internally. Calling this procedure with nSteps equal
+ to 10 results in 10 hierarchically arranged internal memory managers,
+ which can allocate up to 4096 (1Kb) entries. Requests for larger
+ entries are handed over to malloc() and then free()ed.]
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Mem_Step_t * Mem_StepStart( int nSteps )
+{
+ Mem_Step_t * p;
+ int i, k;
+ p = ALLOC( Mem_Step_t, 1 );
+ memset( p, 0, sizeof(Mem_Step_t) );
+ p->nMems = nSteps;
+ // start the fixed memory managers
+ p->pMems = ALLOC( Mem_Fixed_t *, p->nMems );
+ for ( i = 0; i < p->nMems; i++ )
+ p->pMems[i] = Mem_FixedStart( (8<<i) );
+ // set up the mapping of the required memory size into the corresponding manager
+ p->nMapSize = (4<<p->nMems);
+ p->pMap = ALLOC( Mem_Fixed_t *, p->nMapSize+1 );
+ p->pMap[0] = NULL;
+ for ( k = 1; k <= 4; k++ )
+ p->pMap[k] = p->pMems[0];
+ for ( i = 0; i < p->nMems; i++ )
+ for ( k = (4<<i)+1; k <= (8<<i); k++ )
+ p->pMap[k] = p->pMems[i];
+//for ( i = 1; i < 100; i ++ )
+//printf( "%10d: size = %10d\n", i, p->pMap[i]->nEntrySize );
+ return p;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Stops the memory manager.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Mem_StepStop( Mem_Step_t * p, int fVerbose )
+{
+ int i;
+ for ( i = 0; i < p->nMems; i++ )
+ Mem_FixedStop( p->pMems[i], fVerbose );
+// if ( p->pLargeChunks )
+// {
+// for ( i = 0; i < p->nLargeChunks; i++ )
+// free( p->pLargeChunks[i] );
+// free( p->pLargeChunks );
+// }
+ free( p->pMems );
+ free( p->pMap );
+ free( p );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Creates the entry.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+char * Mem_StepEntryFetch( Mem_Step_t * p, int nBytes )
+{
+ if ( nBytes == 0 )
+ return NULL;
+ if ( nBytes > p->nMapSize )
+ {
+// printf( "Allocating %d bytes.\n", nBytes );
+/*
+ if ( p->nLargeChunks == p->nLargeChunksAlloc )
+ {
+ if ( p->nLargeChunksAlloc == 0 )
+ p->nLargeChunksAlloc = 5;
+ p->nLargeChunksAlloc *= 2;
+ p->pLargeChunks = REALLOC( char *, p->pLargeChunks, p->nLargeChunksAlloc );
+ }
+ p->pLargeChunks[ p->nLargeChunks++ ] = ALLOC( char, nBytes );
+ return p->pLargeChunks[ p->nLargeChunks - 1 ];
+*/
+ return ALLOC( char, nBytes );
+ }
+ return Mem_FixedEntryFetch( p->pMap[nBytes] );
+}
+
+
+/**Function*************************************************************
+
+ Synopsis [Recycles the entry.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Mem_StepEntryRecycle( Mem_Step_t * p, char * pEntry, int nBytes )
+{
+ if ( nBytes == 0 )
+ return;
+ if ( nBytes > p->nMapSize )
+ {
+ free( pEntry );
+ return;
+ }
+ Mem_FixedEntryRecycle( p->pMap[nBytes], pEntry );
+}
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Mem_StepReadMemUsage( Mem_Step_t * p )
+{
+ int i, nMemTotal = 0;
+ for ( i = 0; i < p->nMems; i++ )
+ nMemTotal += p->pMems[i]->nMemoryAlloc;
+ return nMemTotal;
+}
+
+////////////////////////////////////////////////////////////////////////
+/// END OF FILE ///
+////////////////////////////////////////////////////////////////////////
diff --git a/src/aig/mem/mem.h b/src/aig/mem/mem.h
new file mode 100644
index 00000000..d43e5fc3
--- /dev/null
+++ b/src/aig/mem/mem.h
@@ -0,0 +1,72 @@
+/**CFile****************************************************************
+
+ FileName [mem.h]
+
+ SystemName [ABC: Logic synthesis and verification system.]
+
+ PackageName [Memory management.]
+
+ Synopsis [External declarations.]
+
+ Author [Alan Mishchenko]
+
+ Affiliation [UC Berkeley]
+
+ Date [Ver. 1.0. Started - June 20, 2005.]
+
+ Revision [$Id: mem.h,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#ifndef __MEM_H__
+#define __MEM_H__
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+////////////////////////////////////////////////////////////////////////
+/// DECLARATIONS ///
+////////////////////////////////////////////////////////////////////////
+
+typedef struct Mem_Fixed_t_ Mem_Fixed_t;
+typedef struct Mem_Flex_t_ Mem_Flex_t;
+typedef struct Mem_Step_t_ Mem_Step_t;
+
+////////////////////////////////////////////////////////////////////////
+/// FUNCTION DEFINITIONS ///
+////////////////////////////////////////////////////////////////////////
+
+/*=== mem.c ===========================================================*/
+// fixed-size-block memory manager
+extern Mem_Fixed_t * Mem_FixedStart( int nEntrySize );
+extern void Mem_FixedStop( Mem_Fixed_t * p, int fVerbose );
+extern char * Mem_FixedEntryFetch( Mem_Fixed_t * p );
+extern void Mem_FixedEntryRecycle( Mem_Fixed_t * p, char * pEntry );
+extern void Mem_FixedRestart( Mem_Fixed_t * p );
+extern int Mem_FixedReadMemUsage( Mem_Fixed_t * p );
+extern int Mem_FixedReadMaxEntriesUsed( Mem_Fixed_t * p );
+// flexible-size-block memory manager
+extern Mem_Flex_t * Mem_FlexStart();
+extern void Mem_FlexStop( Mem_Flex_t * p, int fVerbose );
+extern char * Mem_FlexEntryFetch( Mem_Flex_t * p, int nBytes );
+extern void Mem_FlexRestart( Mem_Flex_t * p );
+extern int Mem_FlexReadMemUsage( Mem_Flex_t * p );
+// hierarchical memory manager
+extern Mem_Step_t * Mem_StepStart( int nSteps );
+extern void Mem_StepStop( Mem_Step_t * p, int fVerbose );
+extern char * Mem_StepEntryFetch( Mem_Step_t * p, int nBytes );
+extern void Mem_StepEntryRecycle( Mem_Step_t * p, char * pEntry, int nBytes );
+extern int Mem_StepReadMemUsage( Mem_Step_t * p );
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
+
+////////////////////////////////////////////////////////////////////////
+/// END OF FILE ///
+////////////////////////////////////////////////////////////////////////
+
+
diff --git a/src/aig/mem/module.make b/src/aig/mem/module.make
new file mode 100644
index 00000000..ae6fcbe4
--- /dev/null
+++ b/src/aig/mem/module.make
@@ -0,0 +1 @@
+SRC += src/aig/mem/mem.c
diff --git a/src/aig/ntl/module.make b/src/aig/ntl/module.make
new file mode 100644
index 00000000..f47108a4
--- /dev/null
+++ b/src/aig/ntl/module.make
@@ -0,0 +1,11 @@
+SRC += src/aig/ntl/ntlAig.c \
+ src/aig/ntl/ntlCheck.c \
+ src/aig/ntl/ntlDfs.c \
+ src/aig/ntl/ntlMan.c \
+ src/aig/ntl/ntlMap.c \
+ src/aig/ntl/ntlObj.c \
+ src/aig/ntl/ntlReadBlif.c \
+ src/aig/ntl/ntlTable.c \
+ src/aig/ntl/ntlTime.c \
+ src/aig/ntl/ntlWriteBlif.c
+
diff --git a/src/aig/ntl/ntl.h b/src/aig/ntl/ntl.h
new file mode 100644
index 00000000..dbd8676b
--- /dev/null
+++ b/src/aig/ntl/ntl.h
@@ -0,0 +1,277 @@
+/**CFile****************************************************************
+
+ FileName [ntl.h]
+
+ SystemName [ABC: Logic synthesis and verification system.]
+
+ PackageName [Netlist representation.]
+
+ Synopsis [External declarations.]
+
+ Author [Alan Mishchenko]
+
+ Affiliation [UC Berkeley]
+
+ Date [Ver. 1.0. Started - June 20, 2005.]
+
+ Revision [$Id: .h,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#ifndef __NTL_H__
+#define __NTL_H__
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+////////////////////////////////////////////////////////////////////////
+/// INCLUDES ///
+////////////////////////////////////////////////////////////////////////
+
+#include "aig.h"
+#include "tim.h"
+
+////////////////////////////////////////////////////////////////////////
+/// PARAMETERS ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+/// BASIC TYPES ///
+////////////////////////////////////////////////////////////////////////
+
+typedef struct Ntl_Man_t_ Ntl_Man_t;
+typedef struct Ntl_Mod_t_ Ntl_Mod_t;
+typedef struct Ntl_Obj_t_ Ntl_Obj_t;
+typedef struct Ntl_Net_t_ Ntl_Net_t;
+typedef struct Ntl_Lut_t_ Ntl_Lut_t;
+
+// object types
+typedef enum {
+ NTL_OBJ_NONE, // 0: non-existent object
+ NTL_OBJ_PI, // 1: primary input
+ NTL_OBJ_PO, // 2: primary output
+ NTL_OBJ_LATCH, // 3: latch node
+ NTL_OBJ_NODE, // 4: logic node
+ NTL_OBJ_BOX, // 5: white box or black box
+ NTL_OBJ_VOID // 6: unused object
+} Ntl_Type_t;
+
+struct Ntl_Man_t_
+{
+ // models of this design
+ char * pName; // the name of this design
+ char * pSpec; // the name of input file
+ Vec_Ptr_t * vModels; // the array of all models used to represent boxes
+ // memory managers
+ Aig_MmFlex_t * pMemObjs; // memory for objects
+ Aig_MmFlex_t * pMemSops; // memory for SOPs
+ // extracted representation
+ Vec_Ptr_t * vCis; // the primary inputs of the extracted part
+ Vec_Ptr_t * vCos; // the primary outputs of the extracted part
+ Vec_Ptr_t * vNodes; // the nodes of the abstracted part
+ Vec_Int_t * vBox1Cos; // the first COs of the boxes
+ Aig_Man_t * pAig; // the extracted AIG
+ Tim_Man_t * pManTime; // the timing manager
+};
+
+struct Ntl_Mod_t_
+{
+ // model description
+ Ntl_Man_t * pMan; // the model manager
+ char * pName; // the model name
+ Vec_Ptr_t * vObjs; // the array of all objects
+ Vec_Ptr_t * vPis; // the array of PI objects
+ Vec_Ptr_t * vPos; // the array of PO objects
+ int nObjs[NTL_OBJ_VOID]; // counter of objects of each type
+ // hashing names into nets
+ Ntl_Net_t ** pTable; // the hash table of names into nets
+ int nTableSize; // the allocated table size
+ int nEntries; // the number of entries in the hash table
+ // delay information
+ Vec_Int_t * vDelays;
+ Vec_Int_t * vArrivals;
+ Vec_Int_t * vRequireds;
+ float * pDelayTable;
+};
+
+struct Ntl_Obj_t_
+{
+ Ntl_Mod_t * pModel; // the model
+ unsigned Type : 3; // object type
+ unsigned Id : 27; // object ID
+ unsigned MarkA : 1; // temporary mark
+ unsigned MarkB : 1; // temporary mark
+ short nFanins; // the number of fanins
+ short nFanouts; // the number of fanouts
+ union { // functionality
+ Ntl_Mod_t * pImplem; // model (for boxes)
+ char * pSop; // SOP (for logic nodes)
+ unsigned LatchId; // init state + register class (for latches)
+ };
+ Ntl_Net_t * pFanio[0]; // fanins/fanouts
+};
+
+struct Ntl_Net_t_
+{
+ Ntl_Obj_t * pDriver; // driver of the net
+ Ntl_Net_t * pNext; // next net in the hash table
+ Aig_Obj_t * pFunc; // the AIG representation
+ char nVisits; // the number of times the net is visited
+ char fMark; // temporary mark
+ char pName[0]; // the name of this net
+};
+
+struct Ntl_Lut_t_
+{
+ int Id; // the ID of the root AIG node
+ int nFanins; // the number of fanins
+ int * pFanins; // the array of fanins
+ unsigned * pTruth; // the truth table
+};
+
+////////////////////////////////////////////////////////////////////////
+/// MACRO DEFINITIONS ///
+////////////////////////////////////////////////////////////////////////
+
+
+////////////////////////////////////////////////////////////////////////
+/// INLINED FUNCTIONS ///
+////////////////////////////////////////////////////////////////////////
+
+static inline int Ntl_ModelPiNum( Ntl_Mod_t * p ) { return p->nObjs[NTL_OBJ_PI]; }
+static inline int Ntl_ModelPoNum( Ntl_Mod_t * p ) { return p->nObjs[NTL_OBJ_PO]; }
+static inline int Ntl_ModelNodeNum( Ntl_Mod_t * p ) { return p->nObjs[NTL_OBJ_NODE]; }
+static inline int Ntl_ModelLatchNum( Ntl_Mod_t * p ) { return p->nObjs[NTL_OBJ_LATCH]; }
+static inline int Ntl_ModelBoxNum( Ntl_Mod_t * p ) { return p->nObjs[NTL_OBJ_BOX]; }
+static inline int Ntl_ModelCiNum( Ntl_Mod_t * p ) { return p->nObjs[NTL_OBJ_PI] + p->nObjs[NTL_OBJ_LATCH]; }
+static inline int Ntl_ModelCoNum( Ntl_Mod_t * p ) { return p->nObjs[NTL_OBJ_PO] + p->nObjs[NTL_OBJ_LATCH]; }
+
+static inline Ntl_Obj_t * Ntl_ModelPi( Ntl_Mod_t * p, int i ) { return Vec_PtrEntry(p->vPis, i); }
+static inline Ntl_Obj_t * Ntl_ModelPo( Ntl_Mod_t * p, int i ) { return Vec_PtrEntry(p->vPos, i); }
+
+static inline char * Ntl_ModelPiName( Ntl_Mod_t * p, int i ) { return Ntl_ModelPi(p, i)->pFanio[0]->pName; }
+static inline char * Ntl_ModelPoName( Ntl_Mod_t * p, int i ) { return Ntl_ModelPo(p, i)->pFanio[0]->pName; }
+
+static inline int Ntl_ModelIsBlackBox( Ntl_Mod_t * p ) { return Ntl_ModelPiNum(p) + Ntl_ModelPoNum(p) == Vec_PtrSize(p->vObjs); }
+
+static inline int Ntl_ObjFaninNum( Ntl_Obj_t * p ) { return p->nFanins; }
+static inline int Ntl_ObjFanoutNum( Ntl_Obj_t * p ) { return p->nFanouts; }
+
+static inline int Ntl_ObjIsPi( Ntl_Obj_t * p ) { return p->Type == NTL_OBJ_PI; }
+static inline int Ntl_ObjIsPo( Ntl_Obj_t * p ) { return p->Type == NTL_OBJ_PO; }
+static inline int Ntl_ObjIsNode( Ntl_Obj_t * p ) { return p->Type == NTL_OBJ_NODE; }
+static inline int Ntl_ObjIsLatch( Ntl_Obj_t * p ) { return p->Type == NTL_OBJ_LATCH; }
+static inline int Ntl_ObjIsBox( Ntl_Obj_t * p ) { return p->Type == NTL_OBJ_BOX; }
+
+static inline Ntl_Net_t * Ntl_ObjFanin0( Ntl_Obj_t * p ) { return p->pFanio[0]; }
+static inline Ntl_Net_t * Ntl_ObjFanout0( Ntl_Obj_t * p ) { return p->pFanio[p->nFanins]; }
+
+static inline Ntl_Net_t * Ntl_ObjFanin( Ntl_Obj_t * p, int i ) { return p->pFanio[i]; }
+static inline Ntl_Net_t * Ntl_ObjFanout( Ntl_Obj_t * p, int i ) { return p->pFanio[p->nFanins+1]; }
+
+static inline void Ntl_ObjSetFanin( Ntl_Obj_t * p, Ntl_Net_t * pNet, int i ) { p->pFanio[i] = pNet; }
+static inline void Ntl_ObjSetFanout( Ntl_Obj_t * p, Ntl_Net_t * pNet, int i ) { p->pFanio[p->nFanins+i] = pNet; pNet->pDriver = p; }
+
+////////////////////////////////////////////////////////////////////////
+/// ITERATORS ///
+////////////////////////////////////////////////////////////////////////
+
+#define Ntl_ManForEachModel( p, pNtl, i ) \
+ Vec_PtrForEachEntry( p->vModels, pNtl, i )
+#define Ntl_ManForEachCiNet( p, pNtl, i ) \
+ Vec_PtrForEachEntry( p->vCis, pNtl, i )
+#define Ntl_ManForEachCoNet( p, pNtl, i ) \
+ Vec_PtrForEachEntry( p->vCos, pNtl, i )
+#define Ntl_ManForEachNode( p, pObj, i ) \
+ for ( i = 0; (i < Vec_PtrSize(p->vNodes)) && (((pObj) = Vec_PtrEntry(p->vNodes, i)), 1); i++ ) \
+ if ( !Ntl_ObjIsNode(pObj) ) {} else
+#define Ntl_ManForEachBox( p, pObj, i ) \
+ for ( i = 0; (i < Vec_PtrSize(p->vNodes)) && (((pObj) = Vec_PtrEntry(p->vNodes, i)), 1); i++ ) \
+ if ( !Ntl_ObjIsBox(pObj) ) {} else
+
+#define Ntl_ModelForEachPi( pNtl, pObj, i ) \
+ Vec_PtrForEachEntry( pNtl->vPis, pObj, i )
+#define Ntl_ModelForEachPo( pNtl, pObj, i ) \
+ Vec_PtrForEachEntry( pNtl->vPos, pObj, i )
+#define Ntl_ModelForEachObj( pNtl, pObj, i ) \
+ for ( i = 0; (i < Vec_PtrSize(pNtl->vObjs)) && (((pObj) = Vec_PtrEntry(pNtl->vObjs, i)), 1); i++ ) \
+ if ( pObj == NULL ) {} else
+#define Ntl_ModelForEachLatch( pNtl, pObj, i ) \
+ for ( i = 0; (i < Vec_PtrSize(pNtl->vObjs)) && (((pObj) = Vec_PtrEntry(pNtl->vObjs, i)), 1); i++ ) \
+ if ( !Ntl_ObjIsLatch(pObj) ) {} else
+#define Ntl_ModelForEachNode( pNtl, pObj, i ) \
+ for ( i = 0; (i < Vec_PtrSize(pNtl->vObjs)) && (((pObj) = Vec_PtrEntry(pNtl->vObjs, i)), 1); i++ ) \
+ if ( !Ntl_ObjIsNode(pObj) ) {} else
+#define Ntl_ModelForEachBox( pNtl, pObj, i ) \
+ for ( i = 0; (i < Vec_PtrSize(pNtl->vObjs)) && (((pObj) = Vec_PtrEntry(pNtl->vObjs, i)), 1); i++ ) \
+ if ( !Ntl_ObjIsBox(pObj) ) {} else
+#define Ntl_ModelForEachNet( pNtl, pNet, i ) \
+ for ( i = 0; i < pNtl->nTableSize; i++ ) \
+ for ( pNet = pNtl->pTable[i]; pNet; pNet = pNet->pNext )
+
+#define Ntl_ObjForEachFanin( pObj, pFanin, i ) \
+ for ( i = 0; (i < (pObj)->nFanins) && ((pFanin) = (pObj)->pFanio[i]); i++ )
+#define Ntl_ObjForEachFanout( pObj, pFanout, i ) \
+ for ( i = 0; (i < (pObj)->nFanouts) && ((pFanout) = (pObj)->pFanio[(pObj)->nFanins+i]); i++ )
+
+////////////////////////////////////////////////////////////////////////
+/// FUNCTION DECLARATIONS ///
+////////////////////////////////////////////////////////////////////////
+
+/*=== ntlAig.c ==========================================================*/
+extern Aig_Obj_t * Ntl_ManExtractAigNode( Ntl_Obj_t * pNode );
+extern int Ntl_ManExtract( Ntl_Man_t * p );
+extern int Ntl_ManInsert( Ntl_Man_t * p, Vec_Ptr_t * vMapping );
+extern int Ntl_ManInsertTest( Ntl_Man_t * p );
+extern int Ntl_ManInsertTestFpga( Ntl_Man_t * p );
+extern int Ntl_ManInsertTestIf( Ntl_Man_t * p );
+/*=== ntlCheck.c ==========================================================*/
+extern int Ntl_ManCheck( Ntl_Man_t * pMan );
+extern int Ntl_ModelCheck( Ntl_Mod_t * pModel );
+extern void Ntl_ModelFixNonDrivenNets( Ntl_Mod_t * pModel );
+/*=== ntlDfs.c ==========================================================*/
+extern int Ntl_ManDfs( Ntl_Man_t * p );
+/*=== ntlMan.c ============================================================*/
+extern Ntl_Man_t * Ntl_ManAlloc( char * pFileName );
+extern void Ntl_ManFree( Ntl_Man_t * p );
+extern Ntl_Mod_t * Ntl_ManFindModel( Ntl_Man_t * p, char * pName );
+extern void Ntl_ManPrintStats( Ntl_Man_t * p );
+extern Ntl_Mod_t * Ntl_ModelAlloc( Ntl_Man_t * pMan, char * pName );
+extern void Ntl_ModelFree( Ntl_Mod_t * p );
+/*=== ntlMap.c ============================================================*/
+extern Vec_Ptr_t * Ntl_MappingAlloc( int nLuts, int nVars );
+extern Vec_Ptr_t * Ntl_MappingFromAig( Aig_Man_t * p );
+extern Vec_Ptr_t * Ntl_MappingFpga( Aig_Man_t * p );
+extern Vec_Ptr_t * Ntl_MappingIf( Ntl_Man_t * pMan, Aig_Man_t * p );
+/*=== ntlObj.c ============================================================*/
+extern Ntl_Obj_t * Ntl_ModelCreatePi( Ntl_Mod_t * pModel );
+extern Ntl_Obj_t * Ntl_ModelCreatePo( Ntl_Mod_t * pModel, Ntl_Net_t * pNet );
+extern Ntl_Obj_t * Ntl_ModelCreateLatch( Ntl_Mod_t * pModel );
+extern Ntl_Obj_t * Ntl_ModelCreateNode( Ntl_Mod_t * pModel, int nFanins );
+extern Ntl_Obj_t * Ntl_ModelCreateBox( Ntl_Mod_t * pModel, int nFanins, int nFanouts );
+extern char * Ntl_ManStoreName( Ntl_Man_t * p, char * pName );
+extern char * Ntl_ManStoreSop( Ntl_Man_t * p, char * pSop );
+extern char * Ntl_ManStoreFileName( Ntl_Man_t * p, char * pFileName );
+/*=== ntlTable.c ==========================================================*/
+extern Ntl_Net_t * Ntl_ModelFindNet( Ntl_Mod_t * p, char * pName );
+extern Ntl_Net_t * Ntl_ModelFindOrCreateNet( Ntl_Mod_t * p, char * pName );
+extern int Ntl_ModelSetNetDriver( Ntl_Obj_t * pObj, Ntl_Net_t * pNet );
+extern int Ntl_ModelFindPioNumber( Ntl_Mod_t * p, char * pName, int * pNumber );
+/*=== ntlTime.c ==========================================================*/
+extern Tim_Man_t * Ntl_ManCreateTiming( Ntl_Man_t * p );
+/*=== ntlReadBlif.c ==========================================================*/
+extern Ntl_Man_t * Ioa_ReadBlif( char * pFileName, int fCheck );
+/*=== ntlWriteBlif.c ==========================================================*/
+extern void Ioa_WriteBlif( Ntl_Man_t * p, char * pFileName );
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
+
+////////////////////////////////////////////////////////////////////////
+/// END OF FILE ///
+////////////////////////////////////////////////////////////////////////
+
diff --git a/src/aig/ntl/ntlAig.c b/src/aig/ntl/ntlAig.c
new file mode 100644
index 00000000..c0a122d3
--- /dev/null
+++ b/src/aig/ntl/ntlAig.c
@@ -0,0 +1,596 @@
+/**CFile****************************************************************
+
+ FileName [ntlAig.c]
+
+ SystemName [ABC: Logic synthesis and verification system.]
+
+ PackageName [Netlist representation.]
+
+ Synopsis [Netlist SOP to AIG conversion.]
+
+ Author [Alan Mishchenko]
+
+ Affiliation [UC Berkeley]
+
+ Date [Ver. 1.0. Started - June 20, 2005.]
+
+ Revision [$Id: ntlAig.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "ntl.h"
+#include "dec.h"
+#include "kit.h"
+
+////////////////////////////////////////////////////////////////////////
+/// DECLARATIONS ///
+////////////////////////////////////////////////////////////////////////
+
+#define Ntl_SopForEachCube( pSop, nFanins, pCube ) \
+ for ( pCube = (pSop); *pCube; pCube += (nFanins) + 3 )
+#define Ntl_CubeForEachVar( pCube, Value, i ) \
+ for ( i = 0; (pCube[i] != ' ') && (Value = pCube[i]); i++ )
+
+////////////////////////////////////////////////////////////////////////
+/// FUNCTION DEFINITIONS ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+ Synopsis [Checks if the cover is constant 0.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Ntl_SopIsConst0( char * pSop )
+{
+ return pSop[0] == ' ' && pSop[1] == '0';
+}
+
+/**Function*************************************************************
+
+ Synopsis [Reads the number of variables in the cover.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Ntl_SopGetVarNum( char * pSop )
+{
+ char * pCur;
+ for ( pCur = pSop; *pCur != '\n'; pCur++ );
+ return pCur - pSop - 2;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Reads the number of cubes in the cover.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Ntl_SopGetCubeNum( char * pSop )
+{
+ char * pCur;
+ int nCubes = 0;
+ if ( pSop == NULL )
+ return 0;
+ for ( pCur = pSop; *pCur; pCur++ )
+ nCubes += (*pCur == '\n');
+ return nCubes;
+}
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Ntl_SopIsComplement( char * pSop )
+{
+ char * pCur;
+ for ( pCur = pSop; *pCur; pCur++ )
+ if ( *pCur == '\n' )
+ return (int)(*(pCur - 1) == '0' || *(pCur - 1) == 'n');
+ assert( 0 );
+ return 0;
+}
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Ntl_SopComplement( char * pSop )
+{
+ char * pCur;
+ for ( pCur = pSop; *pCur; pCur++ )
+ if ( *pCur == '\n' )
+ {
+ if ( *(pCur - 1) == '0' )
+ *(pCur - 1) = '1';
+ else if ( *(pCur - 1) == '1' )
+ *(pCur - 1) = '0';
+ else if ( *(pCur - 1) == 'x' )
+ *(pCur - 1) = 'n';
+ else if ( *(pCur - 1) == 'n' )
+ *(pCur - 1) = 'x';
+ else
+ assert( 0 );
+ }
+}
+
+/**Function*************************************************************
+
+ Synopsis [Creates the constant 1 cover with the given number of variables and cubes.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+char * Ntl_SopStart( Aig_MmFlex_t * pMan, int nCubes, int nVars )
+{
+ char * pSopCover, * pCube;
+ int i, Length;
+
+ Length = nCubes * (nVars + 3);
+ pSopCover = Aig_MmFlexEntryFetch( pMan, Length + 1 );
+ memset( pSopCover, '-', Length );
+ pSopCover[Length] = 0;
+
+ for ( i = 0; i < nCubes; i++ )
+ {
+ pCube = pSopCover + i * (nVars + 3);
+ pCube[nVars + 0] = ' ';
+ pCube[nVars + 1] = '1';
+ pCube[nVars + 2] = '\n';
+ }
+ return pSopCover;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Creates the cover from the ISOP computed from TT.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+char * Ntl_SopCreateFromIsop( Aig_MmFlex_t * pMan, int nVars, Vec_Int_t * vCover )
+{
+ char * pSop, * pCube;
+ int i, k, Entry, Literal;
+ assert( Vec_IntSize(vCover) > 0 );
+ if ( Vec_IntSize(vCover) == 0 )
+ return NULL;
+ // start the cover
+ pSop = Ntl_SopStart( pMan, Vec_IntSize(vCover), nVars );
+ // create cubes
+ Vec_IntForEachEntry( vCover, Entry, i )
+ {
+ pCube = pSop + i * (nVars + 3);
+ for ( k = 0; k < nVars; k++ )
+ {
+ Literal = 3 & (Entry >> (k << 1));
+ if ( Literal == 1 )
+ pCube[k] = '0';
+ else if ( Literal == 2 )
+ pCube[k] = '1';
+ else if ( Literal != 0 )
+ assert( 0 );
+ }
+ }
+ return pSop;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Transforms truth table into the SOP.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+char * Ntl_SopFromTruth( Ntl_Man_t * p, unsigned * pTruth, int nVars, Vec_Int_t * vCover )
+{
+ char * pSop;
+ int RetValue;
+ if ( Kit_TruthIsConst0(pTruth, nVars) )
+ return Ntl_ManStoreSop( p, " 0\n" );
+ if ( Kit_TruthIsConst1(pTruth, nVars) )
+ return Ntl_ManStoreSop( p, " 1\n" );
+ RetValue = Kit_TruthIsop( pTruth, nVars, vCover, 0 ); // 1 );
+ assert( RetValue == 0 || RetValue == 1 );
+ pSop = Ntl_SopCreateFromIsop( p->pMemSops, nVars, vCover );
+ if ( RetValue )
+ Ntl_SopComplement( pSop );
+ return pSop;
+}
+
+
+
+/**Function*************************************************************
+
+ Synopsis [Strashes one logic node using its SOP.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Aig_Obj_t * Ntl_ConvertSopToAigInternal( Aig_Man_t * pMan, Ntl_Obj_t * pNode, char * pSop )
+{
+ Ntl_Net_t * pNet;
+ Aig_Obj_t * pAnd, * pSum;
+ int i, Value, nFanins;
+ char * pCube;
+ // get the number of variables
+ nFanins = Ntl_SopGetVarNum(pSop);
+ // go through the cubes of the node's SOP
+ pSum = Aig_ManConst0(pMan);
+ Ntl_SopForEachCube( pSop, nFanins, pCube )
+ {
+ // create the AND of literals
+ pAnd = Aig_ManConst1(pMan);
+ Ntl_CubeForEachVar( pCube, Value, i )
+ {
+ pNet = Ntl_ObjFanin( pNode, i );
+ if ( Value == '1' )
+ pAnd = Aig_And( pMan, pAnd, pNet->pFunc );
+ else if ( Value == '0' )
+ pAnd = Aig_And( pMan, pAnd, Aig_Not(pNet->pFunc) );
+ }
+ // add to the sum of cubes
+ pSum = Aig_Or( pMan, pSum, pAnd );
+ }
+ // decide whether to complement the result
+ if ( Ntl_SopIsComplement(pSop) )
+ pSum = Aig_Not(pSum);
+ return pSum;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Transforms the decomposition graph into the AIG.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Aig_Obj_t * Ntl_GraphToNetworkAig( Aig_Man_t * pMan, Dec_Graph_t * pGraph )
+{
+ Dec_Node_t * pNode;
+ Aig_Obj_t * pAnd0, * pAnd1;
+ int i;
+ // check for constant function
+ if ( Dec_GraphIsConst(pGraph) )
+ return Aig_NotCond( Aig_ManConst1(pMan), Dec_GraphIsComplement(pGraph) );
+ // check for a literal
+ if ( Dec_GraphIsVar(pGraph) )
+ return Aig_NotCond( Dec_GraphVar(pGraph)->pFunc, Dec_GraphIsComplement(pGraph) );
+ // build the AIG nodes corresponding to the AND gates of the graph
+ Dec_GraphForEachNode( pGraph, pNode, i )
+ {
+ pAnd0 = Aig_NotCond( Dec_GraphNode(pGraph, pNode->eEdge0.Node)->pFunc, pNode->eEdge0.fCompl );
+ pAnd1 = Aig_NotCond( Dec_GraphNode(pGraph, pNode->eEdge1.Node)->pFunc, pNode->eEdge1.fCompl );
+ pNode->pFunc = Aig_And( pMan, pAnd0, pAnd1 );
+ }
+ // complement the result if necessary
+ return Aig_NotCond( pNode->pFunc, Dec_GraphIsComplement(pGraph) );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Converts the network from AIG to BDD representation.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Aig_Obj_t * Ntl_ManExtractAigNode( Ntl_Obj_t * pNode )
+{
+ Aig_Man_t * pMan = pNode->pModel->pMan->pAig;
+ int fUseFactor = 0;
+ // consider the constant node
+ if ( Ntl_SopGetVarNum(pNode->pSop) == 0 )
+ return Aig_NotCond( Aig_ManConst1(pMan), Ntl_SopIsConst0(pNode->pSop) );
+ // decide when to use factoring
+ if ( fUseFactor && Ntl_SopGetVarNum(pNode->pSop) > 2 && Ntl_SopGetCubeNum(pNode->pSop) > 1 )
+ {
+ Dec_Graph_t * pFForm;
+ Dec_Node_t * pFFNode;
+ Aig_Obj_t * pFunc;
+ int i;
+ // perform factoring
+ pFForm = Dec_Factor( pNode->pSop );
+ // collect the fanins
+ Dec_GraphForEachLeaf( pFForm, pFFNode, i )
+ pFFNode->pFunc = Ntl_ObjFanin(pNode, i)->pFunc;
+ // perform strashing
+ pFunc = Ntl_GraphToNetworkAig( pMan, pFForm );
+ Dec_GraphFree( pFForm );
+ return pFunc;
+ }
+ return Ntl_ConvertSopToAigInternal( pMan, pNode, pNode->pSop );
+}
+
+
+
+
+/**Function*************************************************************
+
+ Synopsis [Extracts AIG from the netlist.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Ntl_ManExtract_old( Ntl_Man_t * p )
+{
+ Ntl_Obj_t * pNode;
+ Ntl_Net_t * pNet;
+ int i;
+ // check the DFS traversal
+ if ( !Ntl_ManDfs( p ) )
+ return 0;
+ // start the AIG manager
+ assert( p->pAig == NULL );
+ p->pAig = Aig_ManStart( 10000 );
+ // create the primary inputs
+ Ntl_ManForEachCiNet( p, pNet, i )
+ pNet->pFunc = Aig_ObjCreatePi( p->pAig );
+ // convert internal nodes to AIGs
+ Ntl_ManForEachNode( p, pNode, i )
+ Ntl_ObjFanout0(pNode)->pFunc = Ntl_ManExtractAigNode( pNode );
+ // create the primary outputs
+ Ntl_ManForEachCoNet( p, pNet, i )
+ Aig_ObjCreatePo( p->pAig, pNet->pFunc );
+ // cleanup the AIG
+ Aig_ManCleanup( p->pAig );
+ return 1;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Extracts AIG from the netlist.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Ntl_ManExtract( Ntl_Man_t * p )
+{
+ // start the AIG manager
+ assert( p->pAig == NULL );
+ p->pAig = Aig_ManStart( 10000 );
+ // check the DFS traversal
+ if ( !Ntl_ManDfs( p ) )
+ return 0;
+ // cleanup the AIG
+ Aig_ManCleanup( p->pAig );
+ return 1;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Inserts the given mapping into the netlist.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Ntl_ManInsert( Ntl_Man_t * p, Vec_Ptr_t * vMapping )
+{
+ char Buffer[100];
+ Vec_Ptr_t * vCopies;
+ Vec_Int_t * vCover;
+ Ntl_Mod_t * pRoot;
+ Ntl_Obj_t * pNode;
+ Ntl_Net_t * pNet, * pNetCo;
+ Ntl_Lut_t * pLut;
+ int i, k, nDigits;
+ // remove old nodes
+ pRoot = Vec_PtrEntry( p->vModels, 0 );
+ Ntl_ModelForEachNode( pRoot, pNode, i )
+ Vec_PtrWriteEntry( pRoot->vObjs, pNode->Id, NULL );
+ // start mapping of AIG nodes into their copies
+ vCopies = Vec_PtrStart( Aig_ManObjNumMax(p->pAig) );
+ Ntl_ManForEachCiNet( p, pNet, i )
+ Vec_PtrWriteEntry( vCopies, pNet->pFunc->Id, pNet );
+ // create a new node for each LUT
+ vCover = Vec_IntAlloc( 1 << 16 );
+ nDigits = Aig_Base10Log( Vec_PtrSize(vMapping) );
+ Vec_PtrForEachEntry( vMapping, pLut, i )
+ {
+ pNode = Ntl_ModelCreateNode( pRoot, pLut->nFanins );
+ pNode->pSop = Ntl_SopFromTruth( p, pLut->pTruth, pLut->nFanins, vCover );
+ if ( !Kit_TruthIsConst0(pLut->pTruth, pLut->nFanins) && !Kit_TruthIsConst1(pLut->pTruth, pLut->nFanins) )
+ {
+ for ( k = 0; k < pLut->nFanins; k++ )
+ {
+ pNet = Vec_PtrEntry( vCopies, pLut->pFanins[k] );
+ if ( pNet == NULL )
+ {
+ printf( "Ntl_ManInsert(): Internal error: Net not found.\n" );
+ return 0;
+ }
+ Ntl_ObjSetFanin( pNode, pNet, k );
+ }
+ }
+ sprintf( Buffer, "lut%0*d", nDigits, i );
+ if ( (pNet = Ntl_ModelFindNet( pRoot, Buffer )) )
+ {
+ printf( "Ntl_ManInsert(): Internal error: Intermediate net name is not unique.\n" );
+ return 0;
+ }
+ pNet = Ntl_ModelFindOrCreateNet( pRoot, Buffer );
+ if ( !Ntl_ModelSetNetDriver( pNode, pNet ) )
+ {
+ printf( "Ntl_ManInsert(): Internal error: Net has more than one fanin.\n" );
+ return 0;
+ }
+ Vec_PtrWriteEntry( vCopies, pLut->Id, pNet );
+ }
+ Vec_IntFree( vCover );
+ // mark CIs and outputs of the registers
+ Ntl_ManForEachCiNet( p, pNetCo, i )
+ pNetCo->nVisits = 101;
+ // update the CO pointers
+ Ntl_ManForEachCoNet( p, pNetCo, i )
+ {
+ if ( pNetCo->nVisits == 101 )
+ continue;
+ pNetCo->nVisits = 101;
+ pNet = Vec_PtrEntry( vCopies, Aig_Regular(pNetCo->pFunc)->Id );
+ pNode = Ntl_ModelCreateNode( pRoot, 1 );
+ pNode->pSop = Aig_IsComplement(pNetCo->pFunc)? Ntl_ManStoreSop( p, "0 1\n" ) : Ntl_ManStoreSop( p, "1 1\n" );
+ Ntl_ObjSetFanin( pNode, pNet, 0 );
+ // update the CO driver net
+ pNetCo->pDriver = NULL;
+ if ( !Ntl_ModelSetNetDriver( pNode, pNetCo ) )
+ {
+ printf( "Ntl_ManInsert(): Internal error: PO net has more than one fanin.\n" );
+ return 0;
+ }
+ }
+ Vec_PtrFree( vCopies );
+ return 1;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Extracts AIG from the netlist.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Ntl_ManPerformSynthesis( Ntl_Man_t * p )
+{
+ extern Aig_Man_t * Dar_ManBalance( Aig_Man_t * p, int fUpdateLevel );
+ extern Aig_Man_t * Dar_ManCompress( Aig_Man_t * pAig, int fBalance, int fUpdateLevel, int fVerbose );
+ Aig_Man_t * pTemp;
+ Ntl_Net_t * pNet;
+ int i;
+ // perform synthesis
+printf( "Pre-synthesis AIG: " );
+Aig_ManPrintStats( p->pAig );
+// p->pAig = Dar_ManBalance( pTemp = p->pAig, 1 );
+ p->pAig = Dar_ManCompress( pTemp = p->pAig, 1, 1, 0 );
+ Ntl_ManForEachCiNet( p, pNet, i )
+ pNet->pFunc = Aig_ManPi( p->pAig, i );
+ Ntl_ManForEachCoNet( p, pNet, i )
+ pNet->pFunc = Aig_ObjChild0( Aig_ManPo( p->pAig, i ) );
+ Aig_ManStop( pTemp );
+printf( "Post-synthesis AIG: " );
+Aig_ManPrintStats( p->pAig );
+ return 1;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Testing procedure for insertion of mapping into the netlist.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Ntl_ManInsertTest( Ntl_Man_t * p )
+{
+ Vec_Ptr_t * vMapping;
+ int RetValue;
+ if ( !Ntl_ManExtract( p ) )
+ return 0;
+ assert( p->pAig != NULL );
+ Ntl_ManPerformSynthesis( p );
+ vMapping = Ntl_MappingFromAig( p->pAig );
+ RetValue = Ntl_ManInsert( p, vMapping );
+ Vec_PtrFree( vMapping );
+ return RetValue;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Testing procedure for insertion of mapping into the netlist.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Ntl_ManInsertTestIf( Ntl_Man_t * p )
+{
+ Vec_Ptr_t * vMapping;
+ int RetValue;
+ if ( !Ntl_ManExtract( p ) )
+ return 0;
+ assert( p->pAig != NULL );
+// Ntl_ManPerformSynthesis( p );
+ vMapping = Ntl_MappingIf( p, p->pAig );
+ RetValue = Ntl_ManInsert( p, vMapping );
+ Vec_PtrFree( vMapping );
+ return RetValue;
+}
+
+
+////////////////////////////////////////////////////////////////////////
+/// END OF FILE ///
+////////////////////////////////////////////////////////////////////////
+
+
diff --git a/src/aig/ntl/ntlCheck.c b/src/aig/ntl/ntlCheck.c
new file mode 100644
index 00000000..d01c7d5e
--- /dev/null
+++ b/src/aig/ntl/ntlCheck.c
@@ -0,0 +1,126 @@
+/**CFile****************************************************************
+
+ FileName [ntlCheck.c]
+
+ SystemName [ABC: Logic synthesis and verification system.]
+
+ PackageName [Netlist representation.]
+
+ Synopsis [Checks consistency of the netlist.]
+
+ Author [Alan Mishchenko]
+
+ Affiliation [UC Berkeley]
+
+ Date [Ver. 1.0. Started - June 20, 2005.]
+
+ Revision [$Id: ntlCheck.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "ntl.h"
+#include "aig.h"
+
+////////////////////////////////////////////////////////////////////////
+/// DECLARATIONS ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+/// FUNCTION DEFINITIONS ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Ntl_ManCheck( Ntl_Man_t * pMan )
+{
+ // check that the models have unique names
+ // check that the models (except the first one) do not have boxes
+ return 1;
+}
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Ntl_ModelCheck( Ntl_Mod_t * pModel )
+{
+ return 1;
+}
+
+
+/**Function*************************************************************
+
+ Synopsis [Reads the verilog file.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Ntl_ModelFixNonDrivenNets( Ntl_Mod_t * pModel )
+{
+ Vec_Ptr_t * vNets;
+ Ntl_Net_t * pNet;
+ Ntl_Obj_t * pNode;
+ int i;
+
+ if ( Ntl_ModelIsBlackBox(pModel) )
+ return;
+
+ // check for non-driven nets
+ vNets = Vec_PtrAlloc( 100 );
+ Ntl_ModelForEachNet( pModel, pNet, i )
+ {
+ if ( pNet->pDriver != NULL )
+ continue;
+ // add the constant 0 driver
+ pNode = Ntl_ModelCreateNode( pModel, 0 );
+ pNode->pSop = Ntl_ManStoreSop( pModel->pMan, " 0\n" );
+ Ntl_ModelSetNetDriver( pNode, pNet );
+ // add the net to those for which the warning will be printed
+ Vec_PtrPush( vNets, pNet );
+ }
+
+ // print the warning
+ if ( Vec_PtrSize(vNets) > 0 )
+ {
+ printf( "Warning: Constant-0 drivers added to %d non-driven nets in network \"%s\":\n", Vec_PtrSize(vNets), pModel->pName );
+ Vec_PtrForEachEntry( vNets, pNet, i )
+ {
+ printf( "%s%s", (i? ", ": ""), pNet->pName );
+ if ( i == 3 )
+ {
+ if ( Vec_PtrSize(vNets) > 3 )
+ printf( " ..." );
+ break;
+ }
+ }
+ printf( "\n" );
+ }
+ Vec_PtrFree( vNets );
+}
+
+
+////////////////////////////////////////////////////////////////////////
+/// END OF FILE ///
+////////////////////////////////////////////////////////////////////////
+
+
diff --git a/src/aig/ntl/ntlDfs.c b/src/aig/ntl/ntlDfs.c
new file mode 100644
index 00000000..1e9503a4
--- /dev/null
+++ b/src/aig/ntl/ntlDfs.c
@@ -0,0 +1,184 @@
+/**CFile****************************************************************
+
+ FileName [ntlDfs.c]
+
+ SystemName [ABC: Logic synthesis and verification system.]
+
+ PackageName [Netlist representation.]
+
+ Synopsis [DFS traversal.]
+
+ Author [Alan Mishchenko]
+
+ Affiliation [UC Berkeley]
+
+ Date [Ver. 1.0. Started - June 20, 2005.]
+
+ Revision [$Id: ntlDfs.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "ntl.h"
+
+////////////////////////////////////////////////////////////////////////
+/// DECLARATIONS ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+/// FUNCTION DEFINITIONS ///
+////////////////////////////////////////////////////////////////////////
+
+
+/**Function*************************************************************
+
+ Synopsis [Collects the nodes in a topological order.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Ntl_ManDfs_rec( Ntl_Man_t * p, Ntl_Net_t * pNet )
+{
+ Ntl_Obj_t * pObj;
+ Ntl_Net_t * pNetFanin;
+ int i;
+ // skip visited
+ if ( pNet->nVisits == 2 )
+ return 1;
+ // if the node is on the path, this is a combinational loop
+ if ( pNet->nVisits == 1 )
+ return 0;
+ // mark the node as the one on the path
+ pNet->nVisits = 1;
+ // derive the box
+ pObj = pNet->pDriver;
+ assert( Ntl_ObjIsNode(pObj) || Ntl_ObjIsBox(pObj) );
+ // visit the input nets of the box
+ Ntl_ObjForEachFanin( pObj, pNetFanin, i )
+ if ( !Ntl_ManDfs_rec( p, pNetFanin ) )
+ return 0;
+ // add box inputs/outputs to COs/CIs
+ if ( Ntl_ObjIsBox(pObj) )
+ {
+ int LevelCur, LevelMax = -AIG_INFINITY;
+ Vec_IntPush( p->vBox1Cos, Aig_ManPoNum(p->pAig) );
+ Ntl_ObjForEachFanin( pObj, pNetFanin, i )
+ {
+ LevelCur = Aig_ObjLevel( Aig_Regular(pNetFanin->pFunc) );
+ LevelMax = AIG_MAX( LevelMax, LevelCur );
+ Vec_PtrPush( p->vCos, pNetFanin );
+ Aig_ObjCreatePo( p->pAig, pNetFanin->pFunc );
+ }
+ Ntl_ObjForEachFanout( pObj, pNetFanin, i )
+ {
+ Vec_PtrPush( p->vCis, pNetFanin );
+ pNetFanin->pFunc = Aig_ObjCreatePi( p->pAig );
+ Aig_ObjSetLevel( pNetFanin->pFunc, LevelMax + 1 );
+ }
+//printf( "Creating fake PO with ID = %d.\n", Aig_ManPo(p->pAig, Vec_IntEntryLast(p->vBox1Cos))->Id );
+ }
+ // store the node
+ Vec_PtrPush( p->vNodes, pObj );
+ if ( Ntl_ObjIsNode(pObj) )
+ pNet->pFunc = Ntl_ManExtractAigNode( pObj );
+ pNet->nVisits = 2;
+ return 1;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Performs DFS.]
+
+ Description [Checks for combinational loops. Collects PI/PO nets.
+ Collects nodes in the topological order.]
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Ntl_ManDfs( Ntl_Man_t * p )
+{
+ Ntl_Mod_t * pRoot;
+ Ntl_Obj_t * pObj;
+ Ntl_Net_t * pNet;
+ int i, nUselessObjects;
+ assert( Vec_PtrSize(p->vCis) == 0 );
+ assert( Vec_PtrSize(p->vCos) == 0 );
+ assert( Vec_PtrSize(p->vNodes) == 0 );
+ assert( Vec_IntSize(p->vBox1Cos) == 0 );
+ // get the root model
+ pRoot = Vec_PtrEntry( p->vModels, 0 );
+ // collect primary inputs
+ Ntl_ModelForEachPi( pRoot, pObj, i )
+ {
+ assert( Ntl_ObjFanoutNum(pObj) == 1 );
+ pNet = Ntl_ObjFanout0(pObj);
+ Vec_PtrPush( p->vCis, pNet );
+ pNet->pFunc = Aig_ObjCreatePi( p->pAig );
+ if ( pNet->nVisits )
+ {
+ printf( "Ntl_ManDfs(): Primary input appears twice in the list.\n" );
+ return 0;
+ }
+ pNet->nVisits = 2;
+ }
+ // collect latch outputs
+ Ntl_ModelForEachLatch( pRoot, pObj, i )
+ {
+ assert( Ntl_ObjFanoutNum(pObj) == 1 );
+ pNet = Ntl_ObjFanout0(pObj);
+ Vec_PtrPush( p->vCis, pNet );
+ pNet->pFunc = Aig_ObjCreatePi( p->pAig );
+ if ( pNet->nVisits )
+ {
+ printf( "Ntl_ManDfs(): Latch output is duplicated or defined as a primary input.\n" );
+ return 0;
+ }
+ pNet->nVisits = 2;
+ }
+ // visit the nodes starting from primary outputs
+ Ntl_ModelForEachPo( pRoot, pObj, i )
+ {
+ pNet = Ntl_ObjFanin0(pObj);
+ if ( !Ntl_ManDfs_rec( p, pNet ) )
+ {
+ printf( "Ntl_ManDfs(): Error: Combinational loop is detected.\n" );
+ Vec_PtrClear( p->vCis );
+ Vec_PtrClear( p->vCos );
+ Vec_PtrClear( p->vNodes );
+ return 0;
+ }
+ Vec_PtrPush( p->vCos, pNet );
+ Aig_ObjCreatePo( p->pAig, pNet->pFunc );
+ }
+ // visit the nodes starting from latch inputs outputs
+ Ntl_ModelForEachLatch( pRoot, pObj, i )
+ {
+ pNet = Ntl_ObjFanin0(pObj);
+ if ( !Ntl_ManDfs_rec( p, pNet ) )
+ {
+ printf( "Ntl_ManDfs(): Error: Combinational loop is detected.\n" );
+ Vec_PtrClear( p->vCis );
+ Vec_PtrClear( p->vCos );
+ Vec_PtrClear( p->vNodes );
+ return 0;
+ }
+ Vec_PtrPush( p->vCos, pNet );
+ Aig_ObjCreatePo( p->pAig, pNet->pFunc );
+ }
+ // report the number of dangling objects
+ nUselessObjects = Ntl_ModelNodeNum(pRoot) + Ntl_ModelBoxNum(pRoot) - Vec_PtrSize(p->vNodes);
+ if ( nUselessObjects )
+ printf( "The number of nodes that do not feed into POs = %d.\n", nUselessObjects );
+ return 1;
+}
+
+////////////////////////////////////////////////////////////////////////
+/// END OF FILE ///
+////////////////////////////////////////////////////////////////////////
+
+
diff --git a/src/aig/ntl/ntlMan.c b/src/aig/ntl/ntlMan.c
new file mode 100644
index 00000000..9b4aff5f
--- /dev/null
+++ b/src/aig/ntl/ntlMan.c
@@ -0,0 +1,196 @@
+/**CFile****************************************************************
+
+ FileName [ntlMan.c]
+
+ SystemName [ABC: Logic synthesis and verification system.]
+
+ PackageName [Netlist representation.]
+
+ Synopsis [Netlist manager.]
+
+ Author [Alan Mishchenko]
+
+ Affiliation [UC Berkeley]
+
+ Date [Ver. 1.0. Started - June 20, 2005.]
+
+ Revision [$Id: ntlMan.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "ntl.h"
+
+////////////////////////////////////////////////////////////////////////
+/// DECLARATIONS ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+/// FUNCTION DEFINITIONS ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+ Synopsis [Allocates the netlist manager.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Ntl_Man_t * Ntl_ManAlloc( char * pFileName )
+{
+ Ntl_Man_t * p;
+ // start the manager
+ p = ALLOC( Ntl_Man_t, 1 );
+ memset( p, 0, sizeof(Ntl_Man_t) );
+ p->vModels = Vec_PtrAlloc( 1000 );
+ p->vCis = Vec_PtrAlloc( 1000 );
+ p->vCos = Vec_PtrAlloc( 1000 );
+ p->vNodes = Vec_PtrAlloc( 1000 );
+ p->vBox1Cos = Vec_IntAlloc( 1000 );
+ // start the manager
+ p->pMemObjs = Aig_MmFlexStart();
+ p->pMemSops = Aig_MmFlexStart();
+ // same the names
+ p->pName = Ntl_ManStoreFileName( p, pFileName );
+ p->pSpec = Ntl_ManStoreName( p, pFileName );
+ return p;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Deallocates the netlist manager.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Ntl_ManFree( Ntl_Man_t * p )
+{
+ if ( p->vModels )
+ {
+ Ntl_Mod_t * pModel;
+ int i;
+ Ntl_ManForEachModel( p, pModel, i )
+ Ntl_ModelFree( pModel );
+ Vec_PtrFree( p->vModels );
+ }
+ if ( p->vCis ) Vec_PtrFree( p->vCis );
+ if ( p->vCos ) Vec_PtrFree( p->vCos );
+ if ( p->vNodes ) Vec_PtrFree( p->vNodes );
+ if ( p->vBox1Cos ) Vec_IntFree( p->vBox1Cos );
+ if ( p->pMemObjs ) Aig_MmFlexStop( p->pMemObjs, 0 );
+ if ( p->pMemSops ) Aig_MmFlexStop( p->pMemSops, 0 );
+ if ( p->pAig ) Aig_ManStop( p->pAig );
+ free( p );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Find the model with the given name.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Ntl_Mod_t * Ntl_ManFindModel( Ntl_Man_t * p, char * pName )
+{
+ Ntl_Mod_t * pModel;
+ int i;
+ Vec_PtrForEachEntry( p->vModels, pModel, i )
+ if ( !strcmp( pModel->pName, pName ) )
+ return pModel;
+ return NULL;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Deallocates the netlist manager.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Ntl_ManPrintStats( Ntl_Man_t * p )
+{
+ Ntl_Mod_t * pRoot;
+ pRoot = Vec_PtrEntry( p->vModels, 0 );
+ printf( "%-15s : ", p->pName );
+ printf( "pi = %5d ", Ntl_ModelPiNum(pRoot) );
+ printf( "po = %5d ", Ntl_ModelPoNum(pRoot) );
+ printf( "latch = %5d ", Ntl_ModelLatchNum(pRoot) );
+ printf( "node = %5d ", Ntl_ModelNodeNum(pRoot) );
+ printf( "box = %4d ", Ntl_ModelBoxNum(pRoot) );
+ printf( "model = %3d", Vec_PtrSize(p->vModels) );
+ printf( "\n" );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Allocates the model.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Ntl_Mod_t * Ntl_ModelAlloc( Ntl_Man_t * pMan, char * pName )
+{
+ Ntl_Mod_t * p;
+ // start the manager
+ p = ALLOC( Ntl_Mod_t, 1 );
+ memset( p, 0, sizeof(Ntl_Mod_t) );
+ p->pMan = pMan;
+ p->pName = Ntl_ManStoreName( p->pMan, pName );
+ Vec_PtrPush( pMan->vModels, p );
+ p->vObjs = Vec_PtrAlloc( 10000 );
+ p->vPis = Vec_PtrAlloc( 1000 );
+ p->vPos = Vec_PtrAlloc( 1000 );
+ // start the table
+ p->nTableSize = Aig_PrimeCudd( 10000 );
+ p->pTable = ALLOC( Ntl_Net_t *, p->nTableSize );
+ memset( p->pTable, 0, sizeof(Ntl_Net_t *) * p->nTableSize );
+ return p;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Deallocates the model.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Ntl_ModelFree( Ntl_Mod_t * p )
+{
+ if ( p->vRequireds ) Vec_IntFree( p->vRequireds );
+ if ( p->vArrivals ) Vec_IntFree( p->vArrivals );
+ if ( p->vDelays ) Vec_IntFree( p->vDelays );
+ Vec_PtrFree( p->vObjs );
+ Vec_PtrFree( p->vPis );
+ Vec_PtrFree( p->vPos );
+ free( p->pTable );
+ free( p );
+}
+
+////////////////////////////////////////////////////////////////////////
+/// END OF FILE ///
+////////////////////////////////////////////////////////////////////////
+
+
diff --git a/src/aig/ntl/ntlMap.c b/src/aig/ntl/ntlMap.c
new file mode 100644
index 00000000..59c40453
--- /dev/null
+++ b/src/aig/ntl/ntlMap.c
@@ -0,0 +1,624 @@
+/**CFile****************************************************************
+
+ FileName [ntlMap.c]
+
+ SystemName [ABC: Logic synthesis and verification system.]
+
+ PackageName [Netlist representation.]
+
+ Synopsis [Derives mapped network from AIG.]
+
+ Author [Alan Mishchenko]
+
+ Affiliation [UC Berkeley]
+
+ Date [Ver. 1.0. Started - June 20, 2005.]
+
+ Revision [$Id: ntlMap.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "ntl.h"
+#include "kit.h"
+
+////////////////////////////////////////////////////////////////////////
+/// DECLARATIONS ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+/// FUNCTION DEFINITIONS ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+ Synopsis [Allocates mapping for the given AIG.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Vec_Ptr_t * Ntl_MappingAlloc( int nLuts, int nVars )
+{
+ char * pMemory;
+ Ntl_Lut_t ** pArray;
+ int nEntrySize, i;
+ nEntrySize = sizeof(Ntl_Lut_t) + sizeof(int) * nVars + sizeof(unsigned) * Aig_TruthWordNum(nVars);
+ pArray = (Ntl_Lut_t **)malloc( (sizeof(Ntl_Lut_t *) + nEntrySize) * nLuts );
+ pMemory = (char *)(pArray + nLuts);
+ memset( pMemory, 0, nEntrySize * nLuts );
+ for ( i = 0; i < nLuts; i++ )
+ {
+ pArray[i] = (Ntl_Lut_t *)pMemory;
+ pArray[i]->pFanins = (int *)(pMemory + sizeof(Ntl_Lut_t));
+ pArray[i]->pTruth = (unsigned *)(pMemory + sizeof(Ntl_Lut_t) + sizeof(int) * nVars);
+ pMemory += nEntrySize;
+ }
+ return Vec_PtrAllocArray( (void **)pArray, nLuts );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Derives trivial mapping from the AIG.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Vec_Ptr_t * Ntl_MappingFromAig( Aig_Man_t * p )
+{
+ Vec_Ptr_t * vMapping;
+ Ntl_Lut_t * pLut;
+ Aig_Obj_t * pObj;
+ int i, k = 0, nBytes = 4;
+ vMapping = Ntl_MappingAlloc( Aig_ManAndNum(p) + (int)(Aig_ManConst1(p)->nRefs > 0), 2 );
+ if ( Aig_ManConst1(p)->nRefs > 0 )
+ {
+ pLut = Vec_PtrEntry( vMapping, k++ );
+ pLut->Id = 0;
+ pLut->nFanins = 0;
+ memset( pLut->pTruth, 0xFF, nBytes );
+ }
+ Aig_ManForEachNode( p, pObj, i )
+ {
+ pLut = Vec_PtrEntry( vMapping, k++ );
+ pLut->Id = pObj->Id;
+ pLut->nFanins = 2;
+ pLut->pFanins[0] = Aig_ObjFaninId0(pObj);
+ pLut->pFanins[1] = Aig_ObjFaninId1(pObj);
+ if ( Aig_ObjFaninC0(pObj) && Aig_ObjFaninC1(pObj) )
+ memset( pLut->pTruth, 0x11, nBytes );
+ else if ( !Aig_ObjFaninC0(pObj) && Aig_ObjFaninC1(pObj) )
+ memset( pLut->pTruth, 0x22, nBytes );
+ else if ( Aig_ObjFaninC0(pObj) && !Aig_ObjFaninC1(pObj) )
+ memset( pLut->pTruth, 0x44, nBytes );
+ else if ( !Aig_ObjFaninC0(pObj) && !Aig_ObjFaninC1(pObj) )
+ memset( pLut->pTruth, 0x88, nBytes );
+ }
+ assert( k == Vec_PtrSize(vMapping) );
+ return vMapping;
+}
+
+
+#include "fpgaInt.h"
+
+/**Function*************************************************************
+
+ Synopsis [Recursively derives the truth table for the cut.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+unsigned * Ntl_FpgaComputeTruth_rec( Fpga_Cut_t * pCut, Vec_Ptr_t * vTruthElem, Vec_Ptr_t * vTruthStore, Vec_Ptr_t * vVisited, int nVars, int * pnCounter )
+{
+ unsigned * pTruth, * pTruth0, * pTruth1;
+ assert( !Fpga_IsComplement(pCut) );
+ // if the cut is visited, return the result
+ if ( pCut->pRoot )
+ return (unsigned *)pCut->pRoot;
+ // compute the functions of the children
+ pTruth0 = Ntl_FpgaComputeTruth_rec( Fpga_CutRegular(pCut->pOne), vTruthElem, vTruthStore, vVisited, nVars, pnCounter );
+ if ( Fpga_CutIsComplement(pCut->pOne) )
+ Kit_TruthNot( pTruth0, pTruth0, nVars );
+ pTruth1 = Ntl_FpgaComputeTruth_rec( Fpga_CutRegular(pCut->pTwo), vTruthElem, vTruthStore, vVisited, nVars, pnCounter );
+ if ( Fpga_CutIsComplement(pCut->pTwo) )
+ Kit_TruthNot( pTruth1, pTruth1, nVars );
+ // get the function of the cut
+ pTruth = Vec_PtrEntry( vTruthStore, (*pnCounter)++ );
+ Kit_TruthAnd( pTruth, pTruth0, pTruth1, nVars );
+ if ( pCut->Phase )
+ Kit_TruthNot( pTruth, pTruth, nVars );
+ assert( pCut->pRoot == NULL );
+ pCut->pRoot = (Fpga_Node_t *)pTruth;
+ // add this cut to the visited list
+ Vec_PtrPush( vVisited, pCut );
+ return pTruth;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Derives the truth table for one cut.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+unsigned * Ntl_FpgaComputeTruth( Fpga_Cut_t * pCut, Vec_Ptr_t * vTruthElem, Vec_Ptr_t * vTruthStore, Vec_Ptr_t * vVisited, int nVars )
+{
+ unsigned * pTruth;
+ int i, nCounter = 0;
+ assert( pCut->nLeaves > 1 );
+ // set the leaf variables
+ for ( i = 0; i < pCut->nLeaves; i++ )
+ pCut->ppLeaves[i]->pCuts->pRoot = (Fpga_Node_t *)Vec_PtrEntry( vTruthElem, i );
+ // recursively compute the function
+ Vec_PtrClear( vVisited );
+ pTruth = Ntl_FpgaComputeTruth_rec( pCut, vTruthElem, vTruthStore, vVisited, nVars, &nCounter );
+ // clean the intermediate BDDs
+ for ( i = 0; i < pCut->nLeaves; i++ )
+ pCut->ppLeaves[i]->pCuts->pRoot = NULL;
+ Vec_PtrForEachEntry( vVisited, pCut, i )
+ pCut->pRoot = NULL;
+ return pTruth;
+}
+
+
+/**Function*************************************************************
+
+ Synopsis [Load the network into FPGA manager.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Fpga_Man_t * Ntl_ManToFpga( Aig_Man_t * p )
+{
+ Fpga_Man_t * pMan;
+ Aig_Obj_t * pNode;//, * pFanin, * pPrev;
+ float * pfArrivals;
+ int i;
+ // start the mapping manager and set its parameters
+ pMan = Fpga_ManCreate( Aig_ManPiNum(p), Aig_ManPoNum(p), 0 );
+ if ( pMan == NULL )
+ return NULL;
+ // set the arrival times
+ pfArrivals = ALLOC( float, Aig_ManPiNum(p) );
+ memset( pfArrivals, 0, sizeof(float) * Aig_ManPiNum(p) );
+ Fpga_ManSetInputArrivals( pMan, pfArrivals );
+ // create PIs and remember them in the old nodes
+ Aig_ManConst1(p)->pData = Fpga_ManReadConst1(pMan);
+ Aig_ManForEachPi( p, pNode, i )
+ pNode->pData = Fpga_ManReadInputs(pMan)[i];
+ // load the AIG into the mapper
+ Aig_ManForEachNode( p, pNode, i )
+ {
+ pNode->pData = Fpga_NodeAnd( pMan,
+ Fpga_NotCond( Aig_ObjFanin0(pNode)->pData, Aig_ObjFaninC0(pNode) ),
+ Fpga_NotCond( Aig_ObjFanin1(pNode)->pData, Aig_ObjFaninC1(pNode) ) );
+ // set up the choice node
+// if ( Aig_AigNodeIsChoice( pNode ) )
+// for ( pPrev = pNode, pFanin = pNode->pData; pFanin; pPrev = pFanin, pFanin = pFanin->pData )
+// {
+// Fpga_NodeSetNextE( (If_Obj_t *)pPrev->pData, (If_Obj_t *)pFanin->pData );
+// Fpga_NodeSetRepr( (If_Obj_t *)pFanin->pData, (If_Obj_t *)pNode->pData );
+// }
+ }
+ // set the primary outputs while copying the phase
+ Aig_ManForEachPo( p, pNode, i )
+ Fpga_ManReadOutputs(pMan)[i] = Fpga_NotCond( Aig_ObjFanin0(pNode)->pData, Aig_ObjFaninC0(pNode) );
+ assert( Fpga_NodeVecReadSize(pMan->vAnds) == Aig_ManNodeNum(p) );
+ return pMan;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Creates the mapped network.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Vec_Ptr_t * Ntl_ManFromFpga( Aig_Man_t * p, Fpga_Man_t * pMan )
+{
+ Fpga_NodeVec_t * vFpgaMap;
+ Fpga_Node_t ** ppLeaves, * pNode;
+ Fpga_Cut_t * pCutBest;
+ Vec_Ptr_t * vTruthElem, * vTruthStore, * vVisited, * vMapping;
+ Vec_Int_t * vFpgaToAig;
+ Aig_Obj_t * pObj;
+ Ntl_Lut_t * pLut;
+ unsigned * pTruth;
+ int i, k, nLuts, nLeaves, nWords, nVarsMax;
+ // create mapping of FPGA nodes into AIG nodes
+ vFpgaToAig = Vec_IntStart( Aig_ManObjNumMax(p) );
+ Vec_IntFill( vFpgaToAig, Aig_ManObjNumMax(p), -1 );
+ Aig_ManForEachObj( p, pObj, i )
+ {
+ if ( Aig_ObjIsPo(pObj) )
+ continue;
+ if ( Aig_ObjIsConst1(pObj) && pObj->pData == NULL )
+ continue;
+ pNode = pObj->pData;
+ assert( pNode != NULL );
+ Vec_IntWriteEntry( vFpgaToAig, Fpga_NodeReadNum(pNode), pObj->Id );
+ }
+ // create the mapping
+
+
+ // make sure nodes are in the top order!!!
+
+
+ nVarsMax = Fpga_ManReadVarMax( pMan );
+ nWords = Aig_TruthWordNum( nVarsMax );
+ vFpgaMap = Fpga_ManReadMapping( pMan );
+ vMapping = Ntl_MappingAlloc( vFpgaMap->nSize + (int)(Aig_ManConst1(p)->nRefs > 0), nVarsMax );
+ nLuts = 0;
+ if ( Aig_ManConst1(p)->nRefs > 0 )
+ {
+ pLut = Vec_PtrEntry( vMapping, nLuts++ );
+ pLut->Id = 0;
+ pLut->nFanins = 0;
+ memset( pLut->pTruth, 0xFF, 4 * nWords );
+ }
+ vVisited = Vec_PtrAlloc( 1000 );
+ vTruthElem = Vec_PtrAllocTruthTables( nVarsMax );
+ vTruthStore = Vec_PtrAllocSimInfo( 256, nWords );
+ for ( i = 0; i < vFpgaMap->nSize; i++ )
+ {
+ // get the best cut
+ pNode = vFpgaMap->pArray[i];
+ pCutBest = Fpga_NodeReadCutBest( pNode );
+ nLeaves = Fpga_CutReadLeavesNum( pCutBest );
+ ppLeaves = Fpga_CutReadLeaves( pCutBest );
+ // fill the LUT
+ pLut = Vec_PtrEntry( vMapping, nLuts++ );
+ pLut->Id = Vec_IntEntry( vFpgaToAig, Fpga_NodeReadNum(pNode) );
+ pLut->nFanins = nLeaves;
+ for ( k = 0; k < nLeaves; k++ )
+ pLut->pFanins[k] = Vec_IntEntry( vFpgaToAig, Fpga_NodeReadNum(ppLeaves[k]) );
+ // compute the truth table
+ pTruth = Ntl_FpgaComputeTruth( pCutBest, vTruthElem, vTruthStore, vVisited, nVarsMax );
+ memcpy( pLut->pTruth, pTruth, 4 * nWords );
+ }
+ assert( nLuts == Vec_PtrSize(vMapping) );
+ Vec_IntFree( vFpgaToAig );
+ Vec_PtrFree( vVisited );
+ Vec_PtrFree( vTruthElem );
+ Vec_PtrFree( vTruthStore );
+ return vMapping;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Interface with the FPGA mapping package.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Vec_Ptr_t * Ntl_MappingFpga( Aig_Man_t * p )
+{
+ Vec_Ptr_t * vMapping;
+ Fpga_Man_t * pMan;
+ // print a warning about choice nodes
+ if ( p->pEquivs )
+ printf( "Ntl_MappingFpga(): Performing FPGA mapping with choices.\n" );
+ // perform FPGA mapping
+ pMan = Ntl_ManToFpga( p );
+ if ( pMan == NULL )
+ return NULL;
+ if ( !Fpga_Mapping( pMan ) )
+ {
+ Fpga_ManFree( pMan );
+ return NULL;
+ }
+ // transform the result of mapping into a BDD network
+ vMapping = Ntl_ManFromFpga( p, pMan );
+ Fpga_ManFree( pMan );
+ if ( vMapping == NULL )
+ return NULL;
+ return vMapping;
+}
+
+
+
+
+#include "if.h"
+
+/**Function*************************************************************
+
+ Synopsis [Load the network into FPGA manager.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Ntk_ManSetIfParsDefault( If_Par_t * pPars )
+{
+// extern void * Abc_FrameReadLibLut();
+ // set defaults
+ memset( pPars, 0, sizeof(If_Par_t) );
+ // user-controlable paramters
+// pPars->nLutSize = -1;
+ pPars->nLutSize = 6;
+ pPars->nCutsMax = 8;
+ pPars->nFlowIters = 1;
+ pPars->nAreaIters = 2;
+ pPars->DelayTarget = -1;
+ pPars->fPreprocess = 1;
+ pPars->fArea = 0;
+ pPars->fFancy = 0;
+ pPars->fExpRed = 0;
+ pPars->fLatchPaths = 0;
+ pPars->fEdge = 1;
+ pPars->fCutMin = 1;
+ pPars->fSeqMap = 0;
+ pPars->fVerbose = 1;
+ // internal parameters
+ pPars->fTruth = 1;
+ pPars->nLatches = 0;
+ pPars->fLiftLeaves = 0;
+// pPars->pLutLib = Abc_FrameReadLibLut();
+ pPars->pLutLib = NULL;
+ pPars->pTimesArr = NULL;
+ pPars->pTimesArr = NULL;
+ pPars->pFuncCost = NULL;
+/*
+ if ( pPars->nLutSize == -1 )
+ {
+ if ( pPars->pLutLib == NULL )
+ {
+ printf( "The LUT library is not given.\n" );
+ return;
+ }
+ // get LUT size from the library
+ pPars->nLutSize = pPars->pLutLib->LutMax;
+ }
+*/
+}
+
+/**Function*************************************************************
+
+ Synopsis [Load the network into FPGA manager.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+If_Man_t * Ntk_ManToIf_old( Aig_Man_t * p, If_Par_t * pPars )
+{
+ If_Man_t * pIfMan;
+ Aig_Obj_t * pNode;//, * pFanin, * pPrev;
+ Vec_Ptr_t * vNodes;
+ int i;
+ // start the mapping manager and set its parameters
+ pIfMan = If_ManStart( pPars );
+ // print warning about excessive memory usage
+ if ( 1.0 * Aig_ManObjNum(p) * pIfMan->nObjBytes / (1<<30) > 1.0 )
+ printf( "Warning: The mapper will allocate %.1f Gb for to represent the subject graph with %d AIG nodes.\n",
+ 1.0 * Aig_ManObjNum(p) * pIfMan->nObjBytes / (1<<30), Aig_ManObjNum(p) );
+ // load the AIG into the mapper
+ vNodes = Aig_ManDfsPio( p );
+ Vec_PtrForEachEntry( vNodes, pNode, i )
+ {
+ if ( Aig_ObjIsAnd(pNode) )
+ pNode->pData = (Aig_Obj_t *)If_ManCreateAnd( pIfMan,
+ If_NotCond( (If_Obj_t *)Aig_ObjFanin0(pNode)->pData, Aig_ObjFaninC0(pNode) ),
+ If_NotCond( (If_Obj_t *)Aig_ObjFanin1(pNode)->pData, Aig_ObjFaninC1(pNode) ) );
+ else if ( Aig_ObjIsPi(pNode) )
+ pNode->pData = If_ManCreateCi( pIfMan );
+ else if ( Aig_ObjIsPo(pNode) )
+ If_ManCreateCo( pIfMan, If_NotCond( Aig_ObjFanin0(pNode)->pData, Aig_ObjFaninC0(pNode) ) );
+ else if ( Aig_ObjIsConst1(pNode) )
+ Aig_ManConst1(p)->pData = If_ManConst1( pIfMan );
+ else // add the node to the mapper
+ assert( 0 );
+ // set up the choice node
+// if ( Aig_AigNodeIsChoice( pNode ) )
+// {
+// pIfMan->nChoices++;
+// for ( pPrev = pNode, pFanin = pNode->pData; pFanin; pPrev = pFanin, pFanin = pFanin->pData )
+// If_ObjSetChoice( (If_Obj_t *)pPrev->pData, (If_Obj_t *)pFanin->pData );
+// If_ManCreateChoice( pIfMan, (If_Obj_t *)pNode->pData );
+// }
+ }
+ Vec_PtrFree( vNodes );
+ return pIfMan;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Load the network into FPGA manager.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+If_Man_t * Ntk_ManToIf( Aig_Man_t * p, If_Par_t * pPars )
+{
+ If_Man_t * pIfMan;
+ Aig_Obj_t * pNode;//, * pFanin, * pPrev;
+ int i;
+ // start the mapping manager and set its parameters
+ pIfMan = If_ManStart( pPars );
+ // print warning about excessive memory usage
+ if ( 1.0 * Aig_ManObjNum(p) * pIfMan->nObjBytes / (1<<30) > 1.0 )
+ printf( "Warning: The mapper will allocate %.1f Gb for to represent the subject graph with %d AIG nodes.\n",
+ 1.0 * Aig_ManObjNum(p) * pIfMan->nObjBytes / (1<<30), Aig_ManObjNum(p) );
+ // load the AIG into the mapper
+ Aig_ManForEachObj( p, pNode, i )
+ {
+ if ( Aig_ObjIsAnd(pNode) )
+ pNode->pData = (Aig_Obj_t *)If_ManCreateAnd( pIfMan,
+ If_NotCond( (If_Obj_t *)Aig_ObjFanin0(pNode)->pData, Aig_ObjFaninC0(pNode) ),
+ If_NotCond( (If_Obj_t *)Aig_ObjFanin1(pNode)->pData, Aig_ObjFaninC1(pNode) ) );
+ else if ( Aig_ObjIsPi(pNode) )
+ {
+ pNode->pData = If_ManCreateCi( pIfMan );
+ ((If_Obj_t *)pNode->pData)->Level = pNode->Level;
+ }
+ else if ( Aig_ObjIsPo(pNode) )
+ If_ManCreateCo( pIfMan, If_NotCond( Aig_ObjFanin0(pNode)->pData, Aig_ObjFaninC0(pNode) ) );
+ else if ( Aig_ObjIsConst1(pNode) )
+ Aig_ManConst1(p)->pData = If_ManConst1( pIfMan );
+ else // add the node to the mapper
+ assert( 0 );
+ // set up the choice node
+// if ( Aig_AigNodeIsChoice( pNode ) )
+// {
+// pIfMan->nChoices++;
+// for ( pPrev = pNode, pFanin = pNode->pData; pFanin; pPrev = pFanin, pFanin = pFanin->pData )
+// If_ObjSetChoice( (If_Obj_t *)pPrev->pData, (If_Obj_t *)pFanin->pData );
+// If_ManCreateChoice( pIfMan, (If_Obj_t *)pNode->pData );
+// }
+ }
+ return pIfMan;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Creates the mapped network.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Vec_Ptr_t * Ntk_ManFromIf( Aig_Man_t * p, If_Man_t * pMan )
+{
+ Vec_Ptr_t * vIfMap;
+ If_Obj_t * pNode, * pLeaf;
+ If_Cut_t * pCutBest;
+ Vec_Ptr_t * vMapping;
+ Vec_Int_t * vIfToAig;
+ Aig_Obj_t * pObj;
+ Ntl_Lut_t * pLut;
+ int * ppLeaves;
+ int i, k, nLuts, nLeaves, nWords, nVarsMax;
+ // create mapping of If nodes into AIG nodes
+ vIfToAig = Vec_IntStart( Aig_ManObjNumMax(p) );
+ Vec_IntFill( vIfToAig, Aig_ManObjNumMax(p), -1 );
+ Aig_ManForEachObj( p, pObj, i )
+ {
+ if ( Aig_ObjIsPo(pObj) )
+ continue;
+ if ( Aig_ObjIsConst1(pObj) && pObj->pData == NULL )
+ continue;
+ if ( Aig_ObjIsPi(pObj) && pObj->pData == NULL )
+ continue;
+ pNode = pObj->pData;
+ assert( pNode != NULL );
+ Vec_IntWriteEntry( vIfToAig, pNode->Id, pObj->Id );
+ }
+ // create the mapping
+ vIfMap = If_ManCollectMappingDirect( pMan );
+ nVarsMax = pMan->pPars->nLutSize;
+ nWords = Aig_TruthWordNum( nVarsMax );
+ vMapping = Ntl_MappingAlloc( Vec_PtrSize(vIfMap) + (int)(Aig_ManConst1(p)->nRefs > 0), nVarsMax );
+ nLuts = 0;
+ if ( Aig_ManConst1(p)->nRefs > 0 )
+ {
+ pLut = Vec_PtrEntry( vMapping, nLuts++ );
+ pLut->Id = 0;
+ pLut->nFanins = 0;
+ memset( pLut->pTruth, 0xFF, 4 * nWords );
+ }
+ Vec_PtrForEachEntry( vIfMap, pNode, i )
+ {
+ // get the best cut
+ pCutBest = If_ObjCutBest(pNode);
+ nLeaves = If_CutLeaveNum( pCutBest );
+ ppLeaves = If_CutLeaves( pCutBest );
+ // fill the LUT
+ pLut = Vec_PtrEntry( vMapping, nLuts++ );
+ pLut->Id = Vec_IntEntry( vIfToAig, pNode->Id );
+ pLut->nFanins = nLeaves;
+ If_CutForEachLeaf( pMan, pCutBest, pLeaf, k )
+ pLut->pFanins[k] = Vec_IntEntry( vIfToAig, pLeaf->Id );
+ // compute the truth table
+ memcpy( pLut->pTruth, If_CutTruth(pCutBest), 4 * nWords );
+ }
+ assert( nLuts == Vec_PtrSize(vMapping) );
+ Vec_IntFree( vIfToAig );
+ Vec_PtrFree( vIfMap );
+ return vMapping;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Interface with the FPGA mapping package.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Vec_Ptr_t * Ntl_MappingIf( Ntl_Man_t * pMan, Aig_Man_t * p )
+{
+ Vec_Ptr_t * vMapping;
+ If_Par_t Pars, * pPars = &Pars;
+ If_Man_t * pIfMan;
+ // perform FPGA mapping
+ Ntk_ManSetIfParsDefault( pPars );
+ // set the arrival times
+ pPars->pTimesArr = ALLOC( float, Aig_ManPiNum(p) );
+ memset( pPars->pTimesArr, 0, sizeof(float) * Aig_ManPiNum(p) );
+ // translate into the mapper
+ pIfMan = Ntk_ManToIf( p, pPars );
+ if ( pIfMan == NULL )
+ return NULL;
+ pIfMan->pManTim = Ntl_ManCreateTiming( pMan );
+ if ( !If_ManPerformMapping( pIfMan ) )
+ {
+ If_ManStop( pIfMan );
+ return NULL;
+ }
+ // transform the result of mapping into the new network
+ vMapping = Ntk_ManFromIf( p, pIfMan );
+ If_ManStop( pIfMan );
+ if ( vMapping == NULL )
+ return NULL;
+ return vMapping;
+}
+
+
+
+////////////////////////////////////////////////////////////////////////
+/// END OF FILE ///
+////////////////////////////////////////////////////////////////////////
+
+
diff --git a/src/aig/ntl/ntlObj.c b/src/aig/ntl/ntlObj.c
new file mode 100644
index 00000000..2e39fbbf
--- /dev/null
+++ b/src/aig/ntl/ntlObj.c
@@ -0,0 +1,238 @@
+/**CFile****************************************************************
+
+ FileName [.c]
+
+ SystemName [ABC: Logic synthesis and verification system.]
+
+ PackageName [Netlist representation.]
+
+ Synopsis []
+
+ Author [Alan Mishchenko]
+
+ Affiliation [UC Berkeley]
+
+ Date [Ver. 1.0. Started - June 20, 2005.]
+
+ Revision [$Id: .c,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "ntl.h"
+
+////////////////////////////////////////////////////////////////////////
+/// DECLARATIONS ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+/// FUNCTION DEFINITIONS ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+ Synopsis [Creates the primary input.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Ntl_Obj_t * Ntl_ModelCreatePi( Ntl_Mod_t * pModel )
+{
+ Ntl_Obj_t * p;
+ p = (Ntl_Obj_t *)Aig_MmFlexEntryFetch( pModel->pMan->pMemObjs, sizeof(Ntl_Obj_t) + sizeof(Ntl_Net_t *) );
+ memset( p, 0, sizeof(Ntl_Obj_t) + sizeof(Ntl_Net_t *) );
+ p->Id = Vec_PtrSize( pModel->vObjs );
+ Vec_PtrPush( pModel->vObjs, p );
+ Vec_PtrPush( pModel->vPis, p );
+ p->pModel = pModel;
+ p->Type = NTL_OBJ_PI;
+ p->nFanins = 0;
+ p->nFanouts = 1;
+ pModel->nObjs[NTL_OBJ_PI]++;
+ return p;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Creates the primary output.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Ntl_Obj_t * Ntl_ModelCreatePo( Ntl_Mod_t * pModel, Ntl_Net_t * pNet )
+{
+ Ntl_Obj_t * p;
+ p = (Ntl_Obj_t *)Aig_MmFlexEntryFetch( pModel->pMan->pMemObjs, sizeof(Ntl_Obj_t) + sizeof(Ntl_Net_t *) );
+ memset( p, 0, sizeof(Ntl_Obj_t) + sizeof(Ntl_Net_t *) );
+ p->Id = Vec_PtrSize( pModel->vObjs );
+ Vec_PtrPush( pModel->vObjs, p );
+ Vec_PtrPush( pModel->vPos, p );
+ p->pModel = pModel;
+ p->Type = NTL_OBJ_PO;
+ p->nFanins = 1;
+ p->nFanouts = 0;
+ p->pFanio[0] = pNet;
+ pModel->nObjs[NTL_OBJ_PO]++;
+ return p;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Creates the primary output.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Ntl_Obj_t * Ntl_ModelCreateLatch( Ntl_Mod_t * pModel )
+{
+ Ntl_Obj_t * p;
+ p = (Ntl_Obj_t *)Aig_MmFlexEntryFetch( pModel->pMan->pMemObjs, sizeof(Ntl_Obj_t) + sizeof(Ntl_Net_t *) * 3 );
+ memset( p, 0, sizeof(Ntl_Obj_t) + sizeof(Ntl_Net_t *) * 3 );
+ p->Id = Vec_PtrSize( pModel->vObjs );
+ Vec_PtrPush( pModel->vObjs, p );
+ p->pModel = pModel;
+ p->Type = NTL_OBJ_LATCH;
+ p->nFanins = 2;
+ p->nFanouts = 1;
+ pModel->nObjs[NTL_OBJ_LATCH]++;
+ return p;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Creates the node.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Ntl_Obj_t * Ntl_ModelCreateNode( Ntl_Mod_t * pModel, int nFanins )
+{
+ Ntl_Obj_t * p;
+ p = (Ntl_Obj_t *)Aig_MmFlexEntryFetch( pModel->pMan->pMemObjs, sizeof(Ntl_Obj_t) + sizeof(Ntl_Net_t *) * (nFanins + 1) );
+ memset( p, 0, sizeof(Ntl_Obj_t) + sizeof(Ntl_Net_t *) * (nFanins + 1) );
+ p->Id = Vec_PtrSize( pModel->vObjs );
+ Vec_PtrPush( pModel->vObjs, p );
+ p->pModel = pModel;
+ p->Type = NTL_OBJ_NODE;
+ p->nFanins = nFanins;
+ p->nFanouts = 1;
+ pModel->nObjs[NTL_OBJ_NODE]++;
+ return p;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Create the latch.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Ntl_Obj_t * Ntl_ModelCreateBox( Ntl_Mod_t * pModel, int nFanins, int nFanouts )
+{
+ Ntl_Obj_t * p;
+ p = (Ntl_Obj_t *)Aig_MmFlexEntryFetch( pModel->pMan->pMemObjs, sizeof(Ntl_Obj_t) + sizeof(Ntl_Net_t *) * (nFanins + nFanouts) );
+ memset( p, 0, sizeof(Ntl_Obj_t) + sizeof(Ntl_Net_t *) * (nFanins + nFanouts) );
+ p->Id = Vec_PtrSize( pModel->vObjs );
+ Vec_PtrPush( pModel->vObjs, p );
+ p->pModel = pModel;
+ p->Type = NTL_OBJ_BOX;
+ p->nFanins = nFanins;
+ p->nFanouts = nFanouts;
+ pModel->nObjs[NTL_OBJ_BOX]++;
+ return p;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Allocates memory and copies the name into it.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+char * Ntl_ManStoreName( Ntl_Man_t * p, char * pName )
+{
+ char * pStore;
+ pStore = Aig_MmFlexEntryFetch( p->pMemObjs, strlen(pName) + 1 );
+ strcpy( pStore, pName );
+ return pStore;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Allocates memory and copies the SOP into it.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+char * Ntl_ManStoreSop( Ntl_Man_t * p, char * pSop )
+{
+ char * pStore;
+ pStore = Aig_MmFlexEntryFetch( p->pMemSops, strlen(pSop) + 1 );
+ strcpy( pStore, pSop );
+ return pStore;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Allocates memory and copies the root of file name there.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+char * Ntl_ManStoreFileName( Ntl_Man_t * p, char * pFileName )
+{
+ char * pBeg, * pEnd, * pStore, * pCur;
+ // find the first dot
+ for ( pEnd = pFileName; *pEnd; pEnd++ )
+ if ( *pEnd == '.' )
+ break;
+ // find the first char
+ for ( pBeg = pEnd - 1; pBeg >= pFileName; pBeg-- )
+ if ( !((*pBeg >= 'a' && *pBeg <= 'z') || (*pBeg >= 'A' && *pBeg <= 'Z') || (*pBeg >= '0' && *pBeg <= '9') || *pBeg == '_') )
+ break;
+ pBeg++;
+ // fill up storage
+ pStore = Aig_MmFlexEntryFetch( p->pMemSops, pEnd - pBeg + 1 );
+ for ( pCur = pStore; pBeg < pEnd; pBeg++, pCur++ )
+ *pCur = *pBeg;
+ *pCur = 0;
+ return pStore;
+}
+
+
+////////////////////////////////////////////////////////////////////////
+/// END OF FILE ///
+////////////////////////////////////////////////////////////////////////
+
+
diff --git a/src/aig/ntl/ntlReadBlif.c b/src/aig/ntl/ntlReadBlif.c
new file mode 100644
index 00000000..d085b5e6
--- /dev/null
+++ b/src/aig/ntl/ntlReadBlif.c
@@ -0,0 +1,1163 @@
+/**CFile****************************************************************
+
+ FileName [ntlReadBlif.c]
+
+ SystemName [ABC: Logic synthesis and verification system.]
+
+ PackageName [Command processing package.]
+
+ Synopsis [Procedures to read BLIF file.]
+
+ Author [Alan Mishchenko]
+
+ Affiliation [UC Berkeley]
+
+ Date [Ver. 1.0. Started - January 8, 2007.]
+
+ Revision [$Id: ntlReadBlif.c,v 1.00 2007/01/08 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "ntl.h"
+
+////////////////////////////////////////////////////////////////////////
+/// DECLARATIONS ///
+////////////////////////////////////////////////////////////////////////
+
+typedef struct Ioa_ReadMod_t_ Ioa_ReadMod_t; // parsing model
+typedef struct Ioa_ReadMan_t_ Ioa_ReadMan_t; // parsing manager
+
+struct Ioa_ReadMod_t_
+{
+ // file lines
+ char * pFirst; // .model line
+ Vec_Ptr_t * vInputs; // .inputs lines
+ Vec_Ptr_t * vOutputs; // .outputs lines
+ Vec_Ptr_t * vLatches; // .latch lines
+ Vec_Ptr_t * vNames; // .names lines
+ Vec_Ptr_t * vSubckts; // .subckt lines
+ Vec_Ptr_t * vDelays; // .delay lines
+ Vec_Ptr_t * vArrivals; // .input_arrival lines
+ Vec_Ptr_t * vRequireds; // .output_required lines
+ int fBlackBox; // indicates blackbox model
+ // the resulting network
+ Ntl_Mod_t * pNtk;
+ // the parent manager
+ Ioa_ReadMan_t * pMan;
+};
+
+struct Ioa_ReadMan_t_
+{
+ // general info about file
+ char * pFileName; // the name of the file
+ char * pBuffer; // the contents of the file
+ Vec_Ptr_t * vLines; // the line beginnings
+ // the results of reading
+ Ntl_Man_t * pDesign; // the design under construction
+ // intermediate storage for models
+ Vec_Ptr_t * vModels; // vector of models
+ Ioa_ReadMod_t * pLatest; // the current model
+ // current processing info
+ Vec_Ptr_t * vTokens; // the current tokens
+ Vec_Ptr_t * vTokens2; // the current tokens
+ Vec_Str_t * vFunc; // the local function
+ // error reporting
+ char sError[512]; // the error string generated during parsing
+ // statistics
+ int nTablesRead; // the number of processed tables
+ int nTablesLeft; // the number of dangling tables
+};
+
+// static functions
+static Ioa_ReadMan_t * Ioa_ReadAlloc();
+static void Ioa_ReadFree( Ioa_ReadMan_t * p );
+static Ioa_ReadMod_t * Ioa_ReadModAlloc();
+static void Ioa_ReadModFree( Ioa_ReadMod_t * p );
+static char * Ioa_ReadLoadFile( char * pFileName );
+static void Ioa_ReadReadPreparse( Ioa_ReadMan_t * p );
+static int Ioa_ReadReadInterfaces( Ioa_ReadMan_t * p );
+static Ntl_Man_t * Ioa_ReadParse( Ioa_ReadMan_t * p );
+static int Ioa_ReadParseLineModel( Ioa_ReadMod_t * p, char * pLine );
+static int Ioa_ReadParseLineInputs( Ioa_ReadMod_t * p, char * pLine );
+static int Ioa_ReadParseLineOutputs( Ioa_ReadMod_t * p, char * pLine );
+static int Ioa_ReadParseLineLatch( Ioa_ReadMod_t * p, char * pLine );
+static int Ioa_ReadParseLineSubckt( Ioa_ReadMod_t * p, char * pLine );
+static int Ioa_ReadParseLineDelay( Ioa_ReadMod_t * p, char * pLine );
+static int Ioa_ReadParseLineTimes( Ioa_ReadMod_t * p, char * pLine, int fOutput );
+static int Ioa_ReadParseLineNamesBlif( Ioa_ReadMod_t * p, char * pLine );
+
+static int Ioa_ReadCharIsSpace( char s ) { return s == ' ' || s == '\t' || s == '\r' || s == '\n'; }
+static int Ioa_ReadCharIsSopSymb( char s ) { return s == '0' || s == '1' || s == '-' || s == '\r' || s == '\n'; }
+
+////////////////////////////////////////////////////////////////////////
+/// FUNCTION DEFINITIONS ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+ Synopsis [Reads the network from the BLIF file.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Ntl_Man_t * Ioa_ReadBlif( char * pFileName, int fCheck )
+{
+ FILE * pFile;
+ Ioa_ReadMan_t * p;
+ Ntl_Mod_t * pNtk;
+ Ntl_Man_t * pDesign;
+ int i;
+
+ // check that the file is available
+ pFile = fopen( pFileName, "rb" );
+ if ( pFile == NULL )
+ {
+ printf( "Ioa_ReadBlif(): The file is unavailable (absent or open).\n" );
+ return 0;
+ }
+ fclose( pFile );
+
+ // start the file reader
+ p = Ioa_ReadAlloc();
+ p->pFileName = pFileName;
+ p->pBuffer = Ioa_ReadLoadFile( pFileName );
+ if ( p->pBuffer == NULL )
+ {
+ Ioa_ReadFree( p );
+ return NULL;
+ }
+ // set the design name
+ p->pDesign = Ntl_ManAlloc( pFileName );
+ // prepare the file for parsing
+ Ioa_ReadReadPreparse( p );
+ // parse interfaces of each network
+ if ( !Ioa_ReadReadInterfaces( p ) )
+ {
+ if ( p->sError[0] )
+ fprintf( stdout, "%s\n", p->sError );
+ Ioa_ReadFree( p );
+ return NULL;
+ }
+ // construct the network
+ pDesign = Ioa_ReadParse( p );
+ if ( p->sError[0] )
+ fprintf( stdout, "%s\n", p->sError );
+ if ( pDesign == NULL )
+ {
+ Ioa_ReadFree( p );
+ return NULL;
+ }
+ p->pDesign = NULL;
+ Ioa_ReadFree( p );
+// pDesign should be linked to all models of the design
+
+ // make sure that everything is okay with the network structure
+ if ( fCheck )
+ {
+ // check individual models
+ Vec_PtrForEachEntry( pDesign->vModels, pNtk, i )
+ {
+ if ( !Ntl_ModelCheck( pNtk ) )
+ {
+ printf( "Ioa_ReadBlif: The network check has failed for network %s.\n", pNtk->pName );
+ Ntl_ManFree( pDesign );
+ return NULL;
+ }
+ }
+ // check the hierarchy
+ if ( !Ntl_ManCheck( pDesign ) )
+ {
+ printf( "Ioa_ReadBlif: The hierarchy check has failed for design %s.\n", pDesign->pName );
+ Ntl_ManFree( pDesign );
+ return NULL;
+ }
+
+ }
+//Ioa_WriteBlif( pDesign, "_temp_.blif" );
+ return pDesign;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Allocates the BLIF parsing structure.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+static Ioa_ReadMan_t * Ioa_ReadAlloc()
+{
+ Ioa_ReadMan_t * p;
+ p = ALLOC( Ioa_ReadMan_t, 1 );
+ memset( p, 0, sizeof(Ioa_ReadMan_t) );
+ p->vLines = Vec_PtrAlloc( 512 );
+ p->vModels = Vec_PtrAlloc( 512 );
+ p->vTokens = Vec_PtrAlloc( 512 );
+ p->vTokens2 = Vec_PtrAlloc( 512 );
+ p->vFunc = Vec_StrAlloc( 512 );
+ return p;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Frees the BLIF parsing structure.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+static void Ioa_ReadFree( Ioa_ReadMan_t * p )
+{
+ Ioa_ReadMod_t * pMod;
+ int i;
+ if ( p->pDesign )
+ Ntl_ManFree( p->pDesign );
+ if ( p->pBuffer )
+ free( p->pBuffer );
+ if ( p->vLines )
+ Vec_PtrFree( p->vLines );
+ if ( p->vModels )
+ {
+ Vec_PtrForEachEntry( p->vModels, pMod, i )
+ Ioa_ReadModFree( pMod );
+ Vec_PtrFree( p->vModels );
+ }
+ Vec_PtrFree( p->vTokens );
+ Vec_PtrFree( p->vTokens2 );
+ Vec_StrFree( p->vFunc );
+ free( p );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Allocates the BLIF parsing structure for one model.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+static Ioa_ReadMod_t * Ioa_ReadModAlloc()
+{
+ Ioa_ReadMod_t * p;
+ p = ALLOC( Ioa_ReadMod_t, 1 );
+ memset( p, 0, sizeof(Ioa_ReadMod_t) );
+ p->vInputs = Vec_PtrAlloc( 512 );
+ p->vOutputs = Vec_PtrAlloc( 512 );
+ p->vLatches = Vec_PtrAlloc( 512 );
+ p->vNames = Vec_PtrAlloc( 512 );
+ p->vSubckts = Vec_PtrAlloc( 512 );
+ p->vDelays = Vec_PtrAlloc( 512 );
+ p->vArrivals = Vec_PtrAlloc( 512 );
+ p->vRequireds = Vec_PtrAlloc( 512 );
+ return p;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Deallocates the BLIF parsing structure for one model.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+static void Ioa_ReadModFree( Ioa_ReadMod_t * p )
+{
+ Vec_PtrFree( p->vInputs );
+ Vec_PtrFree( p->vOutputs );
+ Vec_PtrFree( p->vLatches );
+ Vec_PtrFree( p->vNames );
+ Vec_PtrFree( p->vSubckts );
+ Vec_PtrFree( p->vDelays );
+ Vec_PtrFree( p->vArrivals );
+ Vec_PtrFree( p->vRequireds );
+ free( p );
+}
+
+
+
+/**Function*************************************************************
+
+ Synopsis [Counts the number of given chars.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+static int Ioa_ReadCountChars( char * pLine, char Char )
+{
+ char * pCur;
+ int Counter = 0;
+ for ( pCur = pLine; *pCur; pCur++ )
+ if ( *pCur == Char )
+ Counter++;
+ return Counter;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Collects the already split tokens.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+static void Ioa_ReadCollectTokens( Vec_Ptr_t * vTokens, char * pInput, char * pOutput )
+{
+ char * pCur;
+ Vec_PtrClear( vTokens );
+ for ( pCur = pInput; pCur < pOutput; pCur++ )
+ {
+ if ( *pCur == 0 )
+ continue;
+ Vec_PtrPush( vTokens, pCur );
+ while ( *++pCur );
+ }
+}
+
+/**Function*************************************************************
+
+ Synopsis [Splits the line into tokens.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+static void Ioa_ReadSplitIntoTokens( Vec_Ptr_t * vTokens, char * pLine, char Stop )
+{
+ char * pCur;
+ // clear spaces
+ for ( pCur = pLine; *pCur != Stop; pCur++ )
+ if ( Ioa_ReadCharIsSpace(*pCur) )
+ *pCur = 0;
+ // collect tokens
+ Ioa_ReadCollectTokens( vTokens, pLine, pCur );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Splits the line into tokens.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+static void Ioa_ReadSplitIntoTokensAndClear( Vec_Ptr_t * vTokens, char * pLine, char Stop, char Char )
+{
+ char * pCur;
+ // clear spaces
+ for ( pCur = pLine; *pCur != Stop; pCur++ )
+ if ( Ioa_ReadCharIsSpace(*pCur) || *pCur == Char )
+ *pCur = 0;
+ // collect tokens
+ Ioa_ReadCollectTokens( vTokens, pLine, pCur );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Returns the 1-based number of the line in which the token occurs.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+static int Ioa_ReadGetLine( Ioa_ReadMan_t * p, char * pToken )
+{
+ char * pLine;
+ int i;
+ Vec_PtrForEachEntry( p->vLines, pLine, i )
+ if ( pToken < pLine )
+ return i;
+ return -1;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Reads the file into a character buffer.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+static char * Ioa_ReadLoadFile( char * pFileName )
+{
+ FILE * pFile;
+ int nFileSize;
+ char * pContents;
+ pFile = fopen( pFileName, "rb" );
+ if ( pFile == NULL )
+ {
+ printf( "Ioa_ReadLoadFile(): The file is unavailable (absent or open).\n" );
+ return NULL;
+ }
+ fseek( pFile, 0, SEEK_END );
+ nFileSize = ftell( pFile );
+ if ( nFileSize == 0 )
+ {
+ printf( "Ioa_ReadLoadFile(): The file is empty.\n" );
+ return NULL;
+ }
+ pContents = ALLOC( char, nFileSize + 10 );
+ rewind( pFile );
+ fread( pContents, nFileSize, 1, pFile );
+ fclose( pFile );
+ // finish off the file with the spare .end line
+ // some benchmarks suddenly break off without this line
+ strcpy( pContents + nFileSize, "\n.end\n" );
+ return pContents;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Prepares the parsing.]
+
+ Description [Performs several preliminary operations:
+ - Cuts the file buffer into separate lines.
+ - Removes comments and line extenders.
+ - Sorts lines by directives.
+ - Estimates the number of objects.
+ - Allocates room for the objects.
+ - Allocates room for the hash table.]
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+static void Ioa_ReadReadPreparse( Ioa_ReadMan_t * p )
+{
+ char * pCur, * pPrev;
+ int i, fComment = 0;
+ // parse the buffer into lines and remove comments
+ Vec_PtrPush( p->vLines, p->pBuffer );
+ for ( pCur = p->pBuffer; *pCur; pCur++ )
+ {
+ if ( *pCur == '\n' )
+ {
+ *pCur = 0;
+// if ( *(pCur-1) == '\r' )
+// *(pCur-1) = 0;
+ fComment = 0;
+ Vec_PtrPush( p->vLines, pCur + 1 );
+ }
+ else if ( *pCur == '#' )
+ fComment = 1;
+ // remove comments
+ if ( fComment )
+ *pCur = 0;
+ }
+
+ // unfold the line extensions and sort lines by directive
+ Vec_PtrForEachEntry( p->vLines, pCur, i )
+ {
+ if ( *pCur == 0 )
+ continue;
+ // find previous non-space character
+ for ( pPrev = pCur - 2; pPrev >= p->pBuffer; pPrev-- )
+ if ( !Ioa_ReadCharIsSpace(*pPrev) )
+ break;
+ // if it is the line extender, overwrite it with spaces
+ if ( *pPrev == '\\' )
+ {
+ for ( ; *pPrev; pPrev++ )
+ *pPrev = ' ';
+ *pPrev = ' ';
+ continue;
+ }
+ // skip spaces at the beginning of the line
+ while ( Ioa_ReadCharIsSpace(*pCur++) );
+ // parse directives
+ if ( *(pCur-1) != '.' )
+ continue;
+ if ( !strncmp(pCur, "names", 5) )
+ Vec_PtrPush( p->pLatest->vNames, pCur );
+ else if ( !strncmp(pCur, "latch", 5) )
+ Vec_PtrPush( p->pLatest->vLatches, pCur );
+ else if ( !strncmp(pCur, "inputs", 6) )
+ Vec_PtrPush( p->pLatest->vInputs, pCur );
+ else if ( !strncmp(pCur, "outputs", 7) )
+ Vec_PtrPush( p->pLatest->vOutputs, pCur );
+ else if ( !strncmp(pCur, "subckt", 6) )
+ Vec_PtrPush( p->pLatest->vSubckts, pCur );
+ else if ( !strncmp(pCur, "delay", 5) )
+ Vec_PtrPush( p->pLatest->vDelays, pCur );
+ else if ( !strncmp(pCur, "input_arrival", 13) )
+ Vec_PtrPush( p->pLatest->vArrivals, pCur );
+ else if ( !strncmp(pCur, "output_required", 15) )
+ Vec_PtrPush( p->pLatest->vRequireds, pCur );
+ else if ( !strncmp(pCur, "blackbox", 8) )
+ p->pLatest->fBlackBox = 1;
+ else if ( !strncmp(pCur, "model", 5) )
+ {
+ p->pLatest = Ioa_ReadModAlloc();
+ p->pLatest->pFirst = pCur;
+ p->pLatest->pMan = p;
+ }
+ else if ( !strncmp(pCur, "end", 3) )
+ {
+ if ( p->pLatest )
+ Vec_PtrPush( p->vModels, p->pLatest );
+ p->pLatest = NULL;
+ }
+ else if ( !strncmp(pCur, "exdc", 4) )
+ {
+ fprintf( stdout, "Line %d: Skipping EXDC network.\n", Ioa_ReadGetLine(p, pCur) );
+ break;
+ }
+ else
+ {
+ pCur--;
+ if ( pCur[strlen(pCur)-1] == '\r' )
+ pCur[strlen(pCur)-1] = 0;
+ fprintf( stdout, "Line %d: Skipping line \"%s\".\n", Ioa_ReadGetLine(p, pCur), pCur );
+ }
+ }
+}
+
+/**Function*************************************************************
+
+ Synopsis [Parses interfaces of the models.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+static int Ioa_ReadReadInterfaces( Ioa_ReadMan_t * p )
+{
+ Ioa_ReadMod_t * pMod;
+ char * pLine;
+ int i, k;
+ // iterate through the models
+ Vec_PtrForEachEntry( p->vModels, pMod, i )
+ {
+ // parse the model
+ if ( !Ioa_ReadParseLineModel( pMod, pMod->pFirst ) )
+ return 0;
+ // parse the inputs
+ Vec_PtrForEachEntry( pMod->vInputs, pLine, k )
+ if ( !Ioa_ReadParseLineInputs( pMod, pLine ) )
+ return 0;
+ // parse the outputs
+ Vec_PtrForEachEntry( pMod->vOutputs, pLine, k )
+ if ( !Ioa_ReadParseLineOutputs( pMod, pLine ) )
+ return 0;
+ // parse the delay info
+ Vec_PtrForEachEntry( pMod->vDelays, pLine, k )
+ if ( !Ioa_ReadParseLineDelay( pMod, pLine ) )
+ return 0;
+ Vec_PtrForEachEntry( pMod->vArrivals, pLine, k )
+ if ( !Ioa_ReadParseLineTimes( pMod, pLine, 0 ) )
+ return 0;
+ Vec_PtrForEachEntry( pMod->vRequireds, pLine, k )
+ if ( !Ioa_ReadParseLineTimes( pMod, pLine, 1 ) )
+ return 0;
+ }
+ return 1;
+}
+
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+static Ntl_Man_t * Ioa_ReadParse( Ioa_ReadMan_t * p )
+{
+ Ntl_Man_t * pDesign;
+ Ioa_ReadMod_t * pMod;
+ char * pLine;
+ int i, k;
+ // iterate through the models
+ Vec_PtrForEachEntry( p->vModels, pMod, i )
+ {
+ // parse the latches
+ Vec_PtrForEachEntry( pMod->vLatches, pLine, k )
+ if ( !Ioa_ReadParseLineLatch( pMod, pLine ) )
+ return NULL;
+ // parse the nodes
+ Vec_PtrForEachEntry( pMod->vNames, pLine, k )
+ if ( !Ioa_ReadParseLineNamesBlif( pMod, pLine ) )
+ return NULL;
+ // parse the subcircuits
+ Vec_PtrForEachEntry( pMod->vSubckts, pLine, k )
+ if ( !Ioa_ReadParseLineSubckt( pMod, pLine ) )
+ return NULL;
+ // finalize the network
+ Ntl_ModelFixNonDrivenNets( pMod->pNtk );
+ }
+ // return the network
+ pDesign = p->pDesign;
+ p->pDesign = NULL;
+ return pDesign;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Parses the model line.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+static int Ioa_ReadParseLineModel( Ioa_ReadMod_t * p, char * pLine )
+{
+ Vec_Ptr_t * vTokens = p->pMan->vTokens;
+ char * pToken;
+ Ioa_ReadSplitIntoTokens( vTokens, pLine, '\0' );
+ pToken = Vec_PtrEntry( vTokens, 0 );
+ assert( !strcmp(pToken, "model") );
+ if ( Vec_PtrSize(vTokens) != 2 )
+ {
+ sprintf( p->pMan->sError, "Line %d: The number of entries in .model line (%d) is different from two.", Ioa_ReadGetLine(p->pMan, pToken), Vec_PtrSize(vTokens) );
+ return 0;
+ }
+ p->pNtk = Ntl_ModelAlloc( p->pMan->pDesign, Vec_PtrEntry(vTokens, 1) );
+ return 1;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Parses the inputs line.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+static int Ioa_ReadParseLineInputs( Ioa_ReadMod_t * p, char * pLine )
+{
+ Ntl_Net_t * pNet;
+ Ntl_Obj_t * pObj;
+ Vec_Ptr_t * vTokens = p->pMan->vTokens;
+ char * pToken;
+ int i;
+ Ioa_ReadSplitIntoTokens( vTokens, pLine, '\0' );
+ pToken = Vec_PtrEntry(vTokens, 0);
+ assert( !strcmp(pToken, "inputs") );
+ Vec_PtrForEachEntryStart( vTokens, pToken, i, 1 )
+ {
+ pObj = Ntl_ModelCreatePi( p->pNtk );
+ pNet = Ntl_ModelFindOrCreateNet( p->pNtk, pToken );
+ if ( !Ntl_ModelSetNetDriver( pObj, pNet ) )
+ {
+ sprintf( p->pMan->sError, "Line %d: Net %s already has a driver.", Ioa_ReadGetLine(p->pMan, pToken), pNet->pName );
+ return 0;
+ }
+ }
+ return 1;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Parses the outputs line.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+static int Ioa_ReadParseLineOutputs( Ioa_ReadMod_t * p, char * pLine )
+{
+ Ntl_Net_t * pNet;
+ Ntl_Obj_t * pObj;
+ Vec_Ptr_t * vTokens = p->pMan->vTokens;
+ char * pToken;
+ int i;
+ Ioa_ReadSplitIntoTokens( vTokens, pLine, '\0' );
+ pToken = Vec_PtrEntry(vTokens, 0);
+ assert( !strcmp(pToken, "outputs") );
+ Vec_PtrForEachEntryStart( vTokens, pToken, i, 1 )
+ {
+ pNet = Ntl_ModelFindOrCreateNet( p->pNtk, pToken );
+ pObj = Ntl_ModelCreatePo( p->pNtk, pNet );
+ }
+ return 1;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Parses the latches line.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+static int Ioa_ReadParseLineLatch( Ioa_ReadMod_t * p, char * pLine )
+{
+ Vec_Ptr_t * vTokens = p->pMan->vTokens;
+ Ntl_Net_t * pNetLi, * pNetLo;
+ Ntl_Obj_t * pObj;
+ char * pToken, * pNameLi, * pNameLo;
+ int Init, Class;
+ Ioa_ReadSplitIntoTokens( vTokens, pLine, '\0' );
+ pToken = Vec_PtrEntry(vTokens,0);
+ assert( !strcmp(pToken, "latch") );
+ if ( Vec_PtrSize(vTokens) < 3 )
+ {
+ sprintf( p->pMan->sError, "Line %d: Latch does not have input name and output name.", Ioa_ReadGetLine(p->pMan, pToken) );
+ return 0;
+ }
+ // create latch
+ pNameLi = Vec_PtrEntry( vTokens, 1 );
+ pNameLo = Vec_PtrEntry( vTokens, 2 );
+ pNetLi = Ntl_ModelFindOrCreateNet( p->pNtk, pNameLi );
+ pNetLo = Ntl_ModelFindOrCreateNet( p->pNtk, pNameLo );
+ pObj = Ntl_ModelCreateLatch( p->pNtk );
+ pObj->pFanio[0] = pNetLi;
+ if ( !Ntl_ModelSetNetDriver( pObj, pNetLo ) )
+ {
+ sprintf( p->pMan->sError, "Line %d: Net %s already has a driver.", Ioa_ReadGetLine(p->pMan, pToken), pNetLo->pName );
+ return 0;
+ }
+ // get initial value
+ if ( Vec_PtrSize(vTokens) > 3 )
+ Init = atoi( Vec_PtrEntry(vTokens,Vec_PtrSize(vTokens)-1) );
+ else
+ Init = 2;
+ if ( Init < 0 || Init > 2 )
+ {
+ sprintf( p->pMan->sError, "Line %d: Initial state of the latch is incorrect \"%s\".", Ioa_ReadGetLine(p->pMan, pToken), Vec_PtrEntry(vTokens,3) );
+ return 0;
+ }
+ // get the register class
+ if ( Vec_PtrSize(vTokens) == 6 )
+ Class = atoi( Vec_PtrEntry(vTokens,3) );
+ else
+ Class = 0;
+ if ( Class < 0 || Class > (1<<24) )
+ {
+ sprintf( p->pMan->sError, "Line %d: Class of the latch is incorrect \"%s\".", Ioa_ReadGetLine(p->pMan, pToken), Vec_PtrEntry(vTokens,4) );
+ return 0;
+ }
+ pObj->LatchId = (Class << 2) | Init;
+ // get the clock
+ if ( Vec_PtrSize(vTokens) == 5 || Vec_PtrSize(vTokens) == 6 )
+ {
+ pToken = Vec_PtrEntry(vTokens,Vec_PtrSize(vTokens)-2);
+ pNetLi = Ntl_ModelFindOrCreateNet( p->pNtk, pToken );
+ pObj->pFanio[1] = pNetLi;
+ }
+ return 1;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Parses the subckt line.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+static int Ioa_ReadParseLineSubckt( Ioa_ReadMod_t * p, char * pLine )
+{
+ Vec_Ptr_t * vTokens = p->pMan->vTokens;
+ Ntl_Mod_t * pModel;
+ Ntl_Obj_t * pBox, * pTerm;
+ Ntl_Net_t * pNet;
+ char * pToken, * pName, ** ppNames;
+ int nEquals, i, k;
+
+ // split the line into tokens
+ nEquals = Ioa_ReadCountChars( pLine, '=' );
+ Ioa_ReadSplitIntoTokensAndClear( vTokens, pLine, '\0', '=' );
+ pToken = Vec_PtrEntry(vTokens,0);
+ assert( !strcmp(pToken, "subckt") );
+
+ // get the model for this box
+ pName = Vec_PtrEntry(vTokens,1);
+ pModel = Ntl_ManFindModel( p->pMan->pDesign, pName );
+ if ( pModel == NULL )
+ {
+ sprintf( p->pMan->sError, "Line %d: Cannot find the model for subcircuit %s.", Ioa_ReadGetLine(p->pMan, pToken), pName );
+ return 0;
+ }
+
+ // check if the number of tokens is correct
+ if ( nEquals != Ntl_ModelPiNum(pModel) + Ntl_ModelPoNum(pModel) )
+ {
+ sprintf( p->pMan->sError, "Line %d: The number of ports (%d) in .subckt differs from the sum of PIs and POs of the model (%d).",
+ Ioa_ReadGetLine(p->pMan, pToken), nEquals, Ntl_ModelPiNum(pModel) + Ntl_ModelPoNum(pModel) );
+ return 0;
+ }
+
+ // get the names
+ ppNames = (char **)Vec_PtrArray(vTokens) + 2;
+
+ // create the box with these terminals
+ pBox = Ntl_ModelCreateBox( p->pNtk, Ntl_ModelPiNum(pModel), Ntl_ModelPoNum(pModel) );
+ pBox->pImplem = pModel;
+ Ntl_ModelForEachPi( pModel, pTerm, i )
+ {
+ // find this terminal among the formal inputs of the subcircuit
+ pName = Ntl_ObjFanout0(pTerm)->pName;
+ for ( k = 0; k < nEquals; k++ )
+ if ( !strcmp( ppNames[2*k], pName ) )
+ break;
+ if ( k == nEquals )
+ {
+ sprintf( p->pMan->sError, "Line %d: Cannot find PI \"%s\" of the model \"%s\" as a formal input of the subcircuit.",
+ Ioa_ReadGetLine(p->pMan, pToken), pName, pModel->pName );
+ return 0;
+ }
+ // create the BI with the actual name
+ pNet = Ntl_ModelFindOrCreateNet( p->pNtk, ppNames[2*k+1] );
+ Ntl_ObjSetFanin( pBox, pNet, i );
+ }
+ Ntl_ModelForEachPo( pModel, pTerm, i )
+ {
+ // find this terminal among the formal outputs of the subcircuit
+ pName = Ntl_ObjFanin0(pTerm)->pName;
+ for ( k = 0; k < nEquals; k++ )
+ if ( !strcmp( ppNames[2*k], pName ) )
+ break;
+ if ( k == nEquals )
+ {
+ sprintf( p->pMan->sError, "Line %d: Cannot find PO \"%s\" of the model \"%s\" as a formal output of the subcircuit.",
+ Ioa_ReadGetLine(p->pMan, pToken), pName, pModel->pName );
+ return 0;
+ }
+ // create the BI with the actual name
+ pNet = Ntl_ModelFindOrCreateNet( p->pNtk, ppNames[2*k+1] );
+ Ntl_ObjSetFanout( pBox, pNet, i );
+ }
+ return 1;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Parses the subckt line.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+static int Ioa_ReadParseLineDelay( Ioa_ReadMod_t * p, char * pLine )
+{
+ Vec_Ptr_t * vTokens = p->pMan->vTokens;
+ int RetValue1, RetValue2, Number1, Number2, Temp;
+ char * pToken, * pTokenNum;
+ float Delay;
+ assert( sizeof(float) == sizeof(int) );
+ Ioa_ReadSplitIntoTokens( vTokens, pLine, '\0' );
+ pToken = Vec_PtrEntry(vTokens,0);
+ assert( !strcmp(pToken, "delay") );
+ if ( Vec_PtrSize(vTokens) < 2 && Vec_PtrSize(vTokens) > 4 )
+ {
+ sprintf( p->pMan->sError, "Line %d: Delay line does not have a valid number of parameters (1, 2, or 3).", Ioa_ReadGetLine(p->pMan, pToken) );
+ return 0;
+ }
+ // find the delay number
+ pTokenNum = Vec_PtrEntryLast(vTokens);
+ Delay = atof( pTokenNum );
+ if ( Delay == 0.0 && pTokenNum[0] != '0' )
+ {
+ sprintf( p->pMan->sError, "Line %d: Delay value (%s) appears to be invalid.", Ioa_ReadGetLine(p->pMan, pToken), Vec_PtrEntryLast(vTokens) );
+ return 0;
+ }
+ // find the PI/PO numbers
+ RetValue1 = 0; Number1 = -1;
+ if ( Vec_PtrSize(vTokens) > 2 )
+ {
+ RetValue1 = Ntl_ModelFindPioNumber( p->pNtk, Vec_PtrEntry(vTokens, 1), &Number1 );
+ if ( RetValue1 == 0 )
+ {
+ sprintf( p->pMan->sError, "Line %d: Cannot find signal \"%s\" among PIs/POs.", Ioa_ReadGetLine(p->pMan, pToken), Vec_PtrEntry(vTokens, 1) );
+ return 0;
+ }
+ }
+ RetValue2 = 0; Number2 = -1;
+ if ( Vec_PtrSize(vTokens) > 3 )
+ {
+ RetValue2 = Ntl_ModelFindPioNumber( p->pNtk, Vec_PtrEntry(vTokens, 2), &Number2 );
+ if ( RetValue2 == 0 )
+ {
+ sprintf( p->pMan->sError, "Line %d: Cannot find signal \"%s\" among PIs/POs.", Ioa_ReadGetLine(p->pMan, pToken), Vec_PtrEntry(vTokens, 2) );
+ return 0;
+ }
+ }
+ if ( RetValue1 == RetValue2 && RetValue1 )
+ {
+ sprintf( p->pMan->sError, "Line %d: Both signals \"%s\" and \"%s\" listed appear to be PIs or POs.",
+ Ioa_ReadGetLine(p->pMan, pToken), Vec_PtrEntry(vTokens, 1), Vec_PtrEntry(vTokens, 2) );
+ return 0;
+ }
+ if ( RetValue2 < RetValue1 )
+ {
+ Temp = RetValue2; RetValue2 = RetValue1; RetValue1 = Temp;
+ Temp = Number2; Number2 = Number1; Number1 = Temp;
+ }
+ assert( RetValue1 == 0 || RetValue1 == -1 );
+ assert( RetValue2 == 0 || RetValue2 == 1 );
+ // store the values
+ if ( p->pNtk->vDelays == NULL )
+ p->pNtk->vDelays = Vec_IntAlloc( 100 );
+ Vec_IntPush( p->pNtk->vDelays, Number1 );
+ Vec_IntPush( p->pNtk->vDelays, Number2 );
+ Vec_IntPush( p->pNtk->vDelays, Aig_Float2Int(Delay) );
+ return 1;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Parses the subckt line.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+static int Ioa_ReadParseLineTimes( Ioa_ReadMod_t * p, char * pLine, int fOutput )
+{
+ Vec_Ptr_t * vTokens = p->pMan->vTokens;
+ int RetValue, Number;
+ char * pToken, * pTokenNum;
+ float Delay;
+ assert( sizeof(float) == sizeof(int) );
+ Ioa_ReadSplitIntoTokens( vTokens, pLine, '\0' );
+ pToken = Vec_PtrEntry(vTokens,0);
+ if ( fOutput )
+ assert( !strcmp(pToken, "output_required") );
+ else
+ assert( !strcmp(pToken, "input_arrival") );
+ if ( Vec_PtrSize(vTokens) != 3 )
+ {
+ sprintf( p->pMan->sError, "Line %d: Delay line does not have a valid number of parameters (3).", Ioa_ReadGetLine(p->pMan, pToken) );
+ return 0;
+ }
+ // find the delay number
+ pTokenNum = Vec_PtrEntryLast(vTokens);
+ if ( !strcmp( pTokenNum, "-inf" ) )
+ Delay = -AIG_INFINITY;
+ else if ( !strcmp( pTokenNum, "inf" ) )
+ Delay = AIG_INFINITY;
+ else
+ Delay = atof( pTokenNum );
+ if ( Delay == 0.0 && pTokenNum[0] != '0' )
+ {
+ sprintf( p->pMan->sError, "Line %d: Delay value (%s) appears to be invalid.", Ioa_ReadGetLine(p->pMan, pToken), Vec_PtrEntryLast(vTokens) );
+ return 0;
+ }
+ // find the PI/PO numbers
+ if ( fOutput )
+ {
+ RetValue = Ntl_ModelFindPioNumber( p->pNtk, Vec_PtrEntry(vTokens, 1), &Number );
+ if ( RetValue == 0 )
+ {
+ sprintf( p->pMan->sError, "Line %d: Cannot find signal \"%s\" among POs.", Ioa_ReadGetLine(p->pMan, pToken), Vec_PtrEntry(vTokens, 1) );
+ return 0;
+ }
+ // store the values
+ if ( p->pNtk->vRequireds == NULL )
+ p->pNtk->vRequireds = Vec_IntAlloc( 100 );
+ Vec_IntPush( p->pNtk->vRequireds, Number );
+ Vec_IntPush( p->pNtk->vRequireds, Aig_Float2Int(Delay) );
+ }
+ else
+ {
+ RetValue = Ntl_ModelFindPioNumber( p->pNtk, Vec_PtrEntry(vTokens, 1), &Number );
+ if ( RetValue == 0 )
+ {
+ sprintf( p->pMan->sError, "Line %d: Cannot find signal \"%s\" among PIs.", Ioa_ReadGetLine(p->pMan, pToken), Vec_PtrEntry(vTokens, 1) );
+ return 0;
+ }
+ // store the values
+ if ( p->pNtk->vArrivals == NULL )
+ p->pNtk->vArrivals = Vec_IntAlloc( 100 );
+ Vec_IntPush( p->pNtk->vArrivals, Number );
+ Vec_IntPush( p->pNtk->vArrivals, Aig_Float2Int(Delay) );
+ }
+ return 1;
+}
+
+
+/**Function*************************************************************
+
+ Synopsis [Constructs the SOP cover from the file parsing info.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+static char * Ioa_ReadParseTableBlif( Ioa_ReadMod_t * p, char * pTable, int nFanins )
+{
+ Vec_Ptr_t * vTokens = p->pMan->vTokens;
+ Vec_Str_t * vFunc = p->pMan->vFunc;
+ char * pProduct, * pOutput;
+ int i, Polarity = -1;
+
+ p->pMan->nTablesRead++;
+ // get the tokens
+ Ioa_ReadSplitIntoTokens( vTokens, pTable, '.' );
+ if ( Vec_PtrSize(vTokens) == 0 )
+ return Ntl_ManStoreSop( p->pMan->pDesign, " 0\n" );
+ if ( Vec_PtrSize(vTokens) == 1 )
+ {
+ pOutput = Vec_PtrEntry( vTokens, 0 );
+ if ( ((pOutput[0] - '0') & 0x8E) || pOutput[1] )
+ {
+ sprintf( p->pMan->sError, "Line %d: Constant table has wrong output value \"%s\".", Ioa_ReadGetLine(p->pMan, pOutput), pOutput );
+ return NULL;
+ }
+ return Ntl_ManStoreSop( p->pMan->pDesign, (pOutput[0] == '0') ? " 0\n" : " 1\n" );
+ }
+ pProduct = Vec_PtrEntry( vTokens, 0 );
+ if ( Vec_PtrSize(vTokens) % 2 == 1 )
+ {
+ sprintf( p->pMan->sError, "Line %d: Table has odd number of tokens (%d).", Ioa_ReadGetLine(p->pMan, pProduct), Vec_PtrSize(vTokens) );
+ return NULL;
+ }
+ // parse the table
+ Vec_StrClear( vFunc );
+ for ( i = 0; i < Vec_PtrSize(vTokens)/2; i++ )
+ {
+ pProduct = Vec_PtrEntry( vTokens, 2*i + 0 );
+ pOutput = Vec_PtrEntry( vTokens, 2*i + 1 );
+ if ( strlen(pProduct) != (unsigned)nFanins )
+ {
+ sprintf( p->pMan->sError, "Line %d: Cube \"%s\" has size different from the fanin count (%d).", Ioa_ReadGetLine(p->pMan, pProduct), pProduct, nFanins );
+ return NULL;
+ }
+ if ( ((pOutput[0] - '0') & 0x8E) || pOutput[1] )
+ {
+ sprintf( p->pMan->sError, "Line %d: Output value \"%s\" is incorrect.", Ioa_ReadGetLine(p->pMan, pProduct), pOutput );
+ return NULL;
+ }
+ if ( Polarity == -1 )
+ Polarity = pOutput[0] - '0';
+ else if ( Polarity != pOutput[0] - '0' )
+ {
+ sprintf( p->pMan->sError, "Line %d: Output value \"%s\" differs from the value in the first line of the table (%d).", Ioa_ReadGetLine(p->pMan, pProduct), pOutput, Polarity );
+ return NULL;
+ }
+ // parse one product
+ Vec_StrAppend( vFunc, pProduct );
+ Vec_StrPush( vFunc, ' ' );
+ Vec_StrPush( vFunc, pOutput[0] );
+ Vec_StrPush( vFunc, '\n' );
+ }
+ Vec_StrPush( vFunc, '\0' );
+ return Vec_StrArray( vFunc );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Parses the nodes line.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+static int Ioa_ReadParseLineNamesBlif( Ioa_ReadMod_t * p, char * pLine )
+{
+ Vec_Ptr_t * vTokens = p->pMan->vTokens;
+ Ntl_Obj_t * pNode;
+ Ntl_Net_t * pNetOut, * pNetIn;
+ char * pNameOut, * pNameIn;
+ int i;
+ Ioa_ReadSplitIntoTokens( vTokens, pLine, '\0' );
+ // parse the mapped node
+// if ( !strcmp(Vec_PtrEntry(vTokens,0), "gate") )
+// return Ioa_ReadParseLineGateBlif( p, vTokens );
+ // parse the regular name line
+ assert( !strcmp(Vec_PtrEntry(vTokens,0), "names") );
+ pNameOut = Vec_PtrEntryLast( vTokens );
+/*
+ if ( strcmp( pNameOut, "18434" ) == 0 )
+ {
+ int x = 0;
+ }
+*/
+ pNetOut = Ntl_ModelFindOrCreateNet( p->pNtk, pNameOut );
+ // create fanins
+ pNode = Ntl_ModelCreateNode( p->pNtk, Vec_PtrSize(vTokens) - 2 );
+ for ( i = 0; i < Vec_PtrSize(vTokens) - 2; i++ )
+ {
+ pNameIn = Vec_PtrEntry(vTokens, i+1);
+ pNetIn = Ntl_ModelFindOrCreateNet( p->pNtk, pNameIn );
+ Ntl_ObjSetFanin( pNode, pNetIn, i );
+ }
+ if ( !Ntl_ModelSetNetDriver( pNode, pNetOut ) )
+ {
+ sprintf( p->pMan->sError, "Line %d: Signal \"%s\" is defined more than once.", Ioa_ReadGetLine(p->pMan, pNameOut), pNameOut );
+ return 0;
+ }
+ // parse the table of this node
+ pNode->pSop = Ioa_ReadParseTableBlif( p, pNameOut + strlen(pNameOut), pNode->nFanins );
+ if ( pNode->pSop == NULL )
+ return 0;
+ pNode->pSop = Ntl_ManStoreSop( p->pNtk->pMan, pNode->pSop );
+ return 1;
+}
+
+
+////////////////////////////////////////////////////////////////////////
+/// END OF FILE ///
+////////////////////////////////////////////////////////////////////////
+
+
diff --git a/src/aig/ntl/ntlTable.c b/src/aig/ntl/ntlTable.c
new file mode 100644
index 00000000..b84ac1a5
--- /dev/null
+++ b/src/aig/ntl/ntlTable.c
@@ -0,0 +1,217 @@
+/**CFile****************************************************************
+
+ FileName [ntlTable.c]
+
+ SystemName [ABC: Logic synthesis and verification system.]
+
+ PackageName [Netlist representation.]
+
+ Synopsis [Name table manipulation.]
+
+ Author [Alan Mishchenko]
+
+ Affiliation [UC Berkeley]
+
+ Date [Ver. 1.0. Started - June 20, 2005.]
+
+ Revision [$Id: ntlTable.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "ntl.h"
+
+////////////////////////////////////////////////////////////////////////
+/// DECLARATIONS ///
+////////////////////////////////////////////////////////////////////////
+
+// hashing for strings
+static unsigned Ntl_HashString( char * pName, int TableSize )
+{
+ static int s_Primes[10] = {
+ 1291, 1699, 2357, 4177, 5147,
+ 5647, 6343, 7103, 7873, 8147
+ };
+ unsigned i, Key = 0;
+ for ( i = 0; pName[i] != '\0'; i++ )
+ Key ^= s_Primes[i%10]*pName[i]*pName[i];
+ return Key % TableSize;
+}
+
+////////////////////////////////////////////////////////////////////////
+/// FUNCTION DEFINITIONS ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+ Synopsis [Allocates memory for the net.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Ntl_Net_t * Ntl_ModelCreateNet( Ntl_Mod_t * p, char * pName )
+{
+ Ntl_Net_t * pNet;
+ pNet = (Ntl_Net_t *)Aig_MmFlexEntryFetch( p->pMan->pMemObjs, sizeof(Ntl_Net_t) + strlen(pName) + 1 );
+ memset( pNet, 0, sizeof(Ntl_Net_t) );
+ strcpy( pNet->pName, pName );
+ return pNet;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Resizes the table.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Ntl_ModelTableResize( Ntl_Mod_t * p )
+{
+ Ntl_Net_t ** pTableNew, ** ppSpot, * pEntry, * pEntry2;
+ int nTableSizeNew, Counter, e, clk;
+clk = clock();
+ // get the new table size
+ nTableSizeNew = Aig_PrimeCudd( 3 * p->nTableSize );
+ // allocate a new array
+ pTableNew = ALLOC( Ntl_Net_t *, nTableSizeNew );
+ memset( pTableNew, 0, sizeof(Ntl_Net_t *) * nTableSizeNew );
+ // rehash entries
+ Counter = 0;
+ for ( e = 0; e < p->nTableSize; e++ )
+ for ( pEntry = p->pTable[e], pEntry2 = pEntry? pEntry->pNext : NULL;
+ pEntry; pEntry = pEntry2, pEntry2 = pEntry? pEntry->pNext : NULL )
+ {
+ ppSpot = pTableNew + Ntl_HashString( pEntry->pName, nTableSizeNew );
+ pEntry->pNext = *ppSpot;
+ *ppSpot = pEntry;
+ Counter++;
+ }
+ assert( Counter == p->nEntries );
+// printf( "Increasing the structural table size from %6d to %6d. ", p->nTableSize, nTableSizeNew );
+// PRT( "Time", clock() - clk );
+ // replace the table and the parameters
+ free( p->pTable );
+ p->pTable = pTableNew;
+ p->nTableSize = nTableSizeNew;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Finds or creates the net.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Ntl_Net_t * Ntl_ModelFindNet( Ntl_Mod_t * p, char * pName )
+{
+ Ntl_Net_t * pEnt;
+ unsigned Key = Ntl_HashString( pName, p->nTableSize );
+ for ( pEnt = p->pTable[Key]; pEnt; pEnt = pEnt->pNext )
+ if ( !strcmp( pEnt->pName, pName ) )
+ return pEnt;
+ return NULL;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Finds or creates the net.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Ntl_Net_t * Ntl_ModelFindOrCreateNet( Ntl_Mod_t * p, char * pName )
+{
+ Ntl_Net_t * pEnt;
+ unsigned Key = Ntl_HashString( pName, p->nTableSize );
+ for ( pEnt = p->pTable[Key]; pEnt; pEnt = pEnt->pNext )
+ if ( !strcmp( pEnt->pName, pName ) )
+ return pEnt;
+ pEnt = Ntl_ModelCreateNet( p, pName );
+ pEnt->pNext = p->pTable[Key];
+ p->pTable[Key] = pEnt;
+ if ( ++p->nEntries > 2 * p->nTableSize )
+ Ntl_ModelTableResize( p );
+ return pEnt;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Finds or creates the net.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Ntl_ModelSetNetDriver( Ntl_Obj_t * pObj, Ntl_Net_t * pNet )
+{
+ if ( pObj->pFanio[pObj->nFanins] != NULL )
+ return 0;
+ if ( pNet->pDriver != NULL )
+ return 0;
+ pObj->pFanio[pObj->nFanins] = pNet;
+ pNet->pDriver = pObj;
+ return 1;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Returns -1, 0, +1 (when it is PI, not found, or PO).]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Ntl_ModelFindPioNumber( Ntl_Mod_t * p, char * pName, int * pNumber )
+{
+ Ntl_Net_t * pNet;
+ Ntl_Obj_t * pObj;
+ int i;
+ *pNumber = -1;
+ pNet = Ntl_ModelFindNet( p, pName );
+ if ( pNet == NULL )
+ return 0;
+ Ntl_ModelForEachPo( p, pObj, i )
+ {
+ if ( Ntl_ObjFanin0(pObj) == pNet )
+ {
+ *pNumber = i;
+ return 1;
+ }
+ }
+ Ntl_ModelForEachPi( p, pObj, i )
+ {
+ if ( Ntl_ObjFanout0(pObj) == pNet )
+ {
+ *pNumber = i;
+ return -1;
+ }
+ }
+ return 0;
+}
+
+////////////////////////////////////////////////////////////////////////
+/// END OF FILE ///
+////////////////////////////////////////////////////////////////////////
+
+
diff --git a/src/aig/ntl/ntlTime.c b/src/aig/ntl/ntlTime.c
new file mode 100644
index 00000000..50f3d290
--- /dev/null
+++ b/src/aig/ntl/ntlTime.c
@@ -0,0 +1,128 @@
+/**CFile****************************************************************
+
+ FileName [ntlTime.c]
+
+ SystemName [ABC: Logic synthesis and verification system.]
+
+ PackageName [Netlist representation.]
+
+ Synopsis [Creates timing manager.]
+
+ Author [Alan Mishchenko]
+
+ Affiliation [UC Berkeley]
+
+ Date [Ver. 1.0. Started - June 20, 2005.]
+
+ Revision [$Id: ntlTime.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "ntl.h"
+
+////////////////////////////////////////////////////////////////////////
+/// DECLARATIONS ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+/// FUNCTION DEFINITIONS ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+float * Ntl_ManCreateDelayTable( Vec_Int_t * vDelays, int nIns, int nOuts )
+{
+ float * pDelayTable, Delay;
+ int iIn, iOut, i, k;
+ assert( Vec_IntSize(vDelays) % 3 == 0 );
+ pDelayTable = ALLOC( float, nIns * nOuts );
+ memset( pDelayTable, 0, sizeof(float) * nIns * nOuts );
+ Vec_IntForEachEntry( vDelays, iIn, i )
+ {
+ iOut = Vec_IntEntry(vDelays, ++i);
+ Delay = Aig_Int2Float( Vec_IntEntry(vDelays, ++i) );
+ if ( iIn == -1 && iOut == -1 )
+ for ( k = 0; k < nIns * nOuts; k++ )
+ pDelayTable[k] = Delay;
+ else if ( iIn == -1 )
+ for ( k = 0; k < nIns; k++ )
+ pDelayTable[iOut * nIns + k] = Delay;
+ else if ( iOut == -1 )
+ for ( k = 0; k < nOuts; k++ )
+ pDelayTable[k * nIns + iIn] = Delay;
+ else
+ pDelayTable[iOut * nIns + iIn] = Delay;
+ }
+ return pDelayTable;
+}
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Tim_Man_t * Ntl_ManCreateTiming( Ntl_Man_t * p )
+{
+ Tim_Man_t * pMan;
+ Vec_Ptr_t * vDelayTables;
+ Ntl_Mod_t * pRoot, * pModel;
+ Ntl_Obj_t * pObj;
+ int i, curPi, iBox, Entry;
+ assert( p->pAig != NULL );
+ pRoot = Vec_PtrEntry( p->vModels, 0 );
+ // start the timing manager
+ pMan = Tim_ManStart( Aig_ManPiNum(p->pAig), Aig_ManPoNum(p->pAig) );
+ // unpack the data in the arrival times
+ if ( pRoot->vArrivals )
+ Vec_IntForEachEntry( pRoot->vArrivals, Entry, i )
+ Tim_ManInitPiArrival( pMan, Entry, Aig_Int2Float(Vec_IntEntry(pRoot->vArrivals,++i)) );
+ // unpack the data in the required times
+ if ( pRoot->vRequireds )
+ Vec_IntForEachEntry( pRoot->vRequireds, Entry, i )
+ Tim_ManInitPoRequired( pMan, Entry, Aig_Int2Float(Vec_IntEntry(pRoot->vRequireds,++i)) );
+ // derive timing tables
+ vDelayTables = Vec_PtrAlloc( Vec_PtrSize(p->vModels) );
+ Ntl_ManForEachModel( p, pModel, i )
+ {
+ if ( pModel->vDelays )
+ pModel->pDelayTable = Ntl_ManCreateDelayTable( pModel->vDelays, Ntl_ModelPiNum(pModel), Ntl_ModelPoNum(pModel) );
+ Vec_PtrPush( vDelayTables, pModel->pDelayTable );
+ }
+ Tim_ManSetDelayTables( pMan, vDelayTables );
+ // set up the boxes
+ iBox = 0;
+ curPi = Ntl_ModelCiNum(pRoot);
+ Ntl_ManForEachBox( p, pObj, i )
+ {
+ Tim_ManCreateBoxFirst( pMan, Vec_IntEntry(p->vBox1Cos, iBox), Ntl_ObjFaninNum(pObj), curPi, Ntl_ObjFanoutNum(pObj), pObj->pImplem->pDelayTable );
+ curPi += Ntl_ObjFanoutNum(pObj);
+ iBox++;
+ }
+ // forget refs to the delay tables in the network
+ Ntl_ManForEachModel( p, pModel, i )
+ pModel->pDelayTable = NULL;
+// Tim_ManPrint( pMan );
+ return pMan;
+}
+
+
+////////////////////////////////////////////////////////////////////////
+/// END OF FILE ///
+////////////////////////////////////////////////////////////////////////
+
+
diff --git a/src/aig/ntl/ntlWriteBlif.c b/src/aig/ntl/ntlWriteBlif.c
new file mode 100644
index 00000000..8bcd2044
--- /dev/null
+++ b/src/aig/ntl/ntlWriteBlif.c
@@ -0,0 +1,127 @@
+/**CFile****************************************************************
+
+ FileName [ntlWriteBlif.c]
+
+ SystemName [ABC: Logic synthesis and verification system.]
+
+ PackageName [Command processing package.]
+
+ Synopsis [Procedures to write BLIF files.]
+
+ Author [Alan Mishchenko]
+
+ Affiliation [UC Berkeley]
+
+ Date [Ver. 1.0. Started - June 20, 2005.]
+
+ Revision [$Id: ntlWriteBlif.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "ntl.h"
+#include "ioa.h"
+
+////////////////////////////////////////////////////////////////////////
+/// DECLARATIONS ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+/// FUNCTION DEFINITIONS ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+ Synopsis [Writes one model into the BLIF file.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Ioa_WriteBlifModel( FILE * pFile, Ntl_Mod_t * pModel )
+{
+ Ntl_Obj_t * pObj;
+ Ntl_Net_t * pNet;
+ int i, k;
+ fprintf( pFile, ".model %s\n", pModel->pName );
+ fprintf( pFile, ".inputs" );
+ Ntl_ModelForEachPi( pModel, pObj, i )
+ fprintf( pFile, " %s", Ntl_ObjFanout0(pObj)->pName );
+ fprintf( pFile, "\n" );
+ fprintf( pFile, ".outputs" );
+ Ntl_ModelForEachPo( pModel, pObj, i )
+ fprintf( pFile, " %s", Ntl_ObjFanin0(pObj)->pName );
+ fprintf( pFile, "\n" );
+ Ntl_ModelForEachObj( pModel, pObj, i )
+ {
+ if ( Ntl_ObjIsNode(pObj) )
+ {
+ fprintf( pFile, ".names" );
+ Ntl_ObjForEachFanin( pObj, pNet, k )
+ fprintf( pFile, " %s", pNet->pName );
+ fprintf( pFile, " %s\n", Ntl_ObjFanout0(pObj)->pName );
+ fprintf( pFile, "%s", pObj->pSop );
+ }
+ else if ( Ntl_ObjIsLatch(pObj) )
+ {
+ fprintf( pFile, ".latch" );
+ fprintf( pFile, " %s", Ntl_ObjFanin0(pObj)->pName );
+ fprintf( pFile, " %s", Ntl_ObjFanout0(pObj)->pName );
+ if ( pObj->LatchId >> 2 )
+ fprintf( pFile, " %d", pObj->LatchId >> 2 );
+ if ( pObj->pFanio[1] != NULL )
+ fprintf( pFile, " %s", Ntl_ObjFanin(pObj, 1)->pName );
+ fprintf( pFile, " %d", pObj->LatchId & 3 );
+ fprintf( pFile, "\n" );
+ }
+ else if ( Ntl_ObjIsBox(pObj) )
+ {
+ fprintf( pFile, ".subckt %s", pObj->pImplem->pName );
+ Ntl_ObjForEachFanin( pObj, pNet, k )
+ fprintf( pFile, " %s=%s", Ntl_ModelPiName(pObj->pImplem, k), pNet->pName );
+ Ntl_ObjForEachFanout( pObj, pNet, k )
+ fprintf( pFile, " %s=%s", Ntl_ModelPoName(pObj->pImplem, k), pNet->pName );
+ fprintf( pFile, "\n" );
+ }
+ }
+ fprintf( pFile, ".end\n\n" );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Writes the network into the BLIF file.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Ioa_WriteBlif( Ntl_Man_t * p, char * pFileName )
+{
+ FILE * pFile;
+ Ntl_Mod_t * pModel;
+ int i;
+ // start the output stream
+ pFile = fopen( pFileName, "w" );
+ if ( pFile == NULL )
+ {
+ fprintf( stdout, "Ioa_WriteBlif(): Cannot open the output file \"%s\".\n", pFileName );
+ return;
+ }
+ fprintf( pFile, "# Benchmark \"%s\" written by ABC-8 on %s\n", p->pName, Ioa_TimeStamp() );
+ // write the models
+ Ntl_ManForEachModel( p, pModel, i )
+ Ioa_WriteBlifModel( pFile, pModel );
+ // close the file
+ fclose( pFile );
+}
+
+////////////////////////////////////////////////////////////////////////
+/// END OF FILE ///
+////////////////////////////////////////////////////////////////////////
+
+
diff --git a/src/aig/ntl/ntl_.c b/src/aig/ntl/ntl_.c
new file mode 100644
index 00000000..4b3ad684
--- /dev/null
+++ b/src/aig/ntl/ntl_.c
@@ -0,0 +1,47 @@
+/**CFile****************************************************************
+
+ FileName [ntl_.c]
+
+ SystemName [ABC: Logic synthesis and verification system.]
+
+ PackageName [Netlist representation.]
+
+ Synopsis []
+
+ Author [Alan Mishchenko]
+
+ Affiliation [UC Berkeley]
+
+ Date [Ver. 1.0. Started - June 20, 2005.]
+
+ Revision [$Id: ntl_.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "ntl.h"
+
+////////////////////////////////////////////////////////////////////////
+/// DECLARATIONS ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+/// FUNCTION DEFINITIONS ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+
+////////////////////////////////////////////////////////////////////////
+/// END OF FILE ///
+////////////////////////////////////////////////////////////////////////
+
+
diff --git a/src/aig/rwt/module.make b/src/aig/rwt/module.make
new file mode 100644
index 00000000..439d576f
--- /dev/null
+++ b/src/aig/rwt/module.make
@@ -0,0 +1,3 @@
+SRC += src/aig/rwt/rwtDec.c \
+ src/aig/rwt/rwtMan.c \
+ src/aig/rwt/rwtUtil.c
diff --git a/src/aig/rwt/rwt.h b/src/aig/rwt/rwt.h
new file mode 100644
index 00000000..9199ff2a
--- /dev/null
+++ b/src/aig/rwt/rwt.h
@@ -0,0 +1,156 @@
+/**CFile****************************************************************
+
+ FileName [rwt.h]
+
+ SystemName [ABC: Logic synthesis and verification system.]
+
+ PackageName [DAG-aware AIG rewriting package.]
+
+ Synopsis [External declarations.]
+
+ Author [Alan Mishchenko]
+
+ Affiliation [UC Berkeley]
+
+ Date [Ver. 1.0. Started - June 20, 2005.]
+
+ Revision [$Id: rwt.h,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#ifndef __RWT_H__
+#define __RWT_H__
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+////////////////////////////////////////////////////////////////////////
+/// INCLUDES ///
+////////////////////////////////////////////////////////////////////////
+
+#include "mem.h"
+#include "extra.h"
+#include "vec.h"
+
+////////////////////////////////////////////////////////////////////////
+/// PARAMETERS ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+/// BASIC TYPES ///
+////////////////////////////////////////////////////////////////////////
+
+#define RWT_LIMIT 1048576/4 // ((1 << 20)
+#define RWT_MIN(a,b) (((a) < (b))? (a) : (b))
+#define RWT_MAX(a,b) (((a) > (b))? (a) : (b))
+
+typedef struct Rwt_Man_t_ Rwt_Man_t;
+typedef struct Rwt_Node_t_ Rwt_Node_t;
+
+struct Rwt_Man_t_
+{
+ // internal lookups
+ int nFuncs; // number of four var functions
+ unsigned short * puCanons; // canonical forms
+ char * pPhases; // canonical phases
+ char * pPerms; // canonical permutations
+ unsigned char * pMap; // mapping of functions into class numbers
+ unsigned short * pMapInv; // mapping of classes into functions
+ char * pPractical; // practical NPN classes
+ char ** pPerms4; // four-var permutations
+ // node space
+ Vec_Ptr_t * vForest; // all the nodes
+ Rwt_Node_t ** pTable; // the hash table of nodes by their canonical form
+ Vec_Vec_t * vClasses; // the nodes of the equivalence classes
+ Mem_Fixed_t * pMmNode; // memory for nodes and cuts
+ // statistical variables
+ int nTravIds; // the counter of traversal IDs
+ int nConsidered; // the number of nodes considered
+ int nAdded; // the number of nodes added to lists
+ int nClasses; // the number of NN classes
+ // the result of resynthesis
+ int fCompl; // indicates if the output of FF should be complemented
+ void * pCut; // the decomposition tree (temporary)
+ void * pGraph; // the decomposition tree (temporary)
+ char * pPerm; // permutation used for the best cut
+ Vec_Ptr_t * vFanins; // the fanins array (temporary)
+ Vec_Ptr_t * vFaninsCur; // the fanins array (temporary)
+ Vec_Int_t * vLevNums; // the array of levels (temporary)
+ Vec_Ptr_t * vNodesTemp; // the nodes in MFFC (temporary)
+ // node statistics
+ int nNodesConsidered;
+ int nNodesRewritten;
+ int nNodesGained;
+ int nScores[222];
+ int nCutsGood;
+ int nCutsBad;
+ int nSubgraphs;
+ // runtime statistics
+ int timeStart;
+ int timeTruth;
+ int timeCut;
+ int timeRes;
+ int timeEval;
+ int timeMffc;
+ int timeUpdate;
+ int timeTotal;
+};
+
+struct Rwt_Node_t_ // 24 bytes
+{
+ int Id; // ID
+ int TravId; // traversal ID
+ unsigned uTruth : 16; // truth table
+ unsigned Volume : 8; // volume
+ unsigned Level : 6; // level
+ unsigned fUsed : 1; // mark
+ unsigned fExor : 1; // mark
+ Rwt_Node_t * p0; // first child
+ Rwt_Node_t * p1; // second child
+ Rwt_Node_t * pNext; // next in the table
+};
+
+// manipulation of complemented attributes
+static inline int Rwt_IsComplement( Rwt_Node_t * p ) { return (int)(((unsigned long)p) & 01); }
+static inline Rwt_Node_t * Rwt_Regular( Rwt_Node_t * p ) { return (Rwt_Node_t *)((unsigned long)(p) & ~01); }
+static inline Rwt_Node_t * Rwt_Not( Rwt_Node_t * p ) { return (Rwt_Node_t *)((unsigned long)(p) ^ 01); }
+static inline Rwt_Node_t * Rwt_NotCond( Rwt_Node_t * p, int c ) { return (Rwt_Node_t *)((unsigned long)(p) ^ (c)); }
+
+////////////////////////////////////////////////////////////////////////
+/// MACRO DEFINITIONS ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+/// FUNCTION DECLARATIONS ///
+////////////////////////////////////////////////////////////////////////
+
+/*=== rwrDec.c ========================================================*/
+extern void Rwt_ManPreprocess( Rwt_Man_t * p );
+/*=== rwrMan.c ========================================================*/
+extern Rwt_Man_t * Rwt_ManStart( int fPrecompute );
+extern void Rwt_ManStop( Rwt_Man_t * p );
+extern void Rwt_ManPrintStats( Rwt_Man_t * p );
+extern void Rwt_ManPrintStatsFile( Rwt_Man_t * p );
+extern void * Rwt_ManReadDecs( Rwt_Man_t * p );
+extern Vec_Ptr_t * Rwt_ManReadLeaves( Rwt_Man_t * p );
+extern int Rwt_ManReadCompl( Rwt_Man_t * p );
+extern void Rwt_ManAddTimeCuts( Rwt_Man_t * p, int Time );
+extern void Rwt_ManAddTimeUpdate( Rwt_Man_t * p, int Time );
+extern void Rwt_ManAddTimeTotal( Rwt_Man_t * p, int Time );
+/*=== rwrUtil.c ========================================================*/
+extern void Rwt_ManLoadFromArray( Rwt_Man_t * p, int fVerbose );
+extern char * Rwt_ManGetPractical( Rwt_Man_t * p );
+extern Rwt_Node_t * Rwt_ManAddVar( Rwt_Man_t * p, unsigned uTruth, int fPrecompute );
+extern void Rwt_ManIncTravId( Rwt_Man_t * p );
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
+
+////////////////////////////////////////////////////////////////////////
+/// END OF FILE ///
+////////////////////////////////////////////////////////////////////////
+
diff --git a/src/aig/rwt/rwtDec.c b/src/aig/rwt/rwtDec.c
new file mode 100644
index 00000000..98019629
--- /dev/null
+++ b/src/aig/rwt/rwtDec.c
@@ -0,0 +1,150 @@
+/**CFile****************************************************************
+
+ FileName [rwtDec.c]
+
+ SystemName [ABC: Logic synthesis and verification system.]
+
+ PackageName [DAG-aware AIG rewriting package.]
+
+ Synopsis [Evaluation and decomposition procedures.]
+
+ Author [Alan Mishchenko]
+
+ Affiliation [UC Berkeley]
+
+ Date [Ver. 1.0. Started - June 20, 2005.]
+
+ Revision [$Id: rwtDec.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "rwt.h"
+#include "deco.h"
+
+////////////////////////////////////////////////////////////////////////
+/// DECLARATIONS ///
+////////////////////////////////////////////////////////////////////////
+
+static Dec_Graph_t * Rwt_NodePreprocess( Rwt_Man_t * p, Rwt_Node_t * pNode );
+static Dec_Edge_t Rwt_TravCollect_rec( Rwt_Man_t * p, Rwt_Node_t * pNode, Dec_Graph_t * pGraph );
+
+////////////////////////////////////////////////////////////////////////
+/// FUNCTION DEFINITIONS ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+ Synopsis [Preprocesses computed library of subgraphs.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Rwt_ManPreprocess( Rwt_Man_t * p )
+{
+ Dec_Graph_t * pGraph;
+ Rwt_Node_t * pNode;
+ int i, k;
+ // put the nodes into the structure
+ p->pMapInv = ALLOC( unsigned short, 222 );
+ memset( p->pMapInv, 0, sizeof(unsigned short) * 222 );
+ p->vClasses = Vec_VecStart( 222 );
+ for ( i = 0; i < p->nFuncs; i++ )
+ {
+ if ( p->pTable[i] == NULL )
+ continue;
+ // consider all implementations of this function
+ for ( pNode = p->pTable[i]; pNode; pNode = pNode->pNext )
+ {
+ assert( pNode->uTruth == p->pTable[i]->uTruth );
+ assert( p->pMap[pNode->uTruth] >= 0 && p->pMap[pNode->uTruth] < 222 );
+ Vec_VecPush( p->vClasses, p->pMap[pNode->uTruth], pNode );
+ p->pMapInv[ p->pMap[pNode->uTruth] ] = p->puCanons[pNode->uTruth];
+ }
+ }
+ // compute decomposition forms for each node and verify them
+ Vec_VecForEachEntry( p->vClasses, pNode, i, k )
+ {
+ pGraph = Rwt_NodePreprocess( p, pNode );
+ pNode->pNext = (Rwt_Node_t *)pGraph;
+// assert( pNode->uTruth == (Dec_GraphDeriveTruth(pGraph) & 0xFFFF) );
+ }
+}
+
+/**Function*************************************************************
+
+ Synopsis [Preprocesses subgraphs rooted at this node.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Dec_Graph_t * Rwt_NodePreprocess( Rwt_Man_t * p, Rwt_Node_t * pNode )
+{
+ Dec_Graph_t * pGraph;
+ Dec_Edge_t eRoot;
+ assert( !Rwt_IsComplement(pNode) );
+ // consider constant
+ if ( pNode->uTruth == 0 )
+ return Dec_GraphCreateConst0();
+ // consider the case of elementary var
+ if ( pNode->uTruth == 0x00FF )
+ return Dec_GraphCreateLeaf( 3, 4, 1 );
+ // start the subgraphs
+ pGraph = Dec_GraphCreate( 4 );
+ // collect the nodes
+ Rwt_ManIncTravId( p );
+ eRoot = Rwt_TravCollect_rec( p, pNode, pGraph );
+ Dec_GraphSetRoot( pGraph, eRoot );
+ return pGraph;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Adds one node.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Dec_Edge_t Rwt_TravCollect_rec( Rwt_Man_t * p, Rwt_Node_t * pNode, Dec_Graph_t * pGraph )
+{
+ Dec_Edge_t eNode0, eNode1, eNode;
+ // elementary variable
+ if ( pNode->fUsed )
+ return Dec_EdgeCreate( pNode->Id - 1, 0 );
+ // previously visited node
+ if ( pNode->TravId == p->nTravIds )
+ return Dec_IntToEdge( pNode->Volume );
+ pNode->TravId = p->nTravIds;
+ // solve for children
+ eNode0 = Rwt_TravCollect_rec( p, Rwt_Regular(pNode->p0), pGraph );
+ if ( Rwt_IsComplement(pNode->p0) )
+ eNode0.fCompl = !eNode0.fCompl;
+ eNode1 = Rwt_TravCollect_rec( p, Rwt_Regular(pNode->p1), pGraph );
+ if ( Rwt_IsComplement(pNode->p1) )
+ eNode1.fCompl = !eNode1.fCompl;
+ // create the decomposition node(s)
+ if ( pNode->fExor )
+ eNode = Dec_GraphAddNodeXor( pGraph, eNode0, eNode1, 0 );
+ else
+ eNode = Dec_GraphAddNodeAnd( pGraph, eNode0, eNode1 );
+ // save the result
+ pNode->Volume = Dec_EdgeToInt( eNode );
+ return eNode;
+}
+
+////////////////////////////////////////////////////////////////////////
+/// END OF FILE ///
+////////////////////////////////////////////////////////////////////////
+
+
diff --git a/src/aig/rwt/rwtMan.c b/src/aig/rwt/rwtMan.c
new file mode 100644
index 00000000..869043a4
--- /dev/null
+++ b/src/aig/rwt/rwtMan.c
@@ -0,0 +1,358 @@
+/**CFile****************************************************************
+
+ FileName [rwtMan.c]
+
+ SystemName [ABC: Logic synthesis and verification system.]
+
+ PackageName [DAG-aware AIG rewriting package.]
+
+ Synopsis [Rewriting manager.]
+
+ Author [Alan Mishchenko]
+
+ Affiliation [UC Berkeley]
+
+ Date [Ver. 1.0. Started - June 20, 2005.]
+
+ Revision [$Id: rwtMan.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "rwt.h"
+#include "deco.h"
+
+////////////////////////////////////////////////////////////////////////
+/// DECLARATIONS ///
+////////////////////////////////////////////////////////////////////////
+
+static unsigned short * s_puCanons = NULL;
+static char * s_pPhases = NULL;
+static char * s_pPerms = NULL;
+static unsigned char * s_pMap = NULL;
+
+////////////////////////////////////////////////////////////////////////
+/// FUNCTION DEFINITIONS ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+ Synopsis [Starts residual rewriting manager.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Rwt_ManGlobalStart()
+{
+ if ( s_puCanons == NULL )
+ Extra_Truth4VarNPN( &s_puCanons, &s_pPhases, &s_pPerms, &s_pMap );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Starts residual rewriting manager.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Rwt_ManGlobalStop()
+{
+ FREE( s_puCanons );
+ FREE( s_pPhases );
+ FREE( s_pPerms );
+ FREE( s_pMap );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Starts rewriting manager.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Rwt_Man_t * Rwt_ManStart( int fPrecompute )
+{
+ Rwt_Man_t * p;
+ int clk = clock();
+clk = clock();
+ p = ALLOC( Rwt_Man_t, 1 );
+ memset( p, 0, sizeof(Rwt_Man_t) );
+ p->nFuncs = (1<<16);
+ // copy the global tables
+ Rwt_ManGlobalStart();
+ p->puCanons = s_puCanons;
+ p->pPhases = s_pPhases;
+ p->pPerms = s_pPerms;
+ p->pMap = s_pMap;
+ // initialize practical NPN classes
+ p->pPractical = Rwt_ManGetPractical( p );
+ // create the table
+ p->pTable = ALLOC( Rwt_Node_t *, p->nFuncs );
+ memset( p->pTable, 0, sizeof(Rwt_Node_t *) * p->nFuncs );
+ // create the elementary nodes
+ p->pMmNode = Mem_FixedStart( sizeof(Rwt_Node_t) );
+ p->vForest = Vec_PtrAlloc( 100 );
+ Rwt_ManAddVar( p, 0x0000, fPrecompute ); // constant 0
+ Rwt_ManAddVar( p, 0xAAAA, fPrecompute ); // var A
+ Rwt_ManAddVar( p, 0xCCCC, fPrecompute ); // var B
+ Rwt_ManAddVar( p, 0xF0F0, fPrecompute ); // var C
+ Rwt_ManAddVar( p, 0xFF00, fPrecompute ); // var D
+ p->nClasses = 5;
+ // other stuff
+ p->nTravIds = 1;
+ p->pPerms4 = Extra_Permutations( 4 );
+ p->vLevNums = Vec_IntAlloc( 50 );
+ p->vFanins = Vec_PtrAlloc( 50 );
+ p->vFaninsCur = Vec_PtrAlloc( 50 );
+ p->vNodesTemp = Vec_PtrAlloc( 50 );
+ if ( fPrecompute )
+ { // precompute subgraphs
+// Rwt_ManPrecompute( p );
+// Rwt_ManPrint( p );
+// Rwt_ManWriteToArray( p );
+ }
+ else
+ { // load saved subgraphs
+ Rwt_ManLoadFromArray( p, 0 );
+// Rwt_ManPrint( p );
+ Rwt_ManPreprocess( p );
+ }
+p->timeStart = clock() - clk;
+ return p;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Stops rewriting manager.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Rwt_ManStop( Rwt_Man_t * p )
+{
+ if ( p->vClasses )
+ {
+ Rwt_Node_t * pNode;
+ int i, k;
+ Vec_VecForEachEntry( p->vClasses, pNode, i, k )
+ Dec_GraphFree( (Dec_Graph_t *)pNode->pNext );
+ }
+ if ( p->vClasses ) Vec_VecFree( p->vClasses );
+ Vec_PtrFree( p->vNodesTemp );
+ Vec_PtrFree( p->vForest );
+ Vec_IntFree( p->vLevNums );
+ Vec_PtrFree( p->vFanins );
+ Vec_PtrFree( p->vFaninsCur );
+ Mem_FixedStop( p->pMmNode, 0 );
+ FREE( p->pMapInv );
+ free( p->pTable );
+ free( p->pPractical );
+ free( p->pPerms4 );
+ free( p );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Stops the resynthesis manager.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Rwt_ManPrintStats( Rwt_Man_t * p )
+{
+ int i, Counter = 0;
+ for ( i = 0; i < 222; i++ )
+ Counter += (p->nScores[i] > 0);
+
+ printf( "Rewriting statistics:\n" );
+ printf( "Total cuts tries = %8d.\n", p->nCutsGood );
+ printf( "Bad cuts found = %8d.\n", p->nCutsBad );
+ printf( "Total subgraphs = %8d.\n", p->nSubgraphs );
+ printf( "Used NPN classes = %8d.\n", Counter );
+ printf( "Nodes considered = %8d.\n", p->nNodesConsidered );
+ printf( "Nodes rewritten = %8d.\n", p->nNodesRewritten );
+ printf( "Calculated gain = %8d.\n", p->nNodesGained );
+ PRT( "Start ", p->timeStart );
+ PRT( "Cuts ", p->timeCut );
+ PRT( "Truth ", p->timeTruth );
+ PRT( "Resynthesis ", p->timeRes );
+ PRT( " Mffc ", p->timeMffc );
+ PRT( " Eval ", p->timeEval );
+ PRT( "Update ", p->timeUpdate );
+ PRT( "TOTAL ", p->timeTotal );
+
+/*
+ printf( "The scores are:\n" );
+ for ( i = 0; i < 222; i++ )
+ if ( p->nScores[i] > 0 )
+ {
+ extern void Ivy_TruthDsdComputePrint( unsigned uTruth );
+ printf( "%3d = %8d canon = %5d ", i, p->nScores[i], p->pMapInv[i] );
+ Ivy_TruthDsdComputePrint( (unsigned)p->pMapInv[i] | ((unsigned)p->pMapInv[i] << 16) );
+ }
+ printf( "\n" );
+*/
+}
+
+/**Function*************************************************************
+
+ Synopsis [Stops the resynthesis manager.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Rwt_ManPrintStatsFile( Rwt_Man_t * p )
+{
+ FILE * pTable;
+ pTable = fopen( "stats.txt", "a+" );
+ fprintf( pTable, "%d ", p->nCutsGood );
+ fprintf( pTable, "%d ", p->nSubgraphs );
+ fprintf( pTable, "%d ", p->nNodesRewritten );
+ fprintf( pTable, "%d", p->nNodesGained );
+ fprintf( pTable, "\n" );
+ fclose( pTable );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Stops the resynthesis manager.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void * Rwt_ManReadDecs( Rwt_Man_t * p )
+{
+ return p->pGraph;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Stops the resynthesis manager.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Vec_Ptr_t * Rwt_ManReadLeaves( Rwt_Man_t * p )
+{
+ return p->vFanins;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Stops the resynthesis manager.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Rwt_ManReadCompl( Rwt_Man_t * p )
+{
+ return p->fCompl;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Stops the resynthesis manager.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Rwt_ManAddTimeCuts( Rwt_Man_t * p, int Time )
+{
+ p->timeCut += Time;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Stops the resynthesis manager.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Rwt_ManAddTimeUpdate( Rwt_Man_t * p, int Time )
+{
+ p->timeUpdate += Time;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Stops the resynthesis manager.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Rwt_ManAddTimeTotal( Rwt_Man_t * p, int Time )
+{
+ p->timeTotal += Time;
+}
+
+
+/**Function*************************************************************
+
+ Synopsis [Precomputes AIG subgraphs.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Rwt_Precompute()
+{
+ Rwt_Man_t * p;
+ p = Rwt_ManStart( 1 );
+ Rwt_ManStop( p );
+}
+
+////////////////////////////////////////////////////////////////////////
+/// END OF FILE ///
+////////////////////////////////////////////////////////////////////////
+
+
diff --git a/src/aig/rwt/rwtUtil.c b/src/aig/rwt/rwtUtil.c
new file mode 100644
index 00000000..af3e1893
--- /dev/null
+++ b/src/aig/rwt/rwtUtil.c
@@ -0,0 +1,665 @@
+/**CFile****************************************************************
+
+ FileName [rwtUtil.c]
+
+ SystemName [ABC: Logic synthesis and verification system.]
+
+ PackageName [DAG-aware AIG rewriting package.]
+
+ Synopsis [Various utilities.]
+
+ Author [Alan Mishchenko]
+
+ Affiliation [UC Berkeley]
+
+ Date [Ver. 1.0. Started - June 20, 2005.]
+
+ Revision [$Id: rwtUtil.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "rwt.h"
+
+////////////////////////////////////////////////////////////////////////
+/// DECLARATIONS ///
+////////////////////////////////////////////////////////////////////////
+
+// precomputed data
+#ifdef _WIN32
+unsigned short s_RwtPracticalClasses[];
+unsigned short s_RwtAigSubgraphs[];
+#else
+static unsigned short s_RwtPracticalClasses[];
+static unsigned short s_RwtAigSubgraphs[];
+#endif
+
+////////////////////////////////////////////////////////////////////////
+/// FUNCTION DEFINITIONS ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+ Synopsis [Adds the node to the end of the list.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Rwt_ListAddToTail( Rwt_Node_t ** ppList, Rwt_Node_t * pNode )
+{
+ Rwt_Node_t * pTemp;
+ // find the last one
+ for ( pTemp = *ppList; pTemp; pTemp = pTemp->pNext )
+ ppList = &pTemp->pNext;
+ // attach at the end
+ *ppList = pNode;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Adds one node.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Rwt_Node_t * Rwt_ManAddVar( Rwt_Man_t * p, unsigned uTruth, int fPrecompute )
+{
+ Rwt_Node_t * pNew;
+ pNew = (Rwt_Node_t *)Mem_FixedEntryFetch( p->pMmNode );
+ pNew->Id = p->vForest->nSize;
+ pNew->TravId = 0;
+ pNew->uTruth = uTruth;
+ pNew->Level = 0;
+ pNew->Volume = 0;
+ pNew->fUsed = 1;
+ pNew->fExor = 0;
+ pNew->p0 = NULL;
+ pNew->p1 = NULL;
+ pNew->pNext = NULL;
+ Vec_PtrPush( p->vForest, pNew );
+ if ( fPrecompute )
+ Rwt_ListAddToTail( p->pTable + uTruth, pNew );
+ return pNew;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Adds one node.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Rwt_Node_t * Rwt_ManAddNode( Rwt_Man_t * p, Rwt_Node_t * p0, Rwt_Node_t * p1, int fExor, int Level, int Volume )
+{
+ Rwt_Node_t * pNew;
+ unsigned uTruth;
+ // compute truth table, leve, volume
+ p->nConsidered++;
+ if ( fExor )
+ uTruth = (p0->uTruth ^ p1->uTruth);
+ else
+ uTruth = (Rwt_IsComplement(p0)? ~Rwt_Regular(p0)->uTruth : Rwt_Regular(p0)->uTruth) &
+ (Rwt_IsComplement(p1)? ~Rwt_Regular(p1)->uTruth : Rwt_Regular(p1)->uTruth) & 0xFFFF;
+ // create the new node
+ pNew = (Rwt_Node_t *)Mem_FixedEntryFetch( p->pMmNode );
+ pNew->Id = p->vForest->nSize;
+ pNew->TravId = 0;
+ pNew->uTruth = uTruth;
+ pNew->Level = Level;
+ pNew->Volume = Volume;
+ pNew->fUsed = 0;
+ pNew->fExor = fExor;
+ pNew->p0 = p0;
+ pNew->p1 = p1;
+ pNew->pNext = NULL;
+ Vec_PtrPush( p->vForest, pNew );
+ // do not add if the node is not essential
+ if ( uTruth != p->puCanons[uTruth] )
+ return pNew;
+
+ // add to the list
+ p->nAdded++;
+ if ( p->pTable[uTruth] == NULL )
+ p->nClasses++;
+ Rwt_ListAddToTail( p->pTable + uTruth, pNew );
+ return pNew;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Adds one node.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Rwt_Trav_rec( Rwt_Man_t * p, Rwt_Node_t * pNode, int * pVolume )
+{
+ if ( pNode->fUsed || pNode->TravId == p->nTravIds )
+ return;
+ pNode->TravId = p->nTravIds;
+ (*pVolume)++;
+ if ( pNode->fExor )
+ (*pVolume)++;
+ Rwt_Trav_rec( p, Rwt_Regular(pNode->p0), pVolume );
+ Rwt_Trav_rec( p, Rwt_Regular(pNode->p1), pVolume );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Adds one node.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Rwt_ManIncTravId( Rwt_Man_t * p )
+{
+ Rwt_Node_t * pNode;
+ int i;
+ if ( p->nTravIds++ < 0x8FFFFFFF )
+ return;
+ Vec_PtrForEachEntry( p->vForest, pNode, i )
+ pNode->TravId = 0;
+ p->nTravIds = 1;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Adds one node.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Rwt_ManNodeVolume( Rwt_Man_t * p, Rwt_Node_t * p0, Rwt_Node_t * p1 )
+{
+ int Volume = 0;
+ Rwt_ManIncTravId( p );
+ Rwt_Trav_rec( p, p0, &Volume );
+ Rwt_Trav_rec( p, p1, &Volume );
+ return Volume;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Loads data.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Rwt_ManLoadFromArray( Rwt_Man_t * p, int fVerbose )
+{
+ unsigned short * pArray = s_RwtAigSubgraphs;
+ Rwt_Node_t * p0, * p1;
+ unsigned Entry0, Entry1;
+ int Level, Volume, nEntries, fExor;
+ int i, clk = clock();
+
+ // reconstruct the forest
+ for ( i = 0; ; i++ )
+ {
+ Entry0 = pArray[2*i + 0];
+ Entry1 = pArray[2*i + 1];
+ if ( Entry0 == 0 && Entry1 == 0 )
+ break;
+ // get EXOR flag
+ fExor = (Entry0 & 1);
+ Entry0 >>= 1;
+ // get the nodes
+ p0 = p->vForest->pArray[Entry0 >> 1];
+ p1 = p->vForest->pArray[Entry1 >> 1];
+ // compute the level and volume of the new nodes
+ Level = 1 + RWT_MAX( p0->Level, p1->Level );
+ Volume = 1 + Rwt_ManNodeVolume( p, p0, p1 );
+ // set the complemented attributes
+ p0 = Rwt_NotCond( p0, (Entry0 & 1) );
+ p1 = Rwt_NotCond( p1, (Entry1 & 1) );
+ // add the node
+// Rwt_ManTryNode( p, p0, p1, Level, Volume );
+ Rwt_ManAddNode( p, p0, p1, fExor, Level, Volume + fExor );
+ }
+ nEntries = i - 1;
+ if ( fVerbose )
+ {
+ printf( "The number of classes = %d. Canonical nodes = %d.\n", p->nClasses, p->nAdded );
+ printf( "The number of nodes loaded = %d. ", nEntries ); PRT( "Loading", clock() - clk );
+ }
+}
+
+/**Function*************************************************************
+
+ Synopsis [Create practical classes.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+char * Rwt_ManGetPractical( Rwt_Man_t * p )
+{
+ char * pPractical;
+ int i;
+ pPractical = ALLOC( char, p->nFuncs );
+ memset( pPractical, 0, sizeof(char) * p->nFuncs );
+ pPractical[0] = 1;
+ for ( i = 1; ; i++ )
+ {
+ if ( s_RwtPracticalClasses[i] == 0 )
+ break;
+ pPractical[ s_RwtPracticalClasses[i] ] = 1;
+ }
+ return pPractical;
+}
+
+////////////////////////////////////////////////////////////////////////
+/// END OF FILE ///
+////////////////////////////////////////////////////////////////////////
+
+// the following 135 practical NPN classes of 4-variable functions were computed
+// by considering all 4-input cuts appearing in IWLS, MCNC, and ISCAS benchmarks
+static unsigned short s_RwtPracticalClasses[] =
+{
+ 0x0000, 0x0001, 0x0003, 0x0006, 0x0007, 0x000f, 0x0016, 0x0017, 0x0018, 0x0019, 0x001b,
+ 0x001e, 0x001f, 0x003c, 0x003d, 0x003f, 0x0069, 0x006b, 0x006f, 0x007e, 0x007f, 0x00ff,
+ 0x0116, 0x0118, 0x0119, 0x011a, 0x011b, 0x011e, 0x011f, 0x012c, 0x012d, 0x012f, 0x013c,
+ 0x013d, 0x013e, 0x013f, 0x0168, 0x0169, 0x016f, 0x017f, 0x0180, 0x0181, 0x0182, 0x0183,
+ 0x0186, 0x0189, 0x018b, 0x018f, 0x0198, 0x0199, 0x019b, 0x01a8, 0x01a9, 0x01aa, 0x01ab,
+ 0x01ac, 0x01ad, 0x01ae, 0x01af, 0x01bf, 0x01e9, 0x01ea, 0x01eb, 0x01ee, 0x01ef, 0x01fe,
+ 0x033c, 0x033d, 0x033f, 0x0356, 0x0357, 0x0358, 0x0359, 0x035a, 0x035b, 0x035f, 0x0368,
+ 0x0369, 0x036c, 0x036e, 0x037d, 0x03c0, 0x03c1, 0x03c3, 0x03c7, 0x03cf, 0x03d4, 0x03d5,
+ 0x03d7, 0x03d8, 0x03d9, 0x03dc, 0x03dd, 0x03de, 0x03fc, 0x0660, 0x0661, 0x0666, 0x0669,
+ 0x066f, 0x0676, 0x067e, 0x0690, 0x0696, 0x0697, 0x069f, 0x06b1, 0x06b6, 0x06f0, 0x06f2,
+ 0x06f6, 0x06f9, 0x0776, 0x0778, 0x07b0, 0x07b1, 0x07b4, 0x07bc, 0x07f0, 0x07f2, 0x07f8,
+ 0x0ff0, 0x1683, 0x1696, 0x1698, 0x169e, 0x16e9, 0x178e, 0x17e8, 0x18e7, 0x19e6, 0x1be4,
+ 0x1ee1, 0x3cc3, 0x6996, 0x0000
+};
+
+static unsigned short s_RwtAigSubgraphs[] =
+{
+ 0x0008,0x0002, 0x000a,0x0002, 0x0008,0x0003, 0x000a,0x0003, 0x0009,0x0002,
+ 0x000c,0x0002, 0x000e,0x0002, 0x000c,0x0003, 0x000e,0x0003, 0x000d,0x0002,
+ 0x000c,0x0004, 0x000e,0x0004, 0x000c,0x0005, 0x000e,0x0005, 0x000d,0x0004,
+ 0x0010,0x0002, 0x0012,0x0002, 0x0010,0x0003, 0x0012,0x0003, 0x0011,0x0002,
+ 0x0010,0x0004, 0x0012,0x0004, 0x0010,0x0005, 0x0012,0x0005, 0x0011,0x0004,
+ 0x0010,0x0006, 0x0012,0x0006, 0x0010,0x0007, 0x0012,0x0007, 0x0011,0x0006,
+ 0x0016,0x0005, 0x0014,0x0006, 0x0016,0x0006, 0x0014,0x0007, 0x0016,0x0007,
+ 0x0015,0x0006, 0x0014,0x0008, 0x0016,0x0008, 0x0014,0x0009, 0x0016,0x0009,
+ 0x0015,0x0008, 0x0018,0x0006, 0x001a,0x0006, 0x0018,0x0007, 0x001a,0x0007,
+ 0x0019,0x0006, 0x0018,0x0009, 0x001a,0x0009, 0x0019,0x0008, 0x001e,0x0005,
+ 0x001c,0x0006, 0x001e,0x0006, 0x001c,0x0007, 0x001e,0x0007, 0x001d,0x0006,
+ 0x001c,0x0008, 0x001e,0x0008, 0x001c,0x0009, 0x001e,0x0009, 0x001d,0x0008,
+ 0x0020,0x0006, 0x0022,0x0006, 0x0020,0x0007, 0x0022,0x0007, 0x0021,0x0006,
+ 0x0020,0x0008, 0x0022,0x0008, 0x0020,0x0009, 0x0022,0x0009, 0x0021,0x0008,
+ 0x0024,0x0006, 0x0026,0x0006, 0x0024,0x0007, 0x0026,0x0007, 0x0025,0x0006,
+ 0x0026,0x0008, 0x0024,0x0009, 0x0026,0x0009, 0x0025,0x0008, 0x0028,0x0004,
+ 0x002a,0x0004, 0x0028,0x0005, 0x002a,0x0007, 0x0028,0x0008, 0x002a,0x0009,
+ 0x0029,0x0008, 0x002a,0x000b, 0x0029,0x000a, 0x002a,0x000f, 0x0029,0x000e,
+ 0x002a,0x0011, 0x002a,0x0013, 0x002c,0x0004, 0x002e,0x0004, 0x002c,0x0005,
+ 0x002c,0x0009, 0x002e,0x0009, 0x002d,0x0008, 0x002d,0x000c, 0x002e,0x000f,
+ 0x002e,0x0011, 0x002e,0x0012, 0x0030,0x0004, 0x0032,0x0007, 0x0032,0x0009,
+ 0x0031,0x0008, 0x0032,0x000b, 0x0032,0x000d, 0x0032,0x000f, 0x0031,0x000e,
+ 0x0032,0x0013, 0x0034,0x0004, 0x0036,0x0004, 0x0034,0x0005, 0x0036,0x0005,
+ 0x0035,0x0004, 0x0036,0x0008, 0x0034,0x0009, 0x0036,0x0009, 0x0035,0x0008,
+ 0x0036,0x000b, 0x0036,0x000d, 0x0036,0x0011, 0x0035,0x0010, 0x0036,0x0013,
+ 0x0038,0x0004, 0x0039,0x0004, 0x0038,0x0009, 0x003a,0x0009, 0x0039,0x0008,
+ 0x0038,0x000b, 0x003a,0x000b, 0x003a,0x000d, 0x003a,0x0011, 0x003a,0x0012,
+ 0x0038,0x0013, 0x003a,0x0013, 0x003c,0x0002, 0x003e,0x0002, 0x003c,0x0003,
+ 0x003e,0x0005, 0x003e,0x0007, 0x003c,0x0008, 0x003e,0x0008, 0x003c,0x0009,
+ 0x003e,0x0009, 0x003d,0x0008, 0x003e,0x000d, 0x003e,0x0011, 0x003e,0x0013,
+ 0x003e,0x0017, 0x003e,0x001b, 0x003e,0x001d, 0x0040,0x0002, 0x0042,0x0002,
+ 0x0042,0x0005, 0x0041,0x0006, 0x0042,0x0008, 0x0041,0x0008, 0x0042,0x000d,
+ 0x0042,0x0011, 0x0042,0x0015, 0x0042,0x0019, 0x0042,0x001b, 0x0042,0x001c,
+ 0x0041,0x001c, 0x0044,0x0002, 0x0046,0x0003, 0x0045,0x0004, 0x0046,0x0007,
+ 0x0045,0x0008, 0x0046,0x000b, 0x0046,0x000f, 0x0046,0x0013, 0x0045,0x0012,
+ 0x0046,0x0017, 0x0046,0x001b, 0x0046,0x0021, 0x0048,0x0002, 0x004a,0x0002,
+ 0x0048,0x0003, 0x004a,0x0003, 0x0049,0x0002, 0x0048,0x0008, 0x004a,0x0008,
+ 0x0048,0x0009, 0x004a,0x0009, 0x0049,0x0008, 0x004a,0x000b, 0x004a,0x000f,
+ 0x004a,0x0011, 0x004a,0x0012, 0x004a,0x0013, 0x004a,0x0015, 0x004a,0x0019,
+ 0x004a,0x001b, 0x004a,0x001d, 0x004c,0x0002, 0x004c,0x0003, 0x004d,0x0002,
+ 0x004c,0x0008, 0x004e,0x0008, 0x004c,0x0009, 0x004e,0x0009, 0x004d,0x0008,
+ 0x004c,0x000b, 0x004e,0x000b, 0x004c,0x000f, 0x004e,0x000f, 0x004e,0x0011,
+ 0x004c,0x0012, 0x004c,0x0013, 0x004e,0x0013, 0x004e,0x0015, 0x004c,0x0017,
+ 0x004e,0x0019, 0x004c,0x001b, 0x004e,0x001b, 0x004c,0x001c, 0x004c,0x001d,
+ 0x004e,0x001d, 0x0050,0x0004, 0x0052,0x0004, 0x0050,0x0006, 0x0052,0x0009,
+ 0x0052,0x000d, 0x0052,0x000f, 0x0052,0x0013, 0x0052,0x0017, 0x0052,0x0019,
+ 0x0052,0x001d, 0x0052,0x001f, 0x0052,0x0021, 0x0052,0x0023, 0x0052,0x0024,
+ 0x0052,0x0025, 0x0051,0x0024, 0x0052,0x0027, 0x0054,0x0004, 0x0056,0x0004,
+ 0x0054,0x0005, 0x0056,0x0006, 0x0054,0x0007, 0x0056,0x0011, 0x0056,0x001b,
+ 0x0056,0x001e, 0x0054,0x001f, 0x0056,0x001f, 0x0056,0x0020, 0x0054,0x0021,
+ 0x0055,0x0020, 0x0056,0x0024, 0x0054,0x0025, 0x0056,0x0025, 0x0055,0x0024,
+ 0x0054,0x0027, 0x0056,0x0027, 0x0055,0x0026, 0x005a,0x0007, 0x005a,0x0009,
+ 0x005a,0x000b, 0x005a,0x0015, 0x005a,0x001f, 0x0059,0x0020, 0x0058,0x0024,
+ 0x005a,0x0024, 0x005a,0x0027, 0x0059,0x0026, 0x005c,0x0004, 0x005e,0x0004,
+ 0x005c,0x0005, 0x005e,0x0006, 0x005c,0x0007, 0x005d,0x0006, 0x005e,0x000d,
+ 0x005e,0x0013, 0x005e,0x0017, 0x005c,0x001f, 0x005d,0x001e, 0x005e,0x0020,
+ 0x005e,0x0021, 0x005e,0x0022, 0x005e,0x0023, 0x005c,0x0024, 0x005e,0x0024,
+ 0x005c,0x0025, 0x005e,0x0025, 0x005d,0x0024, 0x005e,0x0026, 0x005e,0x0027,
+ 0x0062,0x0004, 0x0061,0x0004, 0x0062,0x0006, 0x0061,0x0006, 0x0060,0x000f,
+ 0x0060,0x0013, 0x0062,0x0013, 0x0060,0x0019, 0x0062,0x001c, 0x0060,0x001d,
+ 0x0062,0x001d, 0x0062,0x001f, 0x0060,0x0021, 0x0060,0x0023, 0x0062,0x0024,
+ 0x0060,0x0027, 0x0061,0x0026, 0x0064,0x0002, 0x0066,0x0002, 0x0064,0x0006,
+ 0x0066,0x0007, 0x0066,0x0009, 0x0066,0x000d, 0x0066,0x0013, 0x0066,0x0015,
+ 0x0066,0x0017, 0x0066,0x0019, 0x0066,0x001a, 0x0065,0x001a, 0x0066,0x001f,
+ 0x0066,0x0023, 0x0066,0x0027, 0x0066,0x002f, 0x0066,0x0030, 0x006a,0x0002,
+ 0x0068,0x0003, 0x0068,0x0006, 0x006a,0x0006, 0x006a,0x0011, 0x0068,0x0016,
+ 0x0068,0x0017, 0x006a,0x0017, 0x006a,0x001a, 0x006a,0x001b, 0x006a,0x0025,
+ 0x006a,0x002d, 0x006e,0x0003, 0x006e,0x0007, 0x006e,0x0009, 0x006e,0x000b,
+ 0x006e,0x0015, 0x006e,0x0016, 0x006e,0x0017, 0x006c,0x001a, 0x006e,0x001a,
+ 0x006e,0x001f, 0x006e,0x002b, 0x006e,0x0035, 0x0070,0x0002, 0x0070,0x0003,
+ 0x0072,0x0006, 0x0070,0x0007, 0x0071,0x0006, 0x0072,0x000b, 0x0072,0x000f,
+ 0x0072,0x0013, 0x0070,0x0015, 0x0071,0x0014, 0x0072,0x0017, 0x0072,0x0018,
+ 0x0070,0x0019, 0x0072,0x0019, 0x0070,0x001a, 0x0070,0x001b, 0x0072,0x001b,
+ 0x0071,0x001a, 0x0072,0x0021, 0x0072,0x0029, 0x0076,0x0002, 0x0076,0x0003,
+ 0x0075,0x0002, 0x0076,0x0006, 0x0074,0x0007, 0x0076,0x0007, 0x0075,0x0006,
+ 0x0076,0x000d, 0x0076,0x0011, 0x0076,0x0013, 0x0075,0x0014, 0x0076,0x0019,
+ 0x0076,0x001a, 0x0076,0x001b, 0x0075,0x001c, 0x0074,0x0023, 0x0075,0x0022,
+ 0x0074,0x0026, 0x0076,0x0026, 0x0074,0x0027, 0x0076,0x002b, 0x0076,0x002f,
+ 0x0078,0x0002, 0x0078,0x0004, 0x007a,0x0004, 0x007a,0x0005, 0x0079,0x0004,
+ 0x007a,0x0009, 0x007a,0x000a, 0x007a,0x000b, 0x007a,0x000d, 0x007a,0x000f,
+ 0x007a,0x0010, 0x007a,0x0011, 0x007a,0x0012, 0x007a,0x0013, 0x007a,0x0017,
+ 0x007a,0x001b, 0x007a,0x0021, 0x007a,0x0027, 0x007a,0x002b, 0x007a,0x002f,
+ 0x007a,0x0030, 0x0079,0x0034, 0x007a,0x0039, 0x007a,0x003a, 0x007e,0x0002,
+ 0x007c,0x0004, 0x007e,0x0004, 0x007e,0x000c, 0x007c,0x000d, 0x007e,0x0011,
+ 0x007e,0x0013, 0x007e,0x001b, 0x007e,0x0025, 0x007e,0x002d, 0x007e,0x0037,
+ 0x0082,0x0003, 0x0082,0x0005, 0x0082,0x0009, 0x0082,0x000b, 0x0080,0x0010,
+ 0x0082,0x0010, 0x0082,0x0012, 0x0082,0x0015, 0x0082,0x001f, 0x0082,0x002b,
+ 0x0082,0x0035, 0x0082,0x0039, 0x0082,0x003f, 0x0084,0x0002, 0x0086,0x0002,
+ 0x0084,0x0003, 0x0086,0x0003, 0x0085,0x0002, 0x0086,0x0004, 0x0084,0x0005,
+ 0x0085,0x0004, 0x0086,0x000a, 0x0084,0x000b, 0x0085,0x000a, 0x0086,0x000d,
+ 0x0086,0x000e, 0x0086,0x000f, 0x0084,0x0010, 0x0084,0x0011, 0x0086,0x0011,
+ 0x0085,0x0010, 0x0084,0x0012, 0x0084,0x0013, 0x0086,0x0013, 0x0085,0x0012,
+ 0x0086,0x0019, 0x0086,0x0023, 0x0086,0x0029, 0x0086,0x0033, 0x0086,0x0039,
+ 0x008a,0x0003, 0x0089,0x0002, 0x0088,0x0004, 0x008a,0x0004, 0x0088,0x0005,
+ 0x0089,0x0004, 0x008a,0x000b, 0x008a,0x0010, 0x0088,0x0011, 0x008a,0x0011,
+ 0x0089,0x0010, 0x0088,0x0012, 0x008a,0x0012, 0x0089,0x0012, 0x008a,0x0017,
+ 0x008a,0x001b, 0x0089,0x0020, 0x008a,0x0025, 0x0088,0x0027, 0x008a,0x002b,
+ 0x008a,0x002f, 0x008a,0x0039, 0x0088,0x003a, 0x008d,0x0044, 0x0092,0x0009,
+ 0x0092,0x0025, 0x0092,0x0029, 0x0092,0x002d, 0x0092,0x0033, 0x0092,0x0037,
+ 0x0092,0x003d, 0x0092,0x0041, 0x0095,0x0002, 0x0095,0x0004, 0x0095,0x0010,
+ 0x0095,0x0012, 0x0096,0x0021, 0x0096,0x0029, 0x0095,0x002e, 0x0096,0x0030,
+ 0x0096,0x0033, 0x0096,0x003a, 0x0096,0x0043, 0x009a,0x0008, 0x009a,0x0009,
+ 0x0099,0x0008, 0x009a,0x0011, 0x009a,0x0023, 0x009a,0x0033, 0x009a,0x003d,
+ 0x009a,0x0044, 0x009a,0x0045, 0x0099,0x0044, 0x009d,0x0002, 0x009e,0x0008,
+ 0x009c,0x0009, 0x009e,0x0009, 0x009d,0x0008, 0x009e,0x0011, 0x009d,0x0010,
+ 0x009e,0x001f, 0x009e,0x003f, 0x00a0,0x0009, 0x00a0,0x0011, 0x00a2,0x0030,
+ 0x00a2,0x0033, 0x00a6,0x0006, 0x00a6,0x0007, 0x00a6,0x0011, 0x00a6,0x0044,
+ 0x00a6,0x004b, 0x00aa,0x0007, 0x00aa,0x0015, 0x00ae,0x0006, 0x00ae,0x0011,
+ 0x00ae,0x001b, 0x00ae,0x0025, 0x00ae,0x003d, 0x00ae,0x0041, 0x00ae,0x0043,
+ 0x00ae,0x0045, 0x00b2,0x0006, 0x00b0,0x0007, 0x00b1,0x0006, 0x00b2,0x0017,
+ 0x00b1,0x0016, 0x00b0,0x0019, 0x00b2,0x0021, 0x00b2,0x003d, 0x00b5,0x004a,
+ 0x00ba,0x0009, 0x00ba,0x000f, 0x00bc,0x0009, 0x00be,0x0009, 0x00be,0x000f,
+ 0x00bd,0x000e, 0x00be,0x0017, 0x00c2,0x0009, 0x00c2,0x0019, 0x00c2,0x001f,
+ 0x00c2,0x0033, 0x00c6,0x0009, 0x00c5,0x000e, 0x00c6,0x0015, 0x00c6,0x0023,
+ 0x00c4,0x002d, 0x00c6,0x002f, 0x00c5,0x002e, 0x00c6,0x0045, 0x00ce,0x0007,
+ 0x00ce,0x0021, 0x00ce,0x0023, 0x00ce,0x0025, 0x00ce,0x0027, 0x00ce,0x0033,
+ 0x00ce,0x003d, 0x00d2,0x0006, 0x00d0,0x0015, 0x00d0,0x001b, 0x00d2,0x001b,
+ 0x00d1,0x001a, 0x00d0,0x001f, 0x00d2,0x0025, 0x00d1,0x0024, 0x00d2,0x0037,
+ 0x00d2,0x0041, 0x00d2,0x0045, 0x00d9,0x0044, 0x00e1,0x0004, 0x00e2,0x000d,
+ 0x00e2,0x0021, 0x00e0,0x003a, 0x00e6,0x003d, 0x00e6,0x0061, 0x00e6,0x0067,
+ 0x00e9,0x0004, 0x00ea,0x0008, 0x00ea,0x0009, 0x00ea,0x0039, 0x00e9,0x0038,
+ 0x00ea,0x003f, 0x00ec,0x000d, 0x00ee,0x000d, 0x00ee,0x0037, 0x00f2,0x003d,
+ 0x00f2,0x0062, 0x00f5,0x0002, 0x00fa,0x0017, 0x00fa,0x003d, 0x00fe,0x0006,
+ 0x00fd,0x0006, 0x00fc,0x0015, 0x00fe,0x001b, 0x00fc,0x0025, 0x00fe,0x0025,
+ 0x00fd,0x0024, 0x00fe,0x0041, 0x00fe,0x004d, 0x00fd,0x004e, 0x0101,0x0014,
+ 0x0106,0x004d, 0x010a,0x0009, 0x010a,0x000b, 0x0109,0x000a, 0x010a,0x004f,
+ 0x010a,0x0058, 0x010e,0x0008, 0x010c,0x0009, 0x010e,0x0009, 0x010d,0x0008,
+ 0x010e,0x000b, 0x010e,0x002b, 0x010d,0x002a, 0x010e,0x0035, 0x010e,0x003d,
+ 0x010e,0x003f, 0x010e,0x0049, 0x010e,0x0057, 0x010d,0x0056, 0x010d,0x0058,
+ 0x0111,0x0004, 0x0111,0x0006, 0x0110,0x0009, 0x0112,0x0009, 0x0111,0x0008,
+ 0x0112,0x002f, 0x0110,0x0035, 0x0110,0x0037, 0x0112,0x0039, 0x0112,0x003d,
+ 0x0112,0x003f, 0x0112,0x0045, 0x0111,0x0044, 0x0112,0x004b, 0x0112,0x0059,
+ 0x0112,0x0069, 0x0112,0x007f, 0x0116,0x0009, 0x0115,0x0008, 0x0114,0x000b,
+ 0x0116,0x000b, 0x0116,0x0058, 0x011a,0x0015, 0x011a,0x001f, 0x011a,0x002b,
+ 0x011a,0x003f, 0x011a,0x0049, 0x011a,0x0085, 0x011e,0x0007, 0x011e,0x0019,
+ 0x011e,0x001b, 0x011e,0x0023, 0x011e,0x0027, 0x011e,0x002f, 0x011e,0x0043,
+ 0x011e,0x004b, 0x011e,0x004e, 0x011e,0x004f, 0x011e,0x005f, 0x011e,0x0061,
+ 0x011e,0x0065, 0x011e,0x0083, 0x0122,0x0006, 0x0120,0x0007, 0x0122,0x0007,
+ 0x0121,0x0006, 0x0122,0x0049, 0x0121,0x004e, 0x0122,0x008f, 0x0125,0x0004,
+ 0x0124,0x0007, 0x0125,0x0006, 0x0124,0x001b, 0x0126,0x001b, 0x0126,0x0045,
+ 0x0126,0x0087, 0x0128,0x0007, 0x0129,0x0006, 0x012a,0x0019, 0x012a,0x003d,
+ 0x012a,0x0051, 0x012a,0x0065, 0x012a,0x0083, 0x012d,0x005a, 0x0132,0x0009,
+ 0x0132,0x008f, 0x0134,0x0009, 0x0135,0x003e, 0x013a,0x003d, 0x013a,0x0044,
+ 0x0139,0x0044, 0x013e,0x0009, 0x013d,0x0008, 0x013c,0x003d, 0x013c,0x0044,
+ 0x013c,0x0053, 0x013e,0x008f, 0x013e,0x0095, 0x0142,0x0044, 0x0142,0x0097,
+ 0x0142,0x009e, 0x0144,0x0007, 0x0148,0x0015, 0x0148,0x001c, 0x0148,0x001f,
+ 0x0148,0x0026, 0x0149,0x0086, 0x014d,0x0006, 0x014e,0x0044, 0x014d,0x0048,
+ 0x014e,0x009e, 0x0152,0x0009, 0x0151,0x00a6, 0x0155,0x0030, 0x015d,0x003a,
+ 0x0162,0x009e, 0x0164,0x000f, 0x0164,0x0013, 0x0169,0x000e, 0x0174,0x0009,
+ 0x0179,0x0008, 0x0180,0x0009, 0x0181,0x0044, 0x0186,0x0044, 0x0185,0x0044,
+ 0x018a,0x0068, 0x0195,0x004e, 0x01a6,0x0009, 0x01a5,0x0008, 0x01b1,0x003a,
+ 0x01c4,0x0029, 0x01c4,0x0030, 0x01ca,0x008f, 0x01ca,0x0095, 0x01cc,0x0029,
+ 0x01cc,0x0033, 0x01ce,0x003d, 0x01d6,0x00b2, 0x01d8,0x0009, 0x01d9,0x002a,
+ 0x01d9,0x0056, 0x01d9,0x00a4, 0x01dd,0x003a, 0x01e2,0x00b2, 0x01e6,0x0013,
+ 0x01e6,0x009f, 0x01e6,0x00ba, 0x01e6,0x00c0, 0x01e6,0x00d3, 0x01e6,0x00d5,
+ 0x01e6,0x00e5, 0x01e8,0x0005, 0x01f2,0x0013, 0x01f2,0x0095, 0x01f2,0x009f,
+ 0x01f2,0x00ba, 0x01f2,0x00c0, 0x01f2,0x00d3, 0x0202,0x008f, 0x0202,0x0095,
+ 0x0202,0x00f3, 0x0202,0x00f9, 0x020a,0x0044, 0x0209,0x00b4, 0x020e,0x0009,
+ 0x020d,0x0008, 0x020c,0x003d, 0x020c,0x0044, 0x020c,0x0053, 0x020e,0x008f,
+ 0x020e,0x0095, 0x020c,0x00b1, 0x020e,0x00f3, 0x020e,0x00f9, 0x0210,0x0013,
+ 0x0211,0x0024, 0x0210,0x0026, 0x0219,0x0004, 0x021e,0x008f, 0x021e,0x0095,
+ 0x0221,0x003a, 0x0230,0x0009, 0x0236,0x0009, 0x0234,0x0029, 0x0234,0x0030,
+ 0x0234,0x0033, 0x0234,0x003a, 0x0234,0x003d, 0x0234,0x0044, 0x0235,0x00a6,
+ 0x023a,0x0009, 0x023d,0x003a, 0x0245,0x0044, 0x0249,0x003a, 0x024e,0x009e,
+ 0x024e,0x0106, 0x0251,0x0026, 0x0258,0x0013, 0x0259,0x0024, 0x0258,0x0061,
+ 0x0259,0x0086, 0x0258,0x00c7, 0x0258,0x00df, 0x0259,0x00ec, 0x0258,0x00fc,
+ 0x025d,0x0024, 0x025d,0x00de, 0x0260,0x00f6, 0x0268,0x0009, 0x0269,0x0044,
+ 0x0268,0x00f3, 0x0268,0x00f9, 0x026d,0x003a, 0x0270,0x0068, 0x0275,0x003a,
+ 0x027a,0x0044, 0x0279,0x0044, 0x027e,0x007e, 0x0281,0x0044, 0x0285,0x0008,
+ 0x028d,0x0006, 0x028d,0x00d2, 0x0295,0x00cc, 0x0296,0x00f6, 0x0295,0x00f8,
+ 0x0299,0x0030, 0x029e,0x007e, 0x029d,0x0080, 0x02a6,0x008f, 0x02a6,0x0095,
+ 0x02aa,0x0029, 0x02aa,0x0030, 0x02b5,0x0008, 0x02b9,0x003a, 0x02bd,0x0004,
+ 0x02bd,0x00fc, 0x02c2,0x00b2, 0x02c1,0x00b4, 0x02c4,0x0029, 0x02c8,0x0029,
+ 0x02c8,0x0033, 0x02ca,0x003d, 0x02ce,0x0029, 0x02ce,0x0030, 0x02d2,0x0068,
+ 0x02d1,0x006a, 0x02d5,0x006a, 0x02d9,0x0008, 0x02de,0x012c, 0x02e2,0x012c,
+ 0x02e4,0x0009, 0x02e5,0x002a, 0x02e5,0x0056, 0x02e5,0x012c, 0x02ea,0x0029,
+ 0x02ea,0x0030, 0x02e9,0x0030, 0x02ec,0x0029, 0x02ec,0x0030, 0x02ee,0x012c,
+ 0x02f1,0x0068, 0x02f1,0x00b2, 0x02f1,0x0108, 0x02f1,0x012c, 0x02f6,0x0013,
+ 0x02f6,0x0015, 0x02f6,0x001f, 0x02f6,0x0030, 0x02f6,0x0065, 0x02f6,0x0067,
+ 0x02f6,0x009f, 0x02f6,0x00b6, 0x02f6,0x00b9, 0x02f6,0x00c0, 0x02f6,0x00cf,
+ 0x02f6,0x0107, 0x02f6,0x010b, 0x02f6,0x010f, 0x02f6,0x0115, 0x02f6,0x012d,
+ 0x02f6,0x0134, 0x02f6,0x0153, 0x02f6,0x0171, 0x02f6,0x0176, 0x02f8,0x0003,
+ 0x02fa,0x017b, 0x02fc,0x00ba, 0x02fc,0x00d3, 0x0302,0x0013, 0x0302,0x001f,
+ 0x0302,0x0030, 0x0302,0x005d, 0x0302,0x0065, 0x0302,0x0067, 0x0302,0x0099,
+ 0x0302,0x009f, 0x0302,0x00ad, 0x0302,0x00b9, 0x0302,0x00c0, 0x0302,0x00cf,
+ 0x0301,0x00d2, 0x0301,0x00fe, 0x0302,0x0107, 0x0302,0x010b, 0x0302,0x010f,
+ 0x0302,0x0117, 0x0302,0x0134, 0x0302,0x0153, 0x0302,0x0157, 0x0302,0x0176,
+ 0x0306,0x0029, 0x0308,0x00b2, 0x0309,0x00dc, 0x030d,0x00f8, 0x0312,0x00f3,
+ 0x0318,0x007e, 0x031d,0x0080, 0x0321,0x0008, 0x0321,0x0094, 0x0326,0x017b,
+ 0x0326,0x0181, 0x0329,0x012e, 0x032a,0x017b, 0x032a,0x0181, 0x032e,0x008f,
+ 0x032e,0x0095, 0x032e,0x00f3, 0x032e,0x00f9, 0x0332,0x0009, 0x0331,0x0008,
+ 0x0330,0x003d, 0x0330,0x0044, 0x0330,0x0053, 0x0332,0x008f, 0x0332,0x0095,
+ 0x0330,0x00b1, 0x0332,0x00f3, 0x0332,0x00f9, 0x0330,0x0127, 0x0332,0x017b,
+ 0x0332,0x0181, 0x033c,0x0013, 0x033c,0x001c, 0x033d,0x0086, 0x033d,0x00ec,
+ 0x033d,0x0172, 0x033e,0x019d, 0x0345,0x0002, 0x0344,0x008f, 0x0344,0x00f3,
+ 0x034d,0x0030, 0x0352,0x0033, 0x0354,0x0029, 0x0354,0x0030, 0x035a,0x0009,
+ 0x035a,0x017b, 0x035a,0x019b, 0x035a,0x01a2, 0x035e,0x0181, 0x0360,0x0009,
+ 0x0366,0x0009, 0x0364,0x0029, 0x0364,0x0030, 0x0364,0x0033, 0x0364,0x003a,
+ 0x0364,0x003d, 0x0364,0x0044, 0x0369,0x0030, 0x0370,0x0029, 0x0370,0x0030,
+ 0x0376,0x0033, 0x037a,0x0009, 0x037a,0x019b, 0x037a,0x01a2, 0x037c,0x0009,
+ 0x0382,0x0181, 0x0386,0x0009, 0x0384,0x0029, 0x0384,0x0030, 0x0384,0x0033,
+ 0x0384,0x003a, 0x0384,0x003d, 0x0384,0x0044, 0x038a,0x0044, 0x038a,0x009e,
+ 0x038a,0x0106, 0x038a,0x0198, 0x038d,0x010e, 0x038d,0x0152, 0x038d,0x0158,
+ 0x0392,0x009e, 0x0392,0x0106, 0x0392,0x0198, 0x0395,0x0086, 0x0395,0x009a,
+ 0x0395,0x00ec, 0x0395,0x0172, 0x0398,0x014e, 0x0398,0x0175, 0x0398,0x018d,
+ 0x039c,0x0023, 0x039c,0x0027, 0x039c,0x00ef, 0x039c,0x0139, 0x039c,0x0168,
+ 0x03a0,0x0019, 0x03a0,0x001d, 0x03a0,0x0023, 0x03a0,0x0027, 0x03a1,0x004e,
+ 0x03a4,0x0162, 0x03a4,0x0183, 0x03a8,0x0013, 0x03a8,0x0027, 0x03a8,0x0133,
+ 0x03a8,0x0148, 0x03a8,0x0181, 0x03ac,0x0013, 0x03ac,0x0027, 0x03b0,0x017b,
+ 0x03b0,0x0181, 0x03b4,0x004b, 0x03b4,0x00e0, 0x03b4,0x00fb, 0x03b8,0x000f,
+ 0x03b8,0x0013, 0x03b8,0x00ab, 0x03b8,0x00bf, 0x03b8,0x00d0, 0x03bd,0x00da,
+ 0x03bd,0x012c, 0x03c8,0x000f, 0x03c8,0x0013, 0x03c8,0x0019, 0x03c8,0x001d,
+ 0x03cd,0x0086, 0x03cd,0x00ec, 0x03cd,0x0172, 0x03d2,0x00e0, 0x03d2,0x00ef,
+ 0x03d2,0x0112, 0x03d2,0x0139, 0x03d2,0x0168, 0x03d6,0x017b, 0x03d6,0x0181,
+ 0x03da,0x0133, 0x03da,0x0148, 0x03e2,0x0023, 0x03e2,0x0027, 0x03e6,0x0027,
+ 0x03e6,0x0181, 0x03ee,0x017b, 0x03ee,0x0181, 0x03fe,0x003d, 0x0401,0x012a,
+ 0x0401,0x019e, 0x0405,0x01a0, 0x040a,0x000d, 0x040a,0x011f, 0x040a,0x016f,
+ 0x040d,0x012a, 0x0412,0x017b, 0x041a,0x0033, 0x041a,0x003d, 0x041a,0x0181,
+ 0x0421,0x0086, 0x0421,0x009a, 0x0421,0x00ec, 0x0421,0x0172, 0x042e,0x0205,
+ 0x043a,0x0205, 0x043e,0x017b, 0x0442,0x01f5, 0x044c,0x0007, 0x0452,0x0033,
+ 0x0452,0x01ce, 0x0452,0x01d0, 0x0452,0x01f1, 0x0452,0x01fb, 0x0452,0x0225,
+ 0x0454,0x0005, 0x045a,0x0033, 0x045a,0x0181, 0x045a,0x01ce, 0x045a,0x01d0,
+ 0x045a,0x01f1, 0x0469,0x01de, 0x046e,0x0181, 0x047a,0x01ce, 0x047a,0x01f1,
+ 0x0485,0x012c, 0x0489,0x012c, 0x0490,0x01d8, 0x0496,0x0033, 0x0496,0x003d,
+ 0x0498,0x008f, 0x0498,0x00f3, 0x049e,0x0044, 0x049e,0x0221, 0x04a1,0x0006,
+ 0x04a2,0x0044, 0x04a6,0x0221, 0x04a9,0x0004, 0x04ac,0x0027, 0x04b1,0x009a,
+ 0x04b6,0x0097, 0x04b8,0x0027, 0x04c6,0x0219, 0x04ca,0x017b, 0x04cc,0x004b,
+ 0x04d0,0x00ab, 0x04d6,0x017b, 0x04d8,0x000f, 0x04d8,0x0019, 0x04d8,0x0033,
+ 0x04d8,0x003d, 0x04de,0x003d, 0x04de,0x0103, 0x04de,0x018b, 0x04de,0x0231,
+ 0x04e2,0x0044, 0x04e2,0x009e, 0x04e2,0x0106, 0x04e2,0x0198, 0x04e5,0x01a4,
+ 0x04e5,0x01b6, 0x04ea,0x009e, 0x04ea,0x0106, 0x04ea,0x0198, 0x04ed,0x002e,
+ 0x04ed,0x0038, 0x04ed,0x00a2, 0x04f1,0x0086, 0x04f1,0x009a, 0x04f1,0x00ec,
+ 0x04f1,0x0172, 0x04f9,0x004e, 0x04f8,0x0229, 0x04f8,0x022d, 0x0500,0x023e,
+ 0x0504,0x0217, 0x0510,0x00f3, 0x0514,0x0043, 0x0514,0x004d, 0x0514,0x00c3,
+ 0x0514,0x013d, 0x0514,0x0215, 0x0514,0x0232, 0x0515,0x0260, 0x0519,0x002a,
+ 0x0518,0x0030, 0x0518,0x0067, 0x0518,0x00c9, 0x0518,0x01eb, 0x0518,0x01ef,
+ 0x051c,0x0139, 0x051c,0x0168, 0x0520,0x0027, 0x0526,0x014e, 0x0526,0x0175,
+ 0x0526,0x018d, 0x052d,0x0200, 0x0532,0x0021, 0x0532,0x00bf, 0x0532,0x00d0,
+ 0x0532,0x0239, 0x0532,0x0266, 0x053d,0x0024, 0x053d,0x00da, 0x054a,0x000f,
+ 0x054a,0x00ab, 0x054a,0x023a, 0x054e,0x0043, 0x054e,0x004d, 0x054e,0x00c3,
+ 0x054e,0x013d, 0x054e,0x0215, 0x054e,0x0232, 0x054e,0x029d, 0x0552,0x014e,
+ 0x0552,0x018d, 0x0556,0x00f3, 0x0556,0x01e4, 0x055a,0x0299, 0x055d,0x0086,
+ 0x055d,0x009a, 0x055d,0x00ec, 0x055d,0x0172, 0x0566,0x01dc, 0x0566,0x02a5,
+ 0x056d,0x020a, 0x057a,0x003d, 0x057a,0x01d4, 0x057a,0x01f3, 0x0579,0x025e,
+ 0x057e,0x0139, 0x057e,0x0168, 0x0581,0x0006, 0x0586,0x017b, 0x0586,0x0181,
+ 0x0586,0x028c, 0x0588,0x0007, 0x058e,0x0033, 0x058e,0x008f, 0x058e,0x01d0,
+ 0x058e,0x027c, 0x0590,0x0003, 0x0596,0x0033, 0x0596,0x008f, 0x0596,0x0095,
+ 0x0596,0x01d0, 0x0596,0x027c, 0x05a2,0x026f, 0x05a5,0x0284, 0x05aa,0x017b,
+ 0x05ac,0x0205, 0x05b2,0x008f, 0x05b6,0x017b, 0x05b8,0x01da, 0x05c1,0x0276,
+ 0x05c6,0x0248, 0x05c8,0x0247, 0x05c8,0x027e, 0x05cc,0x003d, 0x05cc,0x01d4,
+ 0x05cc,0x01f3, 0x05d0,0x014e, 0x05d0,0x018d, 0x05da,0x00f9, 0x05dd,0x0006,
+ 0x05de,0x0044, 0x05e5,0x002e, 0x05e6,0x02f1, 0x05ea,0x01d4, 0x05ea,0x01f3,
+ 0x05ea,0x022d, 0x05ed,0x0002, 0x05f6,0x0027, 0x05fa,0x0097, 0x05fc,0x003d,
+ 0x0602,0x003d, 0x0606,0x00f3, 0x060a,0x0027, 0x060e,0x003d, 0x060e,0x0103,
+ 0x060e,0x018b, 0x060e,0x0231, 0x060e,0x02d1, 0x0611,0x01fc, 0x0611,0x0234,
+ 0x061a,0x0287, 0x061d,0x0214, 0x0621,0x01d4, 0x062a,0x0027, 0x062a,0x022d,
+ 0x062e,0x009e, 0x062e,0x0106, 0x062e,0x0198, 0x0632,0x009e, 0x0632,0x0106,
+ 0x0632,0x0198, 0x0639,0x0042, 0x0639,0x00b2, 0x0639,0x0108, 0x063d,0x01f8,
+ 0x0641,0x0086, 0x0641,0x009a, 0x0641,0x00ec, 0x0641,0x0172, 0x0645,0x0044,
+ 0x0649,0x0042, 0x0648,0x0087, 0x0648,0x00ed, 0x0648,0x0173, 0x0649,0x01a0,
+ 0x0648,0x0241, 0x0648,0x026f, 0x0648,0x02df, 0x0648,0x0307, 0x064c,0x023a,
+ 0x064c,0x02b3, 0x0651,0x0062, 0x0650,0x0217, 0x0651,0x02ac, 0x0650,0x02d6,
+ 0x0655,0x0042, 0x065d,0x0042, 0x0664,0x02b1, 0x0664,0x02ce, 0x0669,0x0238,
+ 0x066d,0x002a, 0x066c,0x0039, 0x066d,0x01f6, 0x066c,0x0213, 0x066c,0x022e,
+ 0x066d,0x02a2, 0x066c,0x02e1, 0x0671,0x002a, 0x0670,0x0030, 0x0670,0x0067,
+ 0x0670,0x00c9, 0x0670,0x01eb, 0x0670,0x01ef, 0x0670,0x02c3, 0x0675,0x0020,
+ 0x0678,0x0133, 0x0678,0x0148, 0x067c,0x0027, 0x0681,0x023a, 0x0684,0x0021,
+ 0x0684,0x00bf, 0x0684,0x00d0, 0x0689,0x01fc, 0x068e,0x0162, 0x068e,0x0183,
+ 0x0691,0x0200, 0x0696,0x0023, 0x0696,0x00e0, 0x0696,0x00fb, 0x0696,0x0268,
+ 0x069a,0x0282, 0x069d,0x007e, 0x06a2,0x004b, 0x06a2,0x023e, 0x06a2,0x02dc,
+ 0x06a6,0x0097, 0x06aa,0x02b1, 0x06aa,0x02ce, 0x06ae,0x0039, 0x06ae,0x0213,
+ 0x06ae,0x022e, 0x06ae,0x02e1, 0x06b2,0x0162, 0x06b2,0x0183, 0x06b6,0x0023,
+ 0x06b6,0x00e0, 0x06b6,0x00fb, 0x06ba,0x008f, 0x06ba,0x01e4, 0x06be,0x034b,
+ 0x06c1,0x0086, 0x06c1,0x009a, 0x06c1,0x00ec, 0x06c1,0x0172, 0x06c6,0x01da,
+ 0x06c6,0x0280, 0x06c6,0x0351, 0x06ce,0x008f, 0x06d2,0x01e3, 0x06d2,0x0287,
+ 0x06d2,0x0353, 0x06d6,0x027a, 0x06d6,0x029b, 0x06da,0x0033, 0x06da,0x01ce,
+ 0x06da,0x01f1, 0x06de,0x0133, 0x06de,0x0148, 0x06e2,0x0021, 0x06e2,0x00bf,
+ 0x06e2,0x00d0, 0x06e5,0x023a, 0x06e9,0x0004, 0x06ee,0x028c, 0x06ee,0x0338,
+ 0x06f2,0x0328, 0x06f2,0x0330, 0x06f4,0x0005, 0x06f9,0x01e0, 0x06fe,0x0328,
+ 0x06fe,0x0330, 0x0702,0x003d, 0x0702,0x00f3, 0x0702,0x0330, 0x0704,0x0003,
+ 0x070a,0x003d, 0x070a,0x00f3, 0x070a,0x01d4, 0x070a,0x01f3, 0x070a,0x0330,
+ 0x0711,0x032a, 0x0711,0x032e, 0x0716,0x003d, 0x0718,0x0205, 0x0718,0x0282,
+ 0x071e,0x00f3, 0x0720,0x01dc, 0x0720,0x02a5, 0x0726,0x0324, 0x072a,0x028a,
+ 0x072a,0x02a7, 0x0729,0x031c, 0x0729,0x032a, 0x072e,0x003d, 0x072e,0x00f9,
+ 0x072e,0x022d, 0x072e,0x0248, 0x072e,0x02e4, 0x0730,0x003d, 0x0730,0x0247,
+ 0x0730,0x02e3, 0x0730,0x0324, 0x0732,0x0324, 0x0739,0x032e, 0x073e,0x003d,
+ 0x0740,0x003d, 0x0744,0x027a, 0x0744,0x029b, 0x0748,0x0033, 0x0748,0x01ce,
+ 0x0748,0x01f1, 0x074c,0x0162, 0x074c,0x0183, 0x0750,0x0023, 0x0750,0x00e0,
+ 0x0750,0x00fb, 0x0755,0x0246, 0x075a,0x0095, 0x075a,0x0397, 0x075d,0x0004,
+ 0x076a,0x03b3, 0x076d,0x0002, 0x0772,0x02fb, 0x0772,0x0301, 0x0772,0x0315,
+ 0x0772,0x0397, 0x0776,0x008f, 0x077e,0x0027, 0x078a,0x00a1, 0x0792,0x009d,
+ 0x0792,0x00c3, 0x0792,0x02fb, 0x0792,0x0301, 0x0792,0x0315, 0x0792,0x03bd,
+ 0x0796,0x0027, 0x0796,0x024f, 0x079e,0x009d, 0x07a6,0x009d, 0x07a6,0x02fb,
+ 0x07a6,0x0301, 0x07a6,0x0315, 0x07a6,0x03bd, 0x07aa,0x0027, 0x07aa,0x024f,
+ 0x07ae,0x009d, 0x07b9,0x004e, 0x07b8,0x0087, 0x07b8,0x00ed, 0x07b8,0x0173,
+ 0x07b8,0x0197, 0x07b9,0x021a, 0x07b9,0x02b8, 0x07b9,0x0364, 0x07be,0x0029,
+ 0x07be,0x0030, 0x07c0,0x017b, 0x07c6,0x017b, 0x07c8,0x00f3, 0x07ce,0x00f3,
+ 0x07d0,0x008f, 0x07d6,0x008f, 0x07d9,0x01e8, 0x07dd,0x0292, 0x07e2,0x0053,
+ 0x07e6,0x008f, 0x07e6,0x00f3, 0x07e6,0x017b, 0x07e8,0x0029, 0x07e8,0x0030,
+ 0x07ec,0x0021, 0x07ec,0x02ad, 0x07f2,0x0181, 0x07f2,0x0315, 0x07f4,0x0021,
+ 0x07f8,0x020f, 0x07fd,0x002e, 0x0800,0x008f, 0x0805,0x0006, 0x0809,0x03c2,
+ 0x080d,0x0084, 0x0812,0x0009, 0x0811,0x0008, 0x0812,0x00f3, 0x0812,0x00f9,
+ 0x0812,0x017b, 0x0812,0x0181, 0x0814,0x0033, 0x0818,0x0023, 0x081c,0x0285,
+ 0x0826,0x03bd, 0x082c,0x008f, 0x082c,0x017b, 0x0832,0x0043, 0x0832,0x011b,
+ 0x0832,0x01b3, 0x0832,0x01c3, 0x0835,0x032a, 0x0838,0x0085, 0x0839,0x032a,
+ 0x083e,0x0049, 0x083d,0x0084, 0x083e,0x02fb, 0x083e,0x0301, 0x083e,0x0315,
+ 0x083e,0x0397, 0x0842,0x0009, 0x0841,0x0008, 0x0844,0x0009, 0x0846,0x008f,
+ 0x084a,0x0033, 0x084e,0x0285, 0x0851,0x009a, 0x0856,0x00a1, 0x0859,0x031c,
+ 0x085d,0x00b2, 0x0861,0x0012, 0x0861,0x02cc, 0x0865,0x0058, 0x0865,0x007e,
+ 0x0869,0x004a, 0x0871,0x0010, 0x0876,0x003d, 0x0879,0x032c, 0x087e,0x0089,
+ 0x0882,0x0229, 0x0882,0x022d, 0x0882,0x02c7, 0x0882,0x02cb, 0x0886,0x0021,
+ 0x0886,0x02ad, 0x0885,0x0356, 0x088a,0x0017, 0x088a,0x020f, 0x0889,0x0354,
+ 0x088d,0x009c, 0x0892,0x0089, 0x0895,0x0246, 0x089a,0x03bd, 0x089e,0x008f,
+ 0x089e,0x02f9, 0x089e,0x0313, 0x08a1,0x032a, 0x08a6,0x0053, 0x08a6,0x0095,
+ 0x08a6,0x0397, 0x08a8,0x017b, 0x08ad,0x031a, 0x08b2,0x017b, 0x08b4,0x00f3,
+ 0x08b5,0x02a0, 0x08b8,0x0089, 0x08c1,0x0024, 0x08c4,0x00f3, 0x08c9,0x007e,
+ 0x08cd,0x007c, 0x08cd,0x0222, 0x08cd,0x0294, 0x08d1,0x003a, 0x08d6,0x0009,
+ 0x08d9,0x003a, 0x08dc,0x001f, 0x08e0,0x008f, 0x08e0,0x017b, 0x08e4,0x0009,
+ 0x08e8,0x01ed, 0x08ed,0x031c, 0x08f2,0x003d, 0x08f6,0x008f, 0x08f6,0x017b,
+ 0x08fa,0x0009, 0x08fe,0x003d, 0x0902,0x01e9, 0x0904,0x01e9, 0x0904,0x0381,
+ 0x090a,0x03b1, 0x090d,0x031a, 0x0910,0x0299, 0x0914,0x034b, 0x0919,0x0008,
+ 0x091c,0x0033, 0x091c,0x003d, 0x0920,0x0027, 0x0924,0x0027, 0x0924,0x01fb,
+ 0x092a,0x01ce, 0x092a,0x01f1, 0x092d,0x031c, 0x0930,0x001f, 0x0936,0x00c5,
+ 0x0938,0x00c5, 0x0938,0x0381, 0x093c,0x001b, 0x0942,0x017d, 0x094a,0x0027,
+ 0x094e,0x0027, 0x094e,0x01fb, 0x0952,0x03b1, 0x095a,0x0029, 0x095a,0x0030,
+ 0x095d,0x0030, 0x0961,0x0030, 0x0966,0x02f9, 0x0966,0x0313, 0x0968,0x02eb,
+ 0x096d,0x0008, 0x0970,0x017b, 0x0974,0x0033, 0x0979,0x0150, 0x097d,0x009a,
+ 0x0982,0x0293, 0x0984,0x0293, 0x0984,0x0379, 0x098a,0x02eb, 0x098e,0x0009,
+ 0x0992,0x003d, 0x0996,0x003d, 0x0999,0x0062, 0x099e,0x003d, 0x09a0,0x0027,
+ 0x09a5,0x0144, 0x09a8,0x02b5, 0x09ae,0x008f, 0x09ae,0x009d, 0x09b2,0x004d,
+ 0x09b2,0x0053, 0x09b2,0x00c3, 0x09b2,0x013d, 0x09b2,0x01c5, 0x09b2,0x0271,
+ 0x09b4,0x0025, 0x09ba,0x0033, 0x09ba,0x0079, 0x09bc,0x0015, 0x09c2,0x013f,
+ 0x09c4,0x013f, 0x09c4,0x0379, 0x09ca,0x02b5, 0x09cd,0x0006, 0x09da,0x0009,
+ 0x09d9,0x0008, 0x09dc,0x000b, 0x09dc,0x004f, 0x09dd,0x0086, 0x09e0,0x0009,
+ 0x09e6,0x00a1, 0x09e8,0x0009, 0x09ed,0x0086, 0x09f2,0x001f, 0x09f2,0x002f,
+ 0x09f2,0x0049, 0x09f2,0x006f, 0x09f2,0x0085, 0x09f2,0x0091, 0x09f2,0x00a9,
+ 0x09f2,0x00d3, 0x09f2,0x00d7, 0x09f2,0x011d, 0x09f2,0x0121, 0x09f2,0x0235,
+ 0x09f2,0x0393, 0x09f6,0x0324, 0x09f8,0x0049, 0x09f8,0x00a9, 0x09f8,0x011d,
+ 0x09fe,0x001f, 0x09fe,0x0029, 0x09fe,0x0033, 0x09fe,0x003d, 0x09fe,0x0085,
+ 0x09fe,0x008f, 0x09fe,0x00d3, 0x0a00,0x003d, 0x0a06,0x012d, 0x0a0e,0x00b3,
+ 0x0a10,0x000b, 0x0a10,0x0387, 0x0a16,0x0059, 0x0a18,0x0009, 0x0a1e,0x0043,
+ 0x0a24,0x0085, 0x0a2a,0x0009, 0x0a2d,0x0008, 0x0a32,0x028a, 0x0a32,0x02a7,
+ 0x0a31,0x031c, 0x0a35,0x032e, 0x0a39,0x0006, 0x0a3a,0x0105, 0x0a3a,0x024f,
+ 0x0a3c,0x0299, 0x0a42,0x01ed, 0x0a46,0x0299, 0x0a48,0x01ed, 0x0a4c,0x0059,
+ 0x0a52,0x000b, 0x0a52,0x0387, 0x0a56,0x000b, 0x0a5e,0x0009, 0x0a60,0x003d,
+ 0x0a66,0x0105, 0x0a6a,0x0195, 0x0a6c,0x000b, 0x0a76,0x0053, 0x0a78,0x0009,
+ 0x0a7a,0x008f, 0x0a82,0x0299, 0x0a86,0x01ed, 0x0a8a,0x0027, 0x0a8e,0x004b,
+ 0x0a92,0x003d, 0x0a95,0x0322, 0x0a99,0x0038, 0x0a99,0x0090, 0x0a9c,0x0061,
+ 0x0a9c,0x00c7, 0x0a9c,0x012d, 0x0a9c,0x016f, 0x0a9c,0x017d, 0x0a9c,0x02c9,
+ 0x0a9c,0x0383, 0x0aa1,0x0010, 0x0aa4,0x00b3, 0x0aa8,0x002f, 0x0aac,0x0027,
+ 0x0ab0,0x004b, 0x0ab4,0x0043, 0x0ab9,0x0090, 0x0abd,0x0010, 0x0ac4,0x0019,
+ 0x0acc,0x00f5, 0x0acc,0x022b, 0x0acc,0x037b, 0x0ad2,0x008f, 0x0ad2,0x01f1,
+ 0x0ad6,0x0324, 0x0ad9,0x0330, 0x0ade,0x008f, 0x0ade,0x01f1, 0x0ae0,0x017b,
+ 0x0ae4,0x008f, 0x0ae9,0x004e, 0x0aee,0x0027, 0x0af2,0x028a, 0x0af2,0x02a7,
+ 0x0af1,0x031c, 0x0af6,0x0027, 0x0af9,0x031c, 0x0afe,0x00e9, 0x0afe,0x02bb,
+ 0x0b02,0x000b, 0x0b06,0x00f5, 0x0b06,0x022b, 0x0b06,0x037b, 0x0b0a,0x003d,
+ 0x0000,0x0000
+};
+
+
diff --git a/src/aig/tim/module.make b/src/aig/tim/module.make
new file mode 100644
index 00000000..81079346
--- /dev/null
+++ b/src/aig/tim/module.make
@@ -0,0 +1 @@
+SRC += src/aig/tim/tim.c
diff --git a/src/aig/tim/tim.c b/src/aig/tim/tim.c
new file mode 100644
index 00000000..8d312dba
--- /dev/null
+++ b/src/aig/tim/tim.c
@@ -0,0 +1,532 @@
+/**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 <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <assert.h>
+#include <time.h>
+
+#include "vec.h"
+#include "mem.h"
+#include "tim.h"
+
+#define AIG_MIN(a,b) (((a) < (b))? (a) : (b))
+#define AIG_MAX(a,b) (((a) > (b))? (a) : (b))
+#define AIG_ABS(a) (((a) >= 0)? (a) :-(a))
+#define AIG_INFINITY (100000000)
+
+////////////////////////////////////////////////////////////////////////
+/// DECLARATIONS ///
+////////////////////////////////////////////////////////////////////////
+
+typedef struct Tim_Box_t_ Tim_Box_t;
+typedef struct Tim_Obj_t_ Tim_Obj_t;
+
+// timing manager
+struct Tim_Man_t_
+{
+ Vec_Ptr_t * vBoxes; // the timing boxes
+ Vec_Ptr_t * vDelayTables; // pointers to the delay tables
+ Mem_Flex_t * pMemObj; // memory manager for boxes
+ int nTravIds; // traversal ID of the manager
+ int nPis; // the number of PIs
+ int nPos; // the number of POs
+ Tim_Obj_t * pPis; // timing info for the PIs
+ Tim_Obj_t * pPos; // timing info for the POs
+};
+
+// timing box
+struct Tim_Box_t_
+{
+ int iBox; // the unique ID of this box
+ int TravId; // traversal ID of this box
+ int nInputs; // the number of box inputs (POs)
+ int nOutputs; // the number of box outputs (PIs)
+ float * pDelayTable; // delay for each input->output path
+ int Inouts[0]; // the int numbers of PIs and POs
+};
+
+// timing object
+struct Tim_Obj_t_
+{
+ int Id; // the ID of this object
+ int TravId; // traversal ID of this object
+ int iObj2Box; // mapping of the object into its box
+ int iObj2Num; // mapping of the object into its number in the box
+ float timeArr; // arrival time of the object
+ float timeReq; // required time of the object
+};
+
+static inline Tim_Obj_t * Tim_ManPi( Tim_Man_t * p, int i ) { assert( i < p->nPis ); return p->pPis + i; }
+static inline Tim_Obj_t * Tim_ManPo( Tim_Man_t * p, int i ) { assert( i < p->nPos ); return p->pPos + i; }
+
+static inline Tim_Box_t * Tim_ManPiBox( Tim_Man_t * p, int i ) { return Tim_ManPi(p,i)->iObj2Box < 0 ? NULL : Vec_PtrEntry( p->vBoxes, Tim_ManPi(p,i)->iObj2Box ); }
+static inline Tim_Box_t * Tim_ManPoBox( Tim_Man_t * p, int i ) { return Tim_ManPo(p,i)->iObj2Box < 0 ? NULL : Vec_PtrEntry( p->vBoxes, Tim_ManPo(p,i)->iObj2Box ); }
+
+static inline Tim_Obj_t * Tim_ManBoxInput( Tim_Man_t * p, Tim_Box_t * pBox, int i ) { assert( i < pBox->nInputs ); return p->pPos + pBox->Inouts[i]; }
+static inline Tim_Obj_t * Tim_ManBoxOutput( Tim_Man_t * p, Tim_Box_t * pBox, int i ) { assert( i < pBox->nOutputs ); return p->pPis + pBox->Inouts[pBox->nInputs+i]; }
+
+#define Tim_ManBoxForEachInput( p, pBox, pObj, i ) \
+ for ( i = 0; (i < (pBox)->nInputs) && ((pObj) = Tim_ManBoxInput(p, pBox, i)); i++ )
+#define Tim_ManBoxForEachOutput( p, pBox, pObj, i ) \
+ for ( i = 0; (i < (pBox)->nOutputs) && ((pObj) = Tim_ManBoxOutput(p, pBox, i)); i++ )
+
+#define Tim_ManForEachPi( p, pObj, i ) \
+ for ( i = 0; (i < (p)->nPis) && ((pObj) = (p)->pPis + i); i++ ) \
+ if ( pObj->iObj2Box >= 0 ) {} else
+#define Tim_ManForEachPo( p, pObj, i ) \
+ for ( i = 0; (i < (p)->nPos) && ((pObj) = (p)->pPos + i); i++ ) \
+ if ( pObj->iObj2Box >= 0 ) {} else
+#define Tim_ManForEachBox( p, pBox, i ) \
+ Vec_PtrForEachEntry( p->vBoxes, pBox, i )
+
+////////////////////////////////////////////////////////////////////////
+/// FUNCTION DEFINITIONS ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+ Synopsis [Starts the timing manager.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Tim_Man_t * Tim_ManStart( int nPis, int nPos )
+{
+ Tim_Man_t * p;
+ int i;
+ p = ALLOC( Tim_Man_t, 1 );
+ memset( p, 0, sizeof(Tim_Man_t) );
+ p->pMemObj = Mem_FlexStart();
+ p->vBoxes = Vec_PtrAlloc( 100 );
+ p->nPis = nPis;
+ p->nPos = nPos;
+ p->pPis = ALLOC( Tim_Obj_t, nPis );
+ memset( p->pPis, 0, sizeof(Tim_Obj_t) * nPis );
+ p->pPos = ALLOC( Tim_Obj_t, nPos );
+ memset( p->pPos, 0, sizeof(Tim_Obj_t) * nPos );
+ for ( i = 0; i < nPis; i++ )
+ {
+ p->pPis[i].Id = i;
+ p->pPis[i].iObj2Box = p->pPis[i].iObj2Num = -1;
+ p->pPis[i].timeReq = AIG_INFINITY;
+ p->pPis[i].timeArr = 0.0;
+ p->pPis[i].TravId = 0;
+ }
+ for ( i = 0; i < nPos; i++ )
+ {
+ p->pPos[i].Id = i;
+ p->pPos[i].iObj2Box = p->pPos[i].iObj2Num = -1;
+ p->pPos[i].timeReq = AIG_INFINITY;
+ p->pPos[i].timeArr = 0.0;
+ p->pPos[i].TravId = 0;
+ }
+ return p;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Stops the timing manager.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Tim_ManStop( Tim_Man_t * p )
+{
+ float * pTable;
+ int i;
+ if ( p->vDelayTables )
+ {
+ Vec_PtrForEachEntry( p->vDelayTables, pTable, i )
+ FREE( pTable );
+ Vec_PtrFree( p->vDelayTables );
+ }
+ Vec_PtrFree( p->vBoxes );
+ Mem_FlexStop( p->pMemObj, 0 );
+ free( p->pPis );
+ free( p->pPos );
+ free( p );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Stops the timing manager.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Tim_ManPrint( Tim_Man_t * p )
+{
+ Tim_Box_t * pBox;
+ Tim_Obj_t * pObj;
+ int i;
+ printf( "TIMING INFORMATION:\n" );
+ Tim_ManForEachPi( p, pObj, i )
+ printf( "pi%5d : arr = %5.3f req = %5.3f\n", i, pObj->timeArr, pObj->timeReq );
+ Tim_ManForEachPo( p, pObj, i )
+ printf( "po%5d : arr = %5.3f req = %5.3f\n", i, pObj->timeArr, pObj->timeReq );
+ Tim_ManForEachBox( p, pBox, i )
+ {
+ printf( "*** Box %3d : Ins = %d. Outs = %d.\n", i, pBox->nInputs, pBox->nOutputs );
+ printf( "Delay table:" );
+ for ( i = 0; i < pBox->nInputs * pBox->nOutputs; i++ )
+ printf( " %5.3f", pBox->pDelayTable[i] );
+ printf( "\n" );
+ Tim_ManBoxForEachInput( p, pBox, pObj, i )
+ printf( "box-inp%3d : arr = %5.3f req = %5.3f\n", i, pObj->timeArr, pObj->timeReq );
+ Tim_ManBoxForEachOutput( p, pBox, pObj, i )
+ printf( "box-out%3d : arr = %5.3f req = %5.3f\n", i, pObj->timeArr, pObj->timeReq );
+ }
+ printf( "\n" );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Sets the vector of timing tables associated with the manager.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Tim_ManSetDelayTables( Tim_Man_t * p, Vec_Ptr_t * vDelayTables )
+{
+ assert( p->vDelayTables == NULL );
+ p->vDelayTables = vDelayTables;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Creates the new timing box.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Tim_ManCreateBox( Tim_Man_t * p, int * pIns, int nIns, int * pOuts, int nOuts, float * pDelayTable )
+{
+ Tim_Box_t * pBox;
+ int i;
+ pBox = (Tim_Box_t *)Mem_FlexEntryFetch( p->pMemObj, sizeof(Tim_Box_t) + sizeof(int) * (nIns+nOuts) );
+ memset( pBox, 0, sizeof(Tim_Box_t) );
+ pBox->iBox = Vec_PtrSize( p->vBoxes );
+ Vec_PtrPush( p->vBoxes, pBox );
+ pBox->pDelayTable = pDelayTable;
+ pBox->nInputs = nIns;
+ pBox->nOutputs = nOuts;
+ for ( i = 0; i < nIns; i++ )
+ {
+ assert( pIns[i] < p->nPos );
+ pBox->Inouts[i] = pIns[i];
+ p->pPos[pIns[i]].iObj2Box = pBox->iBox;
+ p->pPos[pIns[i]].iObj2Num = i;
+ }
+ for ( i = 0; i < nOuts; i++ )
+ {
+ assert( pOuts[i] < p->nPis );
+ pBox->Inouts[nIns+i] = pOuts[i];
+ p->pPis[pOuts[i]].iObj2Box = pBox->iBox;
+ p->pPis[pOuts[i]].iObj2Num = i;
+ }
+}
+
+/**Function*************************************************************
+
+ Synopsis [Creates the new timing box.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Tim_ManCreateBoxFirst( Tim_Man_t * p, int firstIn, int nIns, int firstOut, int nOuts, float * pDelayTable )
+{
+ Tim_Box_t * pBox;
+ int i;
+ pBox = (Tim_Box_t *)Mem_FlexEntryFetch( p->pMemObj, sizeof(Tim_Box_t) + sizeof(int) * (nIns+nOuts) );
+ memset( pBox, 0, sizeof(Tim_Box_t) );
+ pBox->iBox = Vec_PtrSize( p->vBoxes );
+ Vec_PtrPush( p->vBoxes, pBox );
+ pBox->pDelayTable = pDelayTable;
+ pBox->nInputs = nIns;
+ pBox->nOutputs = nOuts;
+ for ( i = 0; i < nIns; i++ )
+ {
+ assert( firstIn+i < p->nPos );
+ pBox->Inouts[i] = firstIn+i;
+ p->pPos[firstIn+i].iObj2Box = pBox->iBox;
+ p->pPos[firstIn+i].iObj2Num = i;
+ }
+ for ( i = 0; i < nOuts; i++ )
+ {
+ assert( firstOut+i < p->nPis );
+ pBox->Inouts[nIns+i] = firstOut+i;
+ p->pPis[firstOut+i].iObj2Box = pBox->iBox;
+ p->pPis[firstOut+i].iObj2Num = i;
+ }
+}
+
+
+
+/**Function*************************************************************
+
+ Synopsis [Increments the trav ID of the manager.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Tim_ManIncrementTravId( Tim_Man_t * p )
+{
+ p->nTravIds++;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Initializes arrival time of the PI.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Tim_ManInitPiArrival( Tim_Man_t * p, int iPi, float Delay )
+{
+ assert( iPi < p->nPis );
+ p->pPis[iPi].timeArr = Delay;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Initializes required time of the PO.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Tim_ManInitPoRequired( Tim_Man_t * p, int iPo, float Delay )
+{
+ assert( iPo < p->nPos );
+ p->pPos[iPo].timeReq = Delay;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Updates required time of the PO.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Tim_ManSetPoArrival( Tim_Man_t * p, int iPo, float Delay )
+{
+ assert( iPo < p->nPos );
+ assert( p->pPos[iPo].TravId != p->nTravIds );
+ p->pPos[iPo].timeArr = Delay;
+ p->pPos[iPo].TravId = p->nTravIds;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Updates arrival time of the PI.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Tim_ManSetPiRequired( Tim_Man_t * p, int iPi, float Delay )
+{
+ assert( iPi < p->nPis );
+ assert( p->pPis[iPi].TravId != p->nTravIds );
+ p->pPis[iPi].timeReq = Delay;
+ p->pPis[iPi].TravId = p->nTravIds;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Updates required time of the PO.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Tim_ManSetPoRequired( Tim_Man_t * p, int iPo, float Delay )
+{
+ assert( iPo < p->nPos );
+ assert( p->pPos[iPo].TravId != p->nTravIds );
+ p->pPos[iPo].timeReq = Delay;
+ p->pPos[iPo].TravId = p->nTravIds;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Sets the correct required times for all POs.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Tim_ManSetPoRequiredAll( Tim_Man_t * p, float Delay )
+{
+ Tim_Obj_t * pObj;
+ int i;
+ Tim_ManForEachPo( p, pObj, i )
+ Tim_ManSetPoRequired( p, i, Delay );
+}
+
+
+/**Function*************************************************************
+
+ Synopsis [Returns PI arrival time.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+float Tim_ManGetPiArrival( Tim_Man_t * p, int iPi )
+{
+ Tim_Box_t * pBox;
+ Tim_Obj_t * pObjThis, * pObj, * pObjRes;
+ float * pDelays, DelayBest;
+ int i, k;
+ // consider the already processed PI
+ pObjThis = Tim_ManPi( p, iPi );
+ if ( pObjThis->TravId == p->nTravIds )
+ return pObjThis->timeArr;
+ pObjThis->TravId = p->nTravIds;
+ // consider the main PI
+ pBox = Tim_ManPiBox( p, iPi );
+ if ( pBox == NULL )
+ return pObjThis->timeArr;
+ // update box timing
+ pBox->TravId = p->nTravIds;
+ // get the arrival times of the inputs of the box (POs)
+ Tim_ManBoxForEachInput( p, pBox, pObj, i )
+ if ( pObj->TravId != p->nTravIds )
+ printf( "Tim_ManGetPiArrival(): PO arrival times of the box are not up to date!\n" );
+ // compute the arrival times for each output of the box (PIs)
+ Tim_ManBoxForEachOutput( p, pBox, pObjRes, i )
+ {
+ pDelays = pBox->pDelayTable + i * pBox->nInputs;
+ DelayBest = -AIG_INFINITY;
+ Tim_ManBoxForEachInput( p, pBox, pObj, k )
+ DelayBest = AIG_MAX( DelayBest, pObj->timeArr + pDelays[k] );
+ pObjRes->timeArr = DelayBest;
+ pObjRes->TravId = p->nTravIds;
+ }
+ return pObjThis->timeArr;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Returns PO required time.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+float Tim_ManGetPoRequired( Tim_Man_t * p, int iPo )
+{
+ Tim_Box_t * pBox;
+ Tim_Obj_t * pObjThis, * pObj, * pObjRes;
+ float * pDelays, DelayBest;
+ int i, k;
+ // consider the already processed PO
+ pObjThis = Tim_ManPo( p, iPo );
+ if ( pObjThis->TravId == p->nTravIds )
+ return pObjThis->timeReq;
+ pObjThis->TravId = p->nTravIds;
+ // consider the main PO
+ pBox = Tim_ManPoBox( p, iPo );
+ if ( pBox == NULL )
+ return pObjThis->timeReq;
+ // update box timing
+ pBox->TravId = p->nTravIds;
+ // get the required times of the inputs of the box (POs)
+ Tim_ManBoxForEachOutput( p, pBox, pObj, i )
+ if ( pObj->TravId != p->nTravIds )
+ printf( "Tim_ManGetPoRequired(): PI required times of the box are not up to date!\n" );
+ // compute the required times for each output of the box (PIs)
+ Tim_ManBoxForEachInput( p, pBox, pObjRes, i )
+ {
+ DelayBest = AIG_INFINITY;
+ Tim_ManBoxForEachOutput( p, pBox, pObj, k )
+ {
+ pDelays = pBox->pDelayTable + k * pBox->nInputs;
+ DelayBest = AIG_MIN( DelayBest, pObj->timeReq - pDelays[i] );
+ }
+ pObjRes->timeReq = DelayBest;
+ pObjRes->TravId = p->nTravIds;
+ }
+ return pObjThis->timeReq;
+}
+
+
+////////////////////////////////////////////////////////////////////////
+/// END OF FILE ///
+////////////////////////////////////////////////////////////////////////
+
+
diff --git a/src/aig/tim/tim.h b/src/aig/tim/tim.h
new file mode 100644
index 00000000..d7544169
--- /dev/null
+++ b/src/aig/tim/tim.h
@@ -0,0 +1,85 @@
+/**CFile****************************************************************
+
+ FileName [tim.h]
+
+ SystemName [ABC: Logic synthesis and verification system.]
+
+ PackageName [A timing manager.]
+
+ Synopsis [External declarations.]
+
+ Author [Alan Mishchenko]
+
+ Affiliation [UC Berkeley]
+
+ Date [Ver. 1.0. Started - April 28, 2007.]
+
+ Revision [$Id: tim.h,v 1.00 2007/04/28 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#ifndef __TIM_H__
+#define __TIM_H__
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+////////////////////////////////////////////////////////////////////////
+/// INCLUDES ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+/// PARAMETERS ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+/// BASIC TYPES ///
+////////////////////////////////////////////////////////////////////////
+
+typedef struct Tim_Man_t_ Tim_Man_t;
+
+////////////////////////////////////////////////////////////////////////
+/// MACRO DEFINITIONS ///
+////////////////////////////////////////////////////////////////////////
+
+
+////////////////////////////////////////////////////////////////////////
+/// ITERATORS ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+/// SEQUENTIAL ITERATORS ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+/// FUNCTION DECLARATIONS ///
+////////////////////////////////////////////////////////////////////////
+
+/*=== time.c ===========================================================*/
+extern Tim_Man_t * Tim_ManStart( int nPis, int nPos );
+extern void Tim_ManStop( Tim_Man_t * p );
+extern void Tim_ManPrint( Tim_Man_t * p );
+extern void Tim_ManSetDelayTables( Tim_Man_t * p, Vec_Ptr_t * vDelayTables );
+extern void Tim_ManCreateBox( Tim_Man_t * p, int * pIns, int nIns, int * pOuts, int nOuts, float * pDelayTable );
+extern void Tim_ManCreateBoxFirst( Tim_Man_t * p, int firstIn, int nIns, int firstOut, int nOuts, float * pDelayTable );
+extern void Tim_ManIncrementTravId( Tim_Man_t * p );
+extern void Tim_ManInitPiArrival( Tim_Man_t * p, int iPi, float Delay );
+extern void Tim_ManInitPoRequired( Tim_Man_t * p, int iPo, float Delay );
+extern void Tim_ManSetPoArrival( Tim_Man_t * p, int iPo, float Delay );
+extern void Tim_ManSetPiRequired( Tim_Man_t * p, int iPi, float Delay );
+extern void Tim_ManSetPoRequired( Tim_Man_t * p, int iPo, float Delay );
+extern void Tim_ManSetPoRequiredAll( Tim_Man_t * p, float Delay );
+extern float Tim_ManGetPiArrival( Tim_Man_t * p, int iPi );
+extern float Tim_ManGetPoRequired( Tim_Man_t * p, int iPo );
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
+
+////////////////////////////////////////////////////////////////////////
+/// END OF FILE ///
+////////////////////////////////////////////////////////////////////////
+
diff --git a/src/base/abc/1.txt b/src/base/abc/1.txt
new file mode 100644
index 00000000..c0765c2b
--- /dev/null
+++ b/src/base/abc/1.txt
@@ -0,0 +1,21 @@
+Comparing files abcDfs.c and C:\_PROJECTS\AARON\FRETIME\SRC\BASE\ABC\ABCDFS.C
+***** abcDfs.c
+ return pNode->Level;
+ assert( Abc_ObjIsNode( pNode ) );
+ // if this node is already visited, return
+***** C:\_PROJECTS\AARON\FRETIME\SRC\BASE\ABC\ABCDFS.C
+ return pNode->Level;
+ assert( Abc_ObjIsNode( pNode ) || pNode->Type == ABC_OBJ_CONST1);
+ // if this node is already visited, return
+*****
+
+***** abcDfs.c
+ return pNode->Level;
+ assert( Abc_ObjIsNode( pNode ) );
+ // if this node is already visited, return
+***** C:\_PROJECTS\AARON\FRETIME\SRC\BASE\ABC\ABCDFS.C
+ return pNode->Level;
+ assert( Abc_ObjIsNode( pNode ) || pNode->Type == ABC_OBJ_CONST1);
+ // if this node is already visited, return
+*****
+
diff --git a/src/base/abc/abc.h b/src/base/abc/abc.h
index aea5a62d..11161698 100644
--- a/src/base/abc/abc.h
+++ b/src/base/abc/abc.h
@@ -21,6 +21,10 @@
#ifndef __ABC_H__
#define __ABC_H__
+#ifdef __cplusplus
+extern "C" {
+#endif
+
////////////////////////////////////////////////////////////////////////
/// INCLUDES ///
////////////////////////////////////////////////////////////////////////
@@ -32,10 +36,11 @@
#include <time.h>
#include "cuddInt.h"
+#include "hop.h"
#include "extra.h"
-#include "solver.h"
#include "vec.h"
#include "stmm.h"
+#include "nm.h"
////////////////////////////////////////////////////////////////////////
/// PARAMETERS ///
@@ -43,181 +48,235 @@
// network types
typedef enum {
- ABC_TYPE_NONE, // 0: unknown
- ABC_TYPE_NETLIST, // 1: network with PIs/POs, latches, nodes, and nets
- ABC_TYPE_LOGIC, // 2: network with PIs/POs, latches, and nodes
- ABC_TYPE_STRASH, // 3: structurally hashed AIG (two input AND gates with c-attributes on edges)
- ABC_TYPE_SEQ, // 4: sequential AIG (two input AND gates with c- and latch-attributes on edges)
- ABC_TYPE_OTHER // 5: unused
+ ABC_NTK_NONE = 0, // 0: unknown
+ ABC_NTK_NETLIST, // 1: network with PIs/POs, latches, nodes, and nets
+ ABC_NTK_LOGIC, // 2: network with PIs/POs, latches, and nodes
+ ABC_NTK_STRASH, // 3: structurally hashed AIG (two input AND gates with c-attributes on edges)
+ ABC_NTK_OTHER // 4: unused
} Abc_NtkType_t;
// network functionality
typedef enum {
- ABC_FUNC_NONE, // 0: unknown
+ ABC_FUNC_NONE = 0, // 0: unknown
ABC_FUNC_SOP, // 1: sum-of-products
ABC_FUNC_BDD, // 2: binary decision diagrams
ABC_FUNC_AIG, // 3: and-inverter graphs
ABC_FUNC_MAP, // 4: standard cell library
- ABC_FUNC_OTHER // 5: unused
+ ABC_FUNC_BLIFMV, // 5: BLIF-MV node functions
+ ABC_FUNC_BLACKBOX, // 6: black box about which nothing is known
+ ABC_FUNC_OTHER // 7: unused
} Abc_NtkFunc_t;
// Supported type/functionality combinations:
/*------------------------------------------|
| | SOP | BDD | AIG | Map |
|-----------|-------|-------|-------|-------|
-| Netlist | x | | | x |
+| Netlist | x | | x | x |
|-----------|-------|-------|-------|-------|
-| Logic | x | x | | x |
+| Logic | x | x | x | x |
|-----------|-------|-------|-------|-------|
| Strash | | | x | |
-|-----------|-------|-------|-------|-------|
-| Seq | | | x | |
--------------------------------------------|*/
// object types
typedef enum {
- ABC_OBJ_NONE, // 0: unknown
- ABC_OBJ_NET, // 1: net
- ABC_OBJ_NODE, // 2: node
- ABC_OBJ_LATCH, // 3: latch
- ABC_OBJ_PI, // 4: primary input terminal
- ABC_OBJ_PO, // 5: primary output terminal
- ABC_OBJ_OTHER // 6: unused
+ ABC_OBJ_NONE = 0, // 0: unknown
+ ABC_OBJ_CONST1, // 1: constant 1 node (AIG only)
+ ABC_OBJ_PIO, // 2: inout terminal
+ ABC_OBJ_PI, // 3: primary input terminal
+ ABC_OBJ_PO, // 4: primary output terminal
+ ABC_OBJ_BI, // 5: box input terminal
+ ABC_OBJ_BO, // 6: box output terminal
+ ABC_OBJ_ASSERT, // 7: assertion terminal
+ ABC_OBJ_NET, // 8: net
+ ABC_OBJ_NODE, // 9: node
+ ABC_OBJ_LATCH, // 10: latch
+ ABC_OBJ_WHITEBOX, // 11: box with known contents
+ ABC_OBJ_BLACKBOX, // 12: box with unknown contents
+ ABC_OBJ_NUMBER // 13: unused
} Abc_ObjType_t;
+// latch initial values
+typedef enum {
+ ABC_INIT_NONE = 0, // 0: unknown
+ ABC_INIT_ZERO, // 1: zero
+ ABC_INIT_ONE, // 2: one
+ ABC_INIT_DC, // 3: don't-care
+ ABC_INIT_OTHER // 4: unused
+} Abc_InitType_t;
+
////////////////////////////////////////////////////////////////////////
/// BASIC TYPES ///
////////////////////////////////////////////////////////////////////////
//typedef int bool;
+#ifndef __cplusplus
#ifndef bool
#define bool int
#endif
+#endif
-typedef struct Abc_Obj_t_ Abc_Obj_t;
-typedef struct Abc_Ntk_t_ Abc_Ntk_t;
-typedef struct Abc_Aig_t_ Abc_Aig_t;
-typedef struct Abc_ManTime_t_ Abc_ManTime_t;
-typedef struct Abc_ManCut_t_ Abc_ManCut_t;
-typedef struct Abc_Time_t_ Abc_Time_t;
+typedef struct Abc_Lib_t_ Abc_Lib_t;
+typedef struct Abc_Ntk_t_ Abc_Ntk_t;
+typedef struct Abc_Obj_t_ Abc_Obj_t;
+typedef struct Abc_Aig_t_ Abc_Aig_t;
+typedef struct Abc_ManTime_t_ Abc_ManTime_t;
+typedef struct Abc_ManCut_t_ Abc_ManCut_t;
+typedef struct Abc_Time_t_ Abc_Time_t;
struct Abc_Time_t_
{
- float Rise;
- float Fall;
- float Worst;
+ float Rise;
+ float Fall;
+ float Worst;
};
struct Abc_Obj_t_ // 12 words
{
// high-level information
- Abc_Ntk_t * pNtk; // the host network
- unsigned Type : 4; // the object type
- unsigned fExor : 1; // marks AIG node that is a root of EXOR
- unsigned Id : 27; // the ID of the object
+ Abc_Ntk_t * pNtk; // the host network
+ int Id; // the object ID
+ int TravId; // the traversal ID (if changed, update Abc_NtkIncrementTravId)
// internal information
- unsigned fMarkA : 1; // the multipurpose mark
- unsigned fMarkB : 1; // the multipurpose mark
- unsigned fMarkC : 1; // the multipurpose mark
- unsigned fPhase : 1; // the flag to mark the phase of equivalent node
- unsigned TravId : 12; // the traversal ID
- unsigned Level : 16; // the level of the node
+ unsigned Type : 4; // the object type
+ unsigned fMarkA : 1; // the multipurpose mark
+ unsigned fMarkB : 1; // the multipurpose mark
+ unsigned fMarkC : 1; // the multipurpose mark
+ unsigned fPhase : 1; // the flag to mark the phase of equivalent node
+ unsigned fExor : 1; // marks AIG node that is a root of EXOR
+ unsigned fPersist: 1; // marks the persistant AIG node
+ unsigned fCompl0 : 1; // complemented attribute of the first fanin in the AIG
+ unsigned fCompl1 : 1; // complemented attribute of the second fanin in the AIG
+ unsigned Level : 20; // the level of the node
// connectivity
- Vec_Fan_t vFanins; // the array of fanins
- Vec_Fan_t vFanouts; // the array of fanouts
+ Vec_Int_t vFanins; // the array of fanins
+ Vec_Int_t vFanouts; // the array of fanouts
// miscellaneous
- void * pData; // the network specific data (SOP, BDD, gate, equiv class, etc)
- Abc_Obj_t * pNext; // the next pointer in the hash table
- Abc_Obj_t * pCopy; // the copy of this object
+ void * pData; // the network specific data (SOP, BDD, gate, equiv class, etc)
+ Abc_Obj_t * pNext; // the next pointer in the hash table
+ Abc_Obj_t * pCopy; // the copy of this object
+ Hop_Obj_t * pEquiv; // pointer to the HAIG node
};
struct Abc_Ntk_t_
{
// general information
- Abc_NtkType_t ntkType; // type of the network
- Abc_NtkFunc_t ntkFunc; // functionality of the network
- char * pName; // the network name
- char * pSpec; // the name of the spec file if present
- // name representation
- stmm_table * tName2Net; // the table hashing net names into net pointer
- stmm_table * tObj2Name; // the table hashing PI/PO/latch pointers into names
+ Abc_NtkType_t ntkType; // type of the network
+ Abc_NtkFunc_t ntkFunc; // functionality of the network
+ char * pName; // the network name
+ char * pSpec; // the name of the spec file if present
+ Nm_Man_t * pManName; // name manager (stores names of objects)
// components of the network
- Vec_Ptr_t * vObjs; // the array of all objects (net, nodes, latches)
- Vec_Ptr_t * vCis; // the array of combinational inputs (PIs followed by latches)
- Vec_Ptr_t * vCos; // the array of combinational outputs (POs followed by latches)
- Vec_Ptr_t * vLats; // the array of latches (or the cutset in the sequential network)
- // the stats about the number of living objects
- int nObjs; // the number of living objs
- int nNets; // the number of living nets
- int nNodes; // the number of living nodes
- int nLatches; // the number of latches
- int nPis; // the number of primary inputs
- int nPos; // the number of primary outputs
- // the functionality manager
- void * pManFunc; // AIG manager, BDD manager, or memory manager for SOPs
- // the global functions (BDDs)
- void * pManGlob; // the BDD manager
- Vec_Ptr_t * vFuncsGlob; // the BDDs of CO functions
- // the timing manager (for mapped networks)
- Abc_ManTime_t * pManTime; // stores arrival/required times for all nodes
- // the cut manager (for AIGs)
- void * pManCut; // stores information about the cuts computed for the nodes
- // level information (for AIGs)
- int LevelMax; // maximum number of levels
- Vec_Int_t * vLevelsR; // level in the reverse topological order
- // support information
- Vec_Ptr_t * vSupps;
- // the external don't-care if given
- Abc_Ntk_t * pExdc; // the EXDC network
- // miscellaneous data members
- unsigned nTravIds; // the unique traversal IDs of nodes
- Vec_Ptr_t * vPtrTemp; // the temporary array
- Vec_Int_t * vIntTemp; // the temporary array
- Vec_Str_t * vStrTemp; // the temporary array
- void * pData; // the temporary pointer
+ Vec_Ptr_t * vObjs; // the array of all objects (net, nodes, latches, etc)
+ Vec_Ptr_t * vPis; // the array of primary inputs
+ Vec_Ptr_t * vPos; // the array of primary outputs
+ Vec_Ptr_t * vCis; // the array of combinational inputs (PIs, latches)
+ Vec_Ptr_t * vCos; // the array of combinational outputs (POs, asserts, latches)
+ Vec_Ptr_t * vPios; // the array of PIOs
+ Vec_Ptr_t * vAsserts; // the array of assertions
+ Vec_Ptr_t * vBoxes; // the array of boxes
+ // the number of living objects
+ int nObjs; // the number of live objs
+ int nObjCounts[ABC_OBJ_NUMBER]; // the number of objects by type
// the backup network and the step number
- Abc_Ntk_t * pNetBackup; // the pointer to the previous backup network
- int iStep; // the generation number for the given network
- // memory management
- Extra_MmFlex_t * pMmNames; // memory manager for net names
- Extra_MmFixed_t* pMmObj; // memory manager for objects
- Extra_MmStep_t * pMmStep; // memory manager for arrays
+ Abc_Ntk_t * pNetBackup; // the pointer to the previous backup network
+ int iStep; // the generation number for the given network
+ // hierarchy
+ Abc_Lib_t * pDesign;
+ short fHieVisited; // flag to mark the visited network
+ short fHiePath; // flag to mark the network on the path
+ // miscellaneous data members
+ int nTravIds; // the unique traversal IDs of nodes
+ Extra_MmFixed_t * pMmObj; // memory manager for objects
+ Extra_MmStep_t * pMmStep; // memory manager for arrays
+ void * pManFunc; // functionality manager (AIG manager, BDD manager, or memory manager for SOPs)
+// Abc_Lib_t * pVerLib; // for structural verilog designs
+ Abc_ManTime_t * pManTime; // the timing manager (for mapped networks) stores arrival/required times for all nodes
+ void * pManCut; // the cut manager (for AIGs) stores information about the cuts computed for the nodes
+ int LevelMax; // maximum number of levels
+ Vec_Int_t * vLevelsR; // level in the reverse topological order (for AIGs)
+ Vec_Ptr_t * vSupps; // CO support information
+ int * pModel; // counter-example (for miters)
+ void * pSeqModel; // counter-example (for sequential miters)
+ Abc_Ntk_t * pExdc; // the EXDC network (if given)
+ void * pData; // misc
+ Abc_Ntk_t * pCopy;
+ Hop_Man_t * pHaig; // history AIG
+ // node attributes
+ Vec_Ptr_t * vAttrs; // managers of various node attributes (node functionality, global BDDs, etc)
+};
+
+struct Abc_Lib_t_
+{
+ char * pName; // the name of the library
+ void * pManFunc; // functionality manager for the nodes
+ Vec_Ptr_t * vTops; // the array of top-level modules
+ Vec_Ptr_t * vModules; // the array of modules
+ st_table * tModules; // the table hashing module names into their networks
+ Abc_Lib_t * pLibrary; // the library used to map this design
+ void * pGenlib; // the genlib library used to map this design
};
////////////////////////////////////////////////////////////////////////
-/// MACRO DEFITIONS ///
+/// MACRO DEFINITIONS ///
////////////////////////////////////////////////////////////////////////
// maximum/minimum operators
#define ABC_MIN(a,b) (((a) < (b))? (a) : (b))
#define ABC_MAX(a,b) (((a) > (b))? (a) : (b))
-#define ABC_INFINITY (10000000)
+#define ABC_ABS(a) (((a) >= 0)? (a) :-(a))
+#define ABC_INFINITY (100000000)
+
+// transforming floats into ints and back
+static inline int Abc_Float2Int( float Val ) { return *((int *)&Val); }
+static inline float Abc_Int2Float( int Num ) { return *((float *)&Num); }
+static inline int Abc_BitWordNum( int nBits ) { return (nBits>>5) + ((nBits&31) > 0); }
+static inline int Abc_TruthWordNum( int nVars ) { return nVars <= 5 ? 1 : (1 << (nVars - 5)); }
+static inline int Abc_InfoHasBit( unsigned * p, int i ) { return (p[(i)>>5] & (1<<((i) & 31))) > 0; }
+static inline void Abc_InfoSetBit( unsigned * p, int i ) { p[(i)>>5] |= (1<<((i) & 31)); }
+static inline void Abc_InfoXorBit( unsigned * p, int i ) { p[(i)>>5] ^= (1<<((i) & 31)); }
+static inline unsigned Abc_InfoRandomWord() { return ((((unsigned)rand()) << 24) ^ (((unsigned)rand()) << 12) ^ ((unsigned)rand())); } // #define RAND_MAX 0x7fff
+static inline void Abc_InfoRandom( unsigned * p, int nWords ) { int i; for ( i = nWords - 1; i >= 0; i-- ) p[i] = Abc_InfoRandomWord(); }
+static inline void Abc_InfoClear( unsigned * p, int nWords ) { memset( p, 0, sizeof(unsigned) * nWords ); }
+static inline void Abc_InfoFill( unsigned * p, int nWords ) { memset( p, 0xff, sizeof(unsigned) * nWords );}
+static inline void Abc_InfoNot( unsigned * p, int nWords ) { int i; for ( i = nWords - 1; i >= 0; i-- ) p[i] = ~p[i]; }
+static inline int Abc_InfoIsZero( unsigned * p, int nWords ) { int i; for ( i = nWords - 1; i >= 0; i-- ) if ( p[i] ) return 0; return 1; }
+static inline int Abc_InfoIsOne( unsigned * p, int nWords ) { int i; for ( i = nWords - 1; i >= 0; i-- ) if ( ~p[i] ) return 0; return 1; }
+static inline void Abc_InfoCopy( unsigned * p, unsigned * q, int nWords ) { int i; for ( i = nWords - 1; i >= 0; i-- ) p[i] = q[i]; }
+static inline void Abc_InfoAnd( unsigned * p, unsigned * q, int nWords ) { int i; for ( i = nWords - 1; i >= 0; i-- ) p[i] &= q[i]; }
+static inline void Abc_InfoOr( unsigned * p, unsigned * q, int nWords ) { int i; for ( i = nWords - 1; i >= 0; i-- ) p[i] |= q[i]; }
+static inline void Abc_InfoXor( unsigned * p, unsigned * q, int nWords ) { int i; for ( i = nWords - 1; i >= 0; i-- ) p[i] ^= q[i]; }
+static inline int Abc_InfoIsOrOne( unsigned * p, unsigned * q, int nWords ){ int i; for ( i = nWords - 1; i >= 0; i-- ) if ( ~(p[i] | q[i]) ) return 0; return 1; }
+static inline int Abc_InfoIsOrOne3( unsigned * p, unsigned * q, unsigned * r, int nWords ){ int i; for ( i = nWords - 1; i >= 0; i-- ) if ( ~(p[i] | q[i] | r[i]) ) return 0; return 1; }
// checking the network type
-static inline bool Abc_NtkIsNetlist( Abc_Ntk_t * pNtk ) { return pNtk->ntkType == ABC_TYPE_NETLIST; }
-static inline bool Abc_NtkIsLogic( Abc_Ntk_t * pNtk ) { return pNtk->ntkType == ABC_TYPE_LOGIC; }
-static inline bool Abc_NtkIsStrash( Abc_Ntk_t * pNtk ) { return pNtk->ntkType == ABC_TYPE_STRASH; }
-static inline bool Abc_NtkIsSeq( Abc_Ntk_t * pNtk ) { return pNtk->ntkType == ABC_TYPE_SEQ; }
-
-static inline bool Abc_NtkHasSop( Abc_Ntk_t * pNtk ) { return pNtk->ntkFunc == ABC_FUNC_SOP; }
-static inline bool Abc_NtkHasBdd( Abc_Ntk_t * pNtk ) { return pNtk->ntkFunc == ABC_FUNC_BDD; }
-static inline bool Abc_NtkHasAig( Abc_Ntk_t * pNtk ) { return pNtk->ntkFunc == ABC_FUNC_AIG; }
-static inline bool Abc_NtkHasMapping( Abc_Ntk_t * pNtk ) { return pNtk->ntkFunc == ABC_FUNC_MAP; }
-
-static inline bool Abc_NtkIsSopNetlist( Abc_Ntk_t * pNtk ) { return pNtk->ntkFunc == ABC_FUNC_SOP && pNtk->ntkType == ABC_TYPE_NETLIST; }
-static inline bool Abc_NtkIsMappedNetlist( Abc_Ntk_t * pNtk ) { return pNtk->ntkFunc == ABC_FUNC_MAP && pNtk->ntkType == ABC_TYPE_NETLIST; }
-static inline bool Abc_NtkIsSopLogic( Abc_Ntk_t * pNtk ) { return pNtk->ntkFunc == ABC_FUNC_SOP && pNtk->ntkType == ABC_TYPE_LOGIC ; }
-static inline bool Abc_NtkIsBddLogic( Abc_Ntk_t * pNtk ) { return pNtk->ntkFunc == ABC_FUNC_BDD && pNtk->ntkType == ABC_TYPE_LOGIC ; }
-static inline bool Abc_NtkIsMappedLogic( Abc_Ntk_t * pNtk ) { return pNtk->ntkFunc == ABC_FUNC_MAP && pNtk->ntkType == ABC_TYPE_LOGIC ; }
-static inline bool Abc_NtkIsComb( Abc_Ntk_t * pNtk ) { return pNtk->nLatches == 0; }
+static inline bool Abc_NtkIsNetlist( Abc_Ntk_t * pNtk ) { return pNtk->ntkType == ABC_NTK_NETLIST; }
+static inline bool Abc_NtkIsLogic( Abc_Ntk_t * pNtk ) { return pNtk->ntkType == ABC_NTK_LOGIC; }
+static inline bool Abc_NtkIsStrash( Abc_Ntk_t * pNtk ) { return pNtk->ntkType == ABC_NTK_STRASH; }
+
+static inline bool Abc_NtkHasSop( Abc_Ntk_t * pNtk ) { return pNtk->ntkFunc == ABC_FUNC_SOP; }
+static inline bool Abc_NtkHasBdd( Abc_Ntk_t * pNtk ) { return pNtk->ntkFunc == ABC_FUNC_BDD; }
+static inline bool Abc_NtkHasAig( Abc_Ntk_t * pNtk ) { return pNtk->ntkFunc == ABC_FUNC_AIG; }
+static inline bool Abc_NtkHasMapping( Abc_Ntk_t * pNtk ) { return pNtk->ntkFunc == ABC_FUNC_MAP; }
+static inline bool Abc_NtkHasBlifMv( Abc_Ntk_t * pNtk ) { return pNtk->ntkFunc == ABC_FUNC_BLIFMV; }
+static inline bool Abc_NtkHasBlackbox( Abc_Ntk_t * pNtk ) { return pNtk->ntkFunc == ABC_FUNC_BLACKBOX; }
+
+static inline bool Abc_NtkIsSopNetlist( Abc_Ntk_t * pNtk ) { return pNtk->ntkFunc == ABC_FUNC_SOP && pNtk->ntkType == ABC_NTK_NETLIST; }
+static inline bool Abc_NtkIsAigNetlist( Abc_Ntk_t * pNtk ) { return pNtk->ntkFunc == ABC_FUNC_AIG && pNtk->ntkType == ABC_NTK_NETLIST; }
+static inline bool Abc_NtkIsMappedNetlist( Abc_Ntk_t * pNtk ) { return pNtk->ntkFunc == ABC_FUNC_MAP && pNtk->ntkType == ABC_NTK_NETLIST; }
+static inline bool Abc_NtkIsBlifMvNetlist( Abc_Ntk_t * pNtk ) { return pNtk->ntkFunc == ABC_FUNC_BLIFMV && pNtk->ntkType == ABC_NTK_NETLIST; }
+static inline bool Abc_NtkIsSopLogic( Abc_Ntk_t * pNtk ) { return pNtk->ntkFunc == ABC_FUNC_SOP && pNtk->ntkType == ABC_NTK_LOGIC ; }
+static inline bool Abc_NtkIsBddLogic( Abc_Ntk_t * pNtk ) { return pNtk->ntkFunc == ABC_FUNC_BDD && pNtk->ntkType == ABC_NTK_LOGIC ; }
+static inline bool Abc_NtkIsAigLogic( Abc_Ntk_t * pNtk ) { return pNtk->ntkFunc == ABC_FUNC_AIG && pNtk->ntkType == ABC_NTK_LOGIC ; }
+static inline bool Abc_NtkIsMappedLogic( Abc_Ntk_t * pNtk ) { return pNtk->ntkFunc == ABC_FUNC_MAP && pNtk->ntkType == ABC_NTK_LOGIC ; }
// reading data members of the network
-static inline char * Abc_NtkName( Abc_Ntk_t * pNtk ) { return pNtk->pName; }
-static inline char * Abc_NtkSpec( Abc_Ntk_t * pNtk ) { return pNtk->pSpec; }
-static inline int Abc_NtkTravId( Abc_Ntk_t * pNtk ) { return pNtk->nTravIds; }
-static inline Abc_Ntk_t * Abc_NtkExdc( Abc_Ntk_t * pNtk ) { return pNtk->pExdc; }
-static inline Abc_Ntk_t * Abc_NtkBackup( Abc_Ntk_t * pNtk ) { return pNtk->pNetBackup; }
-static inline int Abc_NtkStep ( Abc_Ntk_t * pNtk ) { return pNtk->iStep; }
+static inline char * Abc_NtkName( Abc_Ntk_t * pNtk ) { return pNtk->pName; }
+static inline char * Abc_NtkSpec( Abc_Ntk_t * pNtk ) { return pNtk->pSpec; }
+static inline int Abc_NtkTravId( Abc_Ntk_t * pNtk ) { return pNtk->nTravIds; }
+static inline Abc_Ntk_t * Abc_NtkExdc( Abc_Ntk_t * pNtk ) { return pNtk->pExdc; }
+static inline Abc_Ntk_t * Abc_NtkBackup( Abc_Ntk_t * pNtk ) { return pNtk->pNetBackup; }
+static inline int Abc_NtkStep ( Abc_Ntk_t * pNtk ) { return pNtk->iStep; }
// setting data members of the network
static inline void Abc_NtkSetName ( Abc_Ntk_t * pNtk, char * pName ) { pNtk->pName = pName; }
@@ -226,106 +285,127 @@ static inline void Abc_NtkSetBackup( Abc_Ntk_t * pNtk, Abc_Ntk_t * pNetBa
static inline void Abc_NtkSetStep ( Abc_Ntk_t * pNtk, int iStep ) { pNtk->iStep = iStep; }
// getting the number of objects
-static inline int Abc_NtkObjNumMax( Abc_Ntk_t * pNtk ) { return pNtk->vObjs->nSize; }
-static inline int Abc_NtkObjNum( Abc_Ntk_t * pNtk ) { return pNtk->nObjs; }
-static inline int Abc_NtkNetNum( Abc_Ntk_t * pNtk ) { return pNtk->nNets; }
-static inline int Abc_NtkNodeNum( Abc_Ntk_t * pNtk ) { return pNtk->nNodes; }
-static inline int Abc_NtkLatchNum( Abc_Ntk_t * pNtk ) { return pNtk->nLatches; }
-static inline int Abc_NtkPiNum( Abc_Ntk_t * pNtk ) { return pNtk->nPis; }
-static inline int Abc_NtkPoNum( Abc_Ntk_t * pNtk ) { return pNtk->nPos; }
-static inline int Abc_NtkCiNum( Abc_Ntk_t * pNtk ) { return pNtk->vCis->nSize; }
-static inline int Abc_NtkCoNum( Abc_Ntk_t * pNtk ) { return pNtk->vCos->nSize; }
+static inline int Abc_NtkObjNum( Abc_Ntk_t * pNtk ) { return pNtk->nObjs; }
+static inline int Abc_NtkObjNumMax( Abc_Ntk_t * pNtk ) { return Vec_PtrSize(pNtk->vObjs); }
+static inline int Abc_NtkPiNum( Abc_Ntk_t * pNtk ) { return Vec_PtrSize(pNtk->vPis); }
+static inline int Abc_NtkPoNum( Abc_Ntk_t * pNtk ) { return Vec_PtrSize(pNtk->vPos); }
+static inline int Abc_NtkCiNum( Abc_Ntk_t * pNtk ) { return Vec_PtrSize(pNtk->vCis); }
+static inline int Abc_NtkCoNum( Abc_Ntk_t * pNtk ) { return Vec_PtrSize(pNtk->vCos); }
+static inline int Abc_NtkAssertNum( Abc_Ntk_t * pNtk ) { return Vec_PtrSize(pNtk->vAsserts); }
+static inline int Abc_NtkBoxNum( Abc_Ntk_t * pNtk ) { return Vec_PtrSize(pNtk->vBoxes); }
+static inline int Abc_NtkBiNum( Abc_Ntk_t * pNtk ) { return pNtk->nObjCounts[ABC_OBJ_BI]; }
+static inline int Abc_NtkBoNum( Abc_Ntk_t * pNtk ) { return pNtk->nObjCounts[ABC_OBJ_BO]; }
+static inline int Abc_NtkNetNum( Abc_Ntk_t * pNtk ) { return pNtk->nObjCounts[ABC_OBJ_NET]; }
+static inline int Abc_NtkNodeNum( Abc_Ntk_t * pNtk ) { return pNtk->nObjCounts[ABC_OBJ_NODE]; }
+static inline int Abc_NtkLatchNum( Abc_Ntk_t * pNtk ) { return pNtk->nObjCounts[ABC_OBJ_LATCH]; }
+static inline int Abc_NtkWhiteboxNum( Abc_Ntk_t * pNtk ) { return pNtk->nObjCounts[ABC_OBJ_WHITEBOX]; }
+static inline int Abc_NtkBlackboxNum( Abc_Ntk_t * pNtk ) { return pNtk->nObjCounts[ABC_OBJ_BLACKBOX]; }
+static inline bool Abc_NtkIsComb( Abc_Ntk_t * pNtk ) { return Abc_NtkLatchNum(pNtk) == 0; }
+static inline bool Abc_NtkHasOnlyLatchBoxes(Abc_Ntk_t * pNtk ){ return Abc_NtkLatchNum(pNtk) == Abc_NtkBoxNum(pNtk); }
+
+// creating simple objects
+extern Abc_Obj_t * Abc_NtkCreateObj( Abc_Ntk_t * pNtk, Abc_ObjType_t Type );
+static inline Abc_Obj_t * Abc_NtkCreatePi( Abc_Ntk_t * pNtk ) { return Abc_NtkCreateObj( pNtk, ABC_OBJ_PI ); }
+static inline Abc_Obj_t * Abc_NtkCreatePo( Abc_Ntk_t * pNtk ) { return Abc_NtkCreateObj( pNtk, ABC_OBJ_PO ); }
+static inline Abc_Obj_t * Abc_NtkCreateBi( Abc_Ntk_t * pNtk ) { return Abc_NtkCreateObj( pNtk, ABC_OBJ_BI ); }
+static inline Abc_Obj_t * Abc_NtkCreateBo( Abc_Ntk_t * pNtk ) { return Abc_NtkCreateObj( pNtk, ABC_OBJ_BO ); }
+static inline Abc_Obj_t * Abc_NtkCreateAssert( Abc_Ntk_t * pNtk ) { return Abc_NtkCreateObj( pNtk, ABC_OBJ_ASSERT ); }
+static inline Abc_Obj_t * Abc_NtkCreateNet( Abc_Ntk_t * pNtk ) { return Abc_NtkCreateObj( pNtk, ABC_OBJ_NET ); }
+static inline Abc_Obj_t * Abc_NtkCreateNode( Abc_Ntk_t * pNtk ) { return Abc_NtkCreateObj( pNtk, ABC_OBJ_NODE ); }
+static inline Abc_Obj_t * Abc_NtkCreateLatch( Abc_Ntk_t * pNtk ) { return Abc_NtkCreateObj( pNtk, ABC_OBJ_LATCH ); }
+static inline Abc_Obj_t * Abc_NtkCreateWhitebox( Abc_Ntk_t * pNtk ) { return Abc_NtkCreateObj( pNtk, ABC_OBJ_WHITEBOX ); }
+static inline Abc_Obj_t * Abc_NtkCreateBlackbox( Abc_Ntk_t * pNtk ) { return Abc_NtkCreateObj( pNtk, ABC_OBJ_BLACKBOX ); }
// reading objects
-static inline Abc_Obj_t * Abc_NtkObj( Abc_Ntk_t * pNtk, int i ) { assert( i < Vec_PtrSize(pNtk->vObjs) ); return pNtk->vObjs->pArray[i]; }
-static inline Abc_Obj_t * Abc_NtkLatch( Abc_Ntk_t * pNtk, int i ) { assert( i < Vec_PtrSize(pNtk->vLats) ); return pNtk->vLats->pArray[i]; }
-static inline Abc_Obj_t * Abc_NtkPi( Abc_Ntk_t * pNtk, int i ) { assert( i < Abc_NtkPiNum(pNtk) ); return pNtk->vCis->pArray[i]; }
-static inline Abc_Obj_t * Abc_NtkPo( Abc_Ntk_t * pNtk, int i ) { assert( i < Abc_NtkPoNum(pNtk) ); return pNtk->vCos->pArray[i]; }
-static inline Abc_Obj_t * Abc_NtkCi( Abc_Ntk_t * pNtk, int i ) { assert( i < Abc_NtkCiNum(pNtk) ); return pNtk->vCis->pArray[i]; }
-static inline Abc_Obj_t * Abc_NtkCo( Abc_Ntk_t * pNtk, int i ) { assert( i < Abc_NtkCoNum(pNtk) ); return pNtk->vCos->pArray[i]; }
+static inline Abc_Obj_t * Abc_NtkObj( Abc_Ntk_t * pNtk, int i ) { return (Abc_Obj_t *)Vec_PtrEntry( pNtk->vObjs, i ); }
+static inline Abc_Obj_t * Abc_NtkPi( Abc_Ntk_t * pNtk, int i ) { return (Abc_Obj_t *)Vec_PtrEntry( pNtk->vPis, i ); }
+static inline Abc_Obj_t * Abc_NtkPo( Abc_Ntk_t * pNtk, int i ) { return (Abc_Obj_t *)Vec_PtrEntry( pNtk->vPos, i ); }
+static inline Abc_Obj_t * Abc_NtkCi( Abc_Ntk_t * pNtk, int i ) { return (Abc_Obj_t *)Vec_PtrEntry( pNtk->vCis, i ); }
+static inline Abc_Obj_t * Abc_NtkCo( Abc_Ntk_t * pNtk, int i ) { return (Abc_Obj_t *)Vec_PtrEntry( pNtk->vCos, i ); }
+static inline Abc_Obj_t * Abc_NtkAssert( Abc_Ntk_t * pNtk, int i ) { return (Abc_Obj_t *)Vec_PtrEntry( pNtk->vAsserts, i );}
+static inline Abc_Obj_t * Abc_NtkBox( Abc_Ntk_t * pNtk, int i ) { return (Abc_Obj_t *)Vec_PtrEntry( pNtk->vBoxes, i ); }
+
+// working with complemented attributes of objects
+static inline bool Abc_ObjIsComplement( Abc_Obj_t * p ) { return (bool)((unsigned long)p & (unsigned long)01); }
+static inline Abc_Obj_t * Abc_ObjRegular( Abc_Obj_t * p ) { return (Abc_Obj_t *)((unsigned long)p & ~(unsigned long)01); }
+static inline Abc_Obj_t * Abc_ObjNot( Abc_Obj_t * p ) { return (Abc_Obj_t *)((unsigned long)p ^ (unsigned long)01); }
+static inline Abc_Obj_t * Abc_ObjNotCond( Abc_Obj_t * p, int c ) { return (Abc_Obj_t *)((unsigned long)p ^ (unsigned long)(c!=0)); }
// reading data members of the object
static inline unsigned Abc_ObjType( Abc_Obj_t * pObj ) { return pObj->Type; }
static inline unsigned Abc_ObjId( Abc_Obj_t * pObj ) { return pObj->Id; }
static inline int Abc_ObjTravId( Abc_Obj_t * pObj ) { return pObj->TravId; }
-static inline Vec_Fan_t * Abc_ObjFaninVec( Abc_Obj_t * pObj ) { return &pObj->vFanins; }
-static inline Vec_Fan_t * Abc_ObjFanoutVec( Abc_Obj_t * pObj ) { return &pObj->vFanouts; }
+static inline int Abc_ObjLevel( Abc_Obj_t * pObj ) { return pObj->Level; }
+static inline Vec_Int_t * Abc_ObjFaninVec( Abc_Obj_t * pObj ) { return &pObj->vFanins; }
+static inline Vec_Int_t * Abc_ObjFanoutVec( Abc_Obj_t * pObj ) { return &pObj->vFanouts; }
static inline Abc_Obj_t * Abc_ObjCopy( Abc_Obj_t * pObj ) { return pObj->pCopy; }
static inline Abc_Ntk_t * Abc_ObjNtk( Abc_Obj_t * pObj ) { return pObj->pNtk; }
static inline void * Abc_ObjData( Abc_Obj_t * pObj ) { return pObj->pData; }
+static inline Hop_Obj_t * Abc_ObjEquiv( Abc_Obj_t * pObj ) { return pObj->pEquiv; }
+static inline Abc_Obj_t * Abc_ObjCopyCond( Abc_Obj_t * pObj ) { return Abc_ObjRegular(pObj)->pCopy? Abc_ObjNotCond(Abc_ObjRegular(pObj)->pCopy, Abc_ObjIsComplement(pObj)) : NULL; }
// setting data members of the network
-static inline void Abc_ObjSetCopy( Abc_Obj_t * pObj, Abc_Obj_t * pCopy ) { pObj->pCopy = pCopy; }
-static inline void Abc_ObjSetData( Abc_Obj_t * pObj, void * pData ) { pObj->pData = pData; }
-
-// working with complemented attributes of objects
-static inline bool Abc_ObjIsComplement( Abc_Obj_t * p ) { return (bool)(((unsigned)p) & 01); }
-static inline Abc_Obj_t * Abc_ObjRegular( Abc_Obj_t * p ) { return (Abc_Obj_t *)((unsigned)(p) & ~01); }
-static inline Abc_Obj_t * Abc_ObjNot( Abc_Obj_t * p ) { return (Abc_Obj_t *)((unsigned)(p) ^ 01); }
-static inline Abc_Obj_t * Abc_ObjNotCond( Abc_Obj_t * p, int c ) { return (Abc_Obj_t *)((unsigned)(p) ^ (c)); }
+static inline void Abc_ObjSetLevel( Abc_Obj_t * pObj, int Level ) { pObj->Level = Level; }
+static inline void Abc_ObjSetCopy( Abc_Obj_t * pObj, Abc_Obj_t * pCopy ) { pObj->pCopy = pCopy; }
+static inline void Abc_ObjSetData( Abc_Obj_t * pObj, void * pData ) { pObj->pData = pData; }
// checking the object type
-static inline bool Abc_ObjIsNode( Abc_Obj_t * pObj ) { return pObj->Type == ABC_OBJ_NODE; }
-static inline bool Abc_ObjIsNet( Abc_Obj_t * pObj ) { return pObj->Type == ABC_OBJ_NET; }
-static inline bool Abc_ObjIsLatch( Abc_Obj_t * pObj ) { return pObj->Type == ABC_OBJ_LATCH; }
-static inline bool Abc_ObjIsPi( Abc_Obj_t * pObj ) { return pObj->Type == ABC_OBJ_PI; }
-static inline bool Abc_ObjIsPo( Abc_Obj_t * pObj ) { return pObj->Type == ABC_OBJ_PO; }
-static inline bool Abc_ObjIsPio( Abc_Obj_t * pObj ) { return pObj->Type == ABC_OBJ_PI || pObj->Type == ABC_OBJ_PO; }
-static inline bool Abc_ObjIsCi( Abc_Obj_t * pObj ) { return pObj->Type == ABC_OBJ_PI || pObj->Type == ABC_OBJ_LATCH; }
-static inline bool Abc_ObjIsCo( Abc_Obj_t * pObj ) { return pObj->Type == ABC_OBJ_PO || pObj->Type == ABC_OBJ_LATCH; }
-static inline bool Abc_ObjIsCio( Abc_Obj_t * pObj ) { return pObj->Type == ABC_OBJ_PI || pObj->Type == ABC_OBJ_PO || pObj->Type == ABC_OBJ_LATCH; }
+static inline bool Abc_ObjIsPio( Abc_Obj_t * pObj ) { return pObj->Type == ABC_OBJ_PIO; }
+static inline bool Abc_ObjIsPi( Abc_Obj_t * pObj ) { return pObj->Type == ABC_OBJ_PI; }
+static inline bool Abc_ObjIsPo( Abc_Obj_t * pObj ) { return pObj->Type == ABC_OBJ_PO; }
+static inline bool Abc_ObjIsBi( Abc_Obj_t * pObj ) { return pObj->Type == ABC_OBJ_BI; }
+static inline bool Abc_ObjIsBo( Abc_Obj_t * pObj ) { return pObj->Type == ABC_OBJ_BO; }
+static inline bool Abc_ObjIsAssert( Abc_Obj_t * pObj ) { return pObj->Type == ABC_OBJ_ASSERT; }
+static inline bool Abc_ObjIsCi( Abc_Obj_t * pObj ) { return pObj->Type == ABC_OBJ_PI || pObj->Type == ABC_OBJ_BO; }
+static inline bool Abc_ObjIsCo( Abc_Obj_t * pObj ) { return pObj->Type == ABC_OBJ_PO || pObj->Type == ABC_OBJ_BI || pObj->Type == ABC_OBJ_ASSERT; }
+static inline bool Abc_ObjIsTerm( Abc_Obj_t * pObj ) { return Abc_ObjIsCi(pObj) || Abc_ObjIsCo(pObj); }
+static inline bool Abc_ObjIsNet( Abc_Obj_t * pObj ) { return pObj->Type == ABC_OBJ_NET; }
+static inline bool Abc_ObjIsNode( Abc_Obj_t * pObj ) { return pObj->Type == ABC_OBJ_NODE; }
+static inline bool Abc_ObjIsLatch( Abc_Obj_t * pObj ) { return pObj->Type == ABC_OBJ_LATCH; }
+static inline bool Abc_ObjIsBox( Abc_Obj_t * pObj ) { return pObj->Type == ABC_OBJ_LATCH || pObj->Type == ABC_OBJ_WHITEBOX || pObj->Type == ABC_OBJ_BLACKBOX; }
+static inline bool Abc_ObjIsWhitebox( Abc_Obj_t * pObj ) { return pObj->Type == ABC_OBJ_WHITEBOX;}
+static inline bool Abc_ObjIsBlackbox( Abc_Obj_t * pObj ) { return pObj->Type == ABC_OBJ_BLACKBOX;}
+static inline void Abc_ObjBlackboxToWhitebox( Abc_Obj_t * pObj ) { assert( Abc_ObjIsBlackbox(pObj) ); pObj->Type = ABC_OBJ_WHITEBOX; pObj->pNtk->nObjCounts[ABC_OBJ_BLACKBOX]--; pObj->pNtk->nObjCounts[ABC_OBJ_WHITEBOX]++; }
// working with fanin/fanout edges
-static inline int Abc_ObjFaninNum( Abc_Obj_t * pObj ) { return pObj->vFanins.nSize; }
-static inline int Abc_ObjFanoutNum( Abc_Obj_t * pObj ) { return pObj->vFanouts.nSize; }
-static inline int Abc_ObjFaninId( Abc_Obj_t * pObj, int i) { return pObj->vFanins.pArray[i].iFan; }
-static inline int Abc_ObjFaninId0( Abc_Obj_t * pObj ) { return pObj->vFanins.pArray[0].iFan; }
-static inline int Abc_ObjFaninId1( Abc_Obj_t * pObj ) { return pObj->vFanins.pArray[1].iFan; }
-static inline Abc_Obj_t * Abc_ObjFanout( Abc_Obj_t * pObj, int i ) { return pObj->pNtk->vObjs->pArray[ pObj->vFanouts.pArray[i].iFan ]; }
-static inline Abc_Obj_t * Abc_ObjFanout0( Abc_Obj_t * pObj ) { return pObj->pNtk->vObjs->pArray[ pObj->vFanouts.pArray[0].iFan ]; }
-static inline Abc_Obj_t * Abc_ObjFanin( Abc_Obj_t * pObj, int i ) { return pObj->pNtk->vObjs->pArray[ pObj->vFanins.pArray[i].iFan ]; }
-static inline Abc_Obj_t * Abc_ObjFanin0( Abc_Obj_t * pObj ) { return pObj->pNtk->vObjs->pArray[ pObj->vFanins.pArray[0].iFan ]; }
-static inline Abc_Obj_t * Abc_ObjFanin1( Abc_Obj_t * pObj ) { return pObj->pNtk->vObjs->pArray[ pObj->vFanins.pArray[1].iFan ]; }
-static inline Abc_Obj_t * Abc_ObjFanin0Ntk( Abc_Obj_t * pObj ) { return Abc_NtkIsNetlist(pObj->pNtk)? Abc_ObjFanin0(pObj) : pObj; }
-static inline Abc_Obj_t * Abc_ObjFanout0Ntk( Abc_Obj_t * pObj ) { return Abc_NtkIsNetlist(pObj->pNtk)? Abc_ObjFanout0(pObj) : pObj; }
-static inline bool Abc_ObjFaninC( Abc_Obj_t * pObj, int i ) { return pObj->vFanins.pArray[i].fCompl; }
-static inline bool Abc_ObjFaninC0( Abc_Obj_t * pObj ) { return pObj->vFanins.pArray[0].fCompl; }
-static inline bool Abc_ObjFaninC1( Abc_Obj_t * pObj ) { return pObj->vFanins.pArray[1].fCompl; }
-static inline bool Abc_ObjFanoutC( Abc_Obj_t * pObj, Abc_Obj_t * pFanout ) { assert( !Abc_NtkIsLogic(pObj->pNtk) ); return (Abc_ObjFaninId0(pFanout) == (int)pObj->Id)? Abc_ObjFaninC0(pFanout) : Abc_ObjFaninC1(pFanout); }
-static inline int Abc_ObjFaninL( Abc_Obj_t * pObj, int i ) { return pObj->vFanins.pArray[i].nLats; }
-static inline int Abc_ObjFaninL0( Abc_Obj_t * pObj ) { return pObj->vFanins.pArray[0].nLats; }
-static inline int Abc_ObjFaninL1( Abc_Obj_t * pObj ) { return pObj->vFanins.pArray[1].nLats; }
-static inline int Abc_ObjFaninLMin( Abc_Obj_t * pObj ) { assert( Abc_ObjIsNode(pObj) ); return ABC_MIN( Abc_ObjFaninL0(pObj), Abc_ObjFaninL1(pObj) ); }
-static inline int Abc_ObjFaninLMax( Abc_Obj_t * pObj ) { assert( Abc_ObjIsNode(pObj) ); return ABC_MAX( Abc_ObjFaninL0(pObj), Abc_ObjFaninL1(pObj) ); }
+static inline int Abc_ObjFaninNum( Abc_Obj_t * pObj ) { return pObj->vFanins.nSize; }
+static inline int Abc_ObjFanoutNum( Abc_Obj_t * pObj ) { return pObj->vFanouts.nSize; }
+static inline int Abc_ObjFaninId( Abc_Obj_t * pObj, int i) { return pObj->vFanins.pArray[i]; }
+static inline int Abc_ObjFaninId0( Abc_Obj_t * pObj ) { return pObj->vFanins.pArray[0]; }
+static inline int Abc_ObjFaninId1( Abc_Obj_t * pObj ) { return pObj->vFanins.pArray[1]; }
+static inline int Abc_ObjFanoutEdgeNum( Abc_Obj_t * pObj, Abc_Obj_t * pFanout ) { assert( Abc_NtkHasAig(pObj->pNtk) ); if ( Abc_ObjFaninId0(pFanout) == pObj->Id ) return 0; if ( Abc_ObjFaninId1(pFanout) == pObj->Id ) return 1; assert( 0 ); return -1; }
+static inline Abc_Obj_t * Abc_ObjFanout( Abc_Obj_t * pObj, int i ) { return (Abc_Obj_t *)pObj->pNtk->vObjs->pArray[ pObj->vFanouts.pArray[i] ]; }
+static inline Abc_Obj_t * Abc_ObjFanout0( Abc_Obj_t * pObj ) { return (Abc_Obj_t *)pObj->pNtk->vObjs->pArray[ pObj->vFanouts.pArray[0] ]; }
+static inline Abc_Obj_t * Abc_ObjFanin( Abc_Obj_t * pObj, int i ) { return (Abc_Obj_t *)pObj->pNtk->vObjs->pArray[ pObj->vFanins.pArray[i] ]; }
+static inline Abc_Obj_t * Abc_ObjFanin0( Abc_Obj_t * pObj ) { return (Abc_Obj_t *)pObj->pNtk->vObjs->pArray[ pObj->vFanins.pArray[0] ]; }
+static inline Abc_Obj_t * Abc_ObjFanin1( Abc_Obj_t * pObj ) { return (Abc_Obj_t *)pObj->pNtk->vObjs->pArray[ pObj->vFanins.pArray[1] ]; }
+static inline Abc_Obj_t * Abc_ObjFanin0Ntk( Abc_Obj_t * pObj ) { return (Abc_NtkIsNetlist(pObj->pNtk)? Abc_ObjFanin0(pObj) : pObj); }
+static inline Abc_Obj_t * Abc_ObjFanout0Ntk( Abc_Obj_t * pObj ) { return (Abc_NtkIsNetlist(pObj->pNtk)? Abc_ObjFanout0(pObj) : pObj); }
+static inline bool Abc_ObjFaninC0( Abc_Obj_t * pObj ) { return pObj->fCompl0; }
+static inline bool Abc_ObjFaninC1( Abc_Obj_t * pObj ) { return pObj->fCompl1; }
+static inline bool Abc_ObjFaninC( Abc_Obj_t * pObj, int i ) { assert( i >=0 && i < 2 ); return i? pObj->fCompl1 : pObj->fCompl0; }
+static inline void Abc_ObjSetFaninC( Abc_Obj_t * pObj, int i ){ assert( i >=0 && i < 2 ); if ( i ) pObj->fCompl1 = 1; else pObj->fCompl0 = 1; }
+static inline void Abc_ObjXorFaninC( Abc_Obj_t * pObj, int i ){ assert( i >=0 && i < 2 ); if ( i ) pObj->fCompl1^= 1; else pObj->fCompl0^= 1; }
static inline Abc_Obj_t * Abc_ObjChild( Abc_Obj_t * pObj, int i ) { return Abc_ObjNotCond( Abc_ObjFanin(pObj,i), Abc_ObjFaninC(pObj,i) );}
static inline Abc_Obj_t * Abc_ObjChild0( Abc_Obj_t * pObj ) { return Abc_ObjNotCond( Abc_ObjFanin0(pObj), Abc_ObjFaninC0(pObj) ); }
static inline Abc_Obj_t * Abc_ObjChild1( Abc_Obj_t * pObj ) { return Abc_ObjNotCond( Abc_ObjFanin1(pObj), Abc_ObjFaninC1(pObj) ); }
-static inline Abc_Obj_t * Abc_ObjChildCopy( Abc_Obj_t * pObj, int i ){ return Abc_ObjNotCond( Abc_ObjFanin(pObj,i)->pCopy, Abc_ObjFaninC(pObj,i) );}
-static inline Abc_Obj_t * Abc_ObjChild0Copy( Abc_Obj_t * pObj ) { return Abc_ObjNotCond( Abc_ObjFanin0(pObj)->pCopy, Abc_ObjFaninC0(pObj) ); }
-static inline Abc_Obj_t * Abc_ObjChild1Copy( Abc_Obj_t * pObj ) { return Abc_ObjNotCond( Abc_ObjFanin1(pObj)->pCopy, Abc_ObjFaninC1(pObj) ); }
-static inline Abc_Obj_t * Abc_ObjFanoutFanin( Abc_Obj_t * pObj, Abc_Obj_t * pFanout ) { assert( !Abc_NtkIsLogic(pObj->pNtk) ); return (Abc_ObjFaninId0(pFanout) == (int)pObj->Id)? Abc_ObjChild0(pFanout) : Abc_ObjChild1(pFanout); }
-static inline void Abc_ObjSetFaninC( Abc_Obj_t * pObj, int i ){ pObj->vFanins.pArray[i].fCompl = 1; }
-static inline void Abc_ObjXorFaninC( Abc_Obj_t * pObj, int i ){ pObj->vFanins.pArray[i].fCompl ^= 1; }
-static inline void Abc_ObjSetFaninL( Abc_Obj_t * pObj, int i, int nLats ) { pObj->vFanins.pArray[i].nLats = nLats; }
-static inline void Abc_ObjSetFaninL0( Abc_Obj_t * pObj, int nLats ) { pObj->vFanins.pArray[0].nLats = nLats; }
-static inline void Abc_ObjSetFaninL1( Abc_Obj_t * pObj, int nLats ) { pObj->vFanins.pArray[1].nLats = nLats; }
-static inline void Abc_ObjAddFaninL( Abc_Obj_t * pObj, int i, int nLats ) { pObj->vFanins.pArray[i].nLats += nLats; }
-static inline void Abc_ObjAddFaninL0( Abc_Obj_t * pObj, int nLats ) { pObj->vFanins.pArray[0].nLats += nLats; }
-static inline void Abc_ObjAddFaninL1( Abc_Obj_t * pObj, int nLats ) { pObj->vFanins.pArray[1].nLats += nLats; }
-extern int Abc_ObjFanoutL( Abc_Obj_t * pObj, Abc_Obj_t * pFanout );
-extern void Abc_ObjSetFanoutL( Abc_Obj_t * pObj, Abc_Obj_t * pFanout, int nLats );
-extern void Abc_ObjAddFanoutL( Abc_Obj_t * pObj, Abc_Obj_t * pFanout, int nLats );
-extern int Abc_ObjFanoutLMin( Abc_Obj_t * pObj );
-extern int Abc_ObjFanoutLMax( Abc_Obj_t * pObj );
-
-// checking the node type
-static inline bool Abc_NodeIsAigAnd( Abc_Obj_t * pNode ) { assert(Abc_NtkHasAig(pNode->pNtk)); return Abc_ObjFaninNum(pNode) == 2; }
-static inline bool Abc_NodeIsAigChoice( Abc_Obj_t * pNode ) { assert(Abc_NtkHasAig(pNode->pNtk)); return pNode->pData != NULL && Abc_ObjFanoutNum(pNode) > 0; }
-static inline bool Abc_NodeIsConst( Abc_Obj_t * pNode ) { assert(Abc_ObjIsNode(Abc_ObjRegular(pNode))); return Abc_ObjFaninNum(Abc_ObjRegular(pNode)) == 0; }
-extern bool Abc_NodeIsConst0( Abc_Obj_t * pNode );
-extern bool Abc_NodeIsConst1( Abc_Obj_t * pNode );
-extern bool Abc_NodeIsBuf( Abc_Obj_t * pNode );
-extern bool Abc_NodeIsInv( Abc_Obj_t * pNode );
+static inline Abc_Obj_t * Abc_ObjChildCopy( Abc_Obj_t * pObj, int i ){ return Abc_ObjNotCond( Abc_ObjFanin(pObj,i)->pCopy, Abc_ObjFaninC(pObj,i) ); }
+static inline Abc_Obj_t * Abc_ObjChild0Copy( Abc_Obj_t * pObj ) { return Abc_ObjNotCond( Abc_ObjFanin0(pObj)->pCopy, Abc_ObjFaninC0(pObj) ); }
+static inline Abc_Obj_t * Abc_ObjChild1Copy( Abc_Obj_t * pObj ) { return Abc_ObjNotCond( Abc_ObjFanin1(pObj)->pCopy, Abc_ObjFaninC1(pObj) ); }
+static inline Abc_Obj_t * Abc_ObjChild0Data( Abc_Obj_t * pObj ) { return Abc_ObjNotCond( (Abc_Obj_t *)Abc_ObjFanin0(pObj)->pData, Abc_ObjFaninC0(pObj) ); }
+static inline Abc_Obj_t * Abc_ObjChild1Data( Abc_Obj_t * pObj ) { return Abc_ObjNotCond( (Abc_Obj_t *)Abc_ObjFanin1(pObj)->pData, Abc_ObjFaninC1(pObj) ); }
+static inline Hop_Obj_t * Abc_ObjChild0Equiv( Abc_Obj_t * pObj ) { return Hop_NotCond( Abc_ObjFanin0(pObj)->pEquiv, Abc_ObjFaninC0(pObj) ); }
+static inline Hop_Obj_t * Abc_ObjChild1Equiv( Abc_Obj_t * pObj ) { return Hop_NotCond( Abc_ObjFanin1(pObj)->pEquiv, Abc_ObjFaninC1(pObj) ); }
+
+// checking the AIG node types
+static inline bool Abc_AigNodeIsConst( Abc_Obj_t * pNode ) { assert(Abc_NtkIsStrash(Abc_ObjRegular(pNode)->pNtk)); return Abc_ObjRegular(pNode)->Type == ABC_OBJ_CONST1; }
+static inline bool Abc_AigNodeIsAnd( Abc_Obj_t * pNode ) { assert(!Abc_ObjIsComplement(pNode)); assert(Abc_NtkIsStrash(pNode->pNtk)); return Abc_ObjFaninNum(pNode) == 2; }
+static inline bool Abc_AigNodeIsChoice( Abc_Obj_t * pNode ) { assert(!Abc_ObjIsComplement(pNode)); assert(Abc_NtkIsStrash(pNode->pNtk)); return pNode->pData != NULL && Abc_ObjFanoutNum(pNode) > 0; }
+
+// handling persistent nodes
+static inline int Abc_NodeIsPersistant( Abc_Obj_t * pNode ) { assert( Abc_AigNodeIsAnd(pNode) ); return pNode->fPersist; }
+static inline void Abc_NodeSetPersistant( Abc_Obj_t * pNode ) { assert( Abc_AigNodeIsAnd(pNode) ); pNode->fPersist = 1; }
+static inline void Abc_NodeClearPersistant( Abc_Obj_t * pNode ) { assert( Abc_AigNodeIsAnd(pNode) ); pNode->fPersist = 0; }
// working with the traversal ID
static inline void Abc_NodeSetTravId( Abc_Obj_t * pNode, int TravId ) { pNode->TravId = TravId; }
@@ -335,12 +415,29 @@ static inline bool Abc_NodeIsTravIdCurrent( Abc_Obj_t * pNode ) { r
static inline bool Abc_NodeIsTravIdPrevious( Abc_Obj_t * pNode ) { return (bool)(pNode->TravId == pNode->pNtk->nTravIds - 1); }
// checking initial state of the latches
-static inline void Abc_LatchSetInit0( Abc_Obj_t * pLatch ) { assert(Abc_ObjIsLatch(pLatch)); pLatch->pData = (void *)0; }
-static inline void Abc_LatchSetInit1( Abc_Obj_t * pLatch ) { assert(Abc_ObjIsLatch(pLatch)); pLatch->pData = (void *)1; }
-static inline void Abc_LatchSetInitDc( Abc_Obj_t * pLatch ) { assert(Abc_ObjIsLatch(pLatch)); pLatch->pData = (void *)2; }
-static inline bool Abc_LatchIsInit0( Abc_Obj_t * pLatch ) { assert(Abc_ObjIsLatch(pLatch)); return pLatch->pData == (void *)0; }
-static inline bool Abc_LatchIsInit1( Abc_Obj_t * pLatch ) { assert(Abc_ObjIsLatch(pLatch)); return pLatch->pData == (void *)1; }
-static inline bool Abc_LatchIsInitDc( Abc_Obj_t * pLatch ) { assert(Abc_ObjIsLatch(pLatch)); return pLatch->pData == (void *)2; }
+static inline void Abc_LatchSetInitNone( Abc_Obj_t * pLatch ) { assert(Abc_ObjIsLatch(pLatch)); pLatch->pData = (void *)ABC_INIT_NONE; }
+static inline void Abc_LatchSetInit0( Abc_Obj_t * pLatch ) { assert(Abc_ObjIsLatch(pLatch)); pLatch->pData = (void *)ABC_INIT_ZERO; }
+static inline void Abc_LatchSetInit1( Abc_Obj_t * pLatch ) { assert(Abc_ObjIsLatch(pLatch)); pLatch->pData = (void *)ABC_INIT_ONE; }
+static inline void Abc_LatchSetInitDc( Abc_Obj_t * pLatch ) { assert(Abc_ObjIsLatch(pLatch)); pLatch->pData = (void *)ABC_INIT_DC; }
+static inline bool Abc_LatchIsInitNone( Abc_Obj_t * pLatch ) { assert(Abc_ObjIsLatch(pLatch)); return pLatch->pData == (void *)ABC_INIT_NONE; }
+static inline bool Abc_LatchIsInit0( Abc_Obj_t * pLatch ) { assert(Abc_ObjIsLatch(pLatch)); return pLatch->pData == (void *)ABC_INIT_ZERO; }
+static inline bool Abc_LatchIsInit1( Abc_Obj_t * pLatch ) { assert(Abc_ObjIsLatch(pLatch)); return pLatch->pData == (void *)ABC_INIT_ONE; }
+static inline bool Abc_LatchIsInitDc( Abc_Obj_t * pLatch ) { assert(Abc_ObjIsLatch(pLatch)); return pLatch->pData == (void *)ABC_INIT_DC; }
+static inline int Abc_LatchInit( Abc_Obj_t * pLatch ) { assert(Abc_ObjIsLatch(pLatch)); return (int)pLatch->pData; }
+
+// global BDDs of the nodes
+static inline void * Abc_NtkGlobalBdd( Abc_Ntk_t * pNtk ) { return (void *)Vec_PtrEntry(pNtk->vAttrs, VEC_ATTR_GLOBAL_BDD); }
+static inline DdManager * Abc_NtkGlobalBddMan( Abc_Ntk_t * pNtk ) { return (DdManager *)Vec_AttMan( (Vec_Att_t *)Abc_NtkGlobalBdd(pNtk) ); }
+static inline DdNode ** Abc_NtkGlobalBddArray( Abc_Ntk_t * pNtk ) { return (DdNode **)Vec_AttArray( (Vec_Att_t *)Abc_NtkGlobalBdd(pNtk) ); }
+static inline DdNode * Abc_ObjGlobalBdd( Abc_Obj_t * pObj ) { return (DdNode *)Vec_AttEntry( (Vec_Att_t *)Abc_NtkGlobalBdd(pObj->pNtk), pObj->Id ); }
+static inline void Abc_ObjSetGlobalBdd( Abc_Obj_t * pObj, DdNode * bF ) { Vec_AttWriteEntry( (Vec_Att_t *)Abc_NtkGlobalBdd(pObj->pNtk), pObj->Id, bF ); }
+
+// MV variables of the nodes
+static inline void * Abc_NtkMvVar( Abc_Ntk_t * pNtk ) { return Vec_PtrEntry(pNtk->vAttrs, VEC_ATTR_MVVAR); }
+static inline void * Abc_NtkMvVarMan( Abc_Ntk_t * pNtk ) { return Abc_NtkMvVar(pNtk)? Vec_AttMan( (Vec_Att_t *)Abc_NtkMvVar(pNtk) ) : NULL; }
+static inline void * Abc_ObjMvVar( Abc_Obj_t * pObj ) { return Abc_NtkMvVar(pObj->pNtk)? Vec_AttEntry( (Vec_Att_t *)Abc_NtkMvVar(pObj->pNtk), pObj->Id ) : NULL; }
+static inline int Abc_ObjMvVarNum( Abc_Obj_t * pObj ) { return (Abc_NtkMvVar(pObj->pNtk) && Abc_ObjMvVar(pObj))? *((int*)Abc_ObjMvVar(pObj)) : 2; }
+static inline void Abc_ObjSetMvVar( Abc_Obj_t * pObj, void * pV) { Vec_AttWriteEntry( (Vec_Att_t *)Abc_NtkMvVar(pObj->pNtk), pObj->Id, pV ); }
// outputs the runtime in seconds
#define PRT(a,t) printf("%s = ", (a)); printf("%6.2f sec\n", (float)(t)/(float)(CLOCKS_PER_SEC))
@@ -350,36 +447,59 @@ static inline bool Abc_LatchIsInitDc( Abc_Obj_t * pLatch ) { assert(Abc
////////////////////////////////////////////////////////////////////////
// objects of the network
-#define Abc_NtkForEachObj( pNtk, pObj, i ) \
- for ( i = 0; i < Vec_PtrSize(pNtk->vObjs); i++ ) \
- if ( pObj = Abc_NtkObj(pNtk, i) )
-#define Abc_NtkForEachNet( pNtk, pNet, i ) \
- for ( i = 0; i < Vec_PtrSize(pNtk->vObjs); i++ ) \
- if ( (pNet = Abc_NtkObj(pNtk, i)) && Abc_ObjIsNet(pNet) )
-#define Abc_NtkForEachNode( pNtk, pNode, i ) \
- for ( i = 0; i < Vec_PtrSize(pNtk->vObjs); i++ ) \
- if ( (pNode = Abc_NtkObj(pNtk, i)) && Abc_ObjIsNode(pNode) )
-#define Abc_NtkForEachLatch( pNtk, pObj, i ) \
- for ( i = 0; i < Vec_PtrSize(pNtk->vLats); i++ ) \
- if ( pObj = Abc_NtkLatch(pNtk, i) )
+#define Abc_NtkForEachObj( pNtk, pObj, i ) \
+ for ( i = 0; (i < Vec_PtrSize((pNtk)->vObjs)) && (((pObj) = Abc_NtkObj(pNtk, i)), 1); i++ ) \
+ if ( (pObj) == NULL ) {} else
+#define Abc_NtkForEachNet( pNtk, pNet, i ) \
+ for ( i = 0; (i < Vec_PtrSize((pNtk)->vObjs)) && (((pNet) = Abc_NtkObj(pNtk, i)), 1); i++ ) \
+ if ( (pNet) == NULL || !Abc_ObjIsNet(pNet) ) {} else
+#define Abc_NtkForEachNode( pNtk, pNode, i ) \
+ for ( i = 0; (i < Vec_PtrSize((pNtk)->vObjs)) && (((pNode) = Abc_NtkObj(pNtk, i)), 1); i++ ) \
+ if ( (pNode) == NULL || !Abc_ObjIsNode(pNode) ) {} else
+#define Abc_NtkForEachGate( pNtk, pNode, i ) \
+ for ( i = 0; (i < Vec_PtrSize((pNtk)->vObjs)) && (((pNode) = Abc_NtkObj(pNtk, i)), 1); i++ ) \
+ if ( (pNode) == NULL || !Abc_ObjIsGate(pNode) ) {} else
+#define Abc_AigForEachAnd( pNtk, pNode, i ) \
+ for ( i = 0; (i < Vec_PtrSize((pNtk)->vObjs)) && (((pNode) = Abc_NtkObj(pNtk, i)), 1); i++ ) \
+ if ( (pNode) == NULL || !Abc_AigNodeIsAnd(pNode) ) {} else
+// various boxes
+#define Abc_NtkForEachBox( pNtk, pObj, i ) \
+ for ( i = 0; (i < Vec_PtrSize((pNtk)->vBoxes)) && (((pObj) = Abc_NtkBox(pNtk, i)), 1); i++ )
+#define Abc_NtkForEachLatch( pNtk, pObj, i ) \
+ for ( i = 0; (i < Vec_PtrSize((pNtk)->vBoxes)) && (((pObj) = Abc_NtkBox(pNtk, i)), 1); i++ ) \
+ if ( !Abc_ObjIsLatch(pObj) ) {} else
+#define Abc_NtkForEachLatchInput( pNtk, pObj, i ) \
+ for ( i = 0; (i < Vec_PtrSize((pNtk)->vBoxes)); i++ ) \
+ if ( !(Abc_ObjIsLatch(Abc_NtkBox(pNtk, i)) && (((pObj) = Abc_ObjFanin0(Abc_NtkBox(pNtk, i))), 1)) ) {} else
+#define Abc_NtkForEachLatchOutput( pNtk, pObj, i ) \
+ for ( i = 0; (i < Vec_PtrSize((pNtk)->vBoxes)); i++ ) \
+ if ( !(Abc_ObjIsLatch(Abc_NtkBox(pNtk, i)) && (((pObj) = Abc_ObjFanout0(Abc_NtkBox(pNtk, i))), 1)) ) {} else
+#define Abc_NtkForEachWhitebox( pNtk, pObj, i ) \
+ for ( i = 0; (i < Vec_PtrSize((pNtk)->vBoxes)) && (((pObj) = Abc_NtkBox(pNtk, i)), 1); i++ ) \
+ if ( !Abc_ObjIsWhitebox(pObj) ) {} else
+#define Abc_NtkForEachBlackbox( pNtk, pObj, i ) \
+ for ( i = 0; (i < Vec_PtrSize((pNtk)->vBoxes)) && (((pObj) = Abc_NtkBox(pNtk, i)), 1); i++ ) \
+ if ( !Abc_ObjIsBlackbox(pObj) ) {} else
// inputs and outputs
-#define Abc_NtkForEachPi( pNtk, pPi, i ) \
+#define Abc_NtkForEachPi( pNtk, pPi, i ) \
for ( i = 0; (i < Abc_NtkPiNum(pNtk)) && (((pPi) = Abc_NtkPi(pNtk, i)), 1); i++ )
-#define Abc_NtkForEachPo( pNtk, pPo, i ) \
- for ( i = 0; (i < Abc_NtkPoNum(pNtk)) && (((pPo) = Abc_NtkPo(pNtk, i)), 1); i++ )
-#define Abc_NtkForEachCi( pNtk, pCi, i ) \
+#define Abc_NtkForEachCi( pNtk, pCi, i ) \
for ( i = 0; (i < Abc_NtkCiNum(pNtk)) && (((pCi) = Abc_NtkCi(pNtk, i)), 1); i++ )
-#define Abc_NtkForEachCo( pNtk, pCo, i ) \
+#define Abc_NtkForEachPo( pNtk, pPo, i ) \
+ for ( i = 0; (i < Abc_NtkPoNum(pNtk)) && (((pPo) = Abc_NtkPo(pNtk, i)), 1); i++ )
+#define Abc_NtkForEachCo( pNtk, pCo, i ) \
for ( i = 0; (i < Abc_NtkCoNum(pNtk)) && (((pCo) = Abc_NtkCo(pNtk, i)), 1); i++ )
+#define Abc_NtkForEachAssert( pNtk, pObj, i ) \
+ for ( i = 0; (i < Vec_PtrSize((pNtk)->vAsserts)) && (((pObj) = Abc_NtkAssert(pNtk, i)), 1); i++ )
// fanin and fanouts
-#define Abc_ObjForEachFanin( pObj, pFanin, i ) \
+#define Abc_ObjForEachFanin( pObj, pFanin, i ) \
for ( i = 0; (i < Abc_ObjFaninNum(pObj)) && (((pFanin) = Abc_ObjFanin(pObj, i)), 1); i++ )
-#define Abc_ObjForEachFanout( pObj, pFanout, i ) \
+#define Abc_ObjForEachFanout( pObj, pFanout, i ) \
for ( i = 0; (i < Abc_ObjFanoutNum(pObj)) && (((pFanout) = Abc_ObjFanout(pObj, i)), 1); i++ )
// cubes and literals
-#define Abc_SopForEachCube( pSop, nFanins, pCube ) \
+#define Abc_SopForEachCube( pSop, nFanins, pCube ) \
for ( pCube = (pSop); *pCube; pCube += (nFanins) + 3 )
-#define Abc_CubeForEachVar( pCube, Value, i ) \
+#define Abc_CubeForEachVar( pCube, Value, i ) \
for ( i = 0; (pCube[i] != ' ') && (Value = pCube[i]); i++ )
@@ -389,57 +509,92 @@ static inline bool Abc_LatchIsInitDc( Abc_Obj_t * pLatch ) { assert(Abc
/*=== abcAig.c ==========================================================*/
extern Abc_Aig_t * Abc_AigAlloc( Abc_Ntk_t * pNtk );
-extern Abc_Aig_t * Abc_AigDup( Abc_Aig_t * pMan, Abc_Aig_t * pManNew );
extern void Abc_AigFree( Abc_Aig_t * pMan );
extern int Abc_AigCleanup( Abc_Aig_t * pMan );
extern bool Abc_AigCheck( Abc_Aig_t * pMan );
-extern int Abc_AigGetLevelNum( Abc_Ntk_t * pNtk );
-extern Abc_Obj_t * Abc_AigConst1( Abc_Aig_t * pMan );
-extern Abc_Obj_t * Abc_AigReset( Abc_Aig_t * pMan );
+extern int Abc_AigLevel( Abc_Ntk_t * pNtk );
+extern Abc_Obj_t * Abc_AigConst1( Abc_Ntk_t * pNtk );
extern Abc_Obj_t * Abc_AigAnd( Abc_Aig_t * pMan, Abc_Obj_t * p0, Abc_Obj_t * p1 );
extern Abc_Obj_t * Abc_AigAndLookup( Abc_Aig_t * pMan, Abc_Obj_t * p0, Abc_Obj_t * p1 );
+extern Abc_Obj_t * Abc_AigXorLookup( Abc_Aig_t * pMan, Abc_Obj_t * p0, Abc_Obj_t * p1, int * pType );
+extern Abc_Obj_t * Abc_AigMuxLookup( Abc_Aig_t * pMan, Abc_Obj_t * pC, Abc_Obj_t * pT, Abc_Obj_t * pE, int * pType );
extern Abc_Obj_t * Abc_AigOr( Abc_Aig_t * pMan, Abc_Obj_t * p0, Abc_Obj_t * p1 );
extern Abc_Obj_t * Abc_AigXor( Abc_Aig_t * pMan, Abc_Obj_t * p0, Abc_Obj_t * p1 );
extern Abc_Obj_t * Abc_AigMiter( Abc_Aig_t * pMan, Vec_Ptr_t * vPairs );
-extern void Abc_AigReplace( Abc_Aig_t * pMan, Abc_Obj_t * pOld, Abc_Obj_t * pNew );
+extern void Abc_AigReplace( Abc_Aig_t * pMan, Abc_Obj_t * pOld, Abc_Obj_t * pNew, bool fUpdateLevel );
extern void Abc_AigDeleteNode( Abc_Aig_t * pMan, Abc_Obj_t * pOld );
+extern void Abc_AigRehash( Abc_Aig_t * pMan );
extern bool Abc_AigNodeHasComplFanoutEdge( Abc_Obj_t * pNode );
extern bool Abc_AigNodeHasComplFanoutEdgeTrav( Abc_Obj_t * pNode );
extern void Abc_AigPrintNode( Abc_Obj_t * pNode );
extern bool Abc_AigNodeIsAcyclic( Abc_Obj_t * pNode, Abc_Obj_t * pRoot );
+extern void Abc_AigCheckFaninOrder( Abc_Aig_t * pMan );
+extern void Abc_AigSetNodePhases( Abc_Ntk_t * pNtk );
+extern Vec_Ptr_t * Abc_AigUpdateStart( Abc_Aig_t * pMan, Vec_Ptr_t ** pvUpdatedNets );
+extern void Abc_AigUpdateStop( Abc_Aig_t * pMan );
+extern void Abc_AigUpdateReset( Abc_Aig_t * pMan );
/*=== abcAttach.c ==========================================================*/
extern int Abc_NtkAttach( Abc_Ntk_t * pNtk );
+/*=== abcBlifMv.c ==========================================================*/
+extern void Abc_NtkStartMvVars( Abc_Ntk_t * pNtk );
+extern void Abc_NtkFreeMvVars( Abc_Ntk_t * pNtk );
+extern void Abc_NtkSetMvVarValues( Abc_Obj_t * pObj, int nValues );
+extern Abc_Ntk_t * Abc_NtkStrashBlifMv( Abc_Ntk_t * pNtk );
+extern Abc_Ntk_t * Abc_NtkInsertBlifMv( Abc_Ntk_t * pNtkBase, Abc_Ntk_t * pNtkLogic );
+extern int Abc_NtkConvertToBlifMv( Abc_Ntk_t * pNtk );
+extern char * Abc_NodeConvertSopToMvSop( int nVars, Vec_Int_t * vSop0, Vec_Int_t * vSop1 );
+extern int Abc_NodeEvalMvCost( int nVars, Vec_Int_t * vSop0, Vec_Int_t * vSop1 );
/*=== abcBalance.c ==========================================================*/
-extern Abc_Ntk_t * Abc_NtkBalance( Abc_Ntk_t * pNtk, bool fDuplicate );
+extern Abc_Ntk_t * Abc_NtkBalance( Abc_Ntk_t * pNtk, bool fDuplicate, bool fSelective, bool fUpdateLevel );
/*=== abcCheck.c ==========================================================*/
extern bool Abc_NtkCheck( Abc_Ntk_t * pNtk );
extern bool Abc_NtkCheckRead( Abc_Ntk_t * pNtk );
+extern bool Abc_NtkDoCheck( Abc_Ntk_t * pNtk );
extern bool Abc_NtkCheckObj( Abc_Ntk_t * pNtk, Abc_Obj_t * pObj );
-extern bool Abc_NtkCompareSignals( Abc_Ntk_t * pNtk1, Abc_Ntk_t * pNtk2, int fComb );
+extern bool Abc_NtkCompareSignals( Abc_Ntk_t * pNtk1, Abc_Ntk_t * pNtk2, int fOnlyPis, int fComb );
+extern int Abc_NtkIsAcyclicHierarchy( Abc_Ntk_t * pNtk );
+extern int Abc_NtkCheckUniqueCiNames( Abc_Ntk_t * pNtk );
+extern int Abc_NtkCheckUniqueCoNames( Abc_Ntk_t * pNtk );
+extern int Abc_NtkCheckUniqueCioNames( Abc_Ntk_t * pNtk );
/*=== abcCollapse.c ==========================================================*/
-extern Abc_Ntk_t * Abc_NtkCollapse( Abc_Ntk_t * pNtk, int fVerbose );
+extern Abc_Ntk_t * Abc_NtkCollapse( Abc_Ntk_t * pNtk, int fBddSizeMax, int fDualRail, int fReorder, int fVerbose );
/*=== abcCut.c ==========================================================*/
-extern void * Abc_NodeGetCutsRecursive( void * p, Abc_Obj_t * pObj );
-extern void * Abc_NodeGetCuts( void * p, Abc_Obj_t * pObj );
+extern void * Abc_NodeGetCutsRecursive( void * p, Abc_Obj_t * pObj, int fDag, int fTree );
+extern void * Abc_NodeGetCuts( void * p, Abc_Obj_t * pObj, int fDag, int fTree );
+extern void Abc_NodeGetCutsSeq( void * p, Abc_Obj_t * pObj, int fFirst );
extern void * Abc_NodeReadCuts( void * p, Abc_Obj_t * pObj );
extern void Abc_NodeFreeCuts( void * p, Abc_Obj_t * pObj );
/*=== abcDfs.c ==========================================================*/
extern Vec_Ptr_t * Abc_NtkDfs( Abc_Ntk_t * pNtk, int fCollectAll );
extern Vec_Ptr_t * Abc_NtkDfsNodes( Abc_Ntk_t * pNtk, Abc_Obj_t ** ppNodes, int nNodes );
extern Vec_Ptr_t * Abc_NtkDfsReverse( Abc_Ntk_t * pNtk );
+extern Vec_Ptr_t * Abc_NtkDfsReverseNodes( Abc_Ntk_t * pNtk, Abc_Obj_t ** ppNodes, int nNodes );
+extern Vec_Ptr_t * Abc_NtkDfsReverseNodesContained( Abc_Ntk_t * pNtk, Abc_Obj_t ** ppNodes, int nNodes );
+extern Vec_Ptr_t * Abc_NtkDfsSeq( Abc_Ntk_t * pNtk );
+extern Vec_Ptr_t * Abc_NtkDfsSeqReverse( Abc_Ntk_t * pNtk );
+extern Vec_Ptr_t * Abc_NtkDfsIter( Abc_Ntk_t * pNtk, int fCollectAll );
+extern Vec_Ptr_t * Abc_NtkDfsHie( Abc_Ntk_t * pNtk, int fCollectAll );
+extern bool Abc_NtkIsDfsOrdered( Abc_Ntk_t * pNtk );
+extern Vec_Ptr_t * Abc_NtkSupport( Abc_Ntk_t * pNtk );
+extern Vec_Ptr_t * Abc_NtkNodeSupport( Abc_Ntk_t * pNtk, Abc_Obj_t ** ppNodes, int nNodes );
extern Vec_Ptr_t * Abc_AigDfs( Abc_Ntk_t * pNtk, int fCollectAll, int fCollectCos );
extern Vec_Vec_t * Abc_DfsLevelized( Abc_Obj_t * pNode, bool fTfi );
-extern int Abc_NtkGetLevelNum( Abc_Ntk_t * pNtk );
+extern int Abc_NtkLevel( Abc_Ntk_t * pNtk );
+extern int Abc_NtkLevelReverse( Abc_Ntk_t * pNtk );
extern bool Abc_NtkIsAcyclic( Abc_Ntk_t * pNtk );
+extern Vec_Ptr_t * Abc_AigGetLevelizedOrder( Abc_Ntk_t * pNtk, int fCollectCis );
/*=== abcFanio.c ==========================================================*/
extern void Abc_ObjAddFanin( Abc_Obj_t * pObj, Abc_Obj_t * pFanin );
extern void Abc_ObjDeleteFanin( Abc_Obj_t * pObj, Abc_Obj_t * pFanin );
extern void Abc_ObjRemoveFanins( Abc_Obj_t * pObj );
extern void Abc_ObjPatchFanin( Abc_Obj_t * pObj, Abc_Obj_t * pFaninOld, Abc_Obj_t * pFaninNew );
+extern Abc_Obj_t * Abc_ObjInsertBetween( Abc_Obj_t * pNodeIn, Abc_Obj_t * pNodeOut, Abc_ObjType_t Type );
extern void Abc_ObjTransferFanout( Abc_Obj_t * pObjOld, Abc_Obj_t * pObjNew );
extern void Abc_ObjReplace( Abc_Obj_t * pObjOld, Abc_Obj_t * pObjNew );
+extern int Abc_ObjFanoutFaninNum( Abc_Obj_t * pFanout, Abc_Obj_t * pFanin );
/*=== abcFraig.c ==========================================================*/
-extern Abc_Ntk_t * Abc_NtkFraig( Abc_Ntk_t * pNtk, void * pParams, int fAllNodes );
+extern Abc_Ntk_t * Abc_NtkFraig( Abc_Ntk_t * pNtk, void * pParams, int fAllNodes, int fExdc );
+extern void * Abc_NtkToFraig( Abc_Ntk_t * pNtk, void * pParams, int fAllNodes, int fExdc );
extern Abc_Ntk_t * Abc_NtkFraigTrust( Abc_Ntk_t * pNtk );
extern int Abc_NtkFraigStore( Abc_Ntk_t * pNtk );
extern Abc_Ntk_t * Abc_NtkFraigRestore();
@@ -447,95 +602,133 @@ extern void Abc_NtkFraigStoreClean();
/*=== abcFunc.c ==========================================================*/
extern int Abc_NtkSopToBdd( Abc_Ntk_t * pNtk );
extern DdNode * Abc_ConvertSopToBdd( DdManager * dd, char * pSop );
-extern char * Abc_ConvertBddToSop( Extra_MmFlex_t * pMan, DdManager * dd, DdNode * bFuncOn, DdNode * bFuncOnDc, int nFanins, Vec_Str_t * vCube, int fMode );
-extern int Abc_NtkBddToSop( Abc_Ntk_t * pNtk );
-extern void Abc_NodeBddToCnf( Abc_Obj_t * pNode, Extra_MmFlex_t * pMmMan, Vec_Str_t * vCube, char ** ppSop0, char ** ppSop1 );
+extern char * Abc_ConvertBddToSop( Extra_MmFlex_t * pMan, DdManager * dd, DdNode * bFuncOn, DdNode * bFuncOnDc, int nFanins, int fAllPrimes, Vec_Str_t * vCube, int fMode );
+extern int Abc_NtkBddToSop( Abc_Ntk_t * pNtk, int fDirect );
+extern void Abc_NodeBddToCnf( Abc_Obj_t * pNode, Extra_MmFlex_t * pMmMan, Vec_Str_t * vCube, int fAllPrimes, char ** ppSop0, char ** ppSop1 );
extern int Abc_CountZddCubes( DdManager * dd, DdNode * zCover );
extern void Abc_NtkLogicMakeDirectSops( Abc_Ntk_t * pNtk );
+extern int Abc_NtkSopToAig( Abc_Ntk_t * pNtk );
+extern int Abc_NtkAigToBdd( Abc_Ntk_t * pNtk );
+extern unsigned * Abc_ConvertAigToTruth( Hop_Man_t * p, Hop_Obj_t * pRoot, int nVars, Vec_Int_t * vTruth, int fMsbFirst );
+extern int Abc_NtkMapToSop( Abc_Ntk_t * pNtk );
+extern int Abc_NtkToSop( Abc_Ntk_t * pNtk, int fDirect );
+extern int Abc_NtkToBdd( Abc_Ntk_t * pNtk );
+extern int Abc_NtkToAig( Abc_Ntk_t * pNtk );
+/*=== abcHaig.c ==========================================================*/
+extern int Abc_NtkHaigStart( Abc_Ntk_t * pNtk );
+extern int Abc_NtkHaigStop( Abc_Ntk_t * pNtk );
+extern Abc_Ntk_t * Abc_NtkHaigUse( Abc_Ntk_t * pNtk );
+/*=== abcHie.c ==========================================================*/
+extern Abc_Ntk_t * Abc_NtkFlattenLogicHierarchy( Abc_Ntk_t * pNtk );
+extern Abc_Ntk_t * Abc_NtkConvertBlackboxes( Abc_Ntk_t * pNtk );
+extern Abc_Ntk_t * Abc_NtkInsertNewLogic( Abc_Ntk_t * pNtkH, Abc_Ntk_t * pNtkL );
/*=== abcLatch.c ==========================================================*/
extern bool Abc_NtkLatchIsSelfFeed( Abc_Obj_t * pLatch );
extern int Abc_NtkCountSelfFeedLatches( Abc_Ntk_t * pNtk );
-/*=== abcMap.c ==========================================================*/
-extern int Abc_NtkUnmap( Abc_Ntk_t * pNtk );
+extern int Abc_NtkRemoveSelfFeedLatches( Abc_Ntk_t * pNtk );
+extern Vec_Int_t * Abc_NtkCollectLatchValues( Abc_Ntk_t * pNtk );
+extern void Abc_NtkInsertLatchValues( Abc_Ntk_t * pNtk, Vec_Int_t * vValues );
+extern Abc_Obj_t * Abc_NtkAddLatch( Abc_Ntk_t * pNtk, Abc_Obj_t * pDriver, Abc_InitType_t Init );
+extern void Abc_NtkConvertDcLatches( Abc_Ntk_t * pNtk );
+ /*=== abcLib.c ==========================================================*/
+extern Abc_Lib_t * Abc_LibCreate( char * pName );
+extern void Abc_LibFree( Abc_Lib_t * pLib, Abc_Ntk_t * pNtk );
+extern void Abc_LibPrint( Abc_Lib_t * pLib );
+extern int Abc_LibAddModel( Abc_Lib_t * pLib, Abc_Ntk_t * pNtk );
+extern Abc_Ntk_t * Abc_LibFindModelByName( Abc_Lib_t * pLib, char * pName );
+extern int Abc_LibFindTopLevelModels( Abc_Lib_t * pLib );
+extern Abc_Ntk_t * Abc_LibDeriveRoot( Abc_Lib_t * pLib );
/*=== abcMiter.c ==========================================================*/
extern int Abc_NtkMinimumBase( Abc_Ntk_t * pNtk );
extern int Abc_NodeMinimumBase( Abc_Obj_t * pNode );
extern int Abc_NtkRemoveDupFanins( Abc_Ntk_t * pNtk );
extern int Abc_NodeRemoveDupFanins( Abc_Obj_t * pNode );
/*=== abcMiter.c ==========================================================*/
-extern Abc_Ntk_t * Abc_NtkMiter( Abc_Ntk_t * pNtk1, Abc_Ntk_t * pNtk2, int fComb );
+extern Abc_Ntk_t * Abc_NtkMiter( Abc_Ntk_t * pNtk1, Abc_Ntk_t * pNtk2, int fComb, int nPartSize );
+extern void Abc_NtkMiterAddCone( Abc_Ntk_t * pNtk, Abc_Ntk_t * pNtkMiter, Abc_Obj_t * pNode );
+extern Abc_Ntk_t * Abc_NtkMiterAnd( Abc_Ntk_t * pNtk1, Abc_Ntk_t * pNtk2, int fOr, int fCompl2 );
+extern Abc_Ntk_t * Abc_NtkMiterCofactor( Abc_Ntk_t * pNtk, Vec_Int_t * vPiValues );
extern Abc_Ntk_t * Abc_NtkMiterForCofactors( Abc_Ntk_t * pNtk, int Out, int In1, int In2 );
+extern Abc_Ntk_t * Abc_NtkMiterQuantify( Abc_Ntk_t * pNtk, int In, int fExist );
+extern Abc_Ntk_t * Abc_NtkMiterQuantifyPis( Abc_Ntk_t * pNtk );
extern int Abc_NtkMiterIsConstant( Abc_Ntk_t * pMiter );
extern void Abc_NtkMiterReport( Abc_Ntk_t * pMiter );
-extern int Abc_NtkAppend( Abc_Ntk_t * pNtk1, Abc_Ntk_t * pNtk2 );
extern Abc_Ntk_t * Abc_NtkFrames( Abc_Ntk_t * pNtk, int nFrames, int fInitial );
-/*=== abcObj.c ==========================================================*/
-extern Abc_Obj_t * Abc_ObjAlloc( Abc_Ntk_t * pNtk, Abc_ObjType_t Type );
-extern void Abc_ObjRecycle( Abc_Obj_t * pObj );
-extern void Abc_ObjAdd( Abc_Obj_t * pObj );
-extern Abc_Obj_t * Abc_NtkDupObj( Abc_Ntk_t * pNtkNew, Abc_Obj_t * pObj );
-extern Abc_Obj_t * Abc_NtkDupConst1( Abc_Ntk_t * pNtkAig, Abc_Ntk_t * pNtkNew );
-extern Abc_Obj_t * Abc_NtkDupReset( Abc_Ntk_t * pNtkAig, Abc_Ntk_t * pNtkNew );
-extern void Abc_NtkDeleteObj( Abc_Obj_t * pObj );
-extern Abc_Obj_t * Abc_NtkFindNode( Abc_Ntk_t * pNtk, char * pName );
-extern Abc_Obj_t * Abc_NtkFindCo( Abc_Ntk_t * pNtk, char * pName );
-extern Abc_Obj_t * Abc_NtkFindNet( Abc_Ntk_t * pNtk, char * pName );
-extern Abc_Obj_t * Abc_NtkFindOrCreateNet( Abc_Ntk_t * pNtk, char * pName );
-extern Abc_Obj_t * Abc_NtkCreateNode( Abc_Ntk_t * pNtk );
-extern Abc_Obj_t * Abc_NtkCreatePi( Abc_Ntk_t * pNtk );
-extern Abc_Obj_t * Abc_NtkCreatePo( Abc_Ntk_t * pNtk );
-extern Abc_Obj_t * Abc_NtkCreateLatch( Abc_Ntk_t * pNtk );
-extern Abc_Obj_t * Abc_NodeCreateConst0( Abc_Ntk_t * pNtk );
-extern Abc_Obj_t * Abc_NodeCreateConst1( Abc_Ntk_t * pNtk );
-extern Abc_Obj_t * Abc_NodeCreateInv( Abc_Ntk_t * pNtk, Abc_Obj_t * pFanin );
-extern Abc_Obj_t * Abc_NodeCreateBuf( Abc_Ntk_t * pNtk, Abc_Obj_t * pFanin );
-extern Abc_Obj_t * Abc_NodeCreateAnd( Abc_Ntk_t * pNtk, Vec_Ptr_t * vFanins );
-extern Abc_Obj_t * Abc_NodeCreateOr( Abc_Ntk_t * pNtk, Vec_Ptr_t * vFanins );
-extern Abc_Obj_t * Abc_NodeCreateMux( Abc_Ntk_t * pNtk, Abc_Obj_t * pNodeC, Abc_Obj_t * pNode1, Abc_Obj_t * pNode0 );
-extern Abc_Obj_t * Abc_NodeClone( Abc_Obj_t * pNode );
/*=== abcNames.c ====================================================*/
-extern char * Abc_NtkRegisterName( Abc_Ntk_t * pNtk, char * pName );
-extern char * Abc_NtkRegisterNamePlus( Abc_Ntk_t * pNtk, char * pName, char * pSuffix );
extern char * Abc_ObjName( Abc_Obj_t * pNode );
+extern char * Abc_ObjAssignName( Abc_Obj_t * pObj, char * pName, char * pSuffix );
extern char * Abc_ObjNameSuffix( Abc_Obj_t * pObj, char * pSuffix );
-extern char * Abc_ObjNameUnique( Abc_Ntk_t * pNtk, char * pName );
-extern char * Abc_NtkLogicStoreName( Abc_Obj_t * pNodeNew, char * pNameOld );
-extern char * Abc_NtkLogicStoreNamePlus( Abc_Obj_t * pNodeNew, char * pNameOld, char * pSuffix );
-extern void Abc_NtkCreateCioNamesTable( Abc_Ntk_t * pNtk );
-extern void Abc_NtkDupCioNamesTable( Abc_Ntk_t * pNtk, Abc_Ntk_t * pNtkNew );
+extern char * Abc_ObjNameDummy( char * pPrefix, int Num, int nDigits );
+extern void Abc_NtkTrasferNames( Abc_Ntk_t * pNtk, Abc_Ntk_t * pNtkNew );
+extern void Abc_NtkTrasferNamesNoLatches( Abc_Ntk_t * pNtk, Abc_Ntk_t * pNtkNew );
extern Vec_Ptr_t * Abc_NodeGetFaninNames( Abc_Obj_t * pNode );
extern Vec_Ptr_t * Abc_NodeGetFakeNames( int nNames );
extern void Abc_NodeFreeNames( Vec_Ptr_t * vNames );
extern char ** Abc_NtkCollectCioNames( Abc_Ntk_t * pNtk, int fCollectCos );
extern int Abc_NodeCompareNames( Abc_Obj_t ** pp1, Abc_Obj_t ** pp2 );
extern void Abc_NtkOrderObjsByName( Abc_Ntk_t * pNtk, int fComb );
+extern void Abc_NtkAddDummyPiNames( Abc_Ntk_t * pNtk );
+extern void Abc_NtkAddDummyPoNames( Abc_Ntk_t * pNtk );
+extern void Abc_NtkAddDummyAssertNames( Abc_Ntk_t * pNtk );
+extern void Abc_NtkAddDummyBoxNames( Abc_Ntk_t * pNtk );
extern void Abc_NtkShortNames( Abc_Ntk_t * pNtk );
/*=== abcNetlist.c ==========================================================*/
-extern Abc_Ntk_t * Abc_NtkNetlistToLogic( Abc_Ntk_t * pNtk );
-extern Abc_Ntk_t * Abc_NtkLogicToNetlist( Abc_Ntk_t * pNtk );
-extern Abc_Ntk_t * Abc_NtkLogicToNetlistBench( Abc_Ntk_t * pNtk );
-extern Abc_Ntk_t * Abc_NtkLogicSopToNetlist( Abc_Ntk_t * pNtk );
-extern Abc_Ntk_t * Abc_NtkAigToLogicSop( Abc_Ntk_t * pNtk );
-extern Abc_Ntk_t * Abc_NtkAigToLogicSopBench( Abc_Ntk_t * pNtk );
+extern Abc_Ntk_t * Abc_NtkToLogic( Abc_Ntk_t * pNtk );
+extern Abc_Ntk_t * Abc_NtkToNetlist( Abc_Ntk_t * pNtk );
+extern Abc_Ntk_t * Abc_NtkToNetlistBench( Abc_Ntk_t * pNtk );
/*=== abcNtbdd.c ==========================================================*/
extern Abc_Ntk_t * Abc_NtkDeriveFromBdd( DdManager * dd, DdNode * bFunc, char * pNamePo, Vec_Ptr_t * vNamesPi );
extern Abc_Ntk_t * Abc_NtkBddToMuxes( Abc_Ntk_t * pNtk );
-extern DdManager * Abc_NtkGlobalBdds( Abc_Ntk_t * pNtk, int fLatchOnly );
-extern void Abc_NtkFreeGlobalBdds( Abc_Ntk_t * pNtk );
+extern DdManager * Abc_NtkBuildGlobalBdds( Abc_Ntk_t * pNtk, int fBddSizeMax, int fDropInternal, int fReorder, int fVerbose );
+extern DdManager * Abc_NtkFreeGlobalBdds( Abc_Ntk_t * pNtk, int fFreeMan );
+extern int Abc_NtkSizeOfGlobalBdds( Abc_Ntk_t * pNtk );
/*=== abcNtk.c ==========================================================*/
-extern Abc_Ntk_t * Abc_NtkAlloc( Abc_NtkType_t Type, Abc_NtkFunc_t Func );
+extern Abc_Ntk_t * Abc_NtkAlloc( Abc_NtkType_t Type, Abc_NtkFunc_t Func, int fUseMemMan );
extern Abc_Ntk_t * Abc_NtkStartFrom( Abc_Ntk_t * pNtk, Abc_NtkType_t Type, Abc_NtkFunc_t Func );
+extern Abc_Ntk_t * Abc_NtkStartFromNoLatches( Abc_Ntk_t * pNtk, Abc_NtkType_t Type, Abc_NtkFunc_t Func );
extern void Abc_NtkFinalize( Abc_Ntk_t * pNtk, Abc_Ntk_t * pNtkNew );
-extern void Abc_NtkFinalizeRegular( Abc_Ntk_t * pNtk, Abc_Ntk_t * pNtkNew );
-extern void Abc_NtkFinalizeLatches( Abc_Ntk_t * pNtk );
extern Abc_Ntk_t * Abc_NtkStartRead( char * pName );
extern void Abc_NtkFinalizeRead( Abc_Ntk_t * pNtk );
extern Abc_Ntk_t * Abc_NtkDup( Abc_Ntk_t * pNtk );
-extern Abc_Ntk_t * Abc_NtkSplitOutput( Abc_Ntk_t * pNtk, Abc_Obj_t * pNode, int fUseAllCis );
-extern Abc_Ntk_t * Abc_NtkCreateCone( Abc_Ntk_t * pNtk, Vec_Ptr_t * vRoots, Vec_Int_t * vValues );
-extern Abc_Ntk_t * Abc_NtkSplitNode( Abc_Ntk_t * pNtk, Abc_Obj_t * pNode );
+extern Abc_Ntk_t * Abc_NtkCreateCone( Abc_Ntk_t * pNtk, Abc_Obj_t * pNode, char * pNodeName, int fUseAllCis );
+extern Abc_Ntk_t * Abc_NtkCreateConeArray( Abc_Ntk_t * pNtk, Vec_Ptr_t * vRoots, int fUseAllCis );
+extern void Abc_NtkAppendToCone( Abc_Ntk_t * pNtkNew, Abc_Ntk_t * pNtk, Vec_Ptr_t * vRoots );
+extern Abc_Ntk_t * Abc_NtkCreateMffc( Abc_Ntk_t * pNtk, Abc_Obj_t * pNode, char * pNodeName );
+extern Abc_Ntk_t * Abc_NtkCreateTarget( Abc_Ntk_t * pNtk, Vec_Ptr_t * vRoots, Vec_Int_t * vValues );
+extern Abc_Ntk_t * Abc_NtkCreateFromNode( Abc_Ntk_t * pNtk, Abc_Obj_t * pNode );
+extern Abc_Ntk_t * Abc_NtkCreateWithNode( char * pSop );
extern void Abc_NtkDelete( Abc_Ntk_t * pNtk );
extern void Abc_NtkFixNonDrivenNets( Abc_Ntk_t * pNtk );
+extern void Abc_NtkMakeComb( Abc_Ntk_t * pNtk );
+/*=== abcObj.c ==========================================================*/
+extern Abc_Obj_t * Abc_ObjAlloc( Abc_Ntk_t * pNtk, Abc_ObjType_t Type );
+extern void Abc_ObjRecycle( Abc_Obj_t * pObj );
+extern Abc_Obj_t * Abc_NtkCreateObj( Abc_Ntk_t * pNtk, Abc_ObjType_t Type );
+extern void Abc_NtkDeleteObj( Abc_Obj_t * pObj );
+extern void Abc_NtkDeleteObj_rec( Abc_Obj_t * pObj, int fOnlyNodes );
+extern void Abc_NtkDeleteAll_rec( Abc_Obj_t * pObj );
+extern Abc_Obj_t * Abc_NtkDupObj( Abc_Ntk_t * pNtkNew, Abc_Obj_t * pObj, int fCopyName );
+extern Abc_Obj_t * Abc_NtkDupBox( Abc_Ntk_t * pNtkNew, Abc_Obj_t * pBox, int fCopyName );
+extern Abc_Obj_t * Abc_NtkCloneObj( Abc_Obj_t * pNode );
+extern Abc_Obj_t * Abc_NtkFindNode( Abc_Ntk_t * pNtk, char * pName );
+extern Abc_Obj_t * Abc_NtkFindNet( Abc_Ntk_t * pNtk, char * pName );
+extern Abc_Obj_t * Abc_NtkFindCi( Abc_Ntk_t * pNtk, char * pName );
+extern Abc_Obj_t * Abc_NtkFindCo( Abc_Ntk_t * pNtk, char * pName );
+extern Abc_Obj_t * Abc_NtkFindOrCreateNet( Abc_Ntk_t * pNtk, char * pName );
+extern Abc_Obj_t * Abc_NtkCreateNodeConst0( Abc_Ntk_t * pNtk );
+extern Abc_Obj_t * Abc_NtkCreateNodeConst1( Abc_Ntk_t * pNtk );
+extern Abc_Obj_t * Abc_NtkCreateNodeInv( Abc_Ntk_t * pNtk, Abc_Obj_t * pFanin );
+extern Abc_Obj_t * Abc_NtkCreateNodeBuf( Abc_Ntk_t * pNtk, Abc_Obj_t * pFanin );
+extern Abc_Obj_t * Abc_NtkCreateNodeAnd( Abc_Ntk_t * pNtk, Vec_Ptr_t * vFanins );
+extern Abc_Obj_t * Abc_NtkCreateNodeOr( Abc_Ntk_t * pNtk, Vec_Ptr_t * vFanins );
+extern Abc_Obj_t * Abc_NtkCreateNodeExor( Abc_Ntk_t * pNtk, Vec_Ptr_t * vFanins );
+extern Abc_Obj_t * Abc_NtkCreateNodeMux( Abc_Ntk_t * pNtk, Abc_Obj_t * pNodeC, Abc_Obj_t * pNode1, Abc_Obj_t * pNode0 );
+extern bool Abc_NodeIsConst( Abc_Obj_t * pNode );
+extern bool Abc_NodeIsConst0( Abc_Obj_t * pNode );
+extern bool Abc_NodeIsConst1( Abc_Obj_t * pNode );
+extern bool Abc_NodeIsBuf( Abc_Obj_t * pNode );
+extern bool Abc_NodeIsInv( Abc_Obj_t * pNode );
+extern void Abc_NodeComplement( Abc_Obj_t * pNode );
/*=== abcPrint.c ==========================================================*/
extern void Abc_NtkPrintStats( FILE * pFile, Abc_Ntk_t * pNtk, int fFactored );
extern void Abc_NtkPrintIo( FILE * pFile, Abc_Ntk_t * pNtk );
@@ -544,12 +737,29 @@ extern void Abc_NtkPrintFanio( FILE * pFile, Abc_Ntk_t * pNtk );
extern void Abc_NodePrintFanio( FILE * pFile, Abc_Obj_t * pNode );
extern void Abc_NtkPrintFactor( FILE * pFile, Abc_Ntk_t * pNtk, int fUseRealNames );
extern void Abc_NodePrintFactor( FILE * pFile, Abc_Obj_t * pNode, int fUseRealNames );
-extern void Abc_NtkPrintLevel( FILE * pFile, Abc_Ntk_t * pNtk, int fProfile );
+extern void Abc_NtkPrintLevel( FILE * pFile, Abc_Ntk_t * pNtk, int fProfile, int fListNodes );
extern void Abc_NodePrintLevel( FILE * pFile, Abc_Obj_t * pNode );
+extern void Abc_NtkPrintSkews( FILE * pFile, Abc_Ntk_t * pNtk, int fPrintAll );
+extern void Abc_ObjPrint( FILE * pFile, Abc_Obj_t * pObj );
+/*=== abcProve.c ==========================================================*/
+extern int Abc_NtkMiterProve( Abc_Ntk_t ** ppNtk, void * pParams );
+extern int Abc_NtkIvyProve( Abc_Ntk_t ** ppNtk, void * pPars );
+/*=== abcRec.c ==========================================================*/
+extern void Abc_NtkRecStart( Abc_Ntk_t * pNtk, int nVars, int nCuts );
+extern void Abc_NtkRecStop();
+extern void Abc_NtkRecAdd( Abc_Ntk_t * pNtk );
+extern void Abc_NtkRecPs();
+extern void Abc_NtkRecFilter( int iVar, int iPlus );
+extern Abc_Ntk_t * Abc_NtkRecUse();
+extern int Abc_NtkRecIsRunning();
+extern int Abc_NtkRecVarNum();
+extern Vec_Int_t * Abc_NtkRecMemory();
+extern int Abc_NtkRecStrashNode( Abc_Ntk_t * pNtkNew, Abc_Obj_t * pObj, unsigned * pTruth, int nVars );
/*=== abcReconv.c ==========================================================*/
extern Abc_ManCut_t * Abc_NtkManCutStart( int nNodeSizeMax, int nConeSizeMax, int nNodeFanStop, int nConeFanStop );
extern void Abc_NtkManCutStop( Abc_ManCut_t * p );
extern Vec_Ptr_t * Abc_NtkManCutReadCutLarge( Abc_ManCut_t * p );
+extern Vec_Ptr_t * Abc_NtkManCutReadCutSmall( Abc_ManCut_t * p );
extern Vec_Ptr_t * Abc_NtkManCutReadVisited( Abc_ManCut_t * p );
extern Vec_Ptr_t * Abc_NodeFindCut( Abc_ManCut_t * p, Abc_Obj_t * pRoot, bool fContain );
extern void Abc_NodeConeCollect( Abc_Obj_t ** ppRoots, int nRoots, Vec_Ptr_t * vFanins, Vec_Ptr_t * vVisited, int fIncludeFanins );
@@ -558,37 +768,39 @@ extern DdNode * Abc_NodeConeDcs( DdManager * dd, DdNode ** pbVarsX, Dd
extern Vec_Ptr_t * Abc_NodeCollectTfoCands( Abc_ManCut_t * p, Abc_Obj_t * pRoot, Vec_Ptr_t * vFanins, int LevelMax );
/*=== abcRefs.c ==========================================================*/
extern int Abc_NodeMffcSize( Abc_Obj_t * pNode );
+extern int Abc_NodeMffcSizeSupp( Abc_Obj_t * pNode );
extern int Abc_NodeMffcSizeStop( Abc_Obj_t * pNode );
+extern int Abc_NodeMffcLabelAig( Abc_Obj_t * pNode );
extern int Abc_NodeMffcLabel( Abc_Obj_t * pNode );
-extern Vec_Ptr_t * Abc_NodeMffcCollect( Abc_Obj_t * pNode );
-/*=== abcRenode.c ==========================================================*/
-extern Abc_Ntk_t * Abc_NtkRenode( Abc_Ntk_t * pNtk, int nThresh, int nFaninMax, int fCnf, int fMulti, int fSimple );
-extern DdNode * Abc_NtkRenodeDeriveBdd( DdManager * dd, Abc_Obj_t * pNodeOld, Vec_Ptr_t * vFaninsOld );
+extern void Abc_NodeMffsConeSupp( Abc_Obj_t * pNode, Vec_Ptr_t * vCone, Vec_Ptr_t * vSupp );
+extern int Abc_NodeDeref_rec( Abc_Obj_t * pNode );
+extern int Abc_NodeRef_rec( Abc_Obj_t * pNode );
+/*=== abcRefactor.c ==========================================================*/
+extern int Abc_NtkRefactor( Abc_Ntk_t * pNtk, int nNodeSizeMax, int nConeSizeMax, bool fUpdateLevel, bool fUseZeros, bool fUseDcs, bool fVerbose );
+/*=== abcRewrite.c ==========================================================*/
+extern int Abc_NtkRewrite( Abc_Ntk_t * pNtk, int fUpdateLevel, int fUseZeros, int fVerbose, int fVeryVerbose, int fPlaceEnable );
/*=== abcSat.c ==========================================================*/
-extern bool Abc_NtkMiterSat( Abc_Ntk_t * pNtk, int fVerbose );
-extern solver * Abc_NtkMiterSatCreate( Abc_Ntk_t * pNtk );
-/*=== abcSeq.c ==========================================================*/
-extern Abc_Ntk_t * Abc_NtkAigToSeq( Abc_Ntk_t * pNtk );
-extern Abc_Ntk_t * Abc_NtkSeqToLogicSop( Abc_Ntk_t * pNtk );
-extern int Abc_NtkSeqLatchNum( Abc_Ntk_t * pNtk );
-extern void Abc_NtkSeqRetimeForward( Abc_Ntk_t * pNtk );
-extern void Abc_NtkSeqRetimeBackward( Abc_Ntk_t * pNtk );
-extern void Abc_NtkSeqRetimeDelay( Abc_Ntk_t * pNtk );
+extern int Abc_NtkMiterSat( Abc_Ntk_t * pNtk, sint64 nConfLimit, sint64 nInsLimit, int fVerbose, sint64 * pNumConfs, sint64 * pNumInspects );
+extern void * Abc_NtkMiterSatCreate( Abc_Ntk_t * pNtk, int fAllPrimes );
/*=== abcSop.c ==========================================================*/
extern char * Abc_SopRegister( Extra_MmFlex_t * pMan, char * pName );
extern char * Abc_SopStart( Extra_MmFlex_t * pMan, int nCubes, int nVars );
extern char * Abc_SopCreateConst0( Extra_MmFlex_t * pMan );
extern char * Abc_SopCreateConst1( Extra_MmFlex_t * pMan );
extern char * Abc_SopCreateAnd2( Extra_MmFlex_t * pMan, int fCompl0, int fCompl1 );
-extern char * Abc_SopCreateAnd( Extra_MmFlex_t * pMan, int nVars );
+extern char * Abc_SopCreateAnd( Extra_MmFlex_t * pMan, int nVars, int * pfCompl );
extern char * Abc_SopCreateNand( Extra_MmFlex_t * pMan, int nVars );
extern char * Abc_SopCreateOr( Extra_MmFlex_t * pMan, int nVars, int * pfCompl );
extern char * Abc_SopCreateOrMultiCube( Extra_MmFlex_t * pMan, int nVars, int * pfCompl );
extern char * Abc_SopCreateNor( Extra_MmFlex_t * pMan, int nVars );
extern char * Abc_SopCreateXor( Extra_MmFlex_t * pMan, int nVars );
+extern char * Abc_SopCreateXorSpecial( Extra_MmFlex_t * pMan, int nVars );
extern char * Abc_SopCreateNxor( Extra_MmFlex_t * pMan, int nVars );
+extern char * Abc_SopCreateMux( Extra_MmFlex_t * pMan );
extern char * Abc_SopCreateInv( Extra_MmFlex_t * pMan );
extern char * Abc_SopCreateBuf( Extra_MmFlex_t * pMan );
+extern char * Abc_SopCreateFromTruth( Extra_MmFlex_t * pMan, int nVars, unsigned * pTruth );
+extern char * Abc_SopCreateFromIsop( Extra_MmFlex_t * pMan, int nVars, Vec_Int_t * vCover );
extern int Abc_SopGetCubeNum( char * pSop );
extern int Abc_SopGetLitNum( char * pSop );
extern int Abc_SopGetVarNum( char * pSop );
@@ -602,17 +814,23 @@ extern bool Abc_SopIsBuf( char * pSop );
extern bool Abc_SopIsInv( char * pSop );
extern bool Abc_SopIsAndType( char * pSop );
extern bool Abc_SopIsOrType( char * pSop );
+extern int Abc_SopIsExorType( char * pSop );
extern bool Abc_SopCheck( char * pSop, int nFanins );
-extern void Abc_SopWriteCnf( FILE * pFile, char * pClauses, Vec_Int_t * vVars );
-extern void Abc_SopAddCnfToSolver( solver * pSat, char * pClauses, Vec_Int_t * vVars, Vec_Int_t * vTemp );
+extern char * Abc_SopFromTruthBin( char * pTruth );
+extern char * Abc_SopFromTruthHex( char * pTruth );
+extern char * Abc_SopEncoderPos( Extra_MmFlex_t * pMan, int iValue, int nValues );
+extern char * Abc_SopEncoderLog( Extra_MmFlex_t * pMan, int iBit, int nValues );
+extern char * Abc_SopDecoderPos( Extra_MmFlex_t * pMan, int nValues );
+extern char * Abc_SopDecoderLog( Extra_MmFlex_t * pMan, int nValues );
/*=== abcStrash.c ==========================================================*/
-extern Abc_Ntk_t * Abc_NtkStrash( Abc_Ntk_t * pNtk, bool fAllNodes, bool fCleanup );
-extern Abc_Obj_t * Abc_NodeStrash( Abc_Aig_t * pMan, Abc_Obj_t * pNode );
-extern int Abc_NtkAppend( Abc_Ntk_t * pNtk1, Abc_Ntk_t * pNtk2 );
+extern Abc_Ntk_t * Abc_NtkStrash( Abc_Ntk_t * pNtk, int fAllNodes, int fCleanup, int fRecord );
+extern Abc_Obj_t * Abc_NodeStrash( Abc_Ntk_t * pNtkNew, Abc_Obj_t * pNode, int fRecord );
+extern int Abc_NtkAppend( Abc_Ntk_t * pNtk1, Abc_Ntk_t * pNtk2, int fAddPos );
+extern Abc_Ntk_t * Abc_NtkTopmost( Abc_Ntk_t * pNtk, int nLevels );
/*=== abcSweep.c ==========================================================*/
-extern bool Abc_NtkFraigSweep( Abc_Ntk_t * pNtk, int fUseInv, int fVerbose );
-extern int Abc_NtkCleanup( Abc_Ntk_t * pNtk, int fVerbose );
extern int Abc_NtkSweep( Abc_Ntk_t * pNtk, int fVerbose );
+extern int Abc_NtkCleanup( Abc_Ntk_t * pNtk, int fVerbose );
+extern int Abc_NtkCleanupSeq( Abc_Ntk_t * pNtk, int fLatchSweep, int fAutoSweep, int fVerbose );
/*=== abcTiming.c ==========================================================*/
extern Abc_Time_t * Abc_NodeReadArrival( Abc_Obj_t * pNode );
extern Abc_Time_t * Abc_NodeReadRequired( Abc_Obj_t * pNode );
@@ -629,41 +847,73 @@ extern void Abc_NtkSetNodeLevelsArrival( Abc_Ntk_t * pNtk );
extern float * Abc_NtkGetCiArrivalFloats( Abc_Ntk_t * pNtk );
extern Abc_Time_t * Abc_NtkGetCiArrivalTimes( Abc_Ntk_t * pNtk );
extern float Abc_NtkDelayTrace( Abc_Ntk_t * pNtk );
-extern void Abc_NtkStartReverseLevels( Abc_Ntk_t * pNtk );
+extern int Abc_ObjLevelNew( Abc_Obj_t * pObj );
+extern int Abc_ObjReverseLevelNew( Abc_Obj_t * pObj );
+extern int Abc_ObjRequiredLevel( Abc_Obj_t * pObj );
+extern int Abc_ObjReverseLevel( Abc_Obj_t * pObj );
+extern void Abc_ObjSetReverseLevel( Abc_Obj_t * pObj, int LevelR );
+extern void Abc_NtkStartReverseLevels( Abc_Ntk_t * pNtk, int nMaxLevelIncrease );
extern void Abc_NtkStopReverseLevels( Abc_Ntk_t * pNtk );
-extern void Abc_NodeSetReverseLevel( Abc_Obj_t * pObj, int LevelR );
-extern int Abc_NodeReadReverseLevel( Abc_Obj_t * pObj );
-extern int Abc_NodeReadRequiredLevel( Abc_Obj_t * pObj );
+extern void Abc_NtkUpdateLevel( Abc_Obj_t * pObjNew, Vec_Vec_t * vLevels );
+extern void Abc_NtkUpdateReverseLevel( Abc_Obj_t * pObjNew, Vec_Vec_t * vLevels );
+extern void Abc_NtkUpdate( Abc_Obj_t * pObj, Abc_Obj_t * pObjNew, Vec_Vec_t * vLevels );
/*=== abcUtil.c ==========================================================*/
+extern void * Abc_NtkAttrFree( Abc_Ntk_t * pNtk, int Attr, int fFreeMan );
extern void Abc_NtkIncrementTravId( Abc_Ntk_t * pNtk );
+extern void Abc_NtkOrderCisCos( Abc_Ntk_t * pNtk );
extern int Abc_NtkGetCubeNum( Abc_Ntk_t * pNtk );
+extern int Abc_NtkGetCubePairNum( Abc_Ntk_t * pNtk );
extern int Abc_NtkGetLitNum( Abc_Ntk_t * pNtk );
extern int Abc_NtkGetLitFactNum( Abc_Ntk_t * pNtk );
extern int Abc_NtkGetBddNodeNum( Abc_Ntk_t * pNtk );
+extern int Abc_NtkGetAigNodeNum( Abc_Ntk_t * pNtk );
extern int Abc_NtkGetClauseNum( Abc_Ntk_t * pNtk );
extern double Abc_NtkGetMappedArea( Abc_Ntk_t * pNtk );
extern int Abc_NtkGetExorNum( Abc_Ntk_t * pNtk );
+extern int Abc_NtkGetMuxNum( Abc_Ntk_t * pNtk );
extern int Abc_NtkGetChoiceNum( Abc_Ntk_t * pNtk );
extern int Abc_NtkGetFaninMax( Abc_Ntk_t * pNtk );
+extern int Abc_NtkGetTotalFanins( Abc_Ntk_t * pNtk );
extern void Abc_NtkCleanCopy( Abc_Ntk_t * pNtk );
+extern void Abc_NtkCleanData( Abc_Ntk_t * pNtk );
+extern void Abc_NtkCleanEquiv( Abc_Ntk_t * pNtk );
+extern int Abc_NtkCountCopy( Abc_Ntk_t * pNtk );
+extern Vec_Ptr_t * Abc_NtkSaveCopy( Abc_Ntk_t * pNtk );
+extern void Abc_NtkLoadCopy( Abc_Ntk_t * pNtk, Vec_Ptr_t * vCopies );
+extern void Abc_NtkCleanNext( Abc_Ntk_t * pNtk );
+extern void Abc_NtkCleanMarkA( Abc_Ntk_t * pNtk );
+extern Abc_Obj_t * Abc_NodeFindCoFanout( Abc_Obj_t * pNode );
+extern Abc_Obj_t * Abc_NodeFindNonCoFanout( Abc_Obj_t * pNode );
extern Abc_Obj_t * Abc_NodeHasUniqueCoFanout( Abc_Obj_t * pNode );
extern bool Abc_NtkLogicHasSimpleCos( Abc_Ntk_t * pNtk );
extern int Abc_NtkLogicMakeSimpleCos( Abc_Ntk_t * pNtk, bool fDuplicate );
extern void Abc_VecObjPushUniqueOrderByLevel( Vec_Ptr_t * p, Abc_Obj_t * pNode );
extern bool Abc_NodeIsExorType( Abc_Obj_t * pNode );
extern bool Abc_NodeIsMuxType( Abc_Obj_t * pNode );
+extern bool Abc_NodeIsMuxControlType( Abc_Obj_t * pNode );
extern Abc_Obj_t * Abc_NodeRecognizeMux( Abc_Obj_t * pNode, Abc_Obj_t ** ppNodeT, Abc_Obj_t ** ppNodeE );
extern int Abc_NtkPrepareTwoNtks( FILE * pErr, Abc_Ntk_t * pNtk, char ** argv, int argc, Abc_Ntk_t ** ppNtk1, Abc_Ntk_t ** ppNtk2, int * pfDelete1, int * pfDelete2 );
extern void Abc_NodeCollectFanins( Abc_Obj_t * pNode, Vec_Ptr_t * vNodes );
extern void Abc_NodeCollectFanouts( Abc_Obj_t * pNode, Vec_Ptr_t * vNodes );
+extern Vec_Ptr_t * Abc_NtkCollectLatches( Abc_Ntk_t * pNtk );
extern int Abc_NodeCompareLevelsIncrease( Abc_Obj_t ** pp1, Abc_Obj_t ** pp2 );
extern int Abc_NodeCompareLevelsDecrease( Abc_Obj_t ** pp1, Abc_Obj_t ** pp2 );
extern Vec_Int_t * Abc_NtkFanoutCounts( Abc_Ntk_t * pNtk );
extern Vec_Ptr_t * Abc_NtkCollectObjects( Abc_Ntk_t * pNtk );
+extern Vec_Int_t * Abc_NtkGetCiIds( Abc_Ntk_t * pNtk );
+extern void Abc_NtkReassignIds( Abc_Ntk_t * pNtk );
+extern int Abc_ObjPointerCompare( void ** pp1, void ** pp2 );
+extern void Abc_NtkTransferCopy( Abc_Ntk_t * pNtk );
+/*=== abcVerify.c ==========================================================*/
+extern int * Abc_NtkVerifyGetCleanModel( Abc_Ntk_t * pNtk, int nFrames );
+extern int * Abc_NtkVerifySimulatePattern( Abc_Ntk_t * pNtk, int * pModel );
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
////////////////////////////////////////////////////////////////////////
/// END OF FILE ///
////////////////////////////////////////////////////////////////////////
-
-#endif
-
diff --git a/src/base/abc/abcAig.c b/src/base/abc/abcAig.c
index 1d8931ec..16f66dc6 100644
--- a/src/base/abc/abcAig.c
+++ b/src/base/abc/abcAig.c
@@ -30,6 +30,8 @@
- there are no dangling nodes (the nodes without fanout)
- the level of each AND gate reflects the levels of this fanins
- the EXOR-status of each node is up-to-date
+ - the AND nodes are in the topological order
+ - the constant 1 node has always number 0 in the object list
The operations that are performed on AIGs:
- building new nodes (Abc_AigAnd)
- performing elementary Boolean operations (Abc_AigOr, Abc_AigXor, etc)
@@ -48,17 +50,22 @@
struct Abc_Aig_t_
{
Abc_Ntk_t * pNtkAig; // the AIG network
- Abc_Obj_t * pConst1; // the constant 1 node
- Abc_Obj_t * pReset; // the sequential reset node
+ Abc_Obj_t * pConst1; // the constant 1 object (not a node!)
Abc_Obj_t ** pBins; // the table bins
int nBins; // the size of the table
int nEntries; // the total number of entries in the table
Vec_Ptr_t * vNodes; // the temporary array of nodes
- Vec_Ptr_t * vStackDelete; // the nodes to be deleted
Vec_Ptr_t * vStackReplaceOld; // the nodes to be replaced
Vec_Ptr_t * vStackReplaceNew; // the nodes to be used for replacement
Vec_Vec_t * vLevels; // the nodes to be updated
Vec_Vec_t * vLevelsR; // the nodes to be updated
+ Vec_Ptr_t * vAddedCells; // the added nodes
+ Vec_Ptr_t * vUpdatedNets; // the nodes whose fanouts have changed
+
+ int nStrash0;
+ int nStrash1;
+ int nStrash5;
+ int nStrash2;
};
// iterators through the entries in the linked lists of nodes
@@ -74,24 +81,34 @@ struct Abc_Aig_t_
pEnt2 = pEnt? pEnt->pNext: NULL )
// hash key for the structural hash table
-static inline unsigned Abc_HashKey2( Abc_Obj_t * p0, Abc_Obj_t * p1, int TableSize ) { return ((unsigned)(p0) + (unsigned)(p1) * 12582917) % TableSize; }
+//static inline unsigned Abc_HashKey2( Abc_Obj_t * p0, Abc_Obj_t * p1, int TableSize ) { return ((unsigned)(p0) + (unsigned)(p1) * 12582917) % TableSize; }
//static inline unsigned Abc_HashKey2( Abc_Obj_t * p0, Abc_Obj_t * p1, int TableSize ) { return ((unsigned)((a)->Id + (b)->Id) * ((a)->Id + (b)->Id + 1) / 2) % TableSize; }
+// hashing the node
+static unsigned Abc_HashKey2( Abc_Obj_t * p0, Abc_Obj_t * p1, int TableSize )
+{
+ unsigned Key = 0;
+ Key ^= Abc_ObjRegular(p0)->Id * 7937;
+ Key ^= Abc_ObjRegular(p1)->Id * 2971;
+ Key ^= Abc_ObjIsComplement(p0) * 911;
+ Key ^= Abc_ObjIsComplement(p1) * 353;
+ return Key % TableSize;
+}
+
// structural hash table procedures
static Abc_Obj_t * Abc_AigAndCreate( Abc_Aig_t * pMan, Abc_Obj_t * p0, Abc_Obj_t * p1 );
static Abc_Obj_t * Abc_AigAndCreateFrom( Abc_Aig_t * pMan, Abc_Obj_t * p0, Abc_Obj_t * p1, Abc_Obj_t * pAnd );
static void Abc_AigAndDelete( Abc_Aig_t * pMan, Abc_Obj_t * pThis );
static void Abc_AigResize( Abc_Aig_t * pMan );
// incremental AIG procedures
-static void Abc_AigReplace_int( Abc_Aig_t * pMan );
-static void Abc_AigDelete_int( Abc_Aig_t * pMan );
+static void Abc_AigReplace_int( Abc_Aig_t * pMan, Abc_Obj_t * pOld, Abc_Obj_t * pNew, int fUpdateLevel );
static void Abc_AigUpdateLevel_int( Abc_Aig_t * pMan );
static void Abc_AigUpdateLevelR_int( Abc_Aig_t * pMan );
static void Abc_AigRemoveFromLevelStructure( Vec_Vec_t * vStruct, Abc_Obj_t * pNode );
static void Abc_AigRemoveFromLevelStructureR( Vec_Vec_t * vStruct, Abc_Obj_t * pNode );
////////////////////////////////////////////////////////////////////////
-/// FUNCTION DEFITIONS ///
+/// FUNCTION DEFINITIONS ///
////////////////////////////////////////////////////////////////////////
/**Function*************************************************************
@@ -116,83 +133,23 @@ Abc_Aig_t * Abc_AigAlloc( Abc_Ntk_t * pNtkAig )
pMan->pBins = ALLOC( Abc_Obj_t *, pMan->nBins );
memset( pMan->pBins, 0, sizeof(Abc_Obj_t *) * pMan->nBins );
pMan->vNodes = Vec_PtrAlloc( 100 );
- pMan->vStackDelete = Vec_PtrAlloc( 100 );
+ pMan->vLevels = Vec_VecAlloc( 100 );
+ pMan->vLevelsR = Vec_VecAlloc( 100 );
pMan->vStackReplaceOld = Vec_PtrAlloc( 100 );
pMan->vStackReplaceNew = Vec_PtrAlloc( 100 );
- pMan->vLevels = Vec_VecAlloc( 100 );
- pMan->vLevelsR = Vec_VecAlloc( 100 );
+ // create the constant node
+ assert( pNtkAig->vObjs->nSize == 0 );
+ pMan->pConst1 = Abc_NtkCreateObj( pNtkAig, ABC_OBJ_NODE );
+ pMan->pConst1->Type = ABC_OBJ_CONST1;
+ pMan->pConst1->fPhase = 1;
+ pNtkAig->nObjCounts[ABC_OBJ_NODE]--;
// save the current network
pMan->pNtkAig = pNtkAig;
- // allocate constant nodes
- pMan->pConst1 = Abc_NtkCreateNode( pNtkAig );
- pMan->pConst1->fPhase = 1;
- pMan->pReset = Abc_NtkCreateNode( pNtkAig );
- // subtract these nodes from the total number
- pNtkAig->nNodes -= 2;
return pMan;
}
/**Function*************************************************************
- Synopsis [Duplicated the AIG manager.]
-
- Description [Assumes that CI/CO nodes are already created.
- Transfers the latch attributes on the edges.]
-
- SideEffects []
-
- SeeAlso []
-
-***********************************************************************/
-Abc_Aig_t * Abc_AigDup( Abc_Aig_t * pMan, Abc_Aig_t * pManNew )
-{
- Vec_Ptr_t * vNodes;
- Abc_Obj_t * pObj;
- int i;
- assert( Abc_NtkCiNum(pMan->pNtkAig) == Abc_NtkCiNum(pManNew->pNtkAig) );
- assert( Abc_NtkCoNum(pMan->pNtkAig) == Abc_NtkCoNum(pManNew->pNtkAig) );
- assert( Abc_NtkLatchNum(pMan->pNtkAig) == Abc_NtkLatchNum(pManNew->pNtkAig) );
- // set mapping of the constant nodes
- Abc_AigConst1( pMan )->pCopy = Abc_AigConst1( pManNew );
- Abc_AigReset( pMan )->pCopy = Abc_AigReset( pManNew );
- // set the mapping of CIs/COs
- Abc_NtkForEachPi( pMan->pNtkAig, pObj, i )
- pObj->pCopy = Abc_NtkPi( pManNew->pNtkAig, i );
- Abc_NtkForEachPo( pMan->pNtkAig, pObj, i )
- pObj->pCopy = Abc_NtkPo( pManNew->pNtkAig, i );
- Abc_NtkForEachLatch( pMan->pNtkAig, pObj, i )
- pObj->pCopy = Abc_NtkLatch( pManNew->pNtkAig, i );
- // copy internal nodes
- vNodes = Abc_AigDfs( pMan->pNtkAig, 1, 0 );
- Vec_PtrForEachEntry( vNodes, pObj, i )
- {
- if ( !Abc_NodeIsAigAnd(pObj) )
- continue;
- pObj->pCopy = Abc_AigAnd( pManNew, Abc_ObjChild0Copy(pObj), Abc_ObjChild1Copy(pObj) );
- // transfer latch attributes
- Abc_ObjSetFaninL0( pObj->pCopy, Abc_ObjFaninL0(pObj) );
- Abc_ObjSetFaninL1( pObj->pCopy, Abc_ObjFaninL1(pObj) );
- }
- // relink the choice nodes
- Vec_PtrForEachEntry( vNodes, pObj, i )
- if ( pObj->pData )
- pObj->pCopy->pData = ((Abc_Obj_t *)pObj->pData)->pCopy;
- Vec_PtrFree( vNodes );
- // relink the CO nodes
- Abc_NtkForEachCo( pMan->pNtkAig, pObj, i )
- {
- Abc_ObjAddFanin( pObj->pCopy, Abc_ObjChild0Copy(pObj) );
- Abc_ObjSetFaninL0( pObj->pCopy, Abc_ObjFaninL0(pObj) );
- }
- // get the number of nodes before and after
- if ( Abc_NtkNodeNum(pMan->pNtkAig) != Abc_NtkNodeNum(pManNew->pNtkAig) )
- printf( "Warning: Structural hashing reduced %d nodes (should not happen).\n",
- Abc_NtkNodeNum(pMan->pNtkAig) - Abc_NtkNodeNum(pManNew->pNtkAig) );
- return pManNew;
-}
-
-/**Function*************************************************************
-
Synopsis [Deallocates the local AIG manager.]
Description []
@@ -204,13 +161,15 @@ Abc_Aig_t * Abc_AigDup( Abc_Aig_t * pMan, Abc_Aig_t * pManNew )
***********************************************************************/
void Abc_AigFree( Abc_Aig_t * pMan )
{
- assert( Vec_PtrSize( pMan->vStackDelete ) == 0 );
assert( Vec_PtrSize( pMan->vStackReplaceOld ) == 0 );
assert( Vec_PtrSize( pMan->vStackReplaceNew ) == 0 );
// free the table
+ if ( pMan->vAddedCells )
+ Vec_PtrFree( pMan->vAddedCells );
+ if ( pMan->vUpdatedNets )
+ Vec_PtrFree( pMan->vUpdatedNets );
Vec_VecFree( pMan->vLevels );
Vec_VecFree( pMan->vLevelsR );
- Vec_PtrFree( pMan->vStackDelete );
Vec_PtrFree( pMan->vStackReplaceOld );
Vec_PtrFree( pMan->vStackReplaceNew );
Vec_PtrFree( pMan->vNodes );
@@ -231,18 +190,23 @@ void Abc_AigFree( Abc_Aig_t * pMan )
***********************************************************************/
int Abc_AigCleanup( Abc_Aig_t * pMan )
{
+ Vec_Ptr_t * vDangles;
Abc_Obj_t * pAnd;
- int i, Counter;
+ int i, nNodesOld;
+// printf( "Strash0 = %d. Strash1 = %d. Strash100 = %d. StrashM = %d.\n",
+// pMan->nStrash0, pMan->nStrash1, pMan->nStrash5, pMan->nStrash2 );
+ nNodesOld = pMan->nEntries;
// collect the AND nodes that do not fanout
- assert( Vec_PtrSize( pMan->vStackDelete ) == 0 );
+ vDangles = Vec_PtrAlloc( 100 );
for ( i = 0; i < pMan->nBins; i++ )
Abc_AigBinForEachEntry( pMan->pBins[i], pAnd )
if ( Abc_ObjFanoutNum(pAnd) == 0 )
- Vec_PtrPush( pMan->vStackDelete, pAnd );
+ Vec_PtrPush( vDangles, pAnd );
// process the dangling nodes and their MFFCs
- for ( Counter = 0; Vec_PtrSize(pMan->vStackDelete) > 0; Counter++ )
- Abc_AigDelete_int( pMan );
- return Counter;
+ Vec_PtrForEachEntry( vDangles, pAnd, i )
+ Abc_AigDeleteNode( pMan, pAnd );
+ Vec_PtrFree( vDangles );
+ return nNodesOld - pMan->nEntries;
}
/**Function*************************************************************
@@ -265,7 +229,7 @@ bool Abc_AigCheck( Abc_Aig_t * pMan )
nFanins = Abc_ObjFaninNum(pObj);
if ( nFanins == 0 )
{
- if ( pObj != pMan->pConst1 && pObj != pMan->pReset )
+ if ( !Abc_AigNodeIsConst(pObj) )
{
printf( "Abc_AigCheck: The AIG has non-standard constant nodes.\n" );
return 0;
@@ -298,6 +262,16 @@ bool Abc_AigCheck( Abc_Aig_t * pMan )
printf( "Abc_AigCheck: The number of nodes in the structural hashing table is wrong.\n" );
return 0;
}
+ // if the node is a choice node, nodes in its class should not have fanouts
+ Abc_NtkForEachNode( pMan->pNtkAig, pObj, i )
+ if ( Abc_AigNodeIsChoice(pObj) )
+ for ( pAnd = pObj->pData; pAnd; pAnd = pAnd->pData )
+ if ( Abc_ObjFanoutNum(pAnd) > 0 )
+ {
+ printf( "Abc_AigCheck: Representative %s", Abc_ObjName(pAnd) );
+ printf( " of choice node %s has %d fanouts.\n", Abc_ObjName(pObj), Abc_ObjFanoutNum(pAnd) );
+ return 0;
+ }
return 1;
}
@@ -312,7 +286,7 @@ bool Abc_AigCheck( Abc_Aig_t * pMan )
SeeAlso []
***********************************************************************/
-int Abc_AigGetLevelNum( Abc_Ntk_t * pNtk )
+int Abc_AigLevel( Abc_Ntk_t * pNtk )
{
Abc_Obj_t * pNode;
int i, LevelsMax;
@@ -325,39 +299,6 @@ int Abc_AigGetLevelNum( Abc_Ntk_t * pNtk )
return LevelsMax;
}
-/**Function*************************************************************
-
- Synopsis [Read the constant 1 node.]
-
- Description []
-
- SideEffects []
-
- SeeAlso []
-
-***********************************************************************/
-Abc_Obj_t * Abc_AigConst1( Abc_Aig_t * pMan )
-{
- return pMan->pConst1;
-}
-
-/**Function*************************************************************
-
- Synopsis [Read the reset node.]
-
- Description []
-
- SideEffects []
-
- SeeAlso []
-
-***********************************************************************/
-Abc_Obj_t * Abc_AigReset( Abc_Aig_t * pMan )
-{
- return pMan->pReset;
-}
-
-
/**Function*************************************************************
@@ -385,9 +326,9 @@ Abc_Obj_t * Abc_AigAndCreate( Abc_Aig_t * pMan, Abc_Obj_t * p0, Abc_Obj_t * p1 )
Abc_ObjAddFanin( pAnd, p0 );
Abc_ObjAddFanin( pAnd, p1 );
// set the level of the new node
- pAnd->Level = 1 + ABC_MAX( Abc_ObjRegular(p0)->Level, Abc_ObjRegular(p1)->Level );
- pAnd->fExor = Abc_NodeIsExorType(pAnd);
- pAnd->fPhase = (Abc_ObjIsComplement(p0) ^ Abc_ObjRegular(p0)->fPhase) & (Abc_ObjIsComplement(p1) ^ Abc_ObjRegular(p1)->fPhase);
+ pAnd->Level = 1 + ABC_MAX( Abc_ObjRegular(p0)->Level, Abc_ObjRegular(p1)->Level );
+ pAnd->fExor = Abc_NodeIsExorType(pAnd);
+ pAnd->fPhase = (Abc_ObjIsComplement(p0) ^ Abc_ObjRegular(p0)->fPhase) & (Abc_ObjIsComplement(p1) ^ Abc_ObjRegular(p1)->fPhase);
// add the node to the corresponding linked list in the table
Key = Abc_HashKey2( p0, p1, pMan->nBins );
pAnd->pNext = pMan->pBins[Key];
@@ -396,6 +337,13 @@ Abc_Obj_t * Abc_AigAndCreate( Abc_Aig_t * pMan, Abc_Obj_t * p0, Abc_Obj_t * p1 )
// create the cuts if defined
// if ( pAnd->pNtk->pManCut )
// Abc_NodeGetCuts( pAnd->pNtk->pManCut, pAnd );
+ pAnd->pCopy = NULL;
+ // add the node to the list of updated nodes
+ if ( pMan->vAddedCells )
+ Vec_PtrPush( pMan->vAddedCells, pAnd );
+ // create HAIG
+ if ( pAnd->pNtk->pHaig )
+ pAnd->pEquiv = Hop_And( pAnd->pNtk->pHaig, Abc_ObjChild0Equiv(pAnd), Abc_ObjChild1Equiv(pAnd) );
return pAnd;
}
@@ -428,9 +376,17 @@ Abc_Obj_t * Abc_AigAndCreateFrom( Abc_Aig_t * pMan, Abc_Obj_t * p0, Abc_Obj_t *
Key = Abc_HashKey2( p0, p1, pMan->nBins );
pAnd->pNext = pMan->pBins[Key];
pMan->pBins[Key] = pAnd;
+ pMan->nEntries++;
// create the cuts if defined
// if ( pAnd->pNtk->pManCut )
// Abc_NodeGetCuts( pAnd->pNtk->pManCut, pAnd );
+ pAnd->pCopy = NULL;
+ // add the node to the list of updated nodes
+// if ( pMan->vAddedCells )
+// Vec_PtrPush( pMan->vAddedCells, pAnd );
+ // create HAIG
+ if ( pAnd->pNtk->pHaig )
+ pAnd->pEquiv = Hop_And( pAnd->pNtk->pHaig, Abc_ObjChild0Equiv(pAnd), Abc_ObjChild1Equiv(pAnd) );
return pAnd;
}
@@ -447,25 +403,49 @@ Abc_Obj_t * Abc_AigAndCreateFrom( Abc_Aig_t * pMan, Abc_Obj_t * p0, Abc_Obj_t *
***********************************************************************/
Abc_Obj_t * Abc_AigAndLookup( Abc_Aig_t * pMan, Abc_Obj_t * p0, Abc_Obj_t * p1 )
{
- Abc_Obj_t * pAnd;
+ Abc_Obj_t * pAnd, * pConst1;
unsigned Key;
+ assert( Abc_ObjRegular(p0)->pNtk->pManFunc == pMan );
+ assert( Abc_ObjRegular(p1)->pNtk->pManFunc == pMan );
// check for trivial cases
+ pConst1 = Abc_AigConst1(pMan->pNtkAig);
if ( p0 == p1 )
return p0;
if ( p0 == Abc_ObjNot(p1) )
- return Abc_ObjNot(pMan->pConst1);
- if ( Abc_ObjRegular(p0) == pMan->pConst1 )
+ return Abc_ObjNot(pConst1);
+ if ( Abc_ObjRegular(p0) == pConst1 )
{
- if ( p0 == pMan->pConst1 )
+ if ( p0 == pConst1 )
return p1;
- return Abc_ObjNot(pMan->pConst1);
+ return Abc_ObjNot(pConst1);
}
- if ( Abc_ObjRegular(p1) == pMan->pConst1 )
+ if ( Abc_ObjRegular(p1) == pConst1 )
{
- if ( p1 == pMan->pConst1 )
+ if ( p1 == pConst1 )
return p0;
- return Abc_ObjNot(pMan->pConst1);
+ return Abc_ObjNot(pConst1);
+ }
+/*
+ {
+ int nFans0 = Abc_ObjFanoutNum( Abc_ObjRegular(p0) );
+ int nFans1 = Abc_ObjFanoutNum( Abc_ObjRegular(p1) );
+ if ( nFans0 == 0 || nFans1 == 0 )
+ pMan->nStrash0++;
+ else if ( nFans0 == 1 || nFans1 == 1 )
+ pMan->nStrash1++;
+ else if ( nFans0 <= 100 && nFans1 <= 100 )
+ pMan->nStrash5++;
+ else
+ pMan->nStrash2++;
+ }
+*/
+ {
+ int nFans0 = Abc_ObjFanoutNum( Abc_ObjRegular(p0) );
+ int nFans1 = Abc_ObjFanoutNum( Abc_ObjRegular(p1) );
+ if ( nFans0 == 0 || nFans1 == 0 )
+ return NULL;
}
+
// order the arguments
if ( Abc_ObjRegular(p0)->Id > Abc_ObjRegular(p1)->Id )
pAnd = p0, p0 = p1, p1 = pAnd;
@@ -474,7 +454,78 @@ Abc_Obj_t * Abc_AigAndLookup( Abc_Aig_t * pMan, Abc_Obj_t * p0, Abc_Obj_t * p1 )
// find the matching node in the table
Abc_AigBinForEachEntry( pMan->pBins[Key], pAnd )
if ( p0 == Abc_ObjChild0(pAnd) && p1 == Abc_ObjChild1(pAnd) )
+ {
+// assert( Abc_ObjFanoutNum(Abc_ObjRegular(p0)) && Abc_ObjFanoutNum(p1) );
return pAnd;
+ }
+ return NULL;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Returns the gate implementing EXOR of the two arguments if it exists.]
+
+ Description [The argument nodes can be complemented.]
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Abc_Obj_t * Abc_AigXorLookup( Abc_Aig_t * pMan, Abc_Obj_t * p0, Abc_Obj_t * p1, int * pType )
+{
+ Abc_Obj_t * pNode1, * pNode2, * pNode;
+ // set the flag to zero
+ if ( pType ) *pType = 0;
+ // check the case of XOR(a,b) = OR(ab, a'b')'
+ if ( (pNode1 = Abc_AigAndLookup(pMan, Abc_ObjNot(p0), Abc_ObjNot(p1))) &&
+ (pNode2 = Abc_AigAndLookup(pMan, p0, p1)) )
+ {
+ pNode = Abc_AigAndLookup( pMan, Abc_ObjNot(pNode1), Abc_ObjNot(pNode2) );
+ if ( pNode && pType ) *pType = 1;
+ return pNode;
+ }
+ // check the case of XOR(a,b) = OR(a'b, ab')
+ if ( (pNode1 = Abc_AigAndLookup(pMan, p0, Abc_ObjNot(p1))) &&
+ (pNode2 = Abc_AigAndLookup(pMan, Abc_ObjNot(p0), p1)) )
+ {
+ pNode = Abc_AigAndLookup( pMan, Abc_ObjNot(pNode1), Abc_ObjNot(pNode2) );
+ return pNode? Abc_ObjNot(pNode) : NULL;
+ }
+ return NULL;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Returns the gate implementing EXOR of the two arguments if it exists.]
+
+ Description [The argument nodes can be complemented.]
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Abc_Obj_t * Abc_AigMuxLookup( Abc_Aig_t * pMan, Abc_Obj_t * pC, Abc_Obj_t * pT, Abc_Obj_t * pE, int * pType )
+{
+ Abc_Obj_t * pNode1, * pNode2, * pNode;
+ // set the flag to zero
+ if ( pType ) *pType = 0;
+ // check the case of MUX(c,t,e) = OR(ct', c'e')'
+ if ( (pNode1 = Abc_AigAndLookup(pMan, pC, Abc_ObjNot(pT))) &&
+ (pNode2 = Abc_AigAndLookup(pMan, Abc_ObjNot(pC), Abc_ObjNot(pE))) )
+ {
+ pNode = Abc_AigAndLookup( pMan, Abc_ObjNot(pNode1), Abc_ObjNot(pNode2) );
+ if ( pNode && pType ) *pType = 1;
+ return pNode;
+ }
+ // check the case of MUX(c,t,e) = OR(ct, c'e)
+ if ( (pNode1 = Abc_AigAndLookup(pMan, pC, pT)) &&
+ (pNode2 = Abc_AigAndLookup(pMan, Abc_ObjNot(pC), pE)) )
+ {
+ pNode = Abc_AigAndLookup( pMan, Abc_ObjNot(pNode1), Abc_ObjNot(pNode2) );
+ return pNode? Abc_ObjNot(pNode) : NULL;
+ }
return NULL;
}
@@ -491,13 +542,15 @@ Abc_Obj_t * Abc_AigAndLookup( Abc_Aig_t * pMan, Abc_Obj_t * p0, Abc_Obj_t * p1 )
***********************************************************************/
void Abc_AigAndDelete( Abc_Aig_t * pMan, Abc_Obj_t * pThis )
{
- Abc_Obj_t * pAnd, ** ppPlace;
+ Abc_Obj_t * pAnd, * pAnd0, * pAnd1, ** ppPlace;
unsigned Key;
assert( !Abc_ObjIsComplement(pThis) );
assert( Abc_ObjIsNode(pThis) );
assert( Abc_ObjFaninNum(pThis) == 2 );
assert( pMan->pNtkAig == pThis->pNtk );
// get the hash key for these two nodes
+ pAnd0 = Abc_ObjRegular( Abc_ObjChild0(pThis) );
+ pAnd1 = Abc_ObjRegular( Abc_ObjChild1(pThis) );
Key = Abc_HashKey2( Abc_ObjChild0(pThis), Abc_ObjChild1(pThis), pMan->nBins );
// find the matching node in the table
ppPlace = pMan->pBins + Key;
@@ -561,9 +614,77 @@ clk = clock();
pMan->nBins = nBinsNew;
}
+/**Function*************************************************************
+ Synopsis [Resizes the hash table of AIG nodes.]
+ Description []
+
+ SideEffects []
+ SeeAlso []
+
+***********************************************************************/
+void Abc_AigRehash( Abc_Aig_t * pMan )
+{
+ Abc_Obj_t ** pBinsNew;
+ Abc_Obj_t * pEnt, * pEnt2;
+ int * pArray;
+ unsigned Key;
+ int Counter, Temp, i;
+
+ // allocate a new array
+ pBinsNew = ALLOC( Abc_Obj_t *, pMan->nBins );
+ memset( pBinsNew, 0, sizeof(Abc_Obj_t *) * pMan->nBins );
+ // rehash the entries from the old table
+ Counter = 0;
+ for ( i = 0; i < pMan->nBins; i++ )
+ Abc_AigBinForEachEntrySafe( pMan->pBins[i], pEnt, pEnt2 )
+ {
+ // swap the fanins if needed
+ pArray = pEnt->vFanins.pArray;
+ if ( pArray[0] > pArray[1] )
+ {
+ Temp = pArray[0];
+ pArray[0] = pArray[1];
+ pArray[1] = Temp;
+ Temp = pEnt->fCompl0;
+ pEnt->fCompl0 = pEnt->fCompl1;
+ pEnt->fCompl1 = Temp;
+ }
+ // rehash the node
+ Key = Abc_HashKey2( Abc_ObjChild0(pEnt), Abc_ObjChild1(pEnt), pMan->nBins );
+ pEnt->pNext = pBinsNew[Key];
+ pBinsNew[Key] = pEnt;
+ Counter++;
+ }
+ assert( Counter == pMan->nEntries );
+ // replace the table and the parameters
+ free( pMan->pBins );
+ pMan->pBins = pBinsNew;
+}
+
+
+
+
+
+
+/**Function*************************************************************
+
+ Synopsis [Performs canonicization step.]
+
+ Description [The argument nodes can be complemented.]
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Abc_Obj_t * Abc_AigConst1( Abc_Ntk_t * pNtk )
+{
+ assert( Abc_NtkIsStrash(pNtk) );
+ return ((Abc_Aig_t *)pNtk->pManFunc)->pConst1;
+}
/**Function*************************************************************
@@ -579,7 +700,7 @@ clk = clock();
Abc_Obj_t * Abc_AigAnd( Abc_Aig_t * pMan, Abc_Obj_t * p0, Abc_Obj_t * p1 )
{
Abc_Obj_t * pAnd;
- if ( pAnd = Abc_AigAndLookup( pMan, p0, p1 ) )
+ if ( (pAnd = Abc_AigAndLookup( pMan, p0, p1 )) )
return pAnd;
return Abc_AigAndCreate( pMan, p0, p1 );
}
@@ -616,7 +737,28 @@ Abc_Obj_t * Abc_AigXor( Abc_Aig_t * pMan, Abc_Obj_t * p0, Abc_Obj_t * p1 )
return Abc_AigOr( pMan, Abc_AigAnd(pMan, p0, Abc_ObjNot(p1)),
Abc_AigAnd(pMan, p1, Abc_ObjNot(p0)) );
}
+
+/**Function*************************************************************
+
+ Synopsis [Implements the miter.]
+
+ Description []
+
+ SideEffects []
+ SeeAlso []
+
+***********************************************************************/
+Abc_Obj_t * Abc_AigMiter_rec( Abc_Aig_t * pMan, Abc_Obj_t ** ppObjs, int nObjs )
+{
+ Abc_Obj_t * pObj1, * pObj2;
+ if ( nObjs == 1 )
+ return ppObjs[0];
+ pObj1 = Abc_AigMiter_rec( pMan, ppObjs, nObjs/2 );
+ pObj2 = Abc_AigMiter_rec( pMan, ppObjs + nObjs/2, nObjs - nObjs/2 );
+ return Abc_AigOr( pMan, pObj1, pObj2 );
+}
+
/**Function*************************************************************
Synopsis [Implements the miter.]
@@ -630,11 +772,35 @@ Abc_Obj_t * Abc_AigXor( Abc_Aig_t * pMan, Abc_Obj_t * p0, Abc_Obj_t * p1 )
***********************************************************************/
Abc_Obj_t * Abc_AigMiter( Abc_Aig_t * pMan, Vec_Ptr_t * vPairs )
{
+ int i;
+ if ( vPairs->nSize == 0 )
+ return Abc_ObjNot( Abc_AigConst1(pMan->pNtkAig) );
+ assert( vPairs->nSize % 2 == 0 );
+ // go through the cubes of the node's SOP
+ for ( i = 0; i < vPairs->nSize; i += 2 )
+ vPairs->pArray[i/2] = Abc_AigXor( pMan, vPairs->pArray[i], vPairs->pArray[i+1] );
+ vPairs->nSize = vPairs->nSize/2;
+ return Abc_AigMiter_rec( pMan, (Abc_Obj_t **)vPairs->pArray, vPairs->nSize );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Implements the miter.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Abc_Obj_t * Abc_AigMiter2( Abc_Aig_t * pMan, Vec_Ptr_t * vPairs )
+{
Abc_Obj_t * pMiter, * pXor;
int i;
assert( vPairs->nSize % 2 == 0 );
// go through the cubes of the node's SOP
- pMiter = Abc_ObjNot(pMan->pConst1);
+ pMiter = Abc_ObjNot( Abc_AigConst1(pMan->pNtkAig) );
for ( i = 0; i < vPairs->nSize; i += 2 )
{
pXor = Abc_AigXor( pMan, vPairs->pArray[i], vPairs->pArray[i+1] );
@@ -657,17 +823,29 @@ Abc_Obj_t * Abc_AigMiter( Abc_Aig_t * pMan, Vec_Ptr_t * vPairs )
SeeAlso []
***********************************************************************/
-void Abc_AigReplace( Abc_Aig_t * pMan, Abc_Obj_t * pOld, Abc_Obj_t * pNew )
+void Abc_AigReplace( Abc_Aig_t * pMan, Abc_Obj_t * pOld, Abc_Obj_t * pNew, bool fUpdateLevel )
{
assert( Vec_PtrSize(pMan->vStackReplaceOld) == 0 );
assert( Vec_PtrSize(pMan->vStackReplaceNew) == 0 );
- assert( Vec_PtrSize(pMan->vStackDelete) == 0 );
Vec_PtrPush( pMan->vStackReplaceOld, pOld );
Vec_PtrPush( pMan->vStackReplaceNew, pNew );
+ assert( !Abc_ObjIsComplement(pOld) );
+ // create HAIG
+ if ( pOld->pNtk->pHaig )
+ Hop_ObjCreateChoice( pOld->pEquiv, Abc_ObjRegular(pNew)->pEquiv );
+ // process the replacements
while ( Vec_PtrSize(pMan->vStackReplaceOld) )
- Abc_AigReplace_int( pMan );
- Abc_AigUpdateLevel_int( pMan );
- Abc_AigUpdateLevelR_int( pMan );
+ {
+ pOld = Vec_PtrPop( pMan->vStackReplaceOld );
+ pNew = Vec_PtrPop( pMan->vStackReplaceNew );
+ Abc_AigReplace_int( pMan, pOld, pNew, fUpdateLevel );
+ }
+ if ( fUpdateLevel )
+ {
+ Abc_AigUpdateLevel_int( pMan );
+ if ( pMan->pNtkAig->vLevelsR )
+ Abc_AigUpdateLevelR_int( pMan );
+ }
}
/**Function*************************************************************
@@ -681,14 +859,10 @@ void Abc_AigReplace( Abc_Aig_t * pMan, Abc_Obj_t * pOld, Abc_Obj_t * pNew )
SeeAlso []
***********************************************************************/
-void Abc_AigReplace_int( Abc_Aig_t * pMan )
+void Abc_AigReplace_int( Abc_Aig_t * pMan, Abc_Obj_t * pOld, Abc_Obj_t * pNew, int fUpdateLevel )
{
- Abc_Obj_t * pOld, * pNew, * pFanin1, * pFanin2, * pFanout, * pFanoutNew, * pFanoutFanout;
- int k, v, iFanin;
- // get the pair of nodes to replace
- assert( Vec_PtrSize(pMan->vStackReplaceOld) > 0 );
- pOld = Vec_PtrPop( pMan->vStackReplaceOld );
- pNew = Vec_PtrPop( pMan->vStackReplaceNew );
+ Abc_Obj_t * pFanin1, * pFanin2, * pFanout, * pFanoutNew, * pFanoutFanout;
+ int k, v, iFanin;
// make sure the old node is regular and has fanouts
// (the new node can be complemented and can have fanouts)
assert( !Abc_ObjIsComplement(pOld) );
@@ -703,7 +877,7 @@ void Abc_AigReplace_int( Abc_Aig_t * pMan )
continue;
}
// find the old node as a fanin of this fanout
- iFanin = Vec_FanFindEntry( &pFanout->vFanins, pOld->Id );
+ iFanin = Vec_IntFind( &pFanout->vFanins, pOld->Id );
assert( iFanin == 0 || iFanin == 1 );
// get the new fanin
pFanin1 = Abc_ObjNotCond( pNew, Abc_ObjFaninC(pFanout, iFanin) );
@@ -712,7 +886,7 @@ void Abc_AigReplace_int( Abc_Aig_t * pMan )
pFanin2 = Abc_ObjChild( pFanout, iFanin ^ 1 );
assert( Abc_ObjRegular(pFanin2) != pFanout );
// check if the node with these fanins exists
- if ( pFanoutNew = Abc_AigAndLookup( pMan, pFanin1, pFanin2 ) )
+ if ( (pFanoutNew = Abc_AigAndLookup( pMan, pFanin1, pFanin2 )) )
{ // such node exists (it may be a constant)
// schedule replacement of the old fanout by the new fanout
Vec_PtrPush( pMan->vStackReplaceOld, pFanout );
@@ -738,18 +912,24 @@ void Abc_AigReplace_int( Abc_Aig_t * pMan )
Abc_AigAndCreateFrom( pMan, pFanin1, pFanin2, pFanout );
assert( Abc_AigNodeIsAcyclic(pFanout, pFanout) );
- // schedule the updated fanout for updating direct level
- assert( pFanout->fMarkA == 0 );
- pFanout->fMarkA = 1;
- Vec_VecPush( pMan->vLevels, pFanout->Level, pFanout );
- // schedule the updated fanout for updating reverse level
- assert( pFanout->fMarkB == 0 );
- pFanout->fMarkB = 1;
- Vec_VecPush( pMan->vLevelsR, Abc_NodeReadReverseLevel(pFanout), pFanout );
+ if ( fUpdateLevel )
+ {
+ // schedule the updated fanout for updating direct level
+ assert( pFanout->fMarkA == 0 );
+ pFanout->fMarkA = 1;
+ Vec_VecPush( pMan->vLevels, pFanout->Level, pFanout );
+ // schedule the updated fanout for updating reverse level
+ if ( pMan->pNtkAig->vLevelsR )
+ {
+ assert( pFanout->fMarkB == 0 );
+ pFanout->fMarkB = 1;
+ Vec_VecPush( pMan->vLevelsR, Abc_ObjReverseLevel(pFanout), pFanout );
+ }
+ }
// the fanout has changed, update EXOR status of its fanouts
Abc_ObjForEachFanout( pFanout, pFanoutFanout, v )
- if ( Abc_NodeIsAigAnd(pFanoutFanout) )
+ if ( Abc_AigNodeIsAnd(pFanoutFanout) )
pFanoutFanout->fExor = Abc_NodeIsExorType(pFanoutFanout);
}
// if the node has no fanouts left, remove its MFFC
@@ -768,88 +948,65 @@ void Abc_AigReplace_int( Abc_Aig_t * pMan )
SeeAlso []
***********************************************************************/
-void Abc_AigDeleteNode( Abc_Aig_t * pMan, Abc_Obj_t * pOld )
+void Abc_AigDeleteNode( Abc_Aig_t * pMan, Abc_Obj_t * pNode )
{
- assert( Vec_PtrSize(pMan->vStackDelete) == 0 );
- Vec_PtrPush( pMan->vStackDelete, pOld );
- while ( Vec_PtrSize(pMan->vStackDelete) )
- Abc_AigDelete_int( pMan );
-}
-
-/**Function*************************************************************
-
- Synopsis [Performs internal deletion step.]
-
- Description []
-
- SideEffects []
-
- SeeAlso []
-
-***********************************************************************/
-void Abc_AigDelete_int( Abc_Aig_t * pMan )
-{
- Vec_Ptr_t * vNodes;
- Abc_Obj_t * pRoot, * pObj;
- int k;
- // get the node to delete
- assert( Vec_PtrSize(pMan->vStackDelete) > 0 );
- pRoot = Vec_PtrPop( pMan->vStackDelete );
+ Abc_Obj_t * pNode0, * pNode1, * pTemp;
+ int i, k;
// make sure the node is regular and dangling
- assert( !Abc_ObjIsComplement(pRoot) );
- assert( Abc_ObjIsNode(pRoot) );
- assert( Abc_ObjFaninNum(pRoot) == 2 );
- assert( Abc_ObjFanoutNum(pRoot) == 0 );
-
- // collect the MFFC
- vNodes = Abc_NodeMffcCollect( pRoot );
-
- // if reverse levels are specified, schedule fanins of MFFC for updating
- // currently, we do not do it because we do not know the correct level of the fanins
- // also, it is unlikely that this will make a difference since we are
- // processing the network forward while at this point fanins are left behind...
-/*
- if ( pObj->pNtk->vLevelsR )
- Vec_PtrForEachEntry( vNodes, pObj, k )
+ assert( !Abc_ObjIsComplement(pNode) );
+ assert( Abc_ObjIsNode(pNode) );
+ assert( Abc_ObjFaninNum(pNode) == 2 );
+ assert( Abc_ObjFanoutNum(pNode) == 0 );
+
+ // when deleting an old node that is scheduled for replacement, remove it from the replacement queue
+ Vec_PtrForEachEntry( pMan->vStackReplaceOld, pTemp, i )
+ if ( pNode == pTemp )
{
- Abc_Obj_t * pFanin;
- if ( Abc_ObjIsCi(pObj) )
- continue;
- pFanin = Abc_ObjFanin0(pObj);
- if ( pFanin->fMarkB == 0 )
+ // remove the entry from the replacement array
+ for ( k = i; k < pMan->vStackReplaceOld->nSize - 1; k++ )
{
- pFanin->fMarkB = 1;
- Vec_VecPush( pMan->vLevelsR, Abc_NodeReadReverseLevel(pFanin), pFanin );
- }
- pFanin = Abc_ObjFanin1(pObj);
- if ( pFanin->fMarkB == 0 )
- {
- pFanin->fMarkB = 1;
- Vec_VecPush( pMan->vLevelsR, Abc_NodeReadReverseLevel(pFanin), pFanin );
+ pMan->vStackReplaceOld->pArray[k] = pMan->vStackReplaceOld->pArray[k+1];
+ pMan->vStackReplaceNew->pArray[k] = pMan->vStackReplaceNew->pArray[k+1];
}
+ pMan->vStackReplaceOld->nSize--;
+ pMan->vStackReplaceNew->nSize--;
}
-*/
- // delete the nodes in MFFC
- Vec_PtrForEachEntry( vNodes, pObj, k )
+ // when deleting a new node that should replace another node, do not delete
+ Vec_PtrForEachEntry( pMan->vStackReplaceNew, pTemp, i )
+ if ( pNode == Abc_ObjRegular(pTemp) )
+ return;
+
+ // remember the node's fanins
+ pNode0 = Abc_ObjFanin0( pNode );
+ pNode1 = Abc_ObjFanin1( pNode );
+
+ // add the node to the list of updated nodes
+ if ( pMan->vUpdatedNets )
{
- if ( Abc_ObjIsCi(pObj) )
- continue;
- assert( Abc_ObjFanoutNum(pObj) == 0 );
- // remove the node from the table
- Abc_AigAndDelete( pMan, pObj );
- // if the node is in the level structure, remove it
- if ( pObj->fMarkA )
- Abc_AigRemoveFromLevelStructure( pMan->vLevels, pObj );
- if ( pObj->fMarkB )
- Abc_AigRemoveFromLevelStructureR( pMan->vLevelsR, pObj );
- // remove the node from the network
- Abc_NtkDeleteObj( pObj );
+ Vec_PtrPushUnique( pMan->vUpdatedNets, pNode0 );
+ Vec_PtrPushUnique( pMan->vUpdatedNets, pNode1 );
}
- Vec_PtrFree( vNodes );
+
+ // remove the node from the table
+ Abc_AigAndDelete( pMan, pNode );
+ // if the node is in the level structure, remove it
+ if ( pNode->fMarkA )
+ Abc_AigRemoveFromLevelStructure( pMan->vLevels, pNode );
+ if ( pNode->fMarkB )
+ Abc_AigRemoveFromLevelStructureR( pMan->vLevelsR, pNode );
+ // remove the node from the network
+ Abc_NtkDeleteObj( pNode );
+
+ // call recursively for the fanins
+ if ( Abc_ObjIsNode(pNode0) && pNode0->vFanouts.nSize == 0 )
+ Abc_AigDeleteNode( pMan, pNode0 );
+ if ( Abc_ObjIsNode(pNode1) && pNode1->vFanouts.nSize == 0 )
+ Abc_AigDeleteNode( pMan, pNode1 );
}
+
/**Function*************************************************************
Synopsis [Updates the level of the node after it has changed.]
@@ -937,7 +1094,7 @@ void Abc_AigUpdateLevelR_int( Abc_Aig_t * pMan )
if ( pNode == NULL )
continue;
assert( Abc_ObjIsNode(pNode) );
- assert( Abc_NodeReadReverseLevel(pNode) == i );
+ assert( Abc_ObjReverseLevel(pNode) == i );
// clean the mark
assert( pNode->fMarkB == 1 );
pNode->fMarkB = 0;
@@ -949,17 +1106,17 @@ void Abc_AigUpdateLevelR_int( Abc_Aig_t * pMan )
// get the new reverse level of this fanin
LevelNew = 0;
Abc_ObjForEachFanout( pFanin, pFanout, j )
- if ( LevelNew < Abc_NodeReadReverseLevel(pFanout) )
- LevelNew = Abc_NodeReadReverseLevel(pFanout);
+ if ( LevelNew < Abc_ObjReverseLevel(pFanout) )
+ LevelNew = Abc_ObjReverseLevel(pFanout);
LevelNew += 1;
assert( LevelNew > i );
- if ( Abc_NodeReadReverseLevel(pFanin) == LevelNew ) // no change
+ if ( Abc_ObjReverseLevel(pFanin) == LevelNew ) // no change
continue;
// if the fanin is present in the data structure, pull it out
if ( pFanin->fMarkB )
Abc_AigRemoveFromLevelStructureR( pMan->vLevelsR, pFanin );
// update the reverse level
- Abc_NodeSetReverseLevel( pFanin, LevelNew );
+ Abc_ObjSetReverseLevel( pFanin, LevelNew );
// add the fanin to the data structure to update its fanins
assert( pFanin->fMarkB == 0 );
pFanin->fMarkB = 1;
@@ -1016,7 +1173,7 @@ void Abc_AigRemoveFromLevelStructureR( Vec_Vec_t * vStruct, Abc_Obj_t * pNode )
Abc_Obj_t * pTemp;
int m;
assert( pNode->fMarkB );
- vVecTemp = Vec_VecEntry( vStruct, Abc_NodeReadReverseLevel(pNode) );
+ vVecTemp = Vec_VecEntry( vStruct, Abc_ObjReverseLevel(pNode) );
Vec_PtrForEachEntry( vVecTemp, pTemp, m )
{
if ( pTemp != pNode )
@@ -1049,7 +1206,7 @@ bool Abc_AigNodeHasComplFanoutEdge( Abc_Obj_t * pNode )
int i, iFanin;
Abc_ObjForEachFanout( pNode, pFanout, i )
{
- iFanin = Vec_FanFindEntry( &pFanout->vFanins, pNode->Id );
+ iFanin = Vec_IntFind( &pFanout->vFanins, pNode->Id );
assert( iFanin >= 0 );
if ( Abc_ObjFaninC( pFanout, iFanin ) )
return 1;
@@ -1078,7 +1235,7 @@ bool Abc_AigNodeHasComplFanoutEdgeTrav( Abc_Obj_t * pNode )
{
if ( !Abc_NodeIsTravIdCurrent(pFanout) )
continue;
- iFanin = Vec_FanFindEntry( &pFanout->vFanins, pNode->Id );
+ iFanin = Vec_IntFind( &pFanout->vFanins, pNode->Id );
assert( iFanin >= 0 );
if ( Abc_ObjFaninC( pFanout, iFanin ) )
return 1;
@@ -1106,7 +1263,7 @@ void Abc_AigPrintNode( Abc_Obj_t * pNode )
printf( "CI %4s%s.\n", Abc_ObjName(pNodeR), Abc_ObjIsComplement(pNode)? "\'" : "" );
return;
}
- if ( Abc_NodeIsConst(pNodeR) )
+ if ( Abc_AigNodeIsConst(pNodeR) )
{
printf( "Constant 1 %s.\n", Abc_ObjIsComplement(pNode)? "(complemented)" : "" );
return;
@@ -1137,7 +1294,7 @@ bool Abc_AigNodeIsAcyclic( Abc_Obj_t * pNode, Abc_Obj_t * pRoot )
Abc_Obj_t * pFanin0, * pFanin1;
Abc_Obj_t * pChild00, * pChild01;
Abc_Obj_t * pChild10, * pChild11;
- if ( !Abc_NodeIsAigAnd(pNode) )
+ if ( !Abc_AigNodeIsAnd(pNode) )
return 1;
pFanin0 = Abc_ObjFanin0(pNode);
pFanin1 = Abc_ObjFanin1(pNode);
@@ -1170,6 +1327,148 @@ bool Abc_AigNodeIsAcyclic( Abc_Obj_t * pNode, Abc_Obj_t * pRoot )
return 1;
}
+/**Function*************************************************************
+
+ Synopsis [Resizes the hash table of AIG nodes.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Abc_AigCheckFaninOrder( Abc_Aig_t * pMan )
+{
+ Abc_Obj_t * pEnt;
+ int i;
+ for ( i = 0; i < pMan->nBins; i++ )
+ Abc_AigBinForEachEntry( pMan->pBins[i], pEnt )
+ {
+ if ( Abc_ObjRegular(Abc_ObjChild0(pEnt))->Id > Abc_ObjRegular(Abc_ObjChild1(pEnt))->Id )
+ {
+// int i0 = Abc_ObjRegular(Abc_ObjChild0(pEnt))->Id;
+// int i1 = Abc_ObjRegular(Abc_ObjChild1(pEnt))->Id;
+ printf( "Node %d has incorrect ordering of fanins.\n", pEnt->Id );
+ }
+ }
+}
+
+/**Function*************************************************************
+
+ Synopsis [Sets the correct phase of the nodes.]
+
+ Description [The AIG nodes should be in the DFS order.]
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Abc_AigSetNodePhases( Abc_Ntk_t * pNtk )
+{
+ Abc_Obj_t * pObj;
+ int i;
+ assert( Abc_NtkIsDfsOrdered(pNtk) );
+ Abc_AigConst1(pNtk)->fPhase = 1;
+ Abc_NtkForEachPi( pNtk, pObj, i )
+ pObj->fPhase = 0;
+ Abc_NtkForEachLatchOutput( pNtk, pObj, i )
+ pObj->fPhase = Abc_LatchIsInit1(pObj);
+ Abc_AigForEachAnd( pNtk, pObj, i )
+ pObj->fPhase = (Abc_ObjFanin0(pObj)->fPhase ^ Abc_ObjFaninC0(pObj)) & (Abc_ObjFanin1(pObj)->fPhase ^ Abc_ObjFaninC1(pObj));
+ Abc_NtkForEachPo( pNtk, pObj, i )
+ pObj->fPhase = (Abc_ObjFanin0(pObj)->fPhase ^ Abc_ObjFaninC0(pObj));
+ Abc_NtkForEachLatchInput( pNtk, pObj, i )
+ pObj->fPhase = (Abc_ObjFanin0(pObj)->fPhase ^ Abc_ObjFaninC0(pObj));
+}
+
+
+
+/**Function*************************************************************
+
+ Synopsis [Start the update list.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Vec_Ptr_t * Abc_AigUpdateStart( Abc_Aig_t * pMan, Vec_Ptr_t ** pvUpdatedNets )
+{
+ assert( pMan->vAddedCells == NULL );
+ pMan->vAddedCells = Vec_PtrAlloc( 1000 );
+ pMan->vUpdatedNets = Vec_PtrAlloc( 1000 );
+ *pvUpdatedNets = pMan->vUpdatedNets;
+ return pMan->vAddedCells;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Start the update list.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Abc_AigUpdateStop( Abc_Aig_t * pMan )
+{
+ assert( pMan->vAddedCells != NULL );
+ Vec_PtrFree( pMan->vAddedCells );
+ Vec_PtrFree( pMan->vUpdatedNets );
+ pMan->vAddedCells = NULL;
+ pMan->vUpdatedNets = NULL;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Start the update list.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Abc_AigUpdateReset( Abc_Aig_t * pMan )
+{
+ assert( pMan->vAddedCells != NULL );
+ Vec_PtrClear( pMan->vAddedCells );
+ Vec_PtrClear( pMan->vUpdatedNets );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Start the update list.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Abc_AigCountNext( Abc_Aig_t * pMan )
+{
+ Abc_Obj_t * pAnd;
+ int i, Counter = 0, CounterTotal = 0;
+ // count how many nodes have pNext set
+ for ( i = 0; i < pMan->nBins; i++ )
+ Abc_AigBinForEachEntry( pMan->pBins[i], pAnd )
+ {
+ Counter += (pAnd->pNext != NULL);
+ CounterTotal++;
+ }
+ printf( "Counter = %d. Nodes = %d. Ave = %6.2f\n", Counter, CounterTotal, 1.0 * CounterTotal/pMan->nBins );
+ return Counter;
+}
+
////////////////////////////////////////////////////////////////////////
/// END OF FILE ///
////////////////////////////////////////////////////////////////////////
diff --git a/src/base/abc/abcBlifMv.c b/src/base/abc/abcBlifMv.c
new file mode 100644
index 00000000..48ec58c0
--- /dev/null
+++ b/src/base/abc/abcBlifMv.c
@@ -0,0 +1,970 @@
+/**CFile****************************************************************
+
+ FileName [abcBlifMv.c]
+
+ SystemName [ABC: Logic synthesis and verification system.]
+
+ PackageName [Network and node package.]
+
+ Synopsis [Procedures to process BLIF-MV networks and AIGs.]
+
+ Author [Alan Mishchenko]
+
+ Affiliation [UC Berkeley]
+
+ Date [Ver. 1.0. Started - June 20, 2005.]
+
+ Revision [$Id: abcBlifMv.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "abc.h"
+
+////////////////////////////////////////////////////////////////////////
+/// DECLARATIONS ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+/// FUNCTION DEFINITIONS ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+ Synopsis [Starts the Mv-Var manager.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Abc_NtkStartMvVars( Abc_Ntk_t * pNtk )
+{
+ Vec_Att_t * pAttMan;
+ assert( Abc_NtkMvVar(pNtk) == NULL );
+ pAttMan = Vec_AttAlloc( 0, Abc_NtkObjNumMax(pNtk) + 1, Extra_MmFlexStart(), Extra_MmFlexStop, NULL, NULL );
+ Vec_PtrWriteEntry( pNtk->vAttrs, VEC_ATTR_MVVAR, pAttMan );
+//printf( "allocing attr\n" );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Stops the Mv-Var manager.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Abc_NtkFreeMvVars( Abc_Ntk_t * pNtk )
+{
+ void * pUserMan;
+ pUserMan = Abc_NtkAttrFree( pNtk, VEC_ATTR_GLOBAL_BDD, 0 );
+ Extra_MmFlexStop( pUserMan );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Duplicate the MV variable.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Abc_NtkSetMvVarValues( Abc_Obj_t * pObj, int nValues )
+{
+ Extra_MmFlex_t * pFlex;
+ struct temp
+ {
+ int nValues;
+ char ** pNames;
+ } * pVarStruct;
+ assert( nValues > 1 );
+ // skip binary signals
+ if ( nValues == 2 )
+ return;
+ // skip already assigned signals
+ if ( Abc_ObjMvVar(pObj) != NULL )
+ return;
+ // create the structure
+ pFlex = Abc_NtkMvVarMan( pObj->pNtk );
+ pVarStruct = (void *)Extra_MmFlexEntryFetch( pFlex, sizeof(struct temp) );
+ pVarStruct->nValues = nValues;
+ pVarStruct->pNames = NULL;
+ Abc_ObjSetMvVar( pObj, pVarStruct );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Strashes the BLIF-MV netlist.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+static inline int Abc_StringGetNumber( char ** ppStr )
+{
+ char * pStr = *ppStr;
+ int Number = 0;
+ assert( *pStr >= '0' && *pStr <= '9' );
+ for ( ; *pStr >= '0' && *pStr <= '9'; pStr++ )
+ Number = 10 * Number + *pStr - '0';
+ *ppStr = pStr;
+ return Number;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Strashes one node in the BLIF-MV netlist.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Abc_NodeStrashBlifMv( Abc_Ntk_t * pNtkNew, Abc_Obj_t * pObj )
+{
+ char * pSop;
+ Abc_Obj_t ** pValues, ** pValuesF, ** pValuesF2;
+ Abc_Obj_t * pTemp, * pTemp2, * pFanin, * pFanin2, * pNet;
+ int k, v, Def, DefIndex, Index, nValues, nValuesF, nValuesF2;
+
+ // start the output values
+ assert( Abc_ObjIsNode(pObj) );
+ pNet = Abc_ObjFanout0(pObj);
+ nValues = Abc_ObjMvVarNum(pNet);
+ pValues = ALLOC( Abc_Obj_t *, nValues );
+ for ( k = 0; k < nValues; k++ )
+ pValues[k] = Abc_ObjNot( Abc_AigConst1(pNtkNew) );
+
+ // get the BLIF-MV formula
+ pSop = pObj->pData;
+ // skip the value line
+// while ( *pSop++ != '\n' );
+
+ // handle the constant
+ if ( Abc_ObjFaninNum(pObj) == 0 )
+ {
+ // skip the default if present
+ if ( *pSop == 'd' )
+ while ( *pSop++ != '\n' );
+ // skip space if present
+ if ( *pSop == ' ' )
+ pSop++;
+ Index = Abc_StringGetNumber( &pSop );
+ assert( Index < nValues );
+ pValues[Index] = Abc_AigConst1(pNtkNew);
+ // save the values in the fanout net
+ pNet->pCopy = (Abc_Obj_t *)pValues;
+ return 1;
+ }
+
+ // parse the default line
+ Def = DefIndex = -1;
+ if ( *pSop == 'd' )
+ {
+ pSop++;
+ if ( *pSop == '=' )
+ {
+ pSop++;
+ DefIndex = Abc_StringGetNumber( &pSop );
+ assert( DefIndex < Abc_ObjFaninNum(pObj) );
+ }
+ else if ( *pSop == '-' )
+ {
+ pSop++;
+ Def = 0;
+ }
+ else
+ {
+ Def = Abc_StringGetNumber( &pSop );
+ assert( Def < nValues );
+ }
+ assert( *pSop == '\n' );
+ pSop++;
+ }
+
+ // convert the values
+ while ( *pSop )
+ {
+ // extract the values for each cube
+ pTemp = Abc_AigConst1(pNtkNew);
+ Abc_ObjForEachFanin( pObj, pFanin, k )
+ {
+ if ( *pSop == '-' )
+ {
+ pSop += 2;
+ continue;
+ }
+ if ( *pSop == '!' )
+ {
+ printf( "Abc_NodeStrashBlifMv(): Cannot handle complement in the MV function of node %s.\n", Abc_ObjName(Abc_ObjFanout0(pObj)) );
+ return 0;
+ }
+ if ( *pSop == '{' )
+ {
+ printf( "Abc_NodeStrashBlifMv(): Cannot handle braces in the MV function of node %s.\n", Abc_ObjName(Abc_ObjFanout0(pObj)) );
+ return 0;
+ }
+ // get the value set
+ nValuesF = Abc_ObjMvVarNum(pFanin);
+ pValuesF = (Abc_Obj_t **)pFanin->pCopy;
+ if ( *pSop == '(' )
+ {
+ pSop++;
+ pTemp2 = Abc_ObjNot( Abc_AigConst1(pNtkNew) );
+ while ( *pSop != ')' )
+ {
+ Index = Abc_StringGetNumber( &pSop );
+ assert( Index < nValuesF );
+ pTemp2 = Abc_AigOr( pNtkNew->pManFunc, pTemp2, pValuesF[Index] );
+ assert( *pSop == ')' || *pSop == ',' );
+ if ( *pSop == ',' )
+ pSop++;
+ }
+ assert( *pSop == ')' );
+ pSop++;
+ }
+ else if ( *pSop == '=' )
+ {
+ pSop++;
+ // get the fanin index
+ Index = Abc_StringGetNumber( &pSop );
+ assert( Index < Abc_ObjFaninNum(pObj) );
+ assert( Index != k );
+ // get the fanin
+ pFanin2 = Abc_ObjFanin( pObj, Index );
+ nValuesF2 = Abc_ObjMvVarNum(pFanin2);
+ pValuesF2 = (Abc_Obj_t **)pFanin2->pCopy;
+ // create the sum of products of values
+ assert( nValuesF == nValuesF2 );
+ pTemp2 = Abc_ObjNot( Abc_AigConst1(pNtkNew) );
+ for ( v = 0; v < nValues; v++ )
+ pTemp2 = Abc_AigOr( pNtkNew->pManFunc, pTemp2, Abc_AigAnd(pNtkNew->pManFunc, pValuesF[v], pValuesF2[v]) );
+ }
+ else
+ {
+ Index = Abc_StringGetNumber( &pSop );
+ assert( Index < nValuesF );
+ pTemp2 = pValuesF[Index];
+ }
+ // compute the compute
+ pTemp = Abc_AigAnd( pNtkNew->pManFunc, pTemp, pTemp2 );
+ // advance the reading point
+ assert( *pSop == ' ' );
+ pSop++;
+ }
+ // check if the output value is an equal construct
+ if ( *pSop == '=' )
+ {
+ pSop++;
+ // get the output value
+ Index = Abc_StringGetNumber( &pSop );
+ assert( Index < Abc_ObjFaninNum(pObj) );
+ // add values of the given fanin with the given cube
+ pFanin = Abc_ObjFanin( pObj, Index );
+ nValuesF = Abc_ObjMvVarNum(pFanin);
+ pValuesF = (Abc_Obj_t **)pFanin->pCopy;
+ assert( nValuesF == nValues ); // should be guaranteed by the parser
+ for ( k = 0; k < nValuesF; k++ )
+ pValues[k] = Abc_AigOr( pNtkNew->pManFunc, pValues[k], Abc_AigAnd(pNtkNew->pManFunc, pTemp, pValuesF[k]) );
+ }
+ else
+ {
+ // get the output value
+ Index = Abc_StringGetNumber( &pSop );
+ assert( Index < nValues );
+ pValues[Index] = Abc_AigOr( pNtkNew->pManFunc, pValues[Index], pTemp );
+ }
+ // advance the reading point
+ assert( *pSop == '\n' );
+ pSop++;
+ }
+
+ // compute the default value
+ if ( Def >= 0 || DefIndex >= 0 )
+ {
+ pTemp = Abc_AigConst1(pNtkNew);
+ for ( k = 0; k < nValues; k++ )
+ {
+ if ( k == Def )
+ continue;
+ pTemp = Abc_AigAnd( pNtkNew->pManFunc, pTemp, Abc_ObjNot(pValues[k]) );
+ }
+
+ // assign the default value
+ if ( Def >= 0 )
+ pValues[Def] = pTemp;
+ else
+ {
+ assert( DefIndex >= 0 );
+ // add values of the given fanin with the given cube
+ pFanin = Abc_ObjFanin( pObj, DefIndex );
+ nValuesF = Abc_ObjMvVarNum(pFanin);
+ pValuesF = (Abc_Obj_t **)pFanin->pCopy;
+ assert( nValuesF == nValues ); // should be guaranteed by the parser
+ for ( k = 0; k < nValuesF; k++ )
+ pValues[k] = Abc_AigOr( pNtkNew->pManFunc, pValues[k], Abc_AigAnd(pNtkNew->pManFunc, pTemp, pValuesF[k]) );
+ }
+
+ }
+
+ // save the values in the fanout net
+ pNet->pCopy = (Abc_Obj_t *)pValues;
+ return 1;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Assigns name with index.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+static inline void Abc_NtkConvertAssignName( Abc_Obj_t * pObj, Abc_Obj_t * pNet, int Index )
+{
+ char Suffix[16];
+ assert( Abc_ObjIsTerm(pObj) );
+ assert( Abc_ObjIsNet(pNet) );
+ sprintf( Suffix, "[%d]", Index );
+ Abc_ObjAssignName( pObj, Abc_ObjName(pNet), Suffix );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Strashes the BLIF-MV netlist.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Abc_Ntk_t * Abc_NtkStrashBlifMv( Abc_Ntk_t * pNtk )
+{
+ int fUsePositional = 0;
+ Vec_Ptr_t * vNodes;
+ Abc_Obj_t ** pBits;
+ Abc_Obj_t ** pValues;
+ Abc_Ntk_t * pNtkNew;
+ Abc_Obj_t * pObj, * pTemp, * pBit, * pNet;
+ int i, k, v, nValues, nValuesMax, nBits;
+
+ assert( Abc_NtkIsNetlist(pNtk) );
+ assert( Abc_NtkHasBlifMv(pNtk) );
+ assert( Abc_NtkWhiteboxNum(pNtk) == 0 );
+ assert( Abc_NtkBlackboxNum(pNtk) == 0 );
+
+ // get the largest number of values
+ nValuesMax = 2;
+ Abc_NtkForEachNet( pNtk, pObj, i )
+ {
+ nValues = Abc_ObjMvVarNum(pObj);
+ if ( nValuesMax < nValues )
+ nValuesMax = nValues;
+ }
+ nBits = Extra_Base2Log( nValuesMax );
+ pBits = ALLOC( Abc_Obj_t *, nBits );
+
+ // clean the node copy fields
+ Abc_NtkCleanCopy( pNtk );
+ // collect the nodes
+ vNodes = Abc_NtkDfs( pNtk, 0 );
+
+ // start the network
+ pNtkNew = Abc_NtkAlloc( ABC_NTK_STRASH, ABC_FUNC_AIG, 1 );
+ // duplicate the name and the spec
+ pNtkNew->pName = Extra_UtilStrsav( pNtk->pName );
+// pNtkNew->pSpec = Extra_UtilStrsav( pNtk->pName );
+
+ // encode the CI nets
+ Abc_NtkIncrementTravId( pNtk );
+ if ( fUsePositional )
+ {
+ Abc_NtkForEachCi( pNtk, pObj, i )
+ {
+ pNet = Abc_ObjFanout0(pObj);
+ nValues = Abc_ObjMvVarNum(pNet);
+ pValues = ALLOC( Abc_Obj_t *, nValues );
+ // create PIs for the values
+ for ( v = 0; v < nValues; v++ )
+ {
+ pValues[v] = Abc_NtkCreatePi( pNtkNew );
+ Abc_NtkConvertAssignName( pValues[v], pNet, v );
+ }
+ // save the values in the fanout net
+ pNet->pCopy = (Abc_Obj_t *)pValues;
+ // mark the net
+ Abc_NodeSetTravIdCurrent( pNet );
+ }
+ }
+ else
+ {
+ Abc_NtkForEachCi( pNtk, pObj, i )
+ {
+ pNet = Abc_ObjFanout0(pObj);
+ nValues = Abc_ObjMvVarNum(pNet);
+ pValues = ALLOC( Abc_Obj_t *, nValues );
+ // create PIs for the encoding bits
+ nBits = Extra_Base2Log( nValues );
+ for ( k = 0; k < nBits; k++ )
+ {
+ pBits[k] = Abc_NtkCreatePi( pNtkNew );
+ Abc_NtkConvertAssignName( pBits[k], pNet, k );
+ }
+ // encode the values
+ for ( v = 0; v < nValues; v++ )
+ {
+ pValues[v] = Abc_AigConst1(pNtkNew);
+ for ( k = 0; k < nBits; k++ )
+ {
+ pBit = Abc_ObjNotCond( pBits[k], (v&(1<<k)) == 0 );
+ pValues[v] = Abc_AigAnd( pNtkNew->pManFunc, pValues[v], pBit );
+ }
+ }
+ // save the values in the fanout net
+ pNet->pCopy = (Abc_Obj_t *)pValues;
+ // mark the net
+ Abc_NodeSetTravIdCurrent( pNet );
+ }
+ }
+
+ // process nodes in the topological order
+ Vec_PtrForEachEntry( vNodes, pObj, i )
+ if ( !Abc_NodeStrashBlifMv( pNtkNew, pObj ) )
+ {
+ Abc_NtkDelete( pNtkNew );
+ return NULL;
+ }
+ Vec_PtrFree( vNodes );
+
+ // encode the CO nets
+ if ( fUsePositional )
+ {
+ Abc_NtkForEachCo( pNtk, pObj, i )
+ {
+ pNet = Abc_ObjFanin0(pObj);
+ // skip marked nets
+ if ( Abc_NodeIsTravIdCurrent(pNet) )
+ continue;
+ Abc_NodeSetTravIdCurrent( pNet );
+ nValues = Abc_ObjMvVarNum(pNet);
+ pValues = (Abc_Obj_t **)pNet->pCopy;
+ for ( v = 0; v < nValues; v++ )
+ {
+ pTemp = Abc_NtkCreatePo( pNtkNew );
+ Abc_ObjAddFanin( pTemp, pValues[v] );
+ Abc_NtkConvertAssignName( pTemp, pNet, v );
+ }
+ }
+ }
+ else
+ {
+ Abc_NtkForEachCo( pNtk, pObj, i )
+ {
+ pNet = Abc_ObjFanin0(pObj);
+ // skip marked nets
+ if ( Abc_NodeIsTravIdCurrent(pNet) )
+ continue;
+ Abc_NodeSetTravIdCurrent( pNet );
+ nValues = Abc_ObjMvVarNum(pNet);
+ pValues = (Abc_Obj_t **)pNet->pCopy;
+ nBits = Extra_Base2Log( nValues );
+ for ( k = 0; k < nBits; k++ )
+ {
+ pBit = Abc_ObjNot( Abc_AigConst1(pNtkNew) );
+ for ( v = 0; v < nValues; v++ )
+ if ( v & (1<<k) )
+ pBit = Abc_AigOr( pNtkNew->pManFunc, pBit, pValues[v] );
+ pTemp = Abc_NtkCreatePo( pNtkNew );
+ Abc_ObjAddFanin( pTemp, pBit );
+ Abc_NtkConvertAssignName( pTemp, pNet, k );
+ }
+ }
+ }
+
+ // cleanup
+ free( pBits );
+ Abc_NtkForEachObj( pNtk, pObj, i )
+ if ( pObj->pCopy )
+ free( pObj->pCopy );
+
+ // remove dangling nodes
+ i = Abc_AigCleanup(pNtkNew->pManFunc);
+// printf( "Cleanup removed %d nodes.\n", i );
+// Abc_NtkReassignIds( pNtkNew );
+
+ // check integrity
+ if ( !Abc_NtkCheck( pNtkNew ) )
+ {
+ fprintf( stdout, "Abc_NtkStrashBlifMv(): Network check has failed.\n" );
+ Abc_NtkDelete( pNtkNew );
+ return NULL;
+ }
+ return pNtkNew;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Extract the MV-skeleton of the BLIF-MV network.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Abc_Ntk_t * Abc_NtkSkeletonBlifMv( Abc_Ntk_t * pNtk )
+{
+ int fUsePositional = 0;
+ Abc_Ntk_t * pNtkNew;
+ Abc_Obj_t * pObj, * pNet, * pNetNew, * pNodeNew, * pTermNew, * pBoxNew;
+ int i, k, v, nValues, nBits;
+
+ assert( Abc_NtkIsNetlist(pNtk) );
+ assert( Abc_NtkHasBlifMv(pNtk) );
+ assert( Abc_NtkWhiteboxNum(pNtk) == 0 );
+ assert( Abc_NtkBlackboxNum(pNtk) == 0 );
+
+ // clean the node copy fields
+ Abc_NtkCleanCopy( pNtk );
+
+ // start the network
+ pNtkNew = Abc_NtkAlloc( pNtk->ntkType, pNtk->ntkFunc, 1 );
+ // duplicate the name and the spec
+ pNtkNew->pName = Extra_UtilStrsav( pNtk->pName );
+ pNtkNew->pSpec = Extra_UtilStrsav( pNtk->pName );
+ // create the internal box (it is important to put it first!)
+ pBoxNew = Abc_NtkCreateWhitebox( pNtkNew );
+ // create PIs and their nets
+ Abc_NtkForEachPi( pNtk, pObj, i )
+ {
+ Abc_NtkDupObj( pNtkNew, pObj, 0 );
+ pNet = Abc_ObjFanout0(pObj);
+ Abc_NtkDupObj( pNtkNew, pNet, 1 );
+ Abc_ObjAddFanin( pNet->pCopy, pObj->pCopy );
+ }
+ // create POs and their nets
+ Abc_NtkForEachPo( pNtk, pObj, i )
+ {
+ Abc_NtkDupObj( pNtkNew, pObj, 0 );
+ pNet = Abc_ObjFanin0(pObj);
+ if ( pNet->pCopy == NULL )
+ Abc_NtkDupObj( pNtkNew, pNet, 1 );
+ Abc_ObjAddFanin( pObj->pCopy, pNet->pCopy );
+ }
+ // create latches
+ Abc_NtkForEachLatch( pNtk, pObj, i )
+ {
+ Abc_NtkDupBox( pNtkNew, pObj, 0 );
+ // latch outputs
+ pNet = Abc_ObjFanout0(Abc_ObjFanout0(pObj));
+ assert( pNet->pCopy == NULL );
+ Abc_NtkDupObj( pNtkNew, pNet, 1 );
+ Abc_ObjAddFanin( pNet->pCopy, Abc_ObjFanout0(pObj)->pCopy );
+ // latch inputs
+ pNet = Abc_ObjFanin0(Abc_ObjFanin0(pObj));
+ if ( pNet->pCopy == NULL )
+ Abc_NtkDupObj( pNtkNew, pNet, 1 );
+ Abc_ObjAddFanin( Abc_ObjFanin0(pObj)->pCopy, pNet->pCopy );
+ }
+
+ // encode the CI nets
+ Abc_NtkIncrementTravId( pNtk );
+ if ( fUsePositional )
+ {
+ Abc_NtkForEachCi( pNtk, pObj, i )
+ {
+ pNet = Abc_ObjFanout0(pObj);
+ nValues = Abc_ObjMvVarNum(pNet);
+ for ( v = 0; v < nValues; v++ )
+ {
+ pNodeNew = Abc_NtkCreateNode( pNtkNew );
+ pNodeNew->pData = Abc_SopEncoderPos( pNtkNew->pManFunc, v, nValues );
+ pNetNew = Abc_NtkCreateNet( pNtkNew );
+ pTermNew = Abc_NtkCreateBi( pNtkNew );
+ Abc_ObjAddFanin( pNodeNew, pNet->pCopy );
+ Abc_ObjAddFanin( pNetNew, pNodeNew );
+ Abc_ObjAddFanin( pTermNew, pNetNew );
+ Abc_ObjAddFanin( pBoxNew, pTermNew );
+ }
+ // mark the net
+ Abc_NodeSetTravIdCurrent( pNet );
+ }
+ }
+ else
+ {
+ Abc_NtkForEachCi( pNtk, pObj, i )
+ {
+ pNet = Abc_ObjFanout0(pObj);
+ nValues = Abc_ObjMvVarNum(pNet);
+ nBits = Extra_Base2Log( nValues );
+ for ( k = 0; k < nBits; k++ )
+ {
+ pNodeNew = Abc_NtkCreateNode( pNtkNew );
+ pNodeNew->pData = Abc_SopEncoderLog( pNtkNew->pManFunc, k, nValues );
+ pNetNew = Abc_NtkCreateNet( pNtkNew );
+ pTermNew = Abc_NtkCreateBi( pNtkNew );
+ Abc_ObjAddFanin( pNodeNew, pNet->pCopy );
+ Abc_ObjAddFanin( pNetNew, pNodeNew );
+ Abc_ObjAddFanin( pTermNew, pNetNew );
+ Abc_ObjAddFanin( pBoxNew, pTermNew );
+ }
+ // mark the net
+ Abc_NodeSetTravIdCurrent( pNet );
+ }
+ }
+
+ // encode the CO nets
+ if ( fUsePositional )
+ {
+ Abc_NtkForEachCo( pNtk, pObj, i )
+ {
+ pNet = Abc_ObjFanin0(pObj);
+ // skip marked nets
+ if ( Abc_NodeIsTravIdCurrent(pNet) )
+ continue;
+ Abc_NodeSetTravIdCurrent( pNet );
+ nValues = Abc_ObjMvVarNum(pNet);
+ pNodeNew = Abc_NtkCreateNode( pNtkNew );
+ pNodeNew->pData = Abc_SopDecoderPos( pNtkNew->pManFunc, nValues );
+ for ( v = 0; v < nValues; v++ )
+ {
+ pTermNew = Abc_NtkCreateBo( pNtkNew );
+ pNetNew = Abc_NtkCreateNet( pNtkNew );
+ Abc_ObjAddFanin( pTermNew, pBoxNew );
+ Abc_ObjAddFanin( pNetNew, pTermNew );
+ Abc_ObjAddFanin( pNodeNew, pNetNew );
+ }
+ Abc_ObjAddFanin( pNet->pCopy, pNodeNew );
+ }
+ }
+ else
+ {
+ Abc_NtkForEachCo( pNtk, pObj, i )
+ {
+ pNet = Abc_ObjFanin0(pObj);
+ // skip marked nets
+ if ( Abc_NodeIsTravIdCurrent(pNet) )
+ continue;
+ Abc_NodeSetTravIdCurrent( pNet );
+ nValues = Abc_ObjMvVarNum(pNet);
+ nBits = Extra_Base2Log( nValues );
+ pNodeNew = Abc_NtkCreateNode( pNtkNew );
+ pNodeNew->pData = Abc_SopDecoderLog( pNtkNew->pManFunc, nValues );
+ for ( k = 0; k < nBits; k++ )
+ {
+ pTermNew = Abc_NtkCreateBo( pNtkNew );
+ pNetNew = Abc_NtkCreateNet( pNtkNew );
+ Abc_ObjAddFanin( pTermNew, pBoxNew );
+ Abc_ObjAddFanin( pNetNew, pTermNew );
+ Abc_ObjAddFanin( pNodeNew, pNetNew );
+ }
+ Abc_ObjAddFanin( pNet->pCopy, pNodeNew );
+ }
+ }
+
+ // if it is a BLIF-MV netlist transfer the values of all nets
+ if ( Abc_NtkHasBlifMv(pNtk) && Abc_NtkMvVar(pNtk) )
+ {
+ if ( Abc_NtkMvVar( pNtkNew ) == NULL )
+ Abc_NtkStartMvVars( pNtkNew );
+ Abc_NtkForEachNet( pNtk, pObj, i )
+ if ( pObj->pCopy )
+ Abc_NtkSetMvVarValues( pObj->pCopy, Abc_ObjMvVarNum(pObj) );
+ }
+
+ // check integrity
+ if ( !Abc_NtkCheck( pNtkNew ) )
+ {
+ fprintf( stdout, "Abc_NtkSkeletonBlifMv(): Network check has failed.\n" );
+ Abc_NtkDelete( pNtkNew );
+ return NULL;
+ }
+ return pNtkNew;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Inserts processed network into original base MV network.]
+
+ Description [The original network remembers the interface of combinational
+ logic (PIs/POs/latches names and values). The processed network may
+ be binary or multi-valued (currently, multi-value is not supported).
+ The resulting network has the same interface as the original network
+ while the internal logic is the same as that of the processed network.]
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Abc_Ntk_t * Abc_NtkInsertBlifMv( Abc_Ntk_t * pNtkBase, Abc_Ntk_t * pNtkLogic )
+{
+ Abc_Ntk_t * pNtkSkel, * pNtkNew;
+ Abc_Obj_t * pBox;
+
+ assert( Abc_NtkIsNetlist(pNtkBase) );
+ assert( Abc_NtkHasBlifMv(pNtkBase) );
+ assert( Abc_NtkWhiteboxNum(pNtkBase) == 0 );
+ assert( Abc_NtkBlackboxNum(pNtkBase) == 0 );
+
+ assert( Abc_NtkIsNetlist(pNtkLogic) );
+ assert( Abc_NtkHasBlifMv(pNtkLogic) );
+ assert( Abc_NtkWhiteboxNum(pNtkLogic) == 0 );
+ assert( Abc_NtkBlackboxNum(pNtkLogic) == 0 );
+
+ // extract the skeleton of the old network
+ pNtkSkel = Abc_NtkSkeletonBlifMv( pNtkBase );
+
+ // set the implementation of the box to be the same as the processed network
+ assert( Abc_NtkWhiteboxNum(pNtkSkel) == 1 );
+ pBox = Abc_NtkBox( pNtkSkel, 0 );
+ assert( Abc_ObjIsWhitebox(pBox) );
+ assert( pBox->pData == NULL );
+ assert( Abc_ObjFaninNum(pBox) == Abc_NtkPiNum(pNtkLogic) );
+ assert( Abc_ObjFanoutNum(pBox) == Abc_NtkPoNum(pNtkLogic) );
+ pBox->pData = pNtkLogic;
+
+ // flatten the hierarchy to insert the processed network
+ pNtkNew = Abc_NtkFlattenLogicHierarchy( pNtkSkel );
+ pBox->pData = NULL;
+ Abc_NtkDelete( pNtkSkel );
+ return pNtkNew;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Converts SOP netlist into BLIF-MV netlist.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Abc_NtkConvertToBlifMv( Abc_Ntk_t * pNtk )
+{
+ Extra_MmFlex_t * pMmFlex;
+ Abc_Obj_t * pNode;
+ Vec_Str_t * vCube;
+ char * pSop0, * pSop1, * pBlifMv, * pCube, * pCur;
+ int Value, nCubes, nSize, i, k;
+
+ assert( Abc_NtkIsNetlist(pNtk) );
+ if ( !Abc_NtkToBdd(pNtk) )
+ {
+ printf( "Converting logic functions to BDDs has failed.\n" );
+ return 0;
+ }
+
+ pMmFlex = Extra_MmFlexStart();
+ vCube = Vec_StrAlloc( 100 );
+ Abc_NtkForEachNode( pNtk, pNode, i )
+ {
+ // convert BDD into cubes for on-set and off-set
+ Abc_NodeBddToCnf( pNode, pMmFlex, vCube, 0, &pSop0, &pSop1 );
+ // allocate room for the MV-SOP
+ nCubes = Abc_SopGetCubeNum(pSop0) + Abc_SopGetCubeNum(pSop1);
+ nSize = nCubes*(2*Abc_ObjFaninNum(pNode) + 2)+1;
+ pBlifMv = Extra_MmFlexEntryFetch( pMmFlex, nSize );
+ // add the cubes
+ pCur = pBlifMv;
+ Abc_SopForEachCube( pSop0, Abc_ObjFaninNum(pNode), pCube )
+ {
+ Abc_CubeForEachVar( pCube, Value, k )
+ {
+ *pCur++ = Value;
+ *pCur++ = ' ';
+ }
+ *pCur++ = '0';
+ *pCur++ = '\n';
+ }
+ Abc_SopForEachCube( pSop1, Abc_ObjFaninNum(pNode), pCube )
+ {
+ Abc_CubeForEachVar( pCube, Value, k )
+ {
+ *pCur++ = Value;
+ *pCur++ = ' ';
+ }
+ *pCur++ = '1';
+ *pCur++ = '\n';
+ }
+ *pCur++ = 0;
+ assert( pCur - pBlifMv == nSize );
+ // update the node representation
+ Cudd_RecursiveDeref( pNtk->pManFunc, pNode->pData );
+ pNode->pData = pBlifMv;
+ }
+
+ // update the functionality type
+ pNtk->ntkFunc = ABC_FUNC_BLIFMV;
+ Cudd_Quit( pNtk->pManFunc );
+ pNtk->pManFunc = pMmFlex;
+
+ Vec_StrFree( vCube );
+ return 1;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Converts SOP into MV-SOP.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+char * Abc_NodeConvertSopToMvSop( int nVars, Vec_Int_t * vSop0, Vec_Int_t * vSop1 )
+{
+ char * pMvSop, * pCur;
+ unsigned uCube;
+ int nCubes, nSize, Value, i, k;
+ // consider the case of the constant node
+ if ( Vec_IntSize(vSop0) == 0 || Vec_IntSize(vSop1) == 0 )
+ {
+ // (temporary) create a tautology cube
+ pMvSop = ALLOC( char, nVars + 3 );
+ for ( k = 0; k < nVars; k++ )
+ pMvSop[k] = '-';
+ pMvSop[nVars] = '0' + (int)(Vec_IntSize(vSop1) > 0);
+ pMvSop[nVars+1] = '\n';
+ pMvSop[nVars+2] = 0;
+ return pMvSop;
+ }
+ // find the total number of cubes
+ nCubes = Vec_IntSize(vSop0) + Vec_IntSize(vSop1);
+ // find the size of the MVSOP represented as a C-string
+ // (each cube has nVars variables + one output literal + end-of-line,
+ // and the string is zero-terminated)
+ nSize = nCubes * (nVars + 2) + 1;
+ // allocate memory
+ pMvSop = pCur = ALLOC( char, nSize );
+ // fill in the negative polarity cubes
+ Vec_IntForEachEntry( vSop0, uCube, i )
+ {
+ for ( k = 0; k < nVars; k++ )
+ {
+ Value = (uCube >> (2*k)) & 3;
+ if ( Value == 1 )
+ *pCur++ = '0';
+ else if ( Value == 2 )
+ *pCur++ = '1';
+ else if ( Value == 0 )
+ *pCur++ = '-';
+ else
+ assert( 0 );
+ }
+ *pCur++ = '0';
+ *pCur++ = '\n';
+ }
+ // fill in the positive polarity cubes
+ Vec_IntForEachEntry( vSop1, uCube, i )
+ {
+ for ( k = 0; k < nVars; k++ )
+ {
+ Value = (uCube >> (2*k)) & 3;
+ if ( Value == 1 )
+ *pCur++ = '0';
+ else if ( Value == 2 )
+ *pCur++ = '1';
+ else if ( Value == 0 )
+ *pCur++ = '-';
+ else
+ assert( 0 );
+ }
+ *pCur++ = '1';
+ *pCur++ = '\n';
+ }
+ *pCur++ = 0;
+ assert( pCur - pMvSop == nSize );
+ return pMvSop;
+}
+
+
+/**Function*************************************************************
+
+ Synopsis [A prototype of internal cost evaluation procedure.]
+
+ Description [This procedure takes the number of variables (nVars),
+ the array of values of the inputs and the output (pVarValues)
+ (note that this array has nVars+1 entries), and an MV-SOP represented
+ as a C-string with one charater for each literal, including inputs
+ and output. Each cube is terminated with the new-line character ('\n').
+ The string is zero-terminated.]
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Abc_NodeEvalMvCostInternal( int nVars, int * pVarValues, char * pMvSop )
+{
+ // for now, return the number of cubes in the MV-SOP
+ int Counter = 0;
+ while ( *pMvSop ) Counter += (*pMvSop++ == '\n');
+ return Counter;
+}
+
+
+/**Function*************************************************************
+
+ Synopsis [Evaluates the cost of the cut.]
+
+ Description [The Boolean function of the cut is specified by two SOPs,
+ which represent the negative/positive polarities of the cut function.
+ Converts these two SOPs into a mutually-agreed-upon representation
+ to be passed to the internal cost-evaluation procedure (see the above
+ prototype Abc_NodeEvalMvCostInternal).]
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Abc_NodeEvalMvCost( int nVars, Vec_Int_t * vSop0, Vec_Int_t * vSop1 )
+{
+ char * pMvSop;
+ int * pVarValues;
+ int i, RetValue;
+ // collect the input and output values (currently, they are binary)
+ pVarValues = ALLOC( int, nVars + 1 );
+ for ( i = 0; i <= nVars; i++ )
+ pVarValues[i] = 2;
+ // prepare MV-SOP for evaluation
+ pMvSop = Abc_NodeConvertSopToMvSop( nVars, vSop0, vSop1 );
+ // have a look at the MV-SOP:
+// printf( "%s\n", pMvSop );
+ // get the result of internal cost evaluation
+ RetValue = Abc_NodeEvalMvCostInternal( nVars, pVarValues, pMvSop );
+ // cleanup
+ free( pVarValues );
+ free( pMvSop );
+ return RetValue;
+}
+
+////////////////////////////////////////////////////////////////////////
+/// END OF FILE ///
+////////////////////////////////////////////////////////////////////////
+
+
diff --git a/src/base/abc/abcCheck.c b/src/base/abc/abcCheck.c
index 1d23d7ed..79b76348 100644
--- a/src/base/abc/abcCheck.c
+++ b/src/base/abc/abcCheck.c
@@ -20,12 +20,12 @@
#include "abc.h"
#include "main.h"
+//#include "seq.h"
////////////////////////////////////////////////////////////////////////
/// DECLARATIONS ///
////////////////////////////////////////////////////////////////////////
-static bool Abc_NtkDoCheck( Abc_Ntk_t * pNtk );
static bool Abc_NtkCheckNames( Abc_Ntk_t * pNtk );
static bool Abc_NtkCheckPis( Abc_Ntk_t * pNtk );
static bool Abc_NtkCheckPos( Abc_Ntk_t * pNtk );
@@ -38,8 +38,10 @@ static bool Abc_NtkComparePis( Abc_Ntk_t * pNtk1, Abc_Ntk_t * pNtk2, int fComb )
static bool Abc_NtkComparePos( Abc_Ntk_t * pNtk1, Abc_Ntk_t * pNtk2, int fComb );
static bool Abc_NtkCompareLatches( Abc_Ntk_t * pNtk1, Abc_Ntk_t * pNtk2, int fComb );
+static inline char * Abc_ObjNameNet( Abc_Obj_t * pObj ) { return (Abc_ObjIsNode(pObj) && Abc_NtkIsNetlist(pObj->pNtk)) ? Abc_ObjName(Abc_ObjFanout0(pObj)) : Abc_ObjName(pObj); }
+
////////////////////////////////////////////////////////////////////////
-/// FUNCTION DEFITIONS ///
+/// FUNCTION DEFINITIONS ///
////////////////////////////////////////////////////////////////////////
/**Function*************************************************************
@@ -54,7 +56,7 @@ static bool Abc_NtkCompareLatches( Abc_Ntk_t * pNtk1, Abc_Ntk_t * pNtk2, int fCo
***********************************************************************/
bool Abc_NtkCheck( Abc_Ntk_t * pNtk )
-{
+{
return !Abc_FrameIsFlagEnabled( "check" ) || Abc_NtkDoCheck( pNtk );
}
@@ -90,25 +92,45 @@ bool Abc_NtkDoCheck( Abc_Ntk_t * pNtk )
Abc_Obj_t * pObj, * pNet, * pNode;
int i;
- if ( !Abc_NtkIsNetlist(pNtk) && !Abc_NtkIsLogic(pNtk) && !Abc_NtkIsStrash(pNtk) && !Abc_NtkIsSeq(pNtk) )
+ // check network types
+ if ( !Abc_NtkIsNetlist(pNtk) && !Abc_NtkIsLogic(pNtk) && !Abc_NtkIsStrash(pNtk) )
{
fprintf( stdout, "NetworkCheck: Unknown network type.\n" );
return 0;
}
- if ( !Abc_NtkHasSop(pNtk) && !Abc_NtkHasBdd(pNtk) && !Abc_NtkHasAig(pNtk) && !Abc_NtkHasMapping(pNtk) )
+ if ( !Abc_NtkHasSop(pNtk) && !Abc_NtkHasBdd(pNtk) && !Abc_NtkHasAig(pNtk) && !Abc_NtkHasMapping(pNtk) && !Abc_NtkHasBlifMv(pNtk) && !Abc_NtkHasBlackbox(pNtk) )
{
fprintf( stdout, "NetworkCheck: Unknown functionality type.\n" );
return 0;
}
if ( Abc_NtkHasMapping(pNtk) )
{
- if ( pNtk->pManFunc != Abc_FrameReadLibGen(Abc_FrameGetGlobalFrame()) )
+ if ( pNtk->pManFunc != Abc_FrameReadLibGen() )
{
fprintf( stdout, "NetworkCheck: The library of the mapped network is not the global library.\n" );
return 0;
}
}
+ if ( Abc_NtkHasOnlyLatchBoxes(pNtk) )
+ {
+ // check CI/CO numbers
+ if ( Abc_NtkPiNum(pNtk) + Abc_NtkLatchNum(pNtk) != Abc_NtkCiNum(pNtk) )
+ {
+ fprintf( stdout, "NetworkCheck: Number of CIs does not match number of PIs and latches.\n" );
+ fprintf( stdout, "One possible reason is that latches are added twice:\n" );
+ fprintf( stdout, "in procedure Abc_NtkCreateObj() and in the user's code.\n" );
+ return 0;
+ }
+ if ( Abc_NtkPoNum(pNtk) + Abc_NtkAssertNum(pNtk) + Abc_NtkLatchNum(pNtk) != Abc_NtkCoNum(pNtk) )
+ {
+ fprintf( stdout, "NetworkCheck: Number of COs does not match number of POs, asserts, and latches.\n" );
+ fprintf( stdout, "One possible reason is that latches are added twice:\n" );
+ fprintf( stdout, "in procedure Abc_NtkCreateObj() and in the user's code.\n" );
+ return 0;
+ }
+ }
+
// check the names
if ( !Abc_NtkCheckNames( pNtk ) )
return 0;
@@ -120,6 +142,9 @@ bool Abc_NtkDoCheck( Abc_Ntk_t * pNtk )
if ( !Abc_NtkCheckPos( pNtk ) )
return 0;
+ if ( Abc_NtkHasBlackbox(pNtk) )
+ return 1;
+
// check the connectivity of objects
Abc_NtkForEachObj( pNtk, pObj, i )
if ( !Abc_NtkCheckObj( pNtk, pObj ) )
@@ -148,11 +173,8 @@ bool Abc_NtkDoCheck( Abc_Ntk_t * pNtk )
}
// check the nodes
- if ( Abc_NtkHasAig(pNtk) )
- {
- if ( Abc_NtkIsStrash(pNtk) )
- Abc_AigCheck( pNtk->pManFunc );
- }
+ if ( Abc_NtkIsStrash(pNtk) )
+ Abc_AigCheck( pNtk->pManFunc );
else
{
Abc_NtkForEachNode( pNtk, pNode, i )
@@ -167,7 +189,7 @@ bool Abc_NtkDoCheck( Abc_Ntk_t * pNtk )
// finally, check for combinational loops
// clk = clock();
- if ( !Abc_NtkIsSeq( pNtk ) && !Abc_NtkIsAcyclic( pNtk ) )
+ if ( !Abc_NtkIsAcyclic( pNtk ) )
{
fprintf( stdout, "NetworkCheck: Network contains a combinational loop.\n" );
return 0;
@@ -176,14 +198,29 @@ bool Abc_NtkDoCheck( Abc_Ntk_t * pNtk )
// check the EXDC network if present
if ( pNtk->pExdc )
- {
-// if ( pNtk->Type != pNtk->pExdc->Type )
-// {
-// fprintf( stdout, "NetworkCheck: Network and its EXDC have different types.\n" );
-// return 0;
-// }
- return Abc_NtkCheck( pNtk->pExdc );
+ Abc_NtkCheck( pNtk->pExdc );
+/*
+ // check the hierarchy
+ if ( Abc_NtkIsNetlist(pNtk) && pNtk->tName2Model )
+ {
+ stmm_generator * gen;
+ Abc_Ntk_t * pNtkTemp;
+ char * pName;
+ // check other networks
+ stmm_foreach_item( pNtk->tName2Model, gen, &pName, (char **)&pNtkTemp )
+ {
+ pNtkTemp->fHiePath = pNtkTemp->fHieVisited = 0;
+ if ( !Abc_NtkCheck( pNtkTemp ) )
+ return 0;
+ }
+ // check acyclic dependency of the models
+ if ( !Abc_NtkIsAcyclicHierarchy( pNtk ) )
+ {
+ fprintf( stdout, "NetworkCheck: Network hierarchical dependences contains a cycle.\n" );
+ return 0;
+ }
}
+*/
return 1;
}
@@ -200,73 +237,61 @@ bool Abc_NtkDoCheck( Abc_Ntk_t * pNtk )
***********************************************************************/
bool Abc_NtkCheckNames( Abc_Ntk_t * pNtk )
{
- stmm_generator * gen;
- Abc_Obj_t * pNet, * pNet2, * pObj;
+ Abc_Obj_t * pObj;
+ Vec_Int_t * vNameIds;
char * pName;
- int i;
+ int i, NameId;
if ( Abc_NtkIsNetlist(pNtk) )
- {
- // check that the nets in the table are also in the network
- stmm_foreach_item( pNtk->tName2Net, gen, &pName, (char**)&pNet )
- {
- if ( pNet->pData != pName )
- {
- fprintf( stdout, "NetworkCheck: Net \"%s\" has different name compared to the one in the name table.\n", pNet->pData );
- return 0;
- }
- }
- // check that the nets with names are also in the table
- Abc_NtkForEachNet( pNtk, pNet, i )
- {
- if ( pNet->pData && !stmm_lookup( pNtk->tName2Net, pNet->pData, (char**)&pNet2 ) )
- {
- fprintf( stdout, "NetworkCheck: Net \"%s\" is in the network but not in the name table.\n", pNet->pData );
- return 0;
- }
- }
- }
+ return 1;
- // check PI/PO/latch names
- Abc_NtkForEachPi( pNtk, pObj, i )
+ // check that each CI/CO has a name
+ Abc_NtkForEachCi( pNtk, pObj, i )
{
- if ( !stmm_lookup( pNtk->tObj2Name, (char *)pObj, &pName ) )
- {
- fprintf( stdout, "NetworkCheck: PI \"%s\" is in the network but not in the name table.\n", Abc_ObjName(pObj) );
- return 0;
- }
- if ( Abc_NtkIsNetlist(pNtk) && strcmp( Abc_ObjName(Abc_ObjFanout0(pObj)), pName ) )
+ pObj = Abc_ObjFanout0Ntk(pObj);
+ if ( Nm_ManFindNameById(pObj->pNtk->pManName, pObj->Id) == NULL )
{
- fprintf( stdout, "NetworkCheck: PI \"%s\" has a different name compared to its net.\n", Abc_ObjName(pObj) );
+ fprintf( stdout, "NetworkCheck: CI with ID %d is in the network but not in the name table.\n", pObj->Id );
return 0;
}
}
- Abc_NtkForEachPo( pNtk, pObj, i )
+ Abc_NtkForEachCo( pNtk, pObj, i )
{
- if ( !stmm_lookup( pNtk->tObj2Name, (char *)pObj, &pName ) )
- {
- fprintf( stdout, "NetworkCheck: PO \"%s\" is in the network but not in the name table.\n", Abc_ObjName(pObj) );
- return 0;
- }
- if ( Abc_NtkIsNetlist(pNtk) && strcmp( Abc_ObjName(Abc_ObjFanin0(pObj)), pName ) )
+ pObj = Abc_ObjFanin0Ntk(pObj);
+ if ( Nm_ManFindNameById(pObj->pNtk->pManName, pObj->Id) == NULL )
{
- fprintf( stdout, "NetworkCheck: PO \"%s\" has a different name compared to its net.\n", Abc_ObjName(pObj) );
+ fprintf( stdout, "NetworkCheck: CO with ID %d is in the network but not in the name table.\n", pObj->Id );
return 0;
}
}
- Abc_NtkForEachLatch( pNtk, pObj, i )
+
+ // return the array of all IDs, which have names
+ vNameIds = Nm_ManReturnNameIds( pNtk->pManName );
+ // make sure that these IDs correspond to live objects
+ Vec_IntForEachEntry( vNameIds, NameId, i )
{
- if ( !stmm_lookup( pNtk->tObj2Name, (char *)pObj, &pName ) )
+ if ( Vec_PtrEntry( pNtk->vObjs, NameId ) == NULL )
{
- fprintf( stdout, "NetworkCheck: Latch \"%s\" is in the network but not in the name table.\n", Abc_ObjName(pObj) );
- return 0;
- }
- if ( Abc_NtkIsNetlist(pNtk) && strcmp( Abc_ObjName(Abc_ObjFanout0(pObj)), pName ) )
- {
- fprintf( stdout, "NetworkCheck: Latch \"%s\" has a different name compared to its net.\n", Abc_ObjName(pObj) );
+ Vec_IntFree( vNameIds );
+ pName = Nm_ManFindNameById(pObj->pNtk->pManName, NameId);
+ fprintf( stdout, "NetworkCheck: Object with ID %d is deleted but its name \"%s\" remains in the name table.\n", NameId, pName );
return 0;
}
}
+ Vec_IntFree( vNameIds );
+
+ // make sure the CI names are unique
+ if ( !Abc_NtkCheckUniqueCiNames(pNtk) )
+ return 0;
+
+ // make sure the CO names are unique
+ if ( !Abc_NtkCheckUniqueCoNames(pNtk) )
+ return 0;
+
+ // make sure that if a CO has the same name as a CI, they point directly
+ if ( !Abc_NtkCheckUniqueCioNames(pNtk) )
+ return 0;
+
return 1;
}
@@ -287,12 +312,6 @@ bool Abc_NtkCheckPis( Abc_Ntk_t * pNtk )
Abc_Obj_t * pObj;
int i;
- if ( Abc_NtkCiNum(pNtk) != Abc_NtkPiNum(pNtk) + Abc_NtkLatchNum(pNtk) )
- {
- fprintf( stdout, "NetworkCheck: Incorrect size of the PI array.\n" );
- return 0;
- }
-
// check that PIs are indeed PIs
Abc_NtkForEachPi( pNtk, pObj, i )
{
@@ -341,12 +360,6 @@ bool Abc_NtkCheckPos( Abc_Ntk_t * pNtk )
Abc_Obj_t * pObj;
int i;
- if ( Abc_NtkCoNum(pNtk) != Abc_NtkPoNum(pNtk) + Abc_NtkLatchNum(pNtk) )
- {
- fprintf( stdout, "NetworkCheck: Incorrect size of the PO array.\n" );
- return 0;
- }
-
// check that POs are indeed POs
Abc_NtkForEachPo( pNtk, pObj, i )
{
@@ -414,10 +427,14 @@ bool Abc_NtkCheckObj( Abc_Ntk_t * pNtk, Abc_Obj_t * pObj )
fprintf( stdout, "NetworkCheck: Object \"%s\" has incorrect ID.\n", Abc_ObjName(pObj) );
return 0;
}
+
+ if ( !Abc_FrameIsFlagEnabled("checkfio") )
+ return Value;
+
// go through the fanins of the object and make sure fanins have this object as a fanout
Abc_ObjForEachFanin( pObj, pFanin, i )
{
- if ( Vec_FanFindEntry( &pFanin->vFanouts, pObj->Id ) == -1 )
+ if ( Vec_IntFind( &pFanin->vFanouts, pObj->Id ) == -1 )
{
fprintf( stdout, "NodeCheck: Object \"%s\" has fanin ", Abc_ObjName(pObj) );
fprintf( stdout, "\"%s\" but the fanin does not have it as a fanout.\n", Abc_ObjName(pFanin) );
@@ -427,7 +444,7 @@ bool Abc_NtkCheckObj( Abc_Ntk_t * pNtk, Abc_Obj_t * pObj )
// go through the fanouts of the object and make sure fanouts have this object as a fanin
Abc_ObjForEachFanout( pObj, pFanout, i )
{
- if ( Vec_FanFindEntry( &pFanout->vFanins, pObj->Id ) == -1 )
+ if ( Vec_IntFind( &pFanout->vFanins, pObj->Id ) == -1 )
{
fprintf( stdout, "NodeCheck: Object \"%s\" has fanout ", Abc_ObjName(pObj) );
fprintf( stdout, "\"%s\" but the fanout does not have it as a fanin.\n", Abc_ObjName(pFanout) );
@@ -435,13 +452,10 @@ bool Abc_NtkCheckObj( Abc_Ntk_t * pNtk, Abc_Obj_t * pObj )
}
}
- if ( !Abc_FrameIsFlagEnabled("checkfio") )
- return Value;
-
// make sure fanins are not duplicated
for ( i = 0; i < pObj->vFanins.nSize; i++ )
for ( k = i + 1; k < pObj->vFanins.nSize; k++ )
- if ( pObj->vFanins.pArray[k].iFan == pObj->vFanins.pArray[i].iFan )
+ if ( pObj->vFanins.pArray[k] == pObj->vFanins.pArray[i] )
{
printf( "Warning: Node %s has", Abc_ObjName(pObj) );
printf( " duplicated fanin %s.\n", Abc_ObjName(Abc_ObjFanin(pObj,k)) );
@@ -454,7 +468,7 @@ bool Abc_NtkCheckObj( Abc_Ntk_t * pNtk, Abc_Obj_t * pObj )
// make sure fanouts are not duplicated
for ( i = 0; i < pObj->vFanouts.nSize; i++ )
for ( k = i + 1; k < pObj->vFanouts.nSize; k++ )
- if ( pObj->vFanouts.pArray[k].iFan == pObj->vFanouts.pArray[i].iFan )
+ if ( pObj->vFanouts.pArray[k] == pObj->vFanouts.pArray[i] )
{
printf( "Warning: Node %s has", Abc_ObjName(pObj) );
printf( " duplicated fanout %s.\n", Abc_ObjName(Abc_ObjFanout(pObj,k)) );
@@ -511,7 +525,7 @@ bool Abc_NtkCheckNode( Abc_Ntk_t * pNtk, Abc_Obj_t * pNode )
// the node should have a function assigned unless it is an AIG
if ( pNode->pData == NULL )
{
- fprintf( stdout, "NodeCheck: An internal node \"%s\" does not have a logic function.\n", Abc_ObjName(pNode) );
+ fprintf( stdout, "NodeCheck: An internal node \"%s\" does not have a logic function.\n", Abc_ObjNameNet(pNode) );
return 0;
}
// the netlist and SOP logic network should have SOPs
@@ -519,7 +533,7 @@ bool Abc_NtkCheckNode( Abc_Ntk_t * pNtk, Abc_Obj_t * pNode )
{
if ( !Abc_SopCheck( pNode->pData, Abc_ObjFaninNum(pNode) ) )
{
- fprintf( stdout, "NodeCheck: SOP check for node \"%s\" has failed.\n", Abc_ObjName(pNode) );
+ fprintf( stdout, "NodeCheck: SOP check for node \"%s\" has failed.\n", Abc_ObjNameNet(pNode) );
return 0;
}
}
@@ -528,11 +542,11 @@ bool Abc_NtkCheckNode( Abc_Ntk_t * pNtk, Abc_Obj_t * pNode )
int nSuppSize = Cudd_SupportSize(pNtk->pManFunc, pNode->pData);
if ( nSuppSize > Abc_ObjFaninNum(pNode) )
{
- fprintf( stdout, "NodeCheck: BDD of the node \"%s\" has incorrect support size.\n", Abc_ObjName(pNode) );
+ fprintf( stdout, "NodeCheck: BDD of the node \"%s\" has incorrect support size.\n", Abc_ObjNameNet(pNode) );
return 0;
}
}
- else if ( !Abc_NtkHasMapping(pNtk) )
+ else if ( !Abc_NtkHasMapping(pNtk) && !Abc_NtkHasBlifMv(pNtk) && !Abc_NtkHasAig(pNtk) )
{
assert( 0 );
}
@@ -553,19 +567,14 @@ bool Abc_NtkCheckNode( Abc_Ntk_t * pNtk, Abc_Obj_t * pNode )
bool Abc_NtkCheckLatch( Abc_Ntk_t * pNtk, Abc_Obj_t * pLatch )
{
int Value = 1;
- if ( pNtk->vLats->nSize != Abc_NtkLatchNum(pNtk) )
- {
- fprintf( stdout, "NetworkCheck: Incorrect size of the latch array.\n" );
- return 0;
- }
// check whether the object is a latch
if ( !Abc_ObjIsLatch(pLatch) )
{
- fprintf( stdout, "NodeCheck: Latch \"%s\" is in a latch list but has not latch label.\n", Abc_ObjName(pLatch) );
+ fprintf( stdout, "NodeCheck: Latch \"%s\" is in a latch list but is not a latch.\n", Abc_ObjName(pLatch) );
Value = 0;
}
// make sure the latch has a reasonable return value
- if ( (int)pLatch->pData < 0 || (int)pLatch->pData > 2 )
+ if ( (int)pLatch->pData < ABC_INIT_ZERO || (int)pLatch->pData > ABC_INIT_DC )
{
fprintf( stdout, "NodeCheck: Latch \"%s\" has incorrect reset value (%d).\n",
Abc_ObjName(pLatch), (int)pLatch->pData );
@@ -577,6 +586,33 @@ bool Abc_NtkCheckLatch( Abc_Ntk_t * pNtk, Abc_Obj_t * pLatch )
fprintf( stdout, "NodeCheck: Latch \"%s\" has wrong number (%d) of fanins.\n", Abc_ObjName(pLatch), Abc_ObjFaninNum(pLatch) );
Value = 0;
}
+ // make sure the latch has only one fanout
+ if ( Abc_ObjFanoutNum(pLatch) != 1 )
+ {
+ fprintf( stdout, "NodeCheck: Latch \"%s\" has wrong number (%d) of fanouts.\n", Abc_ObjName(pLatch), Abc_ObjFanoutNum(pLatch) );
+ Value = 0;
+ }
+ // make sure the latch input has only one fanin
+ if ( Abc_ObjFaninNum(Abc_ObjFanin0(pLatch)) != 1 )
+ {
+ fprintf( stdout, "NodeCheck: Input of latch \"%s\" has wrong number (%d) of fanins.\n",
+ Abc_ObjName(Abc_ObjFanin0(pLatch)), Abc_ObjFaninNum(Abc_ObjFanin0(pLatch)) );
+ Value = 0;
+ }
+ // make sure the latch input has only one fanout
+ if ( Abc_ObjFanoutNum(Abc_ObjFanin0(pLatch)) != 1 )
+ {
+ fprintf( stdout, "NodeCheck: Input of latch \"%s\" has wrong number (%d) of fanouts.\n",
+ Abc_ObjName(Abc_ObjFanin0(pLatch)), Abc_ObjFanoutNum(Abc_ObjFanin0(pLatch)) );
+ Value = 0;
+ }
+ // make sure the latch output has only one fanin
+ if ( Abc_ObjFaninNum(Abc_ObjFanout0(pLatch)) != 1 )
+ {
+ fprintf( stdout, "NodeCheck: Output of latch \"%s\" has wrong number (%d) of fanins.\n",
+ Abc_ObjName(Abc_ObjFanout0(pLatch)), Abc_ObjFaninNum(Abc_ObjFanout0(pLatch)) );
+ Value = 0;
+ }
return Value;
}
@@ -660,24 +696,26 @@ bool Abc_NtkComparePos( Abc_Ntk_t * pNtk1, Abc_Ntk_t * pNtk2, int fComb )
SeeAlso []
***********************************************************************/
-bool Abc_NtkCompareLatches( Abc_Ntk_t * pNtk1, Abc_Ntk_t * pNtk2, int fComb )
+bool Abc_NtkCompareBoxes( Abc_Ntk_t * pNtk1, Abc_Ntk_t * pNtk2, int fComb )
{
Abc_Obj_t * pObj1;
int i;
+ assert( Abc_NtkHasOnlyLatchBoxes(pNtk1) );
+ assert( Abc_NtkHasOnlyLatchBoxes(pNtk2) );
if ( !fComb )
return 1;
- if ( Abc_NtkLatchNum(pNtk1) != Abc_NtkLatchNum(pNtk2) )
+ if ( Abc_NtkBoxNum(pNtk1) != Abc_NtkBoxNum(pNtk2) )
{
printf( "Networks have different number of latches.\n" );
return 0;
}
// for each PI of pNet1 find corresponding PI of pNet2 and reorder them
- Abc_NtkForEachLatch( pNtk1, pObj1, i )
+ Abc_NtkForEachBox( pNtk1, pObj1, i )
{
- if ( strcmp( Abc_ObjName(pObj1), Abc_ObjName(Abc_NtkLatch(pNtk2,i)) ) != 0 )
+ if ( strcmp( Abc_ObjName(Abc_ObjFanout0(pObj1)), Abc_ObjName(Abc_ObjFanout0(Abc_NtkBox(pNtk2,i))) ) != 0 )
{
- printf( "Latch #%d is different in network 1 ( \"%s\") and in network 2 (\"%s\").\n",
- i, Abc_ObjName(pObj1), Abc_ObjName(Abc_NtkLatch(pNtk2,i)) );
+ printf( "Box #%d is different in network 1 ( \"%s\") and in network 2 (\"%s\").\n",
+ i, Abc_ObjName(Abc_ObjFanout0(pObj1)), Abc_ObjName(Abc_ObjFanout0(Abc_NtkBox(pNtk2,i))) );
return 0;
}
}
@@ -695,19 +733,207 @@ bool Abc_NtkCompareLatches( Abc_Ntk_t * pNtk1, Abc_Ntk_t * pNtk2, int fComb )
SeeAlso []
***********************************************************************/
-bool Abc_NtkCompareSignals( Abc_Ntk_t * pNtk1, Abc_Ntk_t * pNtk2, int fComb )
+bool Abc_NtkCompareSignals( Abc_Ntk_t * pNtk1, Abc_Ntk_t * pNtk2, int fOnlyPis, int fComb )
{
Abc_NtkOrderObjsByName( pNtk1, fComb );
Abc_NtkOrderObjsByName( pNtk2, fComb );
- if ( !Abc_NtkCompareLatches( pNtk1, pNtk2, fComb ) )
- return 0;
if ( !Abc_NtkComparePis( pNtk1, pNtk2, fComb ) )
return 0;
- if ( !Abc_NtkComparePos( pNtk1, pNtk2, fComb ) )
- return 0;
+ if ( !fOnlyPis )
+ {
+ if ( !Abc_NtkCompareBoxes( pNtk1, pNtk2, fComb ) )
+ return 0;
+ if ( !Abc_NtkComparePos( pNtk1, pNtk2, fComb ) )
+ return 0;
+ }
return 1;
}
+/**Function*************************************************************
+
+ Synopsis [Returns 0 if the network hierachy contains a cycle.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Abc_NtkIsAcyclicHierarchy_rec( Abc_Ntk_t * pNtk )
+{
+ Abc_Ntk_t * pNtkNext;
+ Abc_Obj_t * pObj;
+ int i;
+ // return if visited
+ if ( pNtk->fHieVisited )
+ return 1;
+ pNtk->fHieVisited = 1;
+ // return if black box
+ if ( Abc_NtkHasBlackbox(pNtk) )
+ return 1;
+ assert( Abc_NtkIsNetlist(pNtk) );
+ // go through all the children networks
+ Abc_NtkForEachBox( pNtk, pObj, i )
+ {
+ if ( Abc_ObjIsLatch(pObj) )
+ continue;
+ pNtkNext = pObj->pData;
+ assert( pNtkNext != NULL );
+ if ( pNtkNext->fHiePath )
+ return 0;
+ pNtk->fHiePath = 1;
+ if ( !Abc_NtkIsAcyclicHierarchy_rec( pNtkNext ) )
+ return 0;
+ pNtk->fHiePath = 0;
+ }
+ return 1;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Returns 0 if the network hierachy contains a cycle.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Abc_NtkIsAcyclicHierarchy( Abc_Ntk_t * pNtk )
+{
+ Abc_Ntk_t * pTemp;
+ int i, RetValue;
+ assert( Abc_NtkIsNetlist(pNtk) && pNtk->pDesign );
+ // clear the modules
+ Vec_PtrForEachEntry( pNtk->pDesign->vModules, pTemp, i )
+ pTemp->fHieVisited = pTemp->fHiePath = 0;
+ // traverse
+ pNtk->fHiePath = 1;
+ RetValue = Abc_NtkIsAcyclicHierarchy_rec( pNtk );
+ pNtk->fHiePath = 0;
+ // clear the modules
+ Vec_PtrForEachEntry( pNtk->pDesign->vModules, pTemp, i )
+ pTemp->fHieVisited = pTemp->fHiePath = 0;
+ return RetValue;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Returns 0 if CI names are repeated.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Abc_NtkNamesCompare( char ** pName1, char ** pName2 )
+{
+ return strcmp( *pName1, *pName2 );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Returns 0 if CI names are repeated.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Abc_NtkCheckUniqueCiNames( Abc_Ntk_t * pNtk )
+{
+ Vec_Ptr_t * vNames;
+ Abc_Obj_t * pObj;
+ int i, fRetValue = 1;
+ assert( !Abc_NtkIsNetlist(pNtk) );
+ vNames = Vec_PtrAlloc( Abc_NtkCiNum(pNtk) );
+ Abc_NtkForEachCi( pNtk, pObj, i )
+ Vec_PtrPush( vNames, Abc_ObjName(pObj) );
+ Vec_PtrSort( vNames, Abc_NtkNamesCompare );
+ for ( i = 1; i < Abc_NtkCiNum(pNtk); i++ )
+ if ( !strcmp( Vec_PtrEntry(vNames,i-1), Vec_PtrEntry(vNames,i) ) )
+ {
+ printf( "Abc_NtkCheck: Repeated CI names: %s and %s.\n", Vec_PtrEntry(vNames,i-1), Vec_PtrEntry(vNames,i) );
+ fRetValue = 0;
+ }
+ Vec_PtrFree( vNames );
+ return fRetValue;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Returns 0 if CO names are repeated.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Abc_NtkCheckUniqueCoNames( Abc_Ntk_t * pNtk )
+{
+ Vec_Ptr_t * vNames;
+ Abc_Obj_t * pObj;
+ int i, fRetValue = 1;
+ assert( !Abc_NtkIsNetlist(pNtk) );
+ vNames = Vec_PtrAlloc( Abc_NtkCoNum(pNtk) );
+ Abc_NtkForEachCo( pNtk, pObj, i )
+ Vec_PtrPush( vNames, Abc_ObjName(pObj) );
+ Vec_PtrSort( vNames, Abc_NtkNamesCompare );
+ for ( i = 1; i < Abc_NtkCoNum(pNtk); i++ )
+ {
+// printf( "%s\n", Vec_PtrEntry(vNames,i) );
+ if ( !strcmp( Vec_PtrEntry(vNames,i-1), Vec_PtrEntry(vNames,i) ) )
+ {
+ printf( "Abc_NtkCheck: Repeated CO names: %s and %s.\n", Vec_PtrEntry(vNames,i-1), Vec_PtrEntry(vNames,i) );
+ fRetValue = 0;
+ }
+ }
+ Vec_PtrFree( vNames );
+ return fRetValue;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Returns 0 if there is a pair of CI/CO with the same name and logic in between.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Abc_NtkCheckUniqueCioNames( Abc_Ntk_t * pNtk )
+{
+ Abc_Obj_t * pObj, * pObjCi, * pFanin;
+ int i, nCiId, fRetValue = 1;
+ assert( !Abc_NtkIsNetlist(pNtk) );
+ Abc_NtkForEachCo( pNtk, pObj, i )
+ {
+ nCiId = Nm_ManFindIdByNameTwoTypes( pNtk->pManName, Abc_ObjName(pObj), ABC_OBJ_PI, ABC_OBJ_BO );
+ if ( nCiId == -1 )
+ continue;
+ pObjCi = Abc_NtkObj( pNtk, nCiId );
+ assert( !strcmp( Abc_ObjName(pObj), Abc_ObjName(pObjCi) ) );
+ pFanin = Abc_ObjFanin0(pObj);
+ if ( pFanin != pObjCi )
+ {
+ printf( "Abc_NtkCheck: A CI/CO pair share the name (%s) but do not link directly. The name of the CO fanin is %s.\n",
+ Abc_ObjName(pObj), Abc_ObjName(Abc_ObjFanin0(pObj)) );
+ fRetValue = 0;
+ }
+ }
+ return fRetValue;
+}
+
////////////////////////////////////////////////////////////////////////
/// END OF FILE ///
////////////////////////////////////////////////////////////////////////
diff --git a/src/base/abc/abcDfs.c b/src/base/abc/abcDfs.c
index 2fbbee37..af23f18a 100644
--- a/src/base/abc/abcDfs.c
+++ b/src/base/abc/abcDfs.c
@@ -24,19 +24,47 @@
/// DECLARATIONS ///
////////////////////////////////////////////////////////////////////////
-static void Abc_NtkDfs_rec( Abc_Obj_t * pNode, Vec_Ptr_t * vNodes );
-static void Abc_AigDfs_rec( Abc_Obj_t * pNode, Vec_Ptr_t * vNodes );
-static void Abc_NtkDfsReverse_rec( Abc_Obj_t * pNode, Vec_Ptr_t * vNodes );
-static void Abc_DfsLevelizedTfo_rec( Abc_Obj_t * pNode, Vec_Vec_t * vLevels );
-static int Abc_NtkGetLevelNum_rec( Abc_Obj_t * pNode );
-static bool Abc_NtkIsAcyclic_rec( Abc_Obj_t * pNode );
-
////////////////////////////////////////////////////////////////////////
-/// FUNCTION DEFITIONS ///
+/// FUNCTION DEFINITIONS ///
////////////////////////////////////////////////////////////////////////
/**Function*************************************************************
+ Synopsis [Performs DFS for one node.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Abc_NtkDfs_rec( Abc_Obj_t * pNode, Vec_Ptr_t * vNodes )
+{
+ Abc_Obj_t * pFanin;
+ int i;
+ assert( !Abc_ObjIsNet(pNode) );
+ // if this node is already visited, skip
+ if ( Abc_NodeIsTravIdCurrent( pNode ) )
+ return;
+ // mark the node as visited
+ Abc_NodeSetTravIdCurrent( pNode );
+ // skip the CI
+ if ( Abc_ObjIsCi(pNode) || (Abc_NtkIsStrash(pNode->pNtk) && Abc_AigNodeIsConst(pNode)) )
+ return;
+ assert( Abc_ObjIsNode( pNode ) || Abc_ObjIsBox( pNode ) );
+ // visit the transitive fanin of the node
+ Abc_ObjForEachFanin( pNode, pFanin, i )
+ {
+// pFanin = Abc_ObjFanin( pNode, Abc_ObjFaninNum(pNode)-1-i );
+ Abc_NtkDfs_rec( Abc_ObjFanin0Ntk(pFanin), vNodes );
+ }
+ // add the node after the fanins have been added
+ Vec_PtrPush( vNodes, pNode );
+}
+
+/**Function*************************************************************
+
Synopsis [Returns the DFS ordered array of logic nodes.]
Description [Collects only the internal nodes, leaving CIs and CO.
@@ -104,6 +132,7 @@ Vec_Ptr_t * Abc_NtkDfsNodes( Abc_Ntk_t * pNtk, Abc_Obj_t ** ppNodes, int nNodes
return vNodes;
}
+
/**Function*************************************************************
Synopsis [Performs DFS for one node.]
@@ -115,9 +144,9 @@ Vec_Ptr_t * Abc_NtkDfsNodes( Abc_Ntk_t * pNtk, Abc_Obj_t ** ppNodes, int nNodes
SeeAlso []
***********************************************************************/
-void Abc_NtkDfs_rec( Abc_Obj_t * pNode, Vec_Ptr_t * vNodes )
+void Abc_NtkDfsReverse_rec( Abc_Obj_t * pNode, Vec_Ptr_t * vNodes )
{
- Abc_Obj_t * pFanin;
+ Abc_Obj_t * pFanout;
int i;
assert( !Abc_ObjIsNet(pNode) );
// if this node is already visited, skip
@@ -126,17 +155,17 @@ void Abc_NtkDfs_rec( Abc_Obj_t * pNode, Vec_Ptr_t * vNodes )
// mark the node as visited
Abc_NodeSetTravIdCurrent( pNode );
// skip the CI
- if ( Abc_ObjIsCi(pNode) )
+ if ( Abc_ObjIsCo(pNode) )
return;
assert( Abc_ObjIsNode( pNode ) );
// visit the transitive fanin of the node
- Abc_ObjForEachFanin( pNode, pFanin, i )
- Abc_NtkDfs_rec( Abc_ObjFanin0Ntk(pFanin), vNodes );
+ pNode = Abc_ObjFanout0Ntk(pNode);
+ Abc_ObjForEachFanout( pNode, pFanout, i )
+ Abc_NtkDfsReverse_rec( pFanout, vNodes );
// add the node after the fanins have been added
Vec_PtrPush( vNodes, pNode );
}
-
/**Function*************************************************************
Synopsis [Returns the reverse DFS ordered array of logic nodes.]
@@ -166,9 +195,10 @@ Vec_Ptr_t * Abc_NtkDfsReverse( Abc_Ntk_t * pNtk )
Abc_NtkDfsReverse_rec( pFanout, vNodes );
}
// add constant nodes in the end
- Abc_NtkForEachNode( pNtk, pObj, i )
- if ( Abc_NodeIsConst(pObj) )
- Vec_PtrPush( vNodes, pObj );
+ if ( !Abc_NtkIsStrash(pNtk) )
+ Abc_NtkForEachNode( pNtk, pObj, i )
+ if ( Abc_NodeIsConst(pObj) )
+ Vec_PtrPush( vNodes, pObj );
return vNodes;
}
@@ -183,7 +213,7 @@ Vec_Ptr_t * Abc_NtkDfsReverse( Abc_Ntk_t * pNtk )
SeeAlso []
***********************************************************************/
-void Abc_NtkDfsReverse_rec( Abc_Obj_t * pNode, Vec_Ptr_t * vNodes )
+void Abc_NtkDfsReverseNodes_rec( Abc_Obj_t * pNode, Vec_Ptr_t * vNodes )
{
Abc_Obj_t * pFanout;
int i;
@@ -200,52 +230,524 @@ void Abc_NtkDfsReverse_rec( Abc_Obj_t * pNode, Vec_Ptr_t * vNodes )
// visit the transitive fanin of the node
pNode = Abc_ObjFanout0Ntk(pNode);
Abc_ObjForEachFanout( pNode, pFanout, i )
- Abc_NtkDfsReverse_rec( pFanout, vNodes );
+ Abc_NtkDfsReverseNodes_rec( pFanout, vNodes );
+ // add the node after the fanins have been added
+// Vec_PtrPush( vNodes, pNode );
+ Vec_PtrFillExtra( vNodes, pNode->Level + 1, NULL );
+ pNode->pCopy = Vec_PtrEntry( vNodes, pNode->Level );
+ Vec_PtrWriteEntry( vNodes, pNode->Level, pNode );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Returns the levelized array of TFO nodes.]
+
+ Description [Collects the levelized array of internal nodes, leaving out CIs/COs.
+ However it marks both CIs and COs with the current TravId.]
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Vec_Ptr_t * Abc_NtkDfsReverseNodes( Abc_Ntk_t * pNtk, Abc_Obj_t ** ppNodes, int nNodes )
+{
+ Vec_Ptr_t * vNodes;
+ Abc_Obj_t * pObj, * pFanout;
+ int i, k;
+ assert( Abc_NtkIsStrash(pNtk) );
+ // set the traversal ID
+ Abc_NtkIncrementTravId( pNtk );
+ // start the array of nodes
+ vNodes = Vec_PtrStart( Abc_AigLevel(pNtk) + 1 );
+ for ( i = 0; i < nNodes; i++ )
+ {
+ pObj = ppNodes[i];
+ assert( Abc_ObjIsCi(pObj) );
+ Abc_NodeSetTravIdCurrent( pObj );
+ pObj = Abc_ObjFanout0Ntk(pObj);
+ Abc_ObjForEachFanout( pObj, pFanout, k )
+ Abc_NtkDfsReverseNodes_rec( pFanout, vNodes );
+ }
+ return vNodes;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Returns the levelized array of TFO nodes.]
+
+ Description [Collects the levelized array of internal nodes, leaving out CIs/COs.
+ However it marks both CIs and COs with the current TravId.
+ Collects only the nodes whose support does not exceed the set of given CI nodes.]
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Vec_Ptr_t * Abc_NtkDfsReverseNodesContained( Abc_Ntk_t * pNtk, Abc_Obj_t ** ppNodes, int nNodes )
+{
+ Vec_Ptr_t * vNodes;
+ Abc_Obj_t * pObj, * pFanout, * pFanin;
+ int i, k, m, nLevels;
+ // set the levels
+ nLevels = Abc_NtkLevel( pNtk );
+ // set the traversal ID
+ Abc_NtkIncrementTravId( pNtk );
+ // start the array of nodes
+ vNodes = Vec_PtrStart( nLevels + 2 );
+ for ( i = 0; i < nNodes; i++ )
+ {
+ pObj = ppNodes[i];
+ assert( Abc_ObjIsCi(pObj) );
+ Abc_NodeSetTravIdCurrent( pObj );
+ // add to the array
+ assert( pObj->Level == 0 );
+ pObj->pCopy = Vec_PtrEntry( vNodes, pObj->Level );
+ Vec_PtrWriteEntry( vNodes, pObj->Level, pObj );
+ }
+ // iterate through the levels
+ for ( i = 0; i <= nLevels; i++ )
+ {
+ // iterate through the nodes on each level
+ for ( pObj = Vec_PtrEntry(vNodes, i); pObj; pObj = pObj->pCopy )
+ {
+ // iterate through the fanouts of each node
+ Abc_ObjForEachFanout( pObj, pFanout, k )
+ {
+ // skip visited nodes
+ if ( Abc_NodeIsTravIdCurrent(pFanout) )
+ continue;
+ // visit the fanins of this fanout
+ Abc_ObjForEachFanin( pFanout, pFanin, m )
+ {
+ if ( !Abc_NodeIsTravIdCurrent(pFanin) )
+ break;
+ }
+ if ( m < Abc_ObjFaninNum(pFanout) )
+ continue;
+ // all fanins are already collected
+
+ // mark the node as visited
+ Abc_NodeSetTravIdCurrent( pFanout );
+ // handle the COs
+ if ( Abc_ObjIsCo(pFanout) )
+ pFanout->Level = nLevels + 1;
+ // add to the array
+ pFanout->pCopy = Vec_PtrEntry( vNodes, pFanout->Level );
+ Vec_PtrWriteEntry( vNodes, pFanout->Level, pFanout );
+ // handle the COs
+ if ( Abc_ObjIsCo(pFanout) )
+ pFanout->Level = 0;
+ }
+ }
+ }
+ return vNodes;
+}
+
+
+/**Function*************************************************************
+
+ Synopsis [Performs DFS for one node.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Abc_NtkDfsSeq_rec( Abc_Obj_t * pNode, Vec_Ptr_t * vNodes )
+{
+ Abc_Obj_t * pFanin;
+ int i;
+ // if this node is already visited, skip
+ if ( Abc_NodeIsTravIdCurrent( pNode ) )
+ return;
+ // mark the node as visited
+ Abc_NodeSetTravIdCurrent( pNode );
+ // visit the transitive fanin of the node
+ Abc_ObjForEachFanin( pNode, pFanin, i )
+ Abc_NtkDfsSeq_rec( pFanin, vNodes );
// add the node after the fanins have been added
Vec_PtrPush( vNodes, pNode );
}
+/**Function*************************************************************
+
+ Synopsis [Returns the array of nodes and latches reachable from POs.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Vec_Ptr_t * Abc_NtkDfsSeq( Abc_Ntk_t * pNtk )
+{
+ Vec_Ptr_t * vNodes;
+ Abc_Obj_t * pObj;
+ int i;
+ assert( !Abc_NtkIsNetlist(pNtk) );
+ // set the traversal ID
+ Abc_NtkIncrementTravId( pNtk );
+ // start the array of nodes
+ vNodes = Vec_PtrAlloc( 100 );
+ Abc_NtkForEachPo( pNtk, pObj, i )
+ Abc_NtkDfsSeq_rec( pObj, vNodes );
+ // mark the PIs
+ Abc_NtkForEachPi( pNtk, pObj, i )
+ Abc_NtkDfsSeq_rec( pObj, vNodes );
+ return vNodes;
+}
+
/**Function*************************************************************
- Synopsis [Returns the DFS ordered array of logic nodes.]
+ Synopsis [Performs DFS for one node.]
- Description [Collects only the internal nodes, leaving out CIs/COs.
- However it marks both CIs and COs with the current TravId.]
+ Description []
SideEffects []
SeeAlso []
***********************************************************************/
-Vec_Ptr_t * Abc_AigDfs( Abc_Ntk_t * pNtk, int fCollectAll, int fCollectCos )
+void Abc_NtkDfsSeqReverse_rec( Abc_Obj_t * pNode, Vec_Ptr_t * vNodes )
+{
+ Abc_Obj_t * pFanout;
+ int i;
+ // if this node is already visited, skip
+ if ( Abc_NodeIsTravIdCurrent( pNode ) )
+ return;
+ // mark the node as visited
+ Abc_NodeSetTravIdCurrent( pNode );
+ // visit the transitive fanin of the node
+ Abc_ObjForEachFanout( pNode, pFanout, i )
+ Abc_NtkDfsSeqReverse_rec( pFanout, vNodes );
+ // add the node after the fanins have been added
+ Vec_PtrPush( vNodes, pNode );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Returns the array of nodes and latches reachable from POs.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Vec_Ptr_t * Abc_NtkDfsSeqReverse( Abc_Ntk_t * pNtk )
{
Vec_Ptr_t * vNodes;
- Abc_Obj_t * pNode;
+ Abc_Obj_t * pObj;
int i;
- assert( Abc_NtkIsStrash(pNtk) );
+ assert( !Abc_NtkIsNetlist(pNtk) );
// set the traversal ID
Abc_NtkIncrementTravId( pNtk );
// start the array of nodes
vNodes = Vec_PtrAlloc( 100 );
- // go through the PO nodes and call for each of them
- Abc_NtkForEachCo( pNtk, pNode, i )
+ Abc_NtkForEachPi( pNtk, pObj, i )
+ Abc_NtkDfsSeqReverse_rec( pObj, vNodes );
+ // mark the logic feeding into POs
+ Abc_NtkForEachPo( pNtk, pObj, i )
+ Abc_NtkDfsSeq_rec( pObj, vNodes );
+ return vNodes;
+}
+
+
+/**Function*************************************************************
+
+ Synopsis [Iterative version of the DFS procedure.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Abc_NtkDfs_iter( Vec_Ptr_t * vStack, Abc_Obj_t * pRoot, Vec_Ptr_t * vNodes )
+{
+ Abc_Obj_t * pNode, * pFanin;
+ int iFanin;
+ // if this node is already visited, skip
+ if ( Abc_NodeIsTravIdCurrent( pRoot ) )
+ return;
+ // mark the node as visited
+ Abc_NodeSetTravIdCurrent( pRoot );
+ // skip the CI
+ if ( Abc_ObjIsCi(pRoot) || (Abc_NtkIsStrash(pRoot->pNtk) && Abc_AigNodeIsConst(pRoot)) )
+ return;
+ // add the CI
+ Vec_PtrClear( vStack );
+ Vec_PtrPush( vStack, pRoot );
+ Vec_PtrPush( vStack, (void *)0 );
+ while ( Vec_PtrSize(vStack) > 0 )
{
- Abc_AigDfs_rec( Abc_ObjFanin0(pNode), vNodes );
- Abc_NodeSetTravIdCurrent( pNode );
- if ( fCollectCos )
+ // get the node and its fanin
+ iFanin = (int)Vec_PtrPop(vStack);
+ pNode = Vec_PtrPop(vStack);
+ assert( !Abc_ObjIsNet(pNode) );
+ // add it to the array of nodes if we finished
+ if ( iFanin == Abc_ObjFaninNum(pNode) )
+ {
Vec_PtrPush( vNodes, pNode );
+ continue;
+ }
+ // explore the next fanin
+ Vec_PtrPush( vStack, pNode );
+ Vec_PtrPush( vStack, (void *)(iFanin+1) );
+ // get the fanin
+ pFanin = Abc_ObjFanin0Ntk( Abc_ObjFanin(pNode,iFanin) );
+ // if this node is already visited, skip
+ if ( Abc_NodeIsTravIdCurrent( pFanin ) )
+ continue;
+ // mark the node as visited
+ Abc_NodeSetTravIdCurrent( pFanin );
+ // skip the CI
+ if ( Abc_ObjIsCi(pFanin) || (Abc_NtkIsStrash(pFanin->pNtk) && Abc_AigNodeIsConst(pFanin)) )
+ continue;
+ Vec_PtrPush( vStack, pFanin );
+ Vec_PtrPush( vStack, (void *)0 );
+ }
+}
+
+/**Function*************************************************************
+
+ Synopsis [Returns the DFS ordered array of logic nodes.]
+
+ Description [Collects only the internal nodes, leaving CIs and CO.
+ However it marks with the current TravId both CIs and COs.]
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Vec_Ptr_t * Abc_NtkDfsIter( Abc_Ntk_t * pNtk, int fCollectAll )
+{
+ Vec_Ptr_t * vNodes, * vStack;
+ Abc_Obj_t * pObj;
+ int i;
+ // set the traversal ID
+ Abc_NtkIncrementTravId( pNtk );
+ // start the array of nodes
+ vNodes = Vec_PtrAlloc( 1000 );
+ vStack = Vec_PtrAlloc( 1000 );
+ Abc_NtkForEachCo( pNtk, pObj, i )
+ {
+ Abc_NodeSetTravIdCurrent( pObj );
+ Abc_NtkDfs_iter( vStack, Abc_ObjFanin0Ntk(Abc_ObjFanin0(pObj)), vNodes );
}
// collect dangling nodes if asked to
if ( fCollectAll )
{
- Abc_NtkForEachNode( pNtk, pNode, i )
- if ( !Abc_NodeIsTravIdCurrent(pNode) )
- Abc_AigDfs_rec( pNode, vNodes );
+ Abc_NtkForEachNode( pNtk, pObj, i )
+ if ( !Abc_NodeIsTravIdCurrent(pObj) )
+ Abc_NtkDfs_iter( vStack, pObj, vNodes );
+ }
+ Vec_PtrFree( vStack );
+ return vNodes;
+}
+
+
+/**Function*************************************************************
+
+ Synopsis [Performs DFS for one node.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Abc_NtkDfsHie_rec( Abc_Obj_t * pObj, Vec_Ptr_t * vNodes )
+{
+ Abc_Obj_t * pFanin;
+ int i;
+ // if this node is already visited, skip
+ if ( Abc_NodeIsTravIdCurrent( pObj ) )
+ return;
+ // mark the node as visited
+ Abc_NodeSetTravIdCurrent( pObj );
+ // visit the transitive fanin of the node
+ Abc_ObjForEachFanin( pObj, pFanin, i )
+ Abc_NtkDfsHie_rec( pFanin, vNodes );
+ // add the node after the fanins have been added
+ Vec_PtrPush( vNodes, pObj );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Returns the DFS ordered array of all objects.]
+
+ Description [This procedure collects everything from POs to PIs.]
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Vec_Ptr_t * Abc_NtkDfsHie( Abc_Ntk_t * pNtk, int fCollectAll )
+{
+ Vec_Ptr_t * vNodes;
+ Abc_Obj_t * pObj;
+ int i;
+ // set the traversal ID
+ Abc_NtkIncrementTravId( pNtk );
+ // start the array of nodes
+ vNodes = Vec_PtrAlloc( 100 );
+ Abc_NtkForEachPo( pNtk, pObj, i )
+ Abc_NtkDfsHie_rec( pObj, vNodes );
+ // collect dangling nodes if asked to
+ if ( fCollectAll )
+ {
+ Abc_NtkForEachObj( pNtk, pObj, i )
+ if ( !Abc_NodeIsTravIdCurrent(pObj) )
+ Abc_NtkDfs_rec( pObj, vNodes );
+ }
+ return vNodes;
+}
+
+
+/**Function*************************************************************
+
+ Synopsis [Returns 1 if the ordering of nodes is DFS.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+bool Abc_NtkIsDfsOrdered( Abc_Ntk_t * pNtk )
+{
+ Abc_Obj_t * pNode, * pFanin;
+ int i, k;
+ // set the traversal ID
+ Abc_NtkIncrementTravId( pNtk );
+ // mark the CIs
+ Abc_NtkForEachCi( pNtk, pNode, i )
+ Abc_NodeSetTravIdCurrent( pNode );
+ // go through the nodes
+ Abc_NtkForEachNode( pNtk, pNode, i )
+ {
+ // check the fanins of the node
+ Abc_ObjForEachFanin( pNode, pFanin, k )
+ if ( !Abc_NodeIsTravIdCurrent(pFanin) )
+ return 0;
+ // check the choices of the node
+ if ( Abc_NtkIsStrash(pNtk) && Abc_AigNodeIsChoice(pNode) )
+ for ( pFanin = pNode->pData; pFanin; pFanin = pFanin->pData )
+ if ( !Abc_NodeIsTravIdCurrent(pFanin) )
+ return 0;
+ // mark the node as visited
+ Abc_NodeSetTravIdCurrent( pNode );
+ }
+ return 1;
+}
+
+
+/**Function*************************************************************
+
+ Synopsis [Performs DFS for one node.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Abc_NtkNodeSupport_rec( Abc_Obj_t * pNode, Vec_Ptr_t * vNodes )
+{
+ Abc_Obj_t * pFanin;
+ int i;
+ assert( !Abc_ObjIsNet(pNode) );
+ // if this node is already visited, skip
+ if ( Abc_NodeIsTravIdCurrent( pNode ) )
+ return;
+ // mark the node as visited
+ Abc_NodeSetTravIdCurrent( pNode );
+ // collect the CI
+ if ( Abc_ObjIsCi(pNode) || Abc_ObjFaninNum(pNode) == 0 )
+ {
+ Vec_PtrPush( vNodes, pNode );
+ return;
}
+ assert( Abc_ObjIsNode( pNode ) );
+ // visit the transitive fanin of the node
+ Abc_ObjForEachFanin( pNode, pFanin, i )
+ Abc_NtkNodeSupport_rec( Abc_ObjFanin0Ntk(pFanin), vNodes );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Returns the set of CI nodes in the support of the given nodes.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Vec_Ptr_t * Abc_NtkSupport( Abc_Ntk_t * pNtk )
+{
+ Vec_Ptr_t * vNodes;
+ Abc_Obj_t * pNode;
+ int i;
+ // set the traversal ID
+ Abc_NtkIncrementTravId( pNtk );
+ // start the array of nodes
+ vNodes = Vec_PtrAlloc( 100 );
+ // go through the PO nodes and call for each of them
+ Abc_NtkForEachCo( pNtk, pNode, i )
+ Abc_NtkNodeSupport_rec( Abc_ObjFanin0(pNode), vNodes );
+ // add unused CIs
+ Abc_NtkForEachCi( pNtk, pNode, i )
+ if ( !Abc_NodeIsTravIdCurrent( pNode ) )
+ Vec_PtrPush( vNodes, pNode );
+ assert( Vec_PtrSize(vNodes) == Abc_NtkCiNum(pNtk) );
+ return vNodes;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Returns the set of CI nodes in the support of the given nodes.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Vec_Ptr_t * Abc_NtkNodeSupport( Abc_Ntk_t * pNtk, Abc_Obj_t ** ppNodes, int nNodes )
+{
+ Vec_Ptr_t * vNodes;
+ int i;
+ // set the traversal ID
+ Abc_NtkIncrementTravId( pNtk );
+ // start the array of nodes
+ vNodes = Vec_PtrAlloc( 100 );
+ // go through the PO nodes and call for each of them
+ for ( i = 0; i < nNodes; i++ )
+ if ( Abc_ObjIsCo(ppNodes[i]) )
+ Abc_NtkNodeSupport_rec( Abc_ObjFanin0(ppNodes[i]), vNodes );
+ else
+ Abc_NtkNodeSupport_rec( ppNodes[i], vNodes );
return vNodes;
}
+
/**Function*************************************************************
Synopsis [Performs DFS for one node.]
@@ -267,14 +769,14 @@ void Abc_AigDfs_rec( Abc_Obj_t * pNode, Vec_Ptr_t * vNodes )
// mark the node as visited
Abc_NodeSetTravIdCurrent( pNode );
// skip the PI
- if ( Abc_ObjIsCi(pNode) )
+ if ( Abc_ObjIsCi(pNode) || Abc_AigNodeIsConst(pNode) )
return;
assert( Abc_ObjIsNode( pNode ) );
// visit the transitive fanin of the node
Abc_ObjForEachFanin( pNode, pFanin, i )
Abc_AigDfs_rec( pFanin, vNodes );
// visit the equivalent nodes
- if ( Abc_NodeIsAigChoice( pNode ) )
+ if ( Abc_AigNodeIsChoice( pNode ) )
for ( pFanin = pNode->pData; pFanin; pFanin = pFanin->pData )
Abc_AigDfs_rec( pFanin, vNodes );
// add the node after the fanins have been added
@@ -283,37 +785,45 @@ void Abc_AigDfs_rec( Abc_Obj_t * pNode, Vec_Ptr_t * vNodes )
/**Function*************************************************************
- Synopsis [Collects nodes in the DFS manner by level.]
+ Synopsis [Returns the DFS ordered array of logic nodes.]
- Description [The number of levels should be set!!!]
+ Description [Collects only the internal nodes, leaving out CIs/COs.
+ However it marks both CIs and COs with the current TravId.]
SideEffects []
SeeAlso []
***********************************************************************/
-Vec_Vec_t * Abc_DfsLevelized( Abc_Obj_t * pNode, bool fTfi )
+Vec_Ptr_t * Abc_AigDfs( Abc_Ntk_t * pNtk, int fCollectAll, int fCollectCos )
{
- Vec_Vec_t * vLevels;
- Abc_Obj_t * pFanout;
+ Vec_Ptr_t * vNodes;
+ Abc_Obj_t * pNode;
int i;
- assert( fTfi == 0 );
- assert( !Abc_NtkIsNetlist(pNode->pNtk) );
+ assert( Abc_NtkIsStrash(pNtk) );
// set the traversal ID
- Abc_NtkIncrementTravId( pNode->pNtk );
- vLevels = Vec_VecAlloc( 100 );
- if ( Abc_ObjIsNode(pNode) )
- Abc_DfsLevelizedTfo_rec( pNode, vLevels );
- else
+ Abc_NtkIncrementTravId( pNtk );
+ // start the array of nodes
+ vNodes = Vec_PtrAlloc( 100 );
+ // go through the PO nodes and call for each of them
+ Abc_NtkForEachCo( pNtk, pNode, i )
{
- assert( Abc_ObjIsCi(pNode) );
+ Abc_AigDfs_rec( Abc_ObjFanin0(pNode), vNodes );
Abc_NodeSetTravIdCurrent( pNode );
- Abc_ObjForEachFanout( pNode, pFanout, i )
- Abc_DfsLevelizedTfo_rec( pFanout, vLevels );
+ if ( fCollectCos )
+ Vec_PtrPush( vNodes, pNode );
}
- return vLevels;
+ // collect dangling nodes if asked to
+ if ( fCollectAll )
+ {
+ Abc_NtkForEachNode( pNtk, pNode, i )
+ if ( !Abc_NodeIsTravIdCurrent(pNode) )
+ Abc_AigDfs_rec( pNode, vNodes );
+ }
+ return vNodes;
}
+
/**Function*************************************************************
Synopsis [Collects nodes in the DFS manner by level.]
@@ -345,10 +855,43 @@ void Abc_DfsLevelizedTfo_rec( Abc_Obj_t * pNode, Vec_Vec_t * vLevels )
Abc_DfsLevelizedTfo_rec( pFanout, vLevels );
}
+/**Function*************************************************************
+
+ Synopsis [Collects nodes in the DFS manner by level.]
+
+ Description [The number of levels should be set!!!]
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Vec_Vec_t * Abc_DfsLevelized( Abc_Obj_t * pNode, bool fTfi )
+{
+ Vec_Vec_t * vLevels;
+ Abc_Obj_t * pFanout;
+ int i;
+ assert( fTfi == 0 );
+ assert( !Abc_NtkIsNetlist(pNode->pNtk) );
+ // set the traversal ID
+ Abc_NtkIncrementTravId( pNode->pNtk );
+ vLevels = Vec_VecAlloc( 100 );
+ if ( Abc_ObjIsNode(pNode) )
+ Abc_DfsLevelizedTfo_rec( pNode, vLevels );
+ else
+ {
+ assert( Abc_ObjIsCi(pNode) );
+ Abc_NodeSetTravIdCurrent( pNode );
+ Abc_ObjForEachFanout( pNode, pFanout, i )
+ Abc_DfsLevelizedTfo_rec( pFanout, vLevels );
+ }
+ return vLevels;
+}
+
/**Function*************************************************************
- Synopsis [Computes the number of logic levels not counting PIs/POs.]
+ Synopsis [Recursively counts the number of logic levels of one node.]
Description []
@@ -357,21 +900,31 @@ void Abc_DfsLevelizedTfo_rec( Abc_Obj_t * pNode, Vec_Vec_t * vLevels )
SeeAlso []
***********************************************************************/
-int Abc_NtkGetLevelNum( Abc_Ntk_t * pNtk )
+int Abc_NtkLevel_rec( Abc_Obj_t * pNode )
{
- Abc_Obj_t * pNode;
- int i, LevelsMax;
- // set the traversal ID for this traversal
- Abc_NtkIncrementTravId( pNtk );
- // perform the traversal
- LevelsMax = 0;
- Abc_NtkForEachNode( pNtk, pNode, i )
+ Abc_Obj_t * pNext;
+ int i, Level;
+ assert( !Abc_ObjIsNet(pNode) );
+ // skip the PI
+ if ( Abc_ObjIsCi(pNode) )
+ return pNode->Level;
+ assert( Abc_ObjIsNode( pNode ) || pNode->Type == ABC_OBJ_CONST1);
+ // if this node is already visited, return
+ if ( Abc_NodeIsTravIdCurrent( pNode ) )
+ return pNode->Level;
+ // mark the node as visited
+ Abc_NodeSetTravIdCurrent( pNode );
+ // visit the transitive fanin
+ pNode->Level = 0;
+ Abc_ObjForEachFanin( pNode, pNext, i )
{
- Abc_NtkGetLevelNum_rec( pNode );
- if ( LevelsMax < (int)pNode->Level )
- LevelsMax = (int)pNode->Level;
+ Level = Abc_NtkLevel_rec( Abc_ObjFanin0Ntk(pNext) );
+ if ( pNode->Level < (unsigned)Level )
+ pNode->Level = Level;
}
- return LevelsMax;
+ if ( Abc_ObjFaninNum(pNode) > 0 )
+ pNode->Level++;
+ return pNode->Level;
}
/**Function*************************************************************
@@ -385,15 +938,15 @@ int Abc_NtkGetLevelNum( Abc_Ntk_t * pNtk )
SeeAlso []
***********************************************************************/
-int Abc_NtkGetLevelNum_rec( Abc_Obj_t * pNode )
+int Abc_NtkLevelReverse_rec( Abc_Obj_t * pNode )
{
- Abc_Obj_t * pFanin;
+ Abc_Obj_t * pNext;
int i, Level;
assert( !Abc_ObjIsNet(pNode) );
// skip the PI
- if ( Abc_ObjIsCi(pNode) )
- return 0;
- assert( Abc_ObjIsNode( pNode ) );
+ if ( Abc_ObjIsCo(pNode) )
+ return pNode->Level;
+ assert( Abc_ObjIsNode( pNode ) || pNode->Type == ABC_OBJ_CONST1);
// if this node is already visited, return
if ( Abc_NodeIsTravIdCurrent( pNode ) )
return pNode->Level;
@@ -401,62 +954,78 @@ int Abc_NtkGetLevelNum_rec( Abc_Obj_t * pNode )
Abc_NodeSetTravIdCurrent( pNode );
// visit the transitive fanin
pNode->Level = 0;
- Abc_ObjForEachFanin( pNode, pFanin, i )
+ Abc_ObjForEachFanout( pNode, pNext, i )
{
- Level = Abc_NtkGetLevelNum_rec( Abc_ObjFanin0Ntk(pFanin) );
+ Level = Abc_NtkLevelReverse_rec( Abc_ObjFanout0Ntk(pNext) );
if ( pNode->Level < (unsigned)Level )
pNode->Level = Level;
}
- pNode->Level++;
+ if ( Abc_ObjFaninNum(pNode) > 0 )
+ pNode->Level++;
return pNode->Level;
}
+/**Function*************************************************************
+
+ Synopsis [Computes the number of logic levels not counting PIs/POs.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Abc_NtkLevel( Abc_Ntk_t * pNtk )
+{
+ Abc_Obj_t * pNode;
+ int i, LevelsMax;
+ // set the CI levels to zero
+ Abc_NtkForEachCi( pNtk, pNode, i )
+ pNode->Level = 0;
+ // perform the traversal
+ LevelsMax = 0;
+ Abc_NtkIncrementTravId( pNtk );
+ Abc_NtkForEachNode( pNtk, pNode, i )
+ {
+ Abc_NtkLevel_rec( pNode );
+ if ( LevelsMax < (int)pNode->Level )
+ LevelsMax = (int)pNode->Level;
+ }
+ return LevelsMax;
+}
/**Function*************************************************************
- Synopsis [Detects combinational loops.]
+ Synopsis [Computes the number of logic levels not counting PIs/POs.]
- Description [This procedure is based on the idea suggested by Donald Chai.
- As we traverse the network and visit the nodes, we need to distinquish
- three types of nodes: (1) those that are visited for the first time,
- (2) those that have been visited in this traversal but are currently not
- on the traversal path, (3) those that have been visited and are currently
- on the travesal path. When the node of type (3) is encountered, it means
- that there is a combinational loop. To mark the three types of nodes,
- two new values of the traversal IDs are used.]
+ Description []
SideEffects []
SeeAlso []
***********************************************************************/
-bool Abc_NtkIsAcyclic( Abc_Ntk_t * pNtk )
+int Abc_NtkLevelReverse( Abc_Ntk_t * pNtk )
{
Abc_Obj_t * pNode;
- int fAcyclic, i;
- // set the traversal ID for this DFS ordering
- Abc_NtkIncrementTravId( pNtk );
- Abc_NtkIncrementTravId( pNtk );
- // pNode->TravId == pNet->nTravIds means "pNode is on the path"
- // pNode->TravId == pNet->nTravIds - 1 means "pNode is visited but is not on the path"
- // pNode->TravId < pNet->nTravIds - 1 means "pNode is not visited"
- // traverse the network to detect cycles
- fAcyclic = 1;
+ int i, LevelsMax;
+ // set the CO levels to zero
Abc_NtkForEachCo( pNtk, pNode, i )
+ pNode->Level = 0;
+ // perform the traversal
+ LevelsMax = 0;
+ Abc_NtkIncrementTravId( pNtk );
+ Abc_NtkForEachNode( pNtk, pNode, i )
{
- pNode = Abc_ObjFanin0Ntk(Abc_ObjFanin0(pNode));
- if ( Abc_NodeIsTravIdPrevious(pNode) )
- continue;
- // traverse the output logic cone
- if ( fAcyclic = Abc_NtkIsAcyclic_rec(pNode) )
- continue;
- // stop as soon as the first loop is detected
- fprintf( stdout, " (cone of CO \"%s\")\n", Abc_ObjName(pNode) );
- break;
+ Abc_NtkLevelReverse_rec( pNode );
+ if ( LevelsMax < (int)pNode->Level )
+ LevelsMax = (int)pNode->Level;
}
- return fAcyclic;
+ return LevelsMax;
}
+
/**Function*************************************************************
Synopsis [Recursively detects combinational loops.]
@@ -474,17 +1043,16 @@ bool Abc_NtkIsAcyclic_rec( Abc_Obj_t * pNode )
Abc_Obj_t * pFanin;
int fAcyclic, i;
assert( !Abc_ObjIsNet(pNode) );
- if ( Abc_ObjIsCi(pNode) )
+ if ( Abc_ObjIsCi(pNode) || Abc_ObjIsBox(pNode) || (Abc_NtkIsStrash(pNode->pNtk) && Abc_AigNodeIsConst(pNode)) )
return 1;
- assert( Abc_ObjIsNode( pNode ) );
+ assert( Abc_ObjIsNode(pNode) );
// make sure the node is not visited
assert( !Abc_NodeIsTravIdPrevious(pNode) );
// check if the node is part of the combinational loop
if ( Abc_NodeIsTravIdCurrent(pNode) )
{
- fprintf( stdout, "Network \"%s\" contains combinational loop!\n", pNtk->pName );
- fprintf( stdout, "Node \"%s\" is encountered twice on the following path:\n", Abc_ObjName(pNode) );
- fprintf( stdout, " %s", Abc_ObjName(pNode) );
+ fprintf( stdout, "Network \"%s\" contains combinational loop!\n", Abc_NtkName(pNtk) );
+ fprintf( stdout, "Node \"%s\" is encountered twice on the following path to the COs:\n", Abc_ObjName(pNode) );
return 0;
}
// mark this node as a node on the current path
@@ -502,14 +1070,193 @@ bool Abc_NtkIsAcyclic_rec( Abc_Obj_t * pNode )
if ( fAcyclic = Abc_NtkIsAcyclic_rec(pFanin) )
continue;
// return as soon as the loop is detected
- fprintf( stdout, " <-- %s", Abc_ObjName(pNode) );
+ fprintf( stdout, " %s ->", Abc_ObjName(pFanin) );
return 0;
}
+ // visit choices
+ if ( Abc_NtkIsStrash(pNode->pNtk) && Abc_AigNodeIsChoice(pNode) )
+ {
+ for ( pFanin = pNode->pData; pFanin; pFanin = pFanin->pData )
+ {
+ // check if the fanin is visited
+ if ( Abc_NodeIsTravIdPrevious(pFanin) )
+ continue;
+ // traverse the fanin's cone searching for the loop
+ if ( fAcyclic = Abc_NtkIsAcyclic_rec(pFanin) )
+ continue;
+ // return as soon as the loop is detected
+ fprintf( stdout, " %s", Abc_ObjName(pFanin) );
+ fprintf( stdout, " (choice of %s) -> ", Abc_ObjName(pNode) );
+ return 0;
+ }
+ }
// mark this node as a visited node
Abc_NodeSetTravIdPrevious( pNode );
return 1;
}
+/**Function*************************************************************
+
+ Synopsis [Detects combinational loops.]
+
+ Description [This procedure is based on the idea suggested by Donald Chai.
+ As we traverse the network and visit the nodes, we need to distinquish
+ three types of nodes: (1) those that are visited for the first time,
+ (2) those that have been visited in this traversal but are currently not
+ on the traversal path, (3) those that have been visited and are currently
+ on the travesal path. When the node of type (3) is encountered, it means
+ that there is a combinational loop. To mark the three types of nodes,
+ two new values of the traversal IDs are used.]
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+bool Abc_NtkIsAcyclic( Abc_Ntk_t * pNtk )
+{
+ Abc_Obj_t * pNode;
+ int fAcyclic, i;
+ // set the traversal ID for this DFS ordering
+ Abc_NtkIncrementTravId( pNtk );
+ Abc_NtkIncrementTravId( pNtk );
+ // pNode->TravId == pNet->nTravIds means "pNode is on the path"
+ // pNode->TravId == pNet->nTravIds - 1 means "pNode is visited but is not on the path"
+ // pNode->TravId < pNet->nTravIds - 1 means "pNode is not visited"
+ // traverse the network to detect cycles
+ fAcyclic = 1;
+ Abc_NtkForEachCo( pNtk, pNode, i )
+ {
+ pNode = Abc_ObjFanin0Ntk(Abc_ObjFanin0(pNode));
+ if ( Abc_NodeIsTravIdPrevious(pNode) )
+ continue;
+ // traverse the output logic cone
+ if ( fAcyclic = Abc_NtkIsAcyclic_rec(pNode) )
+ continue;
+ // stop as soon as the first loop is detected
+ fprintf( stdout, " CO \"%s\"\n", Abc_ObjName(Abc_ObjFanout0(pNode)) );
+ break;
+ }
+ return fAcyclic;
+}
+
+
+/**Function*************************************************************
+
+ Synopsis [Analyses choice nodes.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Abc_NodeSetChoiceLevel_rec( Abc_Obj_t * pNode, int fMaximum )
+{
+ Abc_Obj_t * pTemp;
+ int Level1, Level2, Level, LevelE;
+ // skip the visited node
+ if ( Abc_NodeIsTravIdCurrent( pNode ) )
+ return (int)pNode->pCopy;
+ Abc_NodeSetTravIdCurrent( pNode );
+ // compute levels of the children nodes
+ Level1 = Abc_NodeSetChoiceLevel_rec( Abc_ObjFanin0(pNode), fMaximum );
+ Level2 = Abc_NodeSetChoiceLevel_rec( Abc_ObjFanin1(pNode), fMaximum );
+ Level = 1 + ABC_MAX( Level1, Level2 );
+ if ( pNode->pData )
+ {
+ LevelE = Abc_NodeSetChoiceLevel_rec( pNode->pData, fMaximum );
+ if ( fMaximum )
+ Level = ABC_MAX( Level, LevelE );
+ else
+ Level = ABC_MIN( Level, LevelE );
+ // set the level of all equivalent nodes to be the same minimum
+ for ( pTemp = pNode->pData; pTemp; pTemp = pTemp->pData )
+ pTemp->pCopy = (void *)Level;
+ }
+ pNode->pCopy = (void *)Level;
+ return Level;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Resets the levels of the nodes in the choice graph.]
+
+ Description [Makes the level of the choice nodes to be equal to the
+ maximum of the level of the nodes in the equivalence class. This way
+ sorting by level leads to the reverse topological order, which is
+ needed for the required time computation.]
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Abc_AigSetChoiceLevels( Abc_Ntk_t * pNtk )
+{
+ Abc_Obj_t * pObj;
+ int i, LevelMax, LevelCur;
+ assert( Abc_NtkIsStrash(pNtk) );
+ // set the new travid counter
+ Abc_NtkIncrementTravId( pNtk );
+ // set levels of the CI and constant
+ Abc_NtkForEachCi( pNtk, pObj, i )
+ {
+ Abc_NodeSetTravIdCurrent( pObj );
+ pObj->pCopy = NULL;
+ }
+ pObj = Abc_AigConst1( pNtk );
+ Abc_NodeSetTravIdCurrent( pObj );
+ pObj->pCopy = NULL;
+ // set levels of all other nodes
+ LevelMax = 0;
+ Abc_NtkForEachCo( pNtk, pObj, i )
+ {
+ LevelCur = Abc_NodeSetChoiceLevel_rec( Abc_ObjFanin0(pObj), 1 );
+ LevelMax = ABC_MAX( LevelMax, LevelCur );
+ }
+ return LevelMax;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Returns nodes by level from the smallest to the largest.]
+
+ Description [Correctly handles the case of choice nodes, by first
+ spreading them out across several levels and then collecting.]
+
+ SideEffects [What happens with dangling nodes???]
+
+ SeeAlso []
+
+***********************************************************************/
+Vec_Ptr_t * Abc_AigGetLevelizedOrder( Abc_Ntk_t * pNtk, int fCollectCis )
+{
+ Vec_Ptr_t * vNodes, * vLevels;
+ Abc_Obj_t * pNode, ** ppHead;
+ int LevelMax, i;
+ assert( Abc_NtkIsStrash(pNtk) );
+ // set the correct levels
+ Abc_NtkCleanCopy( pNtk );
+ LevelMax = Abc_AigSetChoiceLevels( pNtk );
+ // relink nodes by level
+ vLevels = Vec_PtrStart( LevelMax + 1 );
+ Abc_NtkForEachNode( pNtk, pNode, i )
+ {
+ ppHead = ((Abc_Obj_t **)vLevels->pArray) + (int)pNode->pCopy;
+ pNode->pCopy = *ppHead;
+ *ppHead = pNode;
+ }
+ // recollect nodes
+ vNodes = Vec_PtrStart( Abc_NtkNodeNum(pNtk) );
+ Vec_PtrForEachEntryStart( vLevels, pNode, i, !fCollectCis )
+ for ( ; pNode; pNode = pNode->pCopy )
+ Vec_PtrPush( vNodes, pNode );
+ Vec_PtrFree( vLevels );
+ return vNodes;
+}
+
////////////////////////////////////////////////////////////////////////
/// END OF FILE ///
////////////////////////////////////////////////////////////////////////
diff --git a/src/base/abc/abcFanio.c b/src/base/abc/abcFanio.c
index 2bc87c85..c8536695 100644
--- a/src/base/abc/abcFanio.c
+++ b/src/base/abc/abcFanio.c
@@ -24,14 +24,51 @@
/// DECLARATIONS ///
////////////////////////////////////////////////////////////////////////
-#define ABC_LARGE_ID ((1<<24)-1) // should correspond to value in "vecFan.h"
-
////////////////////////////////////////////////////////////////////////
-/// FUNCTION DEFITIONS ///
+/// FUNCTION DEFINITIONS ///
////////////////////////////////////////////////////////////////////////
/**Function*************************************************************
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+static inline void Vec_IntPushMem( Extra_MmStep_t * pMemMan, Vec_Int_t * p, int Entry )
+{
+ if ( p->nSize == p->nCap )
+ {
+ int * pArray;
+ int i;
+
+ if ( p->nSize == 0 )
+ p->nCap = 1;
+ if ( pMemMan )
+ pArray = (int *)Extra_MmStepEntryFetch( pMemMan, p->nCap * 8 );
+ else
+ pArray = ALLOC( int, p->nCap * 2 );
+ if ( p->pArray )
+ {
+ for ( i = 0; i < p->nSize; i++ )
+ pArray[i] = p->pArray[i];
+ if ( pMemMan )
+ Extra_MmStepEntryRecycle( pMemMan, (char *)p->pArray, p->nCap * 4 );
+ else
+ free( p->pArray );
+ }
+ p->nCap *= 2;
+ p->pArray = pArray;
+ }
+ p->pArray[p->nSize++] = Entry;
+}
+
+/**Function*************************************************************
+
Synopsis [Creates fanout/fanin relationship between the nodes.]
Description []
@@ -47,12 +84,16 @@ void Abc_ObjAddFanin( Abc_Obj_t * pObj, Abc_Obj_t * pFanin )
assert( !Abc_ObjIsComplement(pObj) );
assert( pObj->pNtk == pFaninR->pNtk );
assert( pObj->Id >= 0 && pFaninR->Id >= 0 );
- assert( pObj->Id < ABC_LARGE_ID ); // created but forgot to add it to the network?
- assert( pFaninR->Id < ABC_LARGE_ID ); // created but forgot to add it to the network?
- Vec_FanPush( pObj->pNtk->pMmStep, &pObj->vFanins, Vec_Int2Fan(pFaninR->Id) );
- Vec_FanPush( pObj->pNtk->pMmStep, &pFaninR->vFanouts, Vec_Int2Fan(pObj->Id) );
+ Vec_IntPushMem( pObj->pNtk->pMmStep, &pObj->vFanins, pFaninR->Id );
+ Vec_IntPushMem( pObj->pNtk->pMmStep, &pFaninR->vFanouts, pObj->Id );
if ( Abc_ObjIsComplement(pFanin) )
Abc_ObjSetFaninC( pObj, Abc_ObjFaninNum(pObj)-1 );
+ if ( Abc_ObjIsNet(pObj) && Abc_ObjFaninNum(pObj) > 1 )
+ {
+ int x = 0;
+ }
+// printf( "Adding fanin of %s ", Abc_ObjName(pObj) );
+// printf( "to be %s\n", Abc_ObjName(pFanin) );
}
@@ -73,14 +114,12 @@ void Abc_ObjDeleteFanin( Abc_Obj_t * pObj, Abc_Obj_t * pFanin )
assert( !Abc_ObjIsComplement(pFanin) );
assert( pObj->pNtk == pFanin->pNtk );
assert( pObj->Id >= 0 && pFanin->Id >= 0 );
- assert( pObj->Id < ABC_LARGE_ID ); // created but forgot to add it to the network?
- assert( pFanin->Id < ABC_LARGE_ID ); // created but forgot to add it to the network?
- if ( !Vec_FanDeleteEntry( &pObj->vFanins, pFanin->Id ) )
+ if ( !Vec_IntRemove( &pObj->vFanins, pFanin->Id ) )
{
printf( "The obj %d is not found among the fanins of obj %d ...\n", pFanin->Id, pObj->Id );
return;
}
- if ( !Vec_FanDeleteEntry( &pFanin->vFanouts, pObj->Id ) )
+ if ( !Vec_IntRemove( &pFanin->vFanouts, pObj->Id ) )
{
printf( "The obj %d is not found among the fanouts of obj %d ...\n", pObj->Id, pFanin->Id );
return;
@@ -101,16 +140,19 @@ void Abc_ObjDeleteFanin( Abc_Obj_t * pObj, Abc_Obj_t * pFanin )
***********************************************************************/
void Abc_ObjRemoveFanins( Abc_Obj_t * pObj )
{
- Vec_Fan_t * vFaninsOld;
+ Vec_Int_t * vFaninsOld;
Abc_Obj_t * pFanin;
int k;
// remove old fanins
vFaninsOld = &pObj->vFanins;
for ( k = vFaninsOld->nSize - 1; k >= 0; k-- )
{
- pFanin = Abc_NtkObj( pObj->pNtk, vFaninsOld->pArray[k].iFan );
+ pFanin = Abc_NtkObj( pObj->pNtk, vFaninsOld->pArray[k] );
Abc_ObjDeleteFanin( pObj, pFanin );
}
+ pObj->fCompl0 = 0;
+ pObj->fCompl1 = 0;
+ assert( vFaninsOld->nSize == 0 );
}
/**Function*************************************************************
@@ -130,7 +172,7 @@ void Abc_ObjRemoveFanins( Abc_Obj_t * pObj )
void Abc_ObjPatchFanin( Abc_Obj_t * pObj, Abc_Obj_t * pFaninOld, Abc_Obj_t * pFaninNew )
{
Abc_Obj_t * pFaninNewR = Abc_ObjRegular(pFaninNew);
- int iFanin, fCompl, nLats;
+ int iFanin;//, nLats;//, fCompl;
assert( !Abc_ObjIsComplement(pObj) );
assert( !Abc_ObjIsComplement(pFaninOld) );
assert( pFaninOld != pFaninNewR );
@@ -138,30 +180,74 @@ void Abc_ObjPatchFanin( Abc_Obj_t * pObj, Abc_Obj_t * pFaninOld, Abc_Obj_t * pFa
// assert( pObj != pFaninNewR );
assert( pObj->pNtk == pFaninOld->pNtk );
assert( pObj->pNtk == pFaninNewR->pNtk );
- if ( (iFanin = Vec_FanFindEntry( &pObj->vFanins, pFaninOld->Id )) == -1 )
+ if ( (iFanin = Vec_IntFind( &pObj->vFanins, pFaninOld->Id )) == -1 )
{
printf( "Node %s is not among", Abc_ObjName(pFaninOld) );
printf( " the fanins of node %s...\n", Abc_ObjName(pObj) );
return;
}
+
// remember the attributes of the old fanin
- fCompl = Abc_ObjFaninC(pObj, iFanin);
- nLats = Abc_ObjFaninL(pObj, iFanin);
+// fCompl = Abc_ObjFaninC(pObj, iFanin);
// replace the old fanin entry by the new fanin entry (removes attributes)
- Vec_FanWriteEntry( &pObj->vFanins, iFanin, Vec_Int2Fan(pFaninNewR->Id) );
+ Vec_IntWriteEntry( &pObj->vFanins, iFanin, pFaninNewR->Id );
// set the attributes of the new fanin
- if ( fCompl ^ Abc_ObjIsComplement(pFaninNew) )
- Abc_ObjSetFaninC( pObj, iFanin );
- if ( nLats )
- Abc_ObjSetFaninL( pObj, iFanin, nLats );
+// if ( fCompl ^ Abc_ObjIsComplement(pFaninNew) )
+// Abc_ObjSetFaninC( pObj, iFanin );
+ if ( Abc_ObjIsComplement(pFaninNew) )
+ Abc_ObjXorFaninC( pObj, iFanin );
+
+// if ( Abc_NtkIsSeq(pObj->pNtk) && (nLats = Seq_ObjFaninL(pObj, iFanin)) )
+// Seq_ObjSetFaninL( pObj, iFanin, nLats );
// update the fanout of the fanin
- if ( !Vec_FanDeleteEntry( &pFaninOld->vFanouts, pObj->Id ) )
+ if ( !Vec_IntRemove( &pFaninOld->vFanouts, pObj->Id ) )
{
printf( "Node %s is not among", Abc_ObjName(pObj) );
printf( " the fanouts of its old fanin %s...\n", Abc_ObjName(pFaninOld) );
// return;
}
- Vec_FanPush( pObj->pNtk->pMmStep, &pFaninNewR->vFanouts, Vec_Int2Fan(pObj->Id) );
+ Vec_IntPushMem( pObj->pNtk->pMmStep, &pFaninNewR->vFanouts, pObj->Id );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Inserts one-input node of the type specified between the nodes.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Abc_Obj_t * Abc_ObjInsertBetween( Abc_Obj_t * pNodeIn, Abc_Obj_t * pNodeOut, Abc_ObjType_t Type )
+{
+ Abc_Obj_t * pNodeNew;
+ int iFanoutIndex, iFaninIndex;
+ // find pNodeOut among the fanouts of pNodeIn
+ if ( (iFanoutIndex = Vec_IntFind( &pNodeIn->vFanouts, pNodeOut->Id )) == -1 )
+ {
+ printf( "Node %s is not among", Abc_ObjName(pNodeOut) );
+ printf( " the fanouts of node %s...\n", Abc_ObjName(pNodeIn) );
+ return NULL;
+ }
+ // find pNodeIn among the fanins of pNodeOut
+ if ( (iFaninIndex = Vec_IntFind( &pNodeOut->vFanins, pNodeIn->Id )) == -1 )
+ {
+ printf( "Node %s is not among", Abc_ObjName(pNodeIn) );
+ printf( " the fanins of node %s...\n", Abc_ObjName(pNodeOut) );
+ return NULL;
+ }
+ // create the new node
+ pNodeNew = Abc_NtkCreateObj( pNodeIn->pNtk, Type );
+ // add pNodeIn as fanin and pNodeOut as fanout
+ Vec_IntPushMem( pNodeNew->pNtk->pMmStep, &pNodeNew->vFanins, pNodeIn->Id );
+ Vec_IntPushMem( pNodeNew->pNtk->pMmStep, &pNodeNew->vFanouts, pNodeOut->Id );
+ // update the fanout of pNodeIn
+ Vec_IntWriteEntry( &pNodeIn->vFanouts, iFanoutIndex, pNodeNew->Id );
+ // update the fanin of pNodeOut
+ Vec_IntWriteEntry( &pNodeOut->vFanins, iFaninIndex, pNodeNew->Id );
+ return pNodeNew;
}
/**Function*************************************************************
@@ -177,23 +263,24 @@ void Abc_ObjPatchFanin( Abc_Obj_t * pObj, Abc_Obj_t * pFaninOld, Abc_Obj_t * pFa
***********************************************************************/
void Abc_ObjTransferFanout( Abc_Obj_t * pNodeFrom, Abc_Obj_t * pNodeTo )
{
- Vec_Ptr_t * vFanouts = pNodeFrom->pNtk->vPtrTemp;
+ Vec_Ptr_t * vFanouts;
int nFanoutsOld, i;
assert( !Abc_ObjIsComplement(pNodeFrom) );
assert( !Abc_ObjIsComplement(pNodeTo) );
- assert( Abc_ObjIsNode(pNodeFrom) );
- assert( Abc_ObjIsNode(pNodeTo) );
+ assert( !Abc_ObjIsPo(pNodeFrom) && !Abc_ObjIsPo(pNodeTo) );
assert( pNodeFrom->pNtk == pNodeTo->pNtk );
assert( pNodeFrom != pNodeTo );
assert( Abc_ObjFanoutNum(pNodeFrom) > 0 );
// get the fanouts of the old node
nFanoutsOld = Abc_ObjFanoutNum(pNodeTo);
+ vFanouts = Vec_PtrAlloc( nFanoutsOld );
Abc_NodeCollectFanouts( pNodeFrom, vFanouts );
// patch the fanin of each of them
for ( i = 0; i < vFanouts->nSize; i++ )
Abc_ObjPatchFanin( vFanouts->pArray[i], pNodeFrom, pNodeTo );
assert( Abc_ObjFanoutNum(pNodeFrom) == 0 );
assert( Abc_ObjFanoutNum(pNodeTo) == nFanoutsOld + vFanouts->nSize );
+ Vec_PtrFree( vFanouts );
}
/**Function*************************************************************
@@ -211,16 +298,34 @@ void Abc_ObjReplace( Abc_Obj_t * pNodeOld, Abc_Obj_t * pNodeNew )
{
assert( !Abc_ObjIsComplement(pNodeOld) );
assert( !Abc_ObjIsComplement(pNodeNew) );
- assert( Abc_ObjIsNode(pNodeOld) );
- assert( Abc_ObjIsNode(pNodeNew) );
assert( pNodeOld->pNtk == pNodeNew->pNtk );
assert( pNodeOld != pNodeNew );
assert( Abc_ObjFanoutNum(pNodeOld) > 0 );
- assert( Abc_ObjFanoutNum(pNodeNew) == 0 );
// transfer the fanouts to the old node
Abc_ObjTransferFanout( pNodeOld, pNodeNew );
// remove the old node
- Abc_NtkDeleteObj( pNodeOld );
+ Abc_NtkDeleteObj_rec( pNodeOld, 1 );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Returns the index of the fanin in the fanin list of the fanout.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Abc_ObjFanoutFaninNum( Abc_Obj_t * pFanout, Abc_Obj_t * pFanin )
+{
+ Abc_Obj_t * pObj;
+ int i;
+ Abc_ObjForEachFanin( pFanout, pObj, i )
+ if ( pObj == pFanin )
+ return i;
+ return -1;
}
diff --git a/src/base/abc/abcFunc.c b/src/base/abc/abcFunc.c
index e5af1829..f3297d8f 100644
--- a/src/base/abc/abcFunc.c
+++ b/src/base/abc/abcFunc.c
@@ -19,15 +19,21 @@
***********************************************************************/
#include "abc.h"
+#include "main.h"
+#include "mio.h"
////////////////////////////////////////////////////////////////////////
/// DECLARATIONS ///
////////////////////////////////////////////////////////////////////////
-static int Abc_ConvertZddToSop( DdManager * dd, DdNode * zCover, char * pSop, int nFanins, Vec_Str_t * vCube, int fPhase );
+#define ABC_MUX_CUBES 100000
+
+static int Abc_ConvertZddToSop( DdManager * dd, DdNode * zCover, char * pSop, int nFanins, Vec_Str_t * vCube, int fPhase );
+static DdNode * Abc_ConvertAigToBdd( DdManager * dd, Hop_Obj_t * pRoot);
+static Hop_Obj_t * Abc_ConvertSopToAig( Hop_Man_t * pMan, char * pSop );
////////////////////////////////////////////////////////////////////////
-/// FUNCTION DEFITIONS ///
+/// FUNCTION DEFINITIONS ///
////////////////////////////////////////////////////////////////////////
/**Function*************************************************************
@@ -46,8 +52,8 @@ int Abc_NtkSopToBdd( Abc_Ntk_t * pNtk )
Abc_Obj_t * pNode;
DdManager * dd;
int nFaninsMax, i;
-
- assert( Abc_NtkIsSopLogic(pNtk) );
+
+ assert( Abc_NtkHasSop(pNtk) );
// start the functionality manager
nFaninsMax = Abc_NtkGetFaninMax( pNtk );
@@ -69,7 +75,7 @@ int Abc_NtkSopToBdd( Abc_Ntk_t * pNtk )
Cudd_Ref( pNode->pData );
}
- Extra_MmFlexStop( pNtk->pManFunc, 0 );
+ Extra_MmFlexStop( pNtk->pManFunc );
pNtk->pManFunc = dd;
// update the network type
@@ -93,27 +99,40 @@ DdNode * Abc_ConvertSopToBdd( DdManager * dd, char * pSop )
DdNode * bSum, * bCube, * bTemp, * bVar;
char * pCube;
int nVars, Value, v;
+
// start the cover
nVars = Abc_SopGetVarNum(pSop);
- // check the logic function of the node
bSum = Cudd_ReadLogicZero(dd); Cudd_Ref( bSum );
- Abc_SopForEachCube( pSop, nVars, pCube )
+ if ( Abc_SopIsExorType(pSop) )
+ {
+ for ( v = 0; v < nVars; v++ )
+ {
+ bSum = Cudd_bddXor( dd, bTemp = bSum, Cudd_bddIthVar(dd, v) ); Cudd_Ref( bSum );
+ Cudd_RecursiveDeref( dd, bTemp );
+ }
+ }
+ else
{
- bCube = Cudd_ReadOne(dd); Cudd_Ref( bCube );
- Abc_CubeForEachVar( pCube, Value, v )
+ // check the logic function of the node
+ Abc_SopForEachCube( pSop, nVars, pCube )
{
- if ( Value == '0' )
- bVar = Cudd_Not( Cudd_bddIthVar( dd, v ) );
- else if ( Value == '1' )
- bVar = Cudd_bddIthVar( dd, v );
- else
- continue;
- bCube = Cudd_bddAnd( dd, bTemp = bCube, bVar ); Cudd_Ref( bCube );
+ bCube = Cudd_ReadOne(dd); Cudd_Ref( bCube );
+ Abc_CubeForEachVar( pCube, Value, v )
+ {
+ if ( Value == '0' )
+ bVar = Cudd_Not( Cudd_bddIthVar( dd, v ) );
+ else if ( Value == '1' )
+ bVar = Cudd_bddIthVar( dd, v );
+ else
+ continue;
+ bCube = Cudd_bddAnd( dd, bTemp = bCube, bVar ); Cudd_Ref( bCube );
+ Cudd_RecursiveDeref( dd, bTemp );
+ }
+ bSum = Cudd_bddOr( dd, bTemp = bSum, bCube );
+ Cudd_Ref( bSum );
Cudd_RecursiveDeref( dd, bTemp );
+ Cudd_RecursiveDeref( dd, bCube );
}
- bSum = Cudd_bddOr( dd, bTemp = bSum, bCube ); Cudd_Ref( bSum );
- Cudd_RecursiveDeref( dd, bTemp );
- Cudd_RecursiveDeref( dd, bCube );
}
// complement the result if necessary
bSum = Cudd_NotCond( bSum, !Abc_SopGetPhase(pSop) );
@@ -140,7 +159,7 @@ void Abc_NtkLogicMakeDirectSops( Abc_Ntk_t * pNtk )
Abc_Obj_t * pNode;
int nFaninsMax, fFound, i;
- assert( Abc_NtkIsSopLogic(pNtk) );
+ assert( Abc_NtkHasSop(pNtk) );
// check if there are nodes with complemented SOPs
fFound = 0;
@@ -165,7 +184,7 @@ void Abc_NtkLogicMakeDirectSops( Abc_Ntk_t * pNtk )
if ( Abc_SopIsComplement(pNode->pData) )
{
bFunc = Abc_ConvertSopToBdd( dd, pNode->pData ); Cudd_Ref( bFunc );
- pNode->pData = Abc_ConvertBddToSop( pNtk->pManFunc, dd, bFunc, bFunc, Abc_ObjFaninNum(pNode), vCube, 1 );
+ pNode->pData = Abc_ConvertBddToSop( pNtk->pManFunc, dd, bFunc, bFunc, Abc_ObjFaninNum(pNode), 0, vCube, 1 );
Cudd_RecursiveDeref( dd, bFunc );
assert( !Abc_SopIsComplement(pNode->pData) );
}
@@ -181,27 +200,32 @@ void Abc_NtkLogicMakeDirectSops( Abc_Ntk_t * pNtk )
Synopsis [Converts the network from BDD to SOP representation.]
- Description []
+ Description [If the flag is set to 1, forces the direct phase of all covers.]
SideEffects []
SeeAlso []
***********************************************************************/
-int Abc_NtkBddToSop( Abc_Ntk_t * pNtk )
+int Abc_NtkBddToSop( Abc_Ntk_t * pNtk, int fDirect )
{
Abc_Obj_t * pNode;
+ Extra_MmFlex_t * pManNew;
DdManager * dd = pNtk->pManFunc;
DdNode * bFunc;
- int RetValue, i;
Vec_Str_t * vCube;
+ int i, fMode;
+
+ if ( fDirect )
+ fMode = 1;
+ else
+ fMode = -1;
- assert( Abc_NtkIsBddLogic(pNtk) );
+ assert( Abc_NtkHasBdd(pNtk) );
+ if ( dd->size > 0 )
Cudd_zddVarsFromBddVars( dd, 2 );
- // allocate the new manager
- pNtk->pManFunc = Extra_MmFlexStart();
- // update the network type
- pNtk->ntkFunc = ABC_FUNC_SOP;
+ // create the new manager
+ pManNew = Extra_MmFlexStart();
// go through the objects
vCube = Vec_StrAlloc( 100 );
@@ -209,19 +233,32 @@ int Abc_NtkBddToSop( Abc_Ntk_t * pNtk )
{
assert( pNode->pData );
bFunc = pNode->pData;
- pNode->pData = Abc_ConvertBddToSop( pNtk->pManFunc, dd, bFunc, bFunc, Abc_ObjFaninNum(pNode), vCube, -1 );
- if ( pNode->pData == NULL )
+ pNode->pNext = (Abc_Obj_t *)Abc_ConvertBddToSop( pManNew, dd, bFunc, bFunc, Abc_ObjFaninNum(pNode), 0, vCube, fMode );
+ if ( pNode->pNext == NULL )
+ {
+ Extra_MmFlexStop( pManNew );
+ Abc_NtkCleanNext( pNtk );
+// printf( "Converting from BDDs to SOPs has failed.\n" );
+ Vec_StrFree( vCube );
return 0;
- Cudd_RecursiveDeref( dd, bFunc );
+ }
}
Vec_StrFree( vCube );
+ // update the network type
+ pNtk->ntkFunc = ABC_FUNC_SOP;
+ // set the new manager
+ pNtk->pManFunc = pManNew;
+ // transfer from next to data
+ Abc_NtkForEachNode( pNtk, pNode, i )
+ {
+ Cudd_RecursiveDeref( dd, pNode->pData );
+ pNode->pData = pNode->pNext;
+ pNode->pNext = NULL;
+ }
+
// check for remaining references in the package
- RetValue = Cudd_CheckZeroRef( dd );
- if ( RetValue > 0 )
- printf( "\nThe number of referenced nodes = %d\n\n", RetValue );
-// Cudd_PrintInfo( dd, stdout );
- Cudd_Quit( dd );
+ Extra_StopManager( dd );
return 1;
}
@@ -236,7 +273,7 @@ int Abc_NtkBddToSop( Abc_Ntk_t * pNtk )
SeeAlso []
***********************************************************************/
-char * Abc_ConvertBddToSop( Extra_MmFlex_t * pMan, DdManager * dd, DdNode * bFuncOn, DdNode * bFuncOnDc, int nFanins, Vec_Str_t * vCube, int fMode )
+char * Abc_ConvertBddToSop( Extra_MmFlex_t * pMan, DdManager * dd, DdNode * bFuncOn, DdNode * bFuncOnDc, int nFanins, int fAllPrimes, Vec_Str_t * vCube, int fMode )
{
int fVerify = 0;
char * pSop;
@@ -246,22 +283,25 @@ char * Abc_ConvertBddToSop( Extra_MmFlex_t * pMan, DdManager * dd, DdNode * bFun
assert( bFuncOn == bFuncOnDc || Cudd_bddLeq( dd, bFuncOn, bFuncOnDc ) );
if ( Cudd_IsConstant(bFuncOn) || Cudd_IsConstant(bFuncOnDc) )
{
+ if ( fMode == -1 ) // if the phase is not known, write constant 1
+ fMode = 1;
Vec_StrFill( vCube, nFanins, '-' );
Vec_StrPush( vCube, '\0' );
if ( pMan )
pSop = Extra_MmFlexEntryFetch( pMan, nFanins + 4 );
else
pSop = ALLOC( char, nFanins + 4 );
- if ( bFuncOn == Cudd_ReadLogicZero(dd) )
- sprintf( pSop, "%s 0\n", vCube->pArray );
+ if ( bFuncOn == Cudd_ReadOne(dd) )
+ sprintf( pSop, "%s %d\n", vCube->pArray, fMode );
else
- sprintf( pSop, "%s 1\n", vCube->pArray );
+ sprintf( pSop, "%s %d\n", vCube->pArray, !fMode );
return pSop;
}
if ( fMode == -1 )
{ // try both phases
+ assert( fAllPrimes == 0 );
// get the ZDD of the negative polarity
bCover = Cudd_zddIsop( dd, Cudd_Not(bFuncOnDc), Cudd_Not(bFuncOn), &zCover0 );
@@ -296,20 +336,36 @@ char * Abc_ConvertBddToSop( Extra_MmFlex_t * pMan, DdManager * dd, DdNode * bFun
else if ( fMode == 0 )
{
// get the ZDD of the negative polarity
- bCover = Cudd_zddIsop( dd, Cudd_Not(bFuncOnDc), Cudd_Not(bFuncOn), &zCover );
- Cudd_Ref( zCover );
- Cudd_Ref( bCover );
- Cudd_RecursiveDeref( dd, bCover );
+ if ( fAllPrimes )
+ {
+ zCover = Extra_zddPrimes( dd, Cudd_Not(bFuncOnDc) );
+ Cudd_Ref( zCover );
+ }
+ else
+ {
+ bCover = Cudd_zddIsop( dd, Cudd_Not(bFuncOnDc), Cudd_Not(bFuncOn), &zCover );
+ Cudd_Ref( zCover );
+ Cudd_Ref( bCover );
+ Cudd_RecursiveDeref( dd, bCover );
+ }
nCubes = Abc_CountZddCubes( dd, zCover );
fPhase = 0;
}
else if ( fMode == 1 )
{
// get the ZDD of the positive polarity
- bCover = Cudd_zddIsop( dd, bFuncOn, bFuncOnDc, &zCover );
- Cudd_Ref( zCover );
- Cudd_Ref( bCover );
- Cudd_RecursiveDeref( dd, bCover );
+ if ( fAllPrimes )
+ {
+ zCover = Extra_zddPrimes( dd, bFuncOnDc );
+ Cudd_Ref( zCover );
+ }
+ else
+ {
+ bCover = Cudd_zddIsop( dd, bFuncOn, bFuncOnDc, &zCover );
+ Cudd_Ref( zCover );
+ Cudd_Ref( bCover );
+ Cudd_RecursiveDeref( dd, bCover );
+ }
nCubes = Abc_CountZddCubes( dd, zCover );
fPhase = 1;
}
@@ -318,6 +374,13 @@ char * Abc_ConvertBddToSop( Extra_MmFlex_t * pMan, DdManager * dd, DdNode * bFun
assert( 0 );
}
+ if ( nCubes > ABC_MUX_CUBES )
+ {
+ Cudd_RecursiveDerefZdd( dd, zCover );
+ printf( "The number of cubes exceeded the predefined limit (%d).\n", ABC_MUX_CUBES );
+ return NULL;
+ }
+
// allocate memory for the cover
if ( pMan )
pSop = Extra_MmFlexEntryFetch( pMan, (nFanins + 3) * nCubes + 1 );
@@ -416,11 +479,11 @@ int Abc_ConvertZddToSop( DdManager * dd, DdNode * zCover, char * pSop, int nFani
SeeAlso []
***********************************************************************/
-void Abc_NodeBddToCnf( Abc_Obj_t * pNode, Extra_MmFlex_t * pMmMan, Vec_Str_t * vCube, char ** ppSop0, char ** ppSop1 )
+void Abc_NodeBddToCnf( Abc_Obj_t * pNode, Extra_MmFlex_t * pMmMan, Vec_Str_t * vCube, int fAllPrimes, char ** ppSop0, char ** ppSop1 )
{
- assert( Abc_NtkIsBddLogic(pNode->pNtk) );
- *ppSop0 = Abc_ConvertBddToSop( pMmMan, pNode->pNtk->pManFunc, pNode->pData, pNode->pData, Abc_ObjFaninNum(pNode), vCube, 0 );
- *ppSop1 = Abc_ConvertBddToSop( pMmMan, pNode->pNtk->pManFunc, pNode->pData, pNode->pData, Abc_ObjFaninNum(pNode), vCube, 1 );
+ assert( Abc_NtkHasBdd(pNode->pNtk) );
+ *ppSop0 = Abc_ConvertBddToSop( pMmMan, pNode->pNtk->pManFunc, pNode->pData, pNode->pData, Abc_ObjFaninNum(pNode), fAllPrimes, vCube, 0 );
+ *ppSop1 = Abc_ConvertBddToSop( pMmMan, pNode->pNtk->pManFunc, pNode->pData, pNode->pData, Abc_ObjFaninNum(pNode), fAllPrimes, vCube, 1 );
}
@@ -447,6 +510,8 @@ void Abc_CountZddCubes_rec( DdManager * dd, DdNode * zCover, int * pnCubes )
(*pnCubes)++;
return;
}
+ if ( (*pnCubes) > ABC_MUX_CUBES )
+ return;
extraDecomposeCover( dd, zCover, &zC0, &zC1, &zC2 );
Abc_CountZddCubes_rec( dd, zC0, pnCubes );
Abc_CountZddCubes_rec( dd, zC1, pnCubes );
@@ -472,6 +537,616 @@ int Abc_CountZddCubes( DdManager * dd, DdNode * zCover )
}
+/**Function*************************************************************
+
+ Synopsis [Converts the network from SOP to AIG representation.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Abc_NtkSopToAig( Abc_Ntk_t * pNtk )
+{
+ Abc_Obj_t * pNode;
+ Hop_Man_t * pMan;
+ int i;
+
+ assert( Abc_NtkHasSop(pNtk) );
+
+ // start the functionality manager
+ pMan = Hop_ManStart();
+
+ // convert each node from SOP to BDD
+ Abc_NtkForEachNode( pNtk, pNode, i )
+ {
+ assert( pNode->pData );
+ pNode->pData = Abc_ConvertSopToAig( pMan, pNode->pData );
+ if ( pNode->pData == NULL )
+ {
+ printf( "Abc_NtkSopToAig: Error while converting SOP into AIG.\n" );
+ return 0;
+ }
+ }
+ Extra_MmFlexStop( pNtk->pManFunc );
+ pNtk->pManFunc = pMan;
+
+ // update the network type
+ pNtk->ntkFunc = ABC_FUNC_AIG;
+ return 1;
+}
+
+
+/**Function*************************************************************
+
+ Synopsis [Strashes one logic node using its SOP.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Hop_Obj_t * Abc_ConvertSopToAigInternal( Hop_Man_t * pMan, char * pSop )
+{
+ Hop_Obj_t * pAnd, * pSum;
+ int i, Value, nFanins;
+ char * pCube;
+ // get the number of variables
+ nFanins = Abc_SopGetVarNum(pSop);
+ // go through the cubes of the node's SOP
+ pSum = Hop_ManConst0(pMan);
+ Abc_SopForEachCube( pSop, nFanins, pCube )
+ {
+ // create the AND of literals
+ pAnd = Hop_ManConst1(pMan);
+ Abc_CubeForEachVar( pCube, Value, i )
+ {
+ if ( Value == '1' )
+ pAnd = Hop_And( pMan, pAnd, Hop_IthVar(pMan,i) );
+ else if ( Value == '0' )
+ pAnd = Hop_And( pMan, pAnd, Hop_Not(Hop_IthVar(pMan,i)) );
+ }
+ // add to the sum of cubes
+ pSum = Hop_Or( pMan, pSum, pAnd );
+ }
+ // decide whether to complement the result
+ if ( Abc_SopIsComplement(pSop) )
+ pSum = Hop_Not(pSum);
+ return pSum;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Converts the network from AIG to BDD representation.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Hop_Obj_t * Abc_ConvertSopToAig( Hop_Man_t * pMan, char * pSop )
+{
+ extern Hop_Obj_t * Dec_GraphFactorSop( Hop_Man_t * pMan, char * pSop );
+ int fUseFactor = 1;
+ // consider the constant node
+ if ( Abc_SopGetVarNum(pSop) == 0 )
+ return Hop_NotCond( Hop_ManConst1(pMan), Abc_SopIsConst0(pSop) );
+ // consider the special case of EXOR function
+ if ( Abc_SopIsExorType(pSop) )
+ return Hop_NotCond( Hop_CreateExor(pMan, Abc_SopGetVarNum(pSop)), Abc_SopIsComplement(pSop) );
+ // decide when to use factoring
+ if ( fUseFactor && Abc_SopGetVarNum(pSop) > 2 && Abc_SopGetCubeNum(pSop) > 1 )
+ return Dec_GraphFactorSop( pMan, pSop );
+ return Abc_ConvertSopToAigInternal( pMan, pSop );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Converts the network from AIG to BDD representation.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Abc_NtkAigToBdd( Abc_Ntk_t * pNtk )
+{
+ Abc_Obj_t * pNode;
+ Hop_Man_t * pMan;
+ DdManager * dd;
+ int nFaninsMax, i;
+
+ assert( Abc_NtkHasAig(pNtk) );
+
+ // start the functionality manager
+ nFaninsMax = Abc_NtkGetFaninMax( pNtk );
+ if ( nFaninsMax == 0 )
+ printf( "Warning: The network has only constant nodes.\n" );
+
+ dd = Cudd_Init( nFaninsMax, 0, CUDD_UNIQUE_SLOTS, CUDD_CACHE_SLOTS, 0 );
+
+ // set the mapping of elementary AIG nodes into the elementary BDD nodes
+ pMan = pNtk->pManFunc;
+ assert( Hop_ManPiNum(pMan) >= nFaninsMax );
+ for ( i = 0; i < nFaninsMax; i++ )
+ {
+ Hop_ManPi(pMan, i)->pData = Cudd_bddIthVar(dd, i);
+ Cudd_Ref( Hop_ManPi(pMan, i)->pData );
+ }
+
+ // convert each node from SOP to BDD
+ Abc_NtkForEachNode( pNtk, pNode, i )
+ {
+ assert( pNode->pData );
+ pNode->pData = Abc_ConvertAigToBdd( dd, pNode->pData );
+ if ( pNode->pData == NULL )
+ {
+ printf( "Abc_NtkSopToBdd: Error while converting SOP into BDD.\n" );
+ return 0;
+ }
+ Cudd_Ref( pNode->pData );
+ }
+
+ // dereference intermediate BDD nodes
+ for ( i = 0; i < nFaninsMax; i++ )
+ Cudd_RecursiveDeref( dd, Hop_ManPi(pMan, i)->pData );
+
+ Hop_ManStop( pNtk->pManFunc );
+ pNtk->pManFunc = dd;
+
+ // update the network type
+ pNtk->ntkFunc = ABC_FUNC_BDD;
+ return 1;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Construct BDDs and mark AIG nodes.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Abc_ConvertAigToBdd_rec1( DdManager * dd, Hop_Obj_t * pObj )
+{
+ assert( !Hop_IsComplement(pObj) );
+ if ( !Hop_ObjIsNode(pObj) || Hop_ObjIsMarkA(pObj) )
+ return;
+ Abc_ConvertAigToBdd_rec1( dd, Hop_ObjFanin0(pObj) );
+ Abc_ConvertAigToBdd_rec1( dd, Hop_ObjFanin1(pObj) );
+ pObj->pData = Cudd_bddAnd( dd, (DdNode *)Hop_ObjChild0Copy(pObj), (DdNode *)Hop_ObjChild1Copy(pObj) );
+ Cudd_Ref( pObj->pData );
+ assert( !Hop_ObjIsMarkA(pObj) ); // loop detection
+ Hop_ObjSetMarkA( pObj );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Dereference BDDs and unmark AIG nodes.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Abc_ConvertAigToBdd_rec2( DdManager * dd, Hop_Obj_t * pObj )
+{
+ assert( !Hop_IsComplement(pObj) );
+ if ( !Hop_ObjIsNode(pObj) || !Hop_ObjIsMarkA(pObj) )
+ return;
+ Abc_ConvertAigToBdd_rec2( dd, Hop_ObjFanin0(pObj) );
+ Abc_ConvertAigToBdd_rec2( dd, Hop_ObjFanin1(pObj) );
+ Cudd_RecursiveDeref( dd, pObj->pData );
+ pObj->pData = NULL;
+ assert( Hop_ObjIsMarkA(pObj) ); // loop detection
+ Hop_ObjClearMarkA( pObj );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Converts the network from AIG to BDD representation.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+DdNode * Abc_ConvertAigToBdd( DdManager * dd, Hop_Obj_t * pRoot )
+{
+ DdNode * bFunc;
+ // check the case of a constant
+ if ( Hop_ObjIsConst1( Hop_Regular(pRoot) ) )
+ return Cudd_NotCond( Cudd_ReadOne(dd), Hop_IsComplement(pRoot) );
+ // construct BDD
+ Abc_ConvertAigToBdd_rec1( dd, Hop_Regular(pRoot) );
+ // hold on to the result
+ bFunc = Cudd_NotCond( Hop_Regular(pRoot)->pData, Hop_IsComplement(pRoot) ); Cudd_Ref( bFunc );
+ // dereference BDD
+ Abc_ConvertAigToBdd_rec2( dd, Hop_Regular(pRoot) );
+ // return the result
+ Cudd_Deref( bFunc );
+ return bFunc;
+}
+
+
+
+/**Function*************************************************************
+
+ Synopsis [Construct BDDs and mark AIG nodes.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Abc_ConvertAigToTruth_rec1( Hop_Obj_t * pObj )
+{
+ int Counter = 0;
+ assert( !Hop_IsComplement(pObj) );
+ if ( !Hop_ObjIsNode(pObj) || Hop_ObjIsMarkA(pObj) )
+ return 0;
+ Counter += Abc_ConvertAigToTruth_rec1( Hop_ObjFanin0(pObj) );
+ Counter += Abc_ConvertAigToTruth_rec1( Hop_ObjFanin1(pObj) );
+ assert( !Hop_ObjIsMarkA(pObj) ); // loop detection
+ Hop_ObjSetMarkA( pObj );
+ return Counter + 1;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Computes truth table of the cut.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+unsigned * Abc_ConvertAigToTruth_rec2( Hop_Obj_t * pObj, Vec_Int_t * vTruth, int nWords )
+{
+ unsigned * pTruth, * pTruth0, * pTruth1;
+ int i;
+ assert( !Hop_IsComplement(pObj) );
+ if ( !Hop_ObjIsNode(pObj) || !Hop_ObjIsMarkA(pObj) )
+ return pObj->pData;
+ // compute the truth tables of the fanins
+ pTruth0 = Abc_ConvertAigToTruth_rec2( Hop_ObjFanin0(pObj), vTruth, nWords );
+ pTruth1 = Abc_ConvertAigToTruth_rec2( Hop_ObjFanin1(pObj), vTruth, nWords );
+ // creat the truth table of the node
+ pTruth = Vec_IntFetch( vTruth, nWords );
+ if ( Hop_ObjIsExor(pObj) )
+ for ( i = 0; i < nWords; i++ )
+ pTruth[i] = pTruth0[i] ^ pTruth1[i];
+ else if ( !Hop_ObjFaninC0(pObj) && !Hop_ObjFaninC1(pObj) )
+ for ( i = 0; i < nWords; i++ )
+ pTruth[i] = pTruth0[i] & pTruth1[i];
+ else if ( !Hop_ObjFaninC0(pObj) && Hop_ObjFaninC1(pObj) )
+ for ( i = 0; i < nWords; i++ )
+ pTruth[i] = pTruth0[i] & ~pTruth1[i];
+ else if ( Hop_ObjFaninC0(pObj) && !Hop_ObjFaninC1(pObj) )
+ for ( i = 0; i < nWords; i++ )
+ pTruth[i] = ~pTruth0[i] & pTruth1[i];
+ else // if ( Hop_ObjFaninC0(pObj) && Hop_ObjFaninC1(pObj) )
+ for ( i = 0; i < nWords; i++ )
+ pTruth[i] = ~pTruth0[i] & ~pTruth1[i];
+ assert( Hop_ObjIsMarkA(pObj) ); // loop detection
+ Hop_ObjClearMarkA( pObj );
+ pObj->pData = pTruth;
+ return pTruth;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Computes truth table of the node.]
+
+ Description [Assumes that the structural support is no more than 8 inputs.
+ Uses array vTruth to store temporary truth tables. The returned pointer should
+ be used immediately.]
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+unsigned * Abc_ConvertAigToTruth( Hop_Man_t * p, Hop_Obj_t * pRoot, int nVars, Vec_Int_t * vTruth, int fMsbFirst )
+{
+ static unsigned uTruths[8][8] = { // elementary truth tables
+ { 0xAAAAAAAA,0xAAAAAAAA,0xAAAAAAAA,0xAAAAAAAA,0xAAAAAAAA,0xAAAAAAAA,0xAAAAAAAA,0xAAAAAAAA },
+ { 0xCCCCCCCC,0xCCCCCCCC,0xCCCCCCCC,0xCCCCCCCC,0xCCCCCCCC,0xCCCCCCCC,0xCCCCCCCC,0xCCCCCCCC },
+ { 0xF0F0F0F0,0xF0F0F0F0,0xF0F0F0F0,0xF0F0F0F0,0xF0F0F0F0,0xF0F0F0F0,0xF0F0F0F0,0xF0F0F0F0 },
+ { 0xFF00FF00,0xFF00FF00,0xFF00FF00,0xFF00FF00,0xFF00FF00,0xFF00FF00,0xFF00FF00,0xFF00FF00 },
+ { 0xFFFF0000,0xFFFF0000,0xFFFF0000,0xFFFF0000,0xFFFF0000,0xFFFF0000,0xFFFF0000,0xFFFF0000 },
+ { 0x00000000,0xFFFFFFFF,0x00000000,0xFFFFFFFF,0x00000000,0xFFFFFFFF,0x00000000,0xFFFFFFFF },
+ { 0x00000000,0x00000000,0xFFFFFFFF,0xFFFFFFFF,0x00000000,0x00000000,0xFFFFFFFF,0xFFFFFFFF },
+ { 0x00000000,0x00000000,0x00000000,0x00000000,0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF }
+ };
+ Hop_Obj_t * pObj;
+ unsigned * pTruth, * pTruth2;
+ int i, nWords, nNodes;
+ Vec_Ptr_t * vTtElems;
+
+ // if the number of variables is more than 8, allocate truth tables
+ if ( nVars > 8 )
+ vTtElems = Vec_PtrAllocTruthTables( nVars );
+ else
+ vTtElems = NULL;
+
+ // clear the data fields and set marks
+ nNodes = Abc_ConvertAigToTruth_rec1( pRoot );
+ // prepare memory
+ nWords = Hop_TruthWordNum( nVars );
+ Vec_IntClear( vTruth );
+ Vec_IntGrow( vTruth, nWords * (nNodes+1) );
+ pTruth = Vec_IntFetch( vTruth, nWords );
+ // check the case of a constant
+ if ( Hop_ObjIsConst1( Hop_Regular(pRoot) ) )
+ {
+ assert( nNodes == 0 );
+ if ( Hop_IsComplement(pRoot) )
+ Extra_TruthClear( pTruth, nVars );
+ else
+ Extra_TruthFill( pTruth, nVars );
+ return pTruth;
+ }
+ // set elementary truth tables at the leaves
+ assert( nVars <= Hop_ManPiNum(p) );
+// assert( Hop_ManPiNum(p) <= 8 );
+ if ( fMsbFirst )
+ {
+ Hop_ManForEachPi( p, pObj, i )
+ {
+ if ( vTtElems )
+ pObj->pData = Vec_PtrEntry(vTtElems, nVars-1-i);
+ else
+ pObj->pData = (void *)uTruths[nVars-1-i];
+ }
+ }
+ else
+ {
+ Hop_ManForEachPi( p, pObj, i )
+ {
+ if ( vTtElems )
+ pObj->pData = Vec_PtrEntry(vTtElems, i);
+ else
+ pObj->pData = (void *)uTruths[i];
+ }
+ }
+ // clear the marks and compute the truth table
+ pTruth2 = Abc_ConvertAigToTruth_rec2( pRoot, vTruth, nWords );
+ // copy the result
+ Extra_TruthCopy( pTruth, pTruth2, nVars );
+ if ( vTtElems )
+ Vec_PtrFree( vTtElems );
+ return pTruth;
+}
+
+
+/**Function*************************************************************
+
+ Synopsis [Construct BDDs and mark AIG nodes.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Abc_ConvertAigToAig_rec( Abc_Ntk_t * pNtkAig, Hop_Obj_t * pObj )
+{
+ assert( !Hop_IsComplement(pObj) );
+ if ( !Hop_ObjIsNode(pObj) || Hop_ObjIsMarkA(pObj) )
+ return;
+ Abc_ConvertAigToAig_rec( pNtkAig, Hop_ObjFanin0(pObj) );
+ Abc_ConvertAigToAig_rec( pNtkAig, Hop_ObjFanin1(pObj) );
+ pObj->pData = Abc_AigAnd( pNtkAig->pManFunc, (Abc_Obj_t *)Hop_ObjChild0Copy(pObj), (Abc_Obj_t *)Hop_ObjChild1Copy(pObj) );
+ assert( !Hop_ObjIsMarkA(pObj) ); // loop detection
+ Hop_ObjSetMarkA( pObj );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Converts the network from AIG to BDD representation.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Abc_Obj_t * Abc_ConvertAigToAig( Abc_Ntk_t * pNtkAig, Abc_Obj_t * pObjOld )
+{
+ Hop_Man_t * pHopMan;
+ Hop_Obj_t * pRoot;
+ Abc_Obj_t * pFanin;
+ int i;
+ // get the local AIG
+ pHopMan = pObjOld->pNtk->pManFunc;
+ pRoot = pObjOld->pData;
+ // check the case of a constant
+ if ( Hop_ObjIsConst1( Hop_Regular(pRoot) ) )
+ return Abc_ObjNotCond( Abc_AigConst1(pNtkAig), Hop_IsComplement(pRoot) );
+ // assign the fanin nodes
+ Abc_ObjForEachFanin( pObjOld, pFanin, i )
+ {
+ assert( pFanin->pCopy != NULL );
+ Hop_ManPi(pHopMan, i)->pData = pFanin->pCopy;
+ }
+ // construct the AIG
+ Abc_ConvertAigToAig_rec( pNtkAig, Hop_Regular(pRoot) );
+ Hop_ConeUnmark_rec( Hop_Regular(pRoot) );
+ // return the result
+ return Abc_ObjNotCond( Hop_Regular(pRoot)->pData, Hop_IsComplement(pRoot) );
+}
+
+
+/**Function*************************************************************
+
+ Synopsis [Unmaps the network.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Abc_NtkMapToSop( Abc_Ntk_t * pNtk )
+{
+ extern void * Abc_FrameReadLibGen();
+ Abc_Obj_t * pNode;
+ char * pSop;
+ int i;
+
+ assert( Abc_NtkHasMapping(pNtk) );
+ // update the functionality manager
+ assert( pNtk->pManFunc == Abc_FrameReadLibGen() );
+ pNtk->pManFunc = Extra_MmFlexStart();
+ pNtk->ntkFunc = ABC_FUNC_SOP;
+ // update the nodes
+ Abc_NtkForEachNode( pNtk, pNode, i )
+ {
+ pSop = Mio_GateReadSop(pNode->pData);
+ assert( Abc_SopGetVarNum(pSop) == Abc_ObjFaninNum(pNode) );
+ pNode->pData = Abc_SopRegister( pNtk->pManFunc, pSop );
+ }
+ return 1;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Converts SOP functions into BLIF-MV functions.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Abc_NtkSopToBlifMv( Abc_Ntk_t * pNtk )
+{
+ return 1;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Convers logic network to the SOP form.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Abc_NtkToSop( Abc_Ntk_t * pNtk, int fDirect )
+{
+ assert( !Abc_NtkIsStrash(pNtk) );
+ if ( Abc_NtkHasSop(pNtk) )
+ {
+ if ( !fDirect )
+ return 1;
+ if ( !Abc_NtkSopToBdd(pNtk) )
+ return 0;
+ return Abc_NtkBddToSop(pNtk, fDirect);
+ }
+ if ( Abc_NtkHasMapping(pNtk) )
+ return Abc_NtkMapToSop(pNtk);
+ if ( Abc_NtkHasBdd(pNtk) )
+ return Abc_NtkBddToSop(pNtk, fDirect);
+ if ( Abc_NtkHasAig(pNtk) )
+ {
+ if ( !Abc_NtkAigToBdd(pNtk) )
+ return 0;
+ return Abc_NtkBddToSop(pNtk, fDirect);
+ }
+ assert( 0 );
+ return 0;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Convers logic network to the SOP form.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Abc_NtkToBdd( Abc_Ntk_t * pNtk )
+{
+ assert( !Abc_NtkIsStrash(pNtk) );
+ if ( Abc_NtkHasBdd(pNtk) )
+ return 1;
+ if ( Abc_NtkHasMapping(pNtk) )
+ {
+ Abc_NtkMapToSop(pNtk);
+ return Abc_NtkSopToBdd(pNtk);
+ }
+ if ( Abc_NtkHasSop(pNtk) )
+ return Abc_NtkSopToBdd(pNtk);
+ if ( Abc_NtkHasAig(pNtk) )
+ return Abc_NtkAigToBdd(pNtk);
+ assert( 0 );
+ return 0;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Convers logic network to the SOP form.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Abc_NtkToAig( Abc_Ntk_t * pNtk )
+{
+ assert( !Abc_NtkIsStrash(pNtk) );
+ if ( Abc_NtkHasAig(pNtk) )
+ return 1;
+ if ( Abc_NtkHasMapping(pNtk) )
+ {
+ Abc_NtkMapToSop(pNtk);
+ return Abc_NtkSopToAig(pNtk);
+ }
+ if ( Abc_NtkHasBdd(pNtk) )
+ {
+ if ( !Abc_NtkBddToSop(pNtk,0) )
+ return 0;
+ return Abc_NtkSopToAig(pNtk);
+ }
+ if ( Abc_NtkHasSop(pNtk) )
+ return Abc_NtkSopToAig(pNtk);
+ assert( 0 );
+ return 0;
+}
+
+
////////////////////////////////////////////////////////////////////////
/// END OF FILE ///
////////////////////////////////////////////////////////////////////////
diff --git a/src/base/abc/abcHie.c b/src/base/abc/abcHie.c
new file mode 100644
index 00000000..56333a36
--- /dev/null
+++ b/src/base/abc/abcHie.c
@@ -0,0 +1,492 @@
+/**CFile****************************************************************
+
+ FileName [abcHie.c]
+
+ SystemName [ABC: Logic synthesis and verification system.]
+
+ PackageName [Network and node package.]
+
+ Synopsis [Procedures to handle hierarchy.]
+
+ Author [Alan Mishchenko]
+
+ Affiliation [UC Berkeley]
+
+ Date [Ver. 1.0. Started - June 20, 2005.]
+
+ Revision [$Id: abcHie.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "abc.h"
+
+////////////////////////////////////////////////////////////////////////
+/// DECLARATIONS ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+/// FUNCTION DEFINITIONS ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+ Synopsis [Recursively flattens logic hierarchy of the netlist.]
+
+ Description [When this procedure is called, the PI/PO nets of the old
+ netlist point to the corresponding nets of the flattened netlist.]
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Abc_NtkFlattenLogicHierarchy_rec( Abc_Ntk_t * pNtkNew, Abc_Ntk_t * pNtk, int * pCounter )
+{
+ char Suffix[1000] = {0};
+ Abc_Ntk_t * pNtkModel;
+ Abc_Obj_t * pObj, * pTerm, * pNet, * pFanin;
+ int i, k;
+
+ // process the blackbox
+ if ( Abc_NtkHasBlackbox(pNtk) )
+ {
+ // duplicate the blackbox
+ assert( Abc_NtkBoxNum(pNtk) == 1 );
+ pObj = Abc_NtkBox( pNtk, 0 );
+ Abc_NtkDupBox( pNtkNew, pObj, 1 );
+ pObj->pCopy->pData = pNtk;
+
+ // connect blackbox fanins to the PI nets
+ assert( Abc_ObjFaninNum(pObj->pCopy) == Abc_NtkPiNum(pNtk) );
+ Abc_NtkForEachPi( pNtk, pTerm, i )
+ Abc_ObjAddFanin( Abc_ObjFanin(pObj->pCopy,i), Abc_ObjFanout0(pTerm)->pCopy );
+
+ // connect blackbox fanouts to the PO nets
+ assert( Abc_ObjFanoutNum(pObj->pCopy) == Abc_NtkPoNum(pNtk) );
+ Abc_NtkForEachPo( pNtk, pTerm, i )
+ Abc_ObjAddFanin( Abc_ObjFanin0(pTerm)->pCopy, Abc_ObjFanout(pObj->pCopy,i) );
+ return;
+ }
+
+ (*pCounter)++;
+
+ // create the prefix, which will be appended to the internal names
+ if ( *pCounter )
+ sprintf( Suffix, "_%s_%d", Abc_NtkName(pNtk), *pCounter );
+
+ // duplicate nets of all boxes, including latches
+ Abc_NtkForEachBox( pNtk, pObj, i )
+ {
+ Abc_ObjForEachFanin( pObj, pTerm, k )
+ {
+ pNet = Abc_ObjFanin0(pTerm);
+ if ( pNet->pCopy )
+ continue;
+ pNet->pCopy = Abc_NtkFindOrCreateNet( pNtkNew, Abc_ObjNameSuffix(pNet, Suffix) );
+ }
+ Abc_ObjForEachFanout( pObj, pTerm, k )
+ {
+ pNet = Abc_ObjFanout0(pTerm);
+ if ( pNet->pCopy )
+ continue;
+ pNet->pCopy = Abc_NtkFindOrCreateNet( pNtkNew, Abc_ObjNameSuffix(pNet, Suffix) );
+ }
+ }
+
+ // mark objects that will not be used
+ Abc_NtkIncrementTravId( pNtk );
+ Abc_NtkForEachPi( pNtk, pTerm, i )
+ Abc_NodeSetTravIdCurrent( pTerm );
+ Abc_NtkForEachPo( pNtk, pTerm, i )
+ Abc_NodeSetTravIdCurrent( pTerm );
+ Abc_NtkForEachBox( pNtk, pObj, i )
+ {
+ if ( Abc_ObjIsLatch(pObj) )
+ continue;
+ Abc_NodeSetTravIdCurrent( pObj );
+ Abc_ObjForEachFanin( pObj, pTerm, k )
+ Abc_NodeSetTravIdCurrent( pTerm );
+ Abc_ObjForEachFanout( pObj, pTerm, k )
+ Abc_NodeSetTravIdCurrent( pTerm );
+ }
+
+ // duplicate objects that do not have prototypes yet
+ Abc_NtkForEachObj( pNtk, pObj, i )
+ {
+ if ( Abc_NodeIsTravIdCurrent(pObj) )
+ continue;
+ if ( pObj->pCopy )
+ continue;
+ Abc_NtkDupObj( pNtkNew, pObj, 0 );
+ }
+
+ // connect objects
+ Abc_NtkForEachObj( pNtk, pObj, i )
+ if ( !Abc_NodeIsTravIdCurrent(pObj) )
+ Abc_ObjForEachFanin( pObj, pFanin, k )
+ if ( !Abc_NodeIsTravIdCurrent(pFanin) )
+ Abc_ObjAddFanin( pObj->pCopy, pFanin->pCopy );
+
+ // call recursively
+ Abc_NtkForEachBox( pNtk, pObj, i )
+ {
+ if ( Abc_ObjIsLatch(pObj) )
+ continue;
+ pNtkModel = pObj->pData;
+ // check the match between the number of actual and formal parameters
+ assert( Abc_ObjFaninNum(pObj) == Abc_NtkPiNum(pNtkModel) );
+ assert( Abc_ObjFanoutNum(pObj) == Abc_NtkPoNum(pNtkModel) );
+ // clean the node copy fields
+ Abc_NtkCleanCopy( pNtkModel );
+ // map PIs/POs
+ Abc_ObjForEachFanin( pObj, pTerm, k )
+ Abc_ObjFanout0( Abc_NtkPi(pNtkModel, k) )->pCopy = Abc_ObjFanin0(pTerm)->pCopy;
+ Abc_ObjForEachFanout( pObj, pTerm, k )
+ Abc_ObjFanin0( Abc_NtkPo(pNtkModel, k) )->pCopy = Abc_ObjFanout0(pTerm)->pCopy;
+ // call recursively
+ Abc_NtkFlattenLogicHierarchy_rec( pNtkNew, pNtkModel, pCounter );
+ }
+
+ // if it is a BLIF-MV netlist transfer the values of all nets
+ if ( Abc_NtkHasBlifMv(pNtk) && Abc_NtkMvVar(pNtk) )
+ {
+ if ( Abc_NtkMvVar( pNtkNew ) == NULL )
+ Abc_NtkStartMvVars( pNtkNew );
+ Abc_NtkForEachNet( pNtk, pObj, i )
+ Abc_NtkSetMvVarValues( pObj->pCopy, Abc_ObjMvVarNum(pObj) );
+ }
+}
+
+/**Function*************************************************************
+
+ Synopsis [Flattens the logic hierarchy of the netlist.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Abc_Ntk_t * Abc_NtkFlattenLogicHierarchy( Abc_Ntk_t * pNtk )
+{
+ Abc_Ntk_t * pNtkNew;
+ Abc_Obj_t * pTerm, * pNet;
+ int i, Counter;
+ extern Abc_Lib_t * Abc_LibDupBlackboxes( Abc_Lib_t * pLib, Abc_Ntk_t * pNtkSave );
+
+ assert( Abc_NtkIsNetlist(pNtk) );
+ // start the network
+ pNtkNew = Abc_NtkAlloc( pNtk->ntkType, pNtk->ntkFunc, 1 );
+ // duplicate the name and the spec
+ pNtkNew->pName = Extra_UtilStrsav(pNtk->pName);
+ pNtkNew->pSpec = Extra_UtilStrsav(pNtk->pSpec);
+
+ // clean the node copy fields
+ Abc_NtkCleanCopy( pNtk );
+
+ // duplicate PIs/POs and their nets
+ Abc_NtkForEachPi( pNtk, pTerm, i )
+ {
+ Abc_NtkDupObj( pNtkNew, pTerm, 0 );
+ pNet = Abc_ObjFanout0( pTerm );
+ pNet->pCopy = Abc_NtkFindOrCreateNet( pNtkNew, Abc_ObjName(pNet) );
+ Abc_ObjAddFanin( pNet->pCopy, pTerm->pCopy );
+ }
+ Abc_NtkForEachPo( pNtk, pTerm, i )
+ {
+ Abc_NtkDupObj( pNtkNew, pTerm, 0 );
+ pNet = Abc_ObjFanin0( pTerm );
+ pNet->pCopy = Abc_NtkFindOrCreateNet( pNtkNew, Abc_ObjName(pNet) );
+ Abc_ObjAddFanin( pTerm->pCopy, pNet->pCopy );
+ }
+
+ // recursively flatten hierarchy, create internal logic, add new PI/PO names if there are black boxes
+ Counter = -1;
+ Abc_NtkFlattenLogicHierarchy_rec( pNtkNew, pNtk, &Counter );
+ printf( "Hierarchy reader flattened %d instances of logic boxes and left %d black boxes.\n",
+ Counter, Abc_NtkBlackboxNum(pNtkNew) );
+
+ if ( pNtk->pDesign )
+ {
+ // pass on the design
+ assert( Vec_PtrEntry(pNtk->pDesign->vTops, 0) == pNtk );
+ pNtkNew->pDesign = Abc_LibDupBlackboxes( pNtk->pDesign, pNtkNew );
+ // update the pointers
+ Abc_NtkForEachBlackbox( pNtkNew, pTerm, i )
+ pTerm->pData = ((Abc_Ntk_t *)pTerm->pData)->pCopy;
+ }
+
+ // copy the timing information
+// Abc_ManTimeDup( pNtk, pNtkNew );
+ // duplicate EXDC
+ if ( pNtk->pExdc )
+ printf( "EXDC is not transformed.\n" );
+ if ( !Abc_NtkCheck( pNtkNew ) )
+ {
+ fprintf( stdout, "Abc_NtkFlattenLogicHierarchy(): Network check has failed.\n" );
+ Abc_NtkDelete( pNtkNew );
+ return NULL;
+ }
+ return pNtkNew;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Extracts blackboxes by making them into additional PIs/POs.]
+
+ Description [The input netlist has not logic hierarchy. The resulting
+ netlist has additional PIs/POs for each blackbox input/output.]
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Abc_Ntk_t * Abc_NtkConvertBlackboxes( Abc_Ntk_t * pNtk )
+{
+ Abc_Ntk_t * pNtkNew;
+ Abc_Obj_t * pObj, * pNet, * pFanin, * pTerm;
+ int i, k;
+
+ assert( Abc_NtkIsNetlist(pNtk) );
+ assert( Abc_NtkWhiteboxNum(pNtk) == 0 );
+
+ // start the network
+ pNtkNew = Abc_NtkAlloc( pNtk->ntkType, pNtk->ntkFunc, 1 );
+ // duplicate the name and the spec
+ pNtkNew->pName = Extra_UtilStrsav( pNtk->pName );
+ pNtkNew->pSpec = Extra_UtilStrsav( pNtk->pSpec );
+
+ // clean the node copy fields
+ Abc_NtkCleanCopy( pNtk );
+
+ // mark the nodes that should not be connected
+ Abc_NtkIncrementTravId( pNtk );
+ Abc_NtkForEachBlackbox( pNtk, pObj, i )
+ Abc_NodeSetTravIdCurrent( pObj );
+ Abc_NtkForEachCi( pNtk, pTerm, i )
+ Abc_NodeSetTravIdCurrent( pTerm );
+ Abc_NtkForEachCo( pNtk, pTerm, i )
+ Abc_NodeSetTravIdCurrent( pTerm );
+ // unmark PIs and LIs/LOs
+ Abc_NtkForEachPi( pNtk, pTerm, i )
+ Abc_NodeSetTravIdPrevious( pTerm );
+ Abc_NtkForEachLatchInput( pNtk, pTerm, i )
+ Abc_NodeSetTravIdPrevious( pTerm );
+ Abc_NtkForEachLatchOutput( pNtk, pTerm, i )
+ Abc_NodeSetTravIdPrevious( pTerm );
+ // copy the box outputs
+ Abc_NtkForEachBlackbox( pNtk, pObj, i )
+ Abc_ObjForEachFanout( pObj, pTerm, k )
+ pTerm->pCopy = Abc_NtkCreatePi( pNtkNew );
+
+ // duplicate other objects
+ Abc_NtkForEachObj( pNtk, pObj, i )
+ if ( !Abc_NodeIsTravIdCurrent(pObj) )
+ Abc_NtkDupObj( pNtkNew, pObj, Abc_ObjIsNet(pObj) );
+
+ // connect all objects
+ Abc_NtkForEachObj( pNtk, pObj, i )
+ if ( !Abc_NodeIsTravIdCurrent(pObj) )
+ Abc_ObjForEachFanin( pObj, pFanin, k )
+ Abc_ObjAddFanin( pObj->pCopy, pFanin->pCopy );
+
+ // create unique PO for each net feeding into blackboxes or POs
+ Abc_NtkIncrementTravId( pNtk );
+ Abc_NtkForEachCo( pNtk, pTerm, i )
+ {
+ // skip latch inputs
+ assert( Abc_ObjFanoutNum(pTerm) <= 1 );
+ if ( Abc_ObjFanoutNum(pTerm) > 0 && Abc_ObjIsLatch(Abc_ObjFanout0(pTerm)) )
+ continue;
+ // check if the net is visited
+ pNet = Abc_ObjFanin0(pTerm);
+ if ( Abc_NodeIsTravIdCurrent(pNet) )
+ continue;
+ // create PO
+ Abc_NodeSetTravIdCurrent( pNet );
+ Abc_ObjAddFanin( Abc_NtkCreatePo(pNtkNew), pNet->pCopy );
+ }
+
+ // check integrity
+ if ( !Abc_NtkCheck( pNtkNew ) )
+ {
+ fprintf( stdout, "Abc_NtkConvertBlackboxes(): Network check has failed.\n" );
+ Abc_NtkDelete( pNtkNew );
+ return NULL;
+ }
+ return pNtkNew;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Inserts blackboxes into the netlist.]
+
+ Description [The first arg is the netlist with blackboxes without logic hierarchy.
+ The second arg is a non-hierarchical netlist derived from the above netlist after processing.
+ This procedure create a new netlist, which is comparable to the original netlist with
+ blackboxes, except that it contains logic nodes from the netlist after processing.]
+
+ SideEffects [This procedure silently assumes that blackboxes appear
+ only in the top-level model. If they appear in other models as well,
+ the name of the model and its number were appended to the names of
+ blackbox inputs/outputs.]
+
+ SeeAlso []
+
+***********************************************************************/
+Abc_Ntk_t * Abc_NtkInsertNewLogic( Abc_Ntk_t * pNtkH, Abc_Ntk_t * pNtkL )
+{
+ Abc_Lib_t * pDesign;
+ Abc_Ntk_t * pNtkNew;
+ Abc_Obj_t * pObjH, * pObjL, * pNetH, * pNetL, * pTermH;
+ int i, k;
+
+ assert( Abc_NtkIsNetlist(pNtkH) );
+ assert( Abc_NtkWhiteboxNum(pNtkH) == 0 );
+ assert( Abc_NtkBlackboxNum(pNtkH) > 0 );
+
+ assert( Abc_NtkIsNetlist(pNtkL) );
+ assert( Abc_NtkWhiteboxNum(pNtkL) == 0 );
+ assert( Abc_NtkBlackboxNum(pNtkL) == 0 );
+
+ // prepare the logic network for copying
+ Abc_NtkCleanCopy( pNtkL );
+
+ // start the network
+ pNtkNew = Abc_NtkAlloc( pNtkL->ntkType, pNtkL->ntkFunc, 1 );
+ // duplicate the name and the spec
+ pNtkNew->pName = Extra_UtilStrsav( pNtkH->pName );
+ pNtkNew->pSpec = Extra_UtilStrsav( pNtkH->pSpec );
+
+ // make sure every PI/PO has a PI/PO in the processed network
+ Abc_NtkForEachPi( pNtkH, pObjH, i )
+ {
+ pNetH = Abc_ObjFanout0(pObjH);
+ pNetL = Abc_NtkFindNet( pNtkL, Abc_ObjName(pNetH) );
+ if ( pNetL == NULL || !Abc_ObjIsPi( Abc_ObjFanin0(pNetL) ) )
+ {
+ printf( "Error in Abc_NtkInsertNewLogic(): There is no PI corresponding to the PI %s.\n", Abc_ObjName(pNetH) );
+ Abc_NtkDelete( pNtkNew );
+ return NULL;
+ }
+ if ( pNetL->pCopy )
+ {
+ printf( "Error in Abc_NtkInsertNewLogic(): Primary input %s is repeated twice.\n", Abc_ObjName(pNetH) );
+ Abc_NtkDelete( pNtkNew );
+ return NULL;
+ }
+ // create the new net
+ pNetL->pCopy = Abc_NtkFindOrCreateNet( pNtkNew, Abc_ObjName(pNetH) );
+ Abc_NtkDupObj( pNtkNew, Abc_ObjFanin0(pNetL), 0 );
+ }
+
+ // make sure every BB has a PI/PO in the processed network
+ Abc_NtkForEachBlackbox( pNtkH, pObjH, i )
+ {
+ // duplicate the box
+ Abc_NtkDupBox( pNtkNew, pObjH, 0 );
+ pObjH->pCopy->pData = pObjH->pData;
+ // create PIs
+ Abc_ObjForEachFanout( pObjH, pTermH, k )
+ {
+ pNetH = Abc_ObjFanout0( pTermH );
+ pNetL = Abc_NtkFindNet( pNtkL, Abc_ObjName(pNetH) );
+ if ( pNetL == NULL || !Abc_ObjIsPi( Abc_ObjFanin0(pNetL) ) )
+ {
+ printf( "Error in Abc_NtkInsertNewLogic(): There is no PI corresponding to the inpout %s of blackbox %s.\n", Abc_ObjName(pNetH), Abc_ObjName(pObjH) );
+ Abc_NtkDelete( pNtkNew );
+ return NULL;
+ }
+ if ( pNetL->pCopy )
+ {
+ printf( "Error in Abc_NtkInsertNewLogic(): Box output %s is repeated twice.\n", Abc_ObjName(pNetH) );
+ Abc_NtkDelete( pNtkNew );
+ return NULL;
+ }
+ // create net and map the PI
+ pNetL->pCopy = Abc_NtkFindOrCreateNet( pNtkNew, Abc_ObjName(pNetH) );
+ Abc_ObjFanin0(pNetL)->pCopy = pTermH->pCopy;
+ }
+ }
+
+ Abc_NtkForEachPo( pNtkH, pObjH, i )
+ {
+ pNetH = Abc_ObjFanin0(pObjH);
+ pNetL = Abc_NtkFindNet( pNtkL, Abc_ObjName(pNetH) );
+ if ( pNetL == NULL || !Abc_ObjIsPo( Abc_ObjFanout0(pNetL) ) )
+ {
+ printf( "Error in Abc_NtkInsertNewLogic(): There is no PO corresponding to the PO %s.\n", Abc_ObjName(pNetH) );
+ Abc_NtkDelete( pNtkNew );
+ return NULL;
+ }
+ if ( pNetL->pCopy )
+ continue;
+ // create the new net
+ pNetL->pCopy = Abc_NtkFindOrCreateNet( pNtkNew, Abc_ObjName(pNetH) );
+ Abc_NtkDupObj( pNtkNew, Abc_ObjFanout0(pNetL), 0 );
+ }
+ Abc_NtkForEachBlackbox( pNtkH, pObjH, i )
+ {
+ Abc_ObjForEachFanin( pObjH, pTermH, k )
+ {
+ char * pName;
+ pNetH = Abc_ObjFanin0( pTermH );
+ pName = Abc_ObjName(pNetH);
+ pNetL = Abc_NtkFindNet( pNtkL, Abc_ObjName(pNetH) );
+ if ( pNetL == NULL || !Abc_ObjIsPo( Abc_ObjFanout0(pNetL) ) )
+ {
+ printf( "There is no PO corresponding to the input %s of blackbox %s.\n", Abc_ObjName(pNetH), Abc_ObjName(pObjH) );
+ Abc_NtkDelete( pNtkNew );
+ return NULL;
+ }
+ // create net and map the PO
+ if ( pNetL->pCopy )
+ {
+ if ( Abc_ObjFanout0(pNetL)->pCopy == NULL )
+ Abc_ObjFanout0(pNetL)->pCopy = pTermH->pCopy;
+ else
+ Abc_ObjAddFanin( pTermH->pCopy, pNetL->pCopy );
+ continue;
+ }
+ pNetL->pCopy = Abc_NtkFindOrCreateNet( pNtkNew, Abc_ObjName(pNetH) );
+ Abc_ObjFanout0(pNetL)->pCopy = pTermH->pCopy;
+ }
+ }
+
+ // duplicate other objects of the logic network
+ Abc_NtkForEachObj( pNtkL, pObjL, i )
+ if ( pObjL->pCopy == NULL && !Abc_ObjIsPo(pObjL) ) // skip POs feeding into PIs
+ Abc_NtkDupObj( pNtkNew, pObjL, Abc_ObjIsNet(pObjL) );
+
+ // connect objects
+ Abc_NtkForEachObj( pNtkL, pObjL, i )
+ Abc_ObjForEachFanin( pObjL, pNetL, k )
+ if ( pObjL->pCopy )
+ Abc_ObjAddFanin( pObjL->pCopy, pNetL->pCopy );
+
+ // transfer the design
+ pDesign = pNtkH->pDesign; pNtkH->pDesign = NULL;
+ assert( Vec_PtrEntry( pDesign->vModules, 0 ) == pNtkH );
+ Vec_PtrWriteEntry( pDesign->vModules, 0, pNtkNew );
+ pNtkNew->pDesign = pDesign;
+
+//Abc_NtkPrintStats( stdout, pNtkH, 0 );
+//Abc_NtkPrintStats( stdout, pNtkNew, 0 );
+
+ // check integrity
+ if ( !Abc_NtkCheck( pNtkNew ) )
+ {
+ fprintf( stdout, "Abc_NtkInsertNewLogic(): Network check has failed.\n" );
+ Abc_NtkDelete( pNtkNew );
+ return NULL;
+ }
+ return pNtkNew;
+}
+
+////////////////////////////////////////////////////////////////////////
+/// END OF FILE ///
+////////////////////////////////////////////////////////////////////////
+
+
diff --git a/src/base/abc/abcInt.h b/src/base/abc/abcInt.h
index 1a1ab75f..0e35e774 100644
--- a/src/base/abc/abcInt.h
+++ b/src/base/abc/abcInt.h
@@ -29,18 +29,24 @@
/// PARAMETERS ///
////////////////////////////////////////////////////////////////////////
+#define ABC_NUM_STEPS 10
+
////////////////////////////////////////////////////////////////////////
/// STRUCTURE DEFINITIONS ///
////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////
-/// MACRO DEFITIONS ///
+/// MACRO DEFINITIONS ///
////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////
-/// END OF FILE ///
+/// FUNCTION DECLARATIONS ///
////////////////////////////////////////////////////////////////////////
#endif
+////////////////////////////////////////////////////////////////////////
+/// END OF FILE ///
+////////////////////////////////////////////////////////////////////////
+
diff --git a/src/base/abc/abcLatch.c b/src/base/abc/abcLatch.c
index d804601e..d96bbfac 100644
--- a/src/base/abc/abcLatch.c
+++ b/src/base/abc/abcLatch.c
@@ -25,7 +25,7 @@
////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////
-/// FUNCTION DEFITIONS ///
+/// FUNCTION DEFINITIONS ///
////////////////////////////////////////////////////////////////////////
/**Function*************************************************************
@@ -45,10 +45,10 @@ bool Abc_NtkLatchIsSelfFeed_rec( Abc_Obj_t * pLatch, Abc_Obj_t * pLatchRoot )
assert( Abc_ObjIsLatch(pLatch) );
if ( pLatch == pLatchRoot )
return 1;
- pFanin = Abc_ObjFanin0(pLatch);
- if ( !Abc_ObjIsLatch(pFanin) )
+ pFanin = Abc_ObjFanin0(Abc_ObjFanin0(pLatch));
+ if ( !Abc_ObjIsBo(pFanin) || !Abc_ObjIsLatch(Abc_ObjFanin0(pFanin)) )
return 0;
- return Abc_NtkLatchIsSelfFeed_rec( pFanin, pLatch );
+ return Abc_NtkLatchIsSelfFeed_rec( Abc_ObjFanin0(pFanin), pLatch );
}
/**Function*************************************************************
@@ -66,10 +66,10 @@ bool Abc_NtkLatchIsSelfFeed( Abc_Obj_t * pLatch )
{
Abc_Obj_t * pFanin;
assert( Abc_ObjIsLatch(pLatch) );
- pFanin = Abc_ObjFanin0(pLatch);
- if ( !Abc_ObjIsLatch(pFanin) )
+ pFanin = Abc_ObjFanin0(Abc_ObjFanin0(pLatch));
+ if ( !Abc_ObjIsBo(pFanin) || !Abc_ObjIsLatch(Abc_ObjFanin0(pFanin)) )
return 0;
- return Abc_NtkLatchIsSelfFeed_rec( pFanin, pLatch );
+ return Abc_NtkLatchIsSelfFeed_rec( Abc_ObjFanin0(pFanin), pLatch );
}
/**Function*************************************************************
@@ -89,10 +89,234 @@ int Abc_NtkCountSelfFeedLatches( Abc_Ntk_t * pNtk )
int i, Counter;
Counter = 0;
Abc_NtkForEachLatch( pNtk, pLatch, i )
+ {
+// if ( Abc_NtkLatchIsSelfFeed(pLatch) && Abc_ObjFanoutNum(pLatch) > 1 )
+// printf( "Fanouts = %d.\n", Abc_ObjFanoutNum(pLatch) );
Counter += Abc_NtkLatchIsSelfFeed( pLatch );
+ }
return Counter;
}
+/**Function*************************************************************
+
+ Synopsis [Replaces self-feeding latches by latches with constant inputs.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Abc_NtkRemoveSelfFeedLatches( Abc_Ntk_t * pNtk )
+{
+ Abc_Obj_t * pLatch, * pConst1;
+ int i, Counter;
+ Counter = 0;
+ Abc_NtkForEachLatch( pNtk, pLatch, i )
+ {
+ if ( Abc_NtkLatchIsSelfFeed( pLatch ) )
+ {
+ if ( Abc_NtkIsStrash(pNtk) )
+ pConst1 = Abc_AigConst1(pNtk);
+ else
+ pConst1 = Abc_NtkCreateNodeConst1(pNtk);
+ Abc_ObjPatchFanin( Abc_ObjFanin0(pLatch), Abc_ObjFanin0(Abc_ObjFanin0(pLatch)), pConst1 );
+ Counter++;
+ }
+ }
+ return Counter;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Pipelines the network with latches.]
+
+ Description []
+
+ SideEffects [Does not check the names of the added latches!!!]
+
+ SeeAlso []
+
+***********************************************************************/
+void Abc_NtkLatchPipe( Abc_Ntk_t * pNtk, int nLatches )
+{
+ Vec_Ptr_t * vNodes;
+ Abc_Obj_t * pObj, * pLatch, * pFanin, * pFanout;
+ int i, k, nTotal, nDigits;
+ if ( nLatches < 1 )
+ return;
+ nTotal = nLatches * Abc_NtkPiNum(pNtk);
+ nDigits = Extra_Base10Log( nTotal );
+ vNodes = Vec_PtrAlloc( 100 );
+ Abc_NtkForEachPi( pNtk, pObj, i )
+ {
+ // remember current fanins of the PI
+ Abc_NodeCollectFanouts( pObj, vNodes );
+ // create the latches
+ for ( pFanin = pObj, k = 0; k < nLatches; k++, pFanin = pLatch )
+ {
+ pLatch = Abc_NtkCreateLatch( pNtk );
+ Abc_ObjAddFanin( pLatch, pFanin );
+ Abc_LatchSetInitDc( pLatch );
+ // create the name of the new latch
+ Abc_ObjAssignName( pLatch, Abc_ObjNameDummy("LL", i*nLatches + k, nDigits), NULL );
+ }
+ // patch the PI fanouts
+ Vec_PtrForEachEntry( vNodes, pFanout, k )
+ Abc_ObjPatchFanin( pFanout, pObj, pFanin );
+ }
+ Vec_PtrFree( vNodes );
+ Abc_NtkLogicMakeSimpleCos( pNtk, 0 );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Strashes one logic node using its SOP.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Vec_Int_t * Abc_NtkCollectLatchValues( Abc_Ntk_t * pNtk )
+{
+ Vec_Int_t * vValues;
+ Abc_Obj_t * pLatch;
+ int i;
+ vValues = Vec_IntAlloc( Abc_NtkLatchNum(pNtk) );
+ Abc_NtkForEachLatch( pNtk, pLatch, i )
+ Vec_IntPush( vValues, Abc_LatchIsInit1(pLatch) );
+ return vValues;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Strashes one logic node using its SOP.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Abc_NtkInsertLatchValues( Abc_Ntk_t * pNtk, Vec_Int_t * vValues )
+{
+ Abc_Obj_t * pLatch;
+ int i;
+ Abc_NtkForEachLatch( pNtk, pLatch, i )
+ pLatch->pData = (void *)(vValues? (Vec_IntEntry(vValues,i)? ABC_INIT_ONE : ABC_INIT_ZERO) : ABC_INIT_DC);
+}
+
+/**Function*************************************************************
+
+ Synopsis [Creates latch with the given initial value.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Abc_Obj_t * Abc_NtkAddLatch( Abc_Ntk_t * pNtk, Abc_Obj_t * pDriver, Abc_InitType_t Init )
+{
+ Abc_Obj_t * pLatchOut, * pLatch, * pLatchIn;
+ pLatchOut = Abc_NtkCreateBo(pNtk);
+ pLatch = Abc_NtkCreateLatch(pNtk);
+ pLatchIn = Abc_NtkCreateBi(pNtk);
+ Abc_ObjAssignName( pLatchOut, Abc_ObjName(pLatch), "_lo" );
+ Abc_ObjAssignName( pLatchIn, Abc_ObjName(pLatch), "_li" );
+ Abc_ObjAddFanin( pLatchOut, pLatch );
+ Abc_ObjAddFanin( pLatch, pLatchIn );
+ Abc_ObjAddFanin( pLatchIn, pDriver );
+ pLatch->pData = (void *)Init;
+ return pLatchOut;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Creates MUX.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Abc_NtkNodeConvertToMux( Abc_Ntk_t * pNtk, Abc_Obj_t * pNodeC, Abc_Obj_t * pNode1, Abc_Obj_t * pNode0, Abc_Obj_t * pMux )
+{
+ assert( Abc_NtkIsLogic(pNtk) );
+ Abc_ObjAddFanin( pMux, pNodeC );
+ Abc_ObjAddFanin( pMux, pNode1 );
+ Abc_ObjAddFanin( pMux, pNode0 );
+ if ( Abc_NtkHasSop(pNtk) )
+ pMux->pData = Abc_SopRegister( pNtk->pManFunc, "11- 1\n0-1 1\n" );
+ else if ( Abc_NtkHasBdd(pNtk) )
+ pMux->pData = Cudd_bddIte(pNtk->pManFunc,Cudd_bddIthVar(pNtk->pManFunc,0),Cudd_bddIthVar(pNtk->pManFunc,1),Cudd_bddIthVar(pNtk->pManFunc,2)), Cudd_Ref( pMux->pData );
+ else if ( Abc_NtkHasAig(pNtk) )
+ pMux->pData = Hop_Mux(pNtk->pManFunc,Hop_IthVar(pNtk->pManFunc,0),Hop_IthVar(pNtk->pManFunc,1),Hop_IthVar(pNtk->pManFunc,2));
+ else
+ assert( 0 );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Converts registers with DC values into additional PIs.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Abc_NtkConvertDcLatches( Abc_Ntk_t * pNtk )
+{
+ Abc_Obj_t * pCtrl, * pLatch, * pMux, * pPi;
+ Abc_InitType_t Init = ABC_INIT_ZERO;
+ int i, fFound = 0, Counter;
+ // check if there are latches with DC values
+ Abc_NtkForEachLatch( pNtk, pLatch, i )
+ if ( Abc_LatchIsInitDc(pLatch) )
+ {
+ fFound = 1;
+ break;
+ }
+ if ( !fFound )
+ return;
+ // add control latch
+ pCtrl = Abc_NtkAddLatch( pNtk, Abc_NtkCreateNodeConst1(pNtk), Init );
+ // add fanouts for each latch with DC values
+ Counter = 0;
+ Abc_NtkForEachLatch( pNtk, pLatch, i )
+ {
+ if ( !Abc_LatchIsInitDc(pLatch) )
+ continue;
+ // change latch value
+ pLatch->pData = (void *)Init;
+ // if the latch output has the same name as a PO, rename it
+ if ( Abc_NodeFindCoFanout( Abc_ObjFanout0(pLatch) ) )
+ {
+ Nm_ManDeleteIdName( pLatch->pNtk->pManName, Abc_ObjFanout0(pLatch)->Id );
+ Abc_ObjAssignName( Abc_ObjFanout0(pLatch), Abc_ObjName(pLatch), "_lo" );
+ }
+ // create new PIs
+ pPi = Abc_NtkCreatePi( pNtk );
+ Abc_ObjAssignName( pPi, Abc_ObjName(pLatch), "_pi" );
+ // create a new node and transfer fanout from latch output to the new node
+ pMux = Abc_NtkCreateNode( pNtk );
+ Abc_ObjTransferFanout( Abc_ObjFanout0(pLatch), pMux );
+ // convert the node into a mux
+ Abc_NtkNodeConvertToMux( pNtk, pCtrl, Abc_ObjFanout0(pLatch), pPi, pMux );
+ Counter++;
+ }
+ printf( "The number of converted latches with DC values = %d.\n", Counter );
+}
////////////////////////////////////////////////////////////////////////
diff --git a/src/base/abc/abcLib.c b/src/base/abc/abcLib.c
new file mode 100644
index 00000000..feff1478
--- /dev/null
+++ b/src/base/abc/abcLib.c
@@ -0,0 +1,454 @@
+/**CFile****************************************************************
+
+ FileName [abcLib.c]
+
+ SystemName [ABC: Logic synthesis and verification system.]
+
+ PackageName [Network and node package.]
+
+ Synopsis [Functions to manipulate verilog libraries.]
+
+ Author [Alan Mishchenko]
+
+ Affiliation [UC Berkeley]
+
+ Date [Ver. 1.0. Started - June 20, 2005.]
+
+ Revision [$Id: abcLib.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "abc.h"
+
+////////////////////////////////////////////////////////////////////////
+/// DECLARATIONS ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+/// FUNCTION DEFINITIONS ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+ Synopsis [Create the library.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Abc_Lib_t * Abc_LibCreate( char * pName )
+{
+ Abc_Lib_t * p;
+ p = ALLOC( Abc_Lib_t, 1 );
+ memset( p, 0, sizeof(Abc_Lib_t) );
+ p->pName = Extra_UtilStrsav( pName );
+ p->tModules = st_init_table( strcmp, st_strhash );
+ p->vTops = Vec_PtrAlloc( 100 );
+ p->vModules = Vec_PtrAlloc( 100 );
+ p->pManFunc = Hop_ManStart();
+ p->pLibrary = NULL;
+ return p;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Frees the library.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Abc_LibFree( Abc_Lib_t * pLib, Abc_Ntk_t * pNtkSave )
+{
+ Abc_Ntk_t * pNtk;
+ int i;
+ if ( pLib->pName )
+ free( pLib->pName );
+ if ( pLib->pManFunc )
+ Hop_ManStop( pLib->pManFunc );
+ if ( pLib->tModules )
+ st_free_table( pLib->tModules );
+ if ( pLib->vModules )
+ {
+ Vec_PtrForEachEntry( pLib->vModules, pNtk, i )
+ {
+ if ( pNtk == pNtkSave )
+ continue;
+// pNtk->pManFunc = NULL;
+ pNtk->pDesign = NULL;
+ Abc_NtkDelete( pNtk );
+ }
+ Vec_PtrFree( pLib->vModules );
+ }
+ if ( pLib->vTops )
+ Vec_PtrFree( pLib->vTops );
+ free( pLib );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Frees the library.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Abc_Lib_t * Abc_LibDupBlackboxes( Abc_Lib_t * pLib, Abc_Ntk_t * pNtkSave )
+{
+ Abc_Lib_t * pLibNew;
+ Abc_Ntk_t * pNtkTemp;
+ int i;
+ assert( Vec_PtrSize(pLib->vTops) > 0 );
+ assert( Vec_PtrSize(pLib->vModules) > 1 );
+ pLibNew = Abc_LibCreate( pLib->pName );
+// pLibNew->pManFunc = pNtkSave->pManFunc;
+ Vec_PtrPush( pLibNew->vTops, pNtkSave );
+ Vec_PtrPush( pLibNew->vModules, pNtkSave );
+ Vec_PtrForEachEntry( pLib->vModules, pNtkTemp, i )
+ if ( Abc_NtkHasBlackbox( pNtkTemp ) )
+ Vec_PtrPush( pLibNew->vModules, Abc_NtkDup(pNtkTemp) );
+ return pLibNew;
+}
+
+
+/**Function*************************************************************
+
+ Synopsis [Prints the library.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Abc_LibPrint( Abc_Lib_t * pLib )
+{
+ Abc_Ntk_t * pNtk;
+ Abc_Obj_t * pObj;
+ int i, k;
+ printf( "Models of design %s:\n", pLib->pName );
+ Vec_PtrForEachEntry( pLib->vModules, pNtk, i )
+ {
+ printf( "%2d : %20s ", i+1, pNtk->pName );
+ printf( "nd = %6d lat = %6d whitebox = %3d blackbox = %3d\n",
+ Abc_NtkNodeNum(pNtk), Abc_NtkLatchNum(pNtk),
+ Abc_NtkWhiteboxNum(pNtk), Abc_NtkBlackboxNum(pNtk) );
+ if ( Abc_NtkBlackboxNum(pNtk) == 0 )
+ continue;
+ Abc_NtkForEachWhitebox( pNtk, pObj, k )
+ printf( " %20s (whitebox)\n", Abc_NtkName(pObj->pData) );
+ Abc_NtkForEachBlackbox( pNtk, pObj, k )
+ printf( " %20s (blackbox)\n", Abc_NtkName(pObj->pData) );
+ }
+}
+
+/**Function*************************************************************
+
+ Synopsis [Create the library.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Abc_LibAddModel( Abc_Lib_t * pLib, Abc_Ntk_t * pNtk )
+{
+ if ( st_is_member( pLib->tModules, (char *)pNtk->pName ) )
+ return 0;
+ st_insert( pLib->tModules, (char *)pNtk->pName, (char *)pNtk );
+ Vec_PtrPush( pLib->vModules, pNtk );
+ pNtk->pDesign = pLib;
+ return 1;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Create the library.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Abc_Ntk_t * Abc_LibFindModelByName( Abc_Lib_t * pLib, char * pName )
+{
+ Abc_Ntk_t * pNtk;
+ if ( !st_is_member( pLib->tModules, (char *)pName ) )
+ return NULL;
+ st_lookup( pLib->tModules, (char *)pName, (char **)&pNtk );
+ return pNtk;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Frees the library.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Abc_Ntk_t * Abc_LibDeriveRoot( Abc_Lib_t * pLib )
+{
+ Abc_Ntk_t * pNtk;
+ if ( Vec_PtrSize(pLib->vModules) > 1 )
+ {
+ printf( "The design includes more than one module and is currently not used.\n" );
+ return NULL;
+ }
+ pNtk = Vec_PtrEntry( pLib->vModules, 0 ); Vec_PtrClear( pLib->vModules );
+ pNtk->pManFunc = pLib->pManFunc; pLib->pManFunc = NULL;
+ return pNtk;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Detects the top-level models.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Abc_LibFindTopLevelModels( Abc_Lib_t * pLib )
+{
+ Abc_Ntk_t * pNtk, * pNtkBox;
+ Abc_Obj_t * pObj;
+ int i, k;
+ assert( Vec_PtrSize( pLib->vModules ) > 0 );
+ // clear the models
+ Vec_PtrForEachEntry( pLib->vModules, pNtk, i )
+ pNtk->fHieVisited = 0;
+ // mark all the models reachable from other models
+ Vec_PtrForEachEntry( pLib->vModules, pNtk, i )
+ {
+ Abc_NtkForEachBox( pNtk, pObj, k )
+ {
+ if ( Abc_ObjIsLatch(pObj) )
+ continue;
+ if ( pObj->pData == NULL )
+ continue;
+ pNtkBox = pObj->pData;
+ pNtkBox->fHieVisited = 1;
+ }
+ }
+ // collect the models that are not marked
+ Vec_PtrClear( pLib->vTops );
+ Vec_PtrForEachEntry( pLib->vModules, pNtk, i )
+ {
+ if ( pNtk->fHieVisited == 0 )
+ Vec_PtrPush( pLib->vTops, pNtk );
+ else
+ pNtk->fHieVisited = 0;
+ }
+ return Vec_PtrSize( pLib->vTops );
+}
+
+
+/**Function*************************************************************
+
+ Synopsis [Surround boxes without content (black boxes) with BIs/BOs.]
+
+ Description [Returns the number of black boxes converted.]
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Abc_LibDeriveBlackBoxes( Abc_Ntk_t * pNtk, Abc_Lib_t * pLib )
+{
+/*
+ Abc_Obj_t * pObj, * pFanin, * pFanout;
+ int i, k;
+ assert( Abc_NtkIsNetlist(pNtk) );
+ // collect blackbox nodes
+ assert( Vec_PtrSize(pNtk->vBoxes) == 0 );
+ Vec_PtrClear( pNtk->vBoxes );
+ Abc_NtkForEachBox( pNtk, pObj, i )
+ if ( Abc_NtkNodeNum(pObj->pData) == 0 )
+ Vec_PtrPush( pNtk->vBoxes, pObj );
+ // return if there is no black boxes without content
+ if ( Vec_PtrSize(pNtk->vBoxes) == 0 )
+ return 0;
+ // print the boxes
+ printf( "Black boxes are: " );
+ Abc_NtkForEachBox( pNtk, pObj, i )
+ printf( " %s", ((Abc_Ntk_t *)pObj->pData)->pName );
+ printf( "\n" );
+ // iterate through the boxes and add BIs/BOs
+ Abc_NtkForEachBox( pNtk, pObj, i )
+ {
+ // go through the fanin nets
+ Abc_ObjForEachFanin( pObj, pFanin, k )
+ Abc_ObjInsertBetween( pFanin, pObj, ABC_OBJ_BI );
+ // go through the fanout nets
+ Abc_ObjForEachFanout( pObj, pFanout, k )
+ {
+ Abc_ObjInsertBetween( pObj, pFanout, ABC_OBJ_BO );
+ // if the name is not given assign name
+ if ( pFanout->pData == NULL )
+ {
+ pFanout->pData = Abc_ObjName( pFanout );
+ Nm_ManStoreIdName( pNtk->pManName, pFanout->Id, pFanout->pData, NULL );
+ }
+ }
+ }
+ return Vec_PtrSize(pNtk->vBoxes);
+*/
+ return 0;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Derive the AIG of the logic in the netlist.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Abc_NodeStrashUsingNetwork_rec( Abc_Ntk_t * pNtkAig, Abc_Obj_t * pObj )
+{
+ Abc_Obj_t * pFanin;
+ int i;
+ assert( !Abc_ObjIsNet(pObj) );
+ if ( pObj->pCopy )
+ return;
+ // call for the fanins
+ Abc_ObjForEachFanin( pObj, pFanin, i )
+ Abc_NodeStrashUsingNetwork_rec( pNtkAig, Abc_ObjFanin0Ntk(Abc_ObjFanin0(pObj)) );
+ // compute for the node
+ pObj->pCopy = Abc_NodeStrash( pNtkAig, pObj, 0 );
+ // set for the fanout net
+ Abc_ObjFanout0(pObj)->pCopy = pObj->pCopy;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Derive the AIG of the logic in the netlist.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Abc_NodeStrashUsingNetwork( Abc_Ntk_t * pNtkAig, Abc_Obj_t * pBox )
+{
+ Abc_Ntk_t * pNtkGate;
+ Abc_Obj_t * pObj;
+ unsigned * pPolarity;
+ int i, fCompl;
+ assert( Abc_ObjIsBox(pBox) );
+ pNtkGate = pBox->pData;
+ pPolarity = (unsigned *)pBox->pNext;
+ assert( Abc_NtkIsNetlist(pNtkGate) );
+ assert( Abc_NtkLatchNum(pNtkGate) == 0 );
+ Abc_NtkCleanCopy( pNtkGate );
+ // set the PI values
+ Abc_NtkForEachPi( pNtkGate, pObj, i )
+ {
+ fCompl = (pPolarity && Abc_InfoHasBit(pPolarity, i));
+ pObj->pCopy = Abc_ObjNotCond( Abc_ObjFanin(pBox,i)->pCopy, fCompl );
+ Abc_ObjFanout0(pObj)->pCopy = pObj->pCopy;
+ }
+ // build recursively and set the PO values
+ Abc_NtkForEachPo( pNtkGate, pObj, i )
+ {
+ Abc_NodeStrashUsingNetwork_rec( pNtkAig, Abc_ObjFanin0Ntk(Abc_ObjFanin0(pObj)) );
+ Abc_ObjFanout(pBox,i)->pCopy = Abc_ObjFanin0(pObj)->pCopy;
+ }
+//printf( "processing %d\n", pBox->Id );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Derive the AIG of the logic in the netlist.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Abc_Ntk_t * Abc_LibDeriveAig( Abc_Ntk_t * pNtk, Abc_Lib_t * pLib )
+{
+ ProgressBar * pProgress;
+ Vec_Ptr_t * vNodes;
+ Abc_Ntk_t * pNtkAig;
+ Abc_Obj_t * pObj;
+ int i, nBoxes;
+ // explicitly derive black boxes
+ assert( Abc_NtkIsNetlist(pNtk) );
+ nBoxes = Abc_LibDeriveBlackBoxes( pNtk, pLib );
+ if ( nBoxes )
+ printf( "Detected and transformed %d black boxes.\n", nBoxes );
+ // create the new network with black boxes in place
+ pNtkAig = Abc_NtkStartFrom( pNtk, ABC_NTK_STRASH, ABC_FUNC_AIG );
+ // transer to the nets
+ Abc_NtkForEachCi( pNtk, pObj, i )
+ Abc_ObjFanout0(pObj)->pCopy = pObj->pCopy;
+ // build the AIG for the remaining logic in the netlist
+ vNodes = Abc_NtkDfs( pNtk, 0 );
+ pProgress = Extra_ProgressBarStart( stdout, Vec_PtrSize(vNodes) );
+ Vec_PtrForEachEntry( vNodes, pObj, i )
+ {
+ Extra_ProgressBarUpdate( pProgress, i, NULL );
+ if ( Abc_ObjIsNode(pObj) )
+ {
+ pObj->pCopy = Abc_NodeStrash( pNtkAig, pObj, 0 );
+ Abc_ObjFanout0(pObj)->pCopy = pObj->pCopy;
+ continue;
+ }
+ Abc_NodeStrashUsingNetwork( pNtkAig, pObj );
+ }
+ Extra_ProgressBarStop( pProgress );
+ Vec_PtrFree( vNodes );
+ // deallocate memory manager, which remembers the phase
+ if ( pNtk->pData )
+ {
+ Extra_MmFlexStop( pNtk->pData );
+ pNtk->pData = NULL;
+ }
+ // set the COs
+// Abc_NtkFinalize( pNtk, pNtkAig );
+ Abc_NtkForEachCo( pNtk, pObj, i )
+ Abc_ObjAddFanin( pObj->pCopy, Abc_ObjFanin0(pObj)->pCopy );
+ Abc_AigCleanup( pNtkAig->pManFunc );
+ // make sure that everything is okay
+ if ( !Abc_NtkCheck( pNtkAig ) )
+ {
+ printf( "Abc_LibDeriveAig: The network check has failed.\n" );
+ return 0;
+ }
+ return pNtkAig;
+}
+
+////////////////////////////////////////////////////////////////////////
+/// END OF FILE ///
+////////////////////////////////////////////////////////////////////////
+
+
diff --git a/src/base/abc/abcMinBase.c b/src/base/abc/abcMinBase.c
index e143ba7b..e1c0f4fd 100644
--- a/src/base/abc/abcMinBase.c
+++ b/src/base/abc/abcMinBase.c
@@ -27,7 +27,7 @@
static int Abc_NodeSupport( DdNode * bFunc, Vec_Str_t * vSupport, int nVars );
////////////////////////////////////////////////////////////////////////
-/// FUNCTION DEFITIONS ///
+/// FUNCTION DEFINITIONS ///
////////////////////////////////////////////////////////////////////////
/**Function*************************************************************
@@ -65,8 +65,8 @@ int Abc_NtkMinimumBase( Abc_Ntk_t * pNtk )
***********************************************************************/
int Abc_NodeMinimumBase( Abc_Obj_t * pNode )
{
- Vec_Str_t * vSupport = pNode->pNtk->vStrTemp;
- Vec_Ptr_t * vFanins = pNode->pNtk->vPtrTemp;
+ Vec_Str_t * vSupport;
+ Vec_Ptr_t * vFanins;
DdNode * bTemp;
int i, nVars;
@@ -74,11 +74,16 @@ int Abc_NodeMinimumBase( Abc_Obj_t * pNode )
assert( Abc_ObjIsNode(pNode) );
// compute support
+ vSupport = Vec_StrAlloc( 10 );
nVars = Abc_NodeSupport( Cudd_Regular(pNode->pData), vSupport, Abc_ObjFaninNum(pNode) );
if ( nVars == Abc_ObjFaninNum(pNode) )
+ {
+ Vec_StrFree( vSupport );
return 0;
+ }
// remove unused fanins
+ vFanins = Vec_PtrAlloc( Abc_ObjFaninNum(pNode) );
Abc_NodeCollectFanins( pNode, vFanins );
for ( i = 0; i < vFanins->nSize; i++ )
if ( vSupport->pArray[i] == 0 )
@@ -88,6 +93,8 @@ int Abc_NodeMinimumBase( Abc_Obj_t * pNode )
// update the function of the node
pNode->pData = Extra_bddRemapUp( pNode->pNtk->pManFunc, bTemp = pNode->pData ); Cudd_Ref( pNode->pData );
Cudd_RecursiveDeref( pNode->pNtk->pManFunc, bTemp );
+ Vec_PtrFree( vFanins );
+ Vec_StrFree( vSupport );
return 1;
}
@@ -105,12 +112,11 @@ int Abc_NodeMinimumBase( Abc_Obj_t * pNode )
int Abc_NtkRemoveDupFanins( Abc_Ntk_t * pNtk )
{
Abc_Obj_t * pNode;
- int i, Counter, fChanged;
+ int i, Counter;
assert( Abc_NtkIsBddLogic(pNtk) );
Counter = 0;
Abc_NtkForEachNode( pNtk, pNode, i )
- while ( fChanged = Abc_NodeRemoveDupFanins(pNode) )
- Counter += fChanged;
+ Counter += Abc_NodeRemoveDupFanins( pNode );
return Counter;
}
@@ -125,7 +131,7 @@ int Abc_NtkRemoveDupFanins( Abc_Ntk_t * pNtk )
SeeAlso []
***********************************************************************/
-int Abc_NodeRemoveDupFanins( Abc_Obj_t * pNode )
+int Abc_NodeRemoveDupFanins_int( Abc_Obj_t * pNode )
{
Abc_Obj_t * pFanin1, * pFanin2;
int i, k;
@@ -158,6 +164,24 @@ int Abc_NodeRemoveDupFanins( Abc_Obj_t * pNode )
/**Function*************************************************************
+ Synopsis [Removes duplicated fanins if present.]
+
+ Description [Returns the number of fanins removed.]
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Abc_NodeRemoveDupFanins( Abc_Obj_t * pNode )
+{
+ int Counter = 0;
+ while ( Abc_NodeRemoveDupFanins_int(pNode) )
+ Counter++;
+ return Counter;
+}
+/**Function*************************************************************
+
Synopsis [Computes support of the node.]
Description []
@@ -225,6 +249,256 @@ int Abc_NodeSupport( DdNode * bFunc, Vec_Str_t * vSupport, int nVars )
return Counter;
}
+
+
+/**Function*************************************************************
+
+ Synopsis [Find the number of unique variables after collapsing.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Abc_NodeCheckDupFanin( Abc_Obj_t * pFanin, Abc_Obj_t * pFanout, int * piFanin )
+{
+ Abc_Obj_t * pObj;
+ int i, Counter = 0;
+ Abc_ObjForEachFanin( pFanout, pObj, i )
+ if ( pObj == pFanin )
+ {
+ if ( piFanin )
+ *piFanin = i;
+ Counter++;
+ }
+ return Counter;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Find the number of unique variables after collapsing.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Abc_NodeCollapseSuppSize( Abc_Obj_t * pFanin, Abc_Obj_t * pFanout, Vec_Ptr_t * vFanins )
+{
+ Abc_Obj_t * pObj;
+ int i;
+ Vec_PtrClear( vFanins );
+ Abc_ObjForEachFanin( pFanout, pObj, i )
+ if ( pObj != pFanin )
+ Vec_PtrPushUnique( vFanins, pObj );
+ Abc_ObjForEachFanin( pFanin, pObj, i )
+ Vec_PtrPushUnique( vFanins, pObj );
+ return Vec_PtrSize( vFanins );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Returns the index of the new fanin.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Abc_ObjFaninNumberNew( Vec_Ptr_t * vFanins, Abc_Obj_t * pFanin )
+{
+ Abc_Obj_t * pObj;
+ int i;
+ Vec_PtrForEachEntry( vFanins, pObj, i )
+ if ( pObj == pFanin )
+ return i;
+ return -1;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Find the permutation map for the given node into the new order.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Abc_NodeCollapsePermMap( Abc_Obj_t * pNode, Abc_Obj_t * pSkip, Vec_Ptr_t * vFanins, int * pPerm )
+{
+ Abc_Obj_t * pFanin;
+ int i;
+ for ( i = 0; i < Vec_PtrSize(vFanins); i++ )
+ pPerm[i] = i;
+ Abc_ObjForEachFanin( pNode, pFanin, i )
+ {
+ if ( pFanin == pSkip )
+ continue;
+ pPerm[i] = Abc_ObjFaninNumberNew( vFanins, pFanin );
+ if ( pPerm[i] == -1 )
+ return 0;
+ }
+ return 1;
+}
+
+
+/**Function*************************************************************
+
+ Synopsis [Computes support of the node.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+DdNode * Abc_NodeCollapseFunc( Abc_Obj_t * pFanin, Abc_Obj_t * pFanout, Vec_Ptr_t * vFanins, int * pPermFanin, int * pPermFanout )
+{
+ DdManager * dd = pFanin->pNtk->pManFunc;
+ DdNode * bVar, * bFunc0, * bFunc1, * bTemp, * bFanin, * bFanout;
+ int RetValue, nSize, iFanin;
+ // can only eliminate if fanin occurs in the fanin list of the fanout exactly once
+ if ( Abc_NodeCheckDupFanin( pFanin, pFanout, &iFanin ) != 1 )
+ return NULL;
+ // find the new number of fanins after collapsing
+ nSize = Abc_NodeCollapseSuppSize( pFanin, pFanout, vFanins );
+ bVar = Cudd_bddIthVar( dd, nSize - 1 );
+ assert( nSize <= dd->size );
+ // find the permutation after collapsing
+ RetValue = Abc_NodeCollapsePermMap( pFanin, NULL, vFanins, pPermFanin );
+ assert( RetValue );
+ RetValue = Abc_NodeCollapsePermMap( pFanout, pFanin, vFanins, pPermFanout );
+ assert( RetValue );
+ // cofactor the local function of the node
+ bVar = Cudd_bddIthVar( dd, iFanin );
+ bFunc0 = Cudd_Cofactor( dd, pFanout->pData, Cudd_Not(bVar) ); Cudd_Ref( bFunc0 );
+ bFunc1 = Cudd_Cofactor( dd, pFanout->pData, bVar ); Cudd_Ref( bFunc1 );
+ // find the permutation after collapsing
+ bFunc0 = Cudd_bddPermute( dd, bTemp = bFunc0, pPermFanout ); Cudd_Ref( bFunc0 );
+ Cudd_RecursiveDeref( dd, bTemp );
+ bFunc1 = Cudd_bddPermute( dd, bTemp = bFunc1, pPermFanout ); Cudd_Ref( bFunc1 );
+ Cudd_RecursiveDeref( dd, bTemp );
+ bFanin = Cudd_bddPermute( dd, pFanin->pData, pPermFanin ); Cudd_Ref( bFanin );
+ // create the new function
+ bFanout = Cudd_bddIte( dd, bFanin, bFunc1, bFunc0 ); Cudd_Ref( bFanout );
+ Cudd_RecursiveDeref( dd, bFanin );
+ Cudd_RecursiveDeref( dd, bFunc1 );
+ Cudd_RecursiveDeref( dd, bFunc0 );
+ Cudd_Deref( bFanout );
+ return bFanout;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Collapses one node into its fanout.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Abc_NodeCollapse( Abc_Obj_t * pFanin, Abc_Obj_t * pFanout, Vec_Ptr_t * vFanins, int * pPermFanin, int * pPermFanout )
+{
+ Abc_Obj_t * pFanoutNew, * pObj;
+ DdNode * bFanoutNew;
+ int i;
+ assert( Abc_NtkIsBddLogic(pFanin->pNtk) );
+ assert( Abc_ObjIsNode(pFanin) );
+ assert( Abc_ObjIsNode(pFanout) );
+ bFanoutNew = Abc_NodeCollapseFunc( pFanin, pFanout, vFanins, pPermFanin, pPermFanout );
+ if ( bFanoutNew == NULL )
+ return 0;
+ Cudd_Ref( bFanoutNew );
+ // create the new node
+ pFanoutNew = Abc_NtkCreateNode( pFanin->pNtk );
+ Vec_PtrForEachEntry( vFanins, pObj, i )
+ Abc_ObjAddFanin( pFanoutNew, pObj );
+ pFanoutNew->pData = bFanoutNew;
+ // minimize the node
+ Abc_NodeMinimumBase( pFanoutNew );
+ // transfer the fanout
+ Abc_ObjTransferFanout( pFanout, pFanoutNew );
+ assert( Abc_ObjFanoutNum( pFanout ) == 0 );
+ Abc_NtkDeleteObj_rec( pFanout, 1 );
+ return 1;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Eliminates the nodes into their fanouts if the node size does not exceed this number.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Abc_NtkEliminate( Abc_Ntk_t * pNtk, int nMaxSize, int fReverse, int fVerbose )
+{
+ extern void Abc_NtkBddReorder( Abc_Ntk_t * pNtk, int fVerbose );
+ Vec_Ptr_t * vFanouts, * vFanins, * vNodes;
+ Abc_Obj_t * pNode, * pFanout;
+ int * pPermFanin, * pPermFanout;
+ int RetValue, i, k;
+ assert( nMaxSize > 0 );
+ assert( Abc_NtkIsLogic(pNtk) );
+ // convert network to BDD representation
+ if ( !Abc_NtkToBdd(pNtk) )
+ {
+ fprintf( stdout, "Converting to BDD has failed.\n" );
+ return 0;
+ }
+ // prepare nodes for sweeping
+ Abc_NtkRemoveDupFanins( pNtk );
+ Abc_NtkMinimumBase( pNtk );
+ Abc_NtkCleanup( pNtk, 0 );
+ // get the nodes in the given order
+ vNodes = fReverse? Abc_NtkDfsReverse( pNtk ) : Abc_NtkDfs( pNtk, 0 );
+ // go through the nodes and decide is they can be eliminated
+ pPermFanin = ALLOC( int, nMaxSize + 100 );
+ pPermFanout = ALLOC( int, nMaxSize + 100 );
+ vFanins = Vec_PtrAlloc( 100 );
+ vFanouts = Vec_PtrAlloc( 100 );
+ Vec_PtrForEachEntry( vNodes, pNode, i )
+ {
+ if ( Abc_NodeFindCoFanout(pNode) != NULL )
+ continue;
+ if ( Abc_ObjFaninNum(pNode) > nMaxSize )
+ continue;
+ Abc_ObjForEachFanout( pNode, pFanout, k )
+ if ( Abc_NodeCollapseSuppSize(pNode, pFanout, vFanins) > nMaxSize )
+ break;
+ if ( k < Abc_ObjFanoutNum(pNode) )
+ continue;
+ // perform elimination
+ Abc_NodeCollectFanouts( pNode, vFanouts );
+ Vec_PtrForEachEntry( vFanouts, pFanout, k )
+ {
+ RetValue = Abc_NodeCollapse( pNode, pFanout, vFanins, pPermFanin, pPermFanout );
+ assert( RetValue );
+ }
+ }
+ Abc_NtkBddReorder( pNtk, 0 );
+ Vec_PtrFree( vFanins );
+ Vec_PtrFree( vFanouts );
+ Vec_PtrFree( vNodes );
+ free( pPermFanin );
+ free( pPermFanout );
+ return 1;
+}
+
////////////////////////////////////////////////////////////////////////
/// END OF FILE ///
////////////////////////////////////////////////////////////////////////
diff --git a/src/base/abc/abcNames.c b/src/base/abc/abcNames.c
index 2bf6461b..91964dfa 100644
--- a/src/base/abc/abcNames.c
+++ b/src/base/abc/abcNames.c
@@ -25,95 +25,47 @@
////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////
-/// FUNCTION DEFITIONS ///
+/// FUNCTION DEFINITIONS ///
////////////////////////////////////////////////////////////////////////
/**Function*************************************************************
- Synopsis [Registers the name with the string memory manager.]
+ Synopsis [Returns the unique name for the object.]
- Description [This function should be used to register all names
- permanentsly stored with the network. The pointer returned by
- this procedure contains the copy of the name, which should be used
- in all network manipulation procedures.]
+ Description [If the name previously did not exist, creates a new unique
+ name but does not assign this name to the object. The temporary unique
+ name is stored in a static buffer inside this procedure. It is important
+ that the name is used before the function is called again!]
SideEffects []
SeeAlso []
***********************************************************************/
-char * Abc_NtkRegisterName( Abc_Ntk_t * pNtk, char * pName )
-{
- char * pRegName;
- if ( pName == NULL ) return NULL;
- pRegName = Extra_MmFlexEntryFetch( pNtk->pMmNames, strlen(pName) + 1 );
- strcpy( pRegName, pName );
- return pRegName;
-}
-
-/**Function*************************************************************
-
- Synopsis [Registers the name with the string memory manager.]
-
- Description []
-
- SideEffects []
-
- SeeAlso []
-
-***********************************************************************/
-char * Abc_NtkRegisterNamePlus( Abc_Ntk_t * pNtk, char * pName, char * pSuffix )
+char * Abc_ObjName( Abc_Obj_t * pObj )
{
- char * pRegName;
- assert( pName && pSuffix );
- pRegName = Extra_MmFlexEntryFetch( pNtk->pMmNames, strlen(pName) + strlen(pSuffix) + 1 );
- sprintf( pRegName, "%s%s", pName, pSuffix );
- return pRegName;
+ return Nm_ManCreateUniqueName( pObj->pNtk->pManName, pObj->Id );
}
/**Function*************************************************************
- Synopsis [Gets the long name of the object.]
+ Synopsis [Assigns the given name to the object.]
- Description [The temporary name is stored in a static buffer inside this
- procedure. It is important that the name is used before the function is
- called again!]
+ Description [The object should not have a name assigned. The same
+ name may be used for several objects, which they share the same net
+ in the original netlist. (For example, latch output and primary output
+ may have the same name.) This procedure returns the pointer to the
+ internally stored representation of the given name.]
SideEffects []
SeeAlso []
***********************************************************************/
-char * Abc_ObjName( Abc_Obj_t * pObj )
+char * Abc_ObjAssignName( Abc_Obj_t * pObj, char * pName, char * pSuffix )
{
- static char Buffer[500];
- char * pName;
-
- // check if the object is in the lookup table
- if ( stmm_lookup( pObj->pNtk->tObj2Name, (char *)pObj, &pName ) )
- return pName;
-
- // consider network types
- if ( Abc_NtkIsNetlist(pObj->pNtk) )
- {
- // in a netlist, nets have names, nodes have no names
- if ( Abc_ObjIsNode(pObj) )
- pObj = Abc_ObjFanout0(pObj);
- assert( Abc_ObjIsNet(pObj) );
- // if the name is not given, invent it
- if ( pObj->pData )
- sprintf( Buffer, "%s", pObj->pData );
- else
- sprintf( Buffer, "[%d]", pObj->Id ); // make sure this name is unique!!!
- }
- else
- {
- // in a logic network, PI/PO/latch names are stored in the hash table
- // internal nodes have made up names
- assert( Abc_ObjIsNode(pObj) || Abc_ObjIsLatch(pObj) );
- sprintf( Buffer, "[%d]", pObj->Id );
- }
- return Buffer;
+ assert( pName != NULL );
+ return Nm_ManStoreIdName( pObj->pNtk->pManName, pObj->Id, pObj->Type, pName, pSuffix );
}
/**Function*************************************************************
@@ -136,62 +88,7 @@ char * Abc_ObjNameSuffix( Abc_Obj_t * pObj, char * pSuffix )
/**Function*************************************************************
- Synopsis [Finds a unique name for the node.]
-
- Description [If the name exists, tries appending numbers to it until
- it becomes unique.]
-
- SideEffects []
-
- SeeAlso []
-
-***********************************************************************/
-char * Abc_ObjNameUnique( Abc_Ntk_t * pNtk, char * pName )
-{
- static char Buffer[1000];
- int Counter;
- assert( 0 );
- if ( !stmm_is_member( pNtk->tName2Net, pName ) )
- return pName;
- for ( Counter = 1; ; Counter++ )
- {
- sprintf( Buffer, "%s_%d", pName, Counter );
- if ( !stmm_is_member( pNtk->tName2Net, Buffer ) )
- return Buffer;
- }
- return NULL;
-}
-
-
-/**Function*************************************************************
-
- Synopsis [Adds new name to the network.]
-
- Description [The new object (pObjNew) is a PI, PO or latch. The name
- is registered and added to the hash table.]
-
- SideEffects []
-
- SeeAlso []
-
-***********************************************************************/
-char * Abc_NtkLogicStoreName( Abc_Obj_t * pObjNew, char * pNameOld )
-{
- char * pNewName;
- assert( Abc_ObjIsCio(pObjNew) );
- // get the new name
- pNewName = Abc_NtkRegisterName( pObjNew->pNtk, pNameOld );
- // add the name to the table
- if ( stmm_insert( pObjNew->pNtk->tObj2Name, (char *)pObjNew, pNewName ) )
- {
- assert( 0 ); // the object is added for the second time
- }
- return pNewName;
-}
-
-/**Function*************************************************************
-
- Synopsis [Adds new name to the network.]
+ Synopsis [Returns the dummy PI name.]
Description []
@@ -200,73 +97,73 @@ char * Abc_NtkLogicStoreName( Abc_Obj_t * pObjNew, char * pNameOld )
SeeAlso []
***********************************************************************/
-char * Abc_NtkLogicStoreNamePlus( Abc_Obj_t * pObjNew, char * pNameOld, char * pSuffix )
+char * Abc_ObjNameDummy( char * pPrefix, int Num, int nDigits )
{
- char * pNewName;
- assert( pSuffix );
- assert( Abc_ObjIsCio(pObjNew) );
- // get the new name
- pNewName = Abc_NtkRegisterNamePlus( pObjNew->pNtk, pNameOld, pSuffix );
- // add the name to the table
- if ( stmm_insert( pObjNew->pNtk->tObj2Name, (char *)pObjNew, pNewName ) )
- {
- assert( 0 ); // the object is added for the second time
- }
- return pNewName;
+ static char Buffer[100];
+ sprintf( Buffer, "%s%0*d", pPrefix, nDigits, Num );
+ return Buffer;
}
/**Function*************************************************************
- Synopsis [Creates the name arrays from the old network.]
+ Synopsis [Tranfers names to the old network.]
- Description []
+ Description [Assumes that the new nodes are attached using pObj->pCopy.]
SideEffects []
SeeAlso []
***********************************************************************/
-void Abc_NtkCreateCioNamesTable( Abc_Ntk_t * pNtk )
+void Abc_NtkTrasferNames( Abc_Ntk_t * pNtk, Abc_Ntk_t * pNtkNew )
{
Abc_Obj_t * pObj;
int i;
- assert( Abc_NtkIsNetlist(pNtk) );
- assert( st_count(pNtk->tObj2Name) == 0 );
- Abc_NtkForEachPi( pNtk, pObj, i )
- Abc_NtkLogicStoreName( pObj, Abc_ObjFanout0(pObj)->pData );
- Abc_NtkForEachPo( pNtk, pObj, i )
- Abc_NtkLogicStoreName( pObj, Abc_ObjFanin0(pObj)->pData );
- Abc_NtkForEachLatch( pNtk, pObj, i )
- Abc_NtkLogicStoreName( pObj, Abc_ObjFanout0(pObj)->pData );
+ assert( Abc_NtkPiNum(pNtk) == Abc_NtkPiNum(pNtkNew) );
+ assert( Abc_NtkPoNum(pNtk) == Abc_NtkPoNum(pNtkNew) );
+ assert( Abc_NtkBoxNum(pNtk) == Abc_NtkBoxNum(pNtkNew) );
+ assert( Abc_NtkAssertNum(pNtk) == Abc_NtkAssertNum(pNtkNew) );
+ assert( Nm_ManNumEntries(pNtk->pManName) > 0 );
+ assert( Nm_ManNumEntries(pNtkNew->pManName) == 0 );
+ // copy the CI/CO/box names
+ Abc_NtkForEachCi( pNtk, pObj, i )
+ Abc_ObjAssignName( pObj->pCopy, Abc_ObjName(Abc_ObjFanout0Ntk(pObj)), NULL );
+ Abc_NtkForEachCo( pNtk, pObj, i )
+ Abc_ObjAssignName( pObj->pCopy, Abc_ObjName(Abc_ObjFanin0Ntk(pObj)), NULL );
+ Abc_NtkForEachBox( pNtk, pObj, i )
+ Abc_ObjAssignName( pObj->pCopy, Abc_ObjName(pObj), NULL );
}
/**Function*************************************************************
- Synopsis [Duplicates the name arrays.]
+ Synopsis [Tranfers names to the old network.]
- Description []
+ Description [Assumes that the new nodes are attached using pObj->pCopy.]
SideEffects []
SeeAlso []
***********************************************************************/
-void Abc_NtkDupCioNamesTable( Abc_Ntk_t * pNtk, Abc_Ntk_t * pNtkNew )
+void Abc_NtkTrasferNamesNoLatches( Abc_Ntk_t * pNtk, Abc_Ntk_t * pNtkNew )
{
Abc_Obj_t * pObj;
int i;
assert( Abc_NtkPiNum(pNtk) == Abc_NtkPiNum(pNtkNew) );
assert( Abc_NtkPoNum(pNtk) == Abc_NtkPoNum(pNtkNew) );
- assert( Abc_NtkLatchNum(pNtk) == Abc_NtkLatchNum(pNtkNew) );
- assert( st_count(pNtk->tObj2Name) > 0 );
- assert( st_count(pNtkNew->tObj2Name) == 0 );
- // copy the CI/CO names if given
- Abc_NtkForEachPi( pNtk, pObj, i )
- Abc_NtkLogicStoreName( Abc_NtkPi(pNtkNew,i), Abc_ObjName(pObj) );
- Abc_NtkForEachPo( pNtk, pObj, i )
- Abc_NtkLogicStoreName( Abc_NtkPo(pNtkNew,i), Abc_ObjName(pObj) );
- Abc_NtkForEachLatch( pNtk, pObj, i )
- Abc_NtkLogicStoreName( Abc_NtkLatch(pNtkNew,i), Abc_ObjName(pObj) );
+ assert( Abc_NtkAssertNum(pNtk) == Abc_NtkAssertNum(pNtkNew) );
+ assert( Nm_ManNumEntries(pNtk->pManName) > 0 );
+ assert( Nm_ManNumEntries(pNtkNew->pManName) == 0 );
+ // copy the CI/CO/box name and skip latches and theirs inputs/outputs
+ Abc_NtkForEachCi( pNtk, pObj, i )
+ if ( Abc_ObjFaninNum(pObj) == 0 || !Abc_ObjIsLatch(Abc_ObjFanin0(pObj)) )
+ Abc_ObjAssignName( pObj->pCopy, Abc_ObjName(Abc_ObjFanout0Ntk(pObj)), NULL );
+ Abc_NtkForEachCo( pNtk, pObj, i )
+ if ( Abc_ObjFanoutNum(pObj) == 0 || !Abc_ObjIsLatch(Abc_ObjFanout0(pObj)) )
+ Abc_ObjAssignName( pObj->pCopy, Abc_ObjName(Abc_ObjFanin0Ntk(pObj)), NULL );
+ Abc_NtkForEachBox( pNtk, pObj, i )
+ if ( !Abc_ObjIsLatch(pObj) )
+ Abc_ObjAssignName( pObj->pCopy, Abc_ObjName(pObj), NULL );
}
/**Function*************************************************************
@@ -287,7 +184,7 @@ Vec_Ptr_t * Abc_NodeGetFaninNames( Abc_Obj_t * pNode )
int i;
vNodes = Vec_PtrAlloc( 100 );
Abc_ObjForEachFanin( pNode, pFanin, i )
- Vec_PtrPush( vNodes, util_strsav(Abc_ObjName(pFanin)) );
+ Vec_PtrPush( vNodes, Extra_UtilStrsav(Abc_ObjName(pFanin)) );
return vNodes;
}
@@ -322,7 +219,7 @@ Vec_Ptr_t * Abc_NodeGetFakeNames( int nNames )
Buffer[1] = '0' + i/26;
Buffer[2] = 0;
}
- Vec_PtrPush( vNames, util_strsav(Buffer) );
+ Vec_PtrPush( vNames, Extra_UtilStrsav(Buffer) );
}
return vNames;
}
@@ -415,42 +312,38 @@ void Abc_NtkOrderObjsByName( Abc_Ntk_t * pNtk, int fComb )
{
Abc_Obj_t * pObj;
int i;
+ assert( Abc_NtkAssertNum(pNtk) == 0 );
+ assert( Abc_NtkHasOnlyLatchBoxes(pNtk) );
// temporarily store the names in the copy field
Abc_NtkForEachPi( pNtk, pObj, i )
pObj->pCopy = (Abc_Obj_t *)Abc_ObjName(pObj);
Abc_NtkForEachPo( pNtk, pObj, i )
pObj->pCopy = (Abc_Obj_t *)Abc_ObjName(pObj);
- Abc_NtkForEachLatch( pNtk, pObj, i )
- pObj->pCopy = (Abc_Obj_t *)Abc_ObjName(pObj);
+ Abc_NtkForEachBox( pNtk, pObj, i )
+ pObj->pCopy = (Abc_Obj_t *)Abc_ObjName(Abc_ObjFanout0(pObj));
// order objects alphabetically
- qsort( pNtk->vCis->pArray, pNtk->nPis, sizeof(Abc_Obj_t *),
+ qsort( (void *)Vec_PtrArray(pNtk->vPis), Vec_PtrSize(pNtk->vPis), sizeof(Abc_Obj_t *),
(int (*)(const void *, const void *)) Abc_NodeCompareNames );
- qsort( pNtk->vCos->pArray, pNtk->nPos, sizeof(Abc_Obj_t *),
+ qsort( (void *)Vec_PtrArray(pNtk->vPos), Vec_PtrSize(pNtk->vPos), sizeof(Abc_Obj_t *),
(int (*)(const void *, const void *)) Abc_NodeCompareNames );
// if the comparison if combinational (latches as PIs/POs), order them too
if ( fComb )
- {
- qsort( pNtk->vLats->pArray, pNtk->nLatches, sizeof(Abc_Obj_t *),
+ qsort( (void *)Vec_PtrArray(pNtk->vBoxes), Vec_PtrSize(pNtk->vBoxes), sizeof(Abc_Obj_t *),
(int (*)(const void *, const void *)) Abc_NodeCompareNames );
- // add latches to make COs
- Abc_NtkForEachLatch( pNtk, pObj, i )
- {
- Vec_PtrWriteEntry( pNtk->vCis, pNtk->nPis + i, pObj );
- Vec_PtrWriteEntry( pNtk->vCos, pNtk->nPos + i, pObj );
- }
- }
+ // order CIs/COs first PIs/POs(Asserts) then latches
+ Abc_NtkOrderCisCos( pNtk );
// clean the copy fields
Abc_NtkForEachPi( pNtk, pObj, i )
pObj->pCopy = NULL;
Abc_NtkForEachPo( pNtk, pObj, i )
pObj->pCopy = NULL;
- Abc_NtkForEachLatch( pNtk, pObj, i )
+ Abc_NtkForEachBox( pNtk, pObj, i )
pObj->pCopy = NULL;
}
/**Function*************************************************************
- Synopsis []
+ Synopsis [Adds dummy names.]
Description []
@@ -459,41 +352,112 @@ void Abc_NtkOrderObjsByName( Abc_Ntk_t * pNtk, int fComb )
SeeAlso []
***********************************************************************/
-void Abc_NtkShortNames( Abc_Ntk_t * pNtk )
+void Abc_NtkAddDummyPiNames( Abc_Ntk_t * pNtk )
{
- stmm_table * tObj2NameNew;
Abc_Obj_t * pObj;
- char Buffer[100];
- char * pNameNew;
- int Length, i;
-
- tObj2NameNew = stmm_init_table(stmm_ptrcmp, stmm_ptrhash);
- // create new names and add them to the table
- Length = Extra_Base10Log( Abc_NtkPiNum(pNtk) );
+ int nDigits, i;
+ nDigits = Extra_Base10Log( Abc_NtkPiNum(pNtk) );
Abc_NtkForEachPi( pNtk, pObj, i )
- {
- sprintf( Buffer, "pi%0*d", Length, i );
- pNameNew = Abc_NtkRegisterName( pNtk, Buffer );
- stmm_insert( tObj2NameNew, (char *)pObj, pNameNew );
- }
- // create new names and add them to the table
- Length = Extra_Base10Log( Abc_NtkPoNum(pNtk) );
+ Abc_ObjAssignName( pObj, Abc_ObjNameDummy("pi", i, nDigits), NULL );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Adds dummy names.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Abc_NtkAddDummyPoNames( Abc_Ntk_t * pNtk )
+{
+ Abc_Obj_t * pObj;
+ int nDigits, i;
+ nDigits = Extra_Base10Log( Abc_NtkPoNum(pNtk) );
Abc_NtkForEachPo( pNtk, pObj, i )
+ Abc_ObjAssignName( pObj, Abc_ObjNameDummy("po", i, nDigits), NULL );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Adds dummy names.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Abc_NtkAddDummyAssertNames( Abc_Ntk_t * pNtk )
+{
+ Abc_Obj_t * pObj;
+ int nDigits, i;
+ nDigits = Extra_Base10Log( Abc_NtkAssertNum(pNtk) );
+ Abc_NtkForEachAssert( pNtk, pObj, i )
+ Abc_ObjAssignName( pObj, Abc_ObjNameDummy("a", i, nDigits), NULL );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Adds dummy names.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Abc_NtkAddDummyBoxNames( Abc_Ntk_t * pNtk )
+{
+ Abc_Obj_t * pObj;
+ int nDigits, i;
+ assert( !Abc_NtkIsNetlist(pNtk) );
+ nDigits = Extra_Base10Log( Abc_NtkLatchNum(pNtk) );
+ Abc_NtkForEachLatch( pNtk, pObj, i )
{
- sprintf( Buffer, "po%0*d", Length, i );
- pNameNew = Abc_NtkRegisterName( pNtk, Buffer );
- stmm_insert( tObj2NameNew, (char *)pObj, pNameNew );
+ Abc_ObjAssignName( pObj, Abc_ObjNameDummy("l", i, nDigits), NULL );
+ Abc_ObjAssignName( Abc_ObjFanin0(pObj), Abc_ObjNameDummy("li", i, nDigits), NULL );
+ Abc_ObjAssignName( Abc_ObjFanout0(pObj), Abc_ObjNameDummy("lo", i, nDigits), NULL );
}
- // create new names and add them to the table
- Length = Extra_Base10Log( Abc_NtkLatchNum(pNtk) );
- Abc_NtkForEachLatch( pNtk, pObj, i )
+/*
+ nDigits = Extra_Base10Log( Abc_NtkBlackboxNum(pNtk) );
+ Abc_NtkForEachBlackbox( pNtk, pObj, i )
{
- sprintf( Buffer, "lat%0*d", Length, i );
- pNameNew = Abc_NtkRegisterName( pNtk, Buffer );
- stmm_insert( tObj2NameNew, (char *)pObj, pNameNew );
+ pName = Abc_ObjAssignName( pObj, Abc_ObjNameDummy("B", i, nDigits), NULL );
+ nDigitsF = Extra_Base10Log( Abc_ObjFaninNum(pObj) );
+ Abc_ObjForEachFanin( pObj, pTerm, k )
+ Abc_ObjAssignName( Abc_ObjFanin0(pObj), pName, Abc_ObjNameDummy("i", k, nDigitsF) );
+ nDigitsF = Extra_Base10Log( Abc_ObjFanoutNum(pObj) );
+ Abc_ObjForEachFanout( pObj, pTerm, k )
+ Abc_ObjAssignName( Abc_ObjFanin0(pObj), pName, Abc_ObjNameDummy("o", k, nDigitsF) );
}
- stmm_free_table( pNtk->tObj2Name );
- pNtk->tObj2Name = tObj2NameNew;
+*/
+}
+
+/**Function*************************************************************
+
+ Synopsis [Replaces names by short names.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Abc_NtkShortNames( Abc_Ntk_t * pNtk )
+{
+ Nm_ManFree( pNtk->pManName );
+ pNtk->pManName = Nm_ManCreate( Abc_NtkCiNum(pNtk) + Abc_NtkCoNum(pNtk) + Abc_NtkBoxNum(pNtk) );
+ Abc_NtkAddDummyPiNames( pNtk );
+ Abc_NtkAddDummyPoNames( pNtk );
+ Abc_NtkAddDummyAssertNames( pNtk );
+ Abc_NtkAddDummyBoxNames( pNtk );
}
////////////////////////////////////////////////////////////////////////
diff --git a/src/base/abc/abcNetlist.c b/src/base/abc/abcNetlist.c
index 08ee93bb..26b88c68 100644
--- a/src/base/abc/abcNetlist.c
+++ b/src/base/abc/abcNetlist.c
@@ -19,13 +19,19 @@
***********************************************************************/
#include "abc.h"
+//#include "seq.h"
////////////////////////////////////////////////////////////////////////
/// DECLARATIONS ///
////////////////////////////////////////////////////////////////////////
-
+
+static void Abc_NtkAddPoBuffers( Abc_Ntk_t * pNtk );
+static Abc_Ntk_t * Abc_NtkLogicToNetlist( Abc_Ntk_t * pNtk );
+static Abc_Ntk_t * Abc_NtkAigToLogicSop( Abc_Ntk_t * pNtk );
+static Abc_Ntk_t * Abc_NtkAigToLogicSopBench( Abc_Ntk_t * pNtk );
+
////////////////////////////////////////////////////////////////////////
-/// FUNCTION DEFITIONS ///
+/// FUNCTION DEFINITIONS ///
////////////////////////////////////////////////////////////////////////
/**Function*************************************************************
@@ -39,33 +45,37 @@
SeeAlso []
***********************************************************************/
-Abc_Ntk_t * Abc_NtkNetlistToLogic( Abc_Ntk_t * pNtk )
+Abc_Ntk_t * Abc_NtkToLogic( Abc_Ntk_t * pNtk )
{
Abc_Ntk_t * pNtkNew;
Abc_Obj_t * pObj, * pFanin;
int i, k;
+ // consider the case of the AIG
+ if ( Abc_NtkIsStrash(pNtk) )
+ return Abc_NtkAigToLogicSop( pNtk );
assert( Abc_NtkIsNetlist(pNtk) );
+ // consider simple case when there is hierarchy
+// assert( pNtk->pDesign == NULL );
+ assert( Abc_NtkWhiteboxNum(pNtk) == 0 );
+ assert( Abc_NtkBlackboxNum(pNtk) == 0 );
// start the network
- if ( !Abc_NtkHasMapping(pNtk) )
- pNtkNew = Abc_NtkStartFrom( pNtk, ABC_TYPE_LOGIC, ABC_FUNC_SOP );
- else
- pNtkNew = Abc_NtkStartFrom( pNtk, ABC_TYPE_LOGIC, ABC_FUNC_MAP );
+ pNtkNew = Abc_NtkStartFrom( pNtk, ABC_NTK_LOGIC, pNtk->ntkFunc );
// duplicate the nodes
Abc_NtkForEachNode( pNtk, pObj, i )
- Abc_NtkDupObj(pNtkNew, pObj);
+ Abc_NtkDupObj(pNtkNew, pObj, 0);
// reconnect the internal nodes in the new network
Abc_NtkForEachNode( pNtk, pObj, i )
Abc_ObjForEachFanin( pObj, pFanin, k )
Abc_ObjAddFanin( pObj->pCopy, Abc_ObjFanin0(pFanin)->pCopy );
// collect the CO nodes
Abc_NtkFinalize( pNtk, pNtkNew );
- // fix the problem with CO pointing directing to CIs
+ // fix the problem with CO pointing directly to CIs
Abc_NtkLogicMakeSimpleCos( pNtkNew, 0 );
// duplicate EXDC
if ( pNtk->pExdc )
- pNtkNew->pExdc = Abc_NtkNetlistToLogic( pNtk->pExdc );
+ pNtkNew->pExdc = Abc_NtkToLogic( pNtk->pExdc );
if ( !Abc_NtkCheck( pNtkNew ) )
- fprintf( stdout, "Abc_NtkNetlistToLogic(): Network check has failed.\n" );
+ fprintf( stdout, "Abc_NtkToLogic(): Network check has failed.\n" );
return pNtkNew;
}
@@ -80,31 +90,18 @@ Abc_Ntk_t * Abc_NtkNetlistToLogic( Abc_Ntk_t * pNtk )
SeeAlso []
***********************************************************************/
-Abc_Ntk_t * Abc_NtkLogicToNetlist( Abc_Ntk_t * pNtk )
+Abc_Ntk_t * Abc_NtkToNetlist( Abc_Ntk_t * pNtk )
{
Abc_Ntk_t * pNtkNew, * pNtkTemp;
- assert( Abc_NtkIsLogic(pNtk) || Abc_NtkIsStrash(pNtk) || Abc_NtkIsSeq(pNtk) );
+ assert( Abc_NtkIsLogic(pNtk) || Abc_NtkIsStrash(pNtk) );
if ( Abc_NtkIsStrash(pNtk) )
{
pNtkTemp = Abc_NtkAigToLogicSop(pNtk);
- pNtkNew = Abc_NtkLogicSopToNetlist( pNtkTemp );
- Abc_NtkDelete( pNtkTemp );
- }
- else if ( Abc_NtkIsSeq(pNtk) )
- {
- pNtkTemp = Abc_NtkSeqToLogicSop(pNtk);
- pNtkNew = Abc_NtkLogicSopToNetlist( pNtkTemp );
+ pNtkNew = Abc_NtkLogicToNetlist( pNtkTemp );
Abc_NtkDelete( pNtkTemp );
+ return pNtkNew;
}
- else if ( Abc_NtkIsBddLogic(pNtk) )
- {
- Abc_NtkBddToSop(pNtk);
- pNtkNew = Abc_NtkLogicSopToNetlist( pNtk );
- Abc_NtkSopToBdd(pNtk);
- }
- else
- pNtkNew = Abc_NtkLogicSopToNetlist( pNtk );
- return pNtkNew;
+ return Abc_NtkLogicToNetlist( pNtk );
}
/**Function*************************************************************
@@ -118,12 +115,12 @@ Abc_Ntk_t * Abc_NtkLogicToNetlist( Abc_Ntk_t * pNtk )
SeeAlso []
***********************************************************************/
-Abc_Ntk_t * Abc_NtkLogicToNetlistBench( Abc_Ntk_t * pNtk )
+Abc_Ntk_t * Abc_NtkToNetlistBench( Abc_Ntk_t * pNtk )
{
Abc_Ntk_t * pNtkNew, * pNtkTemp;
assert( Abc_NtkIsStrash(pNtk) );
pNtkTemp = Abc_NtkAigToLogicSopBench( pNtk );
- pNtkNew = Abc_NtkLogicSopToNetlist( pNtkTemp );
+ pNtkNew = Abc_NtkLogicToNetlist( pNtkTemp );
Abc_NtkDelete( pNtkTemp );
return pNtkNew;
}
@@ -143,24 +140,31 @@ Abc_Ntk_t * Abc_NtkLogicToNetlistBench( Abc_Ntk_t * pNtk )
SeeAlso []
***********************************************************************/
-Abc_Ntk_t * Abc_NtkLogicSopToNetlist( Abc_Ntk_t * pNtk )
+Abc_Ntk_t * Abc_NtkLogicToNetlist( Abc_Ntk_t * pNtk )
{
Abc_Ntk_t * pNtkNew;
Abc_Obj_t * pObj, * pNet, * pDriver, * pFanin;
- char * pNameCo;
int i, k;
assert( Abc_NtkIsLogic(pNtk) );
- assert( Abc_NtkLogicHasSimpleCos(pNtk) );
- if ( Abc_NtkIsBddLogic(pNtk) )
- Abc_NtkBddToSop(pNtk);
+ // remove dangling nodes
+ Abc_NtkCleanup( pNtk, 0 );
+
+ // make sure the CO names are unique
+ Abc_NtkCheckUniqueCiNames( pNtk );
+ Abc_NtkCheckUniqueCoNames( pNtk );
+ Abc_NtkCheckUniqueCioNames( pNtk );
+
+// assert( Abc_NtkLogicHasSimpleCos(pNtk) );
+ if ( !Abc_NtkLogicHasSimpleCos(pNtk) )
+ {
+ printf( "Abc_NtkLogicToNetlist() warning: The network is converted to have simple COs.\n" );
+ Abc_NtkLogicMakeSimpleCos( pNtk, 0 );
+ }
// start the netlist by creating PI/PO/Latch objects
- if ( Abc_NtkIsSopLogic(pNtk) )
- pNtkNew = Abc_NtkStartFrom( pNtk, ABC_TYPE_NETLIST, ABC_FUNC_SOP );
- else
- pNtkNew = Abc_NtkStartFrom( pNtk, ABC_TYPE_NETLIST, ABC_FUNC_BDD );
+ pNtkNew = Abc_NtkStartFrom( pNtk, ABC_NTK_NETLIST, pNtk->ntkFunc );
// create the CI nets and remember them in the new CI nodes
Abc_NtkForEachCi( pNtk, pObj, i )
{
@@ -170,7 +174,7 @@ Abc_Ntk_t * Abc_NtkLogicSopToNetlist( Abc_Ntk_t * pNtk )
}
// duplicate all nodes
Abc_NtkForEachNode( pNtk, pObj, i )
- Abc_NtkDupObj(pNtkNew, pObj);
+ Abc_NtkDupObj(pNtkNew, pObj, 0);
// first add the nets to the CO drivers
Abc_NtkForEachCo( pNtk, pObj, i )
{
@@ -182,18 +186,21 @@ Abc_Ntk_t * Abc_NtkLogicSopToNetlist( Abc_Ntk_t * pNtk )
continue;
}
assert( Abc_ObjIsNode(pDriver) );
- // the driver is a node
-
- // get the CO name
- pNameCo = Abc_ObjIsPo(pObj)? Abc_ObjName(pObj) : Abc_ObjNameSuffix( pObj, "_in" );
- // make sure CO has a unique name
- assert( Abc_NtkFindNet( pNtkNew, pNameCo ) == NULL );
- // create the CO net and connect it to CO
- pNet = Abc_NtkFindOrCreateNet( pNtkNew, pNameCo );
- Abc_ObjAddFanin( pObj->pCopy, pNet );
- // connect the CO net to the new driver and remember it in the new driver
- Abc_ObjAddFanin( pNet, pDriver->pCopy );
- pDriver->pCopy->pCopy = pNet;
+ // if the CO driver has no net, create it
+ if ( pDriver->pCopy->pCopy == NULL )
+ {
+ // create the CO net and connect it to CO
+ pNet = Abc_NtkFindOrCreateNet( pNtkNew, Abc_ObjName(pObj) );
+ Abc_ObjAddFanin( pObj->pCopy, pNet );
+ // connect the CO net to the new driver and remember it in the new driver
+ Abc_ObjAddFanin( pNet, pDriver->pCopy );
+ pDriver->pCopy->pCopy = pNet;
+ }
+ else
+ {
+ assert( !strcmp( Abc_ObjName(pDriver->pCopy->pCopy), Abc_ObjName(pObj) ) );
+ Abc_ObjAddFanin( pObj->pCopy, pDriver->pCopy->pCopy );
+ }
}
// create the missing nets
Abc_NtkForEachNode( pNtk, pObj, i )
@@ -201,7 +208,7 @@ Abc_Ntk_t * Abc_NtkLogicSopToNetlist( Abc_Ntk_t * pNtk )
if ( pObj->pCopy->pCopy ) // the net of the new object is already created
continue;
// create the new net
- pNet = Abc_NtkFindOrCreateNet( pNtkNew, Abc_ObjName(pObj) );
+ pNet = Abc_NtkFindOrCreateNet( pNtkNew, Abc_ObjName(pObj) ); // here we create ridiculous names net line "n48", where 48 is the ID of the node
Abc_ObjAddFanin( pNet, pObj->pCopy );
pObj->pCopy->pCopy = pNet;
}
@@ -211,9 +218,9 @@ Abc_Ntk_t * Abc_NtkLogicSopToNetlist( Abc_Ntk_t * pNtk )
Abc_ObjAddFanin( pObj->pCopy, pFanin->pCopy->pCopy );
// duplicate EXDC
if ( pNtk->pExdc )
- pNtkNew->pExdc = Abc_NtkLogicToNetlist( pNtk->pExdc );
+ pNtkNew->pExdc = Abc_NtkToNetlist( pNtk->pExdc );
if ( !Abc_NtkCheck( pNtkNew ) )
- fprintf( stdout, "Abc_NtkLogicSopToNetlist(): Network check has failed.\n" );
+ fprintf( stdout, "Abc_NtkLogicToNetlist(): Network check has failed.\n" );
return pNtkNew;
}
@@ -232,40 +239,40 @@ Abc_Ntk_t * Abc_NtkAigToLogicSop( Abc_Ntk_t * pNtk )
{
Abc_Ntk_t * pNtkNew;
Abc_Obj_t * pObj, * pFanin, * pNodeNew;
+ Vec_Int_t * vInts;
int i, k;
assert( Abc_NtkIsStrash(pNtk) );
// start the network
- pNtkNew = Abc_NtkStartFrom( pNtk, ABC_TYPE_LOGIC, ABC_FUNC_SOP );
- // create the constant node
- Abc_NtkDupConst1( pNtk, pNtkNew );
+ pNtkNew = Abc_NtkStartFrom( pNtk, ABC_NTK_LOGIC, ABC_FUNC_SOP );
+ // if the constant node is used, duplicate it
+ pObj = Abc_AigConst1(pNtk);
+ if ( Abc_ObjFanoutNum(pObj) > 0 )
+ pObj->pCopy = Abc_NtkCreateNodeConst1(pNtkNew);
// duplicate the nodes and create node functions
Abc_NtkForEachNode( pNtk, pObj, i )
{
- if ( Abc_NodeIsConst(pObj) )
- continue;
- Abc_NtkDupObj(pNtkNew, pObj);
+ Abc_NtkDupObj(pNtkNew, pObj, 0);
pObj->pCopy->pData = Abc_SopCreateAnd2( pNtkNew->pManFunc, Abc_ObjFaninC0(pObj), Abc_ObjFaninC1(pObj) );
}
// create the choice nodes
Abc_NtkForEachNode( pNtk, pObj, i )
{
- if ( Abc_NodeIsConst(pObj) )
- continue;
- if ( !Abc_NodeIsAigChoice(pObj) )
+ if ( !Abc_AigNodeIsChoice(pObj) )
continue;
// create an OR gate
pNodeNew = Abc_NtkCreateNode(pNtkNew);
// add fanins
- Vec_IntClear( pNtk->vIntTemp );
+ vInts = Vec_IntAlloc( 10 );
for ( pFanin = pObj; pFanin; pFanin = pFanin->pData )
{
- Vec_IntPush( pNtk->vIntTemp, (int)(pObj->fPhase != pFanin->fPhase) );
+ Vec_IntPush( vInts, (int)(pObj->fPhase != pFanin->fPhase) );
Abc_ObjAddFanin( pNodeNew, pFanin->pCopy );
}
// create the logic function
- pNodeNew->pData = Abc_SopCreateOrMultiCube( pNtkNew->pManFunc, pNtk->vIntTemp->nSize, pNtk->vIntTemp->pArray );
+ pNodeNew->pData = Abc_SopCreateOrMultiCube( pNtkNew->pManFunc, Vec_IntSize(vInts), Vec_IntArray(vInts) );
// set the new node
pObj->pCopy->pCopy = pNodeNew;
+ Vec_IntFree( vInts );
}
// connect the internal nodes
Abc_NtkForEachNode( pNtk, pObj, i )
@@ -275,7 +282,17 @@ Abc_Ntk_t * Abc_NtkAigToLogicSop( Abc_Ntk_t * pNtk )
else
Abc_ObjAddFanin( pObj->pCopy, pFanin->pCopy );
// connect the COs
- Abc_NtkFinalize( pNtk, pNtkNew );
+// Abc_NtkFinalize( pNtk, pNtkNew );
+ Abc_NtkForEachCo( pNtk, pObj, i )
+ {
+ pFanin = Abc_ObjFanin0(pObj);
+ if ( pFanin->pCopy->pCopy )
+ pNodeNew = Abc_ObjNotCond(pFanin->pCopy->pCopy, Abc_ObjFaninC0(pObj));
+ else
+ pNodeNew = Abc_ObjNotCond(pFanin->pCopy, Abc_ObjFaninC0(pObj));
+ Abc_ObjAddFanin( pObj->pCopy, pNodeNew );
+ }
+
// fix the problem with complemented and duplicated CO edges
Abc_NtkLogicMakeSimpleCos( pNtkNew, 0 );
// duplicate the EXDC Ntk
@@ -312,25 +329,26 @@ Abc_Ntk_t * Abc_NtkAigToLogicSopBench( Abc_Ntk_t * pNtk )
if ( Abc_NtkGetChoiceNum(pNtk) )
printf( "Warning: Choice nodes are skipped.\n" );
// start the network
- pNtkNew = Abc_NtkStartFrom( pNtk, ABC_TYPE_LOGIC, ABC_FUNC_SOP );
- // create the constant node
- Abc_NtkDupConst1( pNtk, pNtkNew );
+ pNtkNew = Abc_NtkStartFrom( pNtk, ABC_NTK_LOGIC, ABC_FUNC_SOP );
// collect the nodes to be used (marks all nodes with current TravId)
vNodes = Abc_NtkDfs( pNtk, 0 );
// create inverters for the CI and remember them
+ pObj = Abc_AigConst1(pNtk);
+ if ( Abc_AigNodeHasComplFanoutEdgeTrav(pObj) )
+ {
+ pObj->pCopy = Abc_NtkCreateNodeConst1(pNtkNew);
+ pObj->pCopy->pCopy = Abc_NtkCreateNodeInv( pNtkNew, pObj->pCopy );
+ }
Abc_NtkForEachCi( pNtk, pObj, i )
if ( Abc_AigNodeHasComplFanoutEdgeTrav(pObj) )
- pObj->pCopy->pCopy = Abc_NodeCreateInv( pNtkNew, pObj->pCopy );
+ pObj->pCopy->pCopy = Abc_NtkCreateNodeInv( pNtkNew, pObj->pCopy );
// duplicate the nodes, create node functions, and inverters
Vec_PtrForEachEntry( vNodes, pObj, i )
{
- if ( !Abc_NodeIsConst(pObj) )
- {
- Abc_NtkDupObj( pNtkNew, pObj );
- pObj->pCopy->pData = Abc_SopCreateAnd( pNtkNew->pManFunc, 2 );
- }
+ Abc_NtkDupObj( pNtkNew, pObj, 0 );
+ pObj->pCopy->pData = Abc_SopCreateAnd( pNtkNew->pManFunc, 2, NULL );
if ( Abc_AigNodeHasComplFanoutEdgeTrav(pObj) )
- pObj->pCopy->pCopy = Abc_NodeCreateInv( pNtkNew, pObj->pCopy );
+ pObj->pCopy->pCopy = Abc_NtkCreateNodeInv( pNtkNew, pObj->pCopy );
}
// connect the objects
Vec_PtrForEachEntry( vNodes, pObj, i )
@@ -361,6 +379,31 @@ Abc_Ntk_t * Abc_NtkAigToLogicSopBench( Abc_Ntk_t * pNtk )
return pNtkNew;
}
+/**Function*************************************************************
+
+ Synopsis [Adds buffers for each PO.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Abc_NtkAddPoBuffers( Abc_Ntk_t * pNtk )
+{
+ Abc_Obj_t * pObj, * pFanin, * pFaninNew;
+ int i;
+ assert( Abc_NtkIsStrash(pNtk) );
+ Abc_NtkForEachPo( pNtk, pObj, i )
+ {
+ pFanin = Abc_ObjChild0(pObj);
+ pFaninNew = Abc_NtkCreateNode(pNtk);
+ Abc_ObjAddFanin( pFaninNew, pFanin );
+ Abc_ObjPatchFanin( pObj, pFanin, pFaninNew );
+ }
+}
+
////////////////////////////////////////////////////////////////////////
/// END OF FILE ///
////////////////////////////////////////////////////////////////////////
diff --git a/src/base/abc/abcNtk.c b/src/base/abc/abcNtk.c
index 5c199141..d78a3a6a 100644
--- a/src/base/abc/abcNtk.c
+++ b/src/base/abc/abcNtk.c
@@ -19,6 +19,7 @@
***********************************************************************/
#include "abc.h"
+#include "abcInt.h"
#include "main.h"
#include "mio.h"
@@ -26,10 +27,8 @@
/// DECLARATIONS ///
////////////////////////////////////////////////////////////////////////
-#define ABC_NUM_STEPS 10
-
////////////////////////////////////////////////////////////////////////
-/// FUNCTION DEFITIONS ///
+/// FUNCTION DEFINITIONS ///
////////////////////////////////////////////////////////////////////////
/**Function*************************************************************
@@ -43,7 +42,7 @@
SeeAlso []
***********************************************************************/
-Abc_Ntk_t * Abc_NtkAlloc( Abc_NtkType_t Type, Abc_NtkFunc_t Func )
+Abc_Ntk_t * Abc_NtkAlloc( Abc_NtkType_t Type, Abc_NtkFunc_t Func, int fUseMemMan )
{
Abc_Ntk_t * pNtk;
pNtk = ALLOC( Abc_Ntk_t, 1 );
@@ -52,32 +51,35 @@ Abc_Ntk_t * Abc_NtkAlloc( Abc_NtkType_t Type, Abc_NtkFunc_t Func )
pNtk->ntkFunc = Func;
// start the object storage
pNtk->vObjs = Vec_PtrAlloc( 100 );
- pNtk->vLats = Vec_PtrAlloc( 100 );
+ pNtk->vAsserts = Vec_PtrAlloc( 100 );
+ pNtk->vPios = Vec_PtrAlloc( 100 );
+ pNtk->vPis = Vec_PtrAlloc( 100 );
+ pNtk->vPos = Vec_PtrAlloc( 100 );
pNtk->vCis = Vec_PtrAlloc( 100 );
pNtk->vCos = Vec_PtrAlloc( 100 );
- pNtk->vPtrTemp = Vec_PtrAlloc( 100 );
- pNtk->vIntTemp = Vec_IntAlloc( 100 );
- pNtk->vStrTemp = Vec_StrAlloc( 100 );
- // start the hash table
- pNtk->tName2Net = stmm_init_table(strcmp, stmm_strhash);
- pNtk->tObj2Name = stmm_init_table(stmm_ptrcmp, stmm_ptrhash);
+ pNtk->vBoxes = Vec_PtrAlloc( 100 );
// start the memory managers
- pNtk->pMmNames = Extra_MmFlexStart();
- pNtk->pMmObj = Extra_MmFixedStart( sizeof(Abc_Obj_t) );
- pNtk->pMmStep = Extra_MmStepStart( ABC_NUM_STEPS );
+ pNtk->pMmObj = fUseMemMan? Extra_MmFixedStart( sizeof(Abc_Obj_t) ) : NULL;
+ pNtk->pMmStep = fUseMemMan? Extra_MmStepStart( ABC_NUM_STEPS ) : NULL;
// get ready to assign the first Obj ID
pNtk->nTravIds = 1;
// start the functionality manager
- if ( Abc_NtkHasSop(pNtk) )
+ if ( Abc_NtkIsStrash(pNtk) )
+ pNtk->pManFunc = Abc_AigAlloc( pNtk );
+ else if ( Abc_NtkHasSop(pNtk) || Abc_NtkHasBlifMv(pNtk) )
pNtk->pManFunc = Extra_MmFlexStart();
else if ( Abc_NtkHasBdd(pNtk) )
pNtk->pManFunc = Cudd_Init( 20, 0, CUDD_UNIQUE_SLOTS, CUDD_CACHE_SLOTS, 0 );
else if ( Abc_NtkHasAig(pNtk) )
- pNtk->pManFunc = Abc_AigAlloc( pNtk );
+ pNtk->pManFunc = Hop_ManStart();
else if ( Abc_NtkHasMapping(pNtk) )
- pNtk->pManFunc = Abc_FrameReadLibGen(Abc_FrameGetGlobalFrame());
- else
+ pNtk->pManFunc = Abc_FrameReadLibGen();
+ else if ( !Abc_NtkHasBlackbox(pNtk) )
assert( 0 );
+ // name manager
+ pNtk->pManName = Nm_ManCreate( 200 );
+ // attribute manager
+ pNtk->vAttrs = Vec_PtrStart( VEC_ATTR_TOTAL_NUM );
return pNtk;
}
@@ -95,38 +97,44 @@ Abc_Ntk_t * Abc_NtkAlloc( Abc_NtkType_t Type, Abc_NtkFunc_t Func )
Abc_Ntk_t * Abc_NtkStartFrom( Abc_Ntk_t * pNtk, Abc_NtkType_t Type, Abc_NtkFunc_t Func )
{
Abc_Ntk_t * pNtkNew;
- Abc_Obj_t * pObj, * pObjNew;
- int i;
+ Abc_Obj_t * pObj;
+ int fCopyNames, i;
if ( pNtk == NULL )
return NULL;
+ // decide whether to copy the names
+ fCopyNames = ( Type != ABC_NTK_NETLIST );
// start the network
- pNtkNew = Abc_NtkAlloc( Type, Func );
+ pNtkNew = Abc_NtkAlloc( Type, Func, 1 );
// duplicate the name and the spec
- pNtkNew->pName = util_strsav(pNtk->pName);
- pNtkNew->pSpec = util_strsav(pNtk->pSpec);
- // clone the PIs/POs/latches
+ pNtkNew->pName = Extra_UtilStrsav(pNtk->pName);
+ pNtkNew->pSpec = Extra_UtilStrsav(pNtk->pSpec);
+ // clean the node copy fields
+ Abc_NtkCleanCopy( pNtk );
+ // map the constant nodes
+ if ( Abc_NtkIsStrash(pNtk) && Abc_NtkIsStrash(pNtkNew) )
+ Abc_AigConst1(pNtk)->pCopy = Abc_AigConst1(pNtkNew);
+ // clone CIs/CIs/boxes
Abc_NtkForEachPi( pNtk, pObj, i )
- Abc_NtkDupObj(pNtkNew, pObj);
+ Abc_NtkDupObj( pNtkNew, pObj, fCopyNames );
Abc_NtkForEachPo( pNtk, pObj, i )
- Abc_NtkDupObj(pNtkNew, pObj);
- Abc_NtkForEachLatch( pNtk, pObj, i )
- {
- pObjNew = Abc_NtkDupObj(pNtkNew, pObj);
- Vec_PtrPush( pNtkNew->vCis, pObjNew );
- Vec_PtrPush( pNtkNew->vCos, pObjNew );
- }
- // clean the node copy fields
- Abc_NtkForEachNode( pNtk, pObj, i )
- pObj->pCopy = NULL;
+ Abc_NtkDupObj( pNtkNew, pObj, fCopyNames );
+ Abc_NtkForEachAssert( pNtk, pObj, i )
+ Abc_NtkDupObj( pNtkNew, pObj, fCopyNames );
+ Abc_NtkForEachBox( pNtk, pObj, i )
+ Abc_NtkDupBox( pNtkNew, pObj, fCopyNames );
// transfer the names
- Abc_NtkDupCioNamesTable( pNtk, pNtkNew );
+// Abc_NtkTrasferNames( pNtk, pNtkNew );
Abc_ManTimeDup( pNtk, pNtkNew );
+ // check that the CI/CO/latches are copied correctly
+ assert( Abc_NtkCiNum(pNtk) == Abc_NtkCiNum(pNtkNew) );
+ assert( Abc_NtkCoNum(pNtk) == Abc_NtkCoNum(pNtkNew) );
+ assert( Abc_NtkLatchNum(pNtk) == Abc_NtkLatchNum(pNtkNew) );
return pNtkNew;
}
/**Function*************************************************************
- Synopsis [Finalizes the network using the existing network as a model.]
+ Synopsis [Starts a new network using existing network as a model.]
Description []
@@ -135,17 +143,44 @@ Abc_Ntk_t * Abc_NtkStartFrom( Abc_Ntk_t * pNtk, Abc_NtkType_t Type, Abc_NtkFunc_
SeeAlso []
***********************************************************************/
-void Abc_NtkFinalize( Abc_Ntk_t * pNtk, Abc_Ntk_t * pNtkNew )
+Abc_Ntk_t * Abc_NtkStartFromNoLatches( Abc_Ntk_t * pNtk, Abc_NtkType_t Type, Abc_NtkFunc_t Func )
{
- Abc_Obj_t * pObj, * pDriver, * pDriverNew;
+ Abc_Ntk_t * pNtkNew;
+ Abc_Obj_t * pObj;
int i;
- // set the COs of the strashed network
- Abc_NtkForEachCo( pNtk, pObj, i )
+ if ( pNtk == NULL )
+ return NULL;
+ assert( Type != ABC_NTK_NETLIST );
+ // start the network
+ pNtkNew = Abc_NtkAlloc( Type, Func, 1 );
+ // duplicate the name and the spec
+ pNtkNew->pName = Extra_UtilStrsav(pNtk->pName);
+ pNtkNew->pSpec = Extra_UtilStrsav(pNtk->pSpec);
+ // clean the node copy fields
+ Abc_NtkCleanCopy( pNtk );
+ // map the constant nodes
+ if ( Abc_NtkIsStrash(pNtk) && Abc_NtkIsStrash(pNtkNew) )
+ Abc_AigConst1(pNtk)->pCopy = Abc_AigConst1(pNtkNew);
+ // clone CIs/CIs/boxes
+ Abc_NtkForEachPi( pNtk, pObj, i )
+ Abc_NtkDupObj( pNtkNew, pObj, 1 );
+ Abc_NtkForEachPo( pNtk, pObj, i )
+ Abc_NtkDupObj( pNtkNew, pObj, 1 );
+ Abc_NtkForEachAssert( pNtk, pObj, i )
+ Abc_NtkDupObj( pNtkNew, pObj, 1 );
+ Abc_NtkForEachBox( pNtk, pObj, i )
{
- pDriver = Abc_ObjFanin0Ntk( Abc_ObjFanin0(pObj) );
- pDriverNew = Abc_ObjNotCond(pDriver->pCopy, Abc_ObjFaninC0(pObj));
- Abc_ObjAddFanin( pObj->pCopy, pDriverNew );
+ if ( Abc_ObjIsLatch(pObj) )
+ continue;
+ Abc_NtkDupBox(pNtkNew, pObj, 1);
}
+ // transfer the names
+// Abc_NtkTrasferNamesNoLatches( pNtk, pNtkNew );
+ Abc_ManTimeDup( pNtk, pNtkNew );
+ // check that the CI/CO/latches are copied correctly
+ assert( Abc_NtkPiNum(pNtk) == Abc_NtkPiNum(pNtkNew) );
+ assert( Abc_NtkPoNum(pNtk) == Abc_NtkPoNum(pNtkNew) );
+ return pNtkNew;
}
/**Function*************************************************************
@@ -159,7 +194,7 @@ void Abc_NtkFinalize( Abc_Ntk_t * pNtk, Abc_Ntk_t * pNtkNew )
SeeAlso []
***********************************************************************/
-void Abc_NtkFinalizeRegular( Abc_Ntk_t * pNtk, Abc_Ntk_t * pNtkNew )
+void Abc_NtkFinalize( Abc_Ntk_t * pNtk, Abc_Ntk_t * pNtkNew )
{
Abc_Obj_t * pObj, * pDriver, * pDriverNew;
int i;
@@ -167,37 +202,13 @@ void Abc_NtkFinalizeRegular( Abc_Ntk_t * pNtk, Abc_Ntk_t * pNtkNew )
Abc_NtkForEachCo( pNtk, pObj, i )
{
pDriver = Abc_ObjFanin0Ntk( Abc_ObjFanin0(pObj) );
- pDriverNew = pDriver->pCopy;
+ pDriverNew = Abc_ObjNotCond(pDriver->pCopy, Abc_ObjFaninC0(pObj));
Abc_ObjAddFanin( pObj->pCopy, pDriverNew );
}
}
/**Function*************************************************************
- Synopsis [Finalizes the network adding latches to CI/CO lists and creates their names.]
-
- Description []
-
- SideEffects []
-
- SeeAlso []
-
-***********************************************************************/
-void Abc_NtkFinalizeLatches( Abc_Ntk_t * pNtk )
-{
- Abc_Obj_t * pLatch;
- int i;
- // set the COs of the strashed network
- Abc_NtkForEachLatch( pNtk, pLatch, i )
- {
- Vec_PtrPush( pNtk->vCis, pLatch );
- Vec_PtrPush( pNtk->vCos, pLatch );
- Abc_NtkLogicStoreName( pLatch, Abc_ObjNameSuffix(pLatch, "L") );
- }
-}
-
-/**Function*************************************************************
-
Synopsis [Starts a new network using existing network as a model.]
Description []
@@ -211,10 +222,15 @@ Abc_Ntk_t * Abc_NtkStartRead( char * pName )
{
Abc_Ntk_t * pNtkNew;
// allocate the empty network
- pNtkNew = Abc_NtkAlloc( ABC_TYPE_NETLIST, ABC_FUNC_SOP );
+ pNtkNew = Abc_NtkAlloc( ABC_NTK_NETLIST, ABC_FUNC_SOP, 1 );
// set the specs
- pNtkNew->pName = util_strsav( pName );
- pNtkNew->pSpec = util_strsav( pName );
+ pNtkNew->pName = Extra_FileNameGeneric(pName);
+ pNtkNew->pSpec = Extra_UtilStrsav(pName);
+ if ( pNtkNew->pName == NULL || strlen(pNtkNew->pName) == 0 )
+ {
+ FREE( pNtkNew->pName );
+ pNtkNew->pName = Extra_UtilStrsav("unknown");
+ }
return pNtkNew;
}
@@ -231,19 +247,50 @@ Abc_Ntk_t * Abc_NtkStartRead( char * pName )
***********************************************************************/
void Abc_NtkFinalizeRead( Abc_Ntk_t * pNtk )
{
- Abc_Obj_t * pLatch;
+ Abc_Obj_t * pBox, * pObj, * pTerm, * pNet;
int i;
+ if ( Abc_NtkHasBlackbox(pNtk) && Abc_NtkBoxNum(pNtk) == 0 )
+ {
+ pBox = Abc_NtkCreateBlackbox(pNtk);
+ Abc_NtkForEachPi( pNtk, pObj, i )
+ {
+ pTerm = Abc_NtkCreateBi(pNtk);
+ Abc_ObjAddFanin( pTerm, Abc_ObjFanout0(pObj) );
+ Abc_ObjAddFanin( pBox, pTerm );
+ }
+ Abc_NtkForEachPo( pNtk, pObj, i )
+ {
+ pTerm = Abc_NtkCreateBo(pNtk);
+ Abc_ObjAddFanin( pTerm, pBox );
+ Abc_ObjAddFanin( Abc_ObjFanin0(pObj), pTerm );
+ }
+ return;
+ }
assert( Abc_NtkIsNetlist(pNtk) );
- // fix the net drivers
- Abc_NtkFixNonDrivenNets( pNtk );
- // create the names table
- Abc_NtkCreateCioNamesTable( pNtk );
- // add latches to the CI/CO arrays
- Abc_NtkForEachLatch( pNtk, pLatch, i )
+
+ // check if constant 0 net is used
+ pNet = Abc_NtkFindNet( pNtk, "1\'b0" );
+ if ( pNet )
+ {
+ if ( Abc_ObjFanoutNum(pNet) == 0 )
+ Abc_NtkDeleteObj(pNet);
+ else if ( Abc_ObjFaninNum(pNet) == 0 )
+ Abc_ObjAddFanin( pNet, Abc_NtkCreateNodeConst0(pNtk) );
+ }
+ // check if constant 1 net is used
+ pNet = Abc_NtkFindNet( pNtk, "1\'b1" );
+ if ( pNet )
{
- Vec_PtrPush( pNtk->vCis, pLatch );
- Vec_PtrPush( pNtk->vCos, pLatch );
+ if ( Abc_ObjFanoutNum(pNet) == 0 )
+ Abc_NtkDeleteObj(pNet);
+ else if ( Abc_ObjFaninNum(pNet) == 0 )
+ Abc_ObjAddFanin( pNet, Abc_NtkCreateNodeConst1(pNtk) );
}
+ // fix the net drivers
+ Abc_NtkFixNonDrivenNets( pNtk );
+
+ // reorder the CI/COs to PI/POs first
+ Abc_NtkOrderCisCos( pNtk );
}
/**Function*************************************************************
@@ -267,30 +314,47 @@ Abc_Ntk_t * Abc_NtkDup( Abc_Ntk_t * pNtk )
// start the network
pNtkNew = Abc_NtkStartFrom( pNtk, pNtk->ntkType, pNtk->ntkFunc );
// copy the internal nodes
- if ( Abc_NtkHasAig(pNtk) )
- Abc_AigDup( pNtk->pManFunc, pNtkNew->pManFunc );
+ if ( Abc_NtkIsStrash(pNtk) )
+ {
+ // copy the AND gates
+ Abc_AigForEachAnd( pNtk, pObj, i )
+ pObj->pCopy = Abc_AigAnd( pNtkNew->pManFunc, Abc_ObjChild0Copy(pObj), Abc_ObjChild1Copy(pObj) );
+ // relink the choice nodes
+ Abc_AigForEachAnd( pNtk, pObj, i )
+ if ( pObj->pData )
+ pObj->pCopy->pData = ((Abc_Obj_t *)pObj->pData)->pCopy;
+ // relink the CO nodes
+ Abc_NtkForEachCo( pNtk, pObj, i )
+ Abc_ObjAddFanin( pObj->pCopy, Abc_ObjChild0Copy(pObj) );
+ // get the number of nodes before and after
+ if ( Abc_NtkNodeNum(pNtk) != Abc_NtkNodeNum(pNtkNew) )
+ printf( "Warning: Structural hashing during duplication reduced %d nodes (this is a minor bug).\n",
+ Abc_NtkNodeNum(pNtk) - Abc_NtkNodeNum(pNtkNew) );
+ }
else
{
// duplicate the nets and nodes (CIs/COs/latches already dupped)
Abc_NtkForEachObj( pNtk, pObj, i )
if ( pObj->pCopy == NULL )
- Abc_NtkDupObj(pNtkNew, pObj);
+ Abc_NtkDupObj(pNtkNew, pObj, 0);
// reconnect all objects (no need to transfer attributes on edges)
Abc_NtkForEachObj( pNtk, pObj, i )
- Abc_ObjForEachFanin( pObj, pFanin, k )
- Abc_ObjAddFanin( pObj->pCopy, pFanin->pCopy );
+ if ( !Abc_ObjIsBox(pObj) && !Abc_ObjIsBo(pObj) )
+ Abc_ObjForEachFanin( pObj, pFanin, k )
+ Abc_ObjAddFanin( pObj->pCopy, pFanin->pCopy );
}
// duplicate the EXDC Ntk
if ( pNtk->pExdc )
pNtkNew->pExdc = Abc_NtkDup( pNtk->pExdc );
if ( !Abc_NtkCheck( pNtkNew ) )
fprintf( stdout, "Abc_NtkDup(): Network check has failed.\n" );
+ pNtk->pCopy = pNtkNew;
return pNtkNew;
}
/**Function*************************************************************
- Synopsis [Creates the network composed of one output.]
+ Synopsis [Duplicate the network.]
Description []
@@ -299,24 +363,173 @@ Abc_Ntk_t * Abc_NtkDup( Abc_Ntk_t * pNtk )
SeeAlso []
***********************************************************************/
-Abc_Ntk_t * Abc_NtkSplitOutput( Abc_Ntk_t * pNtk, Abc_Obj_t * pNode, int fUseAllCis )
+Abc_Ntk_t * Abc_NtkDouble( Abc_Ntk_t * pNtk )
{
- Vec_Ptr_t * vNodes;
+ char Buffer[500];
Abc_Ntk_t * pNtkNew;
Abc_Obj_t * pObj, * pFanin;
+ int i, k;
+ assert( Abc_NtkIsLogic(pNtk) );
+
+ // start the network
+ pNtkNew = Abc_NtkAlloc( pNtk->ntkType, pNtk->ntkFunc, 1 );
+ sprintf( Buffer, "%s%s", pNtk->pName, "_2x" );
+ pNtkNew->pName = Extra_UtilStrsav(Buffer);
+
+ // clean the node copy fields
+ Abc_NtkCleanCopy( pNtk );
+ // clone CIs/CIs/boxes
+ Abc_NtkForEachPi( pNtk, pObj, i )
+ Abc_NtkDupObj( pNtkNew, pObj, 0 );
+ Abc_NtkForEachPo( pNtk, pObj, i )
+ Abc_NtkDupObj( pNtkNew, pObj, 0 );
+ Abc_NtkForEachAssert( pNtk, pObj, i )
+ Abc_NtkDupObj( pNtkNew, pObj, 0 );
+ Abc_NtkForEachBox( pNtk, pObj, i )
+ Abc_NtkDupBox( pNtkNew, pObj, 0 );
+ // copy the internal nodes
+ // duplicate the nets and nodes (CIs/COs/latches already dupped)
+ Abc_NtkForEachObj( pNtk, pObj, i )
+ if ( pObj->pCopy == NULL )
+ Abc_NtkDupObj(pNtkNew, pObj, 0);
+ // reconnect all objects (no need to transfer attributes on edges)
+ Abc_NtkForEachObj( pNtk, pObj, i )
+ if ( !Abc_ObjIsBox(pObj) && !Abc_ObjIsBo(pObj) )
+ Abc_ObjForEachFanin( pObj, pFanin, k )
+ Abc_ObjAddFanin( pObj->pCopy, pFanin->pCopy );
+
+ // clean the node copy fields
+ Abc_NtkCleanCopy( pNtk );
+ // clone CIs/CIs/boxes
+ Abc_NtkForEachPi( pNtk, pObj, i )
+ Abc_NtkDupObj( pNtkNew, pObj, 0 );
+ Abc_NtkForEachPo( pNtk, pObj, i )
+ Abc_NtkDupObj( pNtkNew, pObj, 0 );
+ Abc_NtkForEachAssert( pNtk, pObj, i )
+ Abc_NtkDupObj( pNtkNew, pObj, 0 );
+ Abc_NtkForEachBox( pNtk, pObj, i )
+ Abc_NtkDupBox( pNtkNew, pObj, 0 );
+ // copy the internal nodes
+ // duplicate the nets and nodes (CIs/COs/latches already dupped)
+ Abc_NtkForEachObj( pNtk, pObj, i )
+ if ( pObj->pCopy == NULL )
+ Abc_NtkDupObj(pNtkNew, pObj, 0);
+ // reconnect all objects (no need to transfer attributes on edges)
+ Abc_NtkForEachObj( pNtk, pObj, i )
+ if ( !Abc_ObjIsBox(pObj) && !Abc_ObjIsBo(pObj) )
+ Abc_ObjForEachFanin( pObj, pFanin, k )
+ Abc_ObjAddFanin( pObj->pCopy, pFanin->pCopy );
+
+ // assign names
+ Abc_NtkForEachCi( pNtk, pObj, i )
+ {
+ Abc_ObjAssignName( Abc_NtkCi(pNtkNew, i), "1_", Abc_ObjName(pObj) );
+ Abc_ObjAssignName( Abc_NtkCi(pNtkNew, Abc_NtkCiNum(pNtk) + i), "2_", Abc_ObjName(pObj) );
+ }
+ Abc_NtkForEachCo( pNtk, pObj, i )
+ {
+ Abc_ObjAssignName( Abc_NtkCo(pNtkNew, i), "1_", Abc_ObjName(pObj) );
+ Abc_ObjAssignName( Abc_NtkCo(pNtkNew, Abc_NtkCoNum(pNtk) + i), "2_", Abc_ObjName(pObj) );
+ }
+
+ // perform the final check
+ if ( !Abc_NtkCheck( pNtkNew ) )
+ fprintf( stdout, "Abc_NtkDup(): Network check has failed.\n" );
+ return pNtkNew;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Attaches the second network at the bottom of the first.]
+
+ Description [Returns the first network. Deletes the second network.]
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Abc_Ntk_t * Abc_NtkAttachBottom( Abc_Ntk_t * pNtkTop, Abc_Ntk_t * pNtkBottom )
+{
+ Abc_Obj_t * pObj, * pFanin, * pBuffer;
+ Vec_Ptr_t * vNodes;
+ int i, k;
+ assert( pNtkBottom != NULL );
+ if ( pNtkTop == NULL )
+ return pNtkBottom;
+ // make sure the networks are combinational
+ assert( Abc_NtkPiNum(pNtkTop) == Abc_NtkCiNum(pNtkTop) );
+ assert( Abc_NtkPiNum(pNtkBottom) == Abc_NtkCiNum(pNtkBottom) );
+ // make sure the POs of the bottom correspond to the PIs of the top
+ assert( Abc_NtkPoNum(pNtkBottom) == Abc_NtkPiNum(pNtkTop) );
+ assert( Abc_NtkPiNum(pNtkBottom) < Abc_NtkPiNum(pNtkTop) );
+ // add buffers for the PIs of the top - save results in the POs of the bottom
+ Abc_NtkForEachPi( pNtkTop, pObj, i )
+ {
+ pBuffer = Abc_NtkCreateNodeBuf( pNtkTop, NULL );
+ Abc_ObjTransferFanout( pObj, pBuffer );
+ Abc_NtkPo(pNtkBottom, i)->pCopy = pBuffer;
+ }
+ // remove useless PIs of the top
+ for ( i = Abc_NtkPiNum(pNtkTop) - 1; i >= Abc_NtkPiNum(pNtkBottom); i-- )
+ Abc_NtkDeleteObj( Abc_NtkPi(pNtkTop, i) );
+ assert( Abc_NtkPiNum(pNtkBottom) == Abc_NtkPiNum(pNtkTop) );
+ // copy the bottom network
+ Abc_NtkForEachPi( pNtkBottom, pObj, i )
+ Abc_NtkPi(pNtkBottom, i)->pCopy = Abc_NtkPi(pNtkTop, i);
+ // construct all nodes
+ vNodes = Abc_NtkDfs( pNtkBottom, 0 );
+ Vec_PtrForEachEntry( vNodes, pObj, i )
+ {
+ Abc_NtkDupObj(pNtkTop, pObj, 0);
+ Abc_ObjForEachFanin( pObj, pFanin, k )
+ Abc_ObjAddFanin( pObj->pCopy, pFanin->pCopy );
+ }
+ Vec_PtrFree( vNodes );
+ // connect the POs
+ Abc_NtkForEachPo( pNtkBottom, pObj, i )
+ Abc_ObjAddFanin( pObj->pCopy, Abc_ObjFanin0(pObj)->pCopy );
+ // delete old network
+ Abc_NtkDelete( pNtkBottom );
+ // return the network
+ if ( !Abc_NtkCheck( pNtkTop ) )
+ fprintf( stdout, "Abc_NtkAttachBottom(): Network check has failed.\n" );
+ return pNtkTop;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Creates the network composed of one logic cone.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Abc_Ntk_t * Abc_NtkCreateCone( Abc_Ntk_t * pNtk, Abc_Obj_t * pNode, char * pNodeName, int fUseAllCis )
+{
+ Abc_Ntk_t * pNtkNew;
+ Vec_Ptr_t * vNodes;
+ Abc_Obj_t * pObj, * pFanin, * pNodeCoNew;
char Buffer[1000];
int i, k;
assert( Abc_NtkIsLogic(pNtk) || Abc_NtkIsStrash(pNtk) );
- assert( Abc_ObjIsCo(pNode) );
+ assert( Abc_ObjIsNode(pNode) );
// start the network
- pNtkNew = Abc_NtkAlloc( pNtk->ntkType, pNtk->ntkFunc );
+ pNtkNew = Abc_NtkAlloc( pNtk->ntkType, pNtk->ntkFunc, 1 );
// set the name
- sprintf( Buffer, "%s_%s", pNtk->pName, Abc_ObjName(pNode) );
- pNtkNew->pName = util_strsav(Buffer);
+ sprintf( Buffer, "%s_%s", pNtk->pName, pNodeName );
+ pNtkNew->pName = Extra_UtilStrsav(Buffer);
- // collect the nodes in the TFI of the output
+ // establish connection between the constant nodes
+ if ( Abc_NtkIsStrash(pNtk) )
+ Abc_AigConst1(pNtk)->pCopy = Abc_AigConst1(pNtkNew);
+
+ // collect the nodes in the TFI of the output (mark the TFI)
vNodes = Abc_NtkDfsNodes( pNtk, &pNode, 1 );
// create the PIs
Abc_NtkForEachCi( pNtk, pObj, i )
@@ -324,12 +537,79 @@ Abc_Ntk_t * Abc_NtkSplitOutput( Abc_Ntk_t * pNtk, Abc_Obj_t * pNode, int fUseAll
if ( fUseAllCis || Abc_NodeIsTravIdCurrent(pObj) ) // TravId is set by DFS
{
pObj->pCopy = Abc_NtkCreatePi(pNtkNew);
- Abc_NtkLogicStoreName( pObj->pCopy, Abc_ObjName(pObj) );
+ Abc_ObjAssignName( pObj->pCopy, Abc_ObjName(pObj), NULL );
+ }
+ }
+ // add the PO corresponding to this output
+ pNodeCoNew = Abc_NtkCreatePo( pNtkNew );
+ Abc_ObjAssignName( pNodeCoNew, pNodeName, NULL );
+ // copy the nodes
+ Vec_PtrForEachEntry( vNodes, pObj, i )
+ {
+ // if it is an AIG, add to the hash table
+ if ( Abc_NtkIsStrash(pNtk) )
+ {
+ pObj->pCopy = Abc_AigAnd( pNtkNew->pManFunc, Abc_ObjChild0Copy(pObj), Abc_ObjChild1Copy(pObj) );
+ }
+ else
+ {
+ Abc_NtkDupObj( pNtkNew, pObj, 0 );
+ Abc_ObjForEachFanin( pObj, pFanin, k )
+ Abc_ObjAddFanin( pObj->pCopy, pFanin->pCopy );
}
}
+ // connect the internal nodes to the new CO
+ Abc_ObjAddFanin( pNodeCoNew, pNode->pCopy );
+ Vec_PtrFree( vNodes );
+
+ if ( !Abc_NtkCheck( pNtkNew ) )
+ fprintf( stdout, "Abc_NtkCreateCone(): Network check has failed.\n" );
+ return pNtkNew;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Creates the network composed of several logic cones.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Abc_Ntk_t * Abc_NtkCreateConeArray( Abc_Ntk_t * pNtk, Vec_Ptr_t * vRoots, int fUseAllCis )
+{
+ Abc_Ntk_t * pNtkNew;
+ Vec_Ptr_t * vNodes;
+ Abc_Obj_t * pObj, * pFanin, * pNodeCoNew;
+ char Buffer[1000];
+ int i, k;
+
+ assert( Abc_NtkIsLogic(pNtk) || Abc_NtkIsStrash(pNtk) );
+
+ // start the network
+ pNtkNew = Abc_NtkAlloc( pNtk->ntkType, pNtk->ntkFunc, 1 );
+ // set the name
+ sprintf( Buffer, "%s_part", pNtk->pName );
+ pNtkNew->pName = Extra_UtilStrsav(Buffer);
+
// establish connection between the constant nodes
if ( Abc_NtkIsStrash(pNtk) )
- Abc_AigConst1(pNtk->pManFunc)->pCopy = Abc_AigConst1(pNtkNew->pManFunc);
+ Abc_AigConst1(pNtk)->pCopy = Abc_AigConst1(pNtkNew);
+
+ // collect the nodes in the TFI of the output (mark the TFI)
+ vNodes = Abc_NtkDfsNodes( pNtk, (Abc_Obj_t **)Vec_PtrArray(vRoots), Vec_PtrSize(vRoots) );
+
+ // create the PIs
+ Abc_NtkForEachCi( pNtk, pObj, i )
+ {
+ if ( fUseAllCis || Abc_NodeIsTravIdCurrent(pObj) ) // TravId is set by DFS
+ {
+ pObj->pCopy = Abc_NtkCreatePi(pNtkNew);
+ Abc_ObjAssignName( pObj->pCopy, Abc_ObjName(pObj), NULL );
+ }
+ }
// copy the nodes
Vec_PtrForEachEntry( vNodes, pObj, i )
@@ -341,26 +621,160 @@ Abc_Ntk_t * Abc_NtkSplitOutput( Abc_Ntk_t * pNtk, Abc_Obj_t * pNode, int fUseAll
}
else
{
- Abc_NtkDupObj( pNtkNew, pObj );
+ Abc_NtkDupObj( pNtkNew, pObj, 0 );
Abc_ObjForEachFanin( pObj, pFanin, k )
Abc_ObjAddFanin( pObj->pCopy, pFanin->pCopy );
}
}
Vec_PtrFree( vNodes );
- // add the PO corresponding to this output
- pNode->pCopy = Abc_NtkCreatePo( pNtkNew );
- Abc_ObjAddFanin( pNode->pCopy, Abc_ObjFanin0(pNode)->pCopy );
- Abc_NtkLogicStoreName( pNode->pCopy, Abc_ObjName(pNode) );
+ // add the POs corresponding to the root nodes
+ Vec_PtrForEachEntry( vRoots, pObj, i )
+ {
+ // create the PO node
+ pNodeCoNew = Abc_NtkCreatePo( pNtkNew );
+ // connect the internal nodes to the new CO
+ if ( Abc_ObjIsCo(pObj) )
+ Abc_ObjAddFanin( pNodeCoNew, Abc_ObjChild0Copy(pObj) );
+ else
+ Abc_ObjAddFanin( pNodeCoNew, pObj->pCopy );
+ // assign the name
+ Abc_ObjAssignName( pNodeCoNew, Abc_ObjName(pObj), NULL );
+ }
+
+ if ( !Abc_NtkCheck( pNtkNew ) )
+ fprintf( stdout, "Abc_NtkCreateConeArray(): Network check has failed.\n" );
+ return pNtkNew;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Adds new nodes to the cone.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Abc_NtkAppendToCone( Abc_Ntk_t * pNtkNew, Abc_Ntk_t * pNtk, Vec_Ptr_t * vRoots )
+{
+ Vec_Ptr_t * vNodes;
+ Abc_Obj_t * pObj;
+ int i, iNodeId;
+
+ assert( Abc_NtkIsStrash(pNtkNew) );
+ assert( Abc_NtkIsStrash(pNtk) );
+
+ // collect the nodes in the TFI of the output (mark the TFI)
+ vNodes = Abc_NtkDfsNodes( pNtk, (Abc_Obj_t **)Vec_PtrArray(vRoots), Vec_PtrSize(vRoots) );
+
+ // establish connection between the constant nodes
+ Abc_AigConst1(pNtk)->pCopy = Abc_AigConst1(pNtkNew);
+
+ // create the PIs
+ Abc_NtkForEachCi( pNtk, pObj, i )
+ {
+ // skip CIs that are not used
+ if ( !Abc_NodeIsTravIdCurrent(pObj) )
+ continue;
+ // find the corresponding CI in the new network
+ iNodeId = Nm_ManFindIdByNameTwoTypes( pNtkNew->pManName, Abc_ObjName(pObj), ABC_OBJ_PI, ABC_OBJ_BO );
+ if ( iNodeId == -1 )
+ {
+ pObj->pCopy = Abc_NtkCreatePi(pNtkNew);
+ Abc_ObjAssignName( pObj->pCopy, Abc_ObjName(pObj), NULL );
+ }
+ else
+ pObj->pCopy = Abc_NtkObj( pNtkNew, iNodeId );
+ }
+
+ // copy the nodes
+ Vec_PtrForEachEntry( vNodes, pObj, i )
+ pObj->pCopy = Abc_AigAnd( pNtkNew->pManFunc, Abc_ObjChild0Copy(pObj), Abc_ObjChild1Copy(pObj) );
+ Vec_PtrFree( vNodes );
+
+ // do not add the COs
+ if ( !Abc_NtkCheck( pNtkNew ) )
+ fprintf( stdout, "Abc_NtkAppendToCone(): Network check has failed.\n" );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Creates the network composed of MFFC of one node.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Abc_Ntk_t * Abc_NtkCreateMffc( Abc_Ntk_t * pNtk, Abc_Obj_t * pNode, char * pNodeName )
+{
+ Abc_Ntk_t * pNtkNew;
+ Abc_Obj_t * pObj, * pFanin, * pNodeCoNew;
+ Vec_Ptr_t * vCone, * vSupp;
+ char Buffer[1000];
+ int i, k;
+
+ assert( Abc_NtkIsLogic(pNtk) || Abc_NtkIsStrash(pNtk) );
+ assert( Abc_ObjIsNode(pNode) );
+
+ // start the network
+ pNtkNew = Abc_NtkAlloc( pNtk->ntkType, pNtk->ntkFunc, 1 );
+ // set the name
+ sprintf( Buffer, "%s_%s", pNtk->pName, pNodeName );
+ pNtkNew->pName = Extra_UtilStrsav(Buffer);
+
+ // establish connection between the constant nodes
+ if ( Abc_NtkIsStrash(pNtk) )
+ Abc_AigConst1(pNtk)->pCopy = Abc_AigConst1(pNtkNew);
+
+ // collect the nodes in MFFC
+ vCone = Vec_PtrAlloc( 100 );
+ vSupp = Vec_PtrAlloc( 100 );
+ Abc_NodeDeref_rec( pNode );
+ Abc_NodeMffsConeSupp( pNode, vCone, vSupp );
+ Abc_NodeRef_rec( pNode );
+ // create the PIs
+ Vec_PtrForEachEntry( vSupp, pObj, i )
+ {
+ pObj->pCopy = Abc_NtkCreatePi(pNtkNew);
+ Abc_ObjAssignName( pObj->pCopy, Abc_ObjName(pObj), NULL );
+ }
+ // create the PO
+ pNodeCoNew = Abc_NtkCreatePo( pNtkNew );
+ Abc_ObjAssignName( pNodeCoNew, pNodeName, NULL );
+ // copy the nodes
+ Vec_PtrForEachEntry( vCone, pObj, i )
+ {
+ // if it is an AIG, add to the hash table
+ if ( Abc_NtkIsStrash(pNtk) )
+ {
+ pObj->pCopy = Abc_AigAnd( pNtkNew->pManFunc, Abc_ObjChild0Copy(pObj), Abc_ObjChild1Copy(pObj) );
+ }
+ else
+ {
+ Abc_NtkDupObj( pNtkNew, pObj, 0 );
+ Abc_ObjForEachFanin( pObj, pFanin, k )
+ Abc_ObjAddFanin( pObj->pCopy, pFanin->pCopy );
+ }
+ }
+ // connect the topmost node
+ Abc_ObjAddFanin( pNodeCoNew, pNode->pCopy );
+ Vec_PtrFree( vCone );
+ Vec_PtrFree( vSupp );
if ( !Abc_NtkCheck( pNtkNew ) )
- fprintf( stdout, "Abc_NtkSplitOutput(): Network check has failed.\n" );
+ fprintf( stdout, "Abc_NtkCreateMffc(): Network check has failed.\n" );
return pNtkNew;
}
/**Function*************************************************************
- Synopsis [Creates the network composed of one output.]
+ Synopsis [Creates the miter composed of one multi-output cone.]
Description []
@@ -369,7 +783,7 @@ Abc_Ntk_t * Abc_NtkSplitOutput( Abc_Ntk_t * pNtk, Abc_Obj_t * pNode, int fUseAll
SeeAlso []
***********************************************************************/
-Abc_Ntk_t * Abc_NtkCreateCone( Abc_Ntk_t * pNtk, Vec_Ptr_t * vRoots, Vec_Int_t * vValues )
+Abc_Ntk_t * Abc_NtkCreateTarget( Abc_Ntk_t * pNtk, Vec_Ptr_t * vRoots, Vec_Int_t * vValues )
{
Vec_Ptr_t * vNodes;
Abc_Ntk_t * pNtkNew;
@@ -380,8 +794,8 @@ Abc_Ntk_t * Abc_NtkCreateCone( Abc_Ntk_t * pNtk, Vec_Ptr_t * vRoots, Vec_Int_t *
// start the network
Abc_NtkCleanCopy( pNtk );
- pNtkNew = Abc_NtkAlloc( ABC_TYPE_STRASH, ABC_FUNC_AIG );
- pNtkNew->pName = util_strsav(pNtk->pName);
+ pNtkNew = Abc_NtkAlloc( ABC_NTK_STRASH, ABC_FUNC_AIG, 1 );
+ pNtkNew->pName = Extra_UtilStrsav(pNtk->pName);
// collect the nodes in the TFI of the output
vNodes = Abc_NtkDfsNodes( pNtk, (Abc_Obj_t **)vRoots->pArray, vRoots->nSize );
@@ -389,18 +803,21 @@ Abc_Ntk_t * Abc_NtkCreateCone( Abc_Ntk_t * pNtk, Vec_Ptr_t * vRoots, Vec_Int_t *
Abc_NtkForEachCi( pNtk, pObj, i )
{
pObj->pCopy = Abc_NtkCreatePi(pNtkNew);
- Abc_NtkLogicStoreName( pObj->pCopy, Abc_ObjName(pObj) );
+ Abc_ObjAssignName( pObj->pCopy, Abc_ObjName(pObj), NULL );
}
// copy the nodes
Vec_PtrForEachEntry( vNodes, pObj, i )
- pObj->pCopy = Abc_NodeStrash( pNtkNew->pManFunc, pObj );
+ pObj->pCopy = Abc_NodeStrash( pNtkNew, pObj, 0 );
Vec_PtrFree( vNodes );
// add the PO
- pFinal = Abc_AigConst1( pNtkNew->pManFunc );
+ pFinal = Abc_AigConst1( pNtkNew );
Vec_PtrForEachEntry( vRoots, pObj, i )
{
- pOther = pObj->pCopy;
+ if ( Abc_ObjIsCo(pObj) )
+ pOther = Abc_ObjFanin0(pObj)->pCopy;
+ else
+ pOther = pObj->pCopy;
if ( Vec_IntEntry(vValues, i) == 0 )
pOther = Abc_ObjNot(pOther);
pFinal = Abc_AigAnd( pNtkNew->pManFunc, pFinal, pOther );
@@ -409,15 +826,15 @@ Abc_Ntk_t * Abc_NtkCreateCone( Abc_Ntk_t * pNtk, Vec_Ptr_t * vRoots, Vec_Int_t *
// add the PO corresponding to this output
pNodePo = Abc_NtkCreatePo( pNtkNew );
Abc_ObjAddFanin( pNodePo, pFinal );
- Abc_NtkLogicStoreName( pNodePo, "miter" );
+ Abc_ObjAssignName( pNodePo, "miter", NULL );
if ( !Abc_NtkCheck( pNtkNew ) )
- fprintf( stdout, "Abc_NtkCreateCone(): Network check has failed.\n" );
+ fprintf( stdout, "Abc_NtkCreateTarget(): Network check has failed.\n" );
return pNtkNew;
}
/**Function*************************************************************
- Synopsis [Deletes the Ntk.]
+ Synopsis [Creates the network composed of one node.]
Description []
@@ -426,30 +843,71 @@ Abc_Ntk_t * Abc_NtkCreateCone( Abc_Ntk_t * pNtk, Vec_Ptr_t * vRoots, Vec_Int_t *
SeeAlso []
***********************************************************************/
-Abc_Ntk_t * Abc_NtkSplitNode( Abc_Ntk_t * pNtk, Abc_Obj_t * pNode )
+Abc_Ntk_t * Abc_NtkCreateFromNode( Abc_Ntk_t * pNtk, Abc_Obj_t * pNode )
{
Abc_Ntk_t * pNtkNew;
Abc_Obj_t * pFanin, * pNodePo;
int i;
// start the network
- pNtkNew = Abc_NtkAlloc( pNtk->ntkType, pNtk->ntkFunc );
- pNtkNew->pName = util_strsav(Abc_ObjName(pNode));
+ pNtkNew = Abc_NtkAlloc( pNtk->ntkType, pNtk->ntkFunc, 1 );
+ pNtkNew->pName = Extra_UtilStrsav(Abc_ObjName(pNode));
// add the PIs corresponding to the fanins of the node
Abc_ObjForEachFanin( pNode, pFanin, i )
{
pFanin->pCopy = Abc_NtkCreatePi( pNtkNew );
- Abc_NtkLogicStoreName( pFanin->pCopy, Abc_ObjName(pFanin) );
+ Abc_ObjAssignName( pFanin->pCopy, Abc_ObjName(pFanin), NULL );
}
// duplicate and connect the node
- pNode->pCopy = Abc_NtkDupObj( pNtkNew, pNode );
+ pNode->pCopy = Abc_NtkDupObj( pNtkNew, pNode, 0 );
Abc_ObjForEachFanin( pNode, pFanin, i )
Abc_ObjAddFanin( pNode->pCopy, pFanin->pCopy );
// create the only PO
pNodePo = Abc_NtkCreatePo( pNtkNew );
Abc_ObjAddFanin( pNodePo, pNode->pCopy );
- Abc_NtkLogicStoreName( pNodePo, Abc_ObjName(pNode) );
+ Abc_ObjAssignName( pNodePo, Abc_ObjName(pNode), NULL );
+ if ( !Abc_NtkCheck( pNtkNew ) )
+ fprintf( stdout, "Abc_NtkCreateFromNode(): Network check has failed.\n" );
+ return pNtkNew;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Creates the network composed of one node with the given SOP.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Abc_Ntk_t * Abc_NtkCreateWithNode( char * pSop )
+{
+ Abc_Ntk_t * pNtkNew;
+ Abc_Obj_t * pFanin, * pNode, * pNodePo;
+ Vec_Ptr_t * vNames;
+ int i, nVars;
+ // start the network
+ pNtkNew = Abc_NtkAlloc( ABC_NTK_LOGIC, ABC_FUNC_SOP, 1 );
+ pNtkNew->pName = Extra_UtilStrsav("ex");
+ // create PIs
+ Vec_PtrPush( pNtkNew->vObjs, NULL );
+ nVars = Abc_SopGetVarNum( pSop );
+ vNames = Abc_NodeGetFakeNames( nVars );
+ for ( i = 0; i < nVars; i++ )
+ Abc_ObjAssignName( Abc_NtkCreatePi(pNtkNew), Vec_PtrEntry(vNames, i), NULL );
+ Abc_NodeFreeNames( vNames );
+ // create the node, add PIs as fanins, set the function
+ pNode = Abc_NtkCreateNode( pNtkNew );
+ Abc_NtkForEachPi( pNtkNew, pFanin, i )
+ Abc_ObjAddFanin( pNode, pFanin );
+ pNode->pData = Abc_SopRegister( pNtkNew->pManFunc, pSop );
+ // create the only PO
+ pNodePo = Abc_NtkCreatePo(pNtkNew);
+ Abc_ObjAddFanin( pNodePo, pNode );
+ Abc_ObjAssignName( pNodePo, "F", NULL );
if ( !Abc_NtkCheck( pNtkNew ) )
- fprintf( stdout, "Abc_NtkSplitNode(): Network check has failed.\n" );
+ fprintf( stdout, "Abc_NtkCreateWithNode(): Network check has failed.\n" );
return pNtkNew;
}
@@ -467,64 +925,107 @@ Abc_Ntk_t * Abc_NtkSplitNode( Abc_Ntk_t * pNtk, Abc_Obj_t * pNode )
void Abc_NtkDelete( Abc_Ntk_t * pNtk )
{
Abc_Obj_t * pObj;
+ void * pAttrMan;
int TotalMemory, i;
int LargePiece = (4 << ABC_NUM_STEPS);
if ( pNtk == NULL )
return;
+ // free the HAIG
+ if ( pNtk->pHaig )
+ Abc_NtkHaigStop( pNtk );
+ // free EXDC Ntk
+ if ( pNtk->pExdc )
+ Abc_NtkDelete( pNtk->pExdc );
+ // dereference the BDDs
+ if ( Abc_NtkHasBdd(pNtk) )
+ {
+ Abc_NtkForEachNode( pNtk, pObj, i )
+ Cudd_RecursiveDeref( pNtk->pManFunc, pObj->pData );
+ }
// make sure all the marks are clean
Abc_NtkForEachObj( pNtk, pObj, i )
{
// free large fanout arrays
- if ( pObj->vFanouts.nCap * 4 > LargePiece )
+ if ( pNtk->pMmObj && pObj->vFanouts.nCap * 4 > LargePiece )
FREE( pObj->vFanouts.pArray );
- // check that the other things are okay
+ // these flags should be always zero
+ // if this is not true, something is wrong somewhere
assert( pObj->fMarkA == 0 );
assert( pObj->fMarkB == 0 );
assert( pObj->fMarkC == 0 );
}
-
- // dereference the BDDs
- if ( Abc_NtkHasBdd(pNtk) )
- Abc_NtkForEachNode( pNtk, pObj, i )
- Cudd_RecursiveDeref( pNtk->pManFunc, pObj->pData );
+ // free the nodes
+ if ( pNtk->pMmStep == NULL )
+ {
+ Abc_NtkForEachObj( pNtk, pObj, i )
+ {
+ FREE( pObj->vFanouts.pArray );
+ FREE( pObj->vFanins.pArray );
+ }
+ }
+ if ( pNtk->pMmObj == NULL )
+ {
+ Abc_NtkForEachObj( pNtk, pObj, i )
+ free( pObj );
+ }
- FREE( pNtk->pName );
- FREE( pNtk->pSpec );
- // copy the EXDC Ntk
- if ( pNtk->pExdc )
- Abc_NtkDelete( pNtk->pExdc );
// free the arrays
- Vec_PtrFree( pNtk->vObjs );
- Vec_PtrFree( pNtk->vLats );
+ Vec_PtrFree( pNtk->vPios );
+ Vec_PtrFree( pNtk->vPis );
+ Vec_PtrFree( pNtk->vPos );
Vec_PtrFree( pNtk->vCis );
Vec_PtrFree( pNtk->vCos );
- Vec_PtrFree( pNtk->vPtrTemp );
- Vec_IntFree( pNtk->vIntTemp );
- Vec_StrFree( pNtk->vStrTemp );
- // free the hash table of Obj name into Obj ID
- stmm_free_table( pNtk->tName2Net );
- stmm_free_table( pNtk->tObj2Name );
+ Vec_PtrFree( pNtk->vAsserts );
+ Vec_PtrFree( pNtk->vObjs );
+ Vec_PtrFree( pNtk->vBoxes );
+ if ( pNtk->vLevelsR ) Vec_IntFree( pNtk->vLevelsR );
+ FREE( pNtk->pModel );
+ FREE( pNtk->pSeqModel );
TotalMemory = 0;
- TotalMemory += Extra_MmFlexReadMemUsage(pNtk->pMmNames);
- TotalMemory += Extra_MmFixedReadMemUsage(pNtk->pMmObj);
- TotalMemory += Extra_MmStepReadMemUsage(pNtk->pMmStep);
+ TotalMemory += pNtk->pMmObj? Extra_MmFixedReadMemUsage(pNtk->pMmObj) : 0;
+ TotalMemory += pNtk->pMmStep? Extra_MmStepReadMemUsage(pNtk->pMmStep) : 0;
// fprintf( stdout, "The total memory allocated internally by the network = %0.2f Mb.\n", ((double)TotalMemory)/(1<<20) );
// free the storage
- Extra_MmFlexStop ( pNtk->pMmNames, 0 );
- Extra_MmFixedStop( pNtk->pMmObj, 0 );
- Extra_MmStepStop ( pNtk->pMmStep, 0 );
+ if ( pNtk->pMmObj )
+ Extra_MmFixedStop( pNtk->pMmObj );
+ if ( pNtk->pMmStep )
+ Extra_MmStepStop ( pNtk->pMmStep );
+ // name manager
+ Nm_ManFree( pNtk->pManName );
// free the timing manager
if ( pNtk->pManTime )
Abc_ManTimeStop( pNtk->pManTime );
// start the functionality manager
- if ( Abc_NtkHasSop(pNtk) )
- Extra_MmFlexStop( pNtk->pManFunc, 0 );
+ if ( Abc_NtkIsStrash(pNtk) )
+ Abc_AigFree( pNtk->pManFunc );
+ else if ( Abc_NtkHasSop(pNtk) || Abc_NtkHasBlifMv(pNtk) )
+ Extra_MmFlexStop( pNtk->pManFunc );
else if ( Abc_NtkHasBdd(pNtk) )
Extra_StopManager( pNtk->pManFunc );
else if ( Abc_NtkHasAig(pNtk) )
- Abc_AigFree( pNtk->pManFunc );
- else if ( !Abc_NtkHasMapping(pNtk) )
+ { if ( pNtk->pManFunc ) Hop_ManStop( pNtk->pManFunc ); }
+ else if ( Abc_NtkHasMapping(pNtk) )
+ pNtk->pManFunc = NULL;
+ else if ( !Abc_NtkHasBlackbox(pNtk) )
assert( 0 );
+ // free the hierarchy
+ if ( pNtk->pDesign )
+ {
+ Abc_LibFree( pNtk->pDesign, pNtk );
+ pNtk->pDesign = NULL;
+ }
+// if ( pNtk->pBlackBoxes )
+// Vec_IntFree( pNtk->pBlackBoxes );
+ // free node attributes
+ Vec_PtrForEachEntry( pNtk->vAttrs, pAttrMan, i )
+ if ( pAttrMan )
+ {
+//printf( "deleting attr\n" );
+ Vec_AttFree( pAttrMan, 1 );
+ }
+ Vec_PtrFree( pNtk->vAttrs );
+ FREE( pNtk->pName );
+ FREE( pNtk->pSpec );
free( pNtk );
}
@@ -545,6 +1046,9 @@ void Abc_NtkFixNonDrivenNets( Abc_Ntk_t * pNtk )
Abc_Obj_t * pNet, * pNode;
int i;
+ if ( Abc_NtkNodeNum(pNtk) == 0 && Abc_NtkBoxNum(pNtk) == 0 )
+ return;
+
// check for non-driven nets
vNets = Vec_PtrAlloc( 100 );
Abc_NtkForEachNet( pNtk, pNet, i )
@@ -552,28 +1056,24 @@ void Abc_NtkFixNonDrivenNets( Abc_Ntk_t * pNtk )
if ( Abc_ObjFaninNum(pNet) > 0 )
continue;
// add the constant 0 driver
- pNode = Abc_NtkCreateNode( pNtk );
- // set the constant function
- Abc_ObjSetData( pNode, Abc_SopRegister(pNtk->pManFunc, " 0\n") );
+ pNode = Abc_NtkCreateNodeConst0( pNtk );
// add the fanout net
Abc_ObjAddFanin( pNet, pNode );
// add the net to those for which the warning will be printed
- Vec_PtrPush( vNets, pNet->pData );
+ Vec_PtrPush( vNets, pNet );
}
// print the warning
if ( vNets->nSize > 0 )
{
- printf( "Constant-zero drivers were added to %d non-driven nets:\n", vNets->nSize );
- for ( i = 0; i < vNets->nSize; i++ )
+ printf( "Warning: Constant-0 drivers added to %d non-driven nets in network \"%s\":\n", Vec_PtrSize(vNets), pNtk->pName );
+ Vec_PtrForEachEntry( vNets, pNet, i )
{
- if ( i == 0 )
- printf( "%s", vNets->pArray[i] );
- else if ( i == 1 )
- printf( ", %s", vNets->pArray[i] );
- else if ( i == 2 )
+ printf( "%s%s", (i? ", ": ""), Abc_ObjName(pNet) );
+ if ( i == 3 )
{
- printf( ", %s, etc.", vNets->pArray[i] );
+ if ( Vec_PtrSize(vNets) > 3 )
+ printf( " ..." );
break;
}
}
@@ -583,6 +1083,150 @@ void Abc_NtkFixNonDrivenNets( Abc_Ntk_t * pNtk )
}
+/**Function*************************************************************
+
+ Synopsis [Converts the network to combinational.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Abc_NtkMakeComb( Abc_Ntk_t * pNtk )
+{
+ Abc_Obj_t * pObj;
+ int i;
+
+ if ( Abc_NtkIsComb(pNtk) )
+ return;
+
+ assert( !Abc_NtkIsNetlist(pNtk) );
+ assert( Abc_NtkHasOnlyLatchBoxes(pNtk) );
+
+ // detach the latches
+// Abc_NtkForEachLatch( pNtk, pObj, i )
+ Vec_PtrForEachEntryReverse( pNtk->vBoxes, pObj, i )
+ Abc_NtkDeleteObj( pObj );
+ assert( Abc_NtkLatchNum(pNtk) == 0 );
+ assert( Abc_NtkBoxNum(pNtk) == 0 );
+
+ // move CIs to become PIs
+ Vec_PtrClear( pNtk->vPis );
+ Abc_NtkForEachCi( pNtk, pObj, i )
+ {
+ if ( Abc_ObjIsBo(pObj) )
+ {
+ pObj->Type = ABC_OBJ_PI;
+ pNtk->nObjCounts[ABC_OBJ_PI]++;
+ pNtk->nObjCounts[ABC_OBJ_BO]--;
+ }
+ Vec_PtrPush( pNtk->vPis, pObj );
+ }
+ assert( Abc_NtkBoNum(pNtk) == 0 );
+
+ // move COs to become POs
+ Vec_PtrClear( pNtk->vPos );
+ Abc_NtkForEachCo( pNtk, pObj, i )
+ {
+ if ( Abc_ObjIsBi(pObj) )
+ {
+ pObj->Type = ABC_OBJ_PO;
+ pNtk->nObjCounts[ABC_OBJ_PO]++;
+ pNtk->nObjCounts[ABC_OBJ_BI]--;
+ }
+ Vec_PtrPush( pNtk->vPos, pObj );
+ }
+ assert( Abc_NtkBiNum(pNtk) == 0 );
+
+ if ( !Abc_NtkCheck( pNtk ) )
+ fprintf( stdout, "Abc_NtkMakeComb(): Network check has failed.\n" );
+}
+
+
+/**Function*************************************************************
+
+ Synopsis [Removes POs with suppsize less than 2 and PIs without fanout.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Abc_Ntk_t * Abc_NtkTrim( Abc_Ntk_t * pNtk )
+{
+ Abc_Obj_t * pObj;
+ int i, k, m;
+
+ // filter POs
+ k = m = 0;
+ Abc_NtkForEachCo( pNtk, pObj, i )
+ {
+ if ( Abc_ObjIsPo(pObj) )
+ {
+ // remove constant nodes and PI pointers
+ if ( Abc_ObjFaninNum(Abc_ObjFanin0(pObj)) == 0 )
+ {
+ Abc_ObjDeleteFanin( pObj, Abc_ObjFanin0(pObj) );
+ if ( Abc_ObjFanoutNum(Abc_ObjFanin0(pObj)) == 0 && !Abc_ObjIsPi(Abc_ObjFanin0(pObj)) )
+ Abc_NtkDeleteObj_rec( Abc_ObjFanin0(pObj), 1 );
+ pNtk->vObjs->pArray[pObj->Id] = NULL;
+ pObj->Id = (1<<26)-1;
+ pNtk->nObjCounts[pObj->Type]--;
+ pNtk->nObjs--;
+ Abc_ObjRecycle( pObj );
+ continue;
+ }
+ // remove buffers/inverters of PIs
+ if ( Abc_ObjFaninNum(Abc_ObjFanin0(pObj)) == 1 )
+ {
+ if ( Abc_ObjIsPi(Abc_ObjFanin0(Abc_ObjFanin0(pObj))) )
+ {
+ Abc_ObjDeleteFanin( pObj, Abc_ObjFanin0(pObj) );
+ if ( Abc_ObjFanoutNum(Abc_ObjFanin0(pObj)) == 0 )
+ Abc_NtkDeleteObj_rec( Abc_ObjFanin0(pObj), 1 );
+ pNtk->vObjs->pArray[pObj->Id] = NULL;
+ pObj->Id = (1<<26)-1;
+ pNtk->nObjCounts[pObj->Type]--;
+ pNtk->nObjs--;
+ Abc_ObjRecycle( pObj );
+ continue;
+ }
+ }
+ Vec_PtrWriteEntry( pNtk->vPos, m++, pObj );
+ }
+ Vec_PtrWriteEntry( pNtk->vCos, k++, pObj );
+ }
+ Vec_PtrShrink( pNtk->vPos, m );
+ Vec_PtrShrink( pNtk->vCos, k );
+
+ // filter PIs
+ k = m = 0;
+ Abc_NtkForEachCi( pNtk, pObj, i )
+ {
+ if ( Abc_ObjIsPi(pObj) )
+ {
+ if ( Abc_ObjFanoutNum(pObj) == 0 )
+ {
+ pNtk->vObjs->pArray[pObj->Id] = NULL;
+ pObj->Id = (1<<26)-1;
+ pNtk->nObjCounts[pObj->Type]--;
+ pNtk->nObjs--;
+ Abc_ObjRecycle( pObj );
+ continue;
+ }
+ Vec_PtrWriteEntry( pNtk->vPis, m++, pObj );
+ }
+ Vec_PtrWriteEntry( pNtk->vCis, k++, pObj );
+ }
+ Vec_PtrShrink( pNtk->vPis, m );
+ Vec_PtrShrink( pNtk->vCis, k );
+
+ return Abc_NtkDup( pNtk );
+}
////////////////////////////////////////////////////////////////////////
diff --git a/src/base/abc/abcObj.c b/src/base/abc/abcObj.c
index 40c6e7a5..7a995c71 100644
--- a/src/base/abc/abcObj.c
+++ b/src/base/abc/abcObj.c
@@ -19,6 +19,7 @@
***********************************************************************/
#include "abc.h"
+#include "abcInt.h"
#include "main.h"
#include "mio.h"
@@ -27,12 +28,12 @@
////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////
-/// FUNCTION DEFITIONS ///
+/// FUNCTION DEFINITIONS ///
////////////////////////////////////////////////////////////////////////
/**Function*************************************************************
- Synopsis [Creates a new Obj.]
+ Synopsis [Creates a new object.]
Description []
@@ -44,17 +45,20 @@
Abc_Obj_t * Abc_ObjAlloc( Abc_Ntk_t * pNtk, Abc_ObjType_t Type )
{
Abc_Obj_t * pObj;
- pObj = (Abc_Obj_t *)Extra_MmFixedEntryFetch( pNtk->pMmObj );
+ if ( pNtk->pMmObj )
+ pObj = (Abc_Obj_t *)Extra_MmFixedEntryFetch( pNtk->pMmObj );
+ else
+ pObj = (Abc_Obj_t *)ALLOC( Abc_Obj_t, 1 );
memset( pObj, 0, sizeof(Abc_Obj_t) );
- pObj->Id = -1;
pObj->pNtk = pNtk;
pObj->Type = Type;
+ pObj->Id = -1;
return pObj;
}
/**Function*************************************************************
- Synopsis [Recycles the Obj.]
+ Synopsis [Recycles the object.]
Description []
@@ -66,8 +70,22 @@ Abc_Obj_t * Abc_ObjAlloc( Abc_Ntk_t * pNtk, Abc_ObjType_t Type )
void Abc_ObjRecycle( Abc_Obj_t * pObj )
{
Abc_Ntk_t * pNtk = pObj->pNtk;
+ int LargePiece = (4 << ABC_NUM_STEPS);
+ // free large fanout arrays
+ if ( pNtk->pMmStep && pObj->vFanouts.nCap * 4 > LargePiece )
+ FREE( pObj->vFanouts.pArray );
+ if ( pNtk->pMmStep == NULL )
+ {
+ FREE( pObj->vFanouts.pArray );
+ FREE( pObj->vFanins.pArray );
+ }
+ // clean the memory to make deleted object distinct from the live one
memset( pObj, 0, sizeof(Abc_Obj_t) );
- Extra_MmFixedEntryRecycle( pNtk->pMmObj, (char *)pObj );
+ // recycle the object
+ if ( pNtk->pMmObj )
+ Extra_MmFixedEntryRecycle( pNtk->pMmObj, (char *)pObj );
+ else
+ free( pObj );
}
/**Function*************************************************************
@@ -81,49 +99,207 @@ void Abc_ObjRecycle( Abc_Obj_t * pObj )
SeeAlso []
***********************************************************************/
-void Abc_ObjAdd( Abc_Obj_t * pObj )
+Abc_Obj_t * Abc_NtkCreateObj( Abc_Ntk_t * pNtk, Abc_ObjType_t Type )
{
- Abc_Ntk_t * pNtk = pObj->pNtk;
- assert( !Abc_ObjIsComplement(pObj) );
- // add to the array of objects
+ Abc_Obj_t * pObj;
+ // create new object, assign ID, and add to the array
+ pObj = Abc_ObjAlloc( pNtk, Type );
pObj->Id = pNtk->vObjs->nSize;
Vec_PtrPush( pNtk->vObjs, pObj );
+ pNtk->nObjCounts[Type]++;
pNtk->nObjs++;
// perform specialized operations depending on the object type
- if ( Abc_ObjIsNet(pObj) )
- {
- // add the name to the table
- if ( pObj->pData && stmm_insert( pNtk->tName2Net, pObj->pData, (char *)pObj ) )
- {
- printf( "Error: The net is already in the table...\n" );
- assert( 0 );
- }
- pNtk->nNets++;
- }
- else if ( Abc_ObjIsNode(pObj) )
- {
- pNtk->nNodes++;
- }
- else if ( Abc_ObjIsLatch(pObj) )
+ switch (Type)
{
- Vec_PtrPush( pNtk->vLats, pObj );
- pNtk->nLatches++;
+ case ABC_OBJ_NONE:
+ assert(0);
+ break;
+ case ABC_OBJ_CONST1:
+ assert(0);
+ break;
+ case ABC_OBJ_PIO:
+ assert(0);
+ break;
+ case ABC_OBJ_PI:
+ Vec_PtrPush( pNtk->vPis, pObj );
+ Vec_PtrPush( pNtk->vCis, pObj );
+ break;
+ case ABC_OBJ_PO:
+ Vec_PtrPush( pNtk->vPos, pObj );
+ Vec_PtrPush( pNtk->vCos, pObj );
+ break;
+ case ABC_OBJ_BI:
+ if ( pNtk->vCos ) Vec_PtrPush( pNtk->vCos, pObj );
+ break;
+ case ABC_OBJ_BO:
+ if ( pNtk->vCis ) Vec_PtrPush( pNtk->vCis, pObj );
+ break;
+ case ABC_OBJ_ASSERT:
+ Vec_PtrPush( pNtk->vAsserts, pObj );
+ Vec_PtrPush( pNtk->vCos, pObj );
+ break;
+ case ABC_OBJ_NET:
+ case ABC_OBJ_NODE:
+ break;
+ case ABC_OBJ_LATCH:
+ pObj->pData = (void *)ABC_INIT_NONE;
+ case ABC_OBJ_WHITEBOX:
+ case ABC_OBJ_BLACKBOX:
+ if ( pNtk->vBoxes ) Vec_PtrPush( pNtk->vBoxes, pObj );
+ break;
+ default:
+ assert(0);
+ break;
}
- else if ( Abc_ObjIsPi(pObj) )
+ return pObj;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Deletes the object from the network.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Abc_NtkDeleteObj( Abc_Obj_t * pObj )
+{
+ Abc_Ntk_t * pNtk = pObj->pNtk;
+ Vec_Ptr_t * vNodes;
+ int i;
+ assert( !Abc_ObjIsComplement(pObj) );
+ // remove from the table of names
+ if ( Nm_ManFindNameById(pObj->pNtk->pManName, pObj->Id) )
+ Nm_ManDeleteIdName(pObj->pNtk->pManName, pObj->Id);
+ // delete fanins and fanouts
+ vNodes = Vec_PtrAlloc( 100 );
+ Abc_NodeCollectFanouts( pObj, vNodes );
+ for ( i = 0; i < vNodes->nSize; i++ )
+ Abc_ObjDeleteFanin( vNodes->pArray[i], pObj );
+ Abc_NodeCollectFanins( pObj, vNodes );
+ for ( i = 0; i < vNodes->nSize; i++ )
+ Abc_ObjDeleteFanin( pObj, vNodes->pArray[i] );
+ Vec_PtrFree( vNodes );
+ // remove from the list of objects
+ Vec_PtrWriteEntry( pNtk->vObjs, pObj->Id, NULL );
+ pObj->Id = (1<<26)-1;
+ pNtk->nObjCounts[pObj->Type]--;
+ pNtk->nObjs--;
+ // perform specialized operations depending on the object type
+ switch (pObj->Type)
{
- Vec_PtrPush( pNtk->vCis, pObj );
- pNtk->nPis++;
+ case ABC_OBJ_NONE:
+ assert(0);
+ break;
+ case ABC_OBJ_CONST1:
+ assert(0);
+ break;
+ case ABC_OBJ_PIO:
+ assert(0);
+ break;
+ case ABC_OBJ_PI:
+ Vec_PtrRemove( pNtk->vPis, pObj );
+ Vec_PtrRemove( pNtk->vCis, pObj );
+ break;
+ case ABC_OBJ_PO:
+ Vec_PtrRemove( pNtk->vPos, pObj );
+ Vec_PtrRemove( pNtk->vCos, pObj );
+ break;
+ case ABC_OBJ_BI:
+ if ( pNtk->vCos ) Vec_PtrRemove( pNtk->vCos, pObj );
+ break;
+ case ABC_OBJ_BO:
+ if ( pNtk->vCis ) Vec_PtrRemove( pNtk->vCis, pObj );
+ break;
+ case ABC_OBJ_ASSERT:
+ Vec_PtrRemove( pNtk->vAsserts, pObj );
+ Vec_PtrRemove( pNtk->vCos, pObj );
+ break;
+ case ABC_OBJ_NET:
+ break;
+ case ABC_OBJ_NODE:
+ if ( Abc_NtkHasBdd(pNtk) )
+ Cudd_RecursiveDeref( pNtk->pManFunc, pObj->pData );
+ pObj->pData = NULL;
+ break;
+ case ABC_OBJ_LATCH:
+ case ABC_OBJ_WHITEBOX:
+ case ABC_OBJ_BLACKBOX:
+ if ( pNtk->vBoxes ) Vec_PtrRemove( pNtk->vBoxes, pObj );
+ break;
+ default:
+ assert(0);
+ break;
}
- else if ( Abc_ObjIsPo(pObj) )
+ // recycle the object memory
+ Abc_ObjRecycle( pObj );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Deletes the node and MFFC of the node.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Abc_NtkDeleteObj_rec( Abc_Obj_t * pObj, int fOnlyNodes )
+{
+ Vec_Ptr_t * vNodes;
+ int i;
+ assert( !Abc_ObjIsComplement(pObj) );
+ assert( !Abc_ObjIsPi(pObj) );
+ assert( Abc_ObjFanoutNum(pObj) == 0 );
+ // delete fanins and fanouts
+ vNodes = Vec_PtrAlloc( 100 );
+ Abc_NodeCollectFanins( pObj, vNodes );
+ Abc_NtkDeleteObj( pObj );
+ if ( fOnlyNodes )
{
- Vec_PtrPush( pNtk->vCos, pObj );
- pNtk->nPos++;
+ Vec_PtrForEachEntry( vNodes, pObj, i )
+ if ( Abc_ObjIsNode(pObj) && Abc_ObjFanoutNum(pObj) == 0 )
+ Abc_NtkDeleteObj_rec( pObj, fOnlyNodes );
}
else
{
- assert( 0 );
+ Vec_PtrForEachEntry( vNodes, pObj, i )
+ if ( !Abc_ObjIsPi(pObj) && Abc_ObjFanoutNum(pObj) == 0 )
+ Abc_NtkDeleteObj_rec( pObj, fOnlyNodes );
}
- assert( pObj->Id >= 0 );
+ Vec_PtrFree( vNodes );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Deletes the node and MFFC of the node.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Abc_NtkDeleteAll_rec( Abc_Obj_t * pObj )
+{
+ Vec_Ptr_t * vNodes;
+ int i;
+ assert( !Abc_ObjIsComplement(pObj) );
+ assert( Abc_ObjFanoutNum(pObj) == 0 );
+ // delete fanins and fanouts
+ vNodes = Vec_PtrAlloc( 100 );
+ Abc_NodeCollectFanins( pObj, vNodes );
+ Abc_NtkDeleteObj( pObj );
+ Vec_PtrForEachEntry( vNodes, pObj, i )
+ if ( !Abc_ObjIsNode(pObj) && Abc_ObjFanoutNum(pObj) == 0 )
+ Abc_NtkDeleteAll_rec( pObj );
+ Vec_PtrFree( vNodes );
}
/**Function*************************************************************
@@ -137,59 +313,68 @@ void Abc_ObjAdd( Abc_Obj_t * pObj )
SeeAlso []
***********************************************************************/
-Abc_Obj_t * Abc_NtkDupObj( Abc_Ntk_t * pNtkNew, Abc_Obj_t * pObj )
+Abc_Obj_t * Abc_NtkDupObj( Abc_Ntk_t * pNtkNew, Abc_Obj_t * pObj, int fCopyName )
{
Abc_Obj_t * pObjNew;
- pObjNew = Abc_ObjAlloc( pNtkNew, pObj->Type );
+ // create the new object
+ pObjNew = Abc_NtkCreateObj( pNtkNew, pObj->Type );
+ // transfer names of the terminal objects
+ if ( fCopyName )
+ {
+ if ( Abc_ObjIsCi(pObj) )
+ {
+ if ( !Abc_NtkIsNetlist(pNtkNew) )
+ Abc_ObjAssignName( pObjNew, Abc_ObjName(Abc_ObjFanout0Ntk(pObj)), NULL );
+ }
+ else if ( Abc_ObjIsCo(pObj) )
+ {
+ if ( !Abc_NtkIsNetlist(pNtkNew) )
+ {
+ if ( Abc_ObjIsPo(pObj) )
+ Abc_ObjAssignName( pObjNew, Abc_ObjName(Abc_ObjFanin0Ntk(pObj)), NULL );
+ else
+ {
+ assert( Abc_ObjIsLatch(Abc_ObjFanout0(pObj)) );
+ Abc_ObjAssignName( pObjNew, Abc_ObjName(pObj), NULL );
+ }
+ }
+ }
+ else if ( Abc_ObjIsBox(pObj) || Abc_ObjIsNet(pObj) )
+ Abc_ObjAssignName( pObjNew, Abc_ObjName(pObj), NULL );
+ }
+ // copy functionality/names
if ( Abc_ObjIsNode(pObj) ) // copy the function if functionality is compatible
{
if ( pNtkNew->ntkFunc == pObj->pNtk->ntkFunc )
{
- if ( Abc_NtkHasSop(pNtkNew) )
+ if ( Abc_NtkIsStrash(pNtkNew) )
+ {}
+ else if ( Abc_NtkHasSop(pNtkNew) || Abc_NtkHasBlifMv(pNtkNew) )
pObjNew->pData = Abc_SopRegister( pNtkNew->pManFunc, pObj->pData );
else if ( Abc_NtkHasBdd(pNtkNew) )
pObjNew->pData = Cudd_bddTransfer(pObj->pNtk->pManFunc, pNtkNew->pManFunc, pObj->pData), Cudd_Ref(pObjNew->pData);
+ else if ( Abc_NtkHasAig(pNtkNew) )
+ pObjNew->pData = Hop_Transfer(pObj->pNtk->pManFunc, pNtkNew->pManFunc, pObj->pData, Abc_ObjFaninNum(pObj));
else if ( Abc_NtkHasMapping(pNtkNew) )
pObjNew->pData = pObj->pData;
- else if ( Abc_NtkHasAig(pNtkNew) )
- assert( 0 );
+ else assert( 0 );
}
}
else if ( Abc_ObjIsNet(pObj) ) // copy the name
- pObjNew->pData = Abc_NtkRegisterName( pNtkNew, pObj->pData );
+ {
+ }
else if ( Abc_ObjIsLatch(pObj) ) // copy the reset value
pObjNew->pData = pObj->pData;
+ // transfer HAIG
+// pObjNew->pEquiv = pObj->pEquiv;
+ // remember the new node in the old node
pObj->pCopy = pObjNew;
- // add the object to the network
- Abc_ObjAdd( pObjNew );
return pObjNew;
}
/**Function*************************************************************
- Synopsis [Creates a new constant node.]
-
- Description []
-
- SideEffects []
-
- SeeAlso []
-
-***********************************************************************/
-Abc_Obj_t * Abc_NtkDupConst1( Abc_Ntk_t * pNtkAig, Abc_Ntk_t * pNtkNew )
-{
- Abc_Obj_t * pConst1;
- assert( Abc_NtkIsStrash(pNtkAig) );
- assert( Abc_NtkIsSopLogic(pNtkNew) );
- pConst1 = Abc_AigConst1(pNtkAig->pManFunc);
- if ( Abc_ObjFanoutNum(pConst1) > 0 )
- pConst1->pCopy = Abc_NodeCreateConst1( pNtkNew );
- return pConst1->pCopy;
-}
-
-/**Function*************************************************************
-
- Synopsis [Creates a new constant node.]
+ Synopsis [Duplicates the latch with its input/output terminals.]
Description []
@@ -198,26 +383,25 @@ Abc_Obj_t * Abc_NtkDupConst1( Abc_Ntk_t * pNtkAig, Abc_Ntk_t * pNtkNew )
SeeAlso []
***********************************************************************/
-Abc_Obj_t * Abc_NtkDupReset( Abc_Ntk_t * pNtkAig, Abc_Ntk_t * pNtkNew )
-{
- Abc_Obj_t * pReset, * pConst1;
- assert( Abc_NtkIsStrash(pNtkAig) );
- assert( Abc_NtkIsSopLogic(pNtkNew) );
- pReset = Abc_AigReset(pNtkAig->pManFunc);
- if ( Abc_ObjFanoutNum(pReset) > 0 )
- {
- // create new latch with reset value 0
- pReset->pCopy = Abc_NtkCreateLatch( pNtkNew );
- // add constant node fanin to the latch
- pConst1 = Abc_NodeCreateConst1( pNtkNew );
- Abc_ObjAddFanin( pReset->pCopy, pConst1 );
- }
- return pReset->pCopy;
-}
+Abc_Obj_t * Abc_NtkDupBox( Abc_Ntk_t * pNtkNew, Abc_Obj_t * pBox, int fCopyName )
+{
+ Abc_Obj_t * pTerm, * pBoxNew;
+ int i;
+ assert( Abc_ObjIsBox(pBox) );
+ // duplicate the box
+ pBoxNew = Abc_NtkDupObj( pNtkNew, pBox, fCopyName );
+ // duplicate the fanins and connect them
+ Abc_ObjForEachFanin( pBox, pTerm, i )
+ Abc_ObjAddFanin( pBoxNew, Abc_NtkDupObj(pNtkNew, pTerm, fCopyName) );
+ // duplicate the fanouts and connect them
+ Abc_ObjForEachFanout( pBox, pTerm, i )
+ Abc_ObjAddFanin( Abc_NtkDupObj(pNtkNew, pTerm, fCopyName), pBoxNew );
+ return pBoxNew;
+}
/**Function*************************************************************
- Synopsis [Deletes the object from the network.]
+ Synopsis [Clones the objects in the same network but does not assign its function.]
Description []
@@ -226,59 +410,17 @@ Abc_Obj_t * Abc_NtkDupReset( Abc_Ntk_t * pNtkAig, Abc_Ntk_t * pNtkNew )
SeeAlso []
***********************************************************************/
-void Abc_NtkDeleteObj( Abc_Obj_t * pObj )
+Abc_Obj_t * Abc_NtkCloneObj( Abc_Obj_t * pObj )
{
- Vec_Ptr_t * vNodes = pObj->pNtk->vPtrTemp;
- Abc_Ntk_t * pNtk = pObj->pNtk;
+ Abc_Obj_t * pClone, * pFanin;
int i;
-
- assert( !Abc_ObjIsComplement(pObj) );
-
- // delete fanins and fanouts
- Abc_NodeCollectFanouts( pObj, vNodes );
- for ( i = 0; i < vNodes->nSize; i++ )
- Abc_ObjDeleteFanin( vNodes->pArray[i], pObj );
- Abc_NodeCollectFanins( pObj, vNodes );
- for ( i = 0; i < vNodes->nSize; i++ )
- Abc_ObjDeleteFanin( pObj, vNodes->pArray[i] );
-
- // remove from the list of objects
- Vec_PtrWriteEntry( pNtk->vObjs, pObj->Id, NULL );
- pObj->Id = (1<<26)-1;
- pNtk->nObjs--;
-
- // perform specialized operations depending on the object type
- if ( Abc_ObjIsNet(pObj) )
- {
- // remove the net from the hash table of nets
- if ( pObj->pData && !stmm_delete( pNtk->tName2Net, (char **)&pObj->pData, (char **)&pObj ) )
- {
- printf( "Error: The net is not in the table...\n" );
- assert( 0 );
- }
- pObj->pData = NULL;
- pNtk->nNets--;
- }
- else if ( Abc_ObjIsNode(pObj) )
- {
- if ( Abc_NtkHasBdd(pNtk) )
- Cudd_RecursiveDeref( pNtk->pManFunc, pObj->pData );
- pNtk->nNodes--;
- }
- else if ( Abc_ObjIsLatch(pObj) )
- {
- pNtk->nLatches--;
- }
- else
- assert( 0 );
- // recycle the net itself
- Abc_ObjRecycle( pObj );
+ pClone = Abc_NtkCreateObj( pObj->pNtk, pObj->Type );
+ Abc_ObjForEachFanin( pObj, pFanin, i )
+ Abc_ObjAddFanin( pClone, pFanin );
+ return pClone;
}
-
-
-
/**Function*************************************************************
Synopsis [Returns the net with the given name.]
@@ -292,38 +434,22 @@ void Abc_NtkDeleteObj( Abc_Obj_t * pObj )
***********************************************************************/
Abc_Obj_t * Abc_NtkFindNode( Abc_Ntk_t * pNtk, char * pName )
{
- Abc_Obj_t * pObj, * pDriver;
- int i, Num;
- // check if the node is among CIs
- Abc_NtkForEachCi( pNtk, pObj, i )
- {
- if ( strcmp( Abc_ObjName(pObj), pName ) == 0 )
- {
- if ( i < Abc_NtkPiNum(pNtk) )
- printf( "Node \"%s\" is a primary input.\n", pName );
- else
- printf( "Node \"%s\" is a latch output.\n", pName );
- return NULL;
- }
- }
- // search the node among COs
- Abc_NtkForEachCo( pNtk, pObj, i )
- {
- if ( strcmp( Abc_ObjName(pObj), pName ) == 0 )
- {
- pDriver = Abc_ObjFanin0(pObj);
- if ( !Abc_ObjIsNode(pDriver) )
- {
- printf( "Node \"%s\" does not have logic associated with it.\n", pName );
- return NULL;
- }
- return pDriver;
- }
- }
+ Abc_Obj_t * pObj;
+ int Num;
+ // try to find the terminal
+ Num = Nm_ManFindIdByName( pNtk->pManName, pName, ABC_OBJ_PO );
+ if ( Num >= 0 )
+ return Abc_ObjFanin0( Abc_NtkObj( pNtk, Num ) );
+ Num = Nm_ManFindIdByName( pNtk->pManName, pName, ABC_OBJ_BI );
+ if ( Num >= 0 )
+ return Abc_ObjFanin0( Abc_NtkObj( pNtk, Num ) );
+ Num = Nm_ManFindIdByName( pNtk->pManName, pName, ABC_OBJ_NODE );
+ if ( Num >= 0 )
+ return Abc_NtkObj( pNtk, Num );
// find the internal node
- if ( pName[0] != '[' || pName[strlen(pName)-1] != ']' )
+ if ( pName[0] != 'n' )
{
- printf( "Name \"%s\" is not found among CIs/COs (internal name looks like this: \"[integer]\").\n", pName );
+ printf( "Name \"%s\" is not found among CO or node names (internal names often look as \"n<num>\").\n", pName );
return NULL;
}
Num = atoi( pName + 1 );
@@ -357,104 +483,70 @@ Abc_Obj_t * Abc_NtkFindNode( Abc_Ntk_t * pNtk, char * pName )
SeeAlso []
***********************************************************************/
-Abc_Obj_t * Abc_NtkFindCo( Abc_Ntk_t * pNtk, char * pName )
-{
- Abc_Obj_t * pNode;
- int i;
- // search the node among COs
- Abc_NtkForEachCo( pNtk, pNode, i )
- {
- if ( strcmp( Abc_ObjName(pNode), pName ) == 0 )
- return pNode;
- }
- return NULL;
-}
-
-/**Function*************************************************************
-
- Synopsis [Returns the net with the given name.]
-
- Description []
-
- SideEffects []
-
- SeeAlso []
-
-***********************************************************************/
Abc_Obj_t * Abc_NtkFindNet( Abc_Ntk_t * pNtk, char * pName )
{
Abc_Obj_t * pNet;
+ int ObjId;
assert( Abc_NtkIsNetlist(pNtk) );
- if ( stmm_lookup( pNtk->tName2Net, pName, (char**)&pNet ) )
- return pNet;
- return NULL;
+ ObjId = Nm_ManFindIdByName( pNtk->pManName, pName, ABC_OBJ_NET );
+ if ( ObjId == -1 )
+ return NULL;
+ pNet = Abc_NtkObj( pNtk, ObjId );
+ return pNet;
}
/**Function*************************************************************
- Synopsis [Finds or creates the net.]
+ Synopsis [Returns CI with the given name.]
- Description []
-
- SideEffects []
+ Description []
+
+ SideEffects []
- SeeAlso []
+ SeeAlso []
***********************************************************************/
-Abc_Obj_t * Abc_NtkFindOrCreateNet( Abc_Ntk_t * pNtk, char * pName )
+Abc_Obj_t * Abc_NtkFindCi( Abc_Ntk_t * pNtk, char * pName )
{
- Abc_Obj_t * pNet;
- assert( Abc_NtkIsNetlist(pNtk) );
- if ( pNet = Abc_NtkFindNet( pNtk, pName ) )
- return pNet;
- // create a new net
- pNet = Abc_ObjAlloc( pNtk, ABC_OBJ_NET );
- pNet->pData = Abc_NtkRegisterName( pNtk, pName );
- Abc_ObjAdd( pNet );
- return pNet;
+ int Num;
+ assert( !Abc_NtkIsNetlist(pNtk) );
+ Num = Nm_ManFindIdByName( pNtk->pManName, pName, ABC_OBJ_PI );
+ if ( Num >= 0 )
+ return Abc_NtkObj( pNtk, Num );
+ Num = Nm_ManFindIdByName( pNtk->pManName, pName, ABC_OBJ_BO );
+ if ( Num >= 0 )
+ return Abc_NtkObj( pNtk, Num );
+ return NULL;
}
-
+
/**Function*************************************************************
- Synopsis [Create the new node.]
+ Synopsis [Returns CO with the given name.]
- Description []
-
- SideEffects []
+ Description []
+
+ SideEffects []
- SeeAlso []
+ SeeAlso []
***********************************************************************/
-Abc_Obj_t * Abc_NtkCreateNode( Abc_Ntk_t * pNtk )
+Abc_Obj_t * Abc_NtkFindCo( Abc_Ntk_t * pNtk, char * pName )
{
- Abc_Obj_t * pObj;
- pObj = Abc_ObjAlloc( pNtk, ABC_OBJ_NODE );
- Abc_ObjAdd( pObj );
- return pObj;
+ int Num;
+ assert( !Abc_NtkIsNetlist(pNtk) );
+ Num = Nm_ManFindIdByName( pNtk->pManName, pName, ABC_OBJ_PO );
+ if ( Num >= 0 )
+ return Abc_NtkObj( pNtk, Num );
+ Num = Nm_ManFindIdByName( pNtk->pManName, pName, ABC_OBJ_BI );
+ if ( Num >= 0 )
+ return Abc_NtkObj( pNtk, Num );
+ return NULL;
}
-
-/**Function*************************************************************
-
- Synopsis [Create the new node.]
-
- Description []
-
- SideEffects []
- SeeAlso []
-***********************************************************************/
-Abc_Obj_t * Abc_NtkCreatePi( Abc_Ntk_t * pNtk )
-{
- Abc_Obj_t * pObj;
- pObj = Abc_ObjAlloc( pNtk, ABC_OBJ_PI );
- Abc_ObjAdd( pObj );
- return pObj;
-}
-
/**Function*************************************************************
- Synopsis [Create the new node.]
+ Synopsis [Finds or creates the net.]
Description []
@@ -463,17 +555,23 @@ Abc_Obj_t * Abc_NtkCreatePi( Abc_Ntk_t * pNtk )
SeeAlso []
***********************************************************************/
-Abc_Obj_t * Abc_NtkCreatePo( Abc_Ntk_t * pNtk )
+Abc_Obj_t * Abc_NtkFindOrCreateNet( Abc_Ntk_t * pNtk, char * pName )
{
- Abc_Obj_t * pObj;
- pObj = Abc_ObjAlloc( pNtk, ABC_OBJ_PO );
- Abc_ObjAdd( pObj );
- return pObj;
+ Abc_Obj_t * pNet;
+ assert( Abc_NtkIsNetlist(pNtk) );
+ if ( pName && (pNet = Abc_NtkFindNet( pNtk, pName )) )
+ return pNet;
+//printf( "Creating net %s.\n", pName );
+ // create a new net
+ pNet = Abc_NtkCreateNet( pNtk );
+ if ( pName )
+ Nm_ManStoreIdName( pNtk->pManName, pNet->Id, pNet->Type, pName, NULL );
+ return pNet;
}
/**Function*************************************************************
- Synopsis [Create the new node.]
+ Synopsis [Creates constant 0 node.]
Description []
@@ -482,17 +580,27 @@ Abc_Obj_t * Abc_NtkCreatePo( Abc_Ntk_t * pNtk )
SeeAlso []
***********************************************************************/
-Abc_Obj_t * Abc_NtkCreateLatch( Abc_Ntk_t * pNtk )
+Abc_Obj_t * Abc_NtkCreateNodeConst0( Abc_Ntk_t * pNtk )
{
- Abc_Obj_t * pObj;
- pObj = Abc_ObjAlloc( pNtk, ABC_OBJ_LATCH );
- Abc_ObjAdd( pObj );
- return pObj;
+ Abc_Obj_t * pNode;
+ assert( Abc_NtkIsLogic(pNtk) || Abc_NtkIsNetlist(pNtk) );
+ pNode = Abc_NtkCreateNode( pNtk );
+ if ( Abc_NtkHasSop(pNtk) || Abc_NtkHasBlifMv(pNtk) )
+ pNode->pData = Abc_SopRegister( pNtk->pManFunc, " 0\n" );
+ else if ( Abc_NtkHasBdd(pNtk) )
+ pNode->pData = Cudd_ReadLogicZero(pNtk->pManFunc), Cudd_Ref( pNode->pData );
+ else if ( Abc_NtkHasAig(pNtk) )
+ pNode->pData = Hop_ManConst0(pNtk->pManFunc);
+ else if ( Abc_NtkHasMapping(pNtk) )
+ pNode->pData = Mio_LibraryReadConst0(Abc_FrameReadLibGen());
+ else if ( !Abc_NtkHasBlackbox(pNtk) )
+ assert( 0 );
+ return pNode;
}
/**Function*************************************************************
- Synopsis [Creates inverter.]
+ Synopsis [Creates constant 1 node.]
Description []
@@ -501,18 +609,20 @@ Abc_Obj_t * Abc_NtkCreateLatch( Abc_Ntk_t * pNtk )
SeeAlso []
***********************************************************************/
-Abc_Obj_t * Abc_NodeCreateConst0( Abc_Ntk_t * pNtk )
+Abc_Obj_t * Abc_NtkCreateNodeConst1( Abc_Ntk_t * pNtk )
{
Abc_Obj_t * pNode;
- assert( !Abc_NtkHasAig(pNtk) );
+ assert( Abc_NtkIsLogic(pNtk) || Abc_NtkIsNetlist(pNtk) );
pNode = Abc_NtkCreateNode( pNtk );
- if ( Abc_NtkHasSop(pNtk) )
- pNode->pData = Abc_SopRegister( pNtk->pManFunc, " 0\n" );
+ if ( Abc_NtkHasSop(pNtk) || Abc_NtkHasBlifMv(pNtk) )
+ pNode->pData = Abc_SopRegister( pNtk->pManFunc, " 1\n" );
else if ( Abc_NtkHasBdd(pNtk) )
- pNode->pData = Cudd_ReadLogicZero(pNtk->pManFunc), Cudd_Ref( pNode->pData );
+ pNode->pData = Cudd_ReadOne(pNtk->pManFunc), Cudd_Ref( pNode->pData );
+ else if ( Abc_NtkHasAig(pNtk) )
+ pNode->pData = Hop_ManConst1(pNtk->pManFunc);
else if ( Abc_NtkHasMapping(pNtk) )
- pNode->pData = Mio_LibraryReadConst0(Abc_FrameReadLibGen(Abc_FrameGetGlobalFrame()));
- else
+ pNode->pData = Mio_LibraryReadConst1(Abc_FrameReadLibGen());
+ else if ( !Abc_NtkHasBlackbox(pNtk) )
assert( 0 );
return pNode;
}
@@ -528,18 +638,20 @@ Abc_Obj_t * Abc_NodeCreateConst0( Abc_Ntk_t * pNtk )
SeeAlso []
***********************************************************************/
-Abc_Obj_t * Abc_NodeCreateConst1( Abc_Ntk_t * pNtk )
+Abc_Obj_t * Abc_NtkCreateNodeInv( Abc_Ntk_t * pNtk, Abc_Obj_t * pFanin )
{
Abc_Obj_t * pNode;
- if ( Abc_NtkHasAig(pNtk) )
- return Abc_AigConst1(pNtk->pManFunc);
+ assert( Abc_NtkIsLogic(pNtk) || Abc_NtkIsNetlist(pNtk) );
pNode = Abc_NtkCreateNode( pNtk );
+ if ( pFanin ) Abc_ObjAddFanin( pNode, pFanin );
if ( Abc_NtkHasSop(pNtk) )
- pNode->pData = Abc_SopRegister( pNtk->pManFunc, " 1\n" );
+ pNode->pData = Abc_SopRegister( pNtk->pManFunc, "0 1\n" );
else if ( Abc_NtkHasBdd(pNtk) )
- pNode->pData = Cudd_ReadOne(pNtk->pManFunc), Cudd_Ref( pNode->pData );
+ pNode->pData = Cudd_Not(Cudd_bddIthVar(pNtk->pManFunc,0)), Cudd_Ref( pNode->pData );
+ else if ( Abc_NtkHasAig(pNtk) )
+ pNode->pData = Hop_Not(Hop_IthVar(pNtk->pManFunc,0));
else if ( Abc_NtkHasMapping(pNtk) )
- pNode->pData = Mio_LibraryReadConst1(Abc_FrameReadLibGen(Abc_FrameGetGlobalFrame()));
+ pNode->pData = Mio_LibraryReadInv(Abc_FrameReadLibGen());
else
assert( 0 );
return pNode;
@@ -547,7 +659,7 @@ Abc_Obj_t * Abc_NodeCreateConst1( Abc_Ntk_t * pNtk )
/**Function*************************************************************
- Synopsis [Creates inverter.]
+ Synopsis [Creates buffer.]
Description []
@@ -556,18 +668,20 @@ Abc_Obj_t * Abc_NodeCreateConst1( Abc_Ntk_t * pNtk )
SeeAlso []
***********************************************************************/
-Abc_Obj_t * Abc_NodeCreateInv( Abc_Ntk_t * pNtk, Abc_Obj_t * pFanin )
+Abc_Obj_t * Abc_NtkCreateNodeBuf( Abc_Ntk_t * pNtk, Abc_Obj_t * pFanin )
{
Abc_Obj_t * pNode;
assert( Abc_NtkIsLogic(pNtk) || Abc_NtkIsNetlist(pNtk) );
- pNode = Abc_NtkCreateNode( pNtk );
- Abc_ObjAddFanin( pNode, pFanin );
+ pNode = Abc_NtkCreateNode( pNtk );
+ if ( pFanin ) Abc_ObjAddFanin( pNode, pFanin );
if ( Abc_NtkHasSop(pNtk) )
- pNode->pData = Abc_SopRegister( pNtk->pManFunc, "0 1\n" );
+ pNode->pData = Abc_SopRegister( pNtk->pManFunc, "1 1\n" );
else if ( Abc_NtkHasBdd(pNtk) )
- pNode->pData = Cudd_Not(Cudd_bddIthVar(pNtk->pManFunc,0)), Cudd_Ref( pNode->pData );
+ pNode->pData = Cudd_bddIthVar(pNtk->pManFunc,0), Cudd_Ref( pNode->pData );
+ else if ( Abc_NtkHasAig(pNtk) )
+ pNode->pData = Hop_IthVar(pNtk->pManFunc,0);
else if ( Abc_NtkHasMapping(pNtk) )
- pNode->pData = Mio_LibraryReadInv(Abc_FrameReadLibGen(Abc_FrameGetGlobalFrame()));
+ pNode->pData = Mio_LibraryReadBuf(Abc_FrameReadLibGen());
else
assert( 0 );
return pNode;
@@ -575,7 +689,7 @@ Abc_Obj_t * Abc_NodeCreateInv( Abc_Ntk_t * pNtk, Abc_Obj_t * pFanin )
/**Function*************************************************************
- Synopsis [Creates buffer.]
+ Synopsis [Creates AND.]
Description []
@@ -584,18 +698,20 @@ Abc_Obj_t * Abc_NodeCreateInv( Abc_Ntk_t * pNtk, Abc_Obj_t * pFanin )
SeeAlso []
***********************************************************************/
-Abc_Obj_t * Abc_NodeCreateBuf( Abc_Ntk_t * pNtk, Abc_Obj_t * pFanin )
+Abc_Obj_t * Abc_NtkCreateNodeAnd( Abc_Ntk_t * pNtk, Vec_Ptr_t * vFanins )
{
Abc_Obj_t * pNode;
+ int i;
assert( Abc_NtkIsLogic(pNtk) || Abc_NtkIsNetlist(pNtk) );
pNode = Abc_NtkCreateNode( pNtk );
- Abc_ObjAddFanin( pNode, pFanin );
+ for ( i = 0; i < vFanins->nSize; i++ )
+ Abc_ObjAddFanin( pNode, vFanins->pArray[i] );
if ( Abc_NtkHasSop(pNtk) )
- pNode->pData = Abc_SopRegister( pNtk->pManFunc, "1 1\n" );
+ pNode->pData = Abc_SopCreateAnd( pNtk->pManFunc, Vec_PtrSize(vFanins), NULL );
else if ( Abc_NtkHasBdd(pNtk) )
- pNode->pData = Cudd_bddIthVar(pNtk->pManFunc,0), Cudd_Ref( pNode->pData );
- else if ( Abc_NtkHasMapping(pNtk) )
- pNode->pData = Mio_LibraryReadBuf(Abc_FrameReadLibGen(Abc_FrameGetGlobalFrame()));
+ pNode->pData = Extra_bddCreateAnd( pNtk->pManFunc, Vec_PtrSize(vFanins) ), Cudd_Ref(pNode->pData);
+ else if ( Abc_NtkHasAig(pNtk) )
+ pNode->pData = Hop_CreateAnd( pNtk->pManFunc, Vec_PtrSize(vFanins) );
else
assert( 0 );
return pNode;
@@ -603,7 +719,7 @@ Abc_Obj_t * Abc_NodeCreateBuf( Abc_Ntk_t * pNtk, Abc_Obj_t * pFanin )
/**Function*************************************************************
- Synopsis [Creates inverter.]
+ Synopsis [Creates OR.]
Description []
@@ -612,39 +728,20 @@ Abc_Obj_t * Abc_NodeCreateBuf( Abc_Ntk_t * pNtk, Abc_Obj_t * pFanin )
SeeAlso []
***********************************************************************/
-Abc_Obj_t * Abc_NodeCreateAnd( Abc_Ntk_t * pNtk, Vec_Ptr_t * vFanins )
+Abc_Obj_t * Abc_NtkCreateNodeOr( Abc_Ntk_t * pNtk, Vec_Ptr_t * vFanins )
{
Abc_Obj_t * pNode;
int i;
- assert( Abc_NtkIsLogic(pNtk) );
+ assert( Abc_NtkIsLogic(pNtk) || Abc_NtkIsNetlist(pNtk) );
pNode = Abc_NtkCreateNode( pNtk );
for ( i = 0; i < vFanins->nSize; i++ )
Abc_ObjAddFanin( pNode, vFanins->pArray[i] );
if ( Abc_NtkHasSop(pNtk) )
- {
- char * pSop;
- pSop = Extra_MmFlexEntryFetch( pNtk->pManFunc, vFanins->nSize + 4 );
- for ( i = 0; i < vFanins->nSize; i++ )
- pSop[i] = '1';
- pSop[i++] = ' ';
- pSop[i++] = '1';
- pSop[i++] = '\n';
- pSop[i++] = 0;
- assert( i == vFanins->nSize + 4 );
- pNode->pData = pSop;
- }
+ pNode->pData = Abc_SopCreateOr( pNtk->pManFunc, Vec_PtrSize(vFanins), NULL );
else if ( Abc_NtkHasBdd(pNtk) )
- {
- DdManager * dd = pNtk->pManFunc;
- DdNode * bFunc, * bTemp;
- bFunc = Cudd_ReadOne(dd); Cudd_Ref( bFunc );
- for ( i = 0; i < vFanins->nSize; i++ )
- {
- bFunc = Cudd_bddAnd( dd, bTemp = bFunc, Cudd_bddIthVar(pNtk->pManFunc,i) ); Cudd_Ref( bFunc );
- Cudd_RecursiveDeref( dd, bTemp );
- }
- pNode->pData = bFunc;
- }
+ pNode->pData = Extra_bddCreateOr( pNtk->pManFunc, Vec_PtrSize(vFanins) ), Cudd_Ref(pNode->pData);
+ else if ( Abc_NtkHasAig(pNtk) )
+ pNode->pData = Hop_CreateOr( pNtk->pManFunc, Vec_PtrSize(vFanins) );
else
assert( 0 );
return pNode;
@@ -652,7 +749,7 @@ Abc_Obj_t * Abc_NodeCreateAnd( Abc_Ntk_t * pNtk, Vec_Ptr_t * vFanins )
/**Function*************************************************************
- Synopsis [Creates inverter.]
+ Synopsis [Creates EXOR.]
Description []
@@ -661,39 +758,20 @@ Abc_Obj_t * Abc_NodeCreateAnd( Abc_Ntk_t * pNtk, Vec_Ptr_t * vFanins )
SeeAlso []
***********************************************************************/
-Abc_Obj_t * Abc_NodeCreateOr( Abc_Ntk_t * pNtk, Vec_Ptr_t * vFanins )
+Abc_Obj_t * Abc_NtkCreateNodeExor( Abc_Ntk_t * pNtk, Vec_Ptr_t * vFanins )
{
Abc_Obj_t * pNode;
int i;
- assert( Abc_NtkIsLogic(pNtk) );
+ assert( Abc_NtkIsLogic(pNtk) || Abc_NtkIsNetlist(pNtk) );
pNode = Abc_NtkCreateNode( pNtk );
for ( i = 0; i < vFanins->nSize; i++ )
Abc_ObjAddFanin( pNode, vFanins->pArray[i] );
if ( Abc_NtkHasSop(pNtk) )
- {
- char * pSop;
- pSop = Extra_MmFlexEntryFetch( pNtk->pManFunc, vFanins->nSize + 4 );
- for ( i = 0; i < vFanins->nSize; i++ )
- pSop[i] = '0';
- pSop[i++] = ' ';
- pSop[i++] = '0';
- pSop[i++] = '\n';
- pSop[i++] = 0;
- assert( i == vFanins->nSize + 4 );
- pNode->pData = pSop;
- }
+ pNode->pData = Abc_SopCreateXorSpecial( pNtk->pManFunc, Vec_PtrSize(vFanins) );
else if ( Abc_NtkHasBdd(pNtk) )
- {
- DdManager * dd = pNtk->pManFunc;
- DdNode * bFunc, * bTemp;
- bFunc = Cudd_ReadLogicZero(dd); Cudd_Ref( bFunc );
- for ( i = 0; i < vFanins->nSize; i++ )
- {
- bFunc = Cudd_bddOr( dd, bTemp = bFunc, Cudd_bddIthVar(pNtk->pManFunc,i) ); Cudd_Ref( bFunc );
- Cudd_RecursiveDeref( dd, bTemp );
- }
- pNode->pData = bFunc;
- }
+ pNode->pData = Extra_bddCreateExor( pNtk->pManFunc, Vec_PtrSize(vFanins) ), Cudd_Ref(pNode->pData);
+ else if ( Abc_NtkHasAig(pNtk) )
+ pNode->pData = Hop_CreateExor( pNtk->pManFunc, Vec_PtrSize(vFanins) );
else
assert( 0 );
return pNode;
@@ -701,7 +779,7 @@ Abc_Obj_t * Abc_NodeCreateOr( Abc_Ntk_t * pNtk, Vec_Ptr_t * vFanins )
/**Function*************************************************************
- Synopsis [Creates inverter.]
+ Synopsis [Creates MUX.]
Description []
@@ -710,7 +788,7 @@ Abc_Obj_t * Abc_NodeCreateOr( Abc_Ntk_t * pNtk, Vec_Ptr_t * vFanins )
SeeAlso []
***********************************************************************/
-Abc_Obj_t * Abc_NodeCreateMux( Abc_Ntk_t * pNtk, Abc_Obj_t * pNodeC, Abc_Obj_t * pNode1, Abc_Obj_t * pNode0 )
+Abc_Obj_t * Abc_NtkCreateNodeMux( Abc_Ntk_t * pNtk, Abc_Obj_t * pNodeC, Abc_Obj_t * pNode1, Abc_Obj_t * pNode0 )
{
Abc_Obj_t * pNode;
assert( Abc_NtkIsLogic(pNtk) );
@@ -722,14 +800,17 @@ Abc_Obj_t * Abc_NodeCreateMux( Abc_Ntk_t * pNtk, Abc_Obj_t * pNodeC, Abc_Obj_t *
pNode->pData = Abc_SopRegister( pNtk->pManFunc, "11- 1\n0-1 1\n" );
else if ( Abc_NtkHasBdd(pNtk) )
pNode->pData = Cudd_bddIte(pNtk->pManFunc,Cudd_bddIthVar(pNtk->pManFunc,0),Cudd_bddIthVar(pNtk->pManFunc,1),Cudd_bddIthVar(pNtk->pManFunc,2)), Cudd_Ref( pNode->pData );
+ else if ( Abc_NtkHasAig(pNtk) )
+ pNode->pData = Hop_Mux(pNtk->pManFunc,Hop_IthVar(pNtk->pManFunc,0),Hop_IthVar(pNtk->pManFunc,1),Hop_IthVar(pNtk->pManFunc,2));
else
assert( 0 );
return pNode;
}
+
/**Function*************************************************************
- Synopsis [Clones the given node but does not assign the function.]
+ Synopsis [Returns 1 if the node is a constant 0 node.]
Description []
@@ -738,22 +819,15 @@ Abc_Obj_t * Abc_NodeCreateMux( Abc_Ntk_t * pNtk, Abc_Obj_t * pNodeC, Abc_Obj_t *
SeeAlso []
***********************************************************************/
-Abc_Obj_t * Abc_NodeClone( Abc_Obj_t * pNode )
-{
- Abc_Obj_t * pClone, * pFanin;
- int i;
- assert( Abc_ObjIsNode(pNode) );
- pClone = Abc_NtkCreateNode( pNode->pNtk );
- Abc_ObjForEachFanin( pNode, pFanin, i )
- Abc_ObjAddFanin( pClone, pFanin );
- return pClone;
+bool Abc_NodeIsConst( Abc_Obj_t * pNode )
+{
+ assert( Abc_NtkIsLogic(pNode->pNtk) || Abc_NtkIsNetlist(pNode->pNtk) );
+ return Abc_ObjIsNode(pNode) && Abc_ObjFaninNum(pNode) == 0;
}
-
-
/**Function*************************************************************
- Synopsis []
+ Synopsis [Returns 1 if the node is a constant 0 node.]
Description []
@@ -765,23 +839,25 @@ Abc_Obj_t * Abc_NodeClone( Abc_Obj_t * pNode )
bool Abc_NodeIsConst0( Abc_Obj_t * pNode )
{
Abc_Ntk_t * pNtk = pNode->pNtk;
- assert(Abc_ObjIsNode(pNode));
- assert(Abc_NodeIsConst(pNode));
+ assert( Abc_NtkIsLogic(pNtk) || Abc_NtkIsNetlist(pNtk) );
+ assert( Abc_ObjIsNode(pNode) );
+ if ( !Abc_NodeIsConst(pNode) )
+ return 0;
if ( Abc_NtkHasSop(pNtk) )
return Abc_SopIsConst0(pNode->pData);
if ( Abc_NtkHasBdd(pNtk) )
return Cudd_IsComplement(pNode->pData);
if ( Abc_NtkHasAig(pNtk) )
- return Abc_ObjNot(pNode) == Abc_AigConst1(pNode->pNtk->pManFunc);
+ return Hop_IsComplement(pNode->pData);
if ( Abc_NtkHasMapping(pNtk) )
- return pNode->pData == Mio_LibraryReadConst0(Abc_FrameReadLibSuper(Abc_FrameGetGlobalFrame()));
+ return pNode->pData == Mio_LibraryReadConst0(Abc_FrameReadLibGen());
assert( 0 );
return 0;
}
/**Function*************************************************************
- Synopsis []
+ Synopsis [Returns 1 if the node is a constant 1 node.]
Description []
@@ -793,23 +869,25 @@ bool Abc_NodeIsConst0( Abc_Obj_t * pNode )
bool Abc_NodeIsConst1( Abc_Obj_t * pNode )
{
Abc_Ntk_t * pNtk = pNode->pNtk;
- assert(Abc_ObjIsNode(pNode));
- assert(Abc_NodeIsConst(pNode));
+ assert( Abc_NtkIsLogic(pNtk) || Abc_NtkIsNetlist(pNtk) );
+ assert( Abc_ObjIsNode(pNode) );
+ if ( !Abc_NodeIsConst(pNode) )
+ return 0;
if ( Abc_NtkHasSop(pNtk) )
return Abc_SopIsConst1(pNode->pData);
if ( Abc_NtkHasBdd(pNtk) )
return !Cudd_IsComplement(pNode->pData);
if ( Abc_NtkHasAig(pNtk) )
- return pNode == Abc_AigConst1(pNode->pNtk->pManFunc);
+ return !Hop_IsComplement(pNode->pData);
if ( Abc_NtkHasMapping(pNtk) )
- return pNode->pData == Mio_LibraryReadConst1(Abc_FrameReadLibSuper(Abc_FrameGetGlobalFrame()));
+ return pNode->pData == Mio_LibraryReadConst1(Abc_FrameReadLibGen());
assert( 0 );
return 0;
}
/**Function*************************************************************
- Synopsis []
+ Synopsis [Returns 1 if the node is a buffer.]
Description []
@@ -821,7 +899,8 @@ bool Abc_NodeIsConst1( Abc_Obj_t * pNode )
bool Abc_NodeIsBuf( Abc_Obj_t * pNode )
{
Abc_Ntk_t * pNtk = pNode->pNtk;
- assert(Abc_ObjIsNode(pNode));
+ assert( Abc_NtkIsLogic(pNtk) || Abc_NtkIsNetlist(pNtk) );
+ assert( Abc_ObjIsNode(pNode) );
if ( Abc_ObjFaninNum(pNode) != 1 )
return 0;
if ( Abc_NtkHasSop(pNtk) )
@@ -829,16 +908,16 @@ bool Abc_NodeIsBuf( Abc_Obj_t * pNode )
if ( Abc_NtkHasBdd(pNtk) )
return !Cudd_IsComplement(pNode->pData);
if ( Abc_NtkHasAig(pNtk) )
- return 0;
+ return !Hop_IsComplement(pNode->pData);
if ( Abc_NtkHasMapping(pNtk) )
- return pNode->pData == Mio_LibraryReadBuf(Abc_FrameReadLibSuper(Abc_FrameGetGlobalFrame()));
+ return pNode->pData == Mio_LibraryReadBuf(Abc_FrameReadLibGen());
assert( 0 );
return 0;
}
/**Function*************************************************************
- Synopsis []
+ Synopsis [Returns 1 if the node is an inverter.]
Description []
@@ -850,7 +929,8 @@ bool Abc_NodeIsBuf( Abc_Obj_t * pNode )
bool Abc_NodeIsInv( Abc_Obj_t * pNode )
{
Abc_Ntk_t * pNtk = pNode->pNtk;
- assert(Abc_ObjIsNode(pNode));
+ assert( Abc_NtkIsLogic(pNtk) || Abc_NtkIsNetlist(pNtk) );
+ assert( Abc_ObjIsNode(pNode) );
if ( Abc_ObjFaninNum(pNode) != 1 )
return 0;
if ( Abc_NtkHasSop(pNtk) )
@@ -858,13 +938,38 @@ bool Abc_NodeIsInv( Abc_Obj_t * pNode )
if ( Abc_NtkHasBdd(pNtk) )
return Cudd_IsComplement(pNode->pData);
if ( Abc_NtkHasAig(pNtk) )
- return 0;
+ return Hop_IsComplement(pNode->pData);
if ( Abc_NtkHasMapping(pNtk) )
- return pNode->pData == Mio_LibraryReadInv(Abc_FrameReadLibSuper(Abc_FrameGetGlobalFrame()));
+ return pNode->pData == Mio_LibraryReadInv(Abc_FrameReadLibGen());
assert( 0 );
return 0;
}
+/**Function*************************************************************
+
+ Synopsis [Complements the local functions of the node.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Abc_NodeComplement( Abc_Obj_t * pNode )
+{
+ assert( Abc_NtkIsLogic(pNode->pNtk) || Abc_NtkIsNetlist(pNode->pNtk) );
+ assert( Abc_ObjIsNode(pNode) );
+ if ( Abc_NtkHasSop(pNode->pNtk) )
+ Abc_SopComplement( pNode->pData );
+ else if ( Abc_NtkHasBdd(pNode->pNtk) )
+ pNode->pData = Cudd_Not( pNode->pData );
+ else if ( Abc_NtkHasAig(pNode->pNtk) )
+ pNode->pData = Hop_Not( pNode->pData );
+ else
+ assert( 0 );
+}
+
////////////////////////////////////////////////////////////////////////
/// END OF FILE ///
////////////////////////////////////////////////////////////////////////
diff --git a/src/base/abc/abcRefs.c b/src/base/abc/abcRefs.c
index 47618bf4..604c5ffa 100644
--- a/src/base/abc/abcRefs.c
+++ b/src/base/abc/abcRefs.c
@@ -24,11 +24,11 @@
/// DECLARATIONS ///
////////////////////////////////////////////////////////////////////////
-static int Abc_NodeRefDeref( Abc_Obj_t * pNode, bool fReference, bool fLabel, Vec_Ptr_t * vNodes );
+static int Abc_NodeRefDeref( Abc_Obj_t * pNode, bool fReference, bool fLabel );
static int Abc_NodeRefDerefStop( Abc_Obj_t * pNode, bool fReference );
////////////////////////////////////////////////////////////////////////
-/// FUNCTION DEFITIONS ///
+/// FUNCTION DEFINITIONS ///
////////////////////////////////////////////////////////////////////////
/**Function*************************************************************
@@ -45,12 +45,13 @@ static int Abc_NodeRefDerefStop( Abc_Obj_t * pNode, bool fReference );
int Abc_NodeMffcSize( Abc_Obj_t * pNode )
{
int nConeSize1, nConeSize2;
- assert( !Abc_ObjIsComplement( pNode ) );
+// assert( Abc_NtkIsStrash(pNode->pNtk) );
+// assert( !Abc_ObjIsComplement( pNode ) );
assert( Abc_ObjIsNode( pNode ) );
if ( Abc_ObjFaninNum(pNode) == 0 )
return 0;
- nConeSize1 = Abc_NodeRefDeref( pNode, 0, 0, NULL ); // dereference
- nConeSize2 = Abc_NodeRefDeref( pNode, 1, 0, NULL ); // reference
+ nConeSize1 = Abc_NodeRefDeref( pNode, 0, 0 ); // dereference
+ nConeSize2 = Abc_NodeRefDeref( pNode, 1, 0 ); // reference
assert( nConeSize1 == nConeSize2 );
assert( nConeSize1 > 0 );
return nConeSize1;
@@ -70,6 +71,7 @@ int Abc_NodeMffcSize( Abc_Obj_t * pNode )
int Abc_NodeMffcSizeStop( Abc_Obj_t * pNode )
{
int nConeSize1, nConeSize2;
+ assert( Abc_NtkIsStrash(pNode->pNtk) );
assert( !Abc_ObjIsComplement( pNode ) );
assert( Abc_ObjIsNode( pNode ) );
if ( Abc_ObjFaninNum(pNode) == 0 )
@@ -92,15 +94,16 @@ int Abc_NodeMffcSizeStop( Abc_Obj_t * pNode )
SeeAlso []
***********************************************************************/
-int Abc_NodeMffcLabel( Abc_Obj_t * pNode )
+int Abc_NodeMffcLabelAig( Abc_Obj_t * pNode )
{
int nConeSize1, nConeSize2;
+ assert( Abc_NtkIsStrash(pNode->pNtk) );
assert( !Abc_ObjIsComplement( pNode ) );
assert( Abc_ObjIsNode( pNode ) );
if ( Abc_ObjFaninNum(pNode) == 0 )
return 0;
- nConeSize1 = Abc_NodeRefDeref( pNode, 0, 1, NULL ); // dereference
- nConeSize2 = Abc_NodeRefDeref( pNode, 1, 0, NULL ); // reference
+ nConeSize1 = Abc_NodeRefDeref( pNode, 0, 1 ); // dereference
+ nConeSize2 = Abc_NodeRefDeref( pNode, 1, 0 ); // reference
assert( nConeSize1 == nConeSize2 );
assert( nConeSize1 > 0 );
return nConeSize1;
@@ -108,33 +111,6 @@ int Abc_NodeMffcLabel( Abc_Obj_t * pNode )
/**Function*************************************************************
- Synopsis [Collects the nodes in MFFC in the topological order.]
-
- Description []
-
- SideEffects []
-
- SeeAlso []
-
-***********************************************************************/
-Vec_Ptr_t * Abc_NodeMffcCollect( Abc_Obj_t * pNode )
-{
- Vec_Ptr_t * vNodes;
- int nConeSize1, nConeSize2;
- assert( !Abc_ObjIsComplement( pNode ) );
- assert( Abc_ObjIsNode( pNode ) );
- vNodes = Vec_PtrAlloc( 8 );
- if ( Abc_ObjFaninNum(pNode) == 0 )
- return vNodes;
- nConeSize1 = Abc_NodeRefDeref( pNode, 0, 0, vNodes ); // dereference
- nConeSize2 = Abc_NodeRefDeref( pNode, 1, 0, NULL ); // reference
- assert( nConeSize1 == nConeSize2 );
- assert( nConeSize1 > 0 );
- return vNodes;
-}
-
-/**Function*************************************************************
-
Synopsis [References/references the node and returns MFFC size.]
Description []
@@ -144,16 +120,13 @@ Vec_Ptr_t * Abc_NodeMffcCollect( Abc_Obj_t * pNode )
SeeAlso []
***********************************************************************/
-int Abc_NodeRefDeref( Abc_Obj_t * pNode, bool fReference, bool fLabel, Vec_Ptr_t * vNodes )
+int Abc_NodeRefDeref( Abc_Obj_t * pNode, bool fReference, bool fLabel )
{
Abc_Obj_t * pNode0, * pNode1;
int Counter;
// label visited nodes
if ( fLabel )
Abc_NodeSetTravIdCurrent( pNode );
- // collect visited nodes
- if ( vNodes )
- Vec_PtrPush( vNodes, pNode );
// skip the CI
if ( Abc_ObjIsCi(pNode) )
return 0;
@@ -164,22 +137,23 @@ int Abc_NodeRefDeref( Abc_Obj_t * pNode, bool fReference, bool fLabel, Vec_Ptr_t
if ( fReference )
{
if ( pNode0->vFanouts.nSize++ == 0 )
- Counter += Abc_NodeRefDeref( pNode0, fReference, fLabel, vNodes );
+ Counter += Abc_NodeRefDeref( pNode0, fReference, fLabel );
if ( pNode1->vFanouts.nSize++ == 0 )
- Counter += Abc_NodeRefDeref( pNode1, fReference, fLabel, vNodes );
+ Counter += Abc_NodeRefDeref( pNode1, fReference, fLabel );
}
else
{
assert( pNode0->vFanouts.nSize > 0 );
assert( pNode1->vFanouts.nSize > 0 );
if ( --pNode0->vFanouts.nSize == 0 )
- Counter += Abc_NodeRefDeref( pNode0, fReference, fLabel, vNodes );
+ Counter += Abc_NodeRefDeref( pNode0, fReference, fLabel );
if ( --pNode1->vFanouts.nSize == 0 )
- Counter += Abc_NodeRefDeref( pNode1, fReference, fLabel, vNodes );
+ Counter += Abc_NodeRefDeref( pNode1, fReference, fLabel );
}
return Counter;
}
+
/**Function*************************************************************
Synopsis [References/references the node and returns MFFC size.]
@@ -221,6 +195,256 @@ int Abc_NodeRefDerefStop( Abc_Obj_t * pNode, bool fReference )
return Counter;
}
+
+
+
+/**Function*************************************************************
+
+ Synopsis [Dereferences the node's MFFC.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Abc_NodeDeref_rec( Abc_Obj_t * pNode )
+{
+ Abc_Obj_t * pFanin;
+ int i, Counter = 1;
+ if ( Abc_ObjIsCi(pNode) )
+ return 0;
+ Abc_ObjForEachFanin( pNode, pFanin, i )
+ {
+ assert( pFanin->vFanouts.nSize > 0 );
+ if ( --pFanin->vFanouts.nSize == 0 )
+ Counter += Abc_NodeDeref_rec( pFanin );
+ }
+ return Counter;
+}
+
+/**Function*************************************************************
+
+ Synopsis [References the node's MFFC.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Abc_NodeRef_rec( Abc_Obj_t * pNode )
+{
+ Abc_Obj_t * pFanin;
+ int i, Counter = 1;
+ if ( Abc_ObjIsCi(pNode) )
+ return 0;
+ Abc_ObjForEachFanin( pNode, pFanin, i )
+ {
+ if ( pFanin->vFanouts.nSize++ == 0 )
+ Counter += Abc_NodeRef_rec( pFanin );
+ }
+ return Counter;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Collects the internal and boundary nodes in the derefed MFFC.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Abc_NodeMffsConeSupp_rec( Abc_Obj_t * pNode, Vec_Ptr_t * vCone, Vec_Ptr_t * vSupp, int fTopmost )
+{
+ Abc_Obj_t * pFanin;
+ int i;
+ // skip visited nodes
+ if ( Abc_NodeIsTravIdCurrent(pNode) )
+ return;
+ Abc_NodeSetTravIdCurrent(pNode);
+ // add to the new support nodes
+ if ( !fTopmost && (Abc_ObjIsCi(pNode) || pNode->vFanouts.nSize > 0) )
+ {
+ if ( vSupp ) Vec_PtrPush( vSupp, pNode );
+ return;
+ }
+ // recur on the children
+ Abc_ObjForEachFanin( pNode, pFanin, i )
+ Abc_NodeMffsConeSupp_rec( pFanin, vCone, vSupp, 0 );
+ // collect the internal node
+ if ( vCone ) Vec_PtrPush( vCone, pNode );
+// printf( "%d ", pNode->Id );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Collects the support of the derefed MFFC.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Abc_NodeMffsConeSupp( Abc_Obj_t * pNode, Vec_Ptr_t * vCone, Vec_Ptr_t * vSupp )
+{
+ assert( Abc_ObjIsNode(pNode) );
+ assert( !Abc_ObjIsComplement(pNode) );
+ if ( vCone ) Vec_PtrClear( vCone );
+ if ( vSupp ) Vec_PtrClear( vSupp );
+ Abc_NtkIncrementTravId( pNode->pNtk );
+ Abc_NodeMffsConeSupp_rec( pNode, vCone, vSupp, 1 );
+// printf( "\n" );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Collects the support of the derefed MFFC.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Abc_NodeMffsConeSuppPrint( Abc_Obj_t * pNode )
+{
+ Vec_Ptr_t * vCone, * vSupp;
+ Abc_Obj_t * pObj;
+ int i;
+ vCone = Vec_PtrAlloc( 100 );
+ vSupp = Vec_PtrAlloc( 100 );
+ Abc_NodeDeref_rec( pNode );
+ Abc_NodeMffsConeSupp( pNode, vCone, vSupp );
+ Abc_NodeRef_rec( pNode );
+ printf( "Node = %6s : Supp = %3d Cone = %3d (",
+ Abc_ObjName(pNode), Vec_PtrSize(vSupp), Vec_PtrSize(vCone) );
+ Vec_PtrForEachEntry( vCone, pObj, i )
+ printf( " %s", Abc_ObjName(pObj) );
+ printf( " )\n" );
+ Vec_PtrFree( vCone );
+ Vec_PtrFree( vSupp );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Collects the internal nodes of the MFFC limited by cut.]
+
+ Description []
+
+ SideEffects [Increments the trav ID and marks visited nodes.]
+
+ SeeAlso []
+
+***********************************************************************/
+int Abc_NodeMffsInside( Abc_Obj_t * pNode, Vec_Ptr_t * vLeaves, Vec_Ptr_t * vInside )
+{
+ Abc_Obj_t * pObj;
+ int i, Count1, Count2;
+ // increment the fanout counters for the leaves
+ Vec_PtrForEachEntry( vLeaves, pObj, i )
+ pObj->vFanouts.nSize++;
+ // dereference the node
+ Count1 = Abc_NodeDeref_rec( pNode );
+ // collect the nodes inside the MFFC
+ Abc_NodeMffsConeSupp( pNode, vInside, NULL );
+ // reference it back
+ Count2 = Abc_NodeRef_rec( pNode );
+ assert( Count1 == Count2 );
+ // remove the extra counters
+ Vec_PtrForEachEntry( vLeaves, pObj, i )
+ pObj->vFanouts.nSize--;
+ return Count1;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Collects the internal nodes of the MFFC limited by cut.]
+
+ Description []
+
+ SideEffects [Increments the trav ID and marks visited nodes.]
+
+ SeeAlso []
+
+***********************************************************************/
+Vec_Ptr_t * Abc_NodeMffsInsideCollect( Abc_Obj_t * pNode )
+{
+ Vec_Ptr_t * vInside;
+ int Count1, Count2;
+ // dereference the node
+ Count1 = Abc_NodeDeref_rec( pNode );
+ // collect the nodes inside the MFFC
+ vInside = Vec_PtrAlloc( 10 );
+ Abc_NodeMffsConeSupp( pNode, vInside, NULL );
+ // reference it back
+ Count2 = Abc_NodeRef_rec( pNode );
+ assert( Count1 == Count2 );
+ return vInside;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Collects the internal and boundary nodes in the derefed MFFC.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Abc_NodeMffcLabel_rec( Abc_Obj_t * pNode, int fTopmost )
+{
+ Abc_Obj_t * pFanin;
+ int i;
+ // add to the new support nodes
+ if ( !fTopmost && (Abc_ObjIsCi(pNode) || pNode->vFanouts.nSize > 0) )
+ return;
+ // skip visited nodes
+ if ( Abc_NodeIsTravIdCurrent(pNode) )
+ return;
+ Abc_NodeSetTravIdCurrent(pNode);
+ // recur on the children
+ Abc_ObjForEachFanin( pNode, pFanin, i )
+ Abc_NodeMffcLabel_rec( pFanin, 0 );
+ // collect the internal node
+// printf( "%d ", pNode->Id );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Collects the internal nodes of the MFFC limited by cut.]
+
+ Description []
+
+ SideEffects [Increments the trav ID and marks visited nodes.]
+
+ SeeAlso []
+
+***********************************************************************/
+int Abc_NodeMffcLabel( Abc_Obj_t * pNode )
+{
+ int Count1, Count2;
+ // dereference the node
+ Count1 = Abc_NodeDeref_rec( pNode );
+ // collect the nodes inside the MFFC
+ Abc_NtkIncrementTravId( pNode->pNtk );
+ Abc_NodeMffcLabel_rec( pNode, 1 );
+ // reference it back
+ Count2 = Abc_NodeRef_rec( pNode );
+ assert( Count1 == Count2 );
+ return Count1;
+}
+
////////////////////////////////////////////////////////////////////////
/// END OF FILE ///
////////////////////////////////////////////////////////////////////////
diff --git a/src/base/abc/abcShow.c b/src/base/abc/abcShow.c
index 20a64246..40d1dcad 100644
--- a/src/base/abc/abcShow.c
+++ b/src/base/abc/abcShow.c
@@ -30,11 +30,11 @@
/// DECLARATIONS ///
////////////////////////////////////////////////////////////////////////
-static void Abc_ShowFile( char * FileNameDot );
+extern void Abc_ShowFile( char * FileNameDot );
static void Abc_ShowGetFileName( char * pName, char * pBuffer );
////////////////////////////////////////////////////////////////////////
-/// FUNCTION DEFITIONS ///
+/// FUNCTION DEFINITIONS ///
////////////////////////////////////////////////////////////////////////
/**Function*************************************************************
@@ -79,47 +79,6 @@ void Abc_NodeShowBdd( Abc_Obj_t * pNode )
/**Function*************************************************************
- Synopsis [Visualizes AIG with choices.]
-
- Description []
-
- SideEffects []
-
- SeeAlso []
-
-***********************************************************************/
-void Abc_NtkShowAig( Abc_Ntk_t * pNtk )
-{
- FILE * pFile;
- Abc_Obj_t * pNode;
- Vec_Ptr_t * vNodes;
- char FileNameDot[200];
- int i;
-
- assert( Abc_NtkIsStrash(pNtk) );
- // create the file name
- Abc_ShowGetFileName( pNtk->pName, FileNameDot );
- // check that the file can be opened
- if ( (pFile = fopen( FileNameDot, "w" )) == NULL )
- {
- fprintf( stdout, "Cannot open the intermediate file \"%s\".\n", FileNameDot );
- return;
- }
-
- // collect all nodes in the network
- vNodes = Vec_PtrAlloc( 100 );
- Abc_NtkForEachObj( pNtk, pNode, i )
- Vec_PtrPush( vNodes, pNode );
- // write the DOT file
- Io_WriteDot( pNtk, vNodes, NULL, FileNameDot );
- Vec_PtrFree( vNodes );
-
- // visualize the file
- Abc_ShowFile( FileNameDot );
-}
-
-/**Function*************************************************************
-
Synopsis [Visualizes a reconvergence driven cut at the node.]
Description []
@@ -170,7 +129,7 @@ void Abc_NodeShowCut( Abc_Obj_t * pNode, int nNodeSizeMax, int nConeSizeMax )
// add the root node to the cone (for visualization)
Vec_PtrPush( vCutSmall, pNode );
// write the DOT file
- Io_WriteDot( pNode->pNtk, vInside, vCutSmall, FileNameDot );
+ Io_WriteDotNtk( pNode->pNtk, vInside, vCutSmall, FileNameDot, 0, 0 );
// stop the cut computation manager
Abc_NtkManCutStop( p );
@@ -178,6 +137,59 @@ void Abc_NodeShowCut( Abc_Obj_t * pNode, int nNodeSizeMax, int nConeSizeMax )
Abc_ShowFile( FileNameDot );
}
+/**Function*************************************************************
+
+ Synopsis [Visualizes AIG with choices.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Abc_NtkShow( Abc_Ntk_t * pNtk, int fGateNames, int fSeq, int fUseReverse )
+{
+ FILE * pFile;
+ Abc_Obj_t * pNode;
+ Vec_Ptr_t * vNodes;
+ char FileNameDot[200];
+ int i;
+
+ assert( Abc_NtkIsStrash(pNtk) || Abc_NtkIsLogic(pNtk) );
+ if ( Abc_NtkIsStrash(pNtk) && Abc_NtkGetChoiceNum(pNtk) )
+ {
+ printf( "Temporarily visualization of AIGs with choice nodes is disabled.\n" );
+ return;
+ }
+ // convert to logic SOP
+ if ( Abc_NtkIsLogic(pNtk) )
+ Abc_NtkToSop( pNtk, 0 );
+ // create the file name
+ Abc_ShowGetFileName( pNtk->pName, FileNameDot );
+ // check that the file can be opened
+ if ( (pFile = fopen( FileNameDot, "w" )) == NULL )
+ {
+ fprintf( stdout, "Cannot open the intermediate file \"%s\".\n", FileNameDot );
+ return;
+ }
+ fclose( pFile );
+
+ // collect all nodes in the network
+ vNodes = Vec_PtrAlloc( 100 );
+ Abc_NtkForEachObj( pNtk, pNode, i )
+ Vec_PtrPush( vNodes, pNode );
+ // write the DOT file
+ if ( fSeq )
+ Io_WriteDotSeq( pNtk, vNodes, NULL, FileNameDot, fGateNames, fUseReverse );
+ else
+ Io_WriteDotNtk( pNtk, vNodes, NULL, FileNameDot, fGateNames, fUseReverse );
+ Vec_PtrFree( vNodes );
+
+ // visualize the file
+ Abc_ShowFile( FileNameDot );
+}
+
/**Function*************************************************************
diff --git a/src/base/abc/abcSop.c b/src/base/abc/abcSop.c
index 28e92889..106901ab 100644
--- a/src/base/abc/abcSop.c
+++ b/src/base/abc/abcSop.c
@@ -28,7 +28,7 @@
01- 1
1-1 1
- is the string: "01- 1/n1-1 1/n" where '/n' is a single char.
+ is the string: "01- 1\n1-1 1\n" where '\n' is a single char.
*/
////////////////////////////////////////////////////////////////////////
@@ -36,7 +36,7 @@
////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////
-/// FUNCTION DEFITIONS ///
+/// FUNCTION DEFINITIONS ///
////////////////////////////////////////////////////////////////////////
/**Function*************************************************************
@@ -61,7 +61,7 @@ char * Abc_SopRegister( Extra_MmFlex_t * pMan, char * pName )
/**Function*************************************************************
- Synopsis [Starts the constant 1 cover with the given number of variables and cubes.]
+ Synopsis [Creates the constant 1 cover with the given number of variables and cubes.]
Description []
@@ -92,7 +92,7 @@ char * Abc_SopStart( Extra_MmFlex_t * pMan, int nCubes, int nVars )
/**Function*************************************************************
- Synopsis [Starts the constant 1 cover with 0 variables.]
+ Synopsis [Creates the constant 1 cover with 0 variables.]
Description []
@@ -108,7 +108,7 @@ char * Abc_SopCreateConst1( Extra_MmFlex_t * pMan )
/**Function*************************************************************
- Synopsis [Starts the constant 1 cover with 0 variables.]
+ Synopsis [Creates the constant 1 cover with 0 variables.]
Description []
@@ -124,7 +124,7 @@ char * Abc_SopCreateConst0( Extra_MmFlex_t * pMan )
/**Function*************************************************************
- Synopsis [Starts the AND2 cover.]
+ Synopsis [Creates the AND2 cover.]
Description []
@@ -147,7 +147,7 @@ char * Abc_SopCreateAnd2( Extra_MmFlex_t * pMan, int fCompl0, int fCompl1 )
/**Function*************************************************************
- Synopsis [Starts the multi-input AND cover.]
+ Synopsis [Creates the multi-input AND cover.]
Description []
@@ -156,19 +156,20 @@ char * Abc_SopCreateAnd2( Extra_MmFlex_t * pMan, int fCompl0, int fCompl1 )
SeeAlso []
***********************************************************************/
-char * Abc_SopCreateAnd( Extra_MmFlex_t * pMan, int nVars )
+char * Abc_SopCreateAnd( Extra_MmFlex_t * pMan, int nVars, int * pfCompl )
{
char * pSop;
int i;
pSop = Abc_SopStart( pMan, 1, nVars );
for ( i = 0; i < nVars; i++ )
- pSop[i] = '1';
+ pSop[i] = '1' - (pfCompl? pfCompl[i] : 0);
+ pSop[nVars + 1] = '1';
return pSop;
}
/**Function*************************************************************
- Synopsis [Starts the multi-input NAND cover.]
+ Synopsis [Creates the multi-input NAND cover.]
Description []
@@ -190,7 +191,7 @@ char * Abc_SopCreateNand( Extra_MmFlex_t * pMan, int nVars )
/**Function*************************************************************
- Synopsis [Starts the multi-input OR cover.]
+ Synopsis [Creates the multi-input OR cover.]
Description []
@@ -212,7 +213,7 @@ char * Abc_SopCreateOr( Extra_MmFlex_t * pMan, int nVars, int * pfCompl )
/**Function*************************************************************
- Synopsis [Starts the multi-input OR cover.]
+ Synopsis [Creates the multi-input OR cover.]
Description []
@@ -237,7 +238,7 @@ char * Abc_SopCreateOrMultiCube( Extra_MmFlex_t * pMan, int nVars, int * pfCompl
/**Function*************************************************************
- Synopsis [Starts the multi-input NOR cover.]
+ Synopsis [Creates the multi-input NOR cover.]
Description []
@@ -258,7 +259,7 @@ char * Abc_SopCreateNor( Extra_MmFlex_t * pMan, int nVars )
/**Function*************************************************************
- Synopsis [Starts the multi-input XOR cover.]
+ Synopsis [Creates the multi-input XOR cover.]
Description []
@@ -275,7 +276,27 @@ char * Abc_SopCreateXor( Extra_MmFlex_t * pMan, int nVars )
/**Function*************************************************************
- Synopsis [Starts the multi-input XNOR cover.]
+ Synopsis [Creates the multi-input XOR cover (special case).]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+char * Abc_SopCreateXorSpecial( Extra_MmFlex_t * pMan, int nVars )
+{
+ char * pSop;
+ pSop = Abc_SopCreateAnd( pMan, nVars, NULL );
+ pSop[nVars+1] = 'x';
+ assert( pSop[nVars+2] == '\n' );
+ return pSop;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Creates the multi-input XNOR cover.]
Description []
@@ -287,12 +308,29 @@ char * Abc_SopCreateXor( Extra_MmFlex_t * pMan, int nVars )
char * Abc_SopCreateNxor( Extra_MmFlex_t * pMan, int nVars )
{
assert( nVars == 2 );
- return Abc_SopRegister(pMan, "11 1\n11 1\n");
+ return Abc_SopRegister(pMan, "11 1\n00 1\n");
}
/**Function*************************************************************
- Synopsis [Starts the inv cover.]
+ Synopsis [Creates the MUX cover.]
+
+ Description [The first input of MUX is the control. The second input
+ is DATA1. The third input is DATA0.]
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+char * Abc_SopCreateMux( Extra_MmFlex_t * pMan )
+{
+ return Abc_SopRegister(pMan, "11- 1\n0-1 1\n");
+}
+
+/**Function*************************************************************
+
+ Synopsis [Creates the inv cover.]
Description []
@@ -308,7 +346,7 @@ char * Abc_SopCreateInv( Extra_MmFlex_t * pMan )
/**Function*************************************************************
- Synopsis [Starts the buf cover.]
+ Synopsis [Creates the buf cover.]
Description []
@@ -322,6 +360,82 @@ char * Abc_SopCreateBuf( Extra_MmFlex_t * pMan )
return Abc_SopRegister(pMan, "1 1\n");
}
+/**Function*************************************************************
+
+ Synopsis [Creates the arbitrary cover from the truth table.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+char * Abc_SopCreateFromTruth( Extra_MmFlex_t * pMan, int nVars, unsigned * pTruth )
+{
+ char * pSop, * pCube;
+ int nMints, Counter, i, k;
+ // count the number of true minterms
+ Counter = 0;
+ nMints = (1 << nVars);
+ for ( i = 0; i < nMints; i++ )
+ Counter += ((pTruth[i>>5] & (1 << (i&31))) > 0);
+ // SOP is not well-defined if the truth table is constant 0
+ assert( Counter > 0 );
+ if ( Counter == 0 )
+ return NULL;
+ // start the cover
+ pSop = Abc_SopStart( pMan, Counter, nVars );
+ // create true minterms
+ Counter = 0;
+ for ( i = 0; i < nMints; i++ )
+ if ( (pTruth[i>>5] & (1 << (i&31))) > 0 )
+ {
+ pCube = pSop + Counter * (nVars + 3);
+ for ( k = 0; k < nVars; k++ )
+ pCube[k] = '0' + ((i & (1 << k)) > 0);
+ Counter++;
+ }
+ return pSop;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Creates the cover from the ISOP computed from TT.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+char * Abc_SopCreateFromIsop( Extra_MmFlex_t * pMan, int nVars, Vec_Int_t * vCover )
+{
+ char * pSop, * pCube;
+ int i, k, Entry, Literal;
+ assert( Vec_IntSize(vCover) > 0 );
+ if ( Vec_IntSize(vCover) == 0 )
+ return NULL;
+ // start the cover
+ pSop = Abc_SopStart( pMan, Vec_IntSize(vCover), nVars );
+ // create cubes
+ Vec_IntForEachEntry( vCover, Entry, i )
+ {
+ pCube = pSop + i * (nVars + 3);
+ for ( k = 0; k < nVars; k++ )
+ {
+ Literal = 3 & (Entry >> (k << 1));
+ if ( Literal == 1 )
+ pCube[k] = '0';
+ else if ( Literal == 2 )
+ pCube[k] = '1';
+ else if ( Literal != 0 )
+ assert( 0 );
+ }
+ }
+ return pSop;
+}
/**Function*************************************************************
@@ -402,9 +516,9 @@ int Abc_SopGetVarNum( char * pSop )
int Abc_SopGetPhase( char * pSop )
{
int nVars = Abc_SopGetVarNum( pSop );
- if ( pSop[nVars+1] == '0' )
+ if ( pSop[nVars+1] == '0' || pSop[nVars+1] == 'n' )
return 0;
- if ( pSop[nVars+1] == '1' )
+ if ( pSop[nVars+1] == '1' || pSop[nVars+1] == 'x' )
return 1;
assert( 0 );
return -1;
@@ -453,6 +567,10 @@ void Abc_SopComplement( char * pSop )
*(pCur - 1) = '1';
else if ( *(pCur - 1) == '1' )
*(pCur - 1) = '0';
+ else if ( *(pCur - 1) == 'x' )
+ *(pCur - 1) = 'n';
+ else if ( *(pCur - 1) == 'n' )
+ *(pCur - 1) = 'x';
else
assert( 0 );
}
@@ -474,7 +592,7 @@ bool Abc_SopIsComplement( char * pSop )
char * pCur;
for ( pCur = pSop; *pCur; pCur++ )
if ( *pCur == '\n' )
- return (int)(*(pCur - 1) == '0');
+ return (int)(*(pCur - 1) == '0' || *(pCur - 1) == 'n');
assert( 0 );
return 0;
}
@@ -616,6 +734,27 @@ bool Abc_SopIsOrType( char * pSop )
SeeAlso []
***********************************************************************/
+int Abc_SopIsExorType( char * pSop )
+{
+ char * pCur;
+ for ( pCur = pSop; *pCur; pCur++ )
+ if ( *pCur == '\n' )
+ return (int)(*(pCur - 1) == 'x' || *(pCur - 1) == 'n');
+ assert( 0 );
+ return 0;
+}
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
bool Abc_SopCheck( char * pSop, int nFanins )
{
char * pCubes, * pCubesOld;
@@ -629,7 +768,8 @@ bool Abc_SopCheck( char * pSop, int nFanins )
// compare the distance
if ( pCubes - pCubesOld != nFanins )
{
- fprintf( stdout, "Abc_SopCheck: SOP has a mismatch between its cover and its fanins.\n" );
+ fprintf( stdout, "Abc_SopCheck: SOP has a mismatch between its cover size (%d) and its fanin number (%d).\n",
+ pCubes - pCubesOld, nFanins );
return 0;
}
// check the output values for this cube
@@ -638,9 +778,9 @@ bool Abc_SopCheck( char * pSop, int nFanins )
fFound0 = 1;
else if ( *pCubes == '1' )
fFound1 = 1;
- else
+ else if ( *pCubes != 'x' && *pCubes != 'n' )
{
- fprintf( stdout, "Abc_SopCheck: SOP has a strange character in the output part of its cube.\n" );
+ fprintf( stdout, "Abc_SopCheck: SOP has a strange character (%c) in the output part of its cube.\n", *pCubes );
return 0;
}
// check the last symbol (new line)
@@ -659,78 +799,274 @@ bool Abc_SopCheck( char * pSop, int nFanins )
return 1;
}
+
/**Function*************************************************************
- Synopsis [Writes the CNF of the SOP into file.]
+ Synopsis [Derives SOP from the truth table representation.]
- Description []
+ Description [Truth table is expected to be in the hexadecimal notation.]
SideEffects []
SeeAlso []
***********************************************************************/
-void Abc_SopWriteCnf( FILE * pFile, char * pClauses, Vec_Int_t * vVars )
+char * Abc_SopFromTruthBin( char * pTruth )
{
- char * pChar;
- int i;
- // check the logic function of the node
- for ( pChar = pClauses; *pChar; pChar++ )
+ char * pSopCover, * pCube;
+ int nTruthSize, nVars, Digit, Length, Mint, i, b;
+ Vec_Int_t * vMints;
+
+ // get the number of variables
+ nTruthSize = strlen(pTruth);
+ nVars = Extra_Base2Log( nTruthSize );
+ if ( nTruthSize != (1 << (nVars)) )
{
- // write the clause
- for ( i = 0; i < vVars->nSize; i++, pChar++ )
- if ( *pChar == '0' )
- fprintf( pFile, "%d ", vVars->pArray[i] );
- else if ( *pChar == '1' )
- fprintf( pFile, "%d ", -vVars->pArray[i] );
- fprintf( pFile, "0\n" );
- // check that the remainig part is fine
- assert( *pChar == ' ' );
- pChar++;
- assert( *pChar == '1' );
- pChar++;
- assert( *pChar == '\n' );
+ printf( "String %s does not look like a truth table of a %d-variable function.\n", pTruth, nVars );
+ return NULL;
}
+
+ // collect the on-set minterms
+ vMints = Vec_IntAlloc( 100 );
+ for ( i = 0; i < nTruthSize; i++ )
+ {
+ if ( pTruth[i] >= '0' && pTruth[i] <= '1' )
+ Digit = pTruth[i] - '0';
+ else
+ {
+ printf( "String %s does not look like a binary representation of the truth table.\n", pTruth );
+ return NULL;
+ }
+ if ( Digit == 1 )
+ Vec_IntPush( vMints, nTruthSize - 1 - i );
+ }
+ if ( Vec_IntSize( vMints ) == 0 || Vec_IntSize( vMints ) == nTruthSize )
+ {
+ Vec_IntFree( vMints );
+ printf( "Cannot create constant function.\n" );
+ return NULL;
+ }
+
+ // create the SOP representation of the minterms
+ Length = Vec_IntSize(vMints) * (nVars + 3);
+ pSopCover = ALLOC( char, Length + 1 );
+ pSopCover[Length] = 0;
+ Vec_IntForEachEntry( vMints, Mint, i )
+ {
+ pCube = pSopCover + i * (nVars + 3);
+ for ( b = 0; b < nVars; b++ )
+ if ( Mint & (1 << (nVars-1-b)) )
+// if ( Mint & (1 << b) )
+ pCube[b] = '1';
+ else
+ pCube[b] = '0';
+ pCube[nVars + 0] = ' ';
+ pCube[nVars + 1] = '1';
+ pCube[nVars + 2] = '\n';
+ }
+ Vec_IntFree( vMints );
+ return pSopCover;
}
/**Function*************************************************************
- Synopsis [Adds the clauses of for the CNF to the solver.]
+ Synopsis [Derives SOP from the truth table representation.]
- Description []
+ Description [Truth table is expected to be in the hexadecimal notation.]
SideEffects []
SeeAlso []
***********************************************************************/
-void Abc_SopAddCnfToSolver( solver * pSat, char * pClauses, Vec_Int_t * vVars, Vec_Int_t * vTemp )
+char * Abc_SopFromTruthHex( char * pTruth )
{
- char * pChar;
- int i, RetValue;
- // check the logic function of the node
- for ( pChar = pClauses; *pChar; pChar++ )
+ char * pSopCover, * pCube;
+ int nTruthSize, nVars, Digit, Length, Mint, i, b;
+ Vec_Int_t * vMints;
+
+ // get the number of variables
+ nTruthSize = strlen(pTruth);
+ nVars = Extra_Base2Log( nTruthSize ) + 2;
+ if ( nTruthSize != (1 << (nVars-2)) )
{
- // add the clause
- vTemp->nSize = 0;
- for ( i = 0; i < vVars->nSize; i++, pChar++ )
- if ( *pChar == '0' )
- Vec_IntPush( vTemp, toLit(vVars->pArray[i]) );
- else if ( *pChar == '1' )
- Vec_IntPush( vTemp, neg(toLit(vVars->pArray[i])) );
- // add the clause to the solver
- RetValue = solver_addclause( pSat, vTemp->pArray, vTemp->pArray + vTemp->nSize );
- assert( RetValue != 1 );
- // check that the remainig part is fine
- assert( *pChar == ' ' );
- pChar++;
- assert( *pChar == '1' );
- pChar++;
- assert( *pChar == '\n' );
+ printf( "String %s does not look like a truth table of a %d-variable function.\n", pTruth, nVars );
+ return NULL;
+ }
+
+ // collect the on-set minterms
+ vMints = Vec_IntAlloc( 100 );
+ for ( i = 0; i < nTruthSize; i++ )
+ {
+ if ( pTruth[i] >= '0' && pTruth[i] <= '9' )
+ Digit = pTruth[i] - '0';
+ else if ( pTruth[i] >= 'a' && pTruth[i] <= 'f' )
+ Digit = 10 + pTruth[i] - 'a';
+ else if ( pTruth[i] >= 'A' && pTruth[i] <= 'F' )
+ Digit = 10 + pTruth[i] - 'A';
+ else
+ {
+ printf( "String %s does not look like a hexadecimal representation of the truth table.\n", pTruth );
+ return NULL;
+ }
+ for ( b = 0; b < 4; b++ )
+ if ( Digit & (1 << b) )
+ Vec_IntPush( vMints, 4*(nTruthSize-1-i)+b );
}
+
+ // create the SOP representation of the minterms
+ Length = Vec_IntSize(vMints) * (nVars + 3);
+ pSopCover = ALLOC( char, Length + 1 );
+ pSopCover[Length] = 0;
+ Vec_IntForEachEntry( vMints, Mint, i )
+ {
+ pCube = pSopCover + i * (nVars + 3);
+ for ( b = 0; b < nVars; b++ )
+// if ( Mint & (1 << (nVars-1-b)) )
+ if ( Mint & (1 << b) )
+ pCube[b] = '1';
+ else
+ pCube[b] = '0';
+ pCube[nVars + 0] = ' ';
+ pCube[nVars + 1] = '1';
+ pCube[nVars + 2] = '\n';
+ }
+ Vec_IntFree( vMints );
+ return pSopCover;
}
+/**Function*************************************************************
+
+ Synopsis [Creates one encoder node.]
+ Description [Produces MV-SOP for BLIF-MV representation.]
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+char * Abc_SopEncoderPos( Extra_MmFlex_t * pMan, int iValue, int nValues )
+{
+ char Buffer[32];
+ assert( iValue < nValues );
+ sprintf( Buffer, "d0\n%d 1\n", iValue );
+ return Abc_SopRegister( pMan, Buffer );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Creates one encoder node.]
+
+ Description [Produces MV-SOP for BLIF-MV representation.]
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+char * Abc_SopEncoderLog( Extra_MmFlex_t * pMan, int iBit, int nValues )
+{
+ char * pResult;
+ Vec_Str_t * vSop;
+ int v, Counter, fFirst = 1, nBits = Extra_Base2Log(nValues);
+ assert( iBit < nBits );
+ // count the number of literals
+ Counter = 0;
+ for ( v = 0; v < nValues; v++ )
+ Counter += ( (v & (1 << iBit)) > 0 );
+ // create the cover
+ vSop = Vec_StrAlloc( 100 );
+ Vec_StrPrintStr( vSop, "d0\n" );
+ if ( Counter > 1 )
+ Vec_StrPrintStr( vSop, "(" );
+ for ( v = 0; v < nValues; v++ )
+ if ( v & (1 << iBit) )
+ {
+ if ( fFirst )
+ fFirst = 0;
+ else
+ Vec_StrPush( vSop, ',' );
+ Vec_StrPrintNum( vSop, v );
+ }
+ if ( Counter > 1 )
+ Vec_StrPrintStr( vSop, ")" );
+ Vec_StrPrintStr( vSop, " 1\n" );
+ Vec_StrPush( vSop, 0 );
+ pResult = Abc_SopRegister( pMan, Vec_StrArray(vSop) );
+ Vec_StrFree( vSop );
+ return pResult;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Creates the decoder node.]
+
+ Description [Produces MV-SOP for BLIF-MV representation.]
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+char * Abc_SopDecoderPos( Extra_MmFlex_t * pMan, int nValues )
+{
+ char * pResult;
+ Vec_Str_t * vSop;
+ int i, k;
+ assert( nValues > 1 );
+ vSop = Vec_StrAlloc( 100 );
+ for ( i = 0; i < nValues; i++ )
+ {
+ for ( k = 0; k < nValues; k++ )
+ {
+ if ( k == i )
+ Vec_StrPrintStr( vSop, "1 " );
+ else
+ Vec_StrPrintStr( vSop, "- " );
+ }
+ Vec_StrPrintNum( vSop, i );
+ Vec_StrPush( vSop, '\n' );
+ }
+ Vec_StrPush( vSop, 0 );
+ pResult = Abc_SopRegister( pMan, Vec_StrArray(vSop) );
+ Vec_StrFree( vSop );
+ return pResult;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Creates the decover node.]
+
+ Description [Produces MV-SOP for BLIF-MV representation.]
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+char * Abc_SopDecoderLog( Extra_MmFlex_t * pMan, int nValues )
+{
+ char * pResult;
+ Vec_Str_t * vSop;
+ int i, b, nBits = Extra_Base2Log(nValues);
+ assert( nValues > 1 && nValues <= (1<<nBits) );
+ vSop = Vec_StrAlloc( 100 );
+ for ( i = 0; i < nValues; i++ )
+ {
+ for ( b = 0; b < nBits; b++ )
+ {
+ Vec_StrPrintNum( vSop, (int)((i & (1 << b)) > 0) );
+ Vec_StrPush( vSop, ' ' );
+ }
+ Vec_StrPrintNum( vSop, i );
+ Vec_StrPush( vSop, '\n' );
+ }
+ Vec_StrPush( vSop, 0 );
+ pResult = Abc_SopRegister( pMan, Vec_StrArray(vSop) );
+ Vec_StrFree( vSop );
+ return pResult;
+}
////////////////////////////////////////////////////////////////////////
/// END OF FILE ///
diff --git a/src/base/abc/abcUtil.c b/src/base/abc/abcUtil.c
index 7a6a705d..d3d32b98 100644
--- a/src/base/abc/abcUtil.c
+++ b/src/base/abc/abcUtil.c
@@ -22,19 +22,39 @@
#include "main.h"
#include "mio.h"
#include "dec.h"
+//#include "seq.h"
////////////////////////////////////////////////////////////////////////
/// DECLARATIONS ///
////////////////////////////////////////////////////////////////////////
-static int Abc_NodeRefDeref( Abc_Obj_t * pNode, bool fFanouts, bool fReference );
-
////////////////////////////////////////////////////////////////////////
-/// FUNCTION DEFITIONS ///
+/// FUNCTION DEFINITIONS ///
////////////////////////////////////////////////////////////////////////
/**Function*************************************************************
+ Synopsis [Frees one attribute manager.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void * Abc_NtkAttrFree( Abc_Ntk_t * pNtk, int Attr, int fFreeMan )
+{
+ void * pUserMan;
+ Vec_Att_t * pAttrMan;
+ pAttrMan = Vec_PtrEntry( pNtk->vAttrs, Attr );
+ Vec_PtrWriteEntry( pNtk->vAttrs, Attr, NULL );
+ pUserMan = Vec_AttFree( pAttrMan, fFreeMan );
+ return pUserMan;
+}
+
+/**Function*************************************************************
+
Synopsis [Increments the current traversal ID of the network.]
Description []
@@ -48,7 +68,7 @@ void Abc_NtkIncrementTravId( Abc_Ntk_t * pNtk )
{
Abc_Obj_t * pObj;
int i;
- if ( pNtk->nTravIds == (1<<12)-1 )
+ if ( pNtk->nTravIds >= (1<<30)-1 )
{
pNtk->nTravIds = 0;
Abc_NtkForEachObj( pNtk, pObj, i )
@@ -59,6 +79,49 @@ void Abc_NtkIncrementTravId( Abc_Ntk_t * pNtk )
/**Function*************************************************************
+ Synopsis [Order CI/COs.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Abc_NtkOrderCisCos( Abc_Ntk_t * pNtk )
+{
+ Abc_Obj_t * pObj, * pTerm;
+ int i, k;
+ Vec_PtrClear( pNtk->vCis );
+ Vec_PtrClear( pNtk->vCos );
+ Abc_NtkForEachPi( pNtk, pObj, i )
+ Vec_PtrPush( pNtk->vCis, pObj );
+ Abc_NtkForEachPo( pNtk, pObj, i )
+ Vec_PtrPush( pNtk->vCos, pObj );
+ Abc_NtkForEachAssert( pNtk, pObj, i )
+ Vec_PtrPush( pNtk->vCos, pObj );
+ Abc_NtkForEachBox( pNtk, pObj, i )
+ {
+ if ( Abc_ObjIsLatch(pObj) )
+ continue;
+ Abc_ObjForEachFanin( pObj, pTerm, k )
+ Vec_PtrPush( pNtk->vCos, pTerm );
+ Abc_ObjForEachFanout( pObj, pTerm, k )
+ Vec_PtrPush( pNtk->vCis, pTerm );
+ }
+ Abc_NtkForEachBox( pNtk, pObj, i )
+ {
+ if ( !Abc_ObjIsLatch(pObj) )
+ continue;
+ Abc_ObjForEachFanin( pObj, pTerm, k )
+ Vec_PtrPush( pNtk->vCos, pTerm );
+ Abc_ObjForEachFanout( pObj, pTerm, k )
+ Vec_PtrPush( pNtk->vCis, pTerm );
+ }
+}
+
+/**Function*************************************************************
+
Synopsis [Reads the number of cubes of the node.]
Description []
@@ -75,6 +138,8 @@ int Abc_NtkGetCubeNum( Abc_Ntk_t * pNtk )
assert( Abc_NtkHasSop(pNtk) );
Abc_NtkForEachNode( pNtk, pNode, i )
{
+ if ( Abc_NodeIsConst(pNode) )
+ continue;
assert( pNode->pData );
nCubes += Abc_SopGetCubeNum( pNode->pData );
}
@@ -92,6 +157,33 @@ int Abc_NtkGetCubeNum( Abc_Ntk_t * pNtk )
SeeAlso []
***********************************************************************/
+int Abc_NtkGetCubePairNum( Abc_Ntk_t * pNtk )
+{
+ Abc_Obj_t * pNode;
+ int i, nCubes, nCubePairs = 0;
+ assert( Abc_NtkHasSop(pNtk) );
+ Abc_NtkForEachNode( pNtk, pNode, i )
+ {
+ if ( Abc_NodeIsConst(pNode) )
+ continue;
+ assert( pNode->pData );
+ nCubes = Abc_SopGetCubeNum( pNode->pData );
+ nCubePairs += nCubes * (nCubes - 1) / 2;
+ }
+ return nCubePairs;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Reads the number of literals in the SOPs of the nodes.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
int Abc_NtkGetLitNum( Abc_Ntk_t * pNtk )
{
Abc_Obj_t * pNode;
@@ -153,7 +245,36 @@ int Abc_NtkGetBddNodeNum( Abc_Ntk_t * pNtk )
Abc_NtkForEachNode( pNtk, pNode, i )
{
assert( pNode->pData );
- nNodes += pNode->pData? Cudd_DagSize( pNode->pData ) : 0;
+ if ( Abc_ObjFaninNum(pNode) < 2 )
+ continue;
+ nNodes += pNode->pData? -1 + Cudd_DagSize( pNode->pData ) : 0;
+ }
+ return nNodes;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Reads the number of BDD nodes.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Abc_NtkGetAigNodeNum( Abc_Ntk_t * pNtk )
+{
+ Abc_Obj_t * pNode;
+ int i, nNodes = 0;
+ assert( Abc_NtkIsAigLogic(pNtk) );
+ Abc_NtkForEachNode( pNtk, pNode, i )
+ {
+ assert( pNode->pData );
+ if ( Abc_ObjFaninNum(pNode) < 2 )
+ continue;
+//printf( "%d ", Hop_DagSize( pNode->pData ) );
+ nNodes += pNode->pData? Hop_DagSize( pNode->pData ) : 0;
}
return nNodes;
}
@@ -218,7 +339,12 @@ double Abc_NtkGetMappedArea( Abc_Ntk_t * pNtk )
TotalArea = 0.0;
Abc_NtkForEachNode( pNtk, pNode, i )
{
- assert( pNode->pData );
+// assert( pNode->pData );
+ if ( pNode->pData == NULL )
+ {
+ printf( "Node without mapping is encountered.\n" );
+ continue;
+ }
TotalArea += Mio_GateReadArea( pNode->pData );
}
return TotalArea;
@@ -246,6 +372,26 @@ int Abc_NtkGetExorNum( Abc_Ntk_t * pNtk )
/**Function*************************************************************
+ Synopsis [Counts the number of exors.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Abc_NtkGetMuxNum( Abc_Ntk_t * pNtk )
+{
+ Abc_Obj_t * pNode;
+ int i, Counter = 0;
+ Abc_NtkForEachNode( pNtk, pNode, i )
+ Counter += Abc_NodeIsMuxType(pNode);
+ return Counter;
+}
+
+/**Function*************************************************************
+
Synopsis [Returns 1 if it is an AIG with choice nodes.]
Description []
@@ -263,7 +409,7 @@ int Abc_NtkGetChoiceNum( Abc_Ntk_t * pNtk )
return 0;
Counter = 0;
Abc_NtkForEachNode( pNtk, pNode, i )
- Counter += Abc_NodeIsAigChoice( pNode );
+ Counter += Abc_AigNodeIsChoice( pNode );
return Counter;
}
@@ -292,6 +438,26 @@ int Abc_NtkGetFaninMax( Abc_Ntk_t * pNtk )
/**Function*************************************************************
+ Synopsis [Reads the total number of all fanins.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Abc_NtkGetTotalFanins( Abc_Ntk_t * pNtk )
+{
+ Abc_Obj_t * pNode;
+ int i, nFanins = 0;
+ Abc_NtkForEachNode( pNtk, pNode, i )
+ nFanins += Abc_ObjFaninNum(pNode);
+ return nFanins;
+}
+
+/**Function*************************************************************
+
Synopsis [Cleans the copy field of all objects.]
Description []
@@ -305,19 +471,199 @@ void Abc_NtkCleanCopy( Abc_Ntk_t * pNtk )
{
Abc_Obj_t * pObj;
int i;
- i = 0;
- // set the data filed to NULL
Abc_NtkForEachObj( pNtk, pObj, i )
pObj->pCopy = NULL;
}
/**Function*************************************************************
- Synopsis [Checks if the internal node has a unique CO.]
+ Synopsis [Cleans the copy field of all objects.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Abc_NtkCleanData( Abc_Ntk_t * pNtk )
+{
+ Abc_Obj_t * pObj;
+ int i;
+ Abc_NtkForEachObj( pNtk, pObj, i )
+ pObj->pData = NULL;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Cleans the copy field of all objects.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Abc_NtkCleanEquiv( Abc_Ntk_t * pNtk )
+{
+ Abc_Obj_t * pObj;
+ int i;
+ Abc_NtkForEachObj( pNtk, pObj, i )
+ pObj->pEquiv = NULL;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Counts the number of nodes having non-trivial copies.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Abc_NtkCountCopy( Abc_Ntk_t * pNtk )
+{
+ Abc_Obj_t * pObj;
+ int i, Counter = 0;
+ Abc_NtkForEachObj( pNtk, pObj, i )
+ {
+ if ( Abc_ObjIsNode(pObj) )
+ Counter += (pObj->pCopy != NULL);
+ }
+ return Counter;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Saves copy field of the objects.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Vec_Ptr_t * Abc_NtkSaveCopy( Abc_Ntk_t * pNtk )
+{
+ Vec_Ptr_t * vCopies;
+ Abc_Obj_t * pObj;
+ int i;
+ vCopies = Vec_PtrStart( Abc_NtkObjNumMax(pNtk) );
+ Abc_NtkForEachObj( pNtk, pObj, i )
+ Vec_PtrWriteEntry( vCopies, i, pObj->pCopy );
+ return vCopies;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Loads copy field of the objects.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Abc_NtkLoadCopy( Abc_Ntk_t * pNtk, Vec_Ptr_t * vCopies )
+{
+ Abc_Obj_t * pObj;
+ int i;
+ Abc_NtkForEachObj( pNtk, pObj, i )
+ pObj->pCopy = Vec_PtrEntry( vCopies, i );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Cleans the copy field of all objects.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Abc_NtkCleanNext( Abc_Ntk_t * pNtk )
+{
+ Abc_Obj_t * pObj;
+ int i = 0;
+ Abc_NtkForEachObj( pNtk, pObj, i )
+ pObj->pNext = NULL;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Cleans the copy field of all objects.]
- Description [Checks if the internal node can borrow a name from a CO
- fanout. This is possible if there is only one CO with non-complemented
- fanin edge pointing to this node.]
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Abc_NtkCleanMarkA( Abc_Ntk_t * pNtk )
+{
+ Abc_Obj_t * pObj;
+ int i = 0;
+ Abc_NtkForEachObj( pNtk, pObj, i )
+ pObj->fMarkA = 0;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Checks if the internal node has CO fanout.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Abc_Obj_t * Abc_NodeFindCoFanout( Abc_Obj_t * pNode )
+{
+ Abc_Obj_t * pFanout;
+ int i;
+ Abc_ObjForEachFanout( pNode, pFanout, i )
+ if ( Abc_ObjIsCo(pFanout) )
+ return pFanout;
+ return NULL;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Checks if the internal node has CO fanout.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Abc_Obj_t * Abc_NodeFindNonCoFanout( Abc_Obj_t * pNode )
+{
+ Abc_Obj_t * pFanout;
+ int i;
+ Abc_ObjForEachFanout( pNode, pFanout, i )
+ if ( !Abc_ObjIsCo(pFanout) )
+ return pFanout;
+ return NULL;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Checks if the internal node has CO drivers with the same name.]
+
+ Description [Checks if the internal node can borrow its name from CO fanouts.
+ This is possible if all COs with non-complemented fanin edge pointing to this
+ node have the same name.]
SideEffects []
@@ -327,23 +673,73 @@ void Abc_NtkCleanCopy( Abc_Ntk_t * pNtk )
Abc_Obj_t * Abc_NodeHasUniqueCoFanout( Abc_Obj_t * pNode )
{
Abc_Obj_t * pFanout, * pFanoutCo;
- int i, Counter;
- if ( !Abc_ObjIsNode(pNode) )
- return NULL;
- Counter = 0;
+ int i;
+ pFanoutCo = NULL;
Abc_ObjForEachFanout( pNode, pFanout, i )
{
- if ( Abc_ObjIsCo(pFanout) && !Abc_ObjFaninC0(pFanout) )
+ if ( !Abc_ObjIsCo(pFanout) )
+ continue;
+ if ( Abc_ObjFaninC0(pFanout) )
+ continue;
+ if ( pFanoutCo == NULL )
{
assert( Abc_ObjFaninNum(pFanout) == 1 );
assert( Abc_ObjFanin0(pFanout) == pNode );
pFanoutCo = pFanout;
- Counter++;
+ continue;
}
+ if ( strcmp( Abc_ObjName(pFanoutCo), Abc_ObjName(pFanout) ) ) // they have diff names
+ return NULL;
}
- if ( Counter == 1 )
- return pFanoutCo;
- return NULL;
+ return pFanoutCo;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Fixes the CO driver problem.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Abc_NtkFixCoDriverProblem( Abc_Obj_t * pDriver, Abc_Obj_t * pNodeCo, int fDuplicate )
+{
+ Abc_Ntk_t * pNtk = pDriver->pNtk;
+ Abc_Obj_t * pDriverNew, * pFanin;
+ int k;
+ if ( fDuplicate && !Abc_ObjIsCi(pDriver) )
+ {
+ pDriverNew = Abc_NtkDupObj( pNtk, pDriver, 0 );
+ Abc_ObjForEachFanin( pDriver, pFanin, k )
+ Abc_ObjAddFanin( pDriverNew, pFanin );
+ if ( Abc_ObjFaninC0(pNodeCo) )
+ {
+ // change polarity of the duplicated driver
+ Abc_NodeComplement( pDriverNew );
+ Abc_ObjXorFaninC( pNodeCo, 0 );
+ }
+ }
+ else
+ {
+ // add inverters and buffers when necessary
+ if ( Abc_ObjFaninC0(pNodeCo) )
+ {
+ pDriverNew = Abc_NtkCreateNodeInv( pNtk, pDriver );
+ Abc_ObjXorFaninC( pNodeCo, 0 );
+ }
+ else
+ pDriverNew = Abc_NtkCreateNodeBuf( pNtk, pDriver );
+ }
+ // update the fanin of the PO node
+ Abc_ObjPatchFanin( pNodeCo, pDriver, pDriverNew );
+ assert( Abc_ObjFanoutNum(pDriverNew) == 1 );
+ // remove the old driver if it dangles
+ // (this happens when the duplicated driver had only one complemented fanout)
+ if ( Abc_ObjFanoutNum(pDriver) == 0 )
+ Abc_NtkDeleteObj( pDriver );
}
/**Function*************************************************************
@@ -352,9 +748,8 @@ Abc_Obj_t * Abc_NodeHasUniqueCoFanout( Abc_Obj_t * pNode )
Description [The COs of a logic network are simple under three conditions:
(1) The edge from CO to its driver is not complemented.
- (2) No two COs share the same driver.
- (3) The driver is not a CI unless the CI and the CO have the same name
- (and so the inv/buf should not be written into a file).]
+ (2) If CI is a driver of a CO, they have the same name.]
+ (3) If two COs share the same driver, they have the same name.]
SideEffects []
@@ -365,19 +760,27 @@ bool Abc_NtkLogicHasSimpleCos( Abc_Ntk_t * pNtk )
{
Abc_Obj_t * pNode, * pDriver;
int i;
- assert( !Abc_NtkIsNetlist(pNtk) );
- // check if there are complemented or idential POs
+ assert( Abc_NtkIsLogic(pNtk) );
Abc_NtkIncrementTravId( pNtk );
Abc_NtkForEachCo( pNtk, pNode, i )
{
+ // if the driver is complemented, this is an error
pDriver = Abc_ObjFanin0(pNode);
if ( Abc_ObjFaninC0(pNode) )
return 0;
- if ( Abc_NodeIsTravIdCurrent(pDriver) )
+ // if the driver is a CI and has different name, this is an error
+ if ( Abc_ObjIsCi(pDriver) && strcmp(Abc_ObjName(pDriver), Abc_ObjName(pNode)) )
return 0;
- if ( Abc_ObjIsCi(pDriver) && strcmp( Abc_ObjName(pDriver), Abc_ObjName(pNode) ) != 0 )
+ // if the driver is visited for the first time, remember the CO name
+ if ( !Abc_NodeIsTravIdCurrent(pDriver) )
+ {
+ pDriver->pNext = (Abc_Obj_t *)Abc_ObjName(pNode);
+ Abc_NodeSetTravIdCurrent(pDriver);
+ continue;
+ }
+ // the driver has second CO - if they have different name, this is an error
+ if ( strcmp((char *)pDriver->pNext, Abc_ObjName(pNode)) ) // diff names
return 0;
- Abc_NodeSetTravIdCurrent(pDriver);
}
return 1;
}
@@ -387,10 +790,9 @@ bool Abc_NtkLogicHasSimpleCos( Abc_Ntk_t * pNtk )
Synopsis [Transforms the network to have simple COs.]
Description [The COs of a logic network are simple under three conditions:
- (1) The edge from the CO to its driver is not complemented.
- (2) No two COs share the same driver.
- (3) The driver is not a CI unless the CI and the CO have the same name
- (and so the inv/buf should not be written into a file).
+ (1) The edge from CO to its driver is not complemented.
+ (2) If CI is a driver of a CO, they have the same name.]
+ (3) If two COs share the same driver, they have the same name.
In some cases, such as FPGA mapping, we prevent the increase in delay
by duplicating the driver nodes, rather than adding invs/bufs.]
@@ -401,63 +803,41 @@ bool Abc_NtkLogicHasSimpleCos( Abc_Ntk_t * pNtk )
***********************************************************************/
int Abc_NtkLogicMakeSimpleCos( Abc_Ntk_t * pNtk, bool fDuplicate )
{
- Abc_Obj_t * pNode, * pDriver, * pDriverNew, * pFanin;
- int i, k, nDupGates = 0;
+ Abc_Obj_t * pNode, * pDriver;
+ int i, nDupGates = 0;
assert( Abc_NtkIsLogic(pNtk) );
- // process the COs by adding inverters and buffers when necessary
+ Abc_NtkIncrementTravId( pNtk );
Abc_NtkForEachCo( pNtk, pNode, i )
{
+ // if the driver is complemented, this is an error
pDriver = Abc_ObjFanin0(pNode);
- if ( Abc_ObjIsCi(pDriver) )
+ if ( Abc_ObjFaninC0(pNode) )
{
- // skip the case when the driver is a different node with the same name
- if ( pDriver != pNode && strcmp(Abc_ObjName(pDriver), Abc_ObjName(pNode)) == 0 )
- {
- assert( !Abc_ObjFaninC0(pNode) );
- continue;
- }
+ Abc_NtkFixCoDriverProblem( pDriver, pNode, fDuplicate );
+ nDupGates++;
+ continue;
}
- else
+ // if the driver is a CI and has different name, this is an error
+ if ( Abc_ObjIsCi(pDriver) && strcmp(Abc_ObjName(pDriver), Abc_ObjName(pNode)) )
{
- // skip the case when the driver's unique CO fanout is this CO
- if ( Abc_NodeHasUniqueCoFanout(pDriver) == pNode )
- continue;
+ Abc_NtkFixCoDriverProblem( pDriver, pNode, fDuplicate );
+ nDupGates++;
+ continue;
}
- if ( fDuplicate && !Abc_ObjIsCi(pDriver) )
+ // if the driver is visited for the first time, remember the CO name
+ if ( !Abc_NodeIsTravIdCurrent(pDriver) )
{
- pDriverNew = Abc_NtkDupObj( pNtk, pDriver );
- Abc_ObjForEachFanin( pDriver, pFanin, k )
- Abc_ObjAddFanin( pDriverNew, pFanin );
- if ( Abc_ObjFaninC0(pNode) )
- {
- // change polarity of the duplicated driver
- if ( Abc_NtkHasSop(pNtk) )
- Abc_SopComplement( pDriverNew->pData );
- else if ( Abc_NtkHasBdd(pNtk) )
- pDriverNew->pData = Cudd_Not( pDriverNew->pData );
- else
- assert( 0 );
- Abc_ObjXorFaninC(pNode, 0);
- }
+ pDriver->pNext = (Abc_Obj_t *)Abc_ObjName(pNode);
+ Abc_NodeSetTravIdCurrent(pDriver);
+ continue;
}
- else
+ // the driver has second CO - if they have different name, this is an error
+ if ( strcmp((char *)pDriver->pNext, Abc_ObjName(pNode)) ) // diff names
{
- // add inverters and buffers when necessary
- if ( Abc_ObjFaninC0(pNode) )
- {
- pDriverNew = Abc_NodeCreateInv( pNtk, pDriver );
- Abc_ObjXorFaninC( pNode, 0 );
- }
- else
- pDriverNew = Abc_NodeCreateBuf( pNtk, pDriver );
+ Abc_NtkFixCoDriverProblem( pDriver, pNode, fDuplicate );
+ nDupGates++;
+ continue;
}
- // update the fanin of the PO node
- Abc_ObjPatchFanin( pNode, pDriver, pDriverNew );
- assert( Abc_ObjFanoutNum(pDriverNew) == 1 );
- nDupGates++;
- // remove the old driver if it dangles
- if ( Abc_ObjFanoutNum(pDriver) == 0 )
- Abc_NtkDeleteObj( pDriver );
}
assert( Abc_NtkLogicHasSimpleCos(pNtk) );
return nDupGates;
@@ -511,7 +891,7 @@ bool Abc_NodeIsExorType( Abc_Obj_t * pNode )
// check that the node is regular
assert( !Abc_ObjIsComplement(pNode) );
// if the node is not AND, this is not EXOR
- if ( !Abc_NodeIsAigAnd(pNode) )
+ if ( !Abc_AigNodeIsAnd(pNode) )
return 0;
// if the children are not complemented, this is not EXOR
if ( !Abc_ObjFaninC0(pNode) || !Abc_ObjFaninC1(pNode) )
@@ -544,7 +924,7 @@ bool Abc_NodeIsMuxType( Abc_Obj_t * pNode )
// check that the node is regular
assert( !Abc_ObjIsComplement(pNode) );
// if the node is not AND, this is not MUX
- if ( !Abc_NodeIsAigAnd(pNode) )
+ if ( !Abc_AigNodeIsAnd(pNode) )
return 0;
// if the children are not complemented, this is not MUX
if ( !Abc_ObjFaninC0(pNode) || !Abc_ObjFaninC1(pNode) )
@@ -564,6 +944,35 @@ bool Abc_NodeIsMuxType( Abc_Obj_t * pNode )
/**Function*************************************************************
+ Synopsis [Returns 1 if the node is the control type of the MUX.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+bool Abc_NodeIsMuxControlType( Abc_Obj_t * pNode )
+{
+ Abc_Obj_t * pNode0, * pNode1;
+ // check that the node is regular
+ assert( !Abc_ObjIsComplement(pNode) );
+ // skip the node that do not have two fanouts
+ if ( Abc_ObjFanoutNum(pNode) != 2 )
+ return 0;
+ // get the fanouts
+ pNode0 = Abc_ObjFanout( pNode, 0 );
+ pNode1 = Abc_ObjFanout( pNode, 1 );
+ // if they have more than one fanout, we are not interested
+ if ( Abc_ObjFanoutNum(pNode0) != 1 || Abc_ObjFanoutNum(pNode1) != 1 )
+ return 0;
+ // if the fanouts have the same fanout, this is MUX or EXOR (or a redundant gate (CA)(CB))
+ return Abc_ObjFanout0(pNode0) == Abc_ObjFanout0(pNode1);
+}
+
+/**Function*************************************************************
+
Synopsis [Recognizes what nodes are control and data inputs of a MUX.]
Description [If the node is a MUX, returns the control variable C.
@@ -673,7 +1082,7 @@ int Abc_NtkPrepareTwoNtks( FILE * pErr, Abc_Ntk_t * pNtk, char ** argv, int argc
{
int fCheck = 1;
FILE * pFile;
- Abc_Ntk_t * pNtk1, * pNtk2;
+ Abc_Ntk_t * pNtk1, * pNtk2, * pNtkTemp;
int util_optind = 0;
*pfDelete1 = 0;
@@ -698,15 +1107,8 @@ int Abc_NtkPrepareTwoNtks( FILE * pErr, Abc_Ntk_t * pNtk, char ** argv, int argc
}
else
fclose( pFile );
-
- if ( Abc_NtkIsSeq(pNtk) )
- {
- pNtk1 = Abc_NtkSeqToLogicSop(pNtk);
- *pfDelete1 = 1;
- }
- else
- pNtk1 = pNtk;
- pNtk2 = Io_Read( pNtk->pSpec, fCheck );
+ pNtk1 = pNtk;
+ pNtk2 = Io_Read( pNtk->pSpec, Io_ReadFileType(pNtk->pSpec), fCheck );
if ( pNtk2 == NULL )
return 0;
*pfDelete2 = 1;
@@ -718,24 +1120,18 @@ int Abc_NtkPrepareTwoNtks( FILE * pErr, Abc_Ntk_t * pNtk, char ** argv, int argc
fprintf( pErr, "Empty current network.\n" );
return 0;
}
- if ( Abc_NtkIsSeq(pNtk) )
- {
- pNtk1 = Abc_NtkSeqToLogicSop(pNtk);
- *pfDelete1 = 1;
- }
- else
- pNtk1 = pNtk;
- pNtk2 = Io_Read( argv[util_optind], fCheck );
+ pNtk1 = pNtk;
+ pNtk2 = Io_Read( argv[util_optind], Io_ReadFileType(argv[util_optind]), fCheck );
if ( pNtk2 == NULL )
return 0;
*pfDelete2 = 1;
}
else if ( argc == util_optind + 2 )
{
- pNtk1 = Io_Read( argv[util_optind], fCheck );
+ pNtk1 = Io_Read( argv[util_optind], Io_ReadFileType(argv[util_optind]), fCheck );
if ( pNtk1 == NULL )
return 0;
- pNtk2 = Io_Read( argv[util_optind+1], fCheck );
+ pNtk2 = Io_Read( argv[util_optind+1], Io_ReadFileType(argv[util_optind+1]), fCheck );
if ( pNtk2 == NULL )
{
Abc_NtkDelete( pNtk1 );
@@ -749,6 +1145,25 @@ int Abc_NtkPrepareTwoNtks( FILE * pErr, Abc_Ntk_t * pNtk, char ** argv, int argc
fprintf( pErr, "Wrong number of arguments.\n" );
return 0;
}
+
+ // make sure the networks are strashed
+ if ( !Abc_NtkIsStrash(pNtk1) )
+ {
+ pNtkTemp = Abc_NtkStrash( pNtk1, 0, 1, 0 );
+ if ( *pfDelete1 )
+ Abc_NtkDelete( pNtk1 );
+ pNtk1 = pNtkTemp;
+ *pfDelete1 = 1;
+ }
+ if ( !Abc_NtkIsStrash(pNtk2) )
+ {
+ pNtkTemp = Abc_NtkStrash( pNtk2, 0, 1, 0 );
+ if ( *pfDelete2 )
+ Abc_NtkDelete( pNtk2 );
+ pNtk2 = pNtkTemp;
+ *pfDelete2 = 1;
+ }
+
*ppNtk1 = pNtk1;
*ppNtk2 = pNtk2;
return 1;
@@ -770,7 +1185,7 @@ void Abc_NodeCollectFanins( Abc_Obj_t * pNode, Vec_Ptr_t * vNodes )
{
Abc_Obj_t * pFanin;
int i;
- vNodes->nSize = 0;
+ Vec_PtrClear(vNodes);
Abc_ObjForEachFanin( pNode, pFanin, i )
Vec_PtrPush( vNodes, pFanin );
}
@@ -790,14 +1205,36 @@ void Abc_NodeCollectFanouts( Abc_Obj_t * pNode, Vec_Ptr_t * vNodes )
{
Abc_Obj_t * pFanout;
int i;
- vNodes->nSize = 0;
+ Vec_PtrClear(vNodes);
Abc_ObjForEachFanout( pNode, pFanout, i )
Vec_PtrPush( vNodes, pFanout );
}
/**Function*************************************************************
- Synopsis [Procedure used for sorting the nodes in decreasing order of levels.]
+ Synopsis [Collects all latches in the network.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Vec_Ptr_t * Abc_NtkCollectLatches( Abc_Ntk_t * pNtk )
+{
+ Vec_Ptr_t * vLatches;
+ Abc_Obj_t * pObj;
+ int i;
+ vLatches = Vec_PtrAlloc( 10 );
+ Abc_NtkForEachObj( pNtk, pObj, i )
+ Vec_PtrPush( vLatches, pObj );
+ return vLatches;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Procedure used for sorting the nodes in increasing order of levels.]
Description []
@@ -883,6 +1320,461 @@ Vec_Ptr_t * Abc_NtkCollectObjects( Abc_Ntk_t * pNtk )
return vNodes;
}
+/**Function*************************************************************
+
+ Synopsis [Returns the array of CI IDs.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Vec_Int_t * Abc_NtkGetCiIds( Abc_Ntk_t * pNtk )
+{
+ Vec_Int_t * vCiIds;
+ Abc_Obj_t * pObj;
+ int i;
+ vCiIds = Vec_IntAlloc( Abc_NtkCiNum(pNtk) );
+ Abc_NtkForEachCi( pNtk, pObj, i )
+ Vec_IntPush( vCiIds, pObj->Id );
+ return vCiIds;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Puts the nodes into the DFS order and reassign their IDs.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Abc_NtkReassignIds( Abc_Ntk_t * pNtk )
+{
+ Vec_Ptr_t * vNodes;
+ Vec_Ptr_t * vObjsNew;
+ Abc_Obj_t * pNode, * pTemp, * pConst1;
+ int i, k;
+ assert( Abc_NtkIsStrash(pNtk) );
+//printf( "Total = %d. Current = %d.\n", Abc_NtkObjNumMax(pNtk), Abc_NtkObjNum(pNtk) );
+ // start the array of objects with new IDs
+ vObjsNew = Vec_PtrAlloc( pNtk->nObjs );
+ // put constant node first
+ pConst1 = Abc_AigConst1(pNtk);
+ assert( pConst1->Id == 0 );
+ Vec_PtrPush( vObjsNew, pConst1 );
+ // put PI nodes next
+ Abc_NtkForEachPi( pNtk, pNode, i )
+ {
+ pNode->Id = Vec_PtrSize( vObjsNew );
+ Vec_PtrPush( vObjsNew, pNode );
+ }
+ // put PO nodes next
+ Abc_NtkForEachPo( pNtk, pNode, i )
+ {
+ pNode->Id = Vec_PtrSize( vObjsNew );
+ Vec_PtrPush( vObjsNew, pNode );
+ }
+ // put assert nodes next
+ Abc_NtkForEachAssert( pNtk, pNode, i )
+ {
+ pNode->Id = Vec_PtrSize( vObjsNew );
+ Vec_PtrPush( vObjsNew, pNode );
+ }
+ // put latches and their inputs/outputs next
+ Abc_NtkForEachBox( pNtk, pNode, i )
+ {
+ pNode->Id = Vec_PtrSize( vObjsNew );
+ Vec_PtrPush( vObjsNew, pNode );
+ Abc_ObjForEachFanin( pNode, pTemp, k )
+ {
+ pTemp->Id = Vec_PtrSize( vObjsNew );
+ Vec_PtrPush( vObjsNew, pTemp );
+ }
+ Abc_ObjForEachFanout( pNode, pTemp, k )
+ {
+ pTemp->Id = Vec_PtrSize( vObjsNew );
+ Vec_PtrPush( vObjsNew, pTemp );
+ }
+ }
+ // finally, internal nodes in the DFS order
+ vNodes = Abc_AigDfs( pNtk, 1, 0 );
+ Vec_PtrForEachEntry( vNodes, pNode, i )
+ {
+ if ( pNode == pConst1 )
+ continue;
+ pNode->Id = Vec_PtrSize( vObjsNew );
+ Vec_PtrPush( vObjsNew, pNode );
+ }
+ Vec_PtrFree( vNodes );
+ assert( Vec_PtrSize(vObjsNew) == pNtk->nObjs );
+
+ // update the fanin/fanout arrays
+ Abc_NtkForEachObj( pNtk, pNode, i )
+ {
+ Abc_ObjForEachFanin( pNode, pTemp, k )
+ pNode->vFanins.pArray[k] = pTemp->Id;
+ Abc_ObjForEachFanout( pNode, pTemp, k )
+ pNode->vFanouts.pArray[k] = pTemp->Id;
+ }
+
+ // replace the array of objs
+ Vec_PtrFree( pNtk->vObjs );
+ pNtk->vObjs = vObjsNew;
+
+ // rehash the AIG
+ Abc_AigRehash( pNtk->pManFunc );
+
+ // update the name manager!!!
+}
+
+/**Function*************************************************************
+
+ Synopsis [Detect cases when non-trivial FF matching is possible.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Abc_NtkDetectMatching( Abc_Ntk_t * pNtk )
+{
+/*
+ Abc_Obj_t * pLatch, * pFanin;
+ int i, nTFFs, nJKFFs;
+ nTFFs = nJKFFs = 0;
+ Abc_NtkForEachLatch( pNtk, pLatch, i )
+ {
+ pFanin = Abc_ObjFanin0(pLatch);
+ if ( Abc_ObjFaninNum(pFanin) != 2 )
+ continue;
+ if ( Abc_NodeIsExorType(pLatch) )
+ {
+ if ( Abc_ObjFanin0(Abc_ObjFanin0(pFanin)) == pLatch ||
+ Abc_ObjFanin1(Abc_ObjFanin0(pFanin)) == pLatch )
+ nTFFs++;
+ }
+ if ( Abc_ObjFaninNum( Abc_ObjFanin0(pFanin) ) != 2 ||
+ Abc_ObjFaninNum( Abc_ObjFanin1(pFanin) ) != 2 )
+ continue;
+
+ if ( (Abc_ObjFanin0(Abc_ObjFanin0(pFanin)) == pLatch ||
+ Abc_ObjFanin1(Abc_ObjFanin0(pFanin)) == pLatch) &&
+ (Abc_ObjFanin0(Abc_ObjFanin1(pFanin)) == pLatch ||
+ Abc_ObjFanin1(Abc_ObjFanin1(pFanin)) == pLatch) )
+ {
+ nJKFFs++;
+ }
+ }
+ printf( "D = %6d. T = %6d. JK = %6d. (%6.2f %%)\n",
+ Abc_NtkLatchNum(pNtk), nTFFs, nJKFFs, 100.0 * nJKFFs / Abc_NtkLatchNum(pNtk) );
+*/
+}
+
+
+/**Function*************************************************************
+
+ Synopsis [Compares the pointers.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Abc_ObjPointerCompare( void ** pp1, void ** pp2 )
+{
+ if ( *pp1 < *pp2 )
+ return -1;
+ if ( *pp1 > *pp2 )
+ return 1;
+ return 0;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Adjusts the copy pointers.]
+
+ Description [This procedure assumes that the network was transformed
+ into another network, which was in turn transformed into yet another
+ network. It makes the pCopy pointers of the original network point to
+ the objects of the yet another network.]
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Abc_NtkTransferCopy( Abc_Ntk_t * pNtk )
+{
+ Abc_Obj_t * pObj;
+ int i;
+ Abc_NtkForEachObj( pNtk, pObj, i )
+ if ( !Abc_ObjIsNet(pObj) )
+ pObj->pCopy = pObj->pCopy? Abc_ObjCopyCond(pObj->pCopy) : NULL;
+}
+
+
+/**Function*************************************************************
+
+ Synopsis [Increaments the cut counter.]
+
+ Description [Returns 1 if it becomes equal to the ref counter.]
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+static inline int Abc_ObjCrossCutInc( Abc_Obj_t * pObj )
+{
+// pObj->pCopy = (void *)(((int)pObj->pCopy)++);
+ int Value = (int)pObj->pCopy;
+ pObj->pCopy = (void *)(Value + 1);
+ return (int)pObj->pCopy == Abc_ObjFanoutNum(pObj);
+}
+
+/**Function*************************************************************
+
+ Synopsis [Computes cross-cut of the circuit.]
+
+ Description [Returns 1 if it is the last visit to the node.]
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Abc_NtkCrossCut_rec( Abc_Obj_t * pObj, int * pnCutSize, int * pnCutSizeMax )
+{
+ Abc_Obj_t * pFanin;
+ int i, nDecrem = 0;
+ int fReverse = 0;
+ if ( Abc_ObjIsCi(pObj) )
+ return 0;
+ // if visited, increment visit counter
+ if ( Abc_NodeIsTravIdCurrent( pObj ) )
+ return Abc_ObjCrossCutInc( pObj );
+ Abc_NodeSetTravIdCurrent( pObj );
+ // visit the fanins
+ if ( !Abc_ObjIsCi(pObj) )
+ {
+ if ( fReverse )
+ {
+ Abc_ObjForEachFanin( pObj, pFanin, i )
+ {
+ pFanin = Abc_ObjFanin( pObj, Abc_ObjFaninNum(pObj) - 1 - i );
+ nDecrem += Abc_NtkCrossCut_rec( pFanin, pnCutSize, pnCutSizeMax );
+ }
+ }
+ else
+ {
+ Abc_ObjForEachFanin( pObj, pFanin, i )
+ nDecrem += Abc_NtkCrossCut_rec( pFanin, pnCutSize, pnCutSizeMax );
+ }
+ }
+ // count the node
+ (*pnCutSize)++;
+ if ( *pnCutSizeMax < *pnCutSize )
+ *pnCutSizeMax = *pnCutSize;
+ (*pnCutSize) -= nDecrem;
+ return Abc_ObjCrossCutInc( pObj );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Computes cross-cut of the circuit.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Abc_NtkCrossCut( Abc_Ntk_t * pNtk )
+{
+ Abc_Obj_t * pObj;
+ int nCutSize = 0, nCutSizeMax = 0;
+ int i;
+ Abc_NtkCleanCopy( pNtk );
+ Abc_NtkIncrementTravId( pNtk );
+ Abc_NtkForEachCo( pNtk, pObj, i )
+ {
+ Abc_NtkCrossCut_rec( pObj, &nCutSize, &nCutSizeMax );
+ nCutSize--;
+ }
+ assert( nCutSize == 0 );
+ printf( "Max cross cut size = %6d. Ratio = %6.2f %%\n", nCutSizeMax, 100.0 * nCutSizeMax/Abc_NtkObjNum(pNtk) );
+ return nCutSizeMax;
+}
+
+
+/**Function*************************************************************
+
+ Synopsis [Prints all 3-var functions.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Abc_NtkPrint256()
+{
+ FILE * pFile;
+ unsigned i;
+ pFile = fopen( "4varfs.txt", "w" );
+ for ( i = 1; i < (1<<16)-1; i++ )
+ {
+ fprintf( pFile, "read_truth " );
+ Extra_PrintBinary( pFile, &i, 16 );
+ fprintf( pFile, "; clp; st; w 1.blif; map; cec 1.blif\n" );
+ }
+ fclose( pFile );
+}
+
+
+static int * pSupps;
+
+/**Function*************************************************************
+
+ Synopsis [Compares the supergates by their level.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Abc_NtkCompareConesCompare( int * pNum1, int * pNum2 )
+{
+ if ( pSupps[*pNum1] > pSupps[*pNum2] )
+ return -1;
+ if ( pSupps[*pNum1] < pSupps[*pNum2] )
+ return 1;
+ return 0;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Analyze choice node support.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Abc_NtkCompareCones( Abc_Ntk_t * pNtk )
+{
+ Vec_Ptr_t * vSupp, * vNodes, * vReverse;
+ Abc_Obj_t * pObj, * pTemp;
+ int Iter, i, k, Counter, CounterCos, CounterCosNew;
+ int * pPerms;
+
+ // sort COs by support size
+ pPerms = ALLOC( int, Abc_NtkCoNum(pNtk) );
+ pSupps = ALLOC( int, Abc_NtkCoNum(pNtk) );
+ Abc_NtkForEachCo( pNtk, pObj, i )
+ {
+ pPerms[i] = i;
+ vSupp = Abc_NtkNodeSupport( pNtk, &pObj, 1 );
+ pSupps[i] = Vec_PtrSize(vSupp);
+ Vec_PtrFree( vSupp );
+ }
+ qsort( (void *)pPerms, Abc_NtkCoNum(pNtk), sizeof(int), (int (*)(const void *, const void *)) Abc_NtkCompareConesCompare );
+
+ // consider COs in this order
+ Iter = 0;
+ Abc_NtkForEachCo( pNtk, pObj, i )
+ {
+ pObj = Abc_NtkCo( pNtk, pPerms[i] );
+ if ( pObj->fMarkA )
+ continue;
+ Iter++;
+
+ vSupp = Abc_NtkNodeSupport( pNtk, &pObj, 1 );
+ vNodes = Abc_NtkDfsNodes( pNtk, &pObj, 1 );
+ vReverse = Abc_NtkDfsReverseNodesContained( pNtk, (Abc_Obj_t **)Vec_PtrArray(vSupp), Vec_PtrSize(vSupp) );
+ // count the number of nodes in the reverse cone
+ Counter = 0;
+ for ( k = 1; k < Vec_PtrSize(vReverse) - 1; k++ )
+ for ( pTemp = Vec_PtrEntry(vReverse, k); pTemp; pTemp = pTemp->pCopy )
+ Counter++;
+ CounterCos = CounterCosNew = 0;
+ for ( pTemp = Vec_PtrEntryLast(vReverse); pTemp; pTemp = pTemp->pCopy )
+ {
+ assert( Abc_ObjIsCo(pTemp) );
+ CounterCos++;
+ if ( pTemp->fMarkA == 0 )
+ CounterCosNew++;
+ pTemp->fMarkA = 1;
+ }
+ // print statistics
+ printf( "%4d CO %5d : Supp = %5d. Lev = %3d. Cone = %5d. Rev = %5d. COs = %3d (%3d).\n",
+ Iter, pPerms[i], Vec_PtrSize(vSupp), Abc_ObjLevel(Abc_ObjFanin0(pObj)), Vec_PtrSize(vNodes), Counter, CounterCos, CounterCosNew );
+
+ // free arrays
+ Vec_PtrFree( vSupp );
+ Vec_PtrFree( vNodes );
+ Vec_PtrFree( vReverse );
+
+ if ( Vec_PtrSize(vSupp) < 10 )
+ break;
+ }
+ Abc_NtkForEachCo( pNtk, pObj, i )
+ pObj->fMarkA = 0;
+
+ free( pPerms );
+ free( pSupps );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Analyze choice node support.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Abc_NtkCompareSupports( Abc_Ntk_t * pNtk )
+{
+ Vec_Ptr_t * vSupp;
+ Abc_Obj_t * pObj, * pTemp;
+ int i, nNodesOld;
+ assert( Abc_NtkIsStrash(pNtk) );
+ Abc_AigForEachAnd( pNtk, pObj, i )
+ {
+ if ( !Abc_AigNodeIsChoice(pObj) )
+ continue;
+
+ vSupp = Abc_NtkNodeSupport( pNtk, &pObj, 1 );
+ nNodesOld = Vec_PtrSize(vSupp);
+ Vec_PtrFree( vSupp );
+
+ for ( pTemp = pObj->pData; pTemp; pTemp = pTemp->pData )
+ {
+ vSupp = Abc_NtkNodeSupport( pNtk, &pTemp, 1 );
+ if ( nNodesOld != Vec_PtrSize(vSupp) )
+ printf( "Choice orig = %3d Choice new = %3d\n", nNodesOld, Vec_PtrSize(vSupp) );
+ Vec_PtrFree( vSupp );
+ }
+ }
+}
////////////////////////////////////////////////////////////////////////
/// END OF FILE ///
diff --git a/src/base/abc/abc_.c b/src/base/abc/abc_.c
index bef3836f..50558bdb 100644
--- a/src/base/abc/abc_.c
+++ b/src/base/abc/abc_.c
@@ -25,7 +25,7 @@
////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////
-/// FUNCTION DEFITIONS ///
+/// FUNCTION DEFINITIONS ///
////////////////////////////////////////////////////////////////////////
/**Function*************************************************************
diff --git a/src/base/abc/module.make b/src/base/abc/module.make
index 649e71a2..7b34d8f6 100644
--- a/src/base/abc/module.make
+++ b/src/base/abc/module.make
@@ -1,9 +1,12 @@
SRC += src/base/abc/abcAig.c \
+ src/base/abc/abcBlifMv.c \
src/base/abc/abcCheck.c \
src/base/abc/abcDfs.c \
src/base/abc/abcFanio.c \
src/base/abc/abcFunc.c \
+ src/base/abc/abcHie.c \
src/base/abc/abcLatch.c \
+ src/base/abc/abcLib.c \
src/base/abc/abcMinBase.c \
src/base/abc/abcNames.c \
src/base/abc/abcNetlist.c \
diff --git a/src/base/abci/abc.c b/src/base/abci/abc.c
index e067a646..f0905155 100644
--- a/src/base/abci/abc.c
+++ b/src/base/abci/abc.c
@@ -23,81 +23,178 @@
#include "fraig.h"
#include "fxu.h"
#include "cut.h"
+#include "fpga.h"
+#include "if.h"
+#include "res.h"
+#include "lpk.h"
+#include "aig.h"
+#include "dar.h"
////////////////////////////////////////////////////////////////////////
/// DECLARATIONS ///
////////////////////////////////////////////////////////////////////////
-static int Abc_CommandPrintStats ( Abc_Frame_t * pAbc, int argc, char ** argv );
-static int Abc_CommandPrintIo ( Abc_Frame_t * pAbc, int argc, char ** argv );
-static int Abc_CommandPrintLatch ( Abc_Frame_t * pAbc, int argc, char ** argv );
-static int Abc_CommandPrintFanio ( Abc_Frame_t * pAbc, int argc, char ** argv );
-static int Abc_CommandPrintFactor ( Abc_Frame_t * pAbc, int argc, char ** argv );
-static int Abc_CommandPrintLevel ( Abc_Frame_t * pAbc, int argc, char ** argv );
-static int Abc_CommandPrintSupport ( Abc_Frame_t * pAbc, int argc, char ** argv );
-static int Abc_CommandPrintSymms ( Abc_Frame_t * pAbc, int argc, char ** argv );
-
-static int Abc_CommandShowBdd ( Abc_Frame_t * pAbc, int argc, char ** argv );
-static int Abc_CommandShowCut ( Abc_Frame_t * pAbc, int argc, char ** argv );
-static int Abc_CommandShowAig ( Abc_Frame_t * pAbc, int argc, char ** argv );
-
-static int Abc_CommandCollapse ( Abc_Frame_t * pAbc, int argc, char ** argv );
-static int Abc_CommandStrash ( Abc_Frame_t * pAbc, int argc, char ** argv );
-static int Abc_CommandBalance ( Abc_Frame_t * pAbc, int argc, char ** argv );
-static int Abc_CommandRenode ( Abc_Frame_t * pAbc, int argc, char ** argv );
-static int Abc_CommandCleanup ( Abc_Frame_t * pAbc, int argc, char ** argv );
-static int Abc_CommandSweep ( Abc_Frame_t * pAbc, int argc, char ** argv );
-static int Abc_CommandFastExtract ( Abc_Frame_t * pAbc, int argc, char ** argv );
-static int Abc_CommandDisjoint ( Abc_Frame_t * pAbc, int argc, char ** argv );
-
-static int Abc_CommandRewrite ( Abc_Frame_t * pAbc, int argc, char ** argv );
-static int Abc_CommandRefactor ( Abc_Frame_t * pAbc, int argc, char ** argv );
-
-static int Abc_CommandLogic ( Abc_Frame_t * pAbc, int argc, char ** argv );
-static int Abc_CommandMiter ( Abc_Frame_t * pAbc, int argc, char ** argv );
-static int Abc_CommandFrames ( Abc_Frame_t * pAbc, int argc, char ** argv );
-static int Abc_CommandSop ( Abc_Frame_t * pAbc, int argc, char ** argv );
-static int Abc_CommandBdd ( Abc_Frame_t * pAbc, int argc, char ** argv );
-static int Abc_CommandMuxes ( Abc_Frame_t * pAbc, int argc, char ** argv );
-static int Abc_CommandSat ( Abc_Frame_t * pAbc, int argc, char ** argv );
-static int Abc_CommandExtSeqDcs ( Abc_Frame_t * pAbc, int argc, char ** argv );
-static int Abc_CommandOneOutput ( Abc_Frame_t * pAbc, int argc, char ** argv );
-static int Abc_CommandOneNode ( Abc_Frame_t * pAbc, int argc, char ** argv );
-static int Abc_CommandShortNames ( Abc_Frame_t * pAbc, int argc, char ** argv );
-static int Abc_CommandCut ( Abc_Frame_t * pAbc, int argc, char ** argv );
-static int Abc_CommandTest ( Abc_Frame_t * pAbc, int argc, char ** argv );
-
-static int Abc_CommandFraig ( Abc_Frame_t * pAbc, int argc, char ** argv );
-static int Abc_CommandFraigTrust ( Abc_Frame_t * pAbc, int argc, char ** argv );
-static int Abc_CommandFraigStore ( Abc_Frame_t * pAbc, int argc, char ** argv );
-static int Abc_CommandFraigRestore ( Abc_Frame_t * pAbc, int argc, char ** argv );
-static int Abc_CommandFraigClean ( Abc_Frame_t * pAbc, int argc, char ** argv );
-static int Abc_CommandFraigSweep ( Abc_Frame_t * pAbc, int argc, char ** argv );
-
-static int Abc_CommandMap ( Abc_Frame_t * pAbc, int argc, char ** argv );
-static int Abc_CommandUnmap ( Abc_Frame_t * pAbc, int argc, char ** argv );
-static int Abc_CommandAttach ( Abc_Frame_t * pAbc, int argc, char ** argv );
-static int Abc_CommandSuperChoice ( Abc_Frame_t * pAbc, int argc, char ** argv );
-
-static int Abc_CommandFpga ( Abc_Frame_t * pAbc, int argc, char ** argv );
-
-static int Abc_CommandSeq ( Abc_Frame_t * pAbc, int argc, char ** argv );
-static int Abc_CommandRetime ( Abc_Frame_t * pAbc, int argc, char ** argv );
-
-static int Abc_CommandCec ( Abc_Frame_t * pAbc, int argc, char ** argv );
-static int Abc_CommandSec ( Abc_Frame_t * pAbc, int argc, char ** argv );
-
-static int Abc_CommandDar ( Abc_Frame_t * pAbc, int argc, char ** argv );
-static int Abc_CommandDar ( Abc_Frame_t * pAbc, int argc, char ** argv );
-static int Abc_CommandDar ( Abc_Frame_t * pAbc, int argc, char ** argv );
-
-static int Abc_CommandSeqCleanup ( Abc_Frame_t * pAbc, int argc, char ** argv );
-static int Abc_CommandLcorr ( Abc_Frame_t * pAbc, int argc, char ** argv );
-static int Abc_CommandSeqSweep ( Abc_Frame_t * pAbc, int argc, char ** argv );
-static int Abc_CommandDSec ( Abc_Frame_t * pAbc, int argc, char ** argv );
+static int Abc_CommandPrintStats ( Abc_Frame_t * pAbc, int argc, char ** argv );
+static int Abc_CommandPrintExdc ( Abc_Frame_t * pAbc, int argc, char ** argv );
+static int Abc_CommandPrintIo ( Abc_Frame_t * pAbc, int argc, char ** argv );
+static int Abc_CommandPrintLatch ( Abc_Frame_t * pAbc, int argc, char ** argv );
+static int Abc_CommandPrintFanio ( Abc_Frame_t * pAbc, int argc, char ** argv );
+static int Abc_CommandPrintMffc ( Abc_Frame_t * pAbc, int argc, char ** argv );
+static int Abc_CommandPrintFactor ( Abc_Frame_t * pAbc, int argc, char ** argv );
+static int Abc_CommandPrintLevel ( Abc_Frame_t * pAbc, int argc, char ** argv );
+static int Abc_CommandPrintSupport ( Abc_Frame_t * pAbc, int argc, char ** argv );
+static int Abc_CommandPrintSymms ( Abc_Frame_t * pAbc, int argc, char ** argv );
+static int Abc_CommandPrintUnate ( Abc_Frame_t * pAbc, int argc, char ** argv );
+static int Abc_CommandPrintAuto ( Abc_Frame_t * pAbc, int argc, char ** argv );
+static int Abc_CommandPrintKMap ( Abc_Frame_t * pAbc, int argc, char ** argv );
+static int Abc_CommandPrintGates ( Abc_Frame_t * pAbc, int argc, char ** argv );
+static int Abc_CommandPrintSharing ( Abc_Frame_t * pAbc, int argc, char ** argv );
+static int Abc_CommandPrintXCut ( Abc_Frame_t * pAbc, int argc, char ** argv );
+static int Abc_CommandPrintDsd ( Abc_Frame_t * pAbc, int argc, char ** argv );
+
+static int Abc_CommandShow ( Abc_Frame_t * pAbc, int argc, char ** argv );
+static int Abc_CommandShowBdd ( Abc_Frame_t * pAbc, int argc, char ** argv );
+static int Abc_CommandShowCut ( Abc_Frame_t * pAbc, int argc, char ** argv );
+
+static int Abc_CommandCollapse ( Abc_Frame_t * pAbc, int argc, char ** argv );
+static int Abc_CommandStrash ( Abc_Frame_t * pAbc, int argc, char ** argv );
+static int Abc_CommandBalance ( Abc_Frame_t * pAbc, int argc, char ** argv );
+static int Abc_CommandMulti ( Abc_Frame_t * pAbc, int argc, char ** argv );
+static int Abc_CommandRenode ( Abc_Frame_t * pAbc, int argc, char ** argv );
+static int Abc_CommandCleanup ( Abc_Frame_t * pAbc, int argc, char ** argv );
+static int Abc_CommandSweep ( Abc_Frame_t * pAbc, int argc, char ** argv );
+static int Abc_CommandFastExtract ( Abc_Frame_t * pAbc, int argc, char ** argv );
+static int Abc_CommandEliminate ( Abc_Frame_t * pAbc, int argc, char ** argv );
+static int Abc_CommandDisjoint ( Abc_Frame_t * pAbc, int argc, char ** argv );
+static int Abc_CommandImfs ( Abc_Frame_t * pAbc, int argc, char ** argv );
+static int Abc_CommandLutpack ( Abc_Frame_t * pAbc, int argc, char ** argv );
+
+static int Abc_CommandRewrite ( Abc_Frame_t * pAbc, int argc, char ** argv );
+static int Abc_CommandRefactor ( Abc_Frame_t * pAbc, int argc, char ** argv );
+static int Abc_CommandRestructure ( Abc_Frame_t * pAbc, int argc, char ** argv );
+static int Abc_CommandResubstitute ( Abc_Frame_t * pAbc, int argc, char ** argv );
+static int Abc_CommandRr ( Abc_Frame_t * pAbc, int argc, char ** argv );
+static int Abc_CommandCascade ( Abc_Frame_t * pAbc, int argc, char ** argv );
+
+static int Abc_CommandLogic ( Abc_Frame_t * pAbc, int argc, char ** argv );
+static int Abc_CommandComb ( Abc_Frame_t * pAbc, int argc, char ** argv );
+static int Abc_CommandMiter ( Abc_Frame_t * pAbc, int argc, char ** argv );
+static int Abc_CommandDemiter ( Abc_Frame_t * pAbc, int argc, char ** argv );
+static int Abc_CommandOrPos ( Abc_Frame_t * pAbc, int argc, char ** argv );
+static int Abc_CommandAndPos ( Abc_Frame_t * pAbc, int argc, char ** argv );
+static int Abc_CommandAppend ( Abc_Frame_t * pAbc, int argc, char ** argv );
+static int Abc_CommandFrames ( Abc_Frame_t * pAbc, int argc, char ** argv );
+static int Abc_CommandSop ( Abc_Frame_t * pAbc, int argc, char ** argv );
+static int Abc_CommandBdd ( Abc_Frame_t * pAbc, int argc, char ** argv );
+static int Abc_CommandAig ( Abc_Frame_t * pAbc, int argc, char ** argv );
+static int Abc_CommandReorder ( Abc_Frame_t * pAbc, int argc, char ** argv );
+static int Abc_CommandOrder ( Abc_Frame_t * pAbc, int argc, char ** argv );
+static int Abc_CommandMuxes ( Abc_Frame_t * pAbc, int argc, char ** argv );
+static int Abc_CommandExtSeqDcs ( Abc_Frame_t * pAbc, int argc, char ** argv );
+static int Abc_CommandCone ( Abc_Frame_t * pAbc, int argc, char ** argv );
+static int Abc_CommandNode ( Abc_Frame_t * pAbc, int argc, char ** argv );
+static int Abc_CommandTopmost ( Abc_Frame_t * pAbc, int argc, char ** argv );
+static int Abc_CommandTrim ( Abc_Frame_t * pAbc, int argc, char ** argv );
+static int Abc_CommandShortNames ( Abc_Frame_t * pAbc, int argc, char ** argv );
+static int Abc_CommandExdcFree ( Abc_Frame_t * pAbc, int argc, char ** argv );
+static int Abc_CommandExdcGet ( Abc_Frame_t * pAbc, int argc, char ** argv );
+static int Abc_CommandExdcSet ( Abc_Frame_t * pAbc, int argc, char ** argv );
+static int Abc_CommandCut ( Abc_Frame_t * pAbc, int argc, char ** argv );
+static int Abc_CommandEspresso ( Abc_Frame_t * pAbc, int argc, char ** argv );
+static int Abc_CommandGen ( Abc_Frame_t * pAbc, int argc, char ** argv );
+//static int Abc_CommandXyz ( Abc_Frame_t * pAbc, int argc, char ** argv );
+static int Abc_CommandDouble ( Abc_Frame_t * pAbc, int argc, char ** argv );
+static int Abc_CommandInter ( Abc_Frame_t * pAbc, int argc, char ** argv );
+static int Abc_CommandTest ( Abc_Frame_t * pAbc, int argc, char ** argv );
+
+static int Abc_CommandQuaVar ( Abc_Frame_t * pAbc, int argc, char ** argv );
+static int Abc_CommandQuaRel ( Abc_Frame_t * pAbc, int argc, char ** argv );
+static int Abc_CommandQuaReach ( Abc_Frame_t * pAbc, int argc, char ** argv );
+
+static int Abc_CommandIStrash ( Abc_Frame_t * pAbc, int argc, char ** argv );
+static int Abc_CommandICut ( Abc_Frame_t * pAbc, int argc, char ** argv );
+static int Abc_CommandIRewrite ( Abc_Frame_t * pAbc, int argc, char ** argv );
+static int Abc_CommandDRewrite ( Abc_Frame_t * pAbc, int argc, char ** argv );
+static int Abc_CommandDRefactor ( Abc_Frame_t * pAbc, int argc, char ** argv );
+static int Abc_CommandDCompress2 ( Abc_Frame_t * pAbc, int argc, char ** argv );
+static int Abc_CommandDChoice ( Abc_Frame_t * pAbc, int argc, char ** argv );
+static int Abc_CommandDrwsat ( Abc_Frame_t * pAbc, int argc, char ** argv );
+static int Abc_CommandIRewriteSeq ( Abc_Frame_t * pAbc, int argc, char ** argv );
+static int Abc_CommandIResyn ( Abc_Frame_t * pAbc, int argc, char ** argv );
+static int Abc_CommandISat ( Abc_Frame_t * pAbc, int argc, char ** argv );
+static int Abc_CommandIFraig ( Abc_Frame_t * pAbc, int argc, char ** argv );
+static int Abc_CommandDFraig ( Abc_Frame_t * pAbc, int argc, char ** argv );
+static int Abc_CommandCSweep ( Abc_Frame_t * pAbc, int argc, char ** argv );
+static int Abc_CommandDProve ( Abc_Frame_t * pAbc, int argc, char ** argv );
+static int Abc_CommandHaig ( Abc_Frame_t * pAbc, int argc, char ** argv );
+static int Abc_CommandMini ( Abc_Frame_t * pAbc, int argc, char ** argv );
+static int Abc_CommandQbf ( Abc_Frame_t * pAbc, int argc, char ** argv );
+
+static int Abc_CommandFraig ( Abc_Frame_t * pAbc, int argc, char ** argv );
+static int Abc_CommandFraigTrust ( Abc_Frame_t * pAbc, int argc, char ** argv );
+static int Abc_CommandFraigStore ( Abc_Frame_t * pAbc, int argc, char ** argv );
+static int Abc_CommandFraigRestore ( Abc_Frame_t * pAbc, int argc, char ** argv );
+static int Abc_CommandFraigClean ( Abc_Frame_t * pAbc, int argc, char ** argv );
+static int Abc_CommandFraigSweep ( Abc_Frame_t * pAbc, int argc, char ** argv );
+static int Abc_CommandFraigDress ( Abc_Frame_t * pAbc, int argc, char ** argv );
+
+static int Abc_CommandHaigStart ( Abc_Frame_t * pAbc, int argc, char ** argv );
+static int Abc_CommandHaigStop ( Abc_Frame_t * pAbc, int argc, char ** argv );
+static int Abc_CommandHaigUse ( Abc_Frame_t * pAbc, int argc, char ** argv );
+
+static int Abc_CommandRecStart ( Abc_Frame_t * pAbc, int argc, char ** argv );
+static int Abc_CommandRecStop ( Abc_Frame_t * pAbc, int argc, char ** argv );
+static int Abc_CommandRecAdd ( Abc_Frame_t * pAbc, int argc, char ** argv );
+static int Abc_CommandRecPs ( Abc_Frame_t * pAbc, int argc, char ** argv );
+static int Abc_CommandRecUse ( Abc_Frame_t * pAbc, int argc, char ** argv );
+
+static int Abc_CommandMap ( Abc_Frame_t * pAbc, int argc, char ** argv );
+static int Abc_CommandUnmap ( Abc_Frame_t * pAbc, int argc, char ** argv );
+static int Abc_CommandAttach ( Abc_Frame_t * pAbc, int argc, char ** argv );
+static int Abc_CommandSuperChoice ( Abc_Frame_t * pAbc, int argc, char ** argv );
+static int Abc_CommandSuperChoiceLut ( Abc_Frame_t * pAbc, int argc, char ** argv );
+
+static int Abc_CommandFpga ( Abc_Frame_t * pAbc, int argc, char ** argv );
+static int Abc_CommandFpgaFast ( Abc_Frame_t * pAbc, int argc, char ** argv );
+static int Abc_CommandIf ( Abc_Frame_t * pAbc, int argc, char ** argv );
+
+static int Abc_CommandScut ( Abc_Frame_t * pAbc, int argc, char ** argv );
+static int Abc_CommandInit ( Abc_Frame_t * pAbc, int argc, char ** argv );
+static int Abc_CommandZero ( Abc_Frame_t * pAbc, int argc, char ** argv );
+static int Abc_CommandUndc ( Abc_Frame_t * pAbc, int argc, char ** argv );
+static int Abc_CommandPipe ( Abc_Frame_t * pAbc, int argc, char ** argv );
+static int Abc_CommandSeq ( Abc_Frame_t * pAbc, int argc, char ** argv );
+static int Abc_CommandUnseq ( Abc_Frame_t * pAbc, int argc, char ** argv );
+static int Abc_CommandRetime ( Abc_Frame_t * pAbc, int argc, char ** argv );
+static int Abc_CommandDRetime ( Abc_Frame_t * pAbc, int argc, char ** argv );
+static int Abc_CommandFlowRetime ( Abc_Frame_t * pAbc, int argc, char ** argv );
+static int Abc_CommandSeqFpga ( Abc_Frame_t * pAbc, int argc, char ** argv );
+static int Abc_CommandSeqMap ( Abc_Frame_t * pAbc, int argc, char ** argv );
+static int Abc_CommandSeqSweep ( Abc_Frame_t * pAbc, int argc, char ** argv );
+static int Abc_CommandLcorr ( Abc_Frame_t * pAbc, int argc, char ** argv );
+static int Abc_CommandSeqCleanup ( Abc_Frame_t * pAbc, int argc, char ** argv );
+static int Abc_CommandCycle ( Abc_Frame_t * pAbc, int argc, char ** argv );
+static int Abc_CommandXsim ( Abc_Frame_t * pAbc, int argc, char ** argv );
+static int Abc_CommandSim ( Abc_Frame_t * pAbc, int argc, char ** argv );
+
+static int Abc_CommandCec ( Abc_Frame_t * pAbc, int argc, char ** argv );
+static int Abc_CommandDCec ( Abc_Frame_t * pAbc, int argc, char ** argv );
+static int Abc_CommandSec ( Abc_Frame_t * pAbc, int argc, char ** argv );
+static int Abc_CommandDSec ( Abc_Frame_t * pAbc, int argc, char ** argv );
+static int Abc_CommandSat ( Abc_Frame_t * pAbc, int argc, char ** argv );
+static int Abc_CommandDSat ( Abc_Frame_t * pAbc, int argc, char ** argv );
+static int Abc_CommandProve ( Abc_Frame_t * pAbc, int argc, char ** argv );
+static int Abc_CommandIProve ( Abc_Frame_t * pAbc, int argc, char ** argv );
+static int Abc_CommandDebug ( Abc_Frame_t * pAbc, int argc, char ** argv );
+static int Abc_CommandBmc ( Abc_Frame_t * pAbc, int argc, char ** argv );
+static int Abc_CommandIndcut ( Abc_Frame_t * pAbc, int argc, char ** argv );
+static int Abc_CommandEnlarge ( Abc_Frame_t * pAbc, int argc, char ** argv );
+
+static int Abc_CommandTraceStart ( Abc_Frame_t * pAbc, int argc, char ** argv );
+static int Abc_CommandTraceCheck ( Abc_Frame_t * pAbc, int argc, char ** argv );
////////////////////////////////////////////////////////////////////////
-/// FUNCTION DEFITIONS ///
+/// FUNCTION DEFINITIONS ///
////////////////////////////////////////////////////////////////////////
/**Function*************************************************************
@@ -113,78 +210,178 @@ static int Abc_CommandDSec ( Abc_Frame_t * pAbc, int argc, char ** argv
***********************************************************************/
void Abc_Init( Abc_Frame_t * pAbc )
{
+// Abc_NtkBddImplicationTest();
+
Cmd_CommandAdd( pAbc, "Printing", "print_stats", Abc_CommandPrintStats, 0 );
+ Cmd_CommandAdd( pAbc, "Printing", "print_exdc", Abc_CommandPrintExdc, 0 );
Cmd_CommandAdd( pAbc, "Printing", "print_io", Abc_CommandPrintIo, 0 );
Cmd_CommandAdd( pAbc, "Printing", "print_latch", Abc_CommandPrintLatch, 0 );
Cmd_CommandAdd( pAbc, "Printing", "print_fanio", Abc_CommandPrintFanio, 0 );
+ Cmd_CommandAdd( pAbc, "Printing", "print_mffc", Abc_CommandPrintMffc, 0 );
Cmd_CommandAdd( pAbc, "Printing", "print_factor", Abc_CommandPrintFactor, 0 );
Cmd_CommandAdd( pAbc, "Printing", "print_level", Abc_CommandPrintLevel, 0 );
Cmd_CommandAdd( pAbc, "Printing", "print_supp", Abc_CommandPrintSupport, 0 );
Cmd_CommandAdd( pAbc, "Printing", "print_symm", Abc_CommandPrintSymms, 0 );
-
+ Cmd_CommandAdd( pAbc, "Printing", "print_unate", Abc_CommandPrintUnate, 0 );
+ Cmd_CommandAdd( pAbc, "Printing", "print_auto", Abc_CommandPrintAuto, 0 );
+ Cmd_CommandAdd( pAbc, "Printing", "print_kmap", Abc_CommandPrintKMap, 0 );
+ Cmd_CommandAdd( pAbc, "Printing", "print_gates", Abc_CommandPrintGates, 0 );
+ Cmd_CommandAdd( pAbc, "Printing", "print_sharing", Abc_CommandPrintSharing, 0 );
+ Cmd_CommandAdd( pAbc, "Printing", "print_xcut", Abc_CommandPrintXCut, 0 );
+ Cmd_CommandAdd( pAbc, "Printing", "print_dsd", Abc_CommandPrintDsd, 0 );
+
+ Cmd_CommandAdd( pAbc, "Printing", "show", Abc_CommandShow, 0 );
Cmd_CommandAdd( pAbc, "Printing", "show_bdd", Abc_CommandShowBdd, 0 );
Cmd_CommandAdd( pAbc, "Printing", "show_cut", Abc_CommandShowCut, 0 );
- Cmd_CommandAdd( pAbc, "Printing", "show_aig", Abc_CommandShowAig, 0 );
Cmd_CommandAdd( pAbc, "Synthesis", "collapse", Abc_CommandCollapse, 1 );
Cmd_CommandAdd( pAbc, "Synthesis", "strash", Abc_CommandStrash, 1 );
Cmd_CommandAdd( pAbc, "Synthesis", "balance", Abc_CommandBalance, 1 );
+ Cmd_CommandAdd( pAbc, "Synthesis", "multi", Abc_CommandMulti, 1 );
Cmd_CommandAdd( pAbc, "Synthesis", "renode", Abc_CommandRenode, 1 );
Cmd_CommandAdd( pAbc, "Synthesis", "cleanup", Abc_CommandCleanup, 1 );
Cmd_CommandAdd( pAbc, "Synthesis", "sweep", Abc_CommandSweep, 1 );
Cmd_CommandAdd( pAbc, "Synthesis", "fx", Abc_CommandFastExtract, 1 );
+ Cmd_CommandAdd( pAbc, "Synthesis", "eliminate", Abc_CommandEliminate, 1 );
Cmd_CommandAdd( pAbc, "Synthesis", "dsd", Abc_CommandDisjoint, 1 );
+ Cmd_CommandAdd( pAbc, "Synthesis", "imfs", Abc_CommandImfs, 1 );
+ Cmd_CommandAdd( pAbc, "Synthesis", "lutpack", Abc_CommandLutpack, 1 );
Cmd_CommandAdd( pAbc, "Synthesis", "rewrite", Abc_CommandRewrite, 1 );
Cmd_CommandAdd( pAbc, "Synthesis", "refactor", Abc_CommandRefactor, 1 );
+// Cmd_CommandAdd( pAbc, "Synthesis", "restructure", Abc_CommandRestructure, 1 );
+ Cmd_CommandAdd( pAbc, "Synthesis", "resub", Abc_CommandResubstitute, 1 );
+ Cmd_CommandAdd( pAbc, "Synthesis", "rr", Abc_CommandRr, 1 );
+ Cmd_CommandAdd( pAbc, "Synthesis", "cascade", Abc_CommandCascade, 1 );
Cmd_CommandAdd( pAbc, "Various", "logic", Abc_CommandLogic, 1 );
+ Cmd_CommandAdd( pAbc, "Various", "comb", Abc_CommandComb, 1 );
Cmd_CommandAdd( pAbc, "Various", "miter", Abc_CommandMiter, 1 );
+ Cmd_CommandAdd( pAbc, "Various", "demiter", Abc_CommandDemiter, 1 );
+ Cmd_CommandAdd( pAbc, "Various", "orpos", Abc_CommandOrPos, 1 );
+ Cmd_CommandAdd( pAbc, "Various", "andpos", Abc_CommandAndPos, 1 );
+ Cmd_CommandAdd( pAbc, "Various", "append", Abc_CommandAppend, 1 );
Cmd_CommandAdd( pAbc, "Various", "frames", Abc_CommandFrames, 1 );
Cmd_CommandAdd( pAbc, "Various", "sop", Abc_CommandSop, 0 );
Cmd_CommandAdd( pAbc, "Various", "bdd", Abc_CommandBdd, 0 );
+ Cmd_CommandAdd( pAbc, "Various", "aig", Abc_CommandAig, 0 );
+ Cmd_CommandAdd( pAbc, "Various", "reorder", Abc_CommandReorder, 0 );
+ Cmd_CommandAdd( pAbc, "Various", "order", Abc_CommandOrder, 0 );
Cmd_CommandAdd( pAbc, "Various", "muxes", Abc_CommandMuxes, 1 );
- Cmd_CommandAdd( pAbc, "Various", "sat", Abc_CommandSat, 0 );
Cmd_CommandAdd( pAbc, "Various", "ext_seq_dcs", Abc_CommandExtSeqDcs, 0 );
- Cmd_CommandAdd( pAbc, "Various", "one_output", Abc_CommandOneOutput, 1 );
- Cmd_CommandAdd( pAbc, "Various", "one_node", Abc_CommandOneNode, 1 );
+ Cmd_CommandAdd( pAbc, "Various", "cone", Abc_CommandCone, 1 );
+ Cmd_CommandAdd( pAbc, "Various", "node", Abc_CommandNode, 1 );
+ Cmd_CommandAdd( pAbc, "Various", "topmost", Abc_CommandTopmost, 1 );
+ Cmd_CommandAdd( pAbc, "Various", "trim", Abc_CommandTrim, 1 );
Cmd_CommandAdd( pAbc, "Various", "short_names", Abc_CommandShortNames, 0 );
+ Cmd_CommandAdd( pAbc, "Various", "exdc_free", Abc_CommandExdcFree, 1 );
+ Cmd_CommandAdd( pAbc, "Various", "exdc_get", Abc_CommandExdcGet, 1 );
+ Cmd_CommandAdd( pAbc, "Various", "exdc_set", Abc_CommandExdcSet, 1 );
Cmd_CommandAdd( pAbc, "Various", "cut", Abc_CommandCut, 0 );
+ Cmd_CommandAdd( pAbc, "Various", "espresso", Abc_CommandEspresso, 1 );
+ Cmd_CommandAdd( pAbc, "Various", "gen", Abc_CommandGen, 0 );
+// Cmd_CommandAdd( pAbc, "Various", "xyz", Abc_CommandXyz, 1 );
+ Cmd_CommandAdd( pAbc, "Various", "double", Abc_CommandDouble, 1 );
+ Cmd_CommandAdd( pAbc, "Various", "inter", Abc_CommandInter, 1 );
Cmd_CommandAdd( pAbc, "Various", "test", Abc_CommandTest, 0 );
+ Cmd_CommandAdd( pAbc, "Various", "qvar", Abc_CommandQuaVar, 1 );
+ Cmd_CommandAdd( pAbc, "Various", "qrel", Abc_CommandQuaRel, 1 );
+ Cmd_CommandAdd( pAbc, "Various", "qreach", Abc_CommandQuaReach, 1 );
+
+ Cmd_CommandAdd( pAbc, "New AIG", "istrash", Abc_CommandIStrash, 1 );
+ Cmd_CommandAdd( pAbc, "New AIG", "icut", Abc_CommandICut, 0 );
+ Cmd_CommandAdd( pAbc, "New AIG", "irw", Abc_CommandIRewrite, 1 );
+ Cmd_CommandAdd( pAbc, "New AIG", "drw", Abc_CommandDRewrite, 1 );
+ Cmd_CommandAdd( pAbc, "New AIG", "drf", Abc_CommandDRefactor, 1 );
+ Cmd_CommandAdd( pAbc, "New AIG", "dcompress2", Abc_CommandDCompress2, 1 );
+ Cmd_CommandAdd( pAbc, "New AIG", "dchoice", Abc_CommandDChoice, 1 );
+ Cmd_CommandAdd( pAbc, "New AIG", "drwsat", Abc_CommandDrwsat, 1 );
+ Cmd_CommandAdd( pAbc, "New AIG", "irws", Abc_CommandIRewriteSeq, 1 );
+ Cmd_CommandAdd( pAbc, "New AIG", "iresyn", Abc_CommandIResyn, 1 );
+ Cmd_CommandAdd( pAbc, "New AIG", "isat", Abc_CommandISat, 1 );
+ Cmd_CommandAdd( pAbc, "New AIG", "ifraig", Abc_CommandIFraig, 1 );
+ Cmd_CommandAdd( pAbc, "New AIG", "dfraig", Abc_CommandDFraig, 1 );
+ Cmd_CommandAdd( pAbc, "New AIG", "csweep", Abc_CommandCSweep, 1 );
+ Cmd_CommandAdd( pAbc, "New AIG", "haig", Abc_CommandHaig, 1 );
+ Cmd_CommandAdd( pAbc, "New AIG", "mini", Abc_CommandMini, 1 );
+ Cmd_CommandAdd( pAbc, "New AIG", "qbf", Abc_CommandQbf, 0 );
+
Cmd_CommandAdd( pAbc, "Fraiging", "fraig", Abc_CommandFraig, 1 );
Cmd_CommandAdd( pAbc, "Fraiging", "fraig_trust", Abc_CommandFraigTrust, 1 );
Cmd_CommandAdd( pAbc, "Fraiging", "fraig_store", Abc_CommandFraigStore, 0 );
Cmd_CommandAdd( pAbc, "Fraiging", "fraig_restore", Abc_CommandFraigRestore, 1 );
Cmd_CommandAdd( pAbc, "Fraiging", "fraig_clean", Abc_CommandFraigClean, 0 );
Cmd_CommandAdd( pAbc, "Fraiging", "fraig_sweep", Abc_CommandFraigSweep, 1 );
+ Cmd_CommandAdd( pAbc, "Fraiging", "dress", Abc_CommandFraigDress, 1 );
+
+ Cmd_CommandAdd( pAbc, "Choicing", "haig_start", Abc_CommandHaigStart, 0 );
+ Cmd_CommandAdd( pAbc, "Choicing", "haig_stop", Abc_CommandHaigStop, 0 );
+ Cmd_CommandAdd( pAbc, "Choicing", "haig_use", Abc_CommandHaigUse, 1 );
+
+ Cmd_CommandAdd( pAbc, "Choicing", "rec_start", Abc_CommandRecStart, 0 );
+ Cmd_CommandAdd( pAbc, "Choicing", "rec_stop", Abc_CommandRecStop, 0 );
+ Cmd_CommandAdd( pAbc, "Choicing", "rec_add", Abc_CommandRecAdd, 0 );
+ Cmd_CommandAdd( pAbc, "Choicing", "rec_ps", Abc_CommandRecPs, 0 );
+ Cmd_CommandAdd( pAbc, "Choicing", "rec_use", Abc_CommandRecUse, 1 );
Cmd_CommandAdd( pAbc, "SC mapping", "map", Abc_CommandMap, 1 );
Cmd_CommandAdd( pAbc, "SC mapping", "unmap", Abc_CommandUnmap, 1 );
Cmd_CommandAdd( pAbc, "SC mapping", "attach", Abc_CommandAttach, 1 );
Cmd_CommandAdd( pAbc, "SC mapping", "sc", Abc_CommandSuperChoice, 1 );
+ Cmd_CommandAdd( pAbc, "SC mapping", "scl", Abc_CommandSuperChoiceLut, 1 );
Cmd_CommandAdd( pAbc, "FPGA mapping", "fpga", Abc_CommandFpga, 1 );
-
- Cmd_CommandAdd( pAbc, "Sequential", "seq", Abc_CommandSeq, 1 );
+ Cmd_CommandAdd( pAbc, "FPGA mapping", "ffpga", Abc_CommandFpgaFast, 1 );
+ Cmd_CommandAdd( pAbc, "FPGA mapping", "if", Abc_CommandIf, 1 );
+
+// Cmd_CommandAdd( pAbc, "Sequential", "scut", Abc_CommandScut, 0 );
+ Cmd_CommandAdd( pAbc, "Sequential", "init", Abc_CommandInit, 1 );
+ Cmd_CommandAdd( pAbc, "Sequential", "zero", Abc_CommandZero, 1 );
+ Cmd_CommandAdd( pAbc, "Sequential", "undc", Abc_CommandUndc, 1 );
+// Cmd_CommandAdd( pAbc, "Sequential", "pipe", Abc_CommandPipe, 1 );
Cmd_CommandAdd( pAbc, "Sequential", "retime", Abc_CommandRetime, 1 );
+ Cmd_CommandAdd( pAbc, "Sequential", "dretime", Abc_CommandDRetime, 1 );
+ Cmd_CommandAdd( pAbc, "Sequential", "fretime", Abc_CommandFlowRetime, 1 );
+// Cmd_CommandAdd( pAbc, "Sequential", "sfpga", Abc_CommandSeqFpga, 1 );
+// Cmd_CommandAdd( pAbc, "Sequential", "smap", Abc_CommandSeqMap, 1 );
+ Cmd_CommandAdd( pAbc, "Sequential", "ssweep", Abc_CommandSeqSweep, 1 );
+ Cmd_CommandAdd( pAbc, "Sequential", "lcorr", Abc_CommandLcorr, 1 );
+ Cmd_CommandAdd( pAbc, "Sequential", "scleanup", Abc_CommandSeqCleanup, 1 );
+ Cmd_CommandAdd( pAbc, "Sequential", "cycle", Abc_CommandCycle, 1 );
+ Cmd_CommandAdd( pAbc, "Sequential", "xsim", Abc_CommandXsim, 0 );
+ Cmd_CommandAdd( pAbc, "Sequential", "sim", Abc_CommandSim, 0 );
Cmd_CommandAdd( pAbc, "Verification", "cec", Abc_CommandCec, 0 );
+ Cmd_CommandAdd( pAbc, "Verification", "dcec", Abc_CommandDCec, 0 );
Cmd_CommandAdd( pAbc, "Verification", "sec", Abc_CommandSec, 0 );
+ Cmd_CommandAdd( pAbc, "Verification", "dsec", Abc_CommandDSec, 0 );
+ Cmd_CommandAdd( pAbc, "Verification", "dprove", Abc_CommandDProve, 0 );
+ Cmd_CommandAdd( pAbc, "Verification", "sat", Abc_CommandSat, 0 );
+ Cmd_CommandAdd( pAbc, "Verification", "dsat", Abc_CommandDSat, 0 );
+ Cmd_CommandAdd( pAbc, "Verification", "prove", Abc_CommandProve, 1 );
+ Cmd_CommandAdd( pAbc, "Verification", "iprove", Abc_CommandIProve, 1 );
+ Cmd_CommandAdd( pAbc, "Verification", "debug", Abc_CommandDebug, 0 );
+ Cmd_CommandAdd( pAbc, "Verification", "bmc", Abc_CommandBmc, 0 );
+ Cmd_CommandAdd( pAbc, "Verification", "indcut", Abc_CommandIndcut, 0 );
+ Cmd_CommandAdd( pAbc, "Verification", "enlarge", Abc_CommandEnlarge, 1 );
+
+// Cmd_CommandAdd( pAbc, "Verification", "trace_start", Abc_CommandTraceStart, 0 );
+// Cmd_CommandAdd( pAbc, "Verification", "trace_check", Abc_CommandTraceCheck, 0 );
// Rwt_Man4ExploreStart();
// Map_Var3Print();
// Map_Var4Test();
- Cmd_CommandAdd( pAbc, "Sequential", "scleanup", Abc_CommandSeqCleanup, 1 );
- Cmd_CommandAdd( pAbc, "Sequential", "lcorr", Abc_CommandLcorr, 1 );
- Cmd_CommandAdd( pAbc, "Sequential", "ssweep", Abc_CommandSeqSweep, 1 );
- Cmd_CommandAdd( pAbc, "Verification", "dsec", Abc_CommandDSec, 0 );
+// Abc_NtkPrint256();
+// Kit_TruthCountMintermsPrecomp();
+// Kit_DsdPrecompute4Vars();
+
{
extern void Dar_LibStart();
Dar_LibStart();
}
-}
+}
/**Function*************************************************************
@@ -199,16 +396,20 @@ void Abc_Init( Abc_Frame_t * pAbc )
***********************************************************************/
void Abc_End()
{
- Abc_NtkFraigStoreClean();
-// Rwt_Man4ExplorePrint();
- {
- extern void Dar_LibStop();
- Dar_LibStop();
- }
+// Dar_LibDumpPriorities();
+
{
extern void Cnf_ClearMemory();
Cnf_ClearMemory();
}
+ {
+ extern void Dar_LibStop();
+ Dar_LibStop();
+ }
+
+ Abc_NtkFraigStoreClean();
+// Rwt_Man4ExplorePrint();
+
}
/**Function*************************************************************
@@ -230,15 +431,15 @@ int Abc_CommandPrintStats( Abc_Frame_t * pAbc, int argc, char ** argv )
int c;
int fFactor;
- pNtk = Abc_FrameReadNet(pAbc);
+ pNtk = Abc_FrameReadNtk(pAbc);
pOut = Abc_FrameReadOut(pAbc);
pErr = Abc_FrameReadErr(pAbc);
// set the defaults
fShort = 1;
fFactor = 0;
- util_getopt_reset();
- while ( ( c = util_getopt( argc, argv, "sfh" ) ) != EOF )
+ Extra_UtilGetoptReset();
+ while ( ( c = Extra_UtilGetopt( argc, argv, "sfh" ) ) != EOF )
{
switch ( c )
{
@@ -257,7 +458,7 @@ int Abc_CommandPrintStats( Abc_Frame_t * pAbc, int argc, char ** argv )
if ( pNtk == NULL )
{
- fprintf( Abc_FrameReadErr(pAbc), "Empty network\n" );
+ fprintf( Abc_FrameReadErr(pAbc), "Empty network.\n" );
return 1;
}
Abc_NtkPrintStats( pOut, pNtk, fFactor );
@@ -265,7 +466,7 @@ int Abc_CommandPrintStats( Abc_Frame_t * pAbc, int argc, char ** argv )
usage:
fprintf( pErr, "usage: print_stats [-fh]\n" );
- fprintf( pErr, "\t prints the network statistics and\n" );
+ fprintf( pErr, "\t prints the network statistics\n" );
fprintf( pErr, "\t-f : toggles printing the literal count in the factored forms [default = %s]\n", fFactor? "yes": "no" );
fprintf( pErr, "\t-h : print the command usage\n");
return 1;
@@ -282,6 +483,98 @@ usage:
SeeAlso []
***********************************************************************/
+int Abc_CommandPrintExdc( Abc_Frame_t * pAbc, int argc, char ** argv )
+{
+ FILE * pOut, * pErr;
+ Abc_Ntk_t * pNtk, * pNtkTemp;
+ double Percentage;
+ bool fShort;
+ int c;
+ int fPrintDc;
+
+ extern double Abc_NtkSpacePercentage( Abc_Obj_t * pNode );
+
+ pNtk = Abc_FrameReadNtk(pAbc);
+ pOut = Abc_FrameReadOut(pAbc);
+ pErr = Abc_FrameReadErr(pAbc);
+
+ // set the defaults
+ fShort = 1;
+ fPrintDc = 0;
+ Extra_UtilGetoptReset();
+ while ( ( c = Extra_UtilGetopt( argc, argv, "sdh" ) ) != EOF )
+ {
+ switch ( c )
+ {
+ case 's':
+ fShort ^= 1;
+ break;
+ case 'd':
+ fPrintDc ^= 1;
+ break;
+ case 'h':
+ goto usage;
+ default:
+ goto usage;
+ }
+ }
+
+ if ( pNtk == NULL )
+ {
+ fprintf( Abc_FrameReadErr(pAbc), "Empty network.\n" );
+ return 1;
+ }
+ if ( pNtk->pExdc == NULL )
+ {
+ fprintf( Abc_FrameReadErr(pAbc), "Network has no EXDC.\n" );
+ return 1;
+ }
+
+ if ( fPrintDc )
+ {
+ if ( !Abc_NtkIsStrash(pNtk->pExdc) )
+ {
+ pNtkTemp = Abc_NtkStrash(pNtk->pExdc, 0, 0, 0);
+ Percentage = Abc_NtkSpacePercentage( Abc_ObjChild0( Abc_NtkPo(pNtkTemp, 0) ) );
+ Abc_NtkDelete( pNtkTemp );
+ }
+ else
+ Percentage = Abc_NtkSpacePercentage( Abc_ObjChild0( Abc_NtkPo(pNtk->pExdc, 0) ) );
+
+ printf( "EXDC network statistics: " );
+ printf( "(" );
+ if ( Percentage > 0.05 && Percentage < 99.95 )
+ printf( "%.2f", Percentage );
+ else if ( Percentage > 0.000005 && Percentage < 99.999995 )
+ printf( "%.6f", Percentage );
+ else
+ printf( "%f", Percentage );
+ printf( " %% don't-cares)\n" );
+ }
+ else
+ printf( "EXDC network statistics: \n" );
+ Abc_NtkPrintStats( pOut, pNtk->pExdc, 0 );
+ return 0;
+
+usage:
+ fprintf( pErr, "usage: print_exdc [-dh]\n" );
+ fprintf( pErr, "\t prints the EXDC network statistics\n" );
+ fprintf( pErr, "\t-d : toggles printing don't-care percentage [default = %s]\n", fPrintDc? "yes": "no" );
+ fprintf( pErr, "\t-h : print the command usage\n");
+ return 1;
+}
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
int Abc_CommandPrintIo( Abc_Frame_t * pAbc, int argc, char ** argv )
{
FILE * pOut, * pErr;
@@ -289,13 +582,13 @@ int Abc_CommandPrintIo( Abc_Frame_t * pAbc, int argc, char ** argv )
Abc_Obj_t * pNode;
int c;
- pNtk = Abc_FrameReadNet(pAbc);
+ pNtk = Abc_FrameReadNtk(pAbc);
pOut = Abc_FrameReadOut(pAbc);
pErr = Abc_FrameReadErr(pAbc);
// set defaults
- util_getopt_reset();
- while ( ( c = util_getopt( argc, argv, "h" ) ) != EOF )
+ Extra_UtilGetoptReset();
+ while ( ( c = Extra_UtilGetopt( argc, argv, "h" ) ) != EOF )
{
switch ( c )
{
@@ -312,18 +605,18 @@ int Abc_CommandPrintIo( Abc_Frame_t * pAbc, int argc, char ** argv )
return 1;
}
- if ( argc > util_optind + 1 )
+ if ( argc > globalUtilOptind + 1 )
{
fprintf( pErr, "Wrong number of auguments.\n" );
goto usage;
}
- if ( argc == util_optind + 1 )
+ if ( argc == globalUtilOptind + 1 )
{
- pNode = Abc_NtkFindNode( pNtk, argv[util_optind] );
+ pNode = Abc_NtkFindNode( pNtk, argv[globalUtilOptind] );
if ( pNode == NULL )
{
- fprintf( pErr, "Cannot find node \"%s\".\n", argv[util_optind] );
+ fprintf( pErr, "Cannot find node \"%s\".\n", argv[globalUtilOptind] );
return 1;
}
Abc_NodePrintFanio( pOut, pNode );
@@ -358,13 +651,13 @@ int Abc_CommandPrintLatch( Abc_Frame_t * pAbc, int argc, char ** argv )
Abc_Ntk_t * pNtk;
int c;
- pNtk = Abc_FrameReadNet(pAbc);
+ pNtk = Abc_FrameReadNtk(pAbc);
pOut = Abc_FrameReadOut(pAbc);
pErr = Abc_FrameReadErr(pAbc);
// set defaults
- util_getopt_reset();
- while ( ( c = util_getopt( argc, argv, "h" ) ) != EOF )
+ Extra_UtilGetoptReset();
+ while ( ( c = Extra_UtilGetopt( argc, argv, "h" ) ) != EOF )
{
switch ( c )
{
@@ -408,13 +701,13 @@ int Abc_CommandPrintFanio( Abc_Frame_t * pAbc, int argc, char ** argv )
Abc_Ntk_t * pNtk;
int c;
- pNtk = Abc_FrameReadNet(pAbc);
+ pNtk = Abc_FrameReadNtk(pAbc);
pOut = Abc_FrameReadOut(pAbc);
pErr = Abc_FrameReadErr(pAbc);
// set defaults
- util_getopt_reset();
- while ( ( c = util_getopt( argc, argv, "h" ) ) != EOF )
+ Extra_UtilGetoptReset();
+ while ( ( c = Extra_UtilGetopt( argc, argv, "h" ) ) != EOF )
{
switch ( c )
{
@@ -453,6 +746,58 @@ usage:
SeeAlso []
***********************************************************************/
+int Abc_CommandPrintMffc( Abc_Frame_t * pAbc, int argc, char ** argv )
+{
+ FILE * pOut, * pErr;
+ Abc_Ntk_t * pNtk;
+ int c;
+ extern void Abc_NtkPrintMffc( FILE * pFile, Abc_Ntk_t * pNtk );
+
+ pNtk = Abc_FrameReadNtk(pAbc);
+ pOut = Abc_FrameReadOut(pAbc);
+ pErr = Abc_FrameReadErr(pAbc);
+
+ // set defaults
+ Extra_UtilGetoptReset();
+ while ( ( c = Extra_UtilGetopt( argc, argv, "h" ) ) != EOF )
+ {
+ switch ( c )
+ {
+ case 'h':
+ goto usage;
+ default:
+ goto usage;
+ }
+ }
+
+ if ( pNtk == NULL )
+ {
+ fprintf( pErr, "Empty network.\n" );
+ return 1;
+ }
+
+ // print the nodes
+ Abc_NtkPrintMffc( pOut, pNtk );
+ return 0;
+
+usage:
+ fprintf( pErr, "usage: print_mffc [-h]\n" );
+ fprintf( pErr, "\t prints the MFFC of each node in the network\n" );
+ fprintf( pErr, "\t-h : print the command usage\n");
+ return 1;
+}
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
int Abc_CommandPrintFactor( Abc_Frame_t * pAbc, int argc, char ** argv )
{
FILE * pOut, * pErr;
@@ -461,14 +806,14 @@ int Abc_CommandPrintFactor( Abc_Frame_t * pAbc, int argc, char ** argv )
int c;
int fUseRealNames;
- pNtk = Abc_FrameReadNet(pAbc);
+ pNtk = Abc_FrameReadNtk(pAbc);
pOut = Abc_FrameReadOut(pAbc);
pErr = Abc_FrameReadErr(pAbc);
// set defaults
fUseRealNames = 1;
- util_getopt_reset();
- while ( ( c = util_getopt( argc, argv, "nh" ) ) != EOF )
+ Extra_UtilGetoptReset();
+ while ( ( c = Extra_UtilGetopt( argc, argv, "nh" ) ) != EOF )
{
switch ( c )
{
@@ -494,18 +839,18 @@ int Abc_CommandPrintFactor( Abc_Frame_t * pAbc, int argc, char ** argv )
return 1;
}
- if ( argc > util_optind + 1 )
+ if ( argc > globalUtilOptind + 1 )
{
fprintf( pErr, "Wrong number of auguments.\n" );
goto usage;
}
- if ( argc == util_optind + 1 )
+ if ( argc == globalUtilOptind + 1 )
{
- pNode = Abc_NtkFindNode( pNtk, argv[util_optind] );
+ pNode = Abc_NtkFindNode( pNtk, argv[globalUtilOptind] );
if ( pNode == NULL )
{
- fprintf( pErr, "Cannot find node \"%s\".\n", argv[util_optind] );
+ fprintf( pErr, "Cannot find node \"%s\".\n", argv[globalUtilOptind] );
return 1;
}
Abc_NodePrintFactor( pOut, pNode, fUseRealNames );
@@ -541,19 +886,24 @@ int Abc_CommandPrintLevel( Abc_Frame_t * pAbc, int argc, char ** argv )
Abc_Ntk_t * pNtk;
Abc_Obj_t * pNode;
int c;
+ int fListNodes;
int fProfile;
- pNtk = Abc_FrameReadNet(pAbc);
+ pNtk = Abc_FrameReadNtk(pAbc);
pOut = Abc_FrameReadOut(pAbc);
pErr = Abc_FrameReadErr(pAbc);
// set defaults
- fProfile = 1;
- util_getopt_reset();
- while ( ( c = util_getopt( argc, argv, "ph" ) ) != EOF )
+ fListNodes = 0;
+ fProfile = 1;
+ Extra_UtilGetoptReset();
+ while ( ( c = Extra_UtilGetopt( argc, argv, "nph" ) ) != EOF )
{
switch ( c )
{
+ case 'n':
+ fListNodes ^= 1;
+ break;
case 'p':
fProfile ^= 1;
break;
@@ -576,30 +926,31 @@ int Abc_CommandPrintLevel( Abc_Frame_t * pAbc, int argc, char ** argv )
return 1;
}
- if ( argc > util_optind + 1 )
+ if ( argc > globalUtilOptind + 1 )
{
fprintf( pErr, "Wrong number of auguments.\n" );
goto usage;
}
- if ( argc == util_optind + 1 )
+ if ( argc == globalUtilOptind + 1 )
{
- pNode = Abc_NtkFindNode( pNtk, argv[util_optind] );
+ pNode = Abc_NtkFindNode( pNtk, argv[globalUtilOptind] );
if ( pNode == NULL )
{
- fprintf( pErr, "Cannot find node \"%s\".\n", argv[util_optind] );
+ fprintf( pErr, "Cannot find node \"%s\".\n", argv[globalUtilOptind] );
return 1;
}
Abc_NodePrintLevel( pOut, pNode );
return 0;
}
// process all COs
- Abc_NtkPrintLevel( pOut, pNtk, fProfile );
+ Abc_NtkPrintLevel( pOut, pNtk, fProfile, fListNodes );
return 0;
usage:
- fprintf( pErr, "usage: print_level [-ph] <node>\n" );
+ fprintf( pErr, "usage: print_level [-nph] <node>\n" );
fprintf( pErr, "\t prints information about node level and cone size\n" );
+ fprintf( pErr, "\t-n : toggles printing nodes by levels [default = %s]\n", fListNodes? "yes": "no" );
fprintf( pErr, "\t-p : toggles printing level profile [default = %s]\n", fProfile? "yes": "no" );
fprintf( pErr, "\t-h : print the command usage\n");
fprintf( pErr, "\tnode : (optional) one node to consider\n");
@@ -623,20 +974,26 @@ int Abc_CommandPrintSupport( Abc_Frame_t * pAbc, int argc, char ** argv )
FILE * pOut, * pErr;
Abc_Ntk_t * pNtk;
int c;
+ int fStruct;
int fVerbose;
extern Vec_Ptr_t * Sim_ComputeFunSupp( Abc_Ntk_t * pNtk, int fVerbose );
+ extern void Abc_NtkPrintStrSupports( Abc_Ntk_t * pNtk );
- pNtk = Abc_FrameReadNet(pAbc);
+ pNtk = Abc_FrameReadNtk(pAbc);
pOut = Abc_FrameReadOut(pAbc);
pErr = Abc_FrameReadErr(pAbc);
// set defaults
+ fStruct = 1;
fVerbose = 0;
- util_getopt_reset();
- while ( ( c = util_getopt( argc, argv, "vh" ) ) != EOF )
+ Extra_UtilGetoptReset();
+ while ( ( c = Extra_UtilGetopt( argc, argv, "svh" ) ) != EOF )
{
switch ( c )
{
+ case 's':
+ fStruct ^= 1;
+ break;
case 'v':
fVerbose ^= 1;
break;
@@ -652,9 +1009,17 @@ int Abc_CommandPrintSupport( Abc_Frame_t * pAbc, int argc, char ** argv )
fprintf( pErr, "Empty network.\n" );
return 1;
}
+
+ // print support information
+ if ( fStruct )
+ {
+ Abc_NtkPrintStrSupports( pNtk );
+ return 0;
+ }
+
if ( !Abc_NtkIsComb(pNtk) )
{
- fprintf( pErr, "This command works only for combinational networks.\n" );
+ fprintf( pErr, "This command works only for combinational networks (run \"comb\").\n" );
return 1;
}
if ( !Abc_NtkIsStrash(pNtk) )
@@ -668,8 +1033,9 @@ int Abc_CommandPrintSupport( Abc_Frame_t * pAbc, int argc, char ** argv )
return 0;
usage:
- fprintf( pErr, "usage: print_supp [-vh]\n" );
+ fprintf( pErr, "usage: print_supp [-svh]\n" );
fprintf( pErr, "\t prints the supports of the CO nodes\n" );
+ fprintf( pErr, "\t-s : toggle printing structural support only [default = %s].\n", fStruct? "yes": "no" );
fprintf( pErr, "\t-v : enable verbose output [default = %s].\n", fVerbose? "yes": "no" );
fprintf( pErr, "\t-h : print the command usage\n");
return 1;
@@ -693,19 +1059,21 @@ int Abc_CommandPrintSymms( Abc_Frame_t * pAbc, int argc, char ** argv )
int c;
int fUseBdds;
int fNaive;
+ int fReorder;
int fVerbose;
- extern void Abc_NtkSymmetries( Abc_Ntk_t * pNtk, int fUseBdds, int fNaive, int fVerbose );
+ extern void Abc_NtkSymmetries( Abc_Ntk_t * pNtk, int fUseBdds, int fNaive, int fReorder, int fVerbose );
- pNtk = Abc_FrameReadNet(pAbc);
+ pNtk = Abc_FrameReadNtk(pAbc);
pOut = Abc_FrameReadOut(pAbc);
pErr = Abc_FrameReadErr(pAbc);
// set defaults
fUseBdds = 0;
fNaive = 0;
+ fReorder = 1;
fVerbose = 0;
- util_getopt_reset();
- while ( ( c = util_getopt( argc, argv, "bnvh" ) ) != EOF )
+ Extra_UtilGetoptReset();
+ while ( ( c = Extra_UtilGetopt( argc, argv, "bnrvh" ) ) != EOF )
{
switch ( c )
{
@@ -715,6 +1083,9 @@ int Abc_CommandPrintSymms( Abc_Frame_t * pAbc, int argc, char ** argv )
case 'n':
fNaive ^= 1;
break;
+ case 'r':
+ fReorder ^= 1;
+ break;
case 'v':
fVerbose ^= 1;
break;
@@ -731,7 +1102,82 @@ int Abc_CommandPrintSymms( Abc_Frame_t * pAbc, int argc, char ** argv )
}
if ( !Abc_NtkIsComb(pNtk) )
{
- fprintf( pErr, "This command works only for combinational networks.\n" );
+ fprintf( pErr, "This command works only for combinational networks (run \"comb\").\n" );
+ return 1;
+ }
+ if ( Abc_NtkIsStrash(pNtk) )
+ Abc_NtkSymmetries( pNtk, fUseBdds, fNaive, fReorder, fVerbose );
+ else
+ {
+ pNtk = Abc_NtkStrash( pNtk, 0, 0, 0 );
+ Abc_NtkSymmetries( pNtk, fUseBdds, fNaive, fReorder, fVerbose );
+ Abc_NtkDelete( pNtk );
+ }
+ return 0;
+
+usage:
+ fprintf( pErr, "usage: print_symm [-bnrvh]\n" );
+ fprintf( pErr, "\t computes symmetries of the PO functions\n" );
+ fprintf( pErr, "\t-b : toggle BDD-based or SAT-based computations [default = %s].\n", fUseBdds? "BDD": "SAT" );
+ fprintf( pErr, "\t-n : enable naive BDD-based computation [default = %s].\n", fNaive? "yes": "no" );
+ fprintf( pErr, "\t-r : enable dynamic BDD variable reordering [default = %s].\n", fReorder? "yes": "no" );
+ fprintf( pErr, "\t-v : enable verbose output [default = %s].\n", fVerbose? "yes": "no" );
+ fprintf( pErr, "\t-h : print the command usage\n");
+ return 1;
+}
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Abc_CommandPrintUnate( Abc_Frame_t * pAbc, int argc, char ** argv )
+{
+ FILE * pOut, * pErr;
+ Abc_Ntk_t * pNtk;
+ int c;
+ int fUseBdds;
+ int fUseNaive;
+ int fVerbose;
+ extern void Abc_NtkPrintUnate( Abc_Ntk_t * pNtk, int fUseBdds, int fUseNaive, int fVerbose );
+
+ pNtk = Abc_FrameReadNtk(pAbc);
+ pOut = Abc_FrameReadOut(pAbc);
+ pErr = Abc_FrameReadErr(pAbc);
+
+ // set defaults
+ fUseBdds = 1;
+ fUseNaive = 0;
+ fVerbose = 0;
+ Extra_UtilGetoptReset();
+ while ( ( c = Extra_UtilGetopt( argc, argv, "bnvh" ) ) != EOF )
+ {
+ switch ( c )
+ {
+ case 'b':
+ fUseBdds ^= 1;
+ break;
+ case 'n':
+ fUseNaive ^= 1;
+ break;
+ case 'v':
+ fVerbose ^= 1;
+ break;
+ case 'h':
+ goto usage;
+ default:
+ goto usage;
+ }
+ }
+ if ( pNtk == NULL )
+ {
+ fprintf( pErr, "Empty network.\n" );
return 1;
}
if ( !Abc_NtkIsStrash(pNtk) )
@@ -739,13 +1185,95 @@ int Abc_CommandPrintSymms( Abc_Frame_t * pAbc, int argc, char ** argv )
fprintf( pErr, "This command works only for AIGs (run \"strash\").\n" );
return 1;
}
- Abc_NtkSymmetries( pNtk, fUseBdds, fNaive, fVerbose );
+ Abc_NtkPrintUnate( pNtk, fUseBdds, fUseNaive, fVerbose );
return 0;
usage:
- fprintf( pErr, "usage: print_symm [-nbvh]\n" );
- fprintf( pErr, "\t computes symmetries of the PO functions\n" );
- fprintf( pErr, "\t-b : toggle BDD-based or SAT-based computations [default = %s].\n", fUseBdds? "bdd": "sat" );
+ fprintf( pErr, "usage: print_unate [-bnvh]\n" );
+ fprintf( pErr, "\t computes unate variables of the PO functions\n" );
+ fprintf( pErr, "\t-b : toggle BDD-based or SAT-based computations [default = %s].\n", fUseBdds? "BDD": "SAT" );
+ fprintf( pErr, "\t-n : toggle naive BDD-based computation [default = %s].\n", fUseNaive? "yes": "no" );
+ fprintf( pErr, "\t-v : enable verbose output [default = %s].\n", fVerbose? "yes": "no" );
+ fprintf( pErr, "\t-h : print the command usage\n");
+ return 1;
+}
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Abc_CommandPrintAuto( Abc_Frame_t * pAbc, int argc, char ** argv )
+{
+ FILE * pOut, * pErr;
+ Abc_Ntk_t * pNtk;
+ int c;
+ int Output;
+ int fNaive;
+ int fVerbose;
+ extern void Abc_NtkAutoPrint( Abc_Ntk_t * pNtk, int Output, int fNaive, int fVerbose );
+
+ pNtk = Abc_FrameReadNtk(pAbc);
+ pOut = Abc_FrameReadOut(pAbc);
+ pErr = Abc_FrameReadErr(pAbc);
+
+ // set defaults
+ Output = -1;
+ fNaive = 0;
+ fVerbose = 0;
+ Extra_UtilGetoptReset();
+ while ( ( c = Extra_UtilGetopt( argc, argv, "Onvh" ) ) != EOF )
+ {
+ switch ( c )
+ {
+ case 'O':
+ if ( globalUtilOptind >= argc )
+ {
+ fprintf( pErr, "Command line switch \"-O\" should be followed by an integer.\n" );
+ goto usage;
+ }
+ Output = atoi(argv[globalUtilOptind]);
+ globalUtilOptind++;
+ if ( Output < 0 )
+ goto usage;
+ break;
+ case 'n':
+ fNaive ^= 1;
+ break;
+ case 'v':
+ fVerbose ^= 1;
+ break;
+ case 'h':
+ goto usage;
+ default:
+ goto usage;
+ }
+ }
+ if ( pNtk == NULL )
+ {
+ fprintf( pErr, "Empty network.\n" );
+ return 1;
+ }
+ if ( !Abc_NtkIsStrash(pNtk) )
+ {
+ fprintf( pErr, "This command works only for AIGs (run \"strash\").\n" );
+ return 1;
+ }
+
+
+ Abc_NtkAutoPrint( pNtk, Output, fNaive, fVerbose );
+ return 0;
+
+usage:
+ fprintf( pErr, "usage: print_auto [-O num] [-nvh]\n" );
+ fprintf( pErr, "\t computes autosymmetries of the PO functions\n" );
+ fprintf( pErr, "\t-O num : (optional) the 0-based number of the output [default = all]\n");
fprintf( pErr, "\t-n : enable naive BDD-based computation [default = %s].\n", fNaive? "yes": "no" );
fprintf( pErr, "\t-v : enable verbose output [default = %s].\n", fVerbose? "yes": "no" );
fprintf( pErr, "\t-h : print the command usage\n");
@@ -763,24 +1291,30 @@ usage:
SeeAlso []
***********************************************************************/
-int Abc_CommandShowBdd( Abc_Frame_t * pAbc, int argc, char ** argv )
+int Abc_CommandPrintKMap( Abc_Frame_t * pAbc, int argc, char ** argv )
{
FILE * pOut, * pErr;
Abc_Ntk_t * pNtk;
Abc_Obj_t * pNode;
int c;
- extern void Abc_NodeShowBdd( Abc_Obj_t * pNode );
+ int fUseRealNames;
+
+ extern void Abc_NodePrintKMap( Abc_Obj_t * pNode, int fUseRealNames );
- pNtk = Abc_FrameReadNet(pAbc);
+ pNtk = Abc_FrameReadNtk(pAbc);
pOut = Abc_FrameReadOut(pAbc);
pErr = Abc_FrameReadErr(pAbc);
// set defaults
- util_getopt_reset();
- while ( ( c = util_getopt( argc, argv, "h" ) ) != EOF )
+ fUseRealNames = 1;
+ Extra_UtilGetoptReset();
+ while ( ( c = Extra_UtilGetopt( argc, argv, "nh" ) ) != EOF )
{
switch ( c )
{
+ case 'n':
+ fUseRealNames ^= 1;
+ break;
case 'h':
goto usage;
default:
@@ -794,35 +1328,106 @@ int Abc_CommandShowBdd( Abc_Frame_t * pAbc, int argc, char ** argv )
return 1;
}
- if ( !Abc_NtkIsBddLogic(pNtk) )
+ if ( !Abc_NtkIsLogic(pNtk) )
{
- fprintf( pErr, "Visualizing BDDs can only be done for logic BDD networks.\n" );
+ fprintf( pErr, "Visualization of Karnaugh maps works for logic networks.\n" );
return 1;
}
-
- if ( argc != util_optind + 1 )
+ if ( argc > globalUtilOptind + 1 )
{
fprintf( pErr, "Wrong number of auguments.\n" );
goto usage;
}
+ if ( argc == globalUtilOptind )
+ {
+ pNode = Abc_ObjFanin0( Abc_NtkPo(pNtk, 0) );
+ if ( !Abc_ObjIsNode(pNode) )
+ {
+ fprintf( pErr, "The driver \"%s\" of the first PO is not an internal node.\n", Abc_ObjName(pNode) );
+ return 1;
+ }
+ }
+ else
+ {
+ pNode = Abc_NtkFindNode( pNtk, argv[globalUtilOptind] );
+ if ( pNode == NULL )
+ {
+ fprintf( pErr, "Cannot find node \"%s\".\n", argv[globalUtilOptind] );
+ return 1;
+ }
+ }
+ Abc_NtkToBdd(pNtk);
+ Abc_NodePrintKMap( pNode, fUseRealNames );
+ return 0;
- pNode = Abc_NtkFindNode( pNtk, argv[util_optind] );
- if ( pNode == NULL )
+usage:
+ fprintf( pErr, "usage: print_kmap [-nh] <node>\n" );
+ fprintf( pErr, " shows the truth table of the node\n" );
+ fprintf( pErr, "\t-n : toggles real/dummy fanin names [default = %s]\n", fUseRealNames? "real": "dummy" );
+ fprintf( pErr, "\t-h : print the command usage\n");
+ fprintf( pErr, "\tnode : the node to consider (default = the driver of the first PO)\n");
+ return 1;
+}
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Abc_CommandPrintGates( Abc_Frame_t * pAbc, int argc, char ** argv )
+{
+ FILE * pOut, * pErr;
+ Abc_Ntk_t * pNtk;
+ int c;
+ int fUseLibrary;
+
+ extern void Abc_NtkPrintGates( Abc_Ntk_t * pNtk, int fUseLibrary );
+
+ pNtk = Abc_FrameReadNtk(pAbc);
+ pOut = Abc_FrameReadOut(pAbc);
+ pErr = Abc_FrameReadErr(pAbc);
+
+ // set defaults
+ fUseLibrary = 1;
+ Extra_UtilGetoptReset();
+ while ( ( c = Extra_UtilGetopt( argc, argv, "lh" ) ) != EOF )
{
- fprintf( pErr, "Cannot find node \"%s\".\n", argv[util_optind] );
+ switch ( c )
+ {
+ case 'l':
+ fUseLibrary ^= 1;
+ break;
+ case 'h':
+ goto usage;
+ default:
+ goto usage;
+ }
+ }
+
+ if ( pNtk == NULL )
+ {
+ fprintf( pErr, "Empty network.\n" );
return 1;
}
- Abc_NodeShowBdd( pNode );
+ if ( Abc_NtkHasAig(pNtk) )
+ {
+ fprintf( pErr, "Printing gates does not work for AIGs and sequential AIGs.\n" );
+ return 1;
+ }
+
+ Abc_NtkPrintGates( pNtk, fUseLibrary );
return 0;
usage:
- fprintf( pErr, "usage: show_bdd [-h] <node>\n" );
- fprintf( pErr, " visualizes the BDD of a node using DOT and GSVIEW\n" );
-#ifdef WIN32
- fprintf( pErr, " \"dot.exe\" and \"gsview32.exe\" should be set in the paths\n" );
- fprintf( pErr, " (\"gsview32.exe\" may be in \"C:\\Program Files\\Ghostgum\\gsview\\\")\n" );
-#endif
- fprintf( pErr, "\tnode : the node to consider\n");
+ fprintf( pErr, "usage: print_gates [-lh]\n" );
+ fprintf( pErr, "\t prints statistics about gates used in the network\n" );
+ fprintf( pErr, "\t-l : used library gate names (if mapped) [default = %s]\n", fUseLibrary? "yes": "no" );
fprintf( pErr, "\t-h : print the command usage\n");
return 1;
}
@@ -838,49 +1443,156 @@ usage:
SeeAlso []
***********************************************************************/
-int Abc_CommandShowCut( Abc_Frame_t * pAbc, int argc, char ** argv )
+int Abc_CommandPrintSharing( Abc_Frame_t * pAbc, int argc, char ** argv )
{
FILE * pOut, * pErr;
Abc_Ntk_t * pNtk;
- Abc_Obj_t * pNode;
int c;
- int nNodeSizeMax;
- int nConeSizeMax;
- extern void Abc_NodeShowCut( Abc_Obj_t * pNode, int nNodeSizeMax, int nConeSizeMax );
+ int fUseLibrary;
+
+ extern void Abc_NtkPrintSharing( Abc_Ntk_t * pNtk );
- pNtk = Abc_FrameReadNet(pAbc);
+ pNtk = Abc_FrameReadNtk(pAbc);
pOut = Abc_FrameReadOut(pAbc);
pErr = Abc_FrameReadErr(pAbc);
// set defaults
- nNodeSizeMax = 10;
- nConeSizeMax = ABC_INFINITY;
- util_getopt_reset();
- while ( ( c = util_getopt( argc, argv, "NCh" ) ) != EOF )
+ fUseLibrary = 1;
+ Extra_UtilGetoptReset();
+ while ( ( c = Extra_UtilGetopt( argc, argv, "lh" ) ) != EOF )
+ {
+ switch ( c )
+ {
+ case 'l':
+ fUseLibrary ^= 1;
+ break;
+ case 'h':
+ goto usage;
+ default:
+ goto usage;
+ }
+ }
+
+ if ( pNtk == NULL )
+ {
+ fprintf( pErr, "Empty network.\n" );
+ return 1;
+ }
+ Abc_NtkPrintSharing( pNtk );
+ return 0;
+
+usage:
+ fprintf( pErr, "usage: print_sharing [-h]\n" );
+ fprintf( pErr, "\t prints the number of shared nodes in the TFI cones of the COs\n" );
+// fprintf( pErr, "\t-l : used library gate names (if mapped) [default = %s]\n", fUseLibrary? "yes": "no" );
+ fprintf( pErr, "\t-h : print the command usage\n");
+ return 1;
+}
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Abc_CommandPrintXCut( Abc_Frame_t * pAbc, int argc, char ** argv )
+{
+ FILE * pOut, * pErr;
+ Abc_Ntk_t * pNtk;
+ int c;
+ int fUseLibrary;
+
+ extern int Abc_NtkCrossCut( Abc_Ntk_t * pNtk );
+
+ pNtk = Abc_FrameReadNtk(pAbc);
+ pOut = Abc_FrameReadOut(pAbc);
+ pErr = Abc_FrameReadErr(pAbc);
+
+ // set defaults
+ fUseLibrary = 1;
+ Extra_UtilGetoptReset();
+ while ( ( c = Extra_UtilGetopt( argc, argv, "lh" ) ) != EOF )
+ {
+ switch ( c )
+ {
+ case 'l':
+ fUseLibrary ^= 1;
+ break;
+ case 'h':
+ goto usage;
+ default:
+ goto usage;
+ }
+ }
+
+ if ( pNtk == NULL )
+ {
+ fprintf( pErr, "Empty network.\n" );
+ return 1;
+ }
+ Abc_NtkCrossCut( pNtk );
+ return 0;
+
+usage:
+ fprintf( pErr, "usage: print_xcut [-h]\n" );
+ fprintf( pErr, "\t prints the size of the cross cut of the current network\n" );
+// fprintf( pErr, "\t-l : used library gate names (if mapped) [default = %s]\n", fUseLibrary? "yes": "no" );
+ fprintf( pErr, "\t-h : print the command usage\n");
+ return 1;
+}
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Abc_CommandPrintDsd( Abc_Frame_t * pAbc, int argc, char ** argv )
+{
+ FILE * pOut, * pErr;
+ Abc_Ntk_t * pNtk;
+ int c;
+ int fCofactor;
+ int nCofLevel;
+
+ extern void Kit_DsdTest( unsigned * pTruth, int nVars );
+ extern void Kit_DsdPrintCofactors( unsigned * pTruth, int nVars, int nCofLevel, int fVerbose );
+
+ pNtk = Abc_FrameReadNtk(pAbc);
+ pOut = Abc_FrameReadOut(pAbc);
+ pErr = Abc_FrameReadErr(pAbc);
+
+ // set defaults
+ nCofLevel = 1;
+ fCofactor = 0;
+ Extra_UtilGetoptReset();
+ while ( ( c = Extra_UtilGetopt( argc, argv, "Nch" ) ) != EOF )
{
switch ( c )
{
case 'N':
- if ( util_optind >= argc )
+ if ( globalUtilOptind >= argc )
{
fprintf( pErr, "Command line switch \"-N\" should be followed by an integer.\n" );
goto usage;
}
- nNodeSizeMax = atoi(argv[util_optind]);
- util_optind++;
- if ( nNodeSizeMax < 0 )
+ nCofLevel = atoi(argv[globalUtilOptind]);
+ globalUtilOptind++;
+ if ( nCofLevel < 0 )
goto usage;
break;
- case 'C':
- if ( util_optind >= argc )
- {
- fprintf( pErr, "Command line switch \"-C\" should be followed by an integer.\n" );
- goto usage;
- }
- nConeSizeMax = atoi(argv[util_optind]);
- util_optind++;
- if ( nConeSizeMax < 0 )
- goto usage;
+ case 'c':
+ fCofactor ^= 1;
break;
case 'h':
goto usage;
@@ -894,38 +1606,205 @@ int Abc_CommandShowCut( Abc_Frame_t * pAbc, int argc, char ** argv )
fprintf( pErr, "Empty network.\n" );
return 1;
}
+ // get the truth table of the first output
+ if ( !Abc_NtkIsLogic(pNtk) )
+ {
+ fprintf( pErr, "Currently works only for logic networks.\n" );
+ return 1;
+ }
+ Abc_NtkToAig( pNtk );
+ // convert it to truth table
+ {
+ Abc_Obj_t * pObj = Abc_ObjFanin0( Abc_NtkPo(pNtk, 0) );
+ Vec_Int_t * vMemory = Vec_IntAlloc(0);
+ unsigned * pTruth;
+ if ( !Abc_ObjIsNode(pObj) )
+ {
+ fprintf( pErr, "The fanin of the first PO node does not have a logic function.\n" );
+ return 1;
+ }
+ if ( Abc_ObjFaninNum(pObj) > 16 )
+ {
+ fprintf( pErr, "Currently works only for up to 16 inputs.\n" );
+ return 1;
+ }
+ pTruth = Abc_ConvertAigToTruth( pNtk->pManFunc, Hop_Regular(pObj->pData), Abc_ObjFaninNum(pObj), vMemory, 0 );
+ if ( Hop_IsComplement(pObj->pData) )
+ Extra_TruthNot( pTruth, pTruth, Abc_ObjFaninNum(pObj) );
+ Extra_PrintBinary( stdout, pTruth, 1 << Abc_ObjFaninNum(pObj) );
+ printf( "\n" );
+ if ( fCofactor )
+ Kit_DsdPrintCofactors( pTruth, Abc_ObjFaninNum(pObj), nCofLevel, 1 );
+ else
+ Kit_DsdTest( pTruth, Abc_ObjFaninNum(pObj) );
+ Vec_IntFree( vMemory );
+ }
+ return 0;
- if ( !Abc_NtkIsStrash(pNtk) )
+usage:
+ fprintf( pErr, "usage: print_dsd [-ch] [-N num]\n" );
+ fprintf( pErr, "\t print DSD formula for a single-output function with less than 16 variables\n" );
+ fprintf( pErr, "\t-c : toggle recursive cofactoring [default = %s]\n", fCofactor? "yes": "no" );
+ fprintf( pErr, "\t-N num : the number of levels to cofactor [default = %d]\n", nCofLevel );
+ fprintf( pErr, "\t-h : print the command usage\n");
+ return 1;
+}
+
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Abc_CommandShow( Abc_Frame_t * pAbc, int argc, char ** argv )
+{
+ FILE * pOut, * pErr;
+ Abc_Ntk_t * pNtk;
+ int c;
+ int fSeq;
+ int fGateNames;
+ int fUseReverse;
+ extern void Abc_NtkShow( Abc_Ntk_t * pNtk, int fGateNames, int fSeq, int fUseReverse );
+
+ pNtk = Abc_FrameReadNtk(pAbc);
+ pOut = Abc_FrameReadOut(pAbc);
+ pErr = Abc_FrameReadErr(pAbc);
+
+ // set defaults
+ fSeq = 0;
+ fGateNames = 0;
+ fUseReverse = 1;
+ Extra_UtilGetoptReset();
+ while ( ( c = Extra_UtilGetopt( argc, argv, "rsgh" ) ) != EOF )
{
- fprintf( pErr, "Visualizing cuts only works for AIGs (run \"strash\").\n" );
+ switch ( c )
+ {
+ case 'r':
+ fUseReverse ^= 1;
+ break;
+ case 's':
+ fSeq ^= 1;
+ break;
+ case 'g':
+ fGateNames ^= 1;
+ break;
+ default:
+ goto usage;
+ }
+ }
+
+ if ( pNtk == NULL )
+ {
+ fprintf( pErr, "Empty network.\n" );
+ return 1;
+ }
+
+ Abc_NtkShow( pNtk, fGateNames, fSeq, fUseReverse );
+ return 0;
+
+usage:
+ fprintf( pErr, "usage: show [-srgh]\n" );
+ fprintf( pErr, " visualizes the network structure using DOT and GSVIEW\n" );
+#ifdef WIN32
+ fprintf( pErr, " \"dot.exe\" and \"gsview32.exe\" should be set in the paths\n" );
+ fprintf( pErr, " (\"gsview32.exe\" may be in \"C:\\Program Files\\Ghostgum\\gsview\\\")\n" );
+#endif
+ fprintf( pErr, "\t-s : toggles visualization of sequential networks [default = %s].\n", fSeq? "yes": "no" );
+ fprintf( pErr, "\t-r : toggles ordering nodes in reverse order [default = %s].\n", fUseReverse? "yes": "no" );
+ fprintf( pErr, "\t-g : toggles printing gate names for mapped network [default = %s].\n", fGateNames? "yes": "no" );
+ fprintf( pErr, "\t-h : print the command usage\n");
+ return 1;
+}
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Abc_CommandShowBdd( Abc_Frame_t * pAbc, int argc, char ** argv )
+{
+ FILE * pOut, * pErr;
+ Abc_Ntk_t * pNtk;
+ Abc_Obj_t * pNode;
+ int c;
+ extern void Abc_NodeShowBdd( Abc_Obj_t * pNode );
+
+ pNtk = Abc_FrameReadNtk(pAbc);
+ pOut = Abc_FrameReadOut(pAbc);
+ pErr = Abc_FrameReadErr(pAbc);
+
+ // set defaults
+ Extra_UtilGetoptReset();
+ while ( ( c = Extra_UtilGetopt( argc, argv, "h" ) ) != EOF )
+ {
+ switch ( c )
+ {
+ case 'h':
+ goto usage;
+ default:
+ goto usage;
+ }
+ }
+
+ if ( pNtk == NULL )
+ {
+ fprintf( pErr, "Empty network.\n" );
+ return 1;
+ }
+
+ if ( !Abc_NtkIsBddLogic(pNtk) )
+ {
+ fprintf( pErr, "Visualizing BDDs can only be done for logic BDD networks (run \"bdd\").\n" );
return 1;
}
- if ( argc != util_optind + 1 )
+
+ if ( argc > globalUtilOptind + 1 )
{
fprintf( pErr, "Wrong number of auguments.\n" );
goto usage;
}
-
- pNode = Abc_NtkFindNode( pNtk, argv[util_optind] );
- if ( pNode == NULL )
+ if ( argc == globalUtilOptind )
{
- fprintf( pErr, "Cannot find node \"%s\".\n", argv[util_optind] );
- return 1;
+ pNode = Abc_ObjFanin0( Abc_NtkPo(pNtk, 0) );
+ if ( !Abc_ObjIsNode(pNode) )
+ {
+ fprintf( pErr, "The driver \"%s\" of the first PO is not an internal node.\n", Abc_ObjName(pNode) );
+ return 1;
+ }
}
- Abc_NodeShowCut( pNode, nNodeSizeMax, nConeSizeMax );
+ else
+ {
+ pNode = Abc_NtkFindNode( pNtk, argv[globalUtilOptind] );
+ if ( pNode == NULL )
+ {
+ fprintf( pErr, "Cannot find node \"%s\".\n", argv[globalUtilOptind] );
+ return 1;
+ }
+ }
+ Abc_NodeShowBdd( pNode );
return 0;
usage:
- fprintf( pErr, "usage: show_cut [-N num] [-C num] [-h] <node>\n" );
- fprintf( pErr, " visualizes the cut of a node using DOT and GSVIEW\n" );
+ fprintf( pErr, "usage: show_bdd [-h] <node>\n" );
+ fprintf( pErr, " visualizes the BDD of a node using DOT and GSVIEW\n" );
#ifdef WIN32
fprintf( pErr, " \"dot.exe\" and \"gsview32.exe\" should be set in the paths\n" );
fprintf( pErr, " (\"gsview32.exe\" may be in \"C:\\Program Files\\Ghostgum\\gsview\\\")\n" );
#endif
- fprintf( pErr, "\t-N num : the max size of the cut to be computed [default = %d]\n", nNodeSizeMax );
- fprintf( pErr, "\t-C num : the max support of the containing cone [default = %d]\n", nConeSizeMax );
- fprintf( pErr, "\tnode : the node to consider\n");
- fprintf( pErr, "\t-h : print the command usage\n");
+ fprintf( pErr, "\tnode : the node to consider [default = the driver of the first PO]\n");
+ fprintf( pErr, "\t-h : print the command usage\n");
return 1;
}
@@ -940,23 +1819,50 @@ usage:
SeeAlso []
***********************************************************************/
-int Abc_CommandShowAig( Abc_Frame_t * pAbc, int argc, char ** argv )
+int Abc_CommandShowCut( Abc_Frame_t * pAbc, int argc, char ** argv )
{
FILE * pOut, * pErr;
Abc_Ntk_t * pNtk;
+ Abc_Obj_t * pNode;
int c;
- extern void Abc_NtkShowAig( Abc_Ntk_t * pNtk );
+ int nNodeSizeMax;
+ int nConeSizeMax;
+ extern void Abc_NodeShowCut( Abc_Obj_t * pNode, int nNodeSizeMax, int nConeSizeMax );
- pNtk = Abc_FrameReadNet(pAbc);
+ pNtk = Abc_FrameReadNtk(pAbc);
pOut = Abc_FrameReadOut(pAbc);
pErr = Abc_FrameReadErr(pAbc);
// set defaults
- util_getopt_reset();
- while ( ( c = util_getopt( argc, argv, "h" ) ) != EOF )
+ nNodeSizeMax = 10;
+ nConeSizeMax = ABC_INFINITY;
+ Extra_UtilGetoptReset();
+ while ( ( c = Extra_UtilGetopt( argc, argv, "NCh" ) ) != EOF )
{
switch ( c )
{
+ case 'N':
+ if ( globalUtilOptind >= argc )
+ {
+ fprintf( pErr, "Command line switch \"-N\" should be followed by an integer.\n" );
+ goto usage;
+ }
+ nNodeSizeMax = atoi(argv[globalUtilOptind]);
+ globalUtilOptind++;
+ if ( nNodeSizeMax < 0 )
+ goto usage;
+ break;
+ case 'C':
+ if ( globalUtilOptind >= argc )
+ {
+ fprintf( pErr, "Command line switch \"-C\" should be followed by an integer.\n" );
+ goto usage;
+ }
+ nConeSizeMax = atoi(argv[globalUtilOptind]);
+ globalUtilOptind++;
+ if ( nConeSizeMax < 0 )
+ goto usage;
+ break;
case 'h':
goto usage;
default:
@@ -972,20 +1878,35 @@ int Abc_CommandShowAig( Abc_Frame_t * pAbc, int argc, char ** argv )
if ( !Abc_NtkIsStrash(pNtk) )
{
- fprintf( pErr, "Visualizing AIG can only be done for AIGs (run \"strash\").\n" );
+ fprintf( pErr, "Visualizing cuts only works for AIGs (run \"strash\").\n" );
+ return 1;
+ }
+ if ( argc != globalUtilOptind + 1 )
+ {
+ fprintf( pErr, "Wrong number of auguments.\n" );
+ goto usage;
+ }
+
+ pNode = Abc_NtkFindNode( pNtk, argv[globalUtilOptind] );
+ if ( pNode == NULL )
+ {
+ fprintf( pErr, "Cannot find node \"%s\".\n", argv[globalUtilOptind] );
return 1;
}
- Abc_NtkShowAig( pNtk );
+ Abc_NodeShowCut( pNode, nNodeSizeMax, nConeSizeMax );
return 0;
usage:
- fprintf( pErr, "usage: show_aig [-h]\n" );
- fprintf( pErr, " visualizes the AIG with choices using DOT and GSVIEW\n" );
+ fprintf( pErr, "usage: show_cut [-N num] [-C num] [-h] <node>\n" );
+ fprintf( pErr, " visualizes the cut of a node using DOT and GSVIEW\n" );
#ifdef WIN32
fprintf( pErr, " \"dot.exe\" and \"gsview32.exe\" should be set in the paths\n" );
fprintf( pErr, " (\"gsview32.exe\" may be in \"C:\\Program Files\\Ghostgum\\gsview\\\")\n" );
#endif
- fprintf( pErr, "\t-h : print the command usage\n");
+ fprintf( pErr, "\t-N num : the max size of the cut to be computed [default = %d]\n", nNodeSizeMax );
+ fprintf( pErr, "\t-C num : the max support of the containing cone [default = %d]\n", nConeSizeMax );
+ fprintf( pErr, "\tnode : the node to consider\n");
+ fprintf( pErr, "\t-h : print the command usage\n");
return 1;
}
@@ -1005,18 +1926,46 @@ int Abc_CommandCollapse( Abc_Frame_t * pAbc, int argc, char ** argv )
{
FILE * pOut, * pErr;
Abc_Ntk_t * pNtk, * pNtkRes;
+ int fVerbose;
+ int fBddSizeMax;
+ int fDualRail;
+ int fReorder;
int c;
- pNtk = Abc_FrameReadNet(pAbc);
+ pNtk = Abc_FrameReadNtk(pAbc);
pOut = Abc_FrameReadOut(pAbc);
pErr = Abc_FrameReadErr(pAbc);
// set defaults
- util_getopt_reset();
- while ( ( c = util_getopt( argc, argv, "h" ) ) != EOF )
+ fVerbose = 1;
+ fReorder = 1;
+ fDualRail = 0;
+ fBddSizeMax = 50000000;
+ Extra_UtilGetoptReset();
+ while ( ( c = Extra_UtilGetopt( argc, argv, "Brdvh" ) ) != EOF )
{
switch ( c )
{
+ case 'B':
+ if ( globalUtilOptind >= argc )
+ {
+ fprintf( pErr, "Command line switch \"-B\" should be followed by an integer.\n" );
+ goto usage;
+ }
+ fBddSizeMax = atoi(argv[globalUtilOptind]);
+ globalUtilOptind++;
+ if ( fBddSizeMax < 0 )
+ goto usage;
+ break;
+ case 'd':
+ fDualRail ^= 1;
+ break;
+ case 'v':
+ fVerbose ^= 1;
+ break;
+ case 'r':
+ fReorder ^= 1;
+ break;
case 'h':
goto usage;
default:
@@ -1038,11 +1987,11 @@ int Abc_CommandCollapse( Abc_Frame_t * pAbc, int argc, char ** argv )
// get the new network
if ( Abc_NtkIsStrash(pNtk) )
- pNtkRes = Abc_NtkCollapse( pNtk, 1 );
+ pNtkRes = Abc_NtkCollapse( pNtk, fBddSizeMax, fDualRail, fReorder, fVerbose );
else
{
- pNtk = Abc_NtkStrash( pNtk, 0, 0 );
- pNtkRes = Abc_NtkCollapse( pNtk, 1 );
+ pNtk = Abc_NtkStrash( pNtk, 0, 0, 0 );
+ pNtkRes = Abc_NtkCollapse( pNtk, fBddSizeMax, fDualRail, fReorder, fVerbose );
Abc_NtkDelete( pNtk );
}
if ( pNtkRes == NULL )
@@ -1055,9 +2004,13 @@ int Abc_CommandCollapse( Abc_Frame_t * pAbc, int argc, char ** argv )
return 0;
usage:
- fprintf( pErr, "usage: collapse [-h]\n" );
- fprintf( pErr, "\t collapses the network by constructing global BDDs\n" );
- fprintf( pErr, "\t-h : print the command usage\n");
+ fprintf( pErr, "usage: collapse [-B num] [-rdvh]\n" );
+ fprintf( pErr, "\t collapses the network by constructing global BDDs\n" );
+ fprintf( pErr, "\t-B num : limit on live BDD nodes during collapsing [default = %d]\n", fBddSizeMax );
+ fprintf( pErr, "\t-r : toggles dynamic variable reordering [default = %s]\n", fReorder? "yes": "no" );
+ fprintf( pErr, "\t-d : toggles dual-rail collapsing mode [default = %s]\n", fDualRail? "yes": "no" );
+ fprintf( pErr, "\t-v : print verbose information [default = %s]\n", fVerbose? "yes": "no" );
+ fprintf( pErr, "\t-h : print the command usage\n");
return 1;
}
@@ -1079,17 +2032,19 @@ int Abc_CommandStrash( Abc_Frame_t * pAbc, int argc, char ** argv )
Abc_Ntk_t * pNtk, * pNtkRes;
int c;
int fAllNodes;
+ int fRecord;
int fCleanup;
- pNtk = Abc_FrameReadNet(pAbc);
+ pNtk = Abc_FrameReadNtk(pAbc);
pOut = Abc_FrameReadOut(pAbc);
pErr = Abc_FrameReadErr(pAbc);
// set defaults
fAllNodes = 0;
fCleanup = 1;
- util_getopt_reset();
- while ( ( c = util_getopt( argc, argv, "ach" ) ) != EOF )
+ fRecord = 0;
+ Extra_UtilGetoptReset();
+ while ( ( c = Extra_UtilGetopt( argc, argv, "acrh" ) ) != EOF )
{
switch ( c )
{
@@ -1099,6 +2054,9 @@ int Abc_CommandStrash( Abc_Frame_t * pAbc, int argc, char ** argv )
case 'c':
fCleanup ^= 1;
break;
+ case 'r':
+ fRecord ^= 1;
+ break;
case 'h':
goto usage;
default:
@@ -1113,7 +2071,7 @@ int Abc_CommandStrash( Abc_Frame_t * pAbc, int argc, char ** argv )
}
// get the new network
- pNtkRes = Abc_NtkStrash( pNtk, fAllNodes, fCleanup );
+ pNtkRes = Abc_NtkStrash( pNtk, fAllNodes, fCleanup, fRecord );
if ( pNtkRes == NULL )
{
fprintf( pErr, "Strashing has failed.\n" );
@@ -1124,10 +2082,11 @@ int Abc_CommandStrash( Abc_Frame_t * pAbc, int argc, char ** argv )
return 0;
usage:
- fprintf( pErr, "usage: strash [-ach]\n" );
+ fprintf( pErr, "usage: strash [-acrh]\n" );
fprintf( pErr, "\t transforms combinational logic into an AIG\n" );
fprintf( pErr, "\t-a : toggles between using all nodes and DFS nodes [default = %s]\n", fAllNodes? "all": "DFS" );
fprintf( pErr, "\t-c : toggles cleanup to remove the dagling AIG nodes [default = %s]\n", fCleanup? "all": "DFS" );
+ fprintf( pErr, "\t-r : enables using the record of AIG subgraphs [default = %s]\n", fRecord? "yes": "no" );
fprintf( pErr, "\t-h : print the command usage\n");
return 1;
}
@@ -1148,22 +2107,32 @@ int Abc_CommandBalance( Abc_Frame_t * pAbc, int argc, char ** argv )
FILE * pOut, * pErr;
Abc_Ntk_t * pNtk, * pNtkRes, * pNtkTemp;
int c;
- int fDuplicate;
+ bool fDuplicate;
+ bool fSelective;
+ bool fUpdateLevel;
- pNtk = Abc_FrameReadNet(pAbc);
+ pNtk = Abc_FrameReadNtk(pAbc);
pOut = Abc_FrameReadOut(pAbc);
pErr = Abc_FrameReadErr(pAbc);
// set defaults
- fDuplicate = 0;
- util_getopt_reset();
- while ( ( c = util_getopt( argc, argv, "dh" ) ) != EOF )
+ fDuplicate = 0;
+ fSelective = 0;
+ fUpdateLevel = 1;
+ Extra_UtilGetoptReset();
+ while ( ( c = Extra_UtilGetopt( argc, argv, "ldsh" ) ) != EOF )
{
switch ( c )
{
+ case 'l':
+ fUpdateLevel ^= 1;
+ break;
case 'd':
fDuplicate ^= 1;
break;
+ case 's':
+ fSelective ^= 1;
+ break;
case 'h':
goto usage;
default:
@@ -1176,21 +2145,20 @@ int Abc_CommandBalance( Abc_Frame_t * pAbc, int argc, char ** argv )
fprintf( pErr, "Empty network.\n" );
return 1;
}
-
// get the new network
if ( Abc_NtkIsStrash(pNtk) )
{
- pNtkRes = Abc_NtkBalance( pNtk, fDuplicate );
+ pNtkRes = Abc_NtkBalance( pNtk, fDuplicate, fSelective, fUpdateLevel );
}
else
{
- pNtkTemp = Abc_NtkStrash( pNtk, 0, 0 );
+ pNtkTemp = Abc_NtkStrash( pNtk, 0, 0, 0 );
if ( pNtkTemp == NULL )
{
fprintf( pErr, "Strashing before balancing has failed.\n" );
return 1;
}
- pNtkRes = Abc_NtkBalance( pNtkTemp, fDuplicate );
+ pNtkRes = Abc_NtkBalance( pNtkTemp, fDuplicate, fSelective, fUpdateLevel );
Abc_NtkDelete( pNtkTemp );
}
@@ -1205,9 +2173,11 @@ int Abc_CommandBalance( Abc_Frame_t * pAbc, int argc, char ** argv )
return 0;
usage:
- fprintf( pErr, "usage: balance [-dh]\n" );
+ fprintf( pErr, "usage: balance [-ldsh]\n" );
fprintf( pErr, "\t transforms the current network into a well-balanced AIG\n" );
+ fprintf( pErr, "\t-l : toggle minimizing the number of levels [default = %s]\n", fUpdateLevel? "yes": "no" );
fprintf( pErr, "\t-d : toggle duplication of logic [default = %s]\n", fDuplicate? "yes": "no" );
+ fprintf( pErr, "\t-s : toggle duplication on the critical paths [default = %s]\n", fSelective? "yes": "no" );
fprintf( pErr, "\t-h : print the command usage\n");
return 1;
}
@@ -1223,7 +2193,7 @@ usage:
SeeAlso []
***********************************************************************/
-int Abc_CommandRenode( Abc_Frame_t * pAbc, int argc, char ** argv )
+int Abc_CommandMulti( Abc_Frame_t * pAbc, int argc, char ** argv )
{
FILE * pOut, * pErr;
Abc_Ntk_t * pNtk, * pNtkRes;
@@ -1231,8 +2201,10 @@ int Abc_CommandRenode( Abc_Frame_t * pAbc, int argc, char ** argv )
int fCnf;
int fMulti;
int fSimple;
+ int fFactor;
+ extern Abc_Ntk_t * Abc_NtkMulti( Abc_Ntk_t * pNtk, int nThresh, int nFaninMax, int fCnf, int fMulti, int fSimple, int fFactor );
- pNtk = Abc_FrameReadNet(pAbc);
+ pNtk = Abc_FrameReadNtk(pAbc);
pOut = Abc_FrameReadOut(pAbc);
pErr = Abc_FrameReadErr(pAbc);
@@ -1240,32 +2212,33 @@ int Abc_CommandRenode( Abc_Frame_t * pAbc, int argc, char ** argv )
nThresh = 1;
nFaninMax = 20;
fCnf = 0;
- fMulti = 0;
+ fMulti = 1;
fSimple = 0;
- util_getopt_reset();
- while ( ( c = util_getopt( argc, argv, "TFmcsh" ) ) != EOF )
+ fFactor = 0;
+ Extra_UtilGetoptReset();
+ while ( ( c = Extra_UtilGetopt( argc, argv, "TFmcsfh" ) ) != EOF )
{
switch ( c )
{
case 'T':
- if ( util_optind >= argc )
+ if ( globalUtilOptind >= argc )
{
fprintf( pErr, "Command line switch \"-T\" should be followed by an integer.\n" );
goto usage;
}
- nThresh = atoi(argv[util_optind]);
- util_optind++;
+ nThresh = atoi(argv[globalUtilOptind]);
+ globalUtilOptind++;
if ( nThresh < 0 )
goto usage;
break;
case 'F':
- if ( util_optind >= argc )
+ if ( globalUtilOptind >= argc )
{
fprintf( pErr, "Command line switch \"-F\" should be followed by an integer.\n" );
goto usage;
}
- nFaninMax = atoi(argv[util_optind]);
- util_optind++;
+ nFaninMax = atoi(argv[globalUtilOptind]);
+ globalUtilOptind++;
if ( nFaninMax < 0 )
goto usage;
break;
@@ -1278,6 +2251,9 @@ int Abc_CommandRenode( Abc_Frame_t * pAbc, int argc, char ** argv )
case 's':
fSimple ^= 1;
break;
+ case 'f':
+ fFactor ^= 1;
+ break;
case 'h':
goto usage;
default:
@@ -1297,7 +2273,7 @@ int Abc_CommandRenode( Abc_Frame_t * pAbc, int argc, char ** argv )
}
// get the new network
- pNtkRes = Abc_NtkRenode( pNtk, nThresh, nFaninMax, fCnf, fMulti, fSimple );
+ pNtkRes = Abc_NtkMulti( pNtk, nThresh, nFaninMax, fCnf, fMulti, fSimple, fFactor );
if ( pNtkRes == NULL )
{
fprintf( pErr, "Renoding has failed.\n" );
@@ -1308,15 +2284,16 @@ int Abc_CommandRenode( Abc_Frame_t * pAbc, int argc, char ** argv )
return 0;
usage:
- fprintf( pErr, "usage: renode [-T num] [-F num] [-cmsh]\n" );
+ fprintf( pErr, "usage: multi [-T num] [-F num] [-msfch]\n" );
fprintf( pErr, "\t transforms an AIG into a logic network by creating larger nodes\n" );
fprintf( pErr, "\t-F num : the maximum fanin size after renoding [default = %d]\n", nFaninMax );
fprintf( pErr, "\t-T num : the threshold for AIG node duplication [default = %d]\n", nThresh );
fprintf( pErr, "\t (an AIG node is the root of a new node after renoding\n" );
- fprintf( pErr, "\t if doing so prevents duplication of more than %d AIG nodes,\n", nThresh );
- fprintf( pErr, "\t that is, if [(numFanouts(Node)-1) * size(MFFC(Node))] > %d)\n", nThresh );
+ fprintf( pErr, "\t if this leads to duplication of no more than %d AIG nodes,\n", nThresh );
+ fprintf( pErr, "\t that is, if [(numFanouts(Node)-1) * size(MFFC(Node))] <= %d)\n", nThresh );
fprintf( pErr, "\t-m : creates multi-input AND graph [default = %s]\n", fMulti? "yes": "no" );
fprintf( pErr, "\t-s : creates a simple AIG (no renoding) [default = %s]\n", fSimple? "yes": "no" );
+ fprintf( pErr, "\t-f : creates a factor-cut network [default = %s]\n", fFactor? "yes": "no" );
fprintf( pErr, "\t-c : performs renoding to derive the CNF [default = %s]\n", fCnf? "yes": "no" );
fprintf( pErr, "\t-h : print the command usage\n");
return 1;
@@ -1333,19 +2310,191 @@ usage:
SeeAlso []
***********************************************************************/
+int Abc_CommandRenode( Abc_Frame_t * pAbc, int argc, char ** argv )
+{
+ FILE * pOut, * pErr;
+ Abc_Ntk_t * pNtk, * pNtkRes;
+ int nLutSize, nCutsMax, c;
+ int nFlowIters, nAreaIters;
+ int fArea;
+ int fUseBdds;
+ int fUseSops;
+ int fUseCnfs;
+ int fUseMv;
+ int fVerbose;
+ extern Abc_Ntk_t * Abc_NtkRenode( Abc_Ntk_t * pNtk, int nLutSize, int nCutsMax, int nFlowIters, int nAreaIters, int fArea, int fUseBdds, int fUseSops, int fUseCnfs, int fUseMv, int fVerbose );
+
+ pNtk = Abc_FrameReadNtk(pAbc);
+ pOut = Abc_FrameReadOut(pAbc);
+ pErr = Abc_FrameReadErr(pAbc);
+
+ // set defaults
+ nLutSize = 8;
+ nCutsMax = 4;
+ nFlowIters = 1;
+ nAreaIters = 1;
+ fArea = 0;
+ fUseBdds = 0;
+ fUseSops = 0;
+ fUseCnfs = 0;
+ fUseMv = 0;
+ fVerbose = 0;
+ Extra_UtilGetoptReset();
+ while ( ( c = Extra_UtilGetopt( argc, argv, "KCFAabscivh" ) ) != EOF )
+ {
+ switch ( c )
+ {
+ case 'K':
+ if ( globalUtilOptind >= argc )
+ {
+ fprintf( pErr, "Command line switch \"-F\" should be followed by an integer.\n" );
+ goto usage;
+ }
+ nLutSize = atoi(argv[globalUtilOptind]);
+ globalUtilOptind++;
+ if ( nLutSize < 0 )
+ goto usage;
+ break;
+ case 'C':
+ if ( globalUtilOptind >= argc )
+ {
+ fprintf( pErr, "Command line switch \"-C\" should be followed by an integer.\n" );
+ goto usage;
+ }
+ nCutsMax = atoi(argv[globalUtilOptind]);
+ globalUtilOptind++;
+ if ( nCutsMax < 0 )
+ goto usage;
+ break;
+ case 'F':
+ if ( globalUtilOptind >= argc )
+ {
+ fprintf( pErr, "Command line switch \"-F\" should be followed by a positive integer.\n" );
+ goto usage;
+ }
+ nFlowIters = atoi(argv[globalUtilOptind]);
+ globalUtilOptind++;
+ if ( nFlowIters < 0 )
+ goto usage;
+ break;
+ case 'A':
+ if ( globalUtilOptind >= argc )
+ {
+ fprintf( pErr, "Command line switch \"-A\" should be followed by a positive integer.\n" );
+ goto usage;
+ }
+ nAreaIters = atoi(argv[globalUtilOptind]);
+ globalUtilOptind++;
+ if ( nAreaIters < 0 )
+ goto usage;
+ break;
+ case 'a':
+ fArea ^= 1;
+ break;
+ case 'b':
+ fUseBdds ^= 1;
+ break;
+ case 's':
+ fUseSops ^= 1;
+ break;
+ case 'c':
+ fUseCnfs ^= 1;
+ break;
+ case 'i':
+ fUseMv ^= 1;
+ break;
+ case 'v':
+ fVerbose ^= 1;
+ break;
+ case 'h':
+ goto usage;
+ default:
+ goto usage;
+ }
+ }
+
+ if ( fUseBdds + fUseSops + fUseCnfs + fUseMv > 1 )
+ {
+ fprintf( pErr, "Cannot optimize two parameters at the same time.\n" );
+ return 1;
+ }
+
+ if ( nLutSize < 3 || nLutSize > IF_MAX_FUNC_LUTSIZE )
+ {
+ fprintf( pErr, "Incorrect LUT size (%d).\n", nLutSize );
+ return 1;
+ }
+
+ if ( nCutsMax < 1 || nCutsMax >= (1<<12) )
+ {
+ fprintf( pErr, "Incorrect number of cuts.\n" );
+ return 1;
+ }
+
+ if ( pNtk == NULL )
+ {
+ fprintf( pErr, "Empty network.\n" );
+ return 1;
+ }
+ if ( !Abc_NtkIsStrash(pNtk) )
+ {
+ fprintf( pErr, "Cannot renode a network that is not an AIG (run \"strash\").\n" );
+ return 1;
+ }
+
+ // get the new network
+ pNtkRes = Abc_NtkRenode( pNtk, nLutSize, nCutsMax, nFlowIters, nAreaIters, fArea, fUseBdds, fUseSops, fUseCnfs, fUseMv, fVerbose );
+ if ( pNtkRes == NULL )
+ {
+ fprintf( pErr, "Renoding has failed.\n" );
+ return 1;
+ }
+ // replace the current network
+ Abc_FrameReplaceCurrentNetwork( pAbc, pNtkRes );
+ return 0;
+
+usage:
+ fprintf( pErr, "usage: renode [-K num] [-C num] [-F num] [-A num] [-sbciav]\n" );
+ fprintf( pErr, "\t transforms the AIG into a logic network with larger nodes\n" );
+ fprintf( pErr, "\t while minimizing the number of FF literals of the node SOPs\n" );
+ fprintf( pErr, "\t-K num : the max cut size for renoding (2 < num < %d) [default = %d]\n", IF_MAX_FUNC_LUTSIZE+1, nLutSize );
+ fprintf( pErr, "\t-C num : the max number of cuts used at a node (0 < num < 2^12) [default = %d]\n", nCutsMax );
+ fprintf( pErr, "\t-F num : the number of area flow recovery iterations (num >= 0) [default = %d]\n", nFlowIters );
+ fprintf( pErr, "\t-A num : the number of exact area recovery iterations (num >= 0) [default = %d]\n", nAreaIters );
+ fprintf( pErr, "\t-s : toggles minimizing SOP cubes instead of FF lits [default = %s]\n", fUseSops? "yes": "no" );
+ fprintf( pErr, "\t-b : toggles minimizing BDD nodes instead of FF lits [default = %s]\n", fUseBdds? "yes": "no" );
+ fprintf( pErr, "\t-c : toggles minimizing CNF clauses instead of FF lits [default = %s]\n", fUseCnfs? "yes": "no" );
+ fprintf( pErr, "\t-i : toggles minimizing MV-SOP instead of FF lits [default = %s]\n", fUseMv? "yes": "no" );
+ fprintf( pErr, "\t-a : toggles area-oriented mapping [default = %s]\n", fArea? "yes": "no" );
+ fprintf( pErr, "\t-v : print verbose information [default = %s]\n", fVerbose? "yes": "no" );
+ fprintf( pErr, "\t-h : print the command usage\n");
+ return 1;
+}
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
int Abc_CommandCleanup( Abc_Frame_t * pAbc, int argc, char ** argv )
{
FILE * pOut, * pErr;
Abc_Ntk_t * pNtk;
int c;
- pNtk = Abc_FrameReadNet(pAbc);
+ pNtk = Abc_FrameReadNtk(pAbc);
pOut = Abc_FrameReadOut(pAbc);
pErr = Abc_FrameReadErr(pAbc);
// set defaults
- util_getopt_reset();
- while ( ( c = util_getopt( argc, argv, "h" ) ) != EOF )
+ Extra_UtilGetoptReset();
+ while ( ( c = Extra_UtilGetopt( argc, argv, "h" ) ) != EOF )
{
switch ( c )
{
@@ -1367,7 +2516,7 @@ int Abc_CommandCleanup( Abc_Frame_t * pAbc, int argc, char ** argv )
return 1;
}
// modify the current network
- Abc_NtkCleanup( pNtk, 0 );
+ Abc_NtkCleanup( pNtk, 1 );
return 0;
usage:
@@ -1394,13 +2543,13 @@ int Abc_CommandSweep( Abc_Frame_t * pAbc, int argc, char ** argv )
Abc_Ntk_t * pNtk;
int c;
- pNtk = Abc_FrameReadNet(pAbc);
+ pNtk = Abc_FrameReadNtk(pAbc);
pOut = Abc_FrameReadOut(pAbc);
pErr = Abc_FrameReadErr(pAbc);
// set defaults
- util_getopt_reset();
- while ( ( c = util_getopt( argc, argv, "h" ) ) != EOF )
+ Extra_UtilGetoptReset();
+ while ( ( c = Extra_UtilGetopt( argc, argv, "h" ) ) != EOF )
{
switch ( c )
{
@@ -1416,9 +2565,9 @@ int Abc_CommandSweep( Abc_Frame_t * pAbc, int argc, char ** argv )
fprintf( pErr, "Empty network.\n" );
return 1;
}
- if ( !Abc_NtkIsSopLogic(pNtk) && !Abc_NtkIsBddLogic(pNtk) )
+ if ( !Abc_NtkIsLogic(pNtk) )
{
- fprintf( pErr, "Sweep cannot be performed on an AIG or a mapped network (unmap it first).\n" );
+ fprintf( pErr, "The classical (SIS-like) sweep can only be performed on a logic network.\n" );
return 1;
}
// modify the current network
@@ -1453,7 +2602,7 @@ int Abc_CommandFastExtract( Abc_Frame_t * pAbc, int argc, char ** argv )
extern bool Abc_NtkFastExtract( Abc_Ntk_t * pNtk, Fxu_Data_t * p );
extern void Abc_NtkFxuFreeInfo( Fxu_Data_t * p );
- pNtk = Abc_FrameReadNet(pAbc);
+ pNtk = Abc_FrameReadNtk(pAbc);
pOut = Abc_FrameReadOut(pAbc);
pErr = Abc_FrameReadErr(pAbc);
@@ -1461,37 +2610,49 @@ int Abc_CommandFastExtract( Abc_Frame_t * pAbc, int argc, char ** argv )
p = ALLOC( Fxu_Data_t, 1 );
memset( p, 0, sizeof(Fxu_Data_t) );
// set the defaults
- p->nPairsMax = 30000;
- p->nNodesExt = 10000;
- p->fOnlyS = 0;
- p->fOnlyD = 0;
- p->fUse0 = 0;
- p->fUseCompl = 1;
- p->fVerbose = 0;
- util_getopt_reset();
- while ( (c = util_getopt(argc, argv, "LNsdzcvh")) != EOF )
+ p->nSingleMax = 20000;
+ p->nPairsMax = 30000;
+ p->nNodesExt = 10000;
+ p->fOnlyS = 0;
+ p->fOnlyD = 0;
+ p->fUse0 = 0;
+ p->fUseCompl = 1;
+ p->fVerbose = 0;
+ Extra_UtilGetoptReset();
+ while ( (c = Extra_UtilGetopt(argc, argv, "SDNsdzcvh")) != EOF )
{
switch (c)
{
- case 'L':
- if ( util_optind >= argc )
+ case 'S':
+ if ( globalUtilOptind >= argc )
+ {
+ fprintf( pErr, "Command line switch \"-S\" should be followed by an integer.\n" );
+ goto usage;
+ }
+ p->nSingleMax = atoi(argv[globalUtilOptind]);
+ globalUtilOptind++;
+ if ( p->nSingleMax < 0 )
+ goto usage;
+ break;
+ case 'D':
+ if ( globalUtilOptind >= argc )
{
- fprintf( pErr, "Command line switch \"-L\" should be followed by an integer.\n" );
+ fprintf( pErr, "Command line switch \"-D\" should be followed by an integer.\n" );
goto usage;
}
- p->nPairsMax = atoi(argv[util_optind]);
- util_optind++;
+ p->nPairsMax = atoi(argv[globalUtilOptind]);
+ globalUtilOptind++;
if ( p->nPairsMax < 0 )
goto usage;
break;
case 'N':
- if ( util_optind >= argc )
+ if ( globalUtilOptind >= argc )
{
fprintf( pErr, "Command line switch \"-N\" should be followed by an integer.\n" );
goto usage;
}
- p->nNodesExt = atoi(argv[util_optind]);
- util_optind++;
+ p->nNodesExt = atoi(argv[globalUtilOptind]);
+ globalUtilOptind++;
if ( p->nNodesExt < 0 )
goto usage;
break;
@@ -1516,7 +2677,7 @@ int Abc_CommandFastExtract( Abc_Frame_t * pAbc, int argc, char ** argv )
default:
goto usage;
}
- }
+ }
if ( pNtk == NULL )
{
@@ -1546,10 +2707,11 @@ int Abc_CommandFastExtract( Abc_Frame_t * pAbc, int argc, char ** argv )
return 0;
usage:
- fprintf( pErr, "usage: fx [-N num] [-L num] [-sdzcvh]\n");
+ fprintf( pErr, "usage: fx [-S num] [-D num] [-N num] [-sdzcvh]\n");
fprintf( pErr, "\t performs unate fast extract on the current network\n");
+ fprintf( pErr, "\t-S num : max number of single-cube divisors to consider [default = %d]\n", p->nSingleMax );
+ fprintf( pErr, "\t-D num : max number of double-cube divisors to consider [default = %d]\n", p->nPairsMax );
fprintf( pErr, "\t-N num : the maximum number of divisors to extract [default = %d]\n", p->nNodesExt );
- fprintf( pErr, "\t-L num : the maximum number of cube pairs to consider [default = %d]\n", p->nPairsMax );
fprintf( pErr, "\t-s : use only single-cube divisors [default = %s]\n", p->fOnlyS? "yes": "no" );
fprintf( pErr, "\t-d : use only double-cube divisors [default = %s]\n", p->fOnlyD? "yes": "no" );
fprintf( pErr, "\t-z : use zero-weight divisors [default = %s]\n", p->fUse0? "yes": "no" );
@@ -1571,6 +2733,97 @@ usage:
SeeAlso []
***********************************************************************/
+int Abc_CommandEliminate( Abc_Frame_t * pAbc, int argc, char ** argv )
+{
+ Abc_Ntk_t * pNtk;
+ FILE * pOut, * pErr;
+ int nMaxSize;
+ int fReverse;
+ int fVerbose;
+ int c;
+ extern int Abc_NtkEliminate( Abc_Ntk_t * pNtk, int nMaxSize, int fReverse, int fVerbose );
+
+ pNtk = Abc_FrameReadNtk(pAbc);
+ pOut = Abc_FrameReadOut(pAbc);
+ pErr = Abc_FrameReadErr(pAbc);
+
+ // set the defaults
+ nMaxSize = 8;
+ fReverse = 0;
+ fVerbose = 0;
+ Extra_UtilGetoptReset();
+ while ( (c = Extra_UtilGetopt(argc, argv, "Nrvh")) != EOF )
+ {
+ switch (c)
+ {
+ case 'N':
+ if ( globalUtilOptind >= argc )
+ {
+ fprintf( pErr, "Command line switch \"-N\" should be followed by a positive integer.\n" );
+ goto usage;
+ }
+ nMaxSize = atoi(argv[globalUtilOptind]);
+ globalUtilOptind++;
+ if ( nMaxSize <= 0 )
+ goto usage;
+ break;
+ case 'r':
+ fReverse ^= 1;
+ break;
+ case 'v':
+ fVerbose ^= 1;
+ break;
+ case 'h':
+ goto usage;
+ break;
+ default:
+ goto usage;
+ }
+ }
+
+ if ( pNtk == NULL )
+ {
+ fprintf( pErr, "Empty network.\n" );
+ return 1;
+ }
+
+ if ( Abc_NtkNodeNum(pNtk) == 0 )
+ {
+ fprintf( pErr, "The network does not have internal nodes.\n" );
+ return 1;
+ }
+
+ if ( !Abc_NtkIsLogic(pNtk) )
+ {
+ fprintf( pErr, "This command can only be applied to a logic network (run \"renode\" or \"if\").\n" );
+ return 1;
+ }
+
+ // the nodes to be merged are linked into the special linked list
+ Abc_NtkEliminate( pNtk, nMaxSize, fReverse, fVerbose );
+ return 0;
+
+usage:
+ fprintf( pErr, "usage: eliminate [-N num] [-rvh]\n");
+ fprintf( pErr, "\t greedily eliminates nodes by collapsing them into fanouts\n");
+ fprintf( pErr, "\t-N num : the maximum support size after collapsing [default = %d]\n", nMaxSize );
+ fprintf( pErr, "\t-r : use the reverse topological order [default = %s]\n", fReverse? "yes": "no" );
+ fprintf( pErr, "\t-v : print verbose information [default = %s]\n", fVerbose? "yes": "no" );
+ fprintf( pErr, "\t-h : print the command usage\n");
+ return 1;
+}
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
int Abc_CommandDisjoint( Abc_Frame_t * pAbc, int argc, char ** argv )
{
FILE * pOut, * pErr;
@@ -1580,7 +2833,7 @@ int Abc_CommandDisjoint( Abc_Frame_t * pAbc, int argc, char ** argv )
extern Abc_Ntk_t * Abc_NtkDsdGlobal( Abc_Ntk_t * pNtk, bool fVerbose, bool fPrint, bool fShort );
extern int Abc_NtkDsdLocal( Abc_Ntk_t * pNtk, bool fVerbose, bool fRecursive );
- pNtk = Abc_FrameReadNet(pAbc);
+ pNtk = Abc_FrameReadNtk(pAbc);
pOut = Abc_FrameReadOut(pAbc);
pErr = Abc_FrameReadErr(pAbc);
@@ -1590,8 +2843,8 @@ int Abc_CommandDisjoint( Abc_Frame_t * pAbc, int argc, char ** argv )
fVerbose = 0;
fPrint = 0;
fShort = 0;
- util_getopt_reset();
- while ( ( c = util_getopt( argc, argv, "grvpsh" ) ) != EOF )
+ Extra_UtilGetoptReset();
+ while ( ( c = Extra_UtilGetopt( argc, argv, "grvpsh" ) ) != EOF )
{
switch ( c )
{
@@ -1630,7 +2883,7 @@ int Abc_CommandDisjoint( Abc_Frame_t * pAbc, int argc, char ** argv )
// get the new network
if ( !Abc_NtkIsStrash(pNtk) )
{
- pNtkNew = Abc_NtkStrash( pNtk, 0, 0 );
+ pNtkNew = Abc_NtkStrash( pNtk, 0, 0, 0 );
pNtkRes = Abc_NtkDsdGlobal( pNtkNew, fVerbose, fPrint, fShort );
Abc_NtkDelete( pNtkNew );
}
@@ -1661,7 +2914,7 @@ int Abc_CommandDisjoint( Abc_Frame_t * pAbc, int argc, char ** argv )
{
if ( !Abc_NtkIsBddLogic( pNtk ) )
{
- fprintf( pErr, "This command is only applicable to logic BDD networks.\n" );
+ fprintf( pErr, "This command is only applicable to logic BDD networks (run \"bdd\").\n" );
return 1;
}
fprintf( stdout, "Performing simple non-recursive DSD of local functions.\n" );
@@ -1693,31 +2946,324 @@ usage:
SeeAlso []
***********************************************************************/
+int Abc_CommandImfs( Abc_Frame_t * pAbc, int argc, char ** argv )
+{
+ FILE * pOut, * pErr;
+ Abc_Ntk_t * pNtk;
+ Res_Par_t Pars, * pPars = &Pars;
+ int c;
+
+// printf( "Implementation of this command is not finished.\n" );
+// return 1;
+
+ pNtk = Abc_FrameReadNtk(pAbc);
+ pOut = Abc_FrameReadOut(pAbc);
+ pErr = Abc_FrameReadErr(pAbc);
+
+ // set defaults
+ pPars->nWindow = 62;
+ pPars->nCands = 5;
+ pPars->nSimWords = 4;
+ pPars->nGrowthLevel = 0;
+ pPars->fArea = 0;
+ pPars->fVerbose = 0;
+ pPars->fVeryVerbose = 0;
+ Extra_UtilGetoptReset();
+ while ( ( c = Extra_UtilGetopt( argc, argv, "WSCLavwh" ) ) != EOF )
+ {
+ switch ( c )
+ {
+ case 'W':
+ if ( globalUtilOptind >= argc )
+ {
+ fprintf( pErr, "Command line switch \"-W\" should be followed by an integer.\n" );
+ goto usage;
+ }
+ pPars->nWindow = atoi(argv[globalUtilOptind]);
+ globalUtilOptind++;
+ if ( pPars->nWindow < 1 || pPars->nWindow > 99 )
+ goto usage;
+ break;
+ case 'S':
+ if ( globalUtilOptind >= argc )
+ {
+ fprintf( pErr, "Command line switch \"-S\" should be followed by an integer.\n" );
+ goto usage;
+ }
+ pPars->nSimWords = atoi(argv[globalUtilOptind]);
+ globalUtilOptind++;
+ if ( pPars->nSimWords < 1 || pPars->nSimWords > 256 )
+ goto usage;
+ break;
+ case 'C':
+ if ( globalUtilOptind >= argc )
+ {
+ fprintf( pErr, "Command line switch \"-C\" should be followed by an integer.\n" );
+ goto usage;
+ }
+ pPars->nCands = atoi(argv[globalUtilOptind]);
+ globalUtilOptind++;
+ if ( pPars->nCands < 0 || pPars->nCands > ABC_INFINITY )
+ goto usage;
+ break;
+ case 'L':
+ if ( globalUtilOptind >= argc )
+ {
+ fprintf( pErr, "Command line switch \"-L\" should be followed by an integer.\n" );
+ goto usage;
+ }
+ pPars->nGrowthLevel = atoi(argv[globalUtilOptind]);
+ globalUtilOptind++;
+ if ( pPars->nGrowthLevel < 0 || pPars->nGrowthLevel > ABC_INFINITY )
+ goto usage;
+ break;
+ case 'a':
+ pPars->fArea ^= 1;
+ break;
+ case 'v':
+ pPars->fVerbose ^= 1;
+ break;
+ case 'w':
+ pPars->fVeryVerbose ^= 1;
+ break;
+ case 'h':
+ goto usage;
+ default:
+ goto usage;
+ }
+ }
+
+ if ( pNtk == NULL )
+ {
+ fprintf( pErr, "Empty network.\n" );
+ return 1;
+ }
+ if ( !Abc_NtkIsLogic(pNtk) )
+ {
+ fprintf( pErr, "This command can only be applied to a logic network.\n" );
+ return 1;
+ }
+
+ // modify the current network
+ if ( !Abc_NtkResynthesize( pNtk, pPars ) )
+ {
+ fprintf( pErr, "Resynthesis has failed.\n" );
+ return 1;
+ }
+ return 0;
+
+usage:
+ fprintf( pErr, "usage: imfs [-W <NM>] [-L <num>] [-C <num>] [-S <num>] [-avwh]\n" );
+ fprintf( pErr, "\t performs resubstitution-based resynthesis with interpolation\n" );
+ fprintf( pErr, "\t (there is another command for resynthesis after LUT mapping, \"lutpack\")\n" );
+ fprintf( pErr, "\t-W <NM> : fanin/fanout levels (NxM) of the window (00 <= NM <= 99) [default = %d%d]\n", pPars->nWindow/10, pPars->nWindow%10 );
+ fprintf( pErr, "\t-C <num> : the max number of resub candidates (1 <= n) [default = %d]\n", pPars->nCands );
+ fprintf( pErr, "\t-S <num> : the number of simulation words (1 <= n <= 256) [default = %d]\n", pPars->nSimWords );
+ fprintf( pErr, "\t-L <num> : the largest increase in node level after resynthesis (0 <= num) [default = %d]\n", pPars->nGrowthLevel );
+ fprintf( pErr, "\t-a : toggle optimization for area only [default = %s]\n", pPars->fArea? "yes": "no" );
+ fprintf( pErr, "\t-v : toggle verbose printout [default = %s]\n", pPars->fVerbose? "yes": "no" );
+ fprintf( pErr, "\t-w : toggle printout subgraph statistics [default = %s]\n", pPars->fVeryVerbose? "yes": "no" );
+ fprintf( pErr, "\t-h : print the command usage\n");
+ return 1;
+}
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Abc_CommandLutpack( Abc_Frame_t * pAbc, int argc, char ** argv )
+{
+ FILE * pOut, * pErr;
+ Abc_Ntk_t * pNtk;
+ Lpk_Par_t Pars, * pPars = &Pars;
+ int c;
+
+ pNtk = Abc_FrameReadNtk(pAbc);
+ pOut = Abc_FrameReadOut(pAbc);
+ pErr = Abc_FrameReadErr(pAbc);
+
+ // set defaults
+ memset( pPars, 0, sizeof(Lpk_Par_t) );
+ pPars->nLutsMax = 4; // (N) the maximum number of LUTs in the structure
+ pPars->nLutsOver = 3; // (Q) the maximum number of LUTs not in the MFFC
+ pPars->nVarsShared = 0; // (S) the maximum number of shared variables (crossbars)
+ pPars->nGrowthLevel = 0; // (L) the maximum number of increased levels
+ pPars->fSatur = 1;
+ pPars->fZeroCost = 0;
+ pPars->fFirst = 0;
+ pPars->fOldAlgo = 0;
+ pPars->fVerbose = 0;
+ pPars->fVeryVerbose = 0;
+ Extra_UtilGetoptReset();
+ while ( ( c = Extra_UtilGetopt( argc, argv, "NQSLszfovwh" ) ) != EOF )
+ {
+ switch ( c )
+ {
+ case 'N':
+ if ( globalUtilOptind >= argc )
+ {
+ fprintf( pErr, "Command line switch \"-N\" should be followed by an integer.\n" );
+ goto usage;
+ }
+ pPars->nLutsMax = atoi(argv[globalUtilOptind]);
+ globalUtilOptind++;
+ if ( pPars->nLutsMax < 2 || pPars->nLutsMax > 8 )
+ goto usage;
+ break;
+ case 'Q':
+ if ( globalUtilOptind >= argc )
+ {
+ fprintf( pErr, "Command line switch \"-Q\" should be followed by an integer.\n" );
+ goto usage;
+ }
+ pPars->nLutsOver = atoi(argv[globalUtilOptind]);
+ globalUtilOptind++;
+ if ( pPars->nLutsOver < 0 || pPars->nLutsOver > 8 )
+ goto usage;
+ break;
+ case 'S':
+ if ( globalUtilOptind >= argc )
+ {
+ fprintf( pErr, "Command line switch \"-S\" should be followed by an integer.\n" );
+ goto usage;
+ }
+ pPars->nVarsShared = atoi(argv[globalUtilOptind]);
+ globalUtilOptind++;
+ if ( pPars->nVarsShared < 0 || pPars->nVarsShared > 4 )
+ goto usage;
+ break;
+ case 'L':
+ if ( globalUtilOptind >= argc )
+ {
+ fprintf( pErr, "Command line switch \"-L\" should be followed by an integer.\n" );
+ goto usage;
+ }
+ pPars->nGrowthLevel = atoi(argv[globalUtilOptind]);
+ globalUtilOptind++;
+ if ( pPars->nGrowthLevel < 0 || pPars->nGrowthLevel > ABC_INFINITY )
+ goto usage;
+ break;
+ case 's':
+ pPars->fSatur ^= 1;
+ break;
+ case 'z':
+ pPars->fZeroCost ^= 1;
+ break;
+ case 'f':
+ pPars->fFirst ^= 1;
+ break;
+ case 'o':
+ pPars->fOldAlgo ^= 1;
+ break;
+ case 'v':
+ pPars->fVerbose ^= 1;
+ break;
+ case 'w':
+ pPars->fVeryVerbose ^= 1;
+ break;
+ case 'h':
+ goto usage;
+ default:
+ goto usage;
+ }
+ }
+
+ if ( pNtk == NULL )
+ {
+ fprintf( pErr, "Empty network.\n" );
+ return 1;
+ }
+ if ( !Abc_NtkIsLogic(pNtk) )
+ {
+ fprintf( pErr, "This command can only be applied to a logic network.\n" );
+ return 1;
+ }
+ if ( pPars->nVarsShared < 0 || pPars->nVarsShared > 3 )
+ {
+ fprintf( pErr, "The number of shared variables (%d) is not in the range 0 <= S <= 3.\n", pPars->nVarsShared );
+ return 1;
+ }
+
+ // modify the current network
+ if ( !Lpk_Resynthesize( pNtk, pPars ) )
+ {
+ fprintf( pErr, "Resynthesis has failed.\n" );
+ return 1;
+ }
+ return 0;
+
+usage:
+ fprintf( pErr, "usage: lutpack [-N <num>] [-Q <num>] [-S <num>] [-L <num>] [-szfovwh]\n" );
+ fprintf( pErr, "\t performs \"rewriting\" for LUT networks;\n" );
+ fprintf( pErr, "\t determines LUT size as the max fanin count of a node;\n" );
+ fprintf( pErr, "\t if the network is not LUT-mapped, packs it into 6-LUTs\n" );
+ fprintf( pErr, "\t (there is another command for resynthesis after LUT mapping, \"imfs\")\n" );
+ fprintf( pErr, "\t-N <num> : the max number of LUTs in the structure (2 <= num) [default = %d]\n", pPars->nLutsMax );
+ fprintf( pErr, "\t-Q <num> : the max number of LUTs not in MFFC (0 <= num) [default = %d]\n", pPars->nLutsOver );
+ fprintf( pErr, "\t-S <num> : the max number of LUT inputs shared (0 <= num <= 3) [default = %d]\n", pPars->nVarsShared );
+ fprintf( pErr, "\t-L <num> : max level increase after resynthesis (0 <= num) [default = %d]\n", pPars->nGrowthLevel );
+ fprintf( pErr, "\t-s : toggle iteration till saturation [default = %s]\n", pPars->fSatur? "yes": "no" );
+ fprintf( pErr, "\t-z : toggle zero-cost replacements [default = %s]\n", pPars->fZeroCost? "yes": "no" );
+ fprintf( pErr, "\t-f : toggle using only first node and first cut [default = %s]\n", pPars->fFirst? "yes": "no" );
+ fprintf( pErr, "\t-o : toggle using old implementation [default = %s]\n", pPars->fOldAlgo? "yes": "no" );
+ fprintf( pErr, "\t-v : toggle verbose printout [default = %s]\n", pPars->fVerbose? "yes": "no" );
+ fprintf( pErr, "\t-w : toggle detailed printout of decomposed functions [default = %s]\n", pPars->fVeryVerbose? "yes": "no" );
+ fprintf( pErr, "\t-h : print the command usage\n");
+ return 1;
+}
+
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
int Abc_CommandRewrite( Abc_Frame_t * pAbc, int argc, char ** argv )
{
FILE * pOut, * pErr;
Abc_Ntk_t * pNtk;
int c;
+ bool fUpdateLevel;
bool fPrecompute;
bool fUseZeros;
bool fVerbose;
+ bool fVeryVerbose;
+ bool fPlaceEnable;
// external functions
- extern void Rwr_Precompute();
- extern int Abc_NtkRewrite( Abc_Ntk_t * pNtk, int fUseZeros, int fVerbose );
+ extern void Rwr_Precompute();
- pNtk = Abc_FrameReadNet(pAbc);
+ pNtk = Abc_FrameReadNtk(pAbc);
pOut = Abc_FrameReadOut(pAbc);
pErr = Abc_FrameReadErr(pAbc);
// set defaults
- fPrecompute = 0;
- fUseZeros = 0;
- fVerbose = 0;
- util_getopt_reset();
- while ( ( c = util_getopt( argc, argv, "xzvh" ) ) != EOF )
+ fUpdateLevel = 1;
+ fPrecompute = 0;
+ fUseZeros = 0;
+ fVerbose = 0;
+ fVeryVerbose = 0;
+ fPlaceEnable = 0;
+ Extra_UtilGetoptReset();
+ while ( ( c = Extra_UtilGetopt( argc, argv, "lxzvwh" ) ) != EOF )
{
switch ( c )
{
+ case 'l':
+ fUpdateLevel ^= 1;
+ break;
case 'x':
fPrecompute ^= 1;
break;
@@ -1727,6 +3273,12 @@ int Abc_CommandRewrite( Abc_Frame_t * pAbc, int argc, char ** argv )
case 'v':
fVerbose ^= 1;
break;
+ case 'w':
+ fVeryVerbose ^= 1;
+ break;
+ case 'p':
+ fPlaceEnable ^= 1;
+ break;
case 'h':
goto usage;
default:
@@ -1757,7 +3309,7 @@ int Abc_CommandRewrite( Abc_Frame_t * pAbc, int argc, char ** argv )
}
// modify the current network
- if ( !Abc_NtkRewrite( pNtk, fUseZeros, fVerbose ) )
+ if ( !Abc_NtkRewrite( pNtk, fUpdateLevel, fUseZeros, fVerbose, fVeryVerbose, fPlaceEnable ) )
{
fprintf( pErr, "Rewriting has failed.\n" );
return 1;
@@ -1765,13 +3317,16 @@ int Abc_CommandRewrite( Abc_Frame_t * pAbc, int argc, char ** argv )
return 0;
usage:
- fprintf( pErr, "usage: rewrite [-zvh]\n" );
+ fprintf( pErr, "usage: rewrite [-lzvwh]\n" );
fprintf( pErr, "\t performs technology-independent rewriting of the AIG\n" );
+ fprintf( pErr, "\t-l : toggle preserving the number of levels [default = %s]\n", fUpdateLevel? "yes": "no" );
fprintf( pErr, "\t-z : toggle using zero-cost replacements [default = %s]\n", fUseZeros? "yes": "no" );
fprintf( pErr, "\t-v : toggle verbose printout [default = %s]\n", fVerbose? "yes": "no" );
+ fprintf( pErr, "\t-w : toggle printout subgraph statistics [default = %s]\n", fVeryVerbose? "yes": "no" );
+// fprintf( pErr, "\t-p : toggle placement-aware rewriting [default = %s]\n", fPlaceEnable? "yes": "no" );
fprintf( pErr, "\t-h : print the command usage\n");
return 1;
-}
+}
/**Function*************************************************************
@@ -1791,48 +3346,53 @@ int Abc_CommandRefactor( Abc_Frame_t * pAbc, int argc, char ** argv )
int c;
int nNodeSizeMax;
int nConeSizeMax;
+ bool fUpdateLevel;
bool fUseZeros;
bool fUseDcs;
bool fVerbose;
- extern int Abc_NtkRefactor( Abc_Ntk_t * pNtk, int nNodeSizeMax, int nConeSizeMax, bool fUseZeros, bool fUseDcs, bool fVerbose );
+ extern int Abc_NtkRefactor( Abc_Ntk_t * pNtk, int nNodeSizeMax, int nConeSizeMax, bool fUpdateLevel, bool fUseZeros, bool fUseDcs, bool fVerbose );
- pNtk = Abc_FrameReadNet(pAbc);
+ pNtk = Abc_FrameReadNtk(pAbc);
pOut = Abc_FrameReadOut(pAbc);
pErr = Abc_FrameReadErr(pAbc);
// set defaults
nNodeSizeMax = 10;
nConeSizeMax = 16;
+ fUpdateLevel = 1;
fUseZeros = 0;
fUseDcs = 0;
fVerbose = 0;
- util_getopt_reset();
- while ( ( c = util_getopt( argc, argv, "NCzdvh" ) ) != EOF )
+ Extra_UtilGetoptReset();
+ while ( ( c = Extra_UtilGetopt( argc, argv, "NClzdvh" ) ) != EOF )
{
switch ( c )
{
case 'N':
- if ( util_optind >= argc )
+ if ( globalUtilOptind >= argc )
{
fprintf( pErr, "Command line switch \"-N\" should be followed by an integer.\n" );
goto usage;
}
- nNodeSizeMax = atoi(argv[util_optind]);
- util_optind++;
+ nNodeSizeMax = atoi(argv[globalUtilOptind]);
+ globalUtilOptind++;
if ( nNodeSizeMax < 0 )
goto usage;
break;
case 'C':
- if ( util_optind >= argc )
+ if ( globalUtilOptind >= argc )
{
fprintf( pErr, "Command line switch \"-C\" should be followed by an integer.\n" );
goto usage;
}
- nConeSizeMax = atoi(argv[util_optind]);
- util_optind++;
+ nConeSizeMax = atoi(argv[globalUtilOptind]);
+ globalUtilOptind++;
if ( nConeSizeMax < 0 )
goto usage;
break;
+ case 'l':
+ fUpdateLevel ^= 1;
+ break;
case 'z':
fUseZeros ^= 1;
break;
@@ -1872,7 +3432,7 @@ int Abc_CommandRefactor( Abc_Frame_t * pAbc, int argc, char ** argv )
}
// modify the current network
- if ( !Abc_NtkRefactor( pNtk, nNodeSizeMax, nConeSizeMax, fUseZeros, fUseDcs, fVerbose ) )
+ if ( !Abc_NtkRefactor( pNtk, nNodeSizeMax, nConeSizeMax, fUpdateLevel, fUseZeros, fUseDcs, fVerbose ) )
{
fprintf( pErr, "Refactoring has failed.\n" );
return 1;
@@ -1880,10 +3440,11 @@ int Abc_CommandRefactor( Abc_Frame_t * pAbc, int argc, char ** argv )
return 0;
usage:
- fprintf( pErr, "usage: refactor [-N num] [-C num] [-zdvh]\n" );
+ fprintf( pErr, "usage: refactor [-N num] [-C num] [-lzdvh]\n" );
fprintf( pErr, "\t performs technology-independent refactoring of the AIG\n" );
fprintf( pErr, "\t-N num : the max support of the collapsed node [default = %d]\n", nNodeSizeMax );
fprintf( pErr, "\t-C num : the max support of the containing cone [default = %d]\n", nConeSizeMax );
+ fprintf( pErr, "\t-l : toggle preserving the number of levels [default = %s]\n", fUpdateLevel? "yes": "no" );
fprintf( pErr, "\t-z : toggle using zero-cost replacements [default = %s]\n", fUseZeros? "yes": "no" );
fprintf( pErr, "\t-d : toggle using don't-cares [default = %s]\n", fUseDcs? "yes": "no" );
fprintf( pErr, "\t-v : toggle verbose printout [default = %s]\n", fVerbose? "yes": "no" );
@@ -1891,6 +3452,452 @@ usage:
return 1;
}
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Abc_CommandRestructure( Abc_Frame_t * pAbc, int argc, char ** argv )
+{
+ FILE * pOut, * pErr;
+ Abc_Ntk_t * pNtk;
+ int c;
+ int nCutsMax;
+ bool fUpdateLevel;
+ bool fUseZeros;
+ bool fVerbose;
+ extern int Abc_NtkRestructure( Abc_Ntk_t * pNtk, int nCutsMax, bool fUpdateLevel, bool fUseZeros, bool fVerbose );
+
+ pNtk = Abc_FrameReadNtk(pAbc);
+ pOut = Abc_FrameReadOut(pAbc);
+ pErr = Abc_FrameReadErr(pAbc);
+
+ // set defaults
+ nCutsMax = 5;
+ fUpdateLevel = 0;
+ fUseZeros = 0;
+ fVerbose = 0;
+ Extra_UtilGetoptReset();
+ while ( ( c = Extra_UtilGetopt( argc, argv, "Klzvh" ) ) != EOF )
+ {
+ switch ( c )
+ {
+ case 'K':
+ if ( globalUtilOptind >= argc )
+ {
+ fprintf( pErr, "Command line switch \"-K\" should be followed by an integer.\n" );
+ goto usage;
+ }
+ nCutsMax = atoi(argv[globalUtilOptind]);
+ globalUtilOptind++;
+ if ( nCutsMax < 0 )
+ goto usage;
+ break;
+ case 'l':
+ fUpdateLevel ^= 1;
+ break;
+ case 'z':
+ fUseZeros ^= 1;
+ break;
+ case 'v':
+ fVerbose ^= 1;
+ break;
+ case 'h':
+ goto usage;
+ default:
+ goto usage;
+ }
+ }
+
+ if ( pNtk == NULL )
+ {
+ fprintf( pErr, "Empty network.\n" );
+ return 1;
+ }
+ if ( nCutsMax < 4 || nCutsMax > CUT_SIZE_MAX )
+ {
+ fprintf( pErr, "Can only compute the cuts for %d <= K <= %d.\n", 4, CUT_SIZE_MAX );
+ return 1;
+ }
+ if ( !Abc_NtkIsStrash(pNtk) )
+ {
+ fprintf( pErr, "This command can only be applied to an AIG (run \"strash\").\n" );
+ return 1;
+ }
+ if ( Abc_NtkGetChoiceNum(pNtk) )
+ {
+ fprintf( pErr, "AIG resynthesis cannot be applied to AIGs with choice nodes.\n" );
+ return 1;
+ }
+
+ // modify the current network
+ if ( !Abc_NtkRestructure( pNtk, nCutsMax, fUpdateLevel, fUseZeros, fVerbose ) )
+ {
+ fprintf( pErr, "Refactoring has failed.\n" );
+ return 1;
+ }
+ return 0;
+
+usage:
+ fprintf( pErr, "usage: restructure [-K num] [-lzvh]\n" );
+ fprintf( pErr, "\t performs technology-independent restructuring of the AIG\n" );
+ fprintf( pErr, "\t-K num : the max cut size (%d <= num <= %d) [default = %d]\n", CUT_SIZE_MIN, CUT_SIZE_MAX, nCutsMax );
+ fprintf( pErr, "\t-l : toggle preserving the number of levels [default = %s]\n", fUpdateLevel? "yes": "no" );
+ fprintf( pErr, "\t-z : toggle using zero-cost replacements [default = %s]\n", fUseZeros? "yes": "no" );
+ fprintf( pErr, "\t-v : toggle verbose printout [default = %s]\n", fVerbose? "yes": "no" );
+ fprintf( pErr, "\t-h : print the command usage\n");
+ return 1;
+}
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Abc_CommandResubstitute( Abc_Frame_t * pAbc, int argc, char ** argv )
+{
+ FILE * pOut, * pErr;
+ Abc_Ntk_t * pNtk;
+ int RS_CUT_MIN = 4;
+ int RS_CUT_MAX = 16;
+ int c;
+ int nCutsMax;
+ int nNodesMax;
+ int nLevelsOdc;
+ bool fUpdateLevel;
+ bool fUseZeros;
+ bool fVerbose;
+ bool fVeryVerbose;
+ extern int Abc_NtkResubstitute( Abc_Ntk_t * pNtk, int nCutsMax, int nNodesMax, int nLevelsOdc, bool fUpdateLevel, bool fVerbose, bool fVeryVerbose );
+
+ pNtk = Abc_FrameReadNtk(pAbc);
+ pOut = Abc_FrameReadOut(pAbc);
+ pErr = Abc_FrameReadErr(pAbc);
+
+ // set defaults
+ nCutsMax = 8;
+ nNodesMax = 1;
+ nLevelsOdc = 0;
+ fUpdateLevel = 1;
+ fUseZeros = 0;
+ fVerbose = 0;
+ fVeryVerbose = 0;
+ Extra_UtilGetoptReset();
+ while ( ( c = Extra_UtilGetopt( argc, argv, "KNFlzvwh" ) ) != EOF )
+ {
+ switch ( c )
+ {
+ case 'K':
+ if ( globalUtilOptind >= argc )
+ {
+ fprintf( pErr, "Command line switch \"-K\" should be followed by an integer.\n" );
+ goto usage;
+ }
+ nCutsMax = atoi(argv[globalUtilOptind]);
+ globalUtilOptind++;
+ if ( nCutsMax < 0 )
+ goto usage;
+ break;
+ case 'N':
+ if ( globalUtilOptind >= argc )
+ {
+ fprintf( pErr, "Command line switch \"-N\" should be followed by an integer.\n" );
+ goto usage;
+ }
+ nNodesMax = atoi(argv[globalUtilOptind]);
+ globalUtilOptind++;
+ if ( nNodesMax < 0 )
+ goto usage;
+ break;
+ case 'F':
+ if ( globalUtilOptind >= argc )
+ {
+ fprintf( pErr, "Command line switch \"-F\" should be followed by an integer.\n" );
+ goto usage;
+ }
+ nLevelsOdc = atoi(argv[globalUtilOptind]);
+ globalUtilOptind++;
+ if ( nLevelsOdc < 0 )
+ goto usage;
+ break;
+ case 'l':
+ fUpdateLevel ^= 1;
+ break;
+ case 'z':
+ fUseZeros ^= 1;
+ break;
+ case 'v':
+ fVerbose ^= 1;
+ break;
+ case 'w':
+ fVeryVerbose ^= 1;
+ break;
+ case 'h':
+ goto usage;
+ default:
+ goto usage;
+ }
+ }
+
+ if ( pNtk == NULL )
+ {
+ fprintf( pErr, "Empty network.\n" );
+ return 1;
+ }
+ if ( nCutsMax < RS_CUT_MIN || nCutsMax > RS_CUT_MAX )
+ {
+ fprintf( pErr, "Can only compute cuts for %d <= K <= %d.\n", RS_CUT_MIN, RS_CUT_MAX );
+ return 1;
+ }
+ if ( nNodesMax < 0 || nNodesMax > 3 )
+ {
+ fprintf( pErr, "Can only resubstitute at most 3 nodes.\n" );
+ return 1;
+ }
+ if ( !Abc_NtkIsStrash(pNtk) )
+ {
+ fprintf( pErr, "This command can only be applied to an AIG (run \"strash\").\n" );
+ return 1;
+ }
+ if ( Abc_NtkGetChoiceNum(pNtk) )
+ {
+ fprintf( pErr, "AIG resynthesis cannot be applied to AIGs with choice nodes.\n" );
+ return 1;
+ }
+
+ // modify the current network
+ if ( !Abc_NtkResubstitute( pNtk, nCutsMax, nNodesMax, nLevelsOdc, fUpdateLevel, fVerbose, fVeryVerbose ) )
+ {
+ fprintf( pErr, "Refactoring has failed.\n" );
+ return 1;
+ }
+ return 0;
+
+usage:
+ fprintf( pErr, "usage: resub [-K num] [-N num] [-F num] [-lzvwh]\n" );
+ fprintf( pErr, "\t performs technology-independent restructuring of the AIG\n" );
+ fprintf( pErr, "\t-K num : the max cut size (%d <= num <= %d) [default = %d]\n", RS_CUT_MIN, RS_CUT_MAX, nCutsMax );
+ fprintf( pErr, "\t-N num : the max number of nodes to add (0 <= num <= 3) [default = %d]\n", nNodesMax );
+ fprintf( pErr, "\t-F num : the number of fanout levels for ODC computation [default = %d]\n", nLevelsOdc );
+ fprintf( pErr, "\t-l : toggle preserving the number of levels [default = %s]\n", fUpdateLevel? "yes": "no" );
+ fprintf( pErr, "\t-z : toggle using zero-cost replacements [default = %s]\n", fUseZeros? "yes": "no" );
+ fprintf( pErr, "\t-v : toggle verbose printout [default = %s]\n", fVerbose? "yes": "no" );
+ fprintf( pErr, "\t-w : toggle verbose printout of ODC computation [default = %s]\n", fVeryVerbose? "yes": "no" );
+ fprintf( pErr, "\t-h : print the command usage\n");
+ return 1;
+}
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Abc_CommandRr( Abc_Frame_t * pAbc, int argc, char ** argv )
+{
+ FILE * pOut, * pErr;
+ Abc_Ntk_t * pNtk;
+ int c, Window;
+ int nFaninLevels;
+ int nFanoutLevels;
+ int fUseFanouts;
+ int fVerbose;
+ extern int Abc_NtkRR( Abc_Ntk_t * pNtk, int nFaninLevels, int nFanoutLevels, int fUseFanouts, int fVerbose );
+
+ pNtk = Abc_FrameReadNtk(pAbc);
+ pOut = Abc_FrameReadOut(pAbc);
+ pErr = Abc_FrameReadErr(pAbc);
+
+ // set defaults
+ nFaninLevels = 3;
+ nFanoutLevels = 3;
+ fUseFanouts = 0;
+ fVerbose = 0;
+ Extra_UtilGetoptReset();
+ while ( ( c = Extra_UtilGetopt( argc, argv, "Wfvh" ) ) != EOF )
+ {
+ switch ( c )
+ {
+ case 'W':
+ if ( globalUtilOptind >= argc )
+ {
+ fprintf( pErr, "Command line switch \"-W\" should be followed by an integer.\n" );
+ goto usage;
+ }
+ Window = atoi(argv[globalUtilOptind]);
+ globalUtilOptind++;
+ if ( Window < 0 )
+ goto usage;
+ nFaninLevels = Window / 10;
+ nFanoutLevels = Window % 10;
+ break;
+ case 'f':
+ fUseFanouts ^= 1;
+ break;
+ case 'v':
+ fVerbose ^= 1;
+ break;
+ case 'h':
+ goto usage;
+ default:
+ goto usage;
+ }
+ }
+
+ if ( pNtk == NULL )
+ {
+ fprintf( pErr, "Empty network.\n" );
+ return 1;
+ }
+ if ( !Abc_NtkIsStrash(pNtk) )
+ {
+ fprintf( pErr, "This command can only be applied to an AIG (run \"strash\").\n" );
+ return 1;
+ }
+ if ( Abc_NtkGetChoiceNum(pNtk) )
+ {
+ fprintf( pErr, "AIG resynthesis cannot be applied to AIGs with choice nodes.\n" );
+ return 1;
+ }
+
+ // modify the current network
+ if ( !Abc_NtkRR( pNtk, nFaninLevels, nFanoutLevels, fUseFanouts, fVerbose ) )
+ {
+ fprintf( pErr, "Redundancy removal has failed.\n" );
+ return 1;
+ }
+ return 0;
+
+usage:
+ fprintf( pErr, "usage: rr [-W NM] [-fvh]\n" );
+ fprintf( pErr, "\t removes combinational redundancies in the current network\n" );
+ fprintf( pErr, "\t-W NM : window size: TFI (N) and TFO (M) logic levels [default = %d%d]\n", nFaninLevels, nFanoutLevels );
+ fprintf( pErr, "\t-f : toggle RR w.r.t. fanouts [default = %s]\n", fUseFanouts? "yes": "no" );
+ fprintf( pErr, "\t-v : toggle verbose printout [default = %s]\n", fVerbose? "yes": "no" );
+ fprintf( pErr, "\t-h : print the command usage\n");
+ return 1;
+}
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Abc_CommandCascade( Abc_Frame_t * pAbc, int argc, char ** argv )
+{
+ FILE * pOut, * pErr;
+ Abc_Ntk_t * pNtk, * pNtkRes;
+ int c, nLutSize;
+ int fCheck;
+ int fVerbose;
+ extern Abc_Ntk_t * Abc_NtkCascade( Abc_Ntk_t * pNtk, int nLutSize, int fCheck, int fVerbose );
+
+ pNtk = Abc_FrameReadNtk(pAbc);
+ pOut = Abc_FrameReadOut(pAbc);
+ pErr = Abc_FrameReadErr(pAbc);
+
+ // set defaults
+ nLutSize = 12;
+ fCheck = 0;
+ fVerbose = 0;
+ Extra_UtilGetoptReset();
+ while ( ( c = Extra_UtilGetopt( argc, argv, "Kcvh" ) ) != EOF )
+ {
+ switch ( c )
+ {
+ case 'K':
+ if ( globalUtilOptind >= argc )
+ {
+ fprintf( pErr, "Command line switch \"-K\" should be followed by an integer.\n" );
+ goto usage;
+ }
+ nLutSize = atoi(argv[globalUtilOptind]);
+ globalUtilOptind++;
+ if ( nLutSize < 0 )
+ goto usage;
+ break;
+ case 'c':
+ fCheck ^= 1;
+ break;
+ case 'v':
+ fVerbose ^= 1;
+ break;
+ case 'h':
+ goto usage;
+ default:
+ goto usage;
+ }
+ }
+
+ if ( pNtk == NULL )
+ {
+ fprintf( pErr, "Empty network.\n" );
+ return 1;
+ }
+
+ if ( !Abc_NtkIsLogic(pNtk) && !Abc_NtkIsStrash(pNtk) )
+ {
+ fprintf( pErr, "Can only collapse a logic network or an AIG.\n" );
+ return 1;
+ }
+
+ // get the new network
+ if ( Abc_NtkIsStrash(pNtk) )
+ pNtkRes = Abc_NtkCascade( pNtk, nLutSize, fCheck, fVerbose );
+ else
+ {
+ pNtk = Abc_NtkStrash( pNtk, 0, 0, 0 );
+ pNtkRes = Abc_NtkCascade( pNtk, nLutSize, fCheck, fVerbose );
+ Abc_NtkDelete( pNtk );
+ }
+ if ( pNtkRes == NULL )
+ {
+ fprintf( pErr, "Cascade synthesis has failed.\n" );
+ return 1;
+ }
+ // replace the current network
+ Abc_FrameReplaceCurrentNetwork( pAbc, pNtkRes );
+ return 0;
+
+usage:
+ fprintf( pErr, "usage: cascade [-K <num>] [-cvh]\n" );
+ fprintf( pErr, "\t performs LUT cascade synthesis for the current network\n" );
+ fprintf( pErr, "\t-K num : the number of LUT inputs [default = %d]\n", nLutSize );
+ fprintf( pErr, "\t-c : check equivalence after synthesis [default = %s]\n", fCheck? "yes": "no" );
+ fprintf( pErr, "\t-v : toggle verbose printout [default = %s]\n", fVerbose? "yes": "no" );
+ fprintf( pErr, "\t-h : print the command usage\n");
+ fprintf( pErr, "\t \n");
+ fprintf( pErr, " A lookup-table cascade is a programmable architecture developed by\n");
+ fprintf( pErr, " Professor Tsutomu Sasao (sasao@cse.kyutech.ac.jp) at Kyushu Institute\n");
+ fprintf( pErr, " of Technology. This work received Takeda Techno-Entrepreneurship Award:\n");
+ fprintf( pErr, " http://www.lsi-cad.com/sasao/photo/takeda.html\n");
+ fprintf( pErr, "\t \n");
+ return 1;
+}
+
/**Function*************************************************************
@@ -1909,13 +3916,13 @@ int Abc_CommandLogic( Abc_Frame_t * pAbc, int argc, char ** argv )
Abc_Ntk_t * pNtk, * pNtkRes;
int c;
- pNtk = Abc_FrameReadNet(pAbc);
+ pNtk = Abc_FrameReadNtk(pAbc);
pOut = Abc_FrameReadOut(pAbc);
pErr = Abc_FrameReadErr(pAbc);
// set defaults
- util_getopt_reset();
- while ( ( c = util_getopt( argc, argv, "h" ) ) != EOF )
+ Extra_UtilGetoptReset();
+ while ( ( c = Extra_UtilGetopt( argc, argv, "h" ) ) != EOF )
{
switch ( c )
{
@@ -1932,14 +3939,14 @@ int Abc_CommandLogic( Abc_Frame_t * pAbc, int argc, char ** argv )
return 1;
}
- if ( !Abc_NtkIsNetlist( pNtk ) )
+ if ( !Abc_NtkIsStrash( pNtk ) )
{
- fprintf( pErr, "This command is only applicable to netlists.\n" );
+ fprintf( pErr, "This command is only applicable to strashed networks.\n" );
return 1;
}
// get the new network
- pNtkRes = Abc_NtkNetlistToLogic( pNtk );
+ pNtkRes = Abc_NtkToLogic( pNtk );
if ( pNtkRes == NULL )
{
fprintf( pErr, "Converting to a logic network has failed.\n" );
@@ -1951,7 +3958,66 @@ int Abc_CommandLogic( Abc_Frame_t * pAbc, int argc, char ** argv )
usage:
fprintf( pErr, "usage: logic [-h]\n" );
- fprintf( pErr, "\t transforms a netlist into a logic network\n" );
+ fprintf( pErr, "\t transforms an AIG into a logic network with SOPs\n" );
+ fprintf( pErr, "\t-h : print the command usage\n");
+ return 1;
+}
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Abc_CommandComb( Abc_Frame_t * pAbc, int argc, char ** argv )
+{
+ FILE * pOut, * pErr;
+ Abc_Ntk_t * pNtk, * pNtkRes;
+ int c;
+
+ pNtk = Abc_FrameReadNtk(pAbc);
+ pOut = Abc_FrameReadOut(pAbc);
+ pErr = Abc_FrameReadErr(pAbc);
+
+ // set defaults
+ Extra_UtilGetoptReset();
+ while ( ( c = Extra_UtilGetopt( argc, argv, "h" ) ) != EOF )
+ {
+ switch ( c )
+ {
+ case 'h':
+ goto usage;
+ default:
+ goto usage;
+ }
+ }
+
+ if ( pNtk == NULL )
+ {
+ fprintf( pErr, "Empty network.\n" );
+ return 1;
+ }
+ if ( Abc_NtkIsComb(pNtk) )
+ {
+ fprintf( pErr, "The network is already combinational.\n" );
+ return 0;
+ }
+
+ // get the new network
+ pNtkRes = Abc_NtkDup( pNtk );
+ Abc_NtkMakeComb( pNtkRes );
+ // replace the current network
+ Abc_FrameReplaceCurrentNetwork( pAbc, pNtkRes );
+ return 0;
+
+usage:
+ fprintf( pErr, "usage: comb [-h]\n" );
+ fprintf( pErr, "\t makes the current network combinational by replacing latches by PI/PO pairs\n" );
fprintf( pErr, "\t-h : print the command usage\n");
return 1;
}
@@ -1969,6 +4035,7 @@ usage:
***********************************************************************/
int Abc_CommandMiter( Abc_Frame_t * pAbc, int argc, char ** argv )
{
+ char Buffer[32];
FILE * pOut, * pErr;
Abc_Ntk_t * pNtk, * pNtk1, * pNtk2, * pNtkRes;
int fDelete1, fDelete2;
@@ -1977,19 +4044,32 @@ int Abc_CommandMiter( Abc_Frame_t * pAbc, int argc, char ** argv )
int c;
int fCheck;
int fComb;
+ int nPartSize;
- pNtk = Abc_FrameReadNet(pAbc);
+ pNtk = Abc_FrameReadNtk(pAbc);
pOut = Abc_FrameReadOut(pAbc);
pErr = Abc_FrameReadErr(pAbc);
// set defaults
fComb = 1;
fCheck = 1;
- util_getopt_reset();
- while ( ( c = util_getopt( argc, argv, "ch" ) ) != EOF )
+ nPartSize = 0;
+ Extra_UtilGetoptReset();
+ while ( ( c = Extra_UtilGetopt( argc, argv, "Pch" ) ) != EOF )
{
switch ( c )
{
+ case 'P':
+ if ( globalUtilOptind >= argc )
+ {
+ fprintf( pErr, "Command line switch \"-P\" should be followed by an integer.\n" );
+ goto usage;
+ }
+ nPartSize = atoi(argv[globalUtilOptind]);
+ globalUtilOptind++;
+ if ( nPartSize < 0 )
+ goto usage;
+ break;
case 'c':
fComb ^= 1;
break;
@@ -1998,13 +4078,13 @@ int Abc_CommandMiter( Abc_Frame_t * pAbc, int argc, char ** argv )
}
}
- pArgvNew = argv + util_optind;
- nArgcNew = argc - util_optind;
+ pArgvNew = argv + globalUtilOptind;
+ nArgcNew = argc - globalUtilOptind;
if ( !Abc_NtkPrepareTwoNtks( pErr, pNtk, pArgvNew, nArgcNew, &pNtk1, &pNtk2, &fDelete1, &fDelete2 ) )
return 1;
// compute the miter
- pNtkRes = Abc_NtkMiter( pNtk1, pNtk2, fComb );
+ pNtkRes = Abc_NtkMiter( pNtk1, pNtk2, fComb, nPartSize );
if ( fDelete1 ) Abc_NtkDelete( pNtk1 );
if ( fDelete2 ) Abc_NtkDelete( pNtk2 );
@@ -2019,14 +4099,325 @@ int Abc_CommandMiter( Abc_Frame_t * pAbc, int argc, char ** argv )
return 0;
usage:
- fprintf( pErr, "usage: miter [-ch] <file1> <file2>\n" );
- fprintf( pErr, "\t computes the miter of the two circuits\n" );
- fprintf( pErr, "\t-c : computes combinational miter (latches as POs) [default = %s]\n", fComb? "yes": "no" );
+ if ( nPartSize == 0 )
+ strcpy( Buffer, "unused" );
+ else
+ sprintf( Buffer, "%d", nPartSize );
+ fprintf( pErr, "usage: miter [-P num] [-ch] <file1> <file2>\n" );
+ fprintf( pErr, "\t computes the miter of the two circuits\n" );
+ fprintf( pErr, "\t-P num : output partition size [default = %s]\n", Buffer );
+ fprintf( pErr, "\t-c : computes combinational miter (latches as POs) [default = %s]\n", fComb? "yes": "no" );
+ fprintf( pErr, "\t-h : print the command usage\n");
+ fprintf( pErr, "\tfile1 : (optional) the file with the first network\n");
+ fprintf( pErr, "\tfile2 : (optional) the file with the second network\n");
+ fprintf( pErr, "\t if no files are given, uses the current network and its spec\n");
+ fprintf( pErr, "\t if one file is given, uses the current network and the file\n");
+ return 1;
+}
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Abc_CommandDemiter( Abc_Frame_t * pAbc, int argc, char ** argv )
+{
+ FILE * pOut, * pErr;
+ Abc_Ntk_t * pNtk;//, * pNtkRes;
+ int fComb;
+ int c;
+ extern int Abc_NtkDemiter( Abc_Ntk_t * pNtk );
+
+ pNtk = Abc_FrameReadNtk(pAbc);
+ pOut = Abc_FrameReadOut(pAbc);
+ pErr = Abc_FrameReadErr(pAbc);
+
+ // set defaults
+ Extra_UtilGetoptReset();
+ while ( ( c = Extra_UtilGetopt( argc, argv, "ch" ) ) != EOF )
+ {
+ switch ( c )
+ {
+ case 'c':
+ fComb ^= 1;
+ break;
+ default:
+ goto usage;
+ }
+ }
+
+ if ( !Abc_NtkIsStrash(pNtk) )
+ {
+ fprintf( pErr, "The network is not strashed.\n" );
+ return 1;
+ }
+
+ if ( Abc_NtkPoNum(pNtk) != 1 )
+ {
+ fprintf( pErr, "The network is not a miter.\n" );
+ return 1;
+ }
+
+ if ( !Abc_NodeIsExorType(Abc_ObjFanin0(Abc_NtkPo(pNtk,0))) )
+ {
+ fprintf( pErr, "The miter's PO is not an EXOR.\n" );
+ return 1;
+ }
+
+ // get the new network
+ if ( !Abc_NtkDemiter( pNtk ) )
+ {
+ fprintf( pErr, "Demitering has failed.\n" );
+ return 1;
+ }
+ // replace the current network
+// Abc_FrameReplaceCurrentNetwork( pAbc, pNtkRes );
+ return 0;
+
+usage:
+ fprintf( pErr, "usage: demiter [-h]\n" );
+ fprintf( pErr, "\t removes topmost EXOR from the miter to create two POs\n" );
+// fprintf( pErr, "\t-c : computes combinational miter (latches as POs) [default = %s]\n", fComb? "yes": "no" );
fprintf( pErr, "\t-h : print the command usage\n");
- fprintf( pErr, "\tfile1 : (optional) the file with the first network\n");
- fprintf( pErr, "\tfile2 : (optional) the file with the second network\n");
- fprintf( pErr, "\t if no files are given, uses the current network and its spec\n");
- fprintf( pErr, "\t if one file is given, uses the current network and the file\n");
+ return 1;
+}
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Abc_CommandOrPos( Abc_Frame_t * pAbc, int argc, char ** argv )
+{
+ FILE * pOut, * pErr;
+ Abc_Ntk_t * pNtk;//, * pNtkRes;
+ int fComb;
+ int c;
+ extern int Abc_NtkCombinePos( Abc_Ntk_t * pNtk, int fAnd );
+
+ pNtk = Abc_FrameReadNtk(pAbc);
+ pOut = Abc_FrameReadOut(pAbc);
+ pErr = Abc_FrameReadErr(pAbc);
+
+ // set defaults
+ Extra_UtilGetoptReset();
+ while ( ( c = Extra_UtilGetopt( argc, argv, "ch" ) ) != EOF )
+ {
+ switch ( c )
+ {
+ case 'c':
+ fComb ^= 1;
+ break;
+ default:
+ goto usage;
+ }
+ }
+
+ if ( !Abc_NtkIsStrash(pNtk) )
+ {
+ fprintf( pErr, "The network is not strashed.\n" );
+ return 1;
+ }
+/*
+ if ( Abc_NtkPoNum(pNtk) == 1 )
+ {
+ fprintf( pErr, "The network already has one PO.\n" );
+ return 1;
+ }
+*/
+/*
+ if ( Abc_NtkLatchNum(pNtk) )
+ {
+ fprintf( pErr, "The miter has latches. ORing is not performed.\n" );
+ return 1;
+ }
+*/
+ // get the new network
+ if ( !Abc_NtkCombinePos( pNtk, 0 ) )
+ {
+ fprintf( pErr, "ORing the POs has failed.\n" );
+ return 1;
+ }
+ // replace the current network
+// Abc_FrameReplaceCurrentNetwork( pAbc, pNtkRes );
+ return 0;
+
+usage:
+ fprintf( pErr, "usage: orpos [-h]\n" );
+ fprintf( pErr, "\t creates single-output miter by ORing the POs of the current network\n" );
+// fprintf( pErr, "\t-c : computes combinational miter (latches as POs) [default = %s]\n", fComb? "yes": "no" );
+ fprintf( pErr, "\t-h : print the command usage\n");
+ return 1;
+}
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Abc_CommandAndPos( Abc_Frame_t * pAbc, int argc, char ** argv )
+{
+ FILE * pOut, * pErr;
+ Abc_Ntk_t * pNtk;//, * pNtkRes;
+ int fComb;
+ int c;
+ extern int Abc_NtkCombinePos( Abc_Ntk_t * pNtk, int fAnd );
+
+ pNtk = Abc_FrameReadNtk(pAbc);
+ pOut = Abc_FrameReadOut(pAbc);
+ pErr = Abc_FrameReadErr(pAbc);
+
+ // set defaults
+ Extra_UtilGetoptReset();
+ while ( ( c = Extra_UtilGetopt( argc, argv, "ch" ) ) != EOF )
+ {
+ switch ( c )
+ {
+ case 'c':
+ fComb ^= 1;
+ break;
+ default:
+ goto usage;
+ }
+ }
+
+ if ( !Abc_NtkIsStrash(pNtk) )
+ {
+ fprintf( pErr, "The network is not strashed.\n" );
+ return 1;
+ }
+
+ if ( Abc_NtkPoNum(pNtk) == 1 )
+ {
+ fprintf( pErr, "The network already has one PO.\n" );
+ return 1;
+ }
+
+ if ( Abc_NtkLatchNum(pNtk) )
+ {
+ fprintf( pErr, "The miter has latches. ORing is not performed.\n" );
+ return 1;
+ }
+
+ // get the new network
+ if ( !Abc_NtkCombinePos( pNtk, 1 ) )
+ {
+ fprintf( pErr, "ANDing the POs has failed.\n" );
+ return 1;
+ }
+ // replace the current network
+// Abc_FrameReplaceCurrentNetwork( pAbc, pNtkRes );
+ return 0;
+
+usage:
+ fprintf( pErr, "usage: andpos [-h]\n" );
+ fprintf( pErr, "\t creates single-output miter by ANDing the POs of the current network\n" );
+// fprintf( pErr, "\t-c : computes combinational miter (latches as POs) [default = %s]\n", fComb? "yes": "no" );
+ fprintf( pErr, "\t-h : print the command usage\n");
+ return 1;
+}
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Abc_CommandAppend( Abc_Frame_t * pAbc, int argc, char ** argv )
+{
+ FILE * pOut, * pErr;
+ Abc_Ntk_t * pNtk, * pNtk2;
+ char * FileName;
+ int fComb;
+ int c;
+
+ pNtk = Abc_FrameReadNtk(pAbc);
+ pOut = Abc_FrameReadOut(pAbc);
+ pErr = Abc_FrameReadErr(pAbc);
+
+ // set defaults
+ Extra_UtilGetoptReset();
+ while ( ( c = Extra_UtilGetopt( argc, argv, "ch" ) ) != EOF )
+ {
+ switch ( c )
+ {
+ case 'c':
+ fComb ^= 1;
+ break;
+ default:
+ goto usage;
+ }
+ }
+
+ // get the second network
+ if ( argc != globalUtilOptind + 1 )
+ {
+ fprintf( pErr, "The network to append is not given.\n" );
+ return 1;
+ }
+
+ if ( !Abc_NtkIsStrash(pNtk) )
+ {
+ fprintf( pErr, "The base network should be strashed for the appending to work.\n" );
+ return 1;
+ }
+
+ // read the second network
+ FileName = argv[globalUtilOptind];
+ pNtk2 = Io_Read( FileName, Io_ReadFileType(FileName), 1 );
+ if ( pNtk2 == NULL )
+ return 1;
+
+ // check if the second network is combinational
+ if ( Abc_NtkLatchNum(pNtk2) )
+ {
+ fprintf( pErr, "The second network has latches. Appending does not work for such networks.\n" );
+ return 1;
+ }
+
+ // get the new network
+ if ( !Abc_NtkAppend( pNtk, pNtk2, 1 ) )
+ {
+ Abc_NtkDelete( pNtk2 );
+ fprintf( pErr, "Appending the networks failed.\n" );
+ return 1;
+ }
+ Abc_NtkDelete( pNtk2 );
+ // sweep dangling logic
+ Abc_AigCleanup( pNtk->pManFunc );
+ // replace the current network
+// Abc_FrameReplaceCurrentNetwork( pAbc, pNtkRes );
+ return 0;
+
+usage:
+ fprintf( pErr, "usage: append [-h] <file>\n" );
+ fprintf( pErr, "\t appends a combinational network on top of the current network\n" );
+// fprintf( pErr, "\t-c : computes combinational miter (latches as POs) [default = %s]\n", fComb? "yes": "no" );
+ fprintf( pErr, "\t-h : print the command usage\n");
+ fprintf( pErr, "\t<file> : file name with the second network\n");
return 1;
}
@@ -2049,27 +4440,27 @@ int Abc_CommandFrames( Abc_Frame_t * pAbc, int argc, char ** argv )
int nFrames;
int c;
- pNtk = Abc_FrameReadNet(pAbc);
+ pNtk = Abc_FrameReadNtk(pAbc);
pOut = Abc_FrameReadOut(pAbc);
pErr = Abc_FrameReadErr(pAbc);
// set defaults
fInitial = 0;
nFrames = 5;
- util_getopt_reset();
- while ( ( c = util_getopt( argc, argv, "Fih" ) ) != EOF )
+ Extra_UtilGetoptReset();
+ while ( ( c = Extra_UtilGetopt( argc, argv, "Fih" ) ) != EOF )
{
switch ( c )
{
case 'F':
- if ( util_optind >= argc )
+ if ( globalUtilOptind >= argc )
{
fprintf( pErr, "Command line switch \"-F\" should be followed by an integer.\n" );
goto usage;
}
- nFrames = atoi(argv[util_optind]);
- util_optind++;
- if ( nFrames < 0 )
+ nFrames = atoi(argv[globalUtilOptind]);
+ globalUtilOptind++;
+ if ( nFrames <= 0 )
goto usage;
break;
case 'i':
@@ -2091,7 +4482,7 @@ int Abc_CommandFrames( Abc_Frame_t * pAbc, int argc, char ** argv )
// get the new network
if ( !Abc_NtkIsStrash(pNtk) )
{
- pNtkTemp = Abc_NtkStrash( pNtk, 0, 0 );
+ pNtkTemp = Abc_NtkStrash( pNtk, 0, 0, 0 );
pNtkRes = Abc_NtkFrames( pNtkTemp, nFrames, fInitial );
Abc_NtkDelete( pNtkTemp );
}
@@ -2131,38 +4522,40 @@ int Abc_CommandSop( Abc_Frame_t * pAbc, int argc, char ** argv )
{
FILE * pOut, * pErr;
Abc_Ntk_t * pNtk;
+ int fDirect;
int c;
- pNtk = Abc_FrameReadNet(pAbc);
+ pNtk = Abc_FrameReadNtk(pAbc);
pOut = Abc_FrameReadOut(pAbc);
pErr = Abc_FrameReadErr(pAbc);
// set defaults
- util_getopt_reset();
- while ( ( c = util_getopt( argc, argv, "h" ) ) != EOF )
+ fDirect = 0;
+ Extra_UtilGetoptReset();
+ while ( ( c = Extra_UtilGetopt( argc, argv, "dh" ) ) != EOF )
{
switch ( c )
{
+ case 'd':
+ fDirect ^= 1;
+ break;
case 'h':
goto usage;
default:
goto usage;
}
}
-
if ( pNtk == NULL )
{
fprintf( pErr, "Empty network.\n" );
return 1;
}
-
- // get the new network
- if ( !Abc_NtkIsBddLogic(pNtk) )
+ if ( !Abc_NtkIsLogic(pNtk) )
{
- fprintf( pErr, "Converting to SOP is possible when node functions are BDDs.\n" );
+ fprintf( pErr, "Converting to SOP is possible only for logic networks.\n" );
return 1;
}
- if ( !Abc_NtkBddToSop( pNtk ) )
+ if ( !Abc_NtkToSop(pNtk, fDirect) )
{
fprintf( pErr, "Converting to SOP has failed.\n" );
return 1;
@@ -2170,8 +4563,9 @@ int Abc_CommandSop( Abc_Frame_t * pAbc, int argc, char ** argv )
return 0;
usage:
- fprintf( pErr, "usage: sop [-h]\n" );
- fprintf( pErr, "\t converts node functions from BDD to SOP\n" );
+ fprintf( pErr, "usage: sop [-dh]\n" );
+ fprintf( pErr, "\t converts node functions to SOP\n" );
+ fprintf( pErr, "\t-d : toggles using both phases or only positive [default = %s]\n", fDirect? "direct": "both" );
fprintf( pErr, "\t-h : print the command usage\n");
return 1;
}
@@ -2193,13 +4587,13 @@ int Abc_CommandBdd( Abc_Frame_t * pAbc, int argc, char ** argv )
Abc_Ntk_t * pNtk;
int c;
- pNtk = Abc_FrameReadNet(pAbc);
+ pNtk = Abc_FrameReadNtk(pAbc);
pOut = Abc_FrameReadOut(pAbc);
pErr = Abc_FrameReadErr(pAbc);
// set defaults
- util_getopt_reset();
- while ( ( c = util_getopt( argc, argv, "h" ) ) != EOF )
+ Extra_UtilGetoptReset();
+ while ( ( c = Extra_UtilGetopt( argc, argv, "h" ) ) != EOF )
{
switch ( c )
{
@@ -2209,20 +4603,22 @@ int Abc_CommandBdd( Abc_Frame_t * pAbc, int argc, char ** argv )
goto usage;
}
}
-
if ( pNtk == NULL )
{
fprintf( pErr, "Empty network.\n" );
return 1;
}
-
- // get the new network
- if ( !Abc_NtkIsSopLogic(pNtk) )
+ if ( !Abc_NtkIsLogic(pNtk) )
{
- fprintf( pErr, "Converting to BDD is possible when node functions are SOPs.\n" );
+ fprintf( pErr, "Converting to BDD is possible only for logic networks.\n" );
return 1;
}
- if ( !Abc_NtkSopToBdd( pNtk ) )
+ if ( Abc_NtkIsBddLogic(pNtk) )
+ {
+ fprintf( pOut, "The logic network is already in the BDD form.\n" );
+ return 0;
+ }
+ if ( !Abc_NtkToBdd(pNtk) )
{
fprintf( pErr, "Converting to BDD has failed.\n" );
return 1;
@@ -2231,7 +4627,7 @@ int Abc_CommandBdd( Abc_Frame_t * pAbc, int argc, char ** argv )
usage:
fprintf( pErr, "usage: bdd [-h]\n" );
- fprintf( pErr, "\t converts node functions from SOP to BDD\n" );
+ fprintf( pErr, "\t converts node functions to BDD\n" );
fprintf( pErr, "\t-h : print the command usage\n");
return 1;
}
@@ -2247,19 +4643,19 @@ usage:
SeeAlso []
***********************************************************************/
-int Abc_CommandMuxes( Abc_Frame_t * pAbc, int argc, char ** argv )
+int Abc_CommandAig( Abc_Frame_t * pAbc, int argc, char ** argv )
{
FILE * pOut, * pErr;
- Abc_Ntk_t * pNtk, * pNtkRes;
+ Abc_Ntk_t * pNtk;
int c;
- pNtk = Abc_FrameReadNet(pAbc);
+ pNtk = Abc_FrameReadNtk(pAbc);
pOut = Abc_FrameReadOut(pAbc);
pErr = Abc_FrameReadErr(pAbc);
// set defaults
- util_getopt_reset();
- while ( ( c = util_getopt( argc, argv, "h" ) ) != EOF )
+ Extra_UtilGetoptReset();
+ while ( ( c = Extra_UtilGetopt( argc, argv, "h" ) ) != EOF )
{
switch ( c )
{
@@ -2269,35 +4665,32 @@ int Abc_CommandMuxes( Abc_Frame_t * pAbc, int argc, char ** argv )
goto usage;
}
}
-
if ( pNtk == NULL )
{
fprintf( pErr, "Empty network.\n" );
return 1;
}
-
- if ( !Abc_NtkIsBddLogic(pNtk) )
+ if ( !Abc_NtkIsLogic(pNtk) )
{
- fprintf( pErr, "Only a BDD logic network can be converted to MUXes.\n" );
+ fprintf( pErr, "Converting to AIG is possible only for logic networks.\n" );
return 1;
}
-
- // get the new network
- pNtkRes = Abc_NtkBddToMuxes( pNtk );
- if ( pNtkRes == NULL )
+ if ( Abc_NtkIsAigLogic(pNtk) )
{
- fprintf( pErr, "Converting to MUXes has failed.\n" );
+ fprintf( pOut, "The logic network is already in the AIG form.\n" );
+ return 0;
+ }
+ if ( !Abc_NtkToAig(pNtk) )
+ {
+ fprintf( pErr, "Converting to AIG has failed.\n" );
return 1;
}
- // replace the current network
- Abc_FrameReplaceCurrentNetwork( pAbc, pNtkRes );
return 0;
usage:
- fprintf( pErr, "usage: muxes [-h]\n" );
- fprintf( pErr, "\t converts the current network by a network derived by\n" );
- fprintf( pErr, "\t replacing all nodes by DAGs isomorphic to the local BDDs\n" );
- fprintf( pErr, "\t-h : print the command usage\n");
+ fprintf( pErr, "usage: aig [-h]\n" );
+ fprintf( pErr, "\t converts node functions to AIG\n" );
+ fprintf( pErr, "\t-h : print the command usage\n");
return 1;
}
@@ -2312,21 +4705,22 @@ usage:
SeeAlso []
***********************************************************************/
-int Abc_CommandSat( Abc_Frame_t * pAbc, int argc, char ** argv )
+int Abc_CommandReorder( Abc_Frame_t * pAbc, int argc, char ** argv )
{
FILE * pOut, * pErr;
Abc_Ntk_t * pNtk;
int c;
int fVerbose;
+ extern void Abc_NtkBddReorder( Abc_Ntk_t * pNtk, int fVerbose );
- pNtk = Abc_FrameReadNet(pAbc);
+ pNtk = Abc_FrameReadNtk(pAbc);
pOut = Abc_FrameReadOut(pAbc);
pErr = Abc_FrameReadErr(pAbc);
// set defaults
fVerbose = 0;
- util_getopt_reset();
- while ( ( c = util_getopt( argc, argv, "vh" ) ) != EOF )
+ Extra_UtilGetoptReset();
+ while ( ( c = Extra_UtilGetopt( argc, argv, "vh" ) ) != EOF )
{
switch ( c )
{
@@ -2345,32 +4739,173 @@ int Abc_CommandSat( Abc_Frame_t * pAbc, int argc, char ** argv )
fprintf( pErr, "Empty network.\n" );
return 1;
}
- if ( Abc_NtkLatchNum(pNtk) > 0 )
+
+ // get the new network
+ if ( !Abc_NtkIsBddLogic(pNtk) )
{
- fprintf( stdout, "Currently can only solve the miter for combinational circuits.\n" );
- return 0;
+ fprintf( pErr, "Variable reordering is possible when node functions are BDDs (run \"bdd\").\n" );
+ return 1;
}
- if ( !Abc_NtkIsLogic(pNtk) )
+ Abc_NtkBddReorder( pNtk, fVerbose );
+ return 0;
+
+usage:
+ fprintf( pErr, "usage: reorder [-vh]\n" );
+ fprintf( pErr, "\t reorders local functions of the nodes using sifting\n" );
+ fprintf( pErr, "\t-v : prints verbose information [default = %s]\n", fVerbose? "yes": "no" );
+ fprintf( pErr, "\t-h : print the command usage\n");
+ return 1;
+}
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Abc_CommandOrder( Abc_Frame_t * pAbc, int argc, char ** argv )
+{
+ FILE * pOut, * pErr, * pFile;
+ Abc_Ntk_t * pNtk;
+ char * pFileName;
+ int c;
+ int fReverse;
+ int fVerbose;
+ extern void Abc_NtkImplementCiOrder( Abc_Ntk_t * pNtk, char * pFileName, int fReverse, int fVerbose );
+ extern void Abc_NtkFindCiOrder( Abc_Ntk_t * pNtk, int fReverse, int fVerbose );
+
+ pNtk = Abc_FrameReadNtk(pAbc);
+ pOut = Abc_FrameReadOut(pAbc);
+ pErr = Abc_FrameReadErr(pAbc);
+
+ // set defaults
+ fReverse = 0;
+ fVerbose = 0;
+ Extra_UtilGetoptReset();
+ while ( ( c = Extra_UtilGetopt( argc, argv, "rvh" ) ) != EOF )
{
- fprintf( stdout, "This command can only be applied to logic network (run \"renode -c\").\n" );
- return 0;
+ switch ( c )
+ {
+ case 'r':
+ fReverse ^= 1;
+ break;
+ case 'v':
+ fVerbose ^= 1;
+ break;
+ case 'h':
+ goto usage;
+ default:
+ goto usage;
+ }
}
- if ( Abc_NtkIsMappedLogic(pNtk) )
- Abc_NtkUnmap(pNtk);
- if ( Abc_NtkIsSopLogic(pNtk) )
- Abc_NtkSopToBdd(pNtk);
- if ( Abc_NtkMiterSat( pNtk, fVerbose ) )
- printf( "The miter is satisfiable.\n" );
+ if ( pNtk == NULL )
+ {
+ fprintf( pErr, "Empty network.\n" );
+ return 1;
+ }
+// if ( Abc_NtkLatchNum(pNtk) > 0 )
+// {
+// printf( "Currently this procedure does not work for sequential networks.\n" );
+// return 1;
+// }
+
+ // if the var order file is given, implement this order
+ pFileName = NULL;
+ if ( argc == globalUtilOptind + 1 )
+ {
+ pFileName = argv[globalUtilOptind];
+ pFile = fopen( pFileName, "r" );
+ if ( pFile == NULL )
+ {
+ fprintf( pErr, "Cannot open file \"%s\" with the BDD variable order.\n", pFileName );
+ return 1;
+ }
+ fclose( pFile );
+ }
+ if ( pFileName )
+ Abc_NtkImplementCiOrder( pNtk, pFileName, fReverse, fVerbose );
else
- printf( "The miter is unsatisfiable.\n" );
+ Abc_NtkFindCiOrder( pNtk, fReverse, fVerbose );
return 0;
usage:
- fprintf( pErr, "usage: sat [-vh]\n" );
- fprintf( pErr, "\t solves the miter\n" );
+ fprintf( pErr, "usage: order [-rvh] <file>\n" );
+ fprintf( pErr, "\t computes a good static CI variable order\n" );
+ fprintf( pErr, "\t-r : toggle reverse ordering [default = %s]\n", fReverse? "yes": "no" );
fprintf( pErr, "\t-v : prints verbose information [default = %s]\n", fVerbose? "yes": "no" );
fprintf( pErr, "\t-h : print the command usage\n");
+ fprintf( pErr, "\t<file> : (optional) file with the given variable order\n" );
+ return 1;
+}
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Abc_CommandMuxes( Abc_Frame_t * pAbc, int argc, char ** argv )
+{
+ FILE * pOut, * pErr;
+ Abc_Ntk_t * pNtk, * pNtkRes;
+ int c;
+
+ pNtk = Abc_FrameReadNtk(pAbc);
+ pOut = Abc_FrameReadOut(pAbc);
+ pErr = Abc_FrameReadErr(pAbc);
+
+ // set defaults
+ Extra_UtilGetoptReset();
+ while ( ( c = Extra_UtilGetopt( argc, argv, "h" ) ) != EOF )
+ {
+ switch ( c )
+ {
+ case 'h':
+ goto usage;
+ default:
+ goto usage;
+ }
+ }
+
+ if ( pNtk == NULL )
+ {
+ fprintf( pErr, "Empty network.\n" );
+ return 1;
+ }
+
+ if ( !Abc_NtkIsBddLogic(pNtk) )
+ {
+ fprintf( pErr, "Only a BDD logic network can be converted to MUXes.\n" );
+ return 1;
+ }
+
+ // get the new network
+ pNtkRes = Abc_NtkBddToMuxes( pNtk );
+ if ( pNtkRes == NULL )
+ {
+ fprintf( pErr, "Converting to MUXes has failed.\n" );
+ return 1;
+ }
+ // replace the current network
+ Abc_FrameReplaceCurrentNetwork( pAbc, pNtkRes );
+ return 0;
+
+usage:
+ fprintf( pErr, "usage: muxes [-h]\n" );
+ fprintf( pErr, "\t converts the current network by a network derived by\n" );
+ fprintf( pErr, "\t replacing all nodes by DAGs isomorphic to the local BDDs\n" );
+ fprintf( pErr, "\t-h : print the command usage\n");
return 1;
}
@@ -2394,14 +4929,14 @@ int Abc_CommandExtSeqDcs( Abc_Frame_t * pAbc, int argc, char ** argv )
int fVerbose;
extern int Abc_NtkExtractSequentialDcs( Abc_Ntk_t * pNet, bool fVerbose );
- pNtk = Abc_FrameReadNet(pAbc);
+ pNtk = Abc_FrameReadNtk(pAbc);
pOut = Abc_FrameReadOut(pAbc);
pErr = Abc_FrameReadErr(pAbc);
// set defaults
fVerbose = 0;
- util_getopt_reset();
- while ( ( c = util_getopt( argc, argv, "vh" ) ) != EOF )
+ Extra_UtilGetoptReset();
+ while ( ( c = Extra_UtilGetopt( argc, argv, "vh" ) ) != EOF )
{
switch ( c )
{
@@ -2427,7 +4962,7 @@ int Abc_CommandExtSeqDcs( Abc_Frame_t * pAbc, int argc, char ** argv )
}
if ( !Abc_NtkIsStrash(pNtk) )
{
- fprintf( stdout, "This command works only for AIGs (run \"strash\").\n" );
+ fprintf( stdout, "Extracting sequential don't-cares works only for AIGs (run \"strash\").\n" );
return 0;
}
if ( !Abc_NtkExtractSequentialDcs( pNtk, fVerbose ) )
@@ -2456,38 +4991,42 @@ usage:
SeeAlso []
***********************************************************************/
-int Abc_CommandOneOutput( Abc_Frame_t * pAbc, int argc, char ** argv )
+int Abc_CommandCone( Abc_Frame_t * pAbc, int argc, char ** argv )
{
FILE * pOut, * pErr;
Abc_Ntk_t * pNtk, * pNtkRes;
- Abc_Obj_t * pNode;
+ Abc_Obj_t * pNode, * pNodeCo;
int c;
int fUseAllCis;
+ int fUseMffc;
int Output;
- pNtk = Abc_FrameReadNet(pAbc);
+ pNtk = Abc_FrameReadNtk(pAbc);
pOut = Abc_FrameReadOut(pAbc);
pErr = Abc_FrameReadErr(pAbc);
// set defaults
fUseAllCis = 0;
+ fUseMffc = 0;
Output = -1;
- util_getopt_reset();
- while ( ( c = util_getopt( argc, argv, "Oah" ) ) != EOF )
+ Extra_UtilGetoptReset();
+ while ( ( c = Extra_UtilGetopt( argc, argv, "Omah" ) ) != EOF )
{
switch ( c )
{
case 'O':
- if ( util_optind >= argc )
+ if ( globalUtilOptind >= argc )
{
fprintf( pErr, "Command line switch \"-O\" should be followed by an integer.\n" );
goto usage;
}
- Output = atoi(argv[util_optind]);
- util_optind++;
+ Output = atoi(argv[globalUtilOptind]);
+ globalUtilOptind++;
if ( Output < 0 )
goto usage;
break;
+ case 'm':
+ fUseMffc ^= 1;
case 'a':
fUseAllCis ^= 1;
break;
@@ -2510,27 +5049,31 @@ int Abc_CommandOneOutput( Abc_Frame_t * pAbc, int argc, char ** argv )
return 1;
}
- if ( argc > util_optind + 1 )
+ if ( argc > globalUtilOptind + 1 )
{
fprintf( pErr, "Wrong number of auguments.\n" );
goto usage;
}
- if ( argc == util_optind + 1 )
+ pNodeCo = NULL;
+ if ( argc == globalUtilOptind + 1 )
{
- pNode = Abc_NtkFindCo( pNtk, argv[util_optind] );
+ pNode = Abc_NtkFindNode( pNtk, argv[globalUtilOptind] );
if ( pNode == NULL )
{
- fprintf( pErr, "Cannot find CO node \"%s\".\n", argv[util_optind] );
+ fprintf( pErr, "Cannot find node \"%s\".\n", argv[globalUtilOptind] );
return 1;
}
- pNtkRes = Abc_NtkSplitOutput( pNtk, pNode, fUseAllCis );
+ if ( fUseMffc )
+ pNtkRes = Abc_NtkCreateMffc( pNtk, pNode, argv[globalUtilOptind] );
+ else
+ pNtkRes = Abc_NtkCreateCone( pNtk, pNode, argv[globalUtilOptind], fUseAllCis );
}
else
{
if ( Output == -1 )
{
- fprintf( pErr, "The output is not specified.\n" );
+ fprintf( pErr, "The node is not specified.\n" );
return 1;
}
if ( Output >= Abc_NtkCoNum(pNtk) )
@@ -2538,11 +5081,17 @@ int Abc_CommandOneOutput( Abc_Frame_t * pAbc, int argc, char ** argv )
fprintf( pErr, "The 0-based output number (%d) is larger than the number of outputs (%d).\n", Output, Abc_NtkCoNum(pNtk) );
return 1;
}
- pNtkRes = Abc_NtkSplitOutput( pNtk, Abc_NtkCo(pNtk,Output), fUseAllCis );
+ pNodeCo = Abc_NtkCo( pNtk, Output );
+ if ( fUseMffc )
+ pNtkRes = Abc_NtkCreateMffc( pNtk, Abc_ObjFanin0(pNodeCo), Abc_ObjName(pNodeCo) );
+ else
+ pNtkRes = Abc_NtkCreateCone( pNtk, Abc_ObjFanin0(pNodeCo), Abc_ObjName(pNodeCo), fUseAllCis );
}
+ if ( pNodeCo && Abc_ObjFaninC0(pNodeCo) )
+ printf( "The extracted cone represents the complement function of the CO.\n" );
if ( pNtkRes == NULL )
{
- fprintf( pErr, "Splitting one output has failed.\n" );
+ fprintf( pErr, "Writing the logic cone of one node has failed.\n" );
return 1;
}
// replace the current network
@@ -2550,12 +5099,13 @@ int Abc_CommandOneOutput( Abc_Frame_t * pAbc, int argc, char ** argv )
return 0;
usage:
- fprintf( pErr, "usage: one_output [-O num] [-ah] <name>\n" );
- fprintf( pErr, "\t replaces the current network by the logic cone of one output\n" );
+ fprintf( pErr, "usage: cone [-O num] [-amh] <name>\n" );
+ fprintf( pErr, "\t replaces the current network by one logic cone\n" );
fprintf( pErr, "\t-a : toggle writing all CIs or structral support only [default = %s]\n", fUseAllCis? "all": "structural" );
+ fprintf( pErr, "\t-m : toggle writing only MFFC or complete TFI cone [default = %s]\n", fUseMffc? "MFFC": "TFI cone" );
fprintf( pErr, "\t-h : print the command usage\n");
- fprintf( pErr, "\t-O num : (optional) the 0-based number of the output\n");
- fprintf( pErr, "\tname : (optional) the name of the output\n");
+ fprintf( pErr, "\t-O num : (optional) the 0-based number of the CO to extract\n");
+ fprintf( pErr, "\tname : (optional) the name of the node to extract\n");
return 1;
}
@@ -2570,20 +5120,20 @@ usage:
SeeAlso []
***********************************************************************/
-int Abc_CommandOneNode( Abc_Frame_t * pAbc, int argc, char ** argv )
+int Abc_CommandNode( Abc_Frame_t * pAbc, int argc, char ** argv )
{
FILE * pOut, * pErr;
Abc_Ntk_t * pNtk, * pNtkRes;
Abc_Obj_t * pNode;
int c;
- pNtk = Abc_FrameReadNet(pAbc);
+ pNtk = Abc_FrameReadNtk(pAbc);
pOut = Abc_FrameReadOut(pAbc);
pErr = Abc_FrameReadErr(pAbc);
// set defaults
- util_getopt_reset();
- while ( ( c = util_getopt( argc, argv, "h" ) ) != EOF )
+ Extra_UtilGetoptReset();
+ while ( ( c = Extra_UtilGetopt( argc, argv, "h" ) ) != EOF )
{
switch ( c )
{
@@ -2606,20 +5156,20 @@ int Abc_CommandOneNode( Abc_Frame_t * pAbc, int argc, char ** argv )
return 1;
}
- if ( argc != util_optind + 1 )
+ if ( argc != globalUtilOptind + 1 )
{
fprintf( pErr, "Wrong number of auguments.\n" );
goto usage;
}
- pNode = Abc_NtkFindNode( pNtk, argv[util_optind] );
+ pNode = Abc_NtkFindNode( pNtk, argv[globalUtilOptind] );
if ( pNode == NULL )
{
- fprintf( pErr, "Cannot find node \"%s\".\n", argv[util_optind] );
+ fprintf( pErr, "Cannot find node \"%s\".\n", argv[globalUtilOptind] );
return 1;
}
- pNtkRes = Abc_NtkSplitNode( pNtk, pNode );
+ pNtkRes = Abc_NtkCreateFromNode( pNtk, pNode );
// pNtkRes = Abc_NtkDeriveFromBdd( pNtk->pManFunc, pNode->pData, NULL, NULL );
if ( pNtkRes == NULL )
{
@@ -2631,7 +5181,7 @@ int Abc_CommandOneNode( Abc_Frame_t * pAbc, int argc, char ** argv )
return 0;
usage:
- fprintf( pErr, "usage: one_node [-h] <name>\n" );
+ fprintf( pErr, "usage: node [-h] <name>\n" );
fprintf( pErr, "\t replaces the current network by the network composed of one node\n" );
fprintf( pErr, "\t-h : print the command usage\n");
fprintf( pErr, "\tname : the node name\n");
@@ -2639,6 +5189,173 @@ usage:
}
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Abc_CommandTopmost( Abc_Frame_t * pAbc, int argc, char ** argv )
+{
+ FILE * pOut, * pErr;
+ Abc_Ntk_t * pNtk, * pNtkRes;
+ int c, nLevels;
+ extern Abc_Ntk_t * Abc_NtkTopmost( Abc_Ntk_t * pNtk, int nLevels );
+
+ pNtk = Abc_FrameReadNtk(pAbc);
+ pOut = Abc_FrameReadOut(pAbc);
+ pErr = Abc_FrameReadErr(pAbc);
+
+ // set defaults
+ nLevels = 10;
+ Extra_UtilGetoptReset();
+ while ( ( c = Extra_UtilGetopt( argc, argv, "Nh" ) ) != EOF )
+ {
+ switch ( c )
+ {
+ case 'N':
+ if ( globalUtilOptind >= argc )
+ {
+ fprintf( pErr, "Command line switch \"-N\" should be followed by an integer.\n" );
+ goto usage;
+ }
+ nLevels = atoi(argv[globalUtilOptind]);
+ globalUtilOptind++;
+ if ( nLevels < 0 )
+ goto usage;
+ break;
+ case 'h':
+ goto usage;
+ default:
+ goto usage;
+ }
+ }
+
+ if ( pNtk == NULL )
+ {
+ fprintf( pErr, "Empty network.\n" );
+ return 1;
+ }
+
+ if ( !Abc_NtkIsStrash(pNtk) )
+ {
+ fprintf( stdout, "Currently only works for structurally hashed circuits.\n" );
+ return 0;
+ }
+
+ if ( Abc_NtkLatchNum(pNtk) > 0 )
+ {
+ fprintf( stdout, "Currently can only works for combinational circuits.\n" );
+ return 0;
+ }
+ if ( Abc_NtkPoNum(pNtk) != 1 )
+ {
+ fprintf( stdout, "Currently expects a single-output miter.\n" );
+ return 0;
+ }
+
+ pNtkRes = Abc_NtkTopmost( pNtk, nLevels );
+ if ( pNtkRes == NULL )
+ {
+ fprintf( pErr, "The command has failed.\n" );
+ return 1;
+ }
+ // replace the current network
+ Abc_FrameReplaceCurrentNetwork( pAbc, pNtkRes );
+ return 0;
+
+usage:
+ fprintf( pErr, "usage: topmost [-N num] [-h]\n" );
+ fprintf( pErr, "\t replaces the current network by several of its topmost levels\n" );
+ fprintf( pErr, "\t-N num : max number of levels [default = %d]\n", nLevels );
+ fprintf( pErr, "\t-h : print the command usage\n");
+ fprintf( pErr, "\tname : the node name\n");
+ return 1;
+}
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Abc_CommandTrim( Abc_Frame_t * pAbc, int argc, char ** argv )
+{
+ FILE * pOut, * pErr;
+ Abc_Ntk_t * pNtk, * pNtkRes;
+ int c, nLevels;
+ extern Abc_Ntk_t * Abc_NtkTrim( Abc_Ntk_t * pNtk );
+
+ pNtk = Abc_FrameReadNtk(pAbc);
+ pOut = Abc_FrameReadOut(pAbc);
+ pErr = Abc_FrameReadErr(pAbc);
+
+ // set defaults
+ nLevels = 10;
+ Extra_UtilGetoptReset();
+ while ( ( c = Extra_UtilGetopt( argc, argv, "Nh" ) ) != EOF )
+ {
+ switch ( c )
+ {
+/*
+ case 'N':
+ if ( globalUtilOptind >= argc )
+ {
+ fprintf( pErr, "Command line switch \"-N\" should be followed by an integer.\n" );
+ goto usage;
+ }
+ nLevels = atoi(argv[globalUtilOptind]);
+ globalUtilOptind++;
+ if ( nLevels < 0 )
+ goto usage;
+ break;
+*/
+ case 'h':
+ goto usage;
+ default:
+ goto usage;
+ }
+ }
+
+ if ( pNtk == NULL )
+ {
+ fprintf( pErr, "Empty network.\n" );
+ return 1;
+ }
+ if ( Abc_NtkIsStrash(pNtk) )
+ {
+ fprintf( stdout, "Currently only works for logic circuits.\n" );
+ return 0;
+ }
+
+ pNtkRes = Abc_NtkTrim( pNtk );
+ if ( pNtkRes == NULL )
+ {
+ fprintf( pErr, "The command has failed.\n" );
+ return 1;
+ }
+ // replace the current network
+ Abc_FrameReplaceCurrentNetwork( pAbc, pNtkRes );
+ return 0;
+
+usage:
+ fprintf( pErr, "usage: trim [-h]\n" );
+ fprintf( pErr, "\t removes POs fed by PIs and constants, and PIs w/o fanout\n" );
+// fprintf( pErr, "\t-N num : max number of levels [default = %d]\n", nLevels );
+ fprintf( pErr, "\t-h : print the command usage\n");
+ return 1;
+}
+
/**Function*************************************************************
@@ -2657,13 +5374,13 @@ int Abc_CommandShortNames( Abc_Frame_t * pAbc, int argc, char ** argv )
Abc_Ntk_t * pNtk;
int c;
- pNtk = Abc_FrameReadNet(pAbc);
+ pNtk = Abc_FrameReadNtk(pAbc);
pOut = Abc_FrameReadOut(pAbc);
pErr = Abc_FrameReadErr(pAbc);
// set defaults
- util_getopt_reset();
- while ( ( c = util_getopt( argc, argv, "h" ) ) != EOF )
+ Extra_UtilGetoptReset();
+ while ( ( c = Extra_UtilGetopt( argc, argv, "h" ) ) != EOF )
{
switch ( c )
{
@@ -2700,73 +5417,301 @@ usage:
SeeAlso []
***********************************************************************/
+int Abc_CommandExdcFree( Abc_Frame_t * pAbc, int argc, char ** argv )
+{
+ FILE * pOut, * pErr;
+ Abc_Ntk_t * pNtk, * pNtkRes;
+ int c;
+
+ pNtk = Abc_FrameReadNtk(pAbc);
+ pOut = Abc_FrameReadOut(pAbc);
+ pErr = Abc_FrameReadErr(pAbc);
+
+ // set defaults
+ Extra_UtilGetoptReset();
+ while ( ( c = Extra_UtilGetopt( argc, argv, "h" ) ) != EOF )
+ {
+ switch ( c )
+ {
+ case 'h':
+ goto usage;
+ default:
+ goto usage;
+ }
+ }
+
+ if ( pNtk == NULL )
+ {
+ fprintf( pErr, "Empty network.\n" );
+ return 1;
+ }
+ if ( pNtk->pExdc == NULL )
+ {
+ fprintf( pErr, "The network has no EXDC.\n" );
+ return 1;
+ }
+
+ Abc_NtkDelete( pNtk->pExdc );
+ pNtk->pExdc = NULL;
+
+ // replace the current network
+ pNtkRes = Abc_NtkDup( pNtk );
+ Abc_FrameReplaceCurrentNetwork( pAbc, pNtkRes );
+ return 0;
+
+usage:
+ fprintf( pErr, "usage: exdc_free [-h]\n" );
+ fprintf( pErr, "\t frees the EXDC network of the current network\n" );
+ fprintf( pErr, "\t-h : print the command usage\n");
+ return 1;
+}
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Abc_CommandExdcGet( Abc_Frame_t * pAbc, int argc, char ** argv )
+{
+ FILE * pOut, * pErr;
+ Abc_Ntk_t * pNtk, * pNtkRes;
+ int c;
+
+ pNtk = Abc_FrameReadNtk(pAbc);
+ pOut = Abc_FrameReadOut(pAbc);
+ pErr = Abc_FrameReadErr(pAbc);
+
+ // set defaults
+ Extra_UtilGetoptReset();
+ while ( ( c = Extra_UtilGetopt( argc, argv, "h" ) ) != EOF )
+ {
+ switch ( c )
+ {
+ case 'h':
+ goto usage;
+ default:
+ goto usage;
+ }
+ }
+
+ if ( pNtk == NULL )
+ {
+ fprintf( pErr, "Empty network.\n" );
+ return 1;
+ }
+ if ( pNtk->pExdc == NULL )
+ {
+ fprintf( pErr, "The network has no EXDC.\n" );
+ return 1;
+ }
+
+ // replace the current network
+ pNtkRes = Abc_NtkDup( pNtk->pExdc );
+ Abc_FrameReplaceCurrentNetwork( pAbc, pNtkRes );
+ return 0;
+
+usage:
+ fprintf( pErr, "usage: exdc_get [-h]\n" );
+ fprintf( pErr, "\t replaces the current network by the EXDC of the current network\n" );
+ fprintf( pErr, "\t-h : print the command usage\n");
+ return 1;
+}
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Abc_CommandExdcSet( Abc_Frame_t * pAbc, int argc, char ** argv )
+{
+ FILE * pOut, * pErr, * pFile;
+ Abc_Ntk_t * pNtk, * pNtkNew, * pNtkRes;
+ char * FileName;
+ int c;
+
+ pNtk = Abc_FrameReadNtk(pAbc);
+ pOut = Abc_FrameReadOut(pAbc);
+ pErr = Abc_FrameReadErr(pAbc);
+
+ // set defaults
+ Extra_UtilGetoptReset();
+ while ( ( c = Extra_UtilGetopt( argc, argv, "h" ) ) != EOF )
+ {
+ switch ( c )
+ {
+ case 'h':
+ goto usage;
+ default:
+ goto usage;
+ }
+ }
+
+ if ( pNtk == NULL )
+ {
+ fprintf( pErr, "Empty network.\n" );
+ return 1;
+ }
+
+ if ( argc != globalUtilOptind + 1 )
+ {
+ goto usage;
+ }
+
+ // get the input file name
+ FileName = argv[globalUtilOptind];
+ if ( (pFile = fopen( FileName, "r" )) == NULL )
+ {
+ fprintf( pAbc->Err, "Cannot open input file \"%s\". ", FileName );
+ if ( FileName = Extra_FileGetSimilarName( FileName, ".mv", ".blif", ".pla", ".eqn", ".bench" ) )
+ fprintf( pAbc->Err, "Did you mean \"%s\"?", FileName );
+ fprintf( pAbc->Err, "\n" );
+ return 1;
+ }
+ fclose( pFile );
+
+ // set the new network
+ pNtkNew = Io_Read( FileName, Io_ReadFileType(FileName), 1 );
+ if ( pNtkNew == NULL )
+ {
+ fprintf( pAbc->Err, "Reading network from file has failed.\n" );
+ return 1;
+ }
+
+ // replace the EXDC
+ if ( pNtk->pExdc )
+ {
+ Abc_NtkDelete( pNtk->pExdc );
+ pNtk->pExdc = NULL;
+ }
+ pNtkRes = Abc_NtkDup( pNtk );
+ pNtkRes->pExdc = pNtkNew;
+
+ // replace the current network
+ Abc_FrameReplaceCurrentNetwork( pAbc, pNtkRes );
+ return 0;
+
+usage:
+ fprintf( pErr, "usage: exdc_set [-h] <file>\n" );
+ fprintf( pErr, "\t sets the network from file as EXDC for the current network\n" );
+ fprintf( pErr, "\t-h : print the command usage\n");
+ fprintf( pErr, "\t<file> : file with the new EXDC network\n");
+ return 1;
+}
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
int Abc_CommandCut( Abc_Frame_t * pAbc, int argc, char ** argv )
{
Cut_Params_t Params, * pParams = &Params;
Cut_Man_t * pCutMan;
+ Cut_Oracle_t * pCutOracle;
FILE * pOut, * pErr;
Abc_Ntk_t * pNtk;
int c;
+ int fOracle;
extern Cut_Man_t * Abc_NtkCuts( Abc_Ntk_t * pNtk, Cut_Params_t * pParams );
+ extern void Abc_NtkCutsOracle( Abc_Ntk_t * pNtk, Cut_Oracle_t * pCutOracle );
- pNtk = Abc_FrameReadNet(pAbc);
+ pNtk = Abc_FrameReadNtk(pAbc);
pOut = Abc_FrameReadOut(pAbc);
pErr = Abc_FrameReadErr(pAbc);
// set defaults
+ fOracle = 0;
+ memset( pParams, 0, sizeof(Cut_Params_t) );
pParams->nVarsMax = 5; // the max cut size ("k" of the k-feasible cuts)
- pParams->nKeepMax = 250; // the max number of cuts kept at a node
- pParams->fTruth = 1; // compute truth tables
- pParams->fHash = 0; // hash cuts to detect unique
- pParams->fFilter = 0; // filter dominated cuts
- pParams->fSeq = 0; // compute sequential cuts
+ pParams->nKeepMax = 1000; // the max number of cuts kept at a node
+ pParams->fTruth = 0; // compute truth tables
+ pParams->fFilter = 1; // filter dominated cuts
pParams->fDrop = 0; // drop cuts on the fly
+ pParams->fDag = 0; // compute DAG cuts
+ pParams->fTree = 0; // compute tree cuts
+ pParams->fGlobal = 0; // compute global cuts
+ pParams->fLocal = 0; // compute local cuts
+ pParams->fFancy = 0; // compute something fancy
+ pParams->fMap = 0; // compute mapping delay
pParams->fVerbose = 0; // the verbosiness flag
- util_getopt_reset();
- while ( ( c = util_getopt( argc, argv, "KMtrfsdvh" ) ) != EOF )
+ Extra_UtilGetoptReset();
+ while ( ( c = Extra_UtilGetopt( argc, argv, "KMtfdxyglzmvoh" ) ) != EOF )
{
switch ( c )
{
case 'K':
- if ( util_optind >= argc )
+ if ( globalUtilOptind >= argc )
{
fprintf( pErr, "Command line switch \"-K\" should be followed by an integer.\n" );
goto usage;
}
- pParams->nVarsMax = atoi(argv[util_optind]);
- util_optind++;
+ pParams->nVarsMax = atoi(argv[globalUtilOptind]);
+ globalUtilOptind++;
if ( pParams->nVarsMax < 0 )
goto usage;
break;
case 'M':
- if ( util_optind >= argc )
+ if ( globalUtilOptind >= argc )
{
fprintf( pErr, "Command line switch \"-M\" should be followed by an integer.\n" );
goto usage;
}
- pParams->nKeepMax = atoi(argv[util_optind]);
- util_optind++;
+ pParams->nKeepMax = atoi(argv[globalUtilOptind]);
+ globalUtilOptind++;
if ( pParams->nKeepMax < 0 )
goto usage;
break;
case 't':
pParams->fTruth ^= 1;
break;
- case 'r':
- pParams->fHash ^= 1;
- break;
case 'f':
pParams->fFilter ^= 1;
break;
- case 's':
- pParams->fSeq ^= 1;
- break;
case 'd':
pParams->fDrop ^= 1;
break;
+ case 'x':
+ pParams->fDag ^= 1;
+ break;
+ case 'y':
+ pParams->fTree ^= 1;
+ break;
+ case 'g':
+ pParams->fGlobal ^= 1;
+ break;
+ case 'l':
+ pParams->fLocal ^= 1;
+ break;
+ case 'z':
+ pParams->fFancy ^= 1;
+ break;
+ case 'm':
+ pParams->fMap ^= 1;
+ break;
case 'v':
pParams->fVerbose ^= 1;
break;
+ case 'o':
+ fOracle ^= 1;
+ break;
case 'h':
goto usage;
default:
@@ -2784,22 +5729,45 @@ int Abc_CommandCut( Abc_Frame_t * pAbc, int argc, char ** argv )
fprintf( pErr, "Cut computation is available only for AIGs (run \"strash\").\n" );
return 1;
}
+ if ( pParams->nVarsMax < CUT_SIZE_MIN || pParams->nVarsMax > CUT_SIZE_MAX )
+ {
+ fprintf( pErr, "Can only compute the cuts for %d <= K <= %d.\n", CUT_SIZE_MIN, CUT_SIZE_MAX );
+ return 1;
+ }
+ if ( pParams->fDag && pParams->fTree )
+ {
+ fprintf( pErr, "Cannot compute both DAG cuts and tree cuts at the same time.\n" );
+ return 1;
+ }
+
+ if ( fOracle )
+ pParams->fRecord = 1;
pCutMan = Abc_NtkCuts( pNtk, pParams );
- Cut_ManPrintStats( pCutMan );
+ if ( fOracle )
+ pCutOracle = Cut_OracleStart( pCutMan );
Cut_ManStop( pCutMan );
+ if ( fOracle )
+ {
+ Abc_NtkCutsOracle( pNtk, pCutOracle );
+ Cut_OracleStop( pCutOracle );
+ }
return 0;
usage:
- fprintf( pErr, "usage: cut [-K num] [-M num] [-trfsdvh]\n" );
+ fprintf( pErr, "usage: cut [-K num] [-M num] [-tfdxyzmvh]\n" );
fprintf( pErr, "\t computes k-feasible cuts for the AIG\n" );
- fprintf( pErr, "\t-K num : max number of leaves (4 <= num <= 6) [default = %d]\n", pParams->nVarsMax );
- fprintf( pErr, "\t-M num : max number of cuts stored at a node [default = %d]\n", pParams->nKeepMax );
- fprintf( pErr, "\t-t : toggle truth table computation [default = %s]\n", pParams->fTruth? "yes": "no" );
- fprintf( pErr, "\t-r : toggle reduction by hashing [default = %s]\n", pParams->fHash? "yes": "no" );
- fprintf( pErr, "\t-f : toggle filtering by dominance [default = %s]\n", pParams->fFilter? "yes": "no" );
- fprintf( pErr, "\t-s : toggle sequential cut computation [default = %s]\n", pParams->fSeq? "yes": "no" );
- fprintf( pErr, "\t-d : toggle dropping when fanouts are done [default = %s]\n", pParams->fDrop? "yes": "no" );
- fprintf( pErr, "\t-v : toggle printing verbose information [default = %s]\n", pParams->fVerbose? "yes": "no" );
+ fprintf( pErr, "\t-K num : max number of leaves (%d <= num <= %d) [default = %d]\n", CUT_SIZE_MIN, CUT_SIZE_MAX, pParams->nVarsMax );
+ fprintf( pErr, "\t-M num : max number of cuts stored at a node [default = %d]\n", pParams->nKeepMax );
+ fprintf( pErr, "\t-t : toggle truth table computation [default = %s]\n", pParams->fTruth? "yes": "no" );
+ fprintf( pErr, "\t-f : toggle filtering of duplicated/dominated [default = %s]\n", pParams->fFilter? "yes": "no" );
+ fprintf( pErr, "\t-d : toggle dropping when fanouts are done [default = %s]\n", pParams->fDrop? "yes": "no" );
+ fprintf( pErr, "\t-x : toggle computing only DAG cuts [default = %s]\n", pParams->fDag? "yes": "no" );
+ fprintf( pErr, "\t-y : toggle computing only tree cuts [default = %s]\n", pParams->fTree? "yes": "no" );
+ fprintf( pErr, "\t-g : toggle computing only global cuts [default = %s]\n", pParams->fGlobal? "yes": "no" );
+ fprintf( pErr, "\t-l : toggle computing only local cuts [default = %s]\n", pParams->fLocal? "yes": "no" );
+ fprintf( pErr, "\t-z : toggle fancy computations [default = %s]\n", pParams->fFancy? "yes": "no" );
+ fprintf( pErr, "\t-m : toggle delay-oriented FPGA mapping [default = %s]\n", pParams->fMap? "yes": "no" );
+ fprintf( pErr, "\t-v : toggle printing verbose information [default = %s]\n", pParams->fVerbose? "yes": "no" );
fprintf( pErr, "\t-h : print the command usage\n");
return 1;
}
@@ -2815,22 +5783,540 @@ usage:
SeeAlso []
***********************************************************************/
-int Abc_CommandTest( Abc_Frame_t * pAbc, int argc, char ** argv )
+int Abc_CommandScut( Abc_Frame_t * pAbc, int argc, char ** argv )
+{
+ Cut_Params_t Params, * pParams = &Params;
+ Cut_Man_t * pCutMan;
+ FILE * pOut, * pErr;
+ Abc_Ntk_t * pNtk;
+ int c;
+ extern Cut_Man_t * Abc_NtkSeqCuts( Abc_Ntk_t * pNtk, Cut_Params_t * pParams );
+
+ pNtk = Abc_FrameReadNtk(pAbc);
+ pOut = Abc_FrameReadOut(pAbc);
+ pErr = Abc_FrameReadErr(pAbc);
+
+ // set defaults
+ memset( pParams, 0, sizeof(Cut_Params_t) );
+ pParams->nVarsMax = 5; // the max cut size ("k" of the k-feasible cuts)
+ pParams->nKeepMax = 1000; // the max number of cuts kept at a node
+ pParams->fTruth = 0; // compute truth tables
+ pParams->fFilter = 1; // filter dominated cuts
+ pParams->fSeq = 1; // compute sequential cuts
+ pParams->fVerbose = 0; // the verbosiness flag
+ Extra_UtilGetoptReset();
+ while ( ( c = Extra_UtilGetopt( argc, argv, "KMtvh" ) ) != EOF )
+ {
+ switch ( c )
+ {
+ case 'K':
+ if ( globalUtilOptind >= argc )
+ {
+ fprintf( pErr, "Command line switch \"-K\" should be followed by an integer.\n" );
+ goto usage;
+ }
+ pParams->nVarsMax = atoi(argv[globalUtilOptind]);
+ globalUtilOptind++;
+ if ( pParams->nVarsMax < 0 )
+ goto usage;
+ break;
+ case 'M':
+ if ( globalUtilOptind >= argc )
+ {
+ fprintf( pErr, "Command line switch \"-M\" should be followed by an integer.\n" );
+ goto usage;
+ }
+ pParams->nKeepMax = atoi(argv[globalUtilOptind]);
+ globalUtilOptind++;
+ if ( pParams->nKeepMax < 0 )
+ goto usage;
+ break;
+ case 't':
+ pParams->fTruth ^= 1;
+ break;
+ case 'v':
+ pParams->fVerbose ^= 1;
+ break;
+ case 'h':
+ goto usage;
+ default:
+ goto usage;
+ }
+ }
+
+ if ( pNtk == NULL )
+ {
+ fprintf( pErr, "Empty network.\n" );
+ return 1;
+ }
+/*
+ if ( !Abc_NtkIsSeq(pNtk) )
+ {
+ fprintf( pErr, "Sequential cuts can be computed for sequential AIGs (run \"seq\").\n" );
+ return 1;
+ }
+*/
+ if ( pParams->nVarsMax < CUT_SIZE_MIN || pParams->nVarsMax > CUT_SIZE_MAX )
+ {
+ fprintf( pErr, "Can only compute the cuts for %d <= K <= %d.\n", CUT_SIZE_MIN, CUT_SIZE_MAX );
+ return 1;
+ }
+
+ pCutMan = Abc_NtkSeqCuts( pNtk, pParams );
+ Cut_ManStop( pCutMan );
+ return 0;
+
+usage:
+ fprintf( pErr, "usage: scut [-K num] [-M num] [-tvh]\n" );
+ fprintf( pErr, "\t computes k-feasible cuts for the sequential AIG\n" );
+ fprintf( pErr, "\t-K num : max number of leaves (%d <= num <= %d) [default = %d]\n", CUT_SIZE_MIN, CUT_SIZE_MAX, pParams->nVarsMax );
+ fprintf( pErr, "\t-M num : max number of cuts stored at a node [default = %d]\n", pParams->nKeepMax );
+ fprintf( pErr, "\t-t : toggle truth table computation [default = %s]\n", pParams->fTruth? "yes": "no" );
+ fprintf( pErr, "\t-v : toggle printing verbose information [default = %s]\n", pParams->fVerbose? "yes": "no" );
+ fprintf( pErr, "\t-h : print the command usage\n");
+ return 1;
+}
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Abc_CommandEspresso( Abc_Frame_t * pAbc, int argc, char ** argv )
+{
+ FILE * pOut, * pErr;
+ Abc_Ntk_t * pNtk;
+ int c;
+ int fVerbose;
+ extern void Abc_NtkEspresso( Abc_Ntk_t * pNtk, int fVerbose );
+
+ pNtk = Abc_FrameReadNtk(pAbc);
+ pOut = Abc_FrameReadOut(pAbc);
+ pErr = Abc_FrameReadErr(pAbc);
+
+ // set defaults
+ fVerbose = 0;
+ Extra_UtilGetoptReset();
+ while ( ( c = Extra_UtilGetopt( argc, argv, "vh" ) ) != EOF )
+ {
+ switch ( c )
+ {
+ case 'v':
+ fVerbose ^= 1;
+ break;
+ case 'h':
+ goto usage;
+ default:
+ goto usage;
+ }
+ }
+ if ( pNtk == NULL )
+ {
+ fprintf( pErr, "Empty network.\n" );
+ return 1;
+ }
+ if ( !Abc_NtkIsLogic(pNtk) )
+ {
+ fprintf( pErr, "SOP minimization is possible for logic networks (run \"renode\").\n" );
+ return 1;
+ }
+ Abc_NtkEspresso( pNtk, fVerbose );
+ return 0;
+
+usage:
+ fprintf( pErr, "usage: espresso [-vh]\n" );
+ fprintf( pErr, "\t minimizes SOPs of the local functions using Espresso\n" );
+ fprintf( pErr, "\t-v : prints verbose information [default = %s]\n", fVerbose? "yes": "no" );
+ fprintf( pErr, "\t-h : print the command usage\n");
+ return 1;
+}
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Abc_CommandGen( Abc_Frame_t * pAbc, int argc, char ** argv )
+{
+ FILE * pOut, * pErr;
+ Abc_Ntk_t * pNtk;
+ int c;
+ int nVars;
+ int fAdder;
+ int fSorter;
+ int fMesh;
+ int fFpga;
+ int fVerbose;
+ char * FileName;
+ extern void Abc_GenAdder( char * pFileName, int nVars );
+ extern void Abc_GenSorter( char * pFileName, int nVars );
+ extern void Abc_GenMesh( char * pFileName, int nVars );
+ extern void Abc_GenFpga( char * pFileName, int nLutSize, int nLuts, int nVars );
+
+
+ pNtk = Abc_FrameReadNtk(pAbc);
+ pOut = Abc_FrameReadOut(pAbc);
+ pErr = Abc_FrameReadErr(pAbc);
+
+ // set defaults
+ nVars = 8;
+ fAdder = 0;
+ fSorter = 0;
+ fMesh = 0;
+ fFpga = 0;
+ fVerbose = 0;
+ Extra_UtilGetoptReset();
+ while ( ( c = Extra_UtilGetopt( argc, argv, "Nasmfvh" ) ) != EOF )
+ {
+ switch ( c )
+ {
+ case 'N':
+ if ( globalUtilOptind >= argc )
+ {
+ fprintf( pErr, "Command line switch \"-N\" should be followed by an integer.\n" );
+ goto usage;
+ }
+ nVars = atoi(argv[globalUtilOptind]);
+ globalUtilOptind++;
+ if ( nVars < 0 )
+ goto usage;
+ break;
+ case 'a':
+ fAdder ^= 1;
+ break;
+ case 's':
+ fSorter ^= 1;
+ break;
+ case 'm':
+ fMesh ^= 1;
+ break;
+ case 'f':
+ fFpga ^= 1;
+ break;
+ case 'v':
+ fVerbose ^= 1;
+ break;
+ case 'h':
+ goto usage;
+ default:
+ goto usage;
+ }
+ }
+
+ if ( argc != globalUtilOptind + 1 )
+ {
+ goto usage;
+ }
+
+ // get the input file name
+ FileName = argv[globalUtilOptind];
+ if ( fAdder )
+ Abc_GenAdder( FileName, nVars );
+ else if ( fSorter )
+ Abc_GenSorter( FileName, nVars );
+ else if ( fMesh )
+ Abc_GenMesh( FileName, nVars );
+ else if ( fFpga )
+ Abc_GenFpga( FileName, 4, 3, 10 );
+// Abc_GenFpga( FileName, 2, 2, 3 );
+// Abc_GenFpga( FileName, 3, 2, 5 );
+ else
+ printf( "Type of circuit is not specified.\n" );
+ return 0;
+
+usage:
+ fprintf( pErr, "usage: gen [-N] [-asmfvh] <file>\n" );
+ fprintf( pErr, "\t generates simple circuits\n" );
+ fprintf( pErr, "\t-N num : the number of variables [default = %d]\n", nVars );
+ fprintf( pErr, "\t-a : generate ripple-carry adder [default = %s]\n", fAdder? "yes": "no" );
+ fprintf( pErr, "\t-s : generate a sorter [default = %s]\n", fSorter? "yes": "no" );
+ fprintf( pErr, "\t-m : generate a mesh [default = %s]\n", fMesh? "yes": "no" );
+ fprintf( pErr, "\t-f : generate a LUT FPGA structure [default = %s]\n", fFpga? "yes": "no" );
+ fprintf( pErr, "\t-v : prints verbose information [default = %s]\n", fVerbose? "yes": "no" );
+ fprintf( pErr, "\t-h : print the command usage\n");
+ fprintf( pErr, "\t<file> : output file name\n");
+ return 1;
+}
+
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Abc_CommandXyz( Abc_Frame_t * pAbc, int argc, char ** argv )
+{
+ FILE * pOut, * pErr;
+ Abc_Ntk_t * pNtk, * pNtkRes;//, * pNtkTemp;
+ int c;
+ int nLutMax;
+ int nPlaMax;
+ int RankCost;
+ int fFastMode;
+ int fRewriting;
+ int fSynthesis;
+ int fVerbose;
+// extern Abc_Ntk_t * Abc_NtkXyz( Abc_Ntk_t * pNtk, int nPlaMax, bool fEsop, bool fSop, bool fInvs, bool fVerbose );
+ extern void * Abc_NtkPlayer( void * pNtk, int nLutMax, int nPlaMax, int RankCost, int fFastMode, int fRewriting, int fSynthesis, int fVerbose );
+
+ pNtk = Abc_FrameReadNtk(pAbc);
+ pOut = Abc_FrameReadOut(pAbc);
+ pErr = Abc_FrameReadErr(pAbc);
+
+ // set defaults
+ nLutMax = 8;
+ nPlaMax = 128;
+ RankCost = 96000;
+ fFastMode = 1;
+ fRewriting = 0;
+ fSynthesis = 0;
+ fVerbose = 0;
+ Extra_UtilGetoptReset();
+ while ( ( c = Extra_UtilGetopt( argc, argv, "LPRfrsvh" ) ) != EOF )
+ {
+ switch ( c )
+ {
+ case 'L':
+ if ( globalUtilOptind >= argc )
+ {
+ fprintf( pErr, "Command line switch \"-L\" should be followed by an integer.\n" );
+ goto usage;
+ }
+ nLutMax = atoi(argv[globalUtilOptind]);
+ globalUtilOptind++;
+ if ( nLutMax < 0 )
+ goto usage;
+ break;
+ case 'P':
+ if ( globalUtilOptind >= argc )
+ {
+ fprintf( pErr, "Command line switch \"-P\" should be followed by an integer.\n" );
+ goto usage;
+ }
+ nPlaMax = atoi(argv[globalUtilOptind]);
+ globalUtilOptind++;
+ if ( nPlaMax < 0 )
+ goto usage;
+ break;
+ case 'R':
+ if ( globalUtilOptind >= argc )
+ {
+ fprintf( pErr, "Command line switch \"-R\" should be followed by an integer.\n" );
+ goto usage;
+ }
+ RankCost = atoi(argv[globalUtilOptind]);
+ globalUtilOptind++;
+ if ( RankCost < 0 )
+ goto usage;
+ break;
+ case 'f':
+ fFastMode ^= 1;
+ break;
+ case 'r':
+ fRewriting ^= 1;
+ break;
+ case 's':
+ fSynthesis ^= 1;
+ break;
+ case 'v':
+ fVerbose ^= 1;
+ break;
+ case 'h':
+ goto usage;
+ default:
+ goto usage;
+ }
+ }
+ if ( pNtk == NULL )
+ {
+ fprintf( pErr, "Empty network.\n" );
+ return 1;
+ }
+
+ if ( !Abc_NtkIsStrash(pNtk) )
+ {
+ fprintf( pErr, "Only works for strashed networks.\n" );
+ return 1;
+ }
+/*
+ if ( nLutMax < 2 || nLutMax > 12 || nPlaMax < 8 || nPlaMax > 128 )
+ {
+ fprintf( pErr, "Incorrect LUT/PLA parameters.\n" );
+ return 1;
+ }
+*/
+ // run the command
+// pNtkRes = Abc_NtkXyz( pNtk, nPlaMax, 1, 0, fInvs, fVerbose );
+/*
+ if ( !Abc_NtkIsStrash(pNtk) )
+ {
+ pNtkTemp = Abc_NtkStrash( pNtk, 0, 1, 0 );
+ pNtkRes = Abc_NtkPlayer( pNtkTemp, nLutMax, nPlaMax, RankCost, fFastMode, fRewriting, fSynthesis, fVerbose );
+ Abc_NtkDelete( pNtkTemp );
+ }
+ else
+ pNtkRes = Abc_NtkPlayer( pNtk, nLutMax, nPlaMax, RankCost, fFastMode, fRewriting, fSynthesis, fVerbose );
+*/
+ pNtkRes = NULL;
+ if ( pNtkRes == NULL )
+ {
+ fprintf( pErr, "Command has failed.\n" );
+ return 0;
+ }
+ // replace the current network
+ Abc_FrameReplaceCurrentNetwork( pAbc, pNtkRes );
+ return 0;
+
+usage:
+ fprintf( pErr, "usage: xyz [-L num] [-P num] [-R num] [-frsvh]\n" );
+ fprintf( pErr, "\t specilized LUT/PLA decomposition\n" );
+ fprintf( pErr, "\t-L num : maximum number of LUT inputs (2<=num<=8) [default = %d]\n", nLutMax );
+ fprintf( pErr, "\t-P num : maximum number of PLA inputs/cubes (8<=num<=128) [default = %d]\n", nPlaMax );
+ fprintf( pErr, "\t-R num : maximum are of one decomposition rank [default = %d]\n", RankCost );
+ fprintf( pErr, "\t-f : toggle using fast LUT mapping mode [default = %s]\n", fFastMode? "yes": "no" );
+ fprintf( pErr, "\t-r : toggle using one pass of AIG rewriting [default = %s]\n", fRewriting? "yes": "no" );
+ fprintf( pErr, "\t-s : toggle using synthesis by AIG rewriting [default = %s]\n", fSynthesis? "yes": "no" );
+ fprintf( pErr, "\t-v : toggle printing verbose information [default = %s]\n", fVerbose? "yes": "no" );
+ fprintf( pErr, "\t-h : print the command usage\n");
+ return 1;
+}
+
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Abc_CommandInter( Abc_Frame_t * pAbc, int argc, char ** argv )
+{
+ FILE * pOut, * pErr;
+ Abc_Ntk_t * pNtk, * pNtkRes, * pNtk1, * pNtk2;
+ char ** pArgvNew;
+ int nArgcNew;
+ int c, fDelete1, fDelete2;
+ int fVerbose;
+ extern Abc_Ntk_t * Abc_NtkInter( Abc_Ntk_t * pNtkOn, Abc_Ntk_t * pNtkOff, int fVerbose );
+
+ pNtk = Abc_FrameReadNtk(pAbc);
+ pOut = Abc_FrameReadOut(pAbc);
+ pErr = Abc_FrameReadErr(pAbc);
+
+ // set defaults
+ fVerbose = 0;
+ Extra_UtilGetoptReset();
+ while ( ( c = Extra_UtilGetopt( argc, argv, "vh" ) ) != EOF )
+ {
+ switch ( c )
+ {
+ case 'v':
+ fVerbose ^= 1;
+ break;
+ case 'h':
+ goto usage;
+ default:
+ goto usage;
+ }
+ }
+
+ pArgvNew = argv + globalUtilOptind;
+ nArgcNew = argc - globalUtilOptind;
+ if ( !Abc_NtkPrepareTwoNtks( pErr, pNtk, pArgvNew, nArgcNew, &pNtk1, &pNtk2, &fDelete1, &fDelete2 ) )
+ return 1;
+ if ( nArgcNew == 0 )
+ {
+ printf( "Deriving new circuit structure for the current network.\n" );
+ Abc_ObjXorFaninC( Abc_NtkPo(pNtk2,0), 0 );
+ }
+ pNtkRes = Abc_NtkInter( pNtk1, pNtk2, fVerbose );
+ if ( fDelete1 ) Abc_NtkDelete( pNtk1 );
+ if ( fDelete2 ) Abc_NtkDelete( pNtk2 );
+
+ if ( pNtkRes == NULL )
+ {
+ fprintf( pErr, "Command has failed.\n" );
+ return 0;
+ }
+ Abc_FrameReplaceCurrentNetwork( pAbc, pNtkRes );
+ return 0;
+
+usage:
+ fprintf( pErr, "usage: inter [-vh] <fileOnSet> <fileOffSet>\n" );
+ fprintf( pErr, "\t derives interpolant of two networks (onset and offset)\n" );
+ fprintf( pErr, "\t-v : toggle printing verbose information [default = %s]\n", fVerbose? "yes": "no" );
+ fprintf( pErr, "\t-h : print the command usage\n");
+ return 1;
+}
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Abc_CommandDouble( Abc_Frame_t * pAbc, int argc, char ** argv )
{
FILE * pOut, * pErr;
Abc_Ntk_t * pNtk, * pNtkRes;
int c;
+ int nFrames;
+ int fVerbose;
+ extern Abc_Ntk_t * Abc_NtkDouble( Abc_Ntk_t * pNtk );
- pNtk = Abc_FrameReadNet(pAbc);
+ pNtk = Abc_FrameReadNtk(pAbc);
pOut = Abc_FrameReadOut(pAbc);
pErr = Abc_FrameReadErr(pAbc);
// set defaults
- util_getopt_reset();
- while ( ( c = util_getopt( argc, argv, "h" ) ) != EOF )
+ nFrames = 50;
+ fVerbose = 0;
+ Extra_UtilGetoptReset();
+ while ( ( c = Extra_UtilGetopt( argc, argv, "vh" ) ) != EOF )
{
switch ( c )
{
+ case 'F':
+ if ( globalUtilOptind >= argc )
+ {
+ fprintf( pErr, "Command line switch \"-F\" should be followed by an integer.\n" );
+ goto usage;
+ }
+ nFrames = atoi(argv[globalUtilOptind]);
+ globalUtilOptind++;
+ if ( nFrames < 0 )
+ goto usage;
+ break;
+ case 'v':
+ fVerbose ^= 1;
+ break;
case 'h':
goto usage;
default:
@@ -2842,8 +6328,143 @@ int Abc_CommandTest( Abc_Frame_t * pAbc, int argc, char ** argv )
fprintf( pErr, "Empty network.\n" );
return 1;
}
+
+ if ( !Abc_NtkIsSopLogic(pNtk) )
+ {
+ fprintf( pErr, "Only works for logic SOP networks.\n" );
+ return 1;
+ }
+
+ pNtkRes = Abc_NtkDouble( pNtk );
+ if ( pNtkRes == NULL )
+ {
+ fprintf( pErr, "Command has failed.\n" );
+ return 0;
+ }
+ Abc_FrameReplaceCurrentNetwork( pAbc, pNtkRes );
+ return 0;
+
+usage:
+ fprintf( pErr, "usage: double [-vh]\n" );
+ fprintf( pErr, "\t puts together two parallel copies of the current network\n" );
+// fprintf( pErr, "\t-F num : the number of frames to simulate [default = %d]\n", nFrames );
+ fprintf( pErr, "\t-v : toggle printing verbose information [default = %s]\n", fVerbose? "yes": "no" );
+ fprintf( pErr, "\t-h : print the command usage\n");
+ return 1;
+}
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Abc_CommandTest( Abc_Frame_t * pAbc, int argc, char ** argv )
+{
+ FILE * pOut, * pErr;
+ Abc_Ntk_t * pNtk;//, * pNtkRes;
+ int c;
+ int fBmc;
+ int nFrames;
+ int nLevels;
+ int fVerbose;
+ int fVeryVerbose;
+// extern Abc_Ntk_t * Abc_NtkNewAig( Abc_Ntk_t * pNtk );
+// extern Abc_Ntk_t * Abc_NtkIvy( Abc_Ntk_t * pNtk );
+// extern void Abc_NtkMaxFlowTest( Abc_Ntk_t * pNtk );
+// extern int Pr_ManProofTest( char * pFileName );
+ extern void Abc_NtkCompareSupports( Abc_Ntk_t * pNtk );
+ extern void Abc_NtkCompareCones( Abc_Ntk_t * pNtk );
+ extern Abc_Ntk_t * Abc_NtkDar( Abc_Ntk_t * pNtk );
+ extern Abc_Ntk_t * Abc_NtkDarToCnf( Abc_Ntk_t * pNtk, char * pFileName );
+ extern Abc_Ntk_t * Abc_NtkFilter( Abc_Ntk_t * pNtk );
+// extern Abc_Ntk_t * Abc_NtkDarRetime( Abc_Ntk_t * pNtk, int nStepsMax, int fVerbose );
+ extern Abc_Ntk_t * Abc_NtkPcmTest( Abc_Ntk_t * pNtk, int fVerbose );
+ extern Abc_NtkDarHaigRecord( Abc_Ntk_t * pNtk );
+// extern void Abc_NtkDarTestBlif( char * pFileName );
+
+ pNtk = Abc_FrameReadNtk(pAbc);
+ pOut = Abc_FrameReadOut(pAbc);
+ pErr = Abc_FrameReadErr(pAbc);
+
+ printf( "This command is temporarily disabled.\n" );
+ return 0;
+
+ // set defaults
+ fVeryVerbose = 0;
+ fVerbose = 1;
+ fBmc = 1;
+ nFrames = 1;
+ nLevels = 200;
+ Extra_UtilGetoptReset();
+ while ( ( c = Extra_UtilGetopt( argc, argv, "FNbvwh" ) ) != EOF )
+ {
+ switch ( c )
+ {
+ case 'F':
+ if ( globalUtilOptind >= argc )
+ {
+ fprintf( pErr, "Command line switch \"-F\" should be followed by an integer.\n" );
+ goto usage;
+ }
+ nFrames = atoi(argv[globalUtilOptind]);
+ globalUtilOptind++;
+ if ( nFrames < 0 )
+ goto usage;
+ break;
+ case 'N':
+ if ( globalUtilOptind >= argc )
+ {
+ fprintf( pErr, "Command line switch \"-N\" should be followed by an integer.\n" );
+ goto usage;
+ }
+ nLevels = atoi(argv[globalUtilOptind]);
+ globalUtilOptind++;
+ if ( nLevels < 0 )
+ goto usage;
+ break;
+ case 'b':
+ fBmc ^= 1;
+ break;
+ case 'v':
+ fVerbose ^= 1;
+ break;
+ case 'w':
+ fVeryVerbose ^= 1;
+ break;
+ case 'h':
+ goto usage;
+ default:
+ goto usage;
+ }
+ }
+/*
+ if ( pNtk == NULL )
+ {
+ fprintf( pErr, "Empty network.\n" );
+ return 1;
+ }
+ if ( Abc_NtkIsSeq(pNtk) )
+ {
+ fprintf( pErr, "Only works for non-sequential networks.\n" );
+ return 1;
+ }
+*/
+
+// Abc_NtkTestEsop( pNtk );
+// Abc_NtkTestSop( pNtk );
+// printf( "This command is currently not used.\n" );
// run the command
- pNtkRes = Abc_NtkMiterForCofactors( pNtk, 0, 0, -1 );
+// pNtkRes = Abc_NtkMiterForCofactors( pNtk, 0, 0, -1 );
+// pNtkRes = Abc_NtkNewAig( pNtk );
+
+/*
+ pNtkRes = NULL;
if ( pNtkRes == NULL )
{
fprintf( pErr, "Command has failed.\n" );
@@ -2851,16 +6472,1937 @@ int Abc_CommandTest( Abc_Frame_t * pAbc, int argc, char ** argv )
}
// replace the current network
Abc_FrameReplaceCurrentNetwork( pAbc, pNtkRes );
- return 0;
+*/
+
+// if ( Cut_CellIsRunning() )
+// Cut_CellDumpToFile();
+// else
+// Cut_CellPrecompute();
+// Cut_CellLoad();
+/*
+ {
+ Abc_Ntk_t * pNtkRes;
+ extern Abc_Ntk_t * Abc_NtkTopmost( Abc_Ntk_t * pNtk, int nLevels );
+ pNtkRes = Abc_NtkTopmost( pNtk, nLevels );
+ Abc_FrameReplaceCurrentNetwork( pAbc, pNtkRes );
+ }
+*/
+// Abc_NtkSimulteBuggyMiter( pNtk );
+
+// Rwr_Temp();
+// Abc_MvExperiment();
+// Ivy_TruthTest();
+
+
+// Ivy_TruthEstimateNodesTest();
+/*
+ pNtkRes = Abc_NtkIvy( pNtk );
+// pNtkRes = Abc_NtkPlayer( pNtk, nLevels, 0 );
+// pNtkRes = NULL;
+ if ( pNtkRes == NULL )
+ {
+ fprintf( pErr, "Command has failed.\n" );
+ return 1;
+ }
+ // replace the current network
+ Abc_FrameReplaceCurrentNetwork( pAbc, pNtkRes );
+*/
+// Abc_NtkMaxFlowTest( pNtk );
+// Pr_ManProofTest( "trace.cnf" );
+
+// Abc_NtkCompareSupports( pNtk );
+// Abc_NtkCompareCones( pNtk );
+/*
+ {
+ extern Vec_Vec_t * Abc_NtkPartitionSmart( Abc_Ntk_t * pNtk, int fVerbose );
+ Vec_Vec_t * vParts;
+ vParts = Abc_NtkPartitionSmart( pNtk, 1 );
+ Vec_VecFree( vParts );
+ }
+*/
+// Abc_Ntk4VarTable( pNtk );
+// Dar_NtkGenerateArrays( pNtk );
+// Dar_ManDeriveCnfTest2();
+/*
+ if ( !Abc_NtkIsStrash(pNtk) )
+ {
+ fprintf( pErr, "Network should be strashed. Command has failed.\n" );
+ return 1;
+ }
+*/
+/*
+ if ( !Abc_NtkIsStrash(pNtk) )
+ {
+ fprintf( stdout, "Currently only works for structurally hashed circuits.\n" );
+ return 0;
+ }
+*/
+/*
+ if ( Abc_NtkIsStrash(pNtk) )
+ {
+ fprintf( stdout, "Currently only works for logic circuits.\n" );
+ return 0;
+ }
+*/
+/*
+// pNtkRes = Abc_NtkDar( pNtk );
+// pNtkRes = Abc_NtkDarRetime( pNtk, nLevels, 1 );
+ pNtkRes = Abc_NtkPcmTest( pNtk, fVerbose );
+// pNtkRes = NULL;
+ if ( pNtkRes == NULL )
+ {
+ fprintf( pErr, "Command has failed.\n" );
+ return 1;
+ }
+ // replace the current network
+ Abc_FrameReplaceCurrentNetwork( pAbc, pNtkRes );
+*/
+// Abc_NtkDarHaigRecord( pNtk );
+// Abc_NtkDarClau( pNtk, nFrames, nLevels, fBmc, fVerbose, fVeryVerbose );
+/*
+ if ( globalUtilOptind != 1 )
+ {
+ fprintf( pErr, "Command has failed.\n" );
+ return 1;
+ }
+ Abc_NtkDarTestBlif( argv[globalUtilOptind] );
+*/
+ return 0;
usage:
- fprintf( pErr, "usage: test [-h]\n" );
+ fprintf( pErr, "usage: test [-vwh]\n" );
fprintf( pErr, "\t testbench for new procedures\n" );
+ fprintf( pErr, "\t-v : toggle printing verbose information [default = %s]\n", fVerbose? "yes": "no" );
+ fprintf( pErr, "\t-w : toggle printing very verbose information [default = %s]\n", fVeryVerbose? "yes": "no" );
+ fprintf( pErr, "\t-h : print the command usage\n");
+ return 1;
+}
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Abc_CommandQuaVar( Abc_Frame_t * pAbc, int argc, char ** argv )
+{
+ FILE * pOut, * pErr;
+ Abc_Ntk_t * pNtk, * pNtkRes;
+ int c, iVar, fUniv, fVerbose, RetValue;
+ extern int Abc_NtkQuantify( Abc_Ntk_t * pNtk, int fUniv, int iVar, int fVerbose );
+
+ pNtk = Abc_FrameReadNtk(pAbc);
+ pOut = Abc_FrameReadOut(pAbc);
+ pErr = Abc_FrameReadErr(pAbc);
+
+ // set defaults
+ iVar = 0;
+ fUniv = 0;
+ fVerbose = 0;
+ Extra_UtilGetoptReset();
+ while ( ( c = Extra_UtilGetopt( argc, argv, "Iuvh" ) ) != EOF )
+ {
+ switch ( c )
+ {
+ case 'I':
+ if ( globalUtilOptind >= argc )
+ {
+ fprintf( pErr, "Command line switch \"-I\" should be followed by an integer.\n" );
+ goto usage;
+ }
+ iVar = atoi(argv[globalUtilOptind]);
+ globalUtilOptind++;
+ if ( iVar < 0 )
+ goto usage;
+ break;
+ case 'u':
+ fUniv ^= 1;
+ break;
+ case 'v':
+ fVerbose ^= 1;
+ break;
+ case 'h':
+ goto usage;
+ default:
+ goto usage;
+ }
+ }
+ if ( pNtk == NULL )
+ {
+ fprintf( pErr, "Empty network.\n" );
+ return 1;
+ }
+ if ( Abc_NtkGetChoiceNum( pNtk ) )
+ {
+ fprintf( pErr, "This command cannot be applied to an AIG with choice nodes.\n" );
+ return 1;
+ }
+
+ // get the strashed network
+ pNtkRes = Abc_NtkStrash( pNtk, 0, 1, 0 );
+ RetValue = Abc_NtkQuantify( pNtkRes, fUniv, iVar, fVerbose );
+ // clean temporary storage for the cofactors
+ Abc_NtkCleanData( pNtkRes );
+ Abc_AigCleanup( pNtkRes->pManFunc );
+ // check the result
+ if ( !RetValue )
+ {
+ fprintf( pErr, "Command has failed.\n" );
+ return 0;
+ }
+ // replace the current network
+ Abc_FrameReplaceCurrentNetwork( pAbc, pNtkRes );
+ return 0;
+
+usage:
+ fprintf( pErr, "usage: qvar [-I num] [-uvh]\n" );
+ fprintf( pErr, "\t quantifies one variable using the AIG\n" );
+ fprintf( pErr, "\t-I num : the zero-based index of a variable to quantify [default = %d]\n", iVar );
+ fprintf( pErr, "\t-u : toggle universal quantification [default = %s]\n", fUniv? "yes": "no" );
+ fprintf( pErr, "\t-v : toggle printing verbose information [default = %s]\n", fVerbose? "yes": "no" );
+ fprintf( pErr, "\t-h : print the command usage\n");
+ return 1;
+}
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Abc_CommandQuaRel( Abc_Frame_t * pAbc, int argc, char ** argv )
+{
+ FILE * pOut, * pErr;
+ Abc_Ntk_t * pNtk, * pNtkRes;
+ int c, iVar, fInputs, fVerbose;
+ extern Abc_Ntk_t * Abc_NtkTransRel( Abc_Ntk_t * pNtk, int fInputs, int fVerbose );
+
+ pNtk = Abc_FrameReadNtk(pAbc);
+ pOut = Abc_FrameReadOut(pAbc);
+ pErr = Abc_FrameReadErr(pAbc);
+
+ // set defaults
+ iVar = 0;
+ fInputs = 1;
+ fVerbose = 0;
+ Extra_UtilGetoptReset();
+ while ( ( c = Extra_UtilGetopt( argc, argv, "Iqvh" ) ) != EOF )
+ {
+ switch ( c )
+ {
+ case 'I':
+ if ( globalUtilOptind >= argc )
+ {
+ fprintf( pErr, "Command line switch \"-I\" should be followed by an integer.\n" );
+ goto usage;
+ }
+ iVar = atoi(argv[globalUtilOptind]);
+ globalUtilOptind++;
+ if ( iVar < 0 )
+ goto usage;
+ break;
+ case 'q':
+ fInputs ^= 1;
+ break;
+ case 'v':
+ fVerbose ^= 1;
+ break;
+ case 'h':
+ goto usage;
+ default:
+ goto usage;
+ }
+ }
+ if ( pNtk == NULL )
+ {
+ fprintf( pErr, "Empty network.\n" );
+ return 1;
+ }
+ if ( Abc_NtkGetChoiceNum( pNtk ) )
+ {
+ fprintf( pErr, "This command cannot be applied to an AIG with choice nodes.\n" );
+ return 1;
+ }
+ if ( Abc_NtkIsComb(pNtk) )
+ {
+ fprintf( pErr, "This command works only for sequential circuits.\n" );
+ return 1;
+ }
+
+ // get the strashed network
+ if ( !Abc_NtkIsStrash(pNtk) )
+ {
+ pNtk = Abc_NtkStrash( pNtk, 0, 1, 0 );
+ pNtkRes = Abc_NtkTransRel( pNtk, fInputs, fVerbose );
+ Abc_NtkDelete( pNtk );
+ }
+ else
+ pNtkRes = Abc_NtkTransRel( pNtk, fInputs, fVerbose );
+ // check if the result is available
+ if ( pNtkRes == NULL )
+ {
+ fprintf( pErr, "Command has failed.\n" );
+ return 0;
+ }
+ // replace the current network
+ Abc_FrameReplaceCurrentNetwork( pAbc, pNtkRes );
+ return 0;
+
+usage:
+ fprintf( pErr, "usage: qrel [-qvh]\n" );
+ fprintf( pErr, "\t computes transition relation of the sequential network\n" );
+// fprintf( pErr, "\t-I num : the zero-based index of a variable to quantify [default = %d]\n", iVar );
+ fprintf( pErr, "\t-q : perform quantification of inputs [default = %s]\n", fInputs? "yes": "no" );
+ fprintf( pErr, "\t-v : toggle printing verbose information [default = %s]\n", fVerbose? "yes": "no" );
+ fprintf( pErr, "\t-h : print the command usage\n");
+ return 1;
+}
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Abc_CommandQuaReach( Abc_Frame_t * pAbc, int argc, char ** argv )
+{
+ FILE * pOut, * pErr;
+ Abc_Ntk_t * pNtk, * pNtkRes;
+ int c, nIters, fVerbose;
+ extern Abc_Ntk_t * Abc_NtkReachability( Abc_Ntk_t * pNtk, int nIters, int fVerbose );
+
+ pNtk = Abc_FrameReadNtk(pAbc);
+ pOut = Abc_FrameReadOut(pAbc);
+ pErr = Abc_FrameReadErr(pAbc);
+
+ // set defaults
+ nIters = 256;
+ fVerbose = 0;
+ Extra_UtilGetoptReset();
+ while ( ( c = Extra_UtilGetopt( argc, argv, "Ivh" ) ) != EOF )
+ {
+ switch ( c )
+ {
+ case 'I':
+ if ( globalUtilOptind >= argc )
+ {
+ fprintf( pErr, "Command line switch \"-I\" should be followed by an integer.\n" );
+ goto usage;
+ }
+ nIters = atoi(argv[globalUtilOptind]);
+ globalUtilOptind++;
+ if ( nIters < 0 )
+ goto usage;
+ break;
+ case 'v':
+ fVerbose ^= 1;
+ break;
+ case 'h':
+ goto usage;
+ default:
+ goto usage;
+ }
+ }
+ if ( pNtk == NULL )
+ {
+ fprintf( pErr, "Empty network.\n" );
+ return 1;
+ }
+ if ( Abc_NtkGetChoiceNum( pNtk ) )
+ {
+ fprintf( pErr, "This command cannot be applied to an AIG with choice nodes.\n" );
+ return 1;
+ }
+ if ( !Abc_NtkIsComb(pNtk) )
+ {
+ fprintf( pErr, "This command works only for combinational transition relations.\n" );
+ return 1;
+ }
+ if ( !Abc_NtkIsStrash(pNtk) )
+ {
+ fprintf( pErr, "This command works only for strashed networks.\n" );
+ return 1;
+ }
+ if ( Abc_NtkPoNum(pNtk) > 1 )
+ {
+ fprintf( pErr, "The transition relation should have one output.\n" );
+ return 1;
+ }
+ if ( Abc_NtkPiNum(pNtk) % 2 != 0 )
+ {
+ fprintf( pErr, "The transition relation should have an even number of inputs.\n" );
+ return 1;
+ }
+
+ pNtkRes = Abc_NtkReachability( pNtk, nIters, fVerbose );
+ if ( pNtkRes == NULL )
+ {
+ fprintf( pErr, "Command has failed.\n" );
+ return 0;
+ }
+ // replace the current network
+ Abc_FrameReplaceCurrentNetwork( pAbc, pNtkRes );
+ return 0;
+
+usage:
+ fprintf( pErr, "usage: qreach [-I num] [-vh]\n" );
+ fprintf( pErr, "\t computes unreachable states using AIG-based quantification\n" );
+ fprintf( pErr, "\t assumes that the current network is a transition relation\n" );
+ fprintf( pErr, "\t assumes that the initial state is composed of all zeros\n" );
+ fprintf( pErr, "\t-I num : the number of image computations to perform [default = %d]\n", nIters );
+ fprintf( pErr, "\t-v : toggle printing verbose information [default = %s]\n", fVerbose? "yes": "no" );
+ fprintf( pErr, "\t-h : print the command usage\n");
+ return 1;
+}
+
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Abc_CommandIStrash( Abc_Frame_t * pAbc, int argc, char ** argv )
+{
+ FILE * pOut, * pErr;
+ Abc_Ntk_t * pNtk, * pNtkRes, * pNtkTemp;
+ int c;
+ extern Abc_Ntk_t * Abc_NtkIvyStrash( Abc_Ntk_t * pNtk );
+
+ pNtk = Abc_FrameReadNtk(pAbc);
+ pOut = Abc_FrameReadOut(pAbc);
+ pErr = Abc_FrameReadErr(pAbc);
+
+ // set defaults
+ Extra_UtilGetoptReset();
+ while ( ( c = Extra_UtilGetopt( argc, argv, "h" ) ) != EOF )
+ {
+ switch ( c )
+ {
+ case 'h':
+ goto usage;
+ default:
+ goto usage;
+ }
+ }
+ if ( pNtk == NULL )
+ {
+ fprintf( pErr, "Empty network.\n" );
+ return 1;
+ }
+ if ( !Abc_NtkIsStrash(pNtk) )
+ {
+ pNtkTemp = Abc_NtkStrash( pNtk, 0, 1, 0 );
+ pNtkRes = Abc_NtkIvyStrash( pNtkTemp );
+ Abc_NtkDelete( pNtkTemp );
+ }
+ else
+ pNtkRes = Abc_NtkIvyStrash( pNtk );
+ if ( pNtkRes == NULL )
+ {
+ fprintf( pErr, "Command has failed.\n" );
+ return 0;
+ }
+ // replace the current network
+ Abc_FrameReplaceCurrentNetwork( pAbc, pNtkRes );
+ return 0;
+
+usage:
+ fprintf( pErr, "usage: istrash [-h]\n" );
+ fprintf( pErr, "\t perform sequential structural hashing\n" );
+ fprintf( pErr, "\t-h : print the command usage\n");
+ return 1;
+}
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Abc_CommandICut( Abc_Frame_t * pAbc, int argc, char ** argv )
+{
+ FILE * pOut, * pErr;
+ Abc_Ntk_t * pNtk;
+ int c, nInputs;
+ extern void Abc_NtkIvyCuts( Abc_Ntk_t * pNtk, int nInputs );
+
+ pNtk = Abc_FrameReadNtk(pAbc);
+ pOut = Abc_FrameReadOut(pAbc);
+ pErr = Abc_FrameReadErr(pAbc);
+
+ // set defaults
+ nInputs = 5;
+ Extra_UtilGetoptReset();
+ while ( ( c = Extra_UtilGetopt( argc, argv, "Kh" ) ) != EOF )
+ {
+ switch ( c )
+ {
+ case 'K':
+ if ( globalUtilOptind >= argc )
+ {
+ fprintf( pErr, "Command line switch \"-K\" should be followed by an integer.\n" );
+ goto usage;
+ }
+ nInputs = atoi(argv[globalUtilOptind]);
+ globalUtilOptind++;
+ if ( nInputs < 0 )
+ goto usage;
+ break;
+ case 'h':
+ goto usage;
+ default:
+ goto usage;
+ }
+ }
+ if ( pNtk == NULL )
+ {
+ fprintf( pErr, "Empty network.\n" );
+ return 1;
+ }
+ if ( !Abc_NtkIsStrash(pNtk) )
+ {
+ fprintf( pErr, "This command works only for strashed networks.\n" );
+ return 1;
+ }
+
+ Abc_NtkIvyCuts( pNtk, nInputs );
+ return 0;
+
+usage:
+ fprintf( pErr, "usage: icut [-K num] [-h]\n" );
+ fprintf( pErr, "\t computes sequential cuts of the given size\n" );
+ fprintf( pErr, "\t-K num : the number of cut inputs (2 <= num <= 6) [default = %d]\n", nInputs );
+ fprintf( pErr, "\t-h : print the command usage\n");
+ return 1;
+}
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Abc_CommandIRewrite( Abc_Frame_t * pAbc, int argc, char ** argv )
+{
+ FILE * pOut, * pErr;
+ Abc_Ntk_t * pNtk, * pNtkRes;
+ int c, fUpdateLevel, fUseZeroCost, fVerbose;
+ extern Abc_Ntk_t * Abc_NtkIvyRewrite( Abc_Ntk_t * pNtk, int fUpdateLevel, int fUseZeroCost, int fVerbose );
+
+ pNtk = Abc_FrameReadNtk(pAbc);
+ pOut = Abc_FrameReadOut(pAbc);
+ pErr = Abc_FrameReadErr(pAbc);
+
+ // set defaults
+ fUpdateLevel = 1;
+ fUseZeroCost = 0;
+ fVerbose = 0;
+ Extra_UtilGetoptReset();
+ while ( ( c = Extra_UtilGetopt( argc, argv, "lzvh" ) ) != EOF )
+ {
+ switch ( c )
+ {
+ case 'l':
+ fUpdateLevel ^= 1;
+ break;
+ case 'z':
+ fUseZeroCost ^= 1;
+ break;
+ case 'v':
+ fVerbose ^= 1;
+ break;
+ case 'h':
+ goto usage;
+ default:
+ goto usage;
+ }
+ }
+ if ( pNtk == NULL )
+ {
+ fprintf( pErr, "Empty network.\n" );
+ return 1;
+ }
+ if ( !Abc_NtkIsStrash(pNtk) )
+ {
+ fprintf( pErr, "This command works only for strashed networks.\n" );
+ return 1;
+ }
+
+ pNtkRes = Abc_NtkIvyRewrite( pNtk, fUpdateLevel, fUseZeroCost, fVerbose );
+ if ( pNtkRes == NULL )
+ {
+ fprintf( pErr, "Command has failed.\n" );
+ return 0;
+ }
+ // replace the current network
+ Abc_FrameReplaceCurrentNetwork( pAbc, pNtkRes );
+ return 0;
+
+usage:
+ fprintf( pErr, "usage: irw [-lzvh]\n" );
+ fprintf( pErr, "\t perform combinational AIG rewriting\n" );
+ fprintf( pErr, "\t-l : toggle preserving the number of levels [default = %s]\n", fUpdateLevel? "yes": "no" );
+ fprintf( pErr, "\t-z : toggle using zero-cost replacements [default = %s]\n", fUseZeroCost? "yes": "no" );
+ fprintf( pErr, "\t-v : toggle verbose printout [default = %s]\n", fVerbose? "yes": "no" );
+ fprintf( pErr, "\t-h : print the command usage\n");
+ return 1;
+}
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Abc_CommandDRewrite( Abc_Frame_t * pAbc, int argc, char ** argv )
+{
+ FILE * pOut, * pErr;
+ Abc_Ntk_t * pNtk, * pNtkRes;
+ Dar_RwrPar_t Pars, * pPars = &Pars;
+ int c;
+
+ extern Abc_Ntk_t * Abc_NtkDRewrite( Abc_Ntk_t * pNtk, Dar_RwrPar_t * pPars );
+
+ pNtk = Abc_FrameReadNtk(pAbc);
+ pOut = Abc_FrameReadOut(pAbc);
+ pErr = Abc_FrameReadErr(pAbc);
+
+ // set defaults
+ Dar_ManDefaultRwrParams( pPars );
+ Extra_UtilGetoptReset();
+ while ( ( c = Extra_UtilGetopt( argc, argv, "CNflzvwh" ) ) != EOF )
+ {
+ switch ( c )
+ {
+ case 'C':
+ if ( globalUtilOptind >= argc )
+ {
+ fprintf( pErr, "Command line switch \"-C\" should be followed by an integer.\n" );
+ goto usage;
+ }
+ pPars->nCutsMax = atoi(argv[globalUtilOptind]);
+ globalUtilOptind++;
+ if ( pPars->nCutsMax < 0 )
+ goto usage;
+ break;
+ case 'N':
+ if ( globalUtilOptind >= argc )
+ {
+ fprintf( pErr, "Command line switch \"-N\" should be followed by an integer.\n" );
+ goto usage;
+ }
+ pPars->nSubgMax = atoi(argv[globalUtilOptind]);
+ globalUtilOptind++;
+ if ( pPars->nSubgMax < 0 )
+ goto usage;
+ break;
+ case 'f':
+ pPars->fFanout ^= 1;
+ break;
+ case 'l':
+ pPars->fUpdateLevel ^= 1;
+ break;
+ case 'z':
+ pPars->fUseZeros ^= 1;
+ break;
+ case 'v':
+ pPars->fVerbose ^= 1;
+ break;
+ case 'w':
+ pPars->fVeryVerbose ^= 1;
+ break;
+ case 'h':
+ goto usage;
+ default:
+ goto usage;
+ }
+ }
+ if ( pNtk == NULL )
+ {
+ fprintf( pErr, "Empty network.\n" );
+ return 1;
+ }
+ if ( !Abc_NtkIsStrash(pNtk) )
+ {
+ fprintf( pErr, "This command works only for strashed networks.\n" );
+ return 1;
+ }
+ pNtkRes = Abc_NtkDRewrite( pNtk, pPars );
+ if ( pNtkRes == NULL )
+ {
+ fprintf( pErr, "Command has failed.\n" );
+ return 0;
+ }
+ // replace the current network
+ Abc_FrameReplaceCurrentNetwork( pAbc, pNtkRes );
+ return 0;
+
+usage:
+ fprintf( pErr, "usage: drw [-C num] [-N num] [-flzvwh]\n" );
+ fprintf( pErr, "\t performs combinational AIG rewriting\n" );
+ fprintf( pErr, "\t-C num : the max number of cuts at a node [default = %d]\n", pPars->nCutsMax );
+ fprintf( pErr, "\t-N num : the max number of subgraphs tried [default = %d]\n", pPars->nSubgMax );
+ fprintf( pErr, "\t-f : toggle representing fanouts [default = %s]\n", pPars->fFanout? "yes": "no" );
+ fprintf( pErr, "\t-l : toggle preserving the number of levels [default = %s]\n", pPars->fUpdateLevel? "yes": "no" );
+ fprintf( pErr, "\t-z : toggle using zero-cost replacements [default = %s]\n", pPars->fUseZeros? "yes": "no" );
+ fprintf( pErr, "\t-v : toggle verbose printout [default = %s]\n", pPars->fVerbose? "yes": "no" );
+ fprintf( pErr, "\t-w : toggle very verbose printout [default = %s]\n", pPars->fVeryVerbose? "yes": "no" );
fprintf( pErr, "\t-h : print the command usage\n");
return 1;
}
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Abc_CommandDRefactor( Abc_Frame_t * pAbc, int argc, char ** argv )
+{
+ FILE * pOut, * pErr;
+ Abc_Ntk_t * pNtk, * pNtkRes;
+ Dar_RefPar_t Pars, * pPars = &Pars;
+ int c;
+
+ extern Abc_Ntk_t * Abc_NtkDRefactor( Abc_Ntk_t * pNtk, Dar_RefPar_t * pPars );
+ pNtk = Abc_FrameReadNtk(pAbc);
+ pOut = Abc_FrameReadOut(pAbc);
+ pErr = Abc_FrameReadErr(pAbc);
+
+ // set defaults
+ Dar_ManDefaultRefParams( pPars );
+ Extra_UtilGetoptReset();
+ while ( ( c = Extra_UtilGetopt( argc, argv, "MKCelzvwh" ) ) != EOF )
+ {
+ switch ( c )
+ {
+ case 'M':
+ if ( globalUtilOptind >= argc )
+ {
+ fprintf( pErr, "Command line switch \"-C\" should be followed by an integer.\n" );
+ goto usage;
+ }
+ pPars->nMffcMin = atoi(argv[globalUtilOptind]);
+ globalUtilOptind++;
+ if ( pPars->nMffcMin < 0 )
+ goto usage;
+ break;
+ case 'K':
+ if ( globalUtilOptind >= argc )
+ {
+ fprintf( pErr, "Command line switch \"-N\" should be followed by an integer.\n" );
+ goto usage;
+ }
+ pPars->nLeafMax = atoi(argv[globalUtilOptind]);
+ globalUtilOptind++;
+ if ( pPars->nLeafMax < 0 )
+ goto usage;
+ break;
+ case 'C':
+ if ( globalUtilOptind >= argc )
+ {
+ fprintf( pErr, "Command line switch \"-C\" should be followed by an integer.\n" );
+ goto usage;
+ }
+ pPars->nCutsMax = atoi(argv[globalUtilOptind]);
+ globalUtilOptind++;
+ if ( pPars->nCutsMax < 0 )
+ goto usage;
+ break;
+ case 'e':
+ pPars->fExtend ^= 1;
+ break;
+ case 'l':
+ pPars->fUpdateLevel ^= 1;
+ break;
+ case 'z':
+ pPars->fUseZeros ^= 1;
+ break;
+ case 'v':
+ pPars->fVerbose ^= 1;
+ break;
+ case 'w':
+ pPars->fVeryVerbose ^= 1;
+ break;
+ case 'h':
+ goto usage;
+ default:
+ goto usage;
+ }
+ }
+ if ( pNtk == NULL )
+ {
+ fprintf( pErr, "Empty network.\n" );
+ return 1;
+ }
+ if ( !Abc_NtkIsStrash(pNtk) )
+ {
+ fprintf( pErr, "This command works only for strashed networks.\n" );
+ return 1;
+ }
+ if ( pPars->nLeafMax < 4 || pPars->nLeafMax > 15 )
+ {
+ fprintf( pErr, "This command only works for cut sizes 4 <= K <= 15.\n" );
+ return 1;
+ }
+ pNtkRes = Abc_NtkDRefactor( pNtk, pPars );
+ if ( pNtkRes == NULL )
+ {
+ fprintf( pErr, "Command has failed.\n" );
+ return 0;
+ }
+ // replace the current network
+ Abc_FrameReplaceCurrentNetwork( pAbc, pNtkRes );
+ return 0;
+
+usage:
+ fprintf( pErr, "usage: drf [-M num] [-K num] [-C num] [-elzvwh]\n" );
+ fprintf( pErr, "\t performs combinational AIG refactoring\n" );
+ fprintf( pErr, "\t-M num : the min MFFC size to attempt refactoring [default = %d]\n", pPars->nMffcMin );
+ fprintf( pErr, "\t-K num : the max number of cuts leaves [default = %d]\n", pPars->nLeafMax );
+ fprintf( pErr, "\t-C num : the max number of cuts to try at a node [default = %d]\n", pPars->nCutsMax );
+ fprintf( pErr, "\t-e : toggle extending tbe cut below MFFC [default = %s]\n", pPars->fExtend? "yes": "no" );
+ fprintf( pErr, "\t-l : toggle preserving the number of levels [default = %s]\n", pPars->fUpdateLevel? "yes": "no" );
+ fprintf( pErr, "\t-z : toggle using zero-cost replacements [default = %s]\n", pPars->fUseZeros? "yes": "no" );
+ fprintf( pErr, "\t-v : toggle verbose printout [default = %s]\n", pPars->fVerbose? "yes": "no" );
+ fprintf( pErr, "\t-w : toggle very verbose printout [default = %s]\n", pPars->fVeryVerbose? "yes": "no" );
+ fprintf( pErr, "\t-h : print the command usage\n");
+ return 1;
+}
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Abc_CommandDCompress2( Abc_Frame_t * pAbc, int argc, char ** argv )
+{
+ FILE * pOut, * pErr;
+ Abc_Ntk_t * pNtk, * pNtkRes;
+ int fBalance, fVerbose, fUpdateLevel, c;
+
+ extern Abc_Ntk_t * Abc_NtkDCompress2( Abc_Ntk_t * pNtk, int fBalance, int fUpdateLevel, int fVerbose );
+
+ pNtk = Abc_FrameReadNtk(pAbc);
+ pOut = Abc_FrameReadOut(pAbc);
+ pErr = Abc_FrameReadErr(pAbc);
+
+ // set defaults
+ fBalance = 0;
+ fVerbose = 0;
+ fUpdateLevel = 0;
+ Extra_UtilGetoptReset();
+ while ( ( c = Extra_UtilGetopt( argc, argv, "blvh" ) ) != EOF )
+ {
+ switch ( c )
+ {
+ case 'b':
+ fBalance ^= 1;
+ break;
+ case 'l':
+ fUpdateLevel ^= 1;
+ break;
+ case 'v':
+ fVerbose ^= 1;
+ break;
+ case 'h':
+ goto usage;
+ default:
+ goto usage;
+ }
+ }
+ if ( pNtk == NULL )
+ {
+ fprintf( pErr, "Empty network.\n" );
+ return 1;
+ }
+ if ( !Abc_NtkIsStrash(pNtk) )
+ {
+ fprintf( pErr, "This command works only for strashed networks.\n" );
+ return 1;
+ }
+ pNtkRes = Abc_NtkDCompress2( pNtk, fBalance, fUpdateLevel, fVerbose );
+ if ( pNtkRes == NULL )
+ {
+ fprintf( pErr, "Command has failed.\n" );
+ return 0;
+ }
+ // replace the current network
+ Abc_FrameReplaceCurrentNetwork( pAbc, pNtkRes );
+ return 0;
+
+usage:
+ fprintf( pErr, "usage: dcompress2 [-blvh]\n" );
+ fprintf( pErr, "\t performs combinational AIG optimization\n" );
+ fprintf( pErr, "\t-b : toggle internal balancing [default = %s]\n", fBalance? "yes": "no" );
+ fprintf( pErr, "\t-l : toggle updating level [default = %s]\n", fUpdateLevel? "yes": "no" );
+ fprintf( pErr, "\t-v : toggle verbose printout [default = %s]\n", fVerbose? "yes": "no" );
+ fprintf( pErr, "\t-h : print the command usage\n");
+ return 1;
+}
+
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Abc_CommandDChoice( Abc_Frame_t * pAbc, int argc, char ** argv )
+{
+ FILE * pOut, * pErr;
+ Abc_Ntk_t * pNtk, * pNtkRes;
+ int fBalance, fVerbose, fUpdateLevel, c;
+
+ extern Abc_Ntk_t * Abc_NtkDChoice( Abc_Ntk_t * pNtk, int fBalance, int fUpdateLevel, int fVerbose );
+
+ pNtk = Abc_FrameReadNtk(pAbc);
+ pOut = Abc_FrameReadOut(pAbc);
+ pErr = Abc_FrameReadErr(pAbc);
+
+ // set defaults
+ fBalance = 1;
+ fUpdateLevel = 1;
+ fVerbose = 0;
+ Extra_UtilGetoptReset();
+ while ( ( c = Extra_UtilGetopt( argc, argv, "blvh" ) ) != EOF )
+ {
+ switch ( c )
+ {
+ case 'b':
+ fBalance ^= 1;
+ break;
+ case 'l':
+ fUpdateLevel ^= 1;
+ break;
+ case 'v':
+ fVerbose ^= 1;
+ break;
+ case 'h':
+ goto usage;
+ default:
+ goto usage;
+ }
+ }
+ if ( pNtk == NULL )
+ {
+ fprintf( pErr, "Empty network.\n" );
+ return 1;
+ }
+ if ( !Abc_NtkIsStrash(pNtk) )
+ {
+ fprintf( pErr, "This command works only for strashed networks.\n" );
+ return 1;
+ }
+ pNtkRes = Abc_NtkDChoice( pNtk, fBalance, fUpdateLevel, fVerbose );
+ if ( pNtkRes == NULL )
+ {
+ fprintf( pErr, "Command has failed.\n" );
+ return 0;
+ }
+ // replace the current network
+ Abc_FrameReplaceCurrentNetwork( pAbc, pNtkRes );
+ return 0;
+
+usage:
+ fprintf( pErr, "usage: dchoice [-blvh]\n" );
+ fprintf( pErr, "\t performs partitioned choicing using a new AIG package\n" );
+ fprintf( pErr, "\t-b : toggle internal balancing [default = %s]\n", fBalance? "yes": "no" );
+ fprintf( pErr, "\t-l : toggle updating level [default = %s]\n", fUpdateLevel? "yes": "no" );
+ fprintf( pErr, "\t-v : toggle verbose printout [default = %s]\n", fVerbose? "yes": "no" );
+ fprintf( pErr, "\t-h : print the command usage\n");
+ return 1;
+}
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Abc_CommandDrwsat( Abc_Frame_t * pAbc, int argc, char ** argv )
+{
+ FILE * pOut, * pErr;
+ Abc_Ntk_t * pNtk, * pNtkRes;
+ int fBalance, fVerbose, c;
+
+ extern Abc_Ntk_t * Abc_NtkDrwsat( Abc_Ntk_t * pNtk, int fBalance, int fVerbose );
+
+ pNtk = Abc_FrameReadNtk(pAbc);
+ pOut = Abc_FrameReadOut(pAbc);
+ pErr = Abc_FrameReadErr(pAbc);
+
+ // set defaults
+ fBalance = 0;
+ fVerbose = 0;
+ Extra_UtilGetoptReset();
+ while ( ( c = Extra_UtilGetopt( argc, argv, "bvh" ) ) != EOF )
+ {
+ switch ( c )
+ {
+ case 'b':
+ fBalance ^= 1;
+ break;
+ case 'v':
+ fVerbose ^= 1;
+ break;
+ case 'h':
+ goto usage;
+ default:
+ goto usage;
+ }
+ }
+ if ( pNtk == NULL )
+ {
+ fprintf( pErr, "Empty network.\n" );
+ return 1;
+ }
+ if ( !Abc_NtkIsStrash(pNtk) )
+ {
+ fprintf( pErr, "This command works only for strashed networks.\n" );
+ return 1;
+ }
+ pNtkRes = Abc_NtkDrwsat( pNtk, fBalance, fVerbose );
+ if ( pNtkRes == NULL )
+ {
+ fprintf( pErr, "Command has failed.\n" );
+ return 0;
+ }
+ // replace the current network
+ Abc_FrameReplaceCurrentNetwork( pAbc, pNtkRes );
+ return 0;
+
+usage:
+ fprintf( pErr, "usage: drwsat [-bvh]\n" );
+ fprintf( pErr, "\t performs combinational AIG optimization for SAT\n" );
+ fprintf( pErr, "\t-b : toggle internal balancing [default = %s]\n", fBalance? "yes": "no" );
+ fprintf( pErr, "\t-v : toggle verbose printout [default = %s]\n", fVerbose? "yes": "no" );
+ fprintf( pErr, "\t-h : print the command usage\n");
+ return 1;
+}
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Abc_CommandIRewriteSeq( Abc_Frame_t * pAbc, int argc, char ** argv )
+{
+ FILE * pOut, * pErr;
+ Abc_Ntk_t * pNtk, * pNtkRes;
+ int c, fUpdateLevel, fUseZeroCost, fVerbose;
+ extern Abc_Ntk_t * Abc_NtkIvyRewriteSeq( Abc_Ntk_t * pNtk, int fUseZeroCost, int fVerbose );
+
+ pNtk = Abc_FrameReadNtk(pAbc);
+ pOut = Abc_FrameReadOut(pAbc);
+ pErr = Abc_FrameReadErr(pAbc);
+
+ // set defaults
+ fUpdateLevel = 0;
+ fUseZeroCost = 0;
+ fVerbose = 0;
+ Extra_UtilGetoptReset();
+ while ( ( c = Extra_UtilGetopt( argc, argv, "lzvh" ) ) != EOF )
+ {
+ switch ( c )
+ {
+ case 'l':
+ fUpdateLevel ^= 1;
+ break;
+ case 'z':
+ fUseZeroCost ^= 1;
+ break;
+ case 'v':
+ fVerbose ^= 1;
+ break;
+ case 'h':
+ goto usage;
+ default:
+ goto usage;
+ }
+ }
+ if ( pNtk == NULL )
+ {
+ fprintf( pErr, "Empty network.\n" );
+ return 1;
+ }
+ if ( !Abc_NtkIsStrash(pNtk) )
+ {
+ fprintf( pErr, "This command works only for strashed networks.\n" );
+ return 1;
+ }
+
+ pNtkRes = Abc_NtkIvyRewriteSeq( pNtk, fUseZeroCost, fVerbose );
+ if ( pNtkRes == NULL )
+ {
+ fprintf( pErr, "Command has failed.\n" );
+ return 0;
+ }
+ // replace the current network
+ Abc_FrameReplaceCurrentNetwork( pAbc, pNtkRes );
+ return 0;
+
+usage:
+ fprintf( pErr, "usage: irws [-zvh]\n" );
+ fprintf( pErr, "\t perform sequential AIG rewriting\n" );
+// fprintf( pErr, "\t-l : toggle preserving the number of levels [default = %s]\n", fUpdateLevel? "yes": "no" );
+ fprintf( pErr, "\t-z : toggle using zero-cost replacements [default = %s]\n", fUseZeroCost? "yes": "no" );
+ fprintf( pErr, "\t-v : toggle verbose printout [default = %s]\n", fVerbose? "yes": "no" );
+ fprintf( pErr, "\t-h : print the command usage\n");
+ return 1;
+}
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Abc_CommandIResyn( Abc_Frame_t * pAbc, int argc, char ** argv )
+{
+ FILE * pOut, * pErr;
+ Abc_Ntk_t * pNtk, * pNtkRes;
+ int c, fUpdateLevel, fVerbose;
+ extern Abc_Ntk_t * Abc_NtkIvyResyn( Abc_Ntk_t * pNtk, int fUpdateLevel, int fVerbose );
+
+ pNtk = Abc_FrameReadNtk(pAbc);
+ pOut = Abc_FrameReadOut(pAbc);
+ pErr = Abc_FrameReadErr(pAbc);
+
+ // set defaults
+ fUpdateLevel = 1;
+ fVerbose = 0;
+ Extra_UtilGetoptReset();
+ while ( ( c = Extra_UtilGetopt( argc, argv, "lzvh" ) ) != EOF )
+ {
+ switch ( c )
+ {
+ case 'l':
+ fUpdateLevel ^= 1;
+ break;
+ case 'v':
+ fVerbose ^= 1;
+ break;
+ case 'h':
+ goto usage;
+ default:
+ goto usage;
+ }
+ }
+ if ( pNtk == NULL )
+ {
+ fprintf( pErr, "Empty network.\n" );
+ return 1;
+ }
+ if ( !Abc_NtkIsStrash(pNtk) )
+ {
+ fprintf( pErr, "This command works only for strashed networks.\n" );
+ return 1;
+ }
+
+ pNtkRes = Abc_NtkIvyResyn( pNtk, fUpdateLevel, fVerbose );
+ if ( pNtkRes == NULL )
+ {
+ fprintf( pErr, "Command has failed.\n" );
+ return 0;
+ }
+ // replace the current network
+ Abc_FrameReplaceCurrentNetwork( pAbc, pNtkRes );
+ return 0;
+
+usage:
+ fprintf( pErr, "usage: iresyn [-lvh]\n" );
+ fprintf( pErr, "\t performs combinational resynthesis\n" );
+ fprintf( pErr, "\t-l : toggle preserving the number of levels [default = %s]\n", fUpdateLevel? "yes": "no" );
+ fprintf( pErr, "\t-v : toggle verbose printout [default = %s]\n", fVerbose? "yes": "no" );
+ fprintf( pErr, "\t-h : print the command usage\n");
+ return 1;
+}
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Abc_CommandISat( Abc_Frame_t * pAbc, int argc, char ** argv )
+{
+ FILE * pOut, * pErr;
+ Abc_Ntk_t * pNtk, * pNtkRes;
+ int c, fUpdateLevel, fVerbose;
+ int nConfLimit;
+
+ extern Abc_Ntk_t * Abc_NtkIvySat( Abc_Ntk_t * pNtk, int nConfLimit, int fVerbose );
+
+ pNtk = Abc_FrameReadNtk(pAbc);
+ pOut = Abc_FrameReadOut(pAbc);
+ pErr = Abc_FrameReadErr(pAbc);
+
+ // set defaults
+ nConfLimit = 100000;
+ fUpdateLevel = 1;
+ fVerbose = 0;
+ Extra_UtilGetoptReset();
+ while ( ( c = Extra_UtilGetopt( argc, argv, "Clzvh" ) ) != EOF )
+ {
+ switch ( c )
+ {
+ case 'C':
+ if ( globalUtilOptind >= argc )
+ {
+ fprintf( pErr, "Command line switch \"-C\" should be followed by an integer.\n" );
+ goto usage;
+ }
+ nConfLimit = atoi(argv[globalUtilOptind]);
+ globalUtilOptind++;
+ if ( nConfLimit < 0 )
+ goto usage;
+ break;
+ case 'l':
+ fUpdateLevel ^= 1;
+ break;
+ case 'v':
+ fVerbose ^= 1;
+ break;
+ case 'h':
+ goto usage;
+ default:
+ goto usage;
+ }
+ }
+ if ( pNtk == NULL )
+ {
+ fprintf( pErr, "Empty network.\n" );
+ return 1;
+ }
+ if ( !Abc_NtkIsStrash(pNtk) )
+ {
+ fprintf( pErr, "This command works only for strashed networks.\n" );
+ return 1;
+ }
+
+ pNtkRes = Abc_NtkIvySat( pNtk, nConfLimit, fVerbose );
+ if ( pNtkRes == NULL )
+ {
+ fprintf( pErr, "Command has failed.\n" );
+ return 0;
+ }
+ // replace the current network
+ Abc_FrameReplaceCurrentNetwork( pAbc, pNtkRes );
+ return 0;
+
+usage:
+ fprintf( pErr, "usage: isat [-C num] [-vh]\n" );
+ fprintf( pErr, "\t tries to prove the miter constant 0\n" );
+ fprintf( pErr, "\t-C num : limit on the number of conflicts [default = %d]\n", nConfLimit );
+// fprintf( pErr, "\t-l : toggle preserving the number of levels [default = %s]\n", fUpdateLevel? "yes": "no" );
+ fprintf( pErr, "\t-v : toggle verbose printout [default = %s]\n", fVerbose? "yes": "no" );
+ fprintf( pErr, "\t-h : print the command usage\n");
+ return 1;
+}
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Abc_CommandIFraig( Abc_Frame_t * pAbc, int argc, char ** argv )
+{
+ FILE * pOut, * pErr;
+ Abc_Ntk_t * pNtk, * pNtkRes;
+ int c, fProve, fVerbose, fDoSparse;
+ int nConfLimit;
+
+ extern Abc_Ntk_t * Abc_NtkIvyFraig( Abc_Ntk_t * pNtk, int nConfLimit, int fDoSparse, int fProve, int fTransfer, int fVerbose );
+
+ pNtk = Abc_FrameReadNtk(pAbc);
+ pOut = Abc_FrameReadOut(pAbc);
+ pErr = Abc_FrameReadErr(pAbc);
+
+ // set defaults
+ nConfLimit = 100;
+ fDoSparse = 0;
+ fProve = 0;
+ fVerbose = 0;
+ Extra_UtilGetoptReset();
+ while ( ( c = Extra_UtilGetopt( argc, argv, "Cspvh" ) ) != EOF )
+ {
+ switch ( c )
+ {
+ case 'C':
+ if ( globalUtilOptind >= argc )
+ {
+ fprintf( pErr, "Command line switch \"-C\" should be followed by an integer.\n" );
+ goto usage;
+ }
+ nConfLimit = atoi(argv[globalUtilOptind]);
+ globalUtilOptind++;
+ if ( nConfLimit < 0 )
+ goto usage;
+ break;
+ case 's':
+ fDoSparse ^= 1;
+ break;
+ case 'p':
+ fProve ^= 1;
+ break;
+ case 'v':
+ fVerbose ^= 1;
+ break;
+ case 'h':
+ goto usage;
+ default:
+ goto usage;
+ }
+ }
+ if ( pNtk == NULL )
+ {
+ fprintf( pErr, "Empty network.\n" );
+ return 1;
+ }
+ if ( !Abc_NtkIsStrash(pNtk) )
+ {
+ fprintf( pErr, "This command works only for strashed networks.\n" );
+ return 1;
+ }
+
+ pNtkRes = Abc_NtkIvyFraig( pNtk, nConfLimit, fDoSparse, fProve, 0, fVerbose );
+ if ( pNtkRes == NULL )
+ {
+ fprintf( pErr, "Command has failed.\n" );
+ return 0;
+ }
+ // replace the current network
+ Abc_FrameReplaceCurrentNetwork( pAbc, pNtkRes );
+ return 0;
+
+usage:
+ fprintf( pErr, "usage: ifraig [-C num] [-spvh]\n" );
+ fprintf( pErr, "\t performs fraiging using a new method\n" );
+ fprintf( pErr, "\t-C num : limit on the number of conflicts [default = %d]\n", nConfLimit );
+ fprintf( pErr, "\t-s : toggle considering sparse functions [default = %s]\n", fDoSparse? "yes": "no" );
+ fprintf( pErr, "\t-p : toggle proving the miter outputs [default = %s]\n", fProve? "yes": "no" );
+ fprintf( pErr, "\t-v : toggle verbose printout [default = %s]\n", fVerbose? "yes": "no" );
+ fprintf( pErr, "\t-h : print the command usage\n");
+ return 1;
+}
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Abc_CommandDFraig( Abc_Frame_t * pAbc, int argc, char ** argv )
+{
+ FILE * pOut, * pErr;
+ Abc_Ntk_t * pNtk, * pNtkRes;
+ int c, nConfLimit, fDoSparse, fProve, fSpeculate, fChoicing, fVerbose;
+
+ extern Abc_Ntk_t * Abc_NtkDarFraig( Abc_Ntk_t * pNtk, int nConfLimit, int fDoSparse, int fProve, int fTransfer, int fSpeculate, int fChoicing, int fVerbose );
+
+ pNtk = Abc_FrameReadNtk(pAbc);
+ pOut = Abc_FrameReadOut(pAbc);
+ pErr = Abc_FrameReadErr(pAbc);
+
+ // set defaults
+ nConfLimit = 100;
+ fDoSparse = 1;
+ fProve = 0;
+ fSpeculate = 0;
+ fChoicing = 0;
+ fVerbose = 0;
+ Extra_UtilGetoptReset();
+ while ( ( c = Extra_UtilGetopt( argc, argv, "Csprcvh" ) ) != EOF )
+ {
+ switch ( c )
+ {
+ case 'C':
+ if ( globalUtilOptind >= argc )
+ {
+ fprintf( pErr, "Command line switch \"-C\" should be followed by an integer.\n" );
+ goto usage;
+ }
+ nConfLimit = atoi(argv[globalUtilOptind]);
+ globalUtilOptind++;
+ if ( nConfLimit < 0 )
+ goto usage;
+ break;
+ case 's':
+ fDoSparse ^= 1;
+ break;
+ case 'p':
+ fProve ^= 1;
+ break;
+ case 'r':
+ fSpeculate ^= 1;
+ break;
+ case 'c':
+ fChoicing ^= 1;
+ break;
+ case 'v':
+ fVerbose ^= 1;
+ break;
+ case 'h':
+ goto usage;
+ default:
+ goto usage;
+ }
+ }
+ if ( pNtk == NULL )
+ {
+ fprintf( pErr, "Empty network.\n" );
+ return 1;
+ }
+ if ( !Abc_NtkIsStrash(pNtk) )
+ {
+ fprintf( pErr, "This command works only for strashed networks.\n" );
+ return 1;
+ }
+
+ pNtkRes = Abc_NtkDarFraig( pNtk, nConfLimit, fDoSparse, fProve, 0, fSpeculate, fChoicing, fVerbose );
+ if ( pNtkRes == NULL )
+ {
+ fprintf( pErr, "Command has failed.\n" );
+ return 0;
+ }
+ // replace the current network
+ Abc_FrameReplaceCurrentNetwork( pAbc, pNtkRes );
+ return 0;
+
+usage:
+ fprintf( pErr, "usage: dfraig [-C num] [-sprcvh]\n" );
+ fprintf( pErr, "\t performs fraiging using a new method\n" );
+ fprintf( pErr, "\t-C num : limit on the number of conflicts [default = %d]\n", nConfLimit );
+ fprintf( pErr, "\t-s : toggle considering sparse functions [default = %s]\n", fDoSparse? "yes": "no" );
+ fprintf( pErr, "\t-p : toggle proving the miter outputs [default = %s]\n", fProve? "yes": "no" );
+ fprintf( pErr, "\t-r : toggle speculative reduction [default = %s]\n", fSpeculate? "yes": "no" );
+ fprintf( pErr, "\t-c : toggle accumulation of choices [default = %s]\n", fChoicing? "yes": "no" );
+ fprintf( pErr, "\t-v : toggle verbose printout [default = %s]\n", fVerbose? "yes": "no" );
+ fprintf( pErr, "\t-h : print the command usage\n");
+ return 1;
+}
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Abc_CommandCSweep( Abc_Frame_t * pAbc, int argc, char ** argv )
+{
+ FILE * pOut, * pErr;
+ Abc_Ntk_t * pNtk, * pNtkRes;
+ int c, nCutsMax, nLeafMax, fVerbose;
+
+ extern Abc_Ntk_t * Abc_NtkCSweep( Abc_Ntk_t * pNtk, int nCutsMax, int nLeafMax, int fVerbose );
+
+ pNtk = Abc_FrameReadNtk(pAbc);
+ pOut = Abc_FrameReadOut(pAbc);
+ pErr = Abc_FrameReadErr(pAbc);
+
+ // set defaults
+ nCutsMax = 8;
+ nLeafMax = 6;
+ fVerbose = 0;
+ Extra_UtilGetoptReset();
+ while ( ( c = Extra_UtilGetopt( argc, argv, "CKvh" ) ) != EOF )
+ {
+ switch ( c )
+ {
+ case 'C':
+ if ( globalUtilOptind >= argc )
+ {
+ fprintf( pErr, "Command line switch \"-C\" should be followed by an integer.\n" );
+ goto usage;
+ }
+ nCutsMax = atoi(argv[globalUtilOptind]);
+ globalUtilOptind++;
+ if ( nCutsMax < 0 )
+ goto usage;
+ break;
+ case 'K':
+ if ( globalUtilOptind >= argc )
+ {
+ fprintf( pErr, "Command line switch \"-K\" should be followed by an integer.\n" );
+ goto usage;
+ }
+ nLeafMax = atoi(argv[globalUtilOptind]);
+ globalUtilOptind++;
+ if ( nLeafMax < 0 )
+ goto usage;
+ break;
+ case 'v':
+ fVerbose ^= 1;
+ break;
+ case 'h':
+ goto usage;
+ default:
+ goto usage;
+ }
+ }
+ if ( pNtk == NULL )
+ {
+ fprintf( pErr, "Empty network.\n" );
+ return 1;
+ }
+
+ if ( nCutsMax < 2 )
+ {
+ fprintf( pErr, "The number of cuts cannot be less than 2.\n" );
+ return 1;
+ }
+
+ if ( nLeafMax < 3 || nLeafMax > 16 )
+ {
+ fprintf( pErr, "The number of leaves is infeasible.\n" );
+ return 1;
+ }
+ if ( !Abc_NtkIsStrash(pNtk) )
+ {
+ fprintf( pErr, "This command works only for strashed networks.\n" );
+ return 1;
+ }
+
+ pNtkRes = Abc_NtkCSweep( pNtk, nCutsMax, nLeafMax, fVerbose );
+ if ( pNtkRes == NULL )
+ {
+ fprintf( pErr, "Command has failed.\n" );
+ return 0;
+ }
+ // replace the current network
+ Abc_FrameReplaceCurrentNetwork( pAbc, pNtkRes );
+ return 0;
+
+usage:
+ fprintf( pErr, "usage: csweep [-C num] [-K num] [-vh]\n" );
+ fprintf( pErr, "\t performs cut sweeping using a new method\n" );
+ fprintf( pErr, "\t-C num : limit on the number of cuts (C >= 2) [default = %d]\n", nCutsMax );
+ fprintf( pErr, "\t-K num : limit on the cut size (3 <= K <= 16) [default = %d]\n", nLeafMax );
+ fprintf( pErr, "\t-v : toggle verbose printout [default = %s]\n", fVerbose? "yes": "no" );
+ fprintf( pErr, "\t-h : print the command usage\n");
+ return 1;
+}
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Abc_CommandIProve( Abc_Frame_t * pAbc, int argc, char ** argv )
+{
+ Prove_Params_t Params, * pParams = &Params;
+ FILE * pOut, * pErr;
+ Abc_Ntk_t * pNtk, * pNtkTemp;
+ int c, clk, RetValue;
+
+ extern int Abc_NtkIvyProve( Abc_Ntk_t ** ppNtk, void * pPars );
+
+ pNtk = Abc_FrameReadNtk(pAbc);
+ pOut = Abc_FrameReadOut(pAbc);
+ pErr = Abc_FrameReadErr(pAbc);
+
+ // set defaults
+ Prove_ParamsSetDefault( pParams );
+ pParams->fUseRewriting = 1;
+ pParams->fVerbose = 0;
+ Extra_UtilGetoptReset();
+ while ( ( c = Extra_UtilGetopt( argc, argv, "rvh" ) ) != EOF )
+ {
+ switch ( c )
+ {
+ case 'r':
+ pParams->fUseRewriting ^= 1;
+ break;
+ case 'v':
+ pParams->fVerbose ^= 1;
+ break;
+ case 'h':
+ goto usage;
+ default:
+ goto usage;
+ }
+ }
+ if ( pNtk == NULL )
+ {
+ fprintf( pErr, "Empty network.\n" );
+ return 1;
+ }
+
+ clk = clock();
+
+ if ( Abc_NtkIsStrash(pNtk) )
+ pNtkTemp = Abc_NtkDup( pNtk );
+ else
+ pNtkTemp = Abc_NtkStrash( pNtk, 0, 0, 0 );
+
+ RetValue = Abc_NtkIvyProve( &pNtkTemp, pParams );
+
+ // verify that the pattern is correct
+ if ( RetValue == 0 )
+ {
+ int * pSimInfo = Abc_NtkVerifySimulatePattern( pNtk, pNtkTemp->pModel );
+ if ( pSimInfo[0] != 1 )
+ printf( "ERROR in Abc_NtkMiterProve(): Generated counter-example is invalid.\n" );
+ free( pSimInfo );
+ }
+
+ if ( RetValue == -1 )
+ printf( "UNDECIDED " );
+ else if ( RetValue == 0 )
+ printf( "SATISFIABLE " );
+ else
+ printf( "UNSATISFIABLE " );
+ //printf( "\n" );
+
+ PRT( "Time", clock() - clk );
+ // replace the current network
+ Abc_FrameReplaceCurrentNetwork( pAbc, pNtkTemp );
+ return 0;
+
+usage:
+ fprintf( pErr, "usage: iprove [-rvh]\n" );
+ fprintf( pErr, "\t performs CEC using a new method\n" );
+ fprintf( pErr, "\t-r : toggle AIG rewriting [default = %s]\n", pParams->fUseRewriting? "yes": "no" );
+ fprintf( pErr, "\t-v : toggle verbose printout [default = %s]\n", pParams->fVerbose? "yes": "no" );
+ fprintf( pErr, "\t-h : print the command usage\n");
+ return 1;
+}
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Abc_CommandHaig( Abc_Frame_t * pAbc, int argc, char ** argv )
+{
+ FILE * pOut, * pErr;
+ Abc_Ntk_t * pNtk, * pNtkRes;
+ int c, fUseZeroCost, fVerbose, nIters;
+ extern Abc_Ntk_t * Abc_NtkIvyHaig( Abc_Ntk_t * pNtk, int nIters, int fUseZeroCost, int fVerbose );
+
+ pNtk = Abc_FrameReadNtk(pAbc);
+ pOut = Abc_FrameReadOut(pAbc);
+ pErr = Abc_FrameReadErr(pAbc);
+
+ // set defaults
+ nIters = 2;
+ fUseZeroCost = 0;
+ fVerbose = 1;
+ Extra_UtilGetoptReset();
+ while ( ( c = Extra_UtilGetopt( argc, argv, "Izvh" ) ) != EOF )
+ {
+ switch ( c )
+ {
+ case 'I':
+ if ( globalUtilOptind >= argc )
+ {
+ fprintf( pErr, "Command line switch \"-I\" should be followed by a positive integer.\n" );
+ goto usage;
+ }
+ nIters = atoi(argv[globalUtilOptind]);
+ globalUtilOptind++;
+ if ( nIters < 0 )
+ goto usage;
+ break;
+ case 'z':
+ fUseZeroCost ^= 1;
+ break;
+ case 'v':
+ fVerbose ^= 1;
+ break;
+ case 'h':
+ goto usage;
+ default:
+ goto usage;
+ }
+ }
+ if ( pNtk == NULL )
+ {
+ fprintf( pErr, "Empty network.\n" );
+ return 1;
+ }
+ if ( !Abc_NtkIsStrash(pNtk) )
+ {
+ fprintf( pErr, "This command works only for strashed networks.\n" );
+ return 1;
+ }
+
+ pNtkRes = Abc_NtkIvyHaig( pNtk, nIters, fUseZeroCost, fVerbose );
+ if ( pNtkRes == NULL )
+ {
+ fprintf( pErr, "Command has failed.\n" );
+ return 0;
+ }
+ // replace the current network
+ Abc_FrameReplaceCurrentNetwork( pAbc, pNtkRes );
+ return 0;
+
+usage:
+ fprintf( pErr, "usage: haig [-Izvh]\n" );
+ fprintf( pErr, "\t prints HAIG stats after sequential rewriting\n" );
+ fprintf( pErr, "\t-I num : the number of rewriting iterations [default = %d]\n", nIters );
+ fprintf( pErr, "\t-z : toggle zero-cost replacements [default = %s]\n", fUseZeroCost? "yes": "no" );
+ fprintf( pErr, "\t-v : toggle verbose printout [default = %s]\n", fVerbose? "yes": "no" );
+ fprintf( pErr, "\t-h : print the command usage\n");
+ return 1;
+}
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Abc_CommandMini( Abc_Frame_t * pAbc, int argc, char ** argv )
+{
+ FILE * pOut, * pErr;
+ Abc_Ntk_t * pNtk, * pNtkRes;
+ int c;
+ extern Abc_Ntk_t * Abc_NtkMiniBalance( Abc_Ntk_t * pNtk );
+
+ pNtk = Abc_FrameReadNtk(pAbc);
+ pOut = Abc_FrameReadOut(pAbc);
+ pErr = Abc_FrameReadErr(pAbc);
+
+ // set defaults
+ Extra_UtilGetoptReset();
+ while ( ( c = Extra_UtilGetopt( argc, argv, "h" ) ) != EOF )
+ {
+ switch ( c )
+ {
+ case 'h':
+ goto usage;
+ default:
+ goto usage;
+ }
+ }
+ if ( pNtk == NULL )
+ {
+ fprintf( pErr, "Empty network.\n" );
+ return 1;
+ }
+ if ( !Abc_NtkIsStrash(pNtk) )
+ {
+ fprintf( pErr, "Only works for combinatinally strashed AIG networks.\n" );
+ return 1;
+ }
+
+ pNtkRes = Abc_NtkMiniBalance( pNtk );
+ if ( pNtkRes == NULL )
+ {
+ fprintf( pErr, "Command has failed.\n" );
+ return 0;
+ }
+ // replace the current network
+ Abc_FrameReplaceCurrentNetwork( pAbc, pNtkRes );
+ return 0;
+
+usage:
+ fprintf( pErr, "usage: mini [-h]\n" );
+ fprintf( pErr, "\t perform balancing using new package\n" );
+ fprintf( pErr, "\t-h : print the command usage\n");
+ return 1;
+}
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Abc_CommandQbf( Abc_Frame_t * pAbc, int argc, char ** argv )
+{
+ FILE * pOut, * pErr;
+ Abc_Ntk_t * pNtk;
+ int c;
+ int nPars;
+ int fVerbose;
+
+ extern void Abc_NtkQbf( Abc_Ntk_t * pNtk, int nPars, int fVerbose );
+
+ pNtk = Abc_FrameReadNtk(pAbc);
+ pOut = Abc_FrameReadOut(pAbc);
+ pErr = Abc_FrameReadErr(pAbc);
+
+ // set defaults
+ nPars = -1;
+ fVerbose = 1;
+ Extra_UtilGetoptReset();
+ while ( ( c = Extra_UtilGetopt( argc, argv, "Pvh" ) ) != EOF )
+ {
+ switch ( c )
+ {
+ case 'P':
+ if ( globalUtilOptind >= argc )
+ {
+ fprintf( pErr, "Command line switch \"-P\" should be followed by an integer.\n" );
+ goto usage;
+ }
+ nPars = atoi(argv[globalUtilOptind]);
+ globalUtilOptind++;
+ if ( nPars < 0 )
+ goto usage;
+ break;
+ case 'v':
+ fVerbose ^= 1;
+ break;
+ case 'h':
+ goto usage;
+ default:
+ goto usage;
+ }
+ }
+ if ( pNtk == NULL )
+ {
+ fprintf( pErr, "Empty network.\n" );
+ return 1;
+ }
+ if ( !Abc_NtkIsComb(pNtk) )
+ {
+ fprintf( pErr, "Works only for combinational networks.\n" );
+ return 1;
+ }
+ if ( Abc_NtkPoNum(pNtk) != 1 )
+ {
+ fprintf( pErr, "The miter should have one primary output.\n" );
+ return 1;
+ }
+ if ( !(nPars > 0 && nPars < Abc_NtkPiNum(pNtk)) )
+ {
+ fprintf( pErr, "The number of paramter variables is invalid (should be > 0 and < PI num).\n" );
+ return 1;
+ }
+ if ( Abc_NtkIsStrash(pNtk) )
+ Abc_NtkQbf( pNtk, nPars, fVerbose );
+ else
+ {
+ pNtk = Abc_NtkStrash( pNtk, 0, 1, 0 );
+ Abc_NtkQbf( pNtk, nPars, fVerbose );
+ Abc_NtkDelete( pNtk );
+ }
+ return 0;
+
+usage:
+ fprintf( pErr, "usage: qbf [-P num] [-vh]\n" );
+ fprintf( pErr, "\t solves a quantified boolean formula problem EpVxM(p,x)\n" );
+ fprintf( pErr, "\t-P num : number of paramters (should be the first PIs) [default = %d]\n", nPars );
+ fprintf( pErr, "\t-v : toggle verbose output [default = %s]\n", fVerbose? "yes": "no" );
+ fprintf( pErr, "\t-h : print the command usage\n");
+ return 1;
+}
/**Function*************************************************************
@@ -2881,61 +8423,65 @@ int Abc_CommandFraig( Abc_Frame_t * pAbc, int argc, char ** argv )
FILE * pOut, * pErr;
Abc_Ntk_t * pNtk, * pNtkRes;
int fAllNodes;
+ int fExdc;
int c;
+ int fPartition = 0;
+ extern void Abc_NtkFraigPartitionedTime( Abc_Ntk_t * pNtk, void * pParams );
- pNtk = Abc_FrameReadNet(pAbc);
+ pNtk = Abc_FrameReadNtk(pAbc);
pOut = Abc_FrameReadOut(pAbc);
pErr = Abc_FrameReadErr(pAbc);
// set defaults
+ fExdc = 0;
fAllNodes = 0;
+ memset( pParams, 0, sizeof(Fraig_Params_t) );
pParams->nPatsRand = 2048; // the number of words of random simulation info
pParams->nPatsDyna = 2048; // the number of words of dynamic simulation info
- pParams->nBTLimit = 99; // the max number of backtracks to perform
- pParams->fFuncRed = 1; // performs only one level hashing
- pParams->fFeedBack = 1; // enables solver feedback
- pParams->fDist1Pats = 1; // enables distance-1 patterns
- pParams->fDoSparse = 0; // performs equiv tests for sparse functions
- pParams->fChoicing = 0; // enables recording structural choices
- pParams->fTryProve = 0; // tries to solve the final miter
- pParams->fVerbose = 0; // the verbosiness flag
- pParams->fVerboseP = 0; // the verbosiness flag
- util_getopt_reset();
- while ( ( c = util_getopt( argc, argv, "RDBrscpvah" ) ) != EOF )
+ pParams->nBTLimit = 100; // the max number of backtracks to perform
+ pParams->fFuncRed = 1; // performs only one level hashing
+ pParams->fFeedBack = 1; // enables solver feedback
+ pParams->fDist1Pats = 1; // enables distance-1 patterns
+ pParams->fDoSparse = 1; // performs equiv tests for sparse functions
+ pParams->fChoicing = 0; // enables recording structural choices
+ pParams->fTryProve = 0; // tries to solve the final miter
+ pParams->fVerbose = 0; // the verbosiness flag
+ pParams->fVerboseP = 0; // the verbosiness flag
+ Extra_UtilGetoptReset();
+ while ( ( c = Extra_UtilGetopt( argc, argv, "RDCrscptvaeh" ) ) != EOF )
{
switch ( c )
{
-
case 'R':
- if ( util_optind >= argc )
+ if ( globalUtilOptind >= argc )
{
fprintf( pErr, "Command line switch \"-R\" should be followed by an integer.\n" );
goto usage;
}
- pParams->nPatsRand = atoi(argv[util_optind]);
- util_optind++;
+ pParams->nPatsRand = atoi(argv[globalUtilOptind]);
+ globalUtilOptind++;
if ( pParams->nPatsRand < 0 )
goto usage;
break;
case 'D':
- if ( util_optind >= argc )
+ if ( globalUtilOptind >= argc )
{
fprintf( pErr, "Command line switch \"-D\" should be followed by an integer.\n" );
goto usage;
}
- pParams->nPatsDyna = atoi(argv[util_optind]);
- util_optind++;
+ pParams->nPatsDyna = atoi(argv[globalUtilOptind]);
+ globalUtilOptind++;
if ( pParams->nPatsDyna < 0 )
goto usage;
break;
- case 'B':
- if ( util_optind >= argc )
+ case 'C':
+ if ( globalUtilOptind >= argc )
{
- fprintf( pErr, "Command line switch \"-B\" should be followed by an integer.\n" );
+ fprintf( pErr, "Command line switch \"-C\" should be followed by an integer.\n" );
goto usage;
}
- pParams->nBTLimit = atoi(argv[util_optind]);
- util_optind++;
+ pParams->nBTLimit = atoi(argv[globalUtilOptind]);
+ globalUtilOptind++;
if ( pParams->nBTLimit < 0 )
goto usage;
break;
@@ -2955,9 +8501,15 @@ int Abc_CommandFraig( Abc_Frame_t * pAbc, int argc, char ** argv )
case 'v':
pParams->fVerbose ^= 1;
break;
+ case 't':
+ fPartition ^= 1;
+ break;
case 'a':
fAllNodes ^= 1;
break;
+ case 'e':
+ fExdc ^= 1;
+ break;
case 'h':
goto usage;
default:
@@ -2980,13 +8532,28 @@ int Abc_CommandFraig( Abc_Frame_t * pAbc, int argc, char ** argv )
pParams->fVerboseP = pParams->fTryProve;
// get the new network
- if ( Abc_NtkIsStrash(pNtk) )
- pNtkRes = Abc_NtkFraig( pNtk, &Params, fAllNodes );
+ if ( fPartition )
+ {
+ pNtkRes = Abc_NtkDup( pNtk );
+ if ( Abc_NtkIsStrash(pNtk) )
+ Abc_NtkFraigPartitionedTime( pNtk, &Params );
+ else
+ {
+ pNtk = Abc_NtkStrash( pNtk, fAllNodes, !fAllNodes, 0 );
+ Abc_NtkFraigPartitionedTime( pNtk, &Params );
+ Abc_NtkDelete( pNtk );
+ }
+ }
else
{
- pNtk = Abc_NtkStrash( pNtk, fAllNodes, !fAllNodes );
- pNtkRes = Abc_NtkFraig( pNtk, &Params, fAllNodes );
- Abc_NtkDelete( pNtk );
+ if ( Abc_NtkIsStrash(pNtk) )
+ pNtkRes = Abc_NtkFraig( pNtk, &Params, fAllNodes, fExdc );
+ else
+ {
+ pNtk = Abc_NtkStrash( pNtk, fAllNodes, !fAllNodes, 0 );
+ pNtkRes = Abc_NtkFraig( pNtk, &Params, fAllNodes, fExdc );
+ Abc_NtkDelete( pNtk );
+ }
}
if ( pNtkRes == NULL )
{
@@ -3003,17 +8570,20 @@ int Abc_CommandFraig( Abc_Frame_t * pAbc, int argc, char ** argv )
usage:
sprintf( Buffer, "%d", pParams->nBTLimit );
- fprintf( pErr, "usage: fraig [-R num] [-D num] [-B num] [-rscpvah]\n" );
+ fprintf( pErr, "usage: fraig [-R num] [-D num] [-C num] [-rscpvtah]\n" );
fprintf( pErr, "\t transforms a logic network into a functionally reduced AIG\n" );
+ fprintf( pErr, "\t (there are also newer fraiging commands, \"ifraig\" and \"dfraig\")\n" );
fprintf( pErr, "\t-R num : number of random patterns (127 < num < 32769) [default = %d]\n", pParams->nPatsRand );
fprintf( pErr, "\t-D num : number of systematic patterns (127 < num < 32769) [default = %d]\n", pParams->nPatsDyna );
- fprintf( pErr, "\t-B num : number of backtracks for one SAT problem [default = %s]\n", pParams->nBTLimit==-1? "infinity" : Buffer );
+ fprintf( pErr, "\t-C num : number of backtracks for one SAT problem [default = %s]\n", pParams->nBTLimit==-1? "infinity" : Buffer );
fprintf( pErr, "\t-r : toggle functional reduction [default = %s]\n", pParams->fFuncRed? "yes": "no" );
fprintf( pErr, "\t-s : toggle considering sparse functions [default = %s]\n", pParams->fDoSparse? "yes": "no" );
fprintf( pErr, "\t-c : toggle accumulation of choices [default = %s]\n", pParams->fChoicing? "yes": "no" );
- fprintf( pErr, "\t-p : toggle proving the final miter [default = %s]\n", pParams->fTryProve? "yes": "no" );
+ fprintf( pErr, "\t-p : toggle proving the miter outputs [default = %s]\n", pParams->fTryProve? "yes": "no" );
fprintf( pErr, "\t-v : toggle verbose output [default = %s]\n", pParams->fVerbose? "yes": "no" );
+ fprintf( pErr, "\t-e : toggle functional sweeping using EXDC [default = %s]\n", fExdc? "yes": "no" );
fprintf( pErr, "\t-a : toggle between all nodes and DFS nodes [default = %s]\n", fAllNodes? "all": "dfs" );
+ fprintf( pErr, "\t-t : toggle using partitioned representation [default = %s]\n", fPartition? "yes": "no" );
fprintf( pErr, "\t-h : print the command usage\n");
return 1;
}
@@ -3036,14 +8606,14 @@ int Abc_CommandFraigTrust( Abc_Frame_t * pAbc, int argc, char ** argv )
int c;
int fDuplicate;
- pNtk = Abc_FrameReadNet(pAbc);
+ pNtk = Abc_FrameReadNtk(pAbc);
pOut = Abc_FrameReadOut(pAbc);
pErr = Abc_FrameReadErr(pAbc);
// set defaults
fDuplicate = 0;
- util_getopt_reset();
- while ( ( c = util_getopt( argc, argv, "dh" ) ) != EOF )
+ Extra_UtilGetoptReset();
+ while ( ( c = Extra_UtilGetopt( argc, argv, "dh" ) ) != EOF )
{
switch ( c )
{
@@ -3100,14 +8670,14 @@ int Abc_CommandFraigStore( Abc_Frame_t * pAbc, int argc, char ** argv )
int c;
int fDuplicate;
- pNtk = Abc_FrameReadNet(pAbc);
+ pNtk = Abc_FrameReadNtk(pAbc);
pOut = Abc_FrameReadOut(pAbc);
pErr = Abc_FrameReadErr(pAbc);
// set defaults
fDuplicate = 0;
- util_getopt_reset();
- while ( ( c = util_getopt( argc, argv, "dh" ) ) != EOF )
+ Extra_UtilGetoptReset();
+ while ( ( c = Extra_UtilGetopt( argc, argv, "dh" ) ) != EOF )
{
switch ( c )
{
@@ -3161,14 +8731,14 @@ int Abc_CommandFraigRestore( Abc_Frame_t * pAbc, int argc, char ** argv )
int c;
int fDuplicate;
- pNtk = Abc_FrameReadNet(pAbc);
+ pNtk = Abc_FrameReadNtk(pAbc);
pOut = Abc_FrameReadOut(pAbc);
pErr = Abc_FrameReadErr(pAbc);
// set defaults
fDuplicate = 0;
- util_getopt_reset();
- while ( ( c = util_getopt( argc, argv, "dh" ) ) != EOF )
+ Extra_UtilGetoptReset();
+ while ( ( c = Extra_UtilGetopt( argc, argv, "dh" ) ) != EOF )
{
switch ( c )
{
@@ -3225,14 +8795,14 @@ int Abc_CommandFraigClean( Abc_Frame_t * pAbc, int argc, char ** argv )
int c;
int fDuplicate;
- pNtk = Abc_FrameReadNet(pAbc);
+ pNtk = Abc_FrameReadNtk(pAbc);
pOut = Abc_FrameReadOut(pAbc);
pErr = Abc_FrameReadErr(pAbc);
// set defaults
fDuplicate = 0;
- util_getopt_reset();
- while ( ( c = util_getopt( argc, argv, "dh" ) ) != EOF )
+ Extra_UtilGetoptReset();
+ while ( ( c = Extra_UtilGetopt( argc, argv, "dh" ) ) != EOF )
{
switch ( c )
{
@@ -3273,26 +8843,37 @@ int Abc_CommandFraigSweep( Abc_Frame_t * pAbc, int argc, char ** argv )
Abc_Ntk_t * pNtk;
int c;
int fUseInv;
+ int fExdc;
int fVerbose;
+ int fVeryVerbose;
+ extern bool Abc_NtkFraigSweep( Abc_Ntk_t * pNtk, int fUseInv, int fExdc, int fVerbose, int fVeryVerbose );
- pNtk = Abc_FrameReadNet(pAbc);
+ pNtk = Abc_FrameReadNtk(pAbc);
pOut = Abc_FrameReadOut(pAbc);
pErr = Abc_FrameReadErr(pAbc);
// set defaults
fUseInv = 1;
+ fExdc = 0;
fVerbose = 0;
- util_getopt_reset();
- while ( ( c = util_getopt( argc, argv, "ivh" ) ) != EOF )
+ fVeryVerbose = 0;
+ Extra_UtilGetoptReset();
+ while ( ( c = Extra_UtilGetopt( argc, argv, "ievwh" ) ) != EOF )
{
switch ( c )
{
case 'i':
fUseInv ^= 1;
break;
+ case 'e':
+ fExdc ^= 1;
+ break;
case 'v':
fVerbose ^= 1;
break;
+ case 'w':
+ fVeryVerbose ^= 1;
+ break;
case 'h':
goto usage;
default:
@@ -3316,7 +8897,7 @@ int Abc_CommandFraigSweep( Abc_Frame_t * pAbc, int argc, char ** argv )
return 1;
}
// modify the current network
- if ( !Abc_NtkFraigSweep( pNtk, fUseInv, fVerbose ) )
+ if ( !Abc_NtkFraigSweep( pNtk, fUseInv, fExdc, fVerbose, fVeryVerbose ) )
{
fprintf( pErr, "Sweeping has failed.\n" );
return 1;
@@ -3324,14 +8905,535 @@ int Abc_CommandFraigSweep( Abc_Frame_t * pAbc, int argc, char ** argv )
return 0;
usage:
- fprintf( pErr, "usage: fraig_sweep [-vh]\n" );
+ fprintf( pErr, "usage: fraig_sweep [-evwh]\n" );
fprintf( pErr, "\t performs technology-dependent sweep\n" );
-// fprintf( pErr, "\t-i : toggle using inverter for complemented nodes [default = %s]\n", fUseInv? "yes": "no" );
+ fprintf( pErr, "\t-e : toggle functional sweeping using EXDC [default = %s]\n", fExdc? "yes": "no" );
fprintf( pErr, "\t-v : prints verbose information [default = %s]\n", fVerbose? "yes": "no" );
+ fprintf( pErr, "\t-w : prints equivalence class information [default = %s]\n", fVeryVerbose? "yes": "no" );
fprintf( pErr, "\t-h : print the command usage\n");
return 1;
}
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Abc_CommandFraigDress( Abc_Frame_t * pAbc, int argc, char ** argv )
+{
+ FILE * pOut, * pErr;
+ Abc_Ntk_t * pNtk;
+ char * pFileName;
+ int c;
+ int fVerbose;
+ extern void Abc_NtkDress( Abc_Ntk_t * pNtk, char * pFileName, int fVerbose );
+
+ pNtk = Abc_FrameReadNtk(pAbc);
+ pOut = Abc_FrameReadOut(pAbc);
+ pErr = Abc_FrameReadErr(pAbc);
+
+ // set defaults
+ fVerbose = 0;
+ Extra_UtilGetoptReset();
+ while ( ( c = Extra_UtilGetopt( argc, argv, "vh" ) ) != EOF )
+ {
+ switch ( c )
+ {
+ case 'v':
+ fVerbose ^= 1;
+ break;
+ case 'h':
+ goto usage;
+ default:
+ goto usage;
+ }
+ }
+ if ( pNtk == NULL )
+ {
+ fprintf( pErr, "Empty network.\n" );
+ return 1;
+ }
+ if ( Abc_NtkIsStrash(pNtk) )
+ {
+ fprintf( pErr, "This command works only for logic networks.\n" );
+ return 1;
+ }
+ if ( argc != globalUtilOptind && argc != globalUtilOptind + 1 )
+ goto usage;
+ if ( argc == globalUtilOptind && Abc_NtkSpec(pNtk) == NULL )
+ {
+ fprintf( pErr, "The current network has no spec.\n" );
+ return 1;
+ }
+ // get the input file name
+ pFileName = (argc == globalUtilOptind + 1) ? argv[globalUtilOptind] : Abc_NtkSpec(pNtk);
+ // modify the current network
+ Abc_NtkDress( pNtk, pFileName, fVerbose );
+ return 0;
+
+usage:
+ fprintf( pErr, "usage: dress [-vh] <file>\n" );
+ fprintf( pErr, "\t transfers internal node names from file to the current network\n" );
+ fprintf( pErr, "\t<file> : network with names (if not given, the current network spec is used)\n" );
+ fprintf( pErr, "\t-v : prints verbose information [default = %s]\n", fVerbose? "yes": "no" );
+ fprintf( pErr, "\t-h : print the command usage\n");
+ return 1;
+}
+
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Abc_CommandHaigStart( Abc_Frame_t * pAbc, int argc, char ** argv )
+{
+ FILE * pOut, * pErr;
+ Abc_Ntk_t * pNtk;
+ int c;
+
+ pNtk = Abc_FrameReadNtk(pAbc);
+ pOut = Abc_FrameReadOut(pAbc);
+ pErr = Abc_FrameReadErr(pAbc);
+
+ // set defaults
+ Extra_UtilGetoptReset();
+ while ( ( c = Extra_UtilGetopt( argc, argv, "dh" ) ) != EOF )
+ {
+ switch ( c )
+ {
+ case 'h':
+ goto usage;
+ default:
+ goto usage;
+ }
+ }
+ if ( !Abc_NtkIsStrash(pNtk) )
+ {
+ fprintf( pErr, "This command works only for AIGs; run strashing (\"st\").\n" );
+ return 0;
+ }
+ Abc_NtkHaigStart( pNtk );
+ return 0;
+
+usage:
+ fprintf( pErr, "usage: haig_start [-h]\n" );
+ fprintf( pErr, "\t starts constructive accumulation of combinational choices\n" );
+ fprintf( pErr, "\t-h : print the command usage\n");
+ return 1;
+}
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Abc_CommandHaigStop( Abc_Frame_t * pAbc, int argc, char ** argv )
+{
+ FILE * pOut, * pErr;
+ Abc_Ntk_t * pNtk;
+ int c;
+
+ pNtk = Abc_FrameReadNtk(pAbc);
+ pOut = Abc_FrameReadOut(pAbc);
+ pErr = Abc_FrameReadErr(pAbc);
+
+ // set defaults
+ Extra_UtilGetoptReset();
+ while ( ( c = Extra_UtilGetopt( argc, argv, "dh" ) ) != EOF )
+ {
+ switch ( c )
+ {
+ case 'h':
+ goto usage;
+ default:
+ goto usage;
+ }
+ }
+ if ( !Abc_NtkIsStrash(pNtk) )
+ {
+ fprintf( pErr, "This command works only for AIGs; run strashing (\"st\").\n" );
+ return 0;
+ }
+ Abc_NtkHaigStop( pNtk );
+ return 0;
+
+usage:
+ fprintf( pErr, "usage: haig_stop [-h]\n" );
+ fprintf( pErr, "\t cleans the internal storage for combinational choices\n" );
+ fprintf( pErr, "\t-h : print the command usage\n");
+ return 1;
+}
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Abc_CommandHaigUse( Abc_Frame_t * pAbc, int argc, char ** argv )
+{
+ FILE * pOut, * pErr;
+ Abc_Ntk_t * pNtk, * pNtkRes;
+ int c;
+
+ pNtk = Abc_FrameReadNtk(pAbc);
+ pOut = Abc_FrameReadOut(pAbc);
+ pErr = Abc_FrameReadErr(pAbc);
+
+ // set defaults
+ Extra_UtilGetoptReset();
+ while ( ( c = Extra_UtilGetopt( argc, argv, "dh" ) ) != EOF )
+ {
+ switch ( c )
+ {
+ case 'h':
+ goto usage;
+ default:
+ goto usage;
+ }
+ }
+ if ( !Abc_NtkIsStrash(pNtk) )
+ {
+ fprintf( pErr, "This command works only for AIGs; run strashing (\"st\").\n" );
+ return 0;
+ }
+ // get the new network
+ pNtkRes = Abc_NtkHaigUse( pNtk );
+ if ( pNtkRes == NULL )
+ {
+ fprintf( pErr, "Transforming internal storage into AIG with choices has failed.\n" );
+ return 1;
+ }
+ // replace the current network
+ Abc_FrameReplaceCurrentNetwork( pAbc, pNtkRes );
+ return 0;
+
+usage:
+ fprintf( pErr, "usage: haig_use [-h]\n" );
+ fprintf( pErr, "\t transforms internal storage into an AIG with choices\n" );
+ fprintf( pErr, "\t-h : print the command usage\n");
+ return 1;
+}
+
+
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Abc_CommandRecStart( Abc_Frame_t * pAbc, int argc, char ** argv )
+{
+ FILE * pOut, * pErr;
+ Abc_Ntk_t * pNtk;
+ int c;
+ int nVars;
+ int nCuts;
+
+ pNtk = Abc_FrameReadNtk(pAbc);
+ pOut = Abc_FrameReadOut(pAbc);
+ pErr = Abc_FrameReadErr(pAbc);
+
+ // set defaults
+ nVars = 4;
+ nCuts = 8;
+ Extra_UtilGetoptReset();
+ while ( ( c = Extra_UtilGetopt( argc, argv, "KCh" ) ) != EOF )
+ {
+ switch ( c )
+ {
+ case 'K':
+ if ( globalUtilOptind >= argc )
+ {
+ fprintf( pErr, "Command line switch \"-K\" should be followed by an integer.\n" );
+ goto usage;
+ }
+ nVars = atoi(argv[globalUtilOptind]);
+ globalUtilOptind++;
+ if ( nVars < 1 )
+ goto usage;
+ break;
+ case 'C':
+ if ( globalUtilOptind >= argc )
+ {
+ fprintf( pErr, "Command line switch \"-C\" should be followed by an integer.\n" );
+ goto usage;
+ }
+ nCuts = atoi(argv[globalUtilOptind]);
+ globalUtilOptind++;
+ if ( nCuts < 1 )
+ goto usage;
+ break;
+ case 'h':
+ goto usage;
+ default:
+ goto usage;
+ }
+ }
+ if ( !(nVars >= 3 && nVars <= 16) )
+ {
+ fprintf( pErr, "The range of allowed values is 3 <= K <= 16.\n" );
+ return 0;
+ }
+ if ( Abc_NtkRecIsRunning() )
+ {
+ fprintf( pErr, "The AIG subgraph recording is already started.\n" );
+ return 0;
+ }
+ if ( pNtk && !Abc_NtkIsStrash(pNtk) )
+ {
+ fprintf( pErr, "This command works only for AIGs; run strashing (\"st\").\n" );
+ return 0;
+ }
+ Abc_NtkRecStart( pNtk, nVars, nCuts );
+ return 0;
+
+usage:
+ fprintf( pErr, "usage: rec_start [-K num] [-C num] [-h]\n" );
+ fprintf( pErr, "\t starts recording AIG subgraphs (should be called for\n" );
+ fprintf( pErr, "\t an empty network or after reading in a previous record)\n" );
+ fprintf( pErr, "\t-K num : the largest number of inputs [default = %d]\n", nVars );
+ fprintf( pErr, "\t-C num : the max number of cuts used at a node (0 < num < 2^12) [default = %d]\n", nCuts );
+ fprintf( pErr, "\t-h : print the command usage\n");
+ return 1;
+}
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Abc_CommandRecStop( Abc_Frame_t * pAbc, int argc, char ** argv )
+{
+ FILE * pOut, * pErr;
+ Abc_Ntk_t * pNtk;
+ int c;
+
+ pNtk = Abc_FrameReadNtk(pAbc);
+ pOut = Abc_FrameReadOut(pAbc);
+ pErr = Abc_FrameReadErr(pAbc);
+
+ // set defaults
+ Extra_UtilGetoptReset();
+ while ( ( c = Extra_UtilGetopt( argc, argv, "dh" ) ) != EOF )
+ {
+ switch ( c )
+ {
+ case 'h':
+ goto usage;
+ default:
+ goto usage;
+ }
+ }
+ if ( !Abc_NtkRecIsRunning() )
+ {
+ fprintf( pErr, "This command works only after calling \"rec_start\".\n" );
+ return 0;
+ }
+ Abc_NtkRecStop();
+ return 0;
+
+usage:
+ fprintf( pErr, "usage: rec_stop [-h]\n" );
+ fprintf( pErr, "\t cleans the internal storage for AIG subgraphs\n" );
+ fprintf( pErr, "\t-h : print the command usage\n");
+ return 1;
+}
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Abc_CommandRecAdd( Abc_Frame_t * pAbc, int argc, char ** argv )
+{
+ FILE * pOut, * pErr;
+ Abc_Ntk_t * pNtk;
+ int c;
+
+ pNtk = Abc_FrameReadNtk(pAbc);
+ pOut = Abc_FrameReadOut(pAbc);
+ pErr = Abc_FrameReadErr(pAbc);
+
+ // set defaults
+ Extra_UtilGetoptReset();
+ while ( ( c = Extra_UtilGetopt( argc, argv, "dh" ) ) != EOF )
+ {
+ switch ( c )
+ {
+ case 'h':
+ goto usage;
+ default:
+ goto usage;
+ }
+ }
+ if ( !Abc_NtkIsStrash(pNtk) )
+ {
+ fprintf( pErr, "This command works for AIGs.\n" );
+ return 0;
+ }
+ if ( !Abc_NtkRecIsRunning() )
+ {
+ fprintf( pErr, "This command works for AIGs after calling \"rec_start\".\n" );
+ return 0;
+ }
+ Abc_NtkRecAdd( pNtk );
+ return 0;
+
+usage:
+ fprintf( pErr, "usage: rec_add [-h]\n" );
+ fprintf( pErr, "\t adds subgraphs from the current network to the set\n" );
+ fprintf( pErr, "\t-h : print the command usage\n");
+ return 1;
+}
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Abc_CommandRecPs( Abc_Frame_t * pAbc, int argc, char ** argv )
+{
+ FILE * pOut, * pErr;
+ Abc_Ntk_t * pNtk;
+ int c;
+
+ pNtk = Abc_FrameReadNtk(pAbc);
+ pOut = Abc_FrameReadOut(pAbc);
+ pErr = Abc_FrameReadErr(pAbc);
+
+ // set defaults
+ Extra_UtilGetoptReset();
+ while ( ( c = Extra_UtilGetopt( argc, argv, "dh" ) ) != EOF )
+ {
+ switch ( c )
+ {
+ case 'h':
+ goto usage;
+ default:
+ goto usage;
+ }
+ }
+ if ( !Abc_NtkRecIsRunning() )
+ {
+ fprintf( pErr, "This command works for AIGs only after calling \"rec_start\".\n" );
+ return 0;
+ }
+ Abc_NtkRecPs();
+ return 0;
+
+usage:
+ fprintf( pErr, "usage: rec_ps [-h]\n" );
+ fprintf( pErr, "\t prints statistics about the recorded AIG subgraphs\n" );
+ fprintf( pErr, "\t-h : print the command usage\n");
+ return 1;
+}
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Abc_CommandRecUse( Abc_Frame_t * pAbc, int argc, char ** argv )
+{
+ FILE * pOut, * pErr;
+ Abc_Ntk_t * pNtk, * pNtkRes;
+ int c;
+
+ pNtk = Abc_FrameReadNtk(pAbc);
+ pOut = Abc_FrameReadOut(pAbc);
+ pErr = Abc_FrameReadErr(pAbc);
+
+ // set defaults
+ Extra_UtilGetoptReset();
+ while ( ( c = Extra_UtilGetopt( argc, argv, "dh" ) ) != EOF )
+ {
+ switch ( c )
+ {
+ case 'h':
+ goto usage;
+ default:
+ goto usage;
+ }
+ }
+ if ( !Abc_NtkRecIsRunning() )
+ {
+ fprintf( pErr, "This command works for AIGs only after calling \"rec_start\".\n" );
+ return 0;
+ }
+ // get the new network
+ pNtkRes = Abc_NtkRecUse();
+ if ( pNtkRes == NULL )
+ {
+ fprintf( pErr, "Transforming internal AIG subgraphs into an AIG with choices has failed.\n" );
+ return 1;
+ }
+ // replace the current network
+ Abc_FrameReplaceCurrentNetwork( pAbc, pNtkRes );
+ return 0;
+
+usage:
+ fprintf( pErr, "usage: rec_use [-h]\n" );
+ fprintf( pErr, "\t transforms internal storage into an AIG with choices\n" );
+ fprintf( pErr, "\t-h : print the command usage\n");
+ return 1;
+}
+
+
/**Function*************************************************************
@@ -3356,8 +9458,9 @@ int Abc_CommandMap( Abc_Frame_t * pAbc, int argc, char ** argv )
int fVerbose;
int c;
extern Abc_Ntk_t * Abc_NtkMap( Abc_Ntk_t * pNtk, double DelayTarget, int fRecovery, int fSwitching, int fVerbose );
+ extern bool Abc_NtkFraigSweep( Abc_Ntk_t * pNtk, int fUseInv, int fExdc, int fVerbose, int fVeryVerbose );
- pNtk = Abc_FrameReadNet(pAbc);
+ pNtk = Abc_FrameReadNtk(pAbc);
pOut = Abc_FrameReadOut(pAbc);
pErr = Abc_FrameReadErr(pAbc);
@@ -3367,19 +9470,19 @@ int Abc_CommandMap( Abc_Frame_t * pAbc, int argc, char ** argv )
fSweep = 1;
fSwitching = 0;
fVerbose = 0;
- util_getopt_reset();
- while ( ( c = util_getopt( argc, argv, "Daspvh" ) ) != EOF )
+ Extra_UtilGetoptReset();
+ while ( ( c = Extra_UtilGetopt( argc, argv, "Daspvh" ) ) != EOF )
{
switch ( c )
{
case 'D':
- if ( util_optind >= argc )
+ if ( globalUtilOptind >= argc )
{
fprintf( pErr, "Command line switch \"-D\" should be followed by a floating point number.\n" );
goto usage;
}
- DelayTarget = (float)atof(argv[util_optind]);
- util_optind++;
+ DelayTarget = (float)atof(argv[globalUtilOptind]);
+ globalUtilOptind++;
if ( DelayTarget <= 0.0 )
goto usage;
break;
@@ -3410,13 +9513,13 @@ int Abc_CommandMap( Abc_Frame_t * pAbc, int argc, char ** argv )
if ( !Abc_NtkIsStrash(pNtk) )
{
- pNtk = Abc_NtkStrash( pNtk, 0, 0 );
+ pNtk = Abc_NtkStrash( pNtk, 0, 0, 0 );
if ( pNtk == NULL )
{
fprintf( pErr, "Strashing before mapping has failed.\n" );
return 1;
}
- pNtk = Abc_NtkBalance( pNtkRes = pNtk, 0 );
+ pNtk = Abc_NtkBalance( pNtkRes = pNtk, 0, 0, 1 );
Abc_NtkDelete( pNtkRes );
if ( pNtk == NULL )
{
@@ -3446,7 +9549,7 @@ int Abc_CommandMap( Abc_Frame_t * pAbc, int argc, char ** argv )
}
if ( fSweep )
- Abc_NtkFraigSweep( pNtkRes, 0, 0 );
+ Abc_NtkFraigSweep( pNtkRes, 0, 0, 0, 0 );
// replace the current network
Abc_FrameReplaceCurrentNetwork( pAbc, pNtkRes );
@@ -3457,14 +9560,14 @@ usage:
sprintf( Buffer, "not used" );
else
sprintf( Buffer, "%.3f", DelayTarget );
- fprintf( pErr, "usage: map [-D num] [-aspvh]\n" );
- fprintf( pErr, "\t performs standard cell mapping of the current network\n" );
- fprintf( pErr, "\t-D num : sets the global required times [default = %s]\n", Buffer );
- fprintf( pErr, "\t-a : toggles area recovery [default = %s]\n", fRecovery? "yes": "no" );
- fprintf( pErr, "\t-s : toggles sweep after mapping [default = %s]\n", fSweep? "yes": "no" );
- fprintf( pErr, "\t-p : optimizes power by minimizing switching activity [default = %s]\n", fSwitching? "yes": "no" );
- fprintf( pErr, "\t-v : toggles verbose output [default = %s]\n", fVerbose? "yes": "no" );
- fprintf( pErr, "\t-h : print the command usage\n");
+ fprintf( pErr, "usage: map [-D float] [-aspvh]\n" );
+ fprintf( pErr, "\t performs standard cell mapping of the current network\n" );
+ fprintf( pErr, "\t-D float : sets the global required times [default = %s]\n", Buffer );
+ fprintf( pErr, "\t-a : toggles area recovery [default = %s]\n", fRecovery? "yes": "no" );
+ fprintf( pErr, "\t-s : toggles sweep after mapping [default = %s]\n", fSweep? "yes": "no" );
+ fprintf( pErr, "\t-p : optimizes power by minimizing switching [default = %s]\n", fSwitching? "yes": "no" );
+ fprintf( pErr, "\t-v : toggles verbose output [default = %s]\n", fVerbose? "yes": "no" );
+ fprintf( pErr, "\t-h : print the command usage\n");
return 1;
}
@@ -3485,15 +9588,14 @@ int Abc_CommandUnmap( Abc_Frame_t * pAbc, int argc, char ** argv )
FILE * pOut, * pErr;
Abc_Ntk_t * pNtk;
int c;
- extern int Abc_NtkUnmap( Abc_Ntk_t * pNtk );
- pNtk = Abc_FrameReadNet(pAbc);
+ pNtk = Abc_FrameReadNtk(pAbc);
pOut = Abc_FrameReadOut(pAbc);
pErr = Abc_FrameReadErr(pAbc);
// set defaults
- util_getopt_reset();
- while ( ( c = util_getopt( argc, argv, "h" ) ) != EOF )
+ Extra_UtilGetoptReset();
+ while ( ( c = Extra_UtilGetopt( argc, argv, "h" ) ) != EOF )
{
switch ( c )
{
@@ -3516,7 +9618,7 @@ int Abc_CommandUnmap( Abc_Frame_t * pAbc, int argc, char ** argv )
}
// get the new network
- if ( !Abc_NtkUnmap( pNtk ) )
+ if ( !Abc_NtkMapToSop( pNtk ) )
{
fprintf( pErr, "Unmapping has failed.\n" );
return 1;
@@ -3546,15 +9648,14 @@ int Abc_CommandAttach( Abc_Frame_t * pAbc, int argc, char ** argv )
FILE * pOut, * pErr;
Abc_Ntk_t * pNtk;
int c;
- extern int Abc_NtkUnmap( Abc_Ntk_t * pNtk );
- pNtk = Abc_FrameReadNet(pAbc);
+ pNtk = Abc_FrameReadNtk(pAbc);
pOut = Abc_FrameReadOut(pAbc);
pErr = Abc_FrameReadErr(pAbc);
// set defaults
- util_getopt_reset();
- while ( ( c = util_getopt( argc, argv, "h" ) ) != EOF )
+ Extra_UtilGetoptReset();
+ while ( ( c = Extra_UtilGetopt( argc, argv, "h" ) ) != EOF )
{
switch ( c )
{
@@ -3611,13 +9712,13 @@ int Abc_CommandSuperChoice( Abc_Frame_t * pAbc, int argc, char ** argv )
int c;
extern Abc_Ntk_t * Abc_NtkSuperChoice( Abc_Ntk_t * pNtk );
- pNtk = Abc_FrameReadNet(pAbc);
+ pNtk = Abc_FrameReadNtk(pAbc);
pOut = Abc_FrameReadOut(pAbc);
pErr = Abc_FrameReadErr(pAbc);
// set defaults
- util_getopt_reset();
- while ( ( c = util_getopt( argc, argv, "h" ) ) != EOF )
+ Extra_UtilGetoptReset();
+ while ( ( c = Extra_UtilGetopt( argc, argv, "h" ) ) != EOF )
{
switch ( c )
{
@@ -3636,7 +9737,7 @@ int Abc_CommandSuperChoice( Abc_Frame_t * pAbc, int argc, char ** argv )
if ( !Abc_NtkIsStrash(pNtk) )
{
- fprintf( pErr, "Works only for the AIG representation (run \"strash\").\n" );
+ fprintf( pErr, "Superchoicing works only for the AIG representation (run \"strash\").\n" );
return 1;
}
@@ -3671,26 +9772,139 @@ usage:
SeeAlso []
***********************************************************************/
+int Abc_CommandSuperChoiceLut( Abc_Frame_t * pAbc, int argc, char ** argv )
+{
+ FILE * pOut, * pErr;
+ Abc_Ntk_t * pNtk, * pNtkRes;
+ int c;
+ int nLutSize;
+ int nCutSizeMax;
+ int fVerbose;
+ extern int Abc_NtkSuperChoiceLut( Abc_Ntk_t * pNtk, int nLutSize, int nCutSizeMax, int fVerbose );
+
+ pNtk = Abc_FrameReadNtk(pAbc);
+ pOut = Abc_FrameReadOut(pAbc);
+ pErr = Abc_FrameReadErr(pAbc);
+
+ // set defaults
+ fVerbose = 1;
+ nLutSize = 4;
+ nCutSizeMax = 10;
+ Extra_UtilGetoptReset();
+ while ( ( c = Extra_UtilGetopt( argc, argv, "KNh" ) ) != EOF )
+ {
+ switch ( c )
+ {
+ case 'K':
+ if ( globalUtilOptind >= argc )
+ {
+ fprintf( pErr, "Command line switch \"-K\" should be followed by a positive integer.\n" );
+ goto usage;
+ }
+ nLutSize = atoi(argv[globalUtilOptind]);
+ globalUtilOptind++;
+ if ( nLutSize < 0 )
+ goto usage;
+ break;
+ case 'N':
+ if ( globalUtilOptind >= argc )
+ {
+ fprintf( pErr, "Command line switch \"-N\" should be followed by a positive integer.\n" );
+ goto usage;
+ }
+ nCutSizeMax = atoi(argv[globalUtilOptind]);
+ globalUtilOptind++;
+ if ( nCutSizeMax < 0 )
+ goto usage;
+ break;
+ case 'v':
+ fVerbose ^= 1;
+ break;
+ case 'h':
+ goto usage;
+ default:
+ goto usage;
+ }
+ }
+
+ if ( pNtk == NULL )
+ {
+ fprintf( pErr, "Empty network.\n" );
+ return 1;
+ }
+
+ if ( !Abc_NtkIsStrash(pNtk) )
+ {
+ fprintf( pErr, "Superchoicing works only for the AIG representation (run \"strash\").\n" );
+ return 1;
+ }
+
+ // convert the network into the SOP network
+ pNtkRes = Abc_NtkToLogic( pNtk );
+
+ // get the new network
+ if ( !Abc_NtkSuperChoiceLut( pNtkRes, nLutSize, nCutSizeMax, fVerbose ) )
+ {
+ Abc_NtkDelete( pNtkRes );
+ fprintf( pErr, "Superchoicing has failed.\n" );
+ return 1;
+ }
+ // replace the current network
+ Abc_FrameReplaceCurrentNetwork( pAbc, pNtkRes );
+ return 0;
+
+usage:
+ fprintf( pErr, "usage: scl [-K num] [-N num] [-vh]\n" );
+ fprintf( pErr, "\t performs superchoicing for K-LUTs\n" );
+ fprintf( pErr, "\t (accumulate: \"r file.blif; b; scl; f -ac; wb file_sc.blif\")\n" );
+ fprintf( pErr, "\t (FPGA map: \"r file_sc.blif; ft; read_lut lutlibK; fpga\")\n" );
+ fprintf( pErr, "\t-K num : the number of LUT inputs [default = %d]\n", nLutSize );
+ fprintf( pErr, "\t-N num : the max size of the cut [default = %d]\n", nCutSizeMax );
+ fprintf( pErr, "\t-v : toggles verbose output [default = %s]\n", fVerbose? "yes": "no" );
+ fprintf( pErr, "\t-h : print the command usage\n");
+ return 1;
+}
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
int Abc_CommandFpga( Abc_Frame_t * pAbc, int argc, char ** argv )
{
+ char Buffer[100];
+ char LutSize[100];
FILE * pOut, * pErr;
Abc_Ntk_t * pNtk, * pNtkRes;
int c;
int fRecovery;
int fSwitching;
+ int fLatchPaths;
int fVerbose;
- extern Abc_Ntk_t * Abc_NtkFpga( Abc_Ntk_t * pNtk, int fRecovery, int fSwitching, int fVerbose );
+ int nLutSize;
+ float DelayTarget;
- pNtk = Abc_FrameReadNet(pAbc);
+ extern Abc_Ntk_t * Abc_NtkFpga( Abc_Ntk_t * pNtk, float DelayTarget, int fRecovery, int fSwitching, int fLatchPaths, int fVerbose );
+
+ pNtk = Abc_FrameReadNtk(pAbc);
pOut = Abc_FrameReadOut(pAbc);
pErr = Abc_FrameReadErr(pAbc);
// set defaults
- fRecovery = 1;
- fSwitching = 0;
- fVerbose = 0;
- util_getopt_reset();
- while ( ( c = util_getopt( argc, argv, "apvh" ) ) != EOF )
+ fRecovery = 1;
+ fSwitching = 0;
+ fLatchPaths = 0;
+ fVerbose = 0;
+ DelayTarget =-1;
+ nLutSize =-1;
+ Extra_UtilGetoptReset();
+ while ( ( c = Extra_UtilGetopt( argc, argv, "aplvhDK" ) ) != EOF )
{
switch ( c )
{
@@ -3700,11 +9914,36 @@ int Abc_CommandFpga( Abc_Frame_t * pAbc, int argc, char ** argv )
case 'p':
fSwitching ^= 1;
break;
+ case 'l':
+ fLatchPaths ^= 1;
+ break;
case 'v':
fVerbose ^= 1;
break;
case 'h':
goto usage;
+ case 'D':
+ if ( globalUtilOptind >= argc )
+ {
+ fprintf( pErr, "Command line switch \"-D\" should be followed by a floating point number.\n" );
+ goto usage;
+ }
+ DelayTarget = (float)atof(argv[globalUtilOptind]);
+ globalUtilOptind++;
+ if ( DelayTarget <= 0.0 )
+ goto usage;
+ break;
+ case 'K':
+ if ( globalUtilOptind >= argc )
+ {
+ fprintf( pErr, "Command line switch \"-K\" should be followed by a positive integer.\n" );
+ goto usage;
+ }
+ nLutSize = atoi(argv[globalUtilOptind]);
+ globalUtilOptind++;
+ if ( nLutSize < 0 )
+ goto usage;
+ break;
default:
goto usage;
}
@@ -3716,16 +9955,26 @@ int Abc_CommandFpga( Abc_Frame_t * pAbc, int argc, char ** argv )
return 1;
}
+ // create the new LUT library
+ if ( nLutSize >= 3 && nLutSize <= 10 )
+ Fpga_SetSimpleLutLib( nLutSize );
+/*
+ else
+ {
+ fprintf( pErr, "Cannot perform FPGA mapping with LUT size %d.\n", nLutSize );
+ return 1;
+ }
+*/
if ( !Abc_NtkIsStrash(pNtk) )
{
// strash and balance the network
- pNtk = Abc_NtkStrash( pNtk, 0, 0 );
+ pNtk = Abc_NtkStrash( pNtk, 0, 0, 0 );
if ( pNtk == NULL )
{
fprintf( pErr, "Strashing before FPGA mapping has failed.\n" );
return 1;
}
- pNtk = Abc_NtkBalance( pNtkRes = pNtk, 0 );
+ pNtk = Abc_NtkBalance( pNtkRes = pNtk, 0, 0, 1 );
Abc_NtkDelete( pNtkRes );
if ( pNtk == NULL )
{
@@ -3734,7 +9983,7 @@ int Abc_CommandFpga( Abc_Frame_t * pAbc, int argc, char ** argv )
}
fprintf( pOut, "The network was strashed and balanced before FPGA mapping.\n" );
// get the new network
- pNtkRes = Abc_NtkFpga( pNtk, fRecovery, fSwitching, fVerbose );
+ pNtkRes = Abc_NtkFpga( pNtk, DelayTarget, fRecovery, fSwitching, fLatchPaths, fVerbose );
if ( pNtkRes == NULL )
{
Abc_NtkDelete( pNtk );
@@ -3746,7 +9995,7 @@ int Abc_CommandFpga( Abc_Frame_t * pAbc, int argc, char ** argv )
else
{
// get the new network
- pNtkRes = Abc_NtkFpga( pNtk, fRecovery, fSwitching, fVerbose );
+ pNtkRes = Abc_NtkFpga( pNtk, DelayTarget, fRecovery, fSwitching, fLatchPaths, fVerbose );
if ( pNtkRes == NULL )
{
fprintf( pErr, "FPGA mapping has failed.\n" );
@@ -3758,16 +10007,160 @@ int Abc_CommandFpga( Abc_Frame_t * pAbc, int argc, char ** argv )
return 0;
usage:
- fprintf( pErr, "usage: fpga [-apvh]\n" );
- fprintf( pErr, "\t performs FPGA mapping of the current network\n" );
- fprintf( pErr, "\t-a : toggles area recovery [default = %s]\n", fRecovery? "yes": "no" );
- fprintf( pErr, "\t-p : optimizes power by minimizing switching activity [default = %s]\n", fSwitching? "yes": "no" );
- fprintf( pErr, "\t-v : toggles verbose output [default = %s]\n", fVerbose? "yes": "no" );
- fprintf( pErr, "\t-h : prints the command usage\n");
+ if ( DelayTarget == -1 )
+ sprintf( Buffer, "best possible" );
+ else
+ sprintf( Buffer, "%.2f", DelayTarget );
+ if ( nLutSize == -1 )
+ sprintf( LutSize, "library" );
+ else
+ sprintf( LutSize, "%d", nLutSize );
+ fprintf( pErr, "usage: fpga [-D float] [-K num] [-aplvh]\n" );
+ fprintf( pErr, "\t performs FPGA mapping of the current network\n" );
+ fprintf( pErr, "\t-a : toggles area recovery [default = %s]\n", fRecovery? "yes": "no" );
+ fprintf( pErr, "\t-p : optimizes power by minimizing switching activity [default = %s]\n", fSwitching? "yes": "no" );
+ fprintf( pErr, "\t-l : optimizes latch paths for delay, other paths for area [default = %s]\n", fLatchPaths? "yes": "no" );
+ fprintf( pErr, "\t-D float : sets the required time for the mapping [default = %s]\n", Buffer );
+ fprintf( pErr, "\t-K num : the number of LUT inputs (2 < num < 11) [default = %s]%s\n", LutSize, (nLutSize == -1 ? " (type \"print_lut\")" : "") );
+ fprintf( pErr, "\t-v : toggles verbose output [default = %s]\n", fVerbose? "yes": "no" );
+ fprintf( pErr, "\t-h : prints the command usage\n");
return 1;
}
+/**Function*************************************************************
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Abc_CommandFpgaFast( Abc_Frame_t * pAbc, int argc, char ** argv )
+{
+ char Buffer[100];
+ FILE * pOut, * pErr;
+ Abc_Ntk_t * pNtk, * pNtkRes;
+ int c;
+ int fRecovery;
+ int fVerbose;
+ int nLutSize;
+ float DelayTarget;
+
+ extern Abc_Ntk_t * Abc_NtkFpgaFast( Abc_Ntk_t * pNtk, int nLutSize, int fRecovery, int fVerbose );
+
+ pNtk = Abc_FrameReadNtk(pAbc);
+ pOut = Abc_FrameReadOut(pAbc);
+ pErr = Abc_FrameReadErr(pAbc);
+
+ // set defaults
+ fRecovery = 1;
+ fVerbose = 0;
+ DelayTarget =-1;
+ nLutSize = 5;
+ Extra_UtilGetoptReset();
+ while ( ( c = Extra_UtilGetopt( argc, argv, "avhDK" ) ) != EOF )
+ {
+ switch ( c )
+ {
+ case 'a':
+ fRecovery ^= 1;
+ break;
+ case 'v':
+ fVerbose ^= 1;
+ break;
+ case 'h':
+ goto usage;
+ case 'D':
+ if ( globalUtilOptind >= argc )
+ {
+ fprintf( pErr, "Command line switch \"-D\" should be followed by a floating point number.\n" );
+ goto usage;
+ }
+ DelayTarget = (float)atof(argv[globalUtilOptind]);
+ globalUtilOptind++;
+ if ( DelayTarget <= 0.0 )
+ goto usage;
+ break;
+ case 'K':
+ if ( globalUtilOptind >= argc )
+ {
+ fprintf( pErr, "Command line switch \"-K\" should be followed by a positive integer.\n" );
+ goto usage;
+ }
+ nLutSize = atoi(argv[globalUtilOptind]);
+ globalUtilOptind++;
+ if ( nLutSize < 0 )
+ goto usage;
+ break;
+ default:
+ goto usage;
+ }
+ }
+
+ if ( pNtk == NULL )
+ {
+ fprintf( pErr, "Empty network.\n" );
+ return 1;
+ }
+
+ if ( !Abc_NtkIsStrash(pNtk) )
+ {
+ // strash and balance the network
+ pNtk = Abc_NtkStrash( pNtk, 0, 0, 0 );
+ if ( pNtk == NULL )
+ {
+ fprintf( pErr, "Strashing before FPGA mapping has failed.\n" );
+ return 1;
+ }
+ pNtk = Abc_NtkBalance( pNtkRes = pNtk, 0, 0, 1 );
+ Abc_NtkDelete( pNtkRes );
+ if ( pNtk == NULL )
+ {
+ fprintf( pErr, "Balancing before FPGA mapping has failed.\n" );
+ return 1;
+ }
+ fprintf( pOut, "The network was strashed and balanced before FPGA mapping.\n" );
+ // get the new network
+ pNtkRes = Abc_NtkFpgaFast( pNtk, nLutSize, fRecovery, fVerbose );
+ if ( pNtkRes == NULL )
+ {
+ Abc_NtkDelete( pNtk );
+ fprintf( pErr, "FPGA mapping has failed.\n" );
+ return 1;
+ }
+ Abc_NtkDelete( pNtk );
+ }
+ else
+ {
+ // get the new network
+ pNtkRes = Abc_NtkFpgaFast( pNtk, nLutSize, fRecovery, fVerbose );
+ if ( pNtkRes == NULL )
+ {
+ fprintf( pErr, "FPGA mapping has failed.\n" );
+ return 1;
+ }
+ }
+ // replace the current network
+ Abc_FrameReplaceCurrentNetwork( pAbc, pNtkRes );
+ return 0;
+
+usage:
+ if ( DelayTarget == -1 )
+ sprintf( Buffer, "not used" );
+ else
+ sprintf( Buffer, "%.2f", DelayTarget );
+ fprintf( pErr, "usage: ffpga [-K num] [-avh]\n" );
+ fprintf( pErr, "\t performs fast FPGA mapping of the current network\n" );
+ fprintf( pErr, "\t-a : toggles area recovery [default = %s]\n", fRecovery? "yes": "no" );
+// fprintf( pErr, "\t-D float : sets the required time for the mapping [default = %s]\n", Buffer );
+ fprintf( pErr, "\t-K num : the number of LUT inputs (2 < num < 32) [default = %d]\n", nLutSize );
+ fprintf( pErr, "\t-v : toggles verbose output [default = %s]\n", fVerbose? "yes": "no" );
+ fprintf( pErr, "\t-h : prints the command usage\n");
+ return 1;
+}
/**Function*************************************************************
@@ -3780,23 +10173,321 @@ usage:
SeeAlso []
***********************************************************************/
-int Abc_CommandSeq( Abc_Frame_t * pAbc, int argc, char ** argv )
+int Abc_CommandIf( Abc_Frame_t * pAbc, int argc, char ** argv )
{
+ char Buffer[100];
+ char LutSize[100];
FILE * pOut, * pErr;
Abc_Ntk_t * pNtk, * pNtkRes;
+ If_Par_t Pars, * pPars = &Pars;
int c;
- extern Abc_Ntk_t * Abc_NtkSuperChoice( Abc_Ntk_t * pNtk );
+ extern Abc_Ntk_t * Abc_NtkIf( Abc_Ntk_t * pNtk, If_Par_t * pPars );
+
+ pNtk = Abc_FrameReadNtk(pAbc);
+ pOut = Abc_FrameReadOut(pAbc);
+ pErr = Abc_FrameReadErr(pAbc);
+
+ // set defaults
+ memset( pPars, 0, sizeof(If_Par_t) );
+ // user-controlable paramters
+ pPars->nLutSize = -1;
+ pPars->nCutsMax = 8;
+ pPars->nFlowIters = 1;
+ pPars->nAreaIters = 2;
+ pPars->DelayTarget = -1;
+ pPars->fPreprocess = 1;
+ pPars->fArea = 0;
+ pPars->fFancy = 0;
+ pPars->fExpRed = 1;
+ pPars->fLatchPaths = 0;
+ pPars->fEdge = 0;
+ pPars->fCutMin = 0;
+ pPars->fSeqMap = 0;
+ pPars->fVerbose = 0;
+ // internal parameters
+ pPars->fTruth = 0;
+ pPars->nLatches = pNtk? Abc_NtkLatchNum(pNtk) : 0;
+ pPars->fLiftLeaves = 0;
+ pPars->pLutLib = Abc_FrameReadLibLut();
+ pPars->pTimesArr = NULL;
+ pPars->pTimesArr = NULL;
+ pPars->pFuncCost = NULL;
+
+ Extra_UtilGetoptReset();
+ while ( ( c = Extra_UtilGetopt( argc, argv, "KCFADpaflemrstvh" ) ) != EOF )
+ {
+ switch ( c )
+ {
+ case 'K':
+ if ( globalUtilOptind >= argc )
+ {
+ fprintf( pErr, "Command line switch \"-K\" should be followed by a positive integer.\n" );
+ goto usage;
+ }
+ pPars->nLutSize = atoi(argv[globalUtilOptind]);
+ globalUtilOptind++;
+ if ( pPars->nLutSize < 0 )
+ goto usage;
+ // if the LUT size is specified, disable library
+ pPars->pLutLib = NULL;
+ break;
+ case 'C':
+ if ( globalUtilOptind >= argc )
+ {
+ fprintf( pErr, "Command line switch \"-C\" should be followed by a positive integer.\n" );
+ goto usage;
+ }
+ pPars->nCutsMax = atoi(argv[globalUtilOptind]);
+ globalUtilOptind++;
+ if ( pPars->nCutsMax < 0 )
+ goto usage;
+ break;
+ case 'F':
+ if ( globalUtilOptind >= argc )
+ {
+ fprintf( pErr, "Command line switch \"-F\" should be followed by a positive integer.\n" );
+ goto usage;
+ }
+ pPars->nFlowIters = atoi(argv[globalUtilOptind]);
+ globalUtilOptind++;
+ if ( pPars->nFlowIters < 0 )
+ goto usage;
+ break;
+ case 'A':
+ if ( globalUtilOptind >= argc )
+ {
+ fprintf( pErr, "Command line switch \"-A\" should be followed by a positive integer.\n" );
+ goto usage;
+ }
+ pPars->nAreaIters = atoi(argv[globalUtilOptind]);
+ globalUtilOptind++;
+ if ( pPars->nAreaIters < 0 )
+ goto usage;
+ break;
+ case 'D':
+ if ( globalUtilOptind >= argc )
+ {
+ fprintf( pErr, "Command line switch \"-D\" should be followed by a floating point number.\n" );
+ goto usage;
+ }
+ pPars->DelayTarget = (float)atof(argv[globalUtilOptind]);
+ globalUtilOptind++;
+ if ( pPars->DelayTarget <= 0.0 )
+ goto usage;
+ break;
+ case 'p':
+ pPars->fPreprocess ^= 1;
+ break;
+ case 'a':
+ pPars->fArea ^= 1;
+ break;
+ case 'r':
+ pPars->fExpRed ^= 1;
+ break;
+ case 'f':
+ pPars->fFancy ^= 1;
+ break;
+ case 'l':
+ pPars->fLatchPaths ^= 1;
+ break;
+ case 'e':
+ pPars->fEdge ^= 1;
+ break;
+ case 'm':
+ pPars->fCutMin ^= 1;
+ break;
+ case 's':
+ pPars->fSeqMap ^= 1;
+ break;
+ case 't':
+ pPars->fLiftLeaves ^= 1;
+ break;
+ case 'v':
+ pPars->fVerbose ^= 1;
+ break;
+ case 'h':
+ default:
+ goto usage;
+ }
+ }
+
+ if ( pNtk == NULL )
+ {
+ fprintf( pErr, "Empty network.\n" );
+ return 1;
+ }
+
+ if ( pPars->fSeqMap && pPars->nLatches == 0 )
+ {
+ fprintf( pErr, "The network has no latches. Use combinational mapping instead of sequential.\n" );
+ return 1;
+ }
+
+ if ( pPars->nLutSize == -1 )
+ {
+ if ( pPars->pLutLib == NULL )
+ {
+ fprintf( pErr, "The LUT library is not given.\n" );
+ return 1;
+ }
+ // get LUT size from the library
+ pPars->nLutSize = pPars->pLutLib->LutMax;
+ }
+
+ if ( pPars->nLutSize < 3 || pPars->nLutSize > IF_MAX_LUTSIZE )
+ {
+ fprintf( pErr, "Incorrect LUT size (%d).\n", pPars->nLutSize );
+ return 1;
+ }
+
+ if ( pPars->nCutsMax < 1 || pPars->nCutsMax >= (1<<12) )
+ {
+ fprintf( pErr, "Incorrect number of cuts.\n" );
+ return 1;
+ }
+
+ // enable truth table computation if choices are selected
+ if ( Abc_NtkGetChoiceNum( pNtk ) )
+ {
+ printf( "Performing FPGA mapping with choices.\n" );
+ pPars->fTruth = 1;
+ }
+ // enable truth table computation if cut minimization is selected
+ if ( pPars->fCutMin )
+ pPars->fTruth = 1;
+
+ // complain if truth tables are requested but the cut size is too large
+ if ( pPars->fTruth && pPars->nLutSize > IF_MAX_FUNC_LUTSIZE )
+ {
+ fprintf( pErr, "Truth tables cannot be computed for LUT larger than %d inputs.\n", IF_MAX_FUNC_LUTSIZE );
+ return 1;
+ }
+
+ // disable cut-expansion if edge-based heuristics are selected
+// if ( pPars->fEdge )
+// pPars->fExpRed = 0;
+
+ if ( !Abc_NtkIsStrash(pNtk) )
+ {
+ // strash and balance the network
+ pNtk = Abc_NtkStrash( pNtk, 0, 0, 0 );
+ if ( pNtk == NULL )
+ {
+ fprintf( pErr, "Strashing before FPGA mapping has failed.\n" );
+ return 1;
+ }
+ pNtk = Abc_NtkBalance( pNtkRes = pNtk, 0, 0, 1 );
+ Abc_NtkDelete( pNtkRes );
+ if ( pNtk == NULL )
+ {
+ fprintf( pErr, "Balancing before FPGA mapping has failed.\n" );
+ return 1;
+ }
+ fprintf( pOut, "The network was strashed and balanced before FPGA mapping.\n" );
+ // get the new network
+ pNtkRes = Abc_NtkIf( pNtk, pPars );
+ if ( pNtkRes == NULL )
+ {
+ Abc_NtkDelete( pNtk );
+ fprintf( pErr, "FPGA mapping has failed.\n" );
+ return 0;
+ }
+ Abc_NtkDelete( pNtk );
+ }
+ else
+ {
+ // get the new network
+ pNtkRes = Abc_NtkIf( pNtk, pPars );
+ if ( pNtkRes == NULL )
+ {
+ fprintf( pErr, "FPGA mapping has failed.\n" );
+ return 0;
+ }
+ }
+ // replace the current network
+ Abc_FrameReplaceCurrentNetwork( pAbc, pNtkRes );
+ return 0;
+
+usage:
+ if ( pPars->DelayTarget == -1 )
+ sprintf( Buffer, "best possible" );
+ else
+ sprintf( Buffer, "%.2f", pPars->DelayTarget );
+ if ( pPars->nLutSize == -1 )
+ sprintf( LutSize, "library" );
+ else
+ sprintf( LutSize, "%d", pPars->nLutSize );
+ fprintf( pErr, "usage: if [-K num] [-C num] [-F num] [-A num] [-D float] [-parlemsvh]\n" );
+ fprintf( pErr, "\t performs FPGA technology mapping of the network\n" );
+ fprintf( pErr, "\t-K num : the number of LUT inputs (2 < num < %d) [default = %s]\n", IF_MAX_LUTSIZE+1, LutSize );
+ fprintf( pErr, "\t-C num : the max number of priority cuts (0 < num < 2^12) [default = %d]\n", pPars->nCutsMax );
+ fprintf( pErr, "\t-F num : the number of area flow recovery iterations (num >= 0) [default = %d]\n", pPars->nFlowIters );
+ fprintf( pErr, "\t-A num : the number of exact area recovery iterations (num >= 0) [default = %d]\n", pPars->nAreaIters );
+ fprintf( pErr, "\t-D float : sets the delay constraint for the mapping [default = %s]\n", Buffer );
+ fprintf( pErr, "\t-p : toggles preprocessing using several starting points [default = %s]\n", pPars->fPreprocess? "yes": "no" );
+ fprintf( pErr, "\t-a : toggles area-oriented mapping [default = %s]\n", pPars->fArea? "yes": "no" );
+// fprintf( pErr, "\t-f : toggles one fancy feature [default = %s]\n", pPars->fFancy? "yes": "no" );
+ fprintf( pErr, "\t-r : enables expansion/reduction of the best cuts [default = %s]\n", pPars->fExpRed? "yes": "no" );
+ fprintf( pErr, "\t-l : optimizes latch paths for delay, other paths for area [default = %s]\n", pPars->fLatchPaths? "yes": "no" );
+ fprintf( pErr, "\t-e : uses edge-based cut selection heuristics [default = %s]\n", pPars->fEdge? "yes": "no" );
+ fprintf( pErr, "\t-m : enables cut minimization by removing vacuous variables [default = %s]\n", pPars->fCutMin? "yes": "no" );
+ fprintf( pErr, "\t-s : toggles sequential mapping [default = %s]\n", pPars->fSeqMap? "yes": "no" );
+// fprintf( pErr, "\t-t : toggles the use of true sequential cuts [default = %s]\n", pPars->fLiftLeaves? "yes": "no" );
+ fprintf( pErr, "\t-v : toggles verbose output [default = %s]\n", pPars->fVerbose? "yes": "no" );
+ fprintf( pErr, "\t-h : prints the command usage\n");
+ return 1;
+}
+
+
- pNtk = Abc_FrameReadNet(pAbc);
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Abc_CommandInit( Abc_Frame_t * pAbc, int argc, char ** argv )
+{
+ FILE * pOut, * pErr;
+ Abc_Ntk_t * pNtk;
+ Abc_Obj_t * pObj;
+ int c, i;
+ int fZeros;
+ int fOnes;
+ int fRandom;
+ int fDontCare;
+
+ pNtk = Abc_FrameReadNtk(pAbc);
pOut = Abc_FrameReadOut(pAbc);
pErr = Abc_FrameReadErr(pAbc);
// set defaults
- util_getopt_reset();
- while ( ( c = util_getopt( argc, argv, "h" ) ) != EOF )
+ fZeros = 0;
+ fOnes = 0;
+ fRandom = 0;
+ fDontCare = 0;
+ Extra_UtilGetoptReset();
+ while ( ( c = Extra_UtilGetopt( argc, argv, "zordh" ) ) != EOF )
{
switch ( c )
{
+ case 'z':
+ fZeros ^= 1;
+ break;
+ case 'o':
+ fOnes ^= 1;
+ break;
+ case 'r':
+ fRandom ^= 1;
+ break;
+ case 'd':
+ fDontCare ^= 1;
+ break;
case 'h':
goto usage;
default:
@@ -3810,17 +10501,107 @@ int Abc_CommandSeq( Abc_Frame_t * pAbc, int argc, char ** argv )
return 1;
}
- printf( "This command is not yet implemented.\n" );
+ if ( Abc_NtkIsComb(pNtk) )
+ {
+ fprintf( pErr, "The current network is combinational.\n" );
+ return 0;
+ }
+
+ if ( fZeros )
+ {
+ Abc_NtkForEachLatch( pNtk, pObj, i )
+ Abc_LatchSetInit0( pObj );
+ }
+ else if ( fOnes )
+ {
+ Abc_NtkForEachLatch( pNtk, pObj, i )
+ Abc_LatchSetInit1( pObj );
+ }
+ else if ( fRandom )
+ {
+ srand( time(NULL) );
+ Abc_NtkForEachLatch( pNtk, pObj, i )
+ if ( rand() & 1 )
+ Abc_LatchSetInit1( pObj );
+ else
+ Abc_LatchSetInit0( pObj );
+ }
+ else if ( fDontCare )
+ {
+ Abc_NtkForEachLatch( pNtk, pObj, i )
+ Abc_LatchSetInitDc( pObj );
+ }
+ else
+ printf( "The initial states remain unchanged.\n" );
return 0;
- if ( !Abc_NtkIsStrash(pNtk) )
+usage:
+ fprintf( pErr, "usage: init [-zordh]\n" );
+ fprintf( pErr, "\t resets initial states of all latches\n" );
+ fprintf( pErr, "\t-z : set zeros initial states [default = %s]\n", fZeros? "yes": "no" );
+ fprintf( pErr, "\t-o : set ones initial states [default = %s]\n", fOnes? "yes": "no" );
+ fprintf( pErr, "\t-d : set don't-care initial states [default = %s]\n", fDontCare? "yes": "no" );
+ fprintf( pErr, "\t-r : set random initial states [default = %s]\n", fRandom? "yes": "no" );
+ fprintf( pErr, "\t-h : print the command usage\n");
+ return 1;
+}
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Abc_CommandZero( Abc_Frame_t * pAbc, int argc, char ** argv )
+{
+ FILE * pOut, * pErr;
+ Abc_Ntk_t * pNtk, * pNtkRes;
+ int c;
+
+ extern Abc_Ntk_t * Abc_NtkRestrashZero( Abc_Ntk_t * pNtk, bool fCleanup );
+
+ pNtk = Abc_FrameReadNtk(pAbc);
+ pOut = Abc_FrameReadOut(pAbc);
+ pErr = Abc_FrameReadErr(pAbc);
+
+ // set defaults
+ Extra_UtilGetoptReset();
+ while ( ( c = Extra_UtilGetopt( argc, argv, "h" ) ) != EOF )
{
- fprintf( pErr, "Works only for AIG (run \"strash\").\n" );
+ switch ( c )
+ {
+ case 'h':
+ goto usage;
+ default:
+ goto usage;
+ }
+ }
+
+ if ( pNtk == NULL )
+ {
+ fprintf( pErr, "Empty network.\n" );
return 1;
}
+ if ( Abc_NtkIsComb(pNtk) )
+ {
+ fprintf( pErr, "The current network is combinational.\n" );
+ return 0;
+ }
+
+ if ( !Abc_NtkIsStrash(pNtk) )
+ {
+ fprintf( pErr, "This command works only for AIGs.\n" );
+ return 0;
+ }
+
// get the new network
- pNtkRes = Abc_NtkAigToSeq( pNtk );
+ pNtkRes = Abc_NtkRestrashZero( pNtk, 0 );
if ( pNtkRes == NULL )
{
fprintf( pErr, "Converting to sequential AIG has failed.\n" );
@@ -3831,8 +10612,8 @@ int Abc_CommandSeq( Abc_Frame_t * pAbc, int argc, char ** argv )
return 0;
usage:
- fprintf( pErr, "usage: seq [-h]\n" );
- fprintf( pErr, "\t converts AIG into sequential AIG (while sweeping latches)\n" );
+ fprintf( pErr, "usage: zero [-h]\n" );
+ fprintf( pErr, "\t converts latches to have const-0 initial value\n" );
fprintf( pErr, "\t-h : print the command usage\n");
return 1;
}
@@ -3848,33 +10629,98 @@ usage:
SeeAlso []
***********************************************************************/
-int Abc_CommandRetime( Abc_Frame_t * pAbc, int argc, char ** argv )
+int Abc_CommandUndc( Abc_Frame_t * pAbc, int argc, char ** argv )
{
FILE * pOut, * pErr;
Abc_Ntk_t * pNtk;
int c;
- int fForward;
- int fBackward;
- extern Abc_Ntk_t * Abc_NtkSuperChoice( Abc_Ntk_t * pNtk );
+ pNtk = Abc_FrameReadNtk(pAbc);
+ pOut = Abc_FrameReadOut(pAbc);
+ pErr = Abc_FrameReadErr(pAbc);
+
+ // set defaults
+ Extra_UtilGetoptReset();
+ while ( ( c = Extra_UtilGetopt( argc, argv, "h" ) ) != EOF )
+ {
+ switch ( c )
+ {
+ case 'h':
+ goto usage;
+ default:
+ goto usage;
+ }
+ }
- pNtk = Abc_FrameReadNet(pAbc);
+ if ( pNtk == NULL )
+ {
+ fprintf( pErr, "Empty network.\n" );
+ return 1;
+ }
+
+ if ( Abc_NtkIsComb(pNtk) )
+ {
+ fprintf( pErr, "The current network is combinational.\n" );
+ return 0;
+ }
+
+ if ( !Abc_NtkIsLogic(pNtk) )
+ {
+ fprintf( pErr, "This command works only for logic networks.\n" );
+ return 0;
+ }
+
+ // get the new network
+ Abc_NtkConvertDcLatches( pNtk );
+ return 0;
+
+usage:
+ fprintf( pErr, "usage: undc [-h]\n" );
+ fprintf( pErr, "\t converts latches with DC init values into free PIs\n" );
+ fprintf( pErr, "\t-h : print the command usage\n");
+ return 1;
+}
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Abc_CommandPipe( Abc_Frame_t * pAbc, int argc, char ** argv )
+{
+ FILE * pOut, * pErr;
+ Abc_Ntk_t * pNtk;
+ int c;
+ int nLatches;
+ extern void Abc_NtkLatchPipe( Abc_Ntk_t * pNtk, int nLatches );
+
+ pNtk = Abc_FrameReadNtk(pAbc);
pOut = Abc_FrameReadOut(pAbc);
pErr = Abc_FrameReadErr(pAbc);
// set defaults
- fForward = 0;
- fBackward = 0;
- util_getopt_reset();
- while ( ( c = util_getopt( argc, argv, "fbh" ) ) != EOF )
+ nLatches = 5;
+ Extra_UtilGetoptReset();
+ while ( ( c = Extra_UtilGetopt( argc, argv, "Lh" ) ) != EOF )
{
switch ( c )
{
- case 'f':
- fForward ^= 1;
- break;
- case 'b':
- fBackward ^= 1;
+ case 'L':
+ if ( globalUtilOptind >= argc )
+ {
+ fprintf( pErr, "Command line switch \"-L\" should be followed by a positive integer.\n" );
+ goto usage;
+ }
+ nLatches = atoi(argv[globalUtilOptind]);
+ globalUtilOptind++;
+ if ( nLatches < 0 )
+ goto usage;
break;
case 'h':
goto usage;
@@ -3889,35 +10735,95 @@ int Abc_CommandRetime( Abc_Frame_t * pAbc, int argc, char ** argv )
return 1;
}
- printf( "This command is not yet implemented.\n" );
+ if ( Abc_NtkIsComb(pNtk) )
+ {
+ fprintf( pErr, "The current network is combinational.\n" );
+ return 1;
+ }
+
+ // update the network
+ Abc_NtkLatchPipe( pNtk, nLatches );
return 0;
+usage:
+ fprintf( pErr, "usage: pipe [-L num] [-h]\n" );
+ fprintf( pErr, "\t inserts the given number of latches at each PI for pipelining\n" );
+ fprintf( pErr, "\t-L num : the number of latches to insert [default = %d]\n", nLatches );
+ fprintf( pErr, "\t-h : print the command usage\n");
+ return 1;
+}
+
+/**Function*************************************************************
- if ( !Abc_NtkIsSeq(pNtk) )
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Abc_CommandSeq( Abc_Frame_t * pAbc, int argc, char ** argv )
+{
+ FILE * pOut, * pErr;
+ Abc_Ntk_t * pNtk, * pNtkRes;
+ int c;
+
+ pNtk = Abc_FrameReadNtk(pAbc);
+ pOut = Abc_FrameReadOut(pAbc);
+ pErr = Abc_FrameReadErr(pAbc);
+
+ // set defaults
+ Extra_UtilGetoptReset();
+ while ( ( c = Extra_UtilGetopt( argc, argv, "h" ) ) != EOF )
{
- fprintf( pErr, "Works only for sequential AIG.\n" );
+ switch ( c )
+ {
+ case 'h':
+ goto usage;
+ default:
+ goto usage;
+ }
+ }
+
+ if ( pNtk == NULL )
+ {
+ fprintf( pErr, "Empty network.\n" );
+ return 1;
+ }
+
+ if ( Abc_NtkLatchNum(pNtk) == 0 )
+ {
+ fprintf( pErr, "The network has no latches.\n" );
+ return 0;
+ }
+
+ if ( !Abc_NtkIsStrash(pNtk) )
+ {
+ fprintf( pErr, "Conversion to sequential AIG works only for combinational AIGs (run \"strash\").\n" );
return 1;
}
// get the new network
- if ( fForward )
- Abc_NtkSeqRetimeForward( pNtk );
- else if ( fBackward )
- Abc_NtkSeqRetimeBackward( pNtk );
- else
- Abc_NtkSeqRetimeDelay( pNtk );
+// pNtkRes = Abc_NtkAigToSeq( pNtk );
+ pNtkRes = NULL;
+ if ( pNtkRes == NULL )
+ {
+ fprintf( pErr, "Converting to sequential AIG has failed.\n" );
+ return 1;
+ }
+ // replace the current network
+ Abc_FrameReplaceCurrentNetwork( pAbc, pNtkRes );
return 0;
usage:
- fprintf( pErr, "usage: retime [-fbh]\n" );
- fprintf( pErr, "\t retimes sequential AIG (default is Pan's algorithm)\n" );
- fprintf( pErr, "\t-f : toggle forward retiming [default = %s]\n", fForward? "yes": "no" );
- fprintf( pErr, "\t-b : toggle backward retiming [default = %s]\n", fBackward? "yes": "no" );
+ fprintf( pErr, "usage: seq [-h]\n" );
+ fprintf( pErr, "\t converts AIG into sequential AIG\n" );
fprintf( pErr, "\t-h : print the command usage\n");
return 1;
}
-
/**Function*************************************************************
Synopsis []
@@ -3929,69 +10835,67 @@ usage:
SeeAlso []
***********************************************************************/
-int Abc_CommandCec( Abc_Frame_t * pAbc, int argc, char ** argv )
+int Abc_CommandUnseq( Abc_Frame_t * pAbc, int argc, char ** argv )
{
FILE * pOut, * pErr;
- Abc_Ntk_t * pNtk, * pNtk1, * pNtk2;
- int fDelete1, fDelete2;
- char ** pArgvNew;
- int nArgcNew;
+ Abc_Ntk_t * pNtk, * pNtkRes;
int c;
- int fSat;
- int fVerbose;
+ int fShare;
- extern void Abc_NtkCecSat( Abc_Ntk_t * pNtk1, Abc_Ntk_t * pNtk2 );
- extern void Abc_NtkCecFraig( Abc_Ntk_t * pNtk1, Abc_Ntk_t * pNtk2, int fVerbose );
-
-
- pNtk = Abc_FrameReadNet(pAbc);
+ pNtk = Abc_FrameReadNtk(pAbc);
pOut = Abc_FrameReadOut(pAbc);
pErr = Abc_FrameReadErr(pAbc);
// set defaults
- fSat = 0;
- fVerbose = 0;
- util_getopt_reset();
- while ( ( c = util_getopt( argc, argv, "svh" ) ) != EOF )
+ fShare = 1;
+ Extra_UtilGetoptReset();
+ while ( ( c = Extra_UtilGetopt( argc, argv, "sh" ) ) != EOF )
{
switch ( c )
{
case 's':
- fSat ^= 1;
- break;
- case 'v':
- fVerbose ^= 1;
+ fShare ^= 1;
break;
+ case 'h':
+ goto usage;
default:
goto usage;
}
}
- pArgvNew = argv + util_optind;
- nArgcNew = argc - util_optind;
- if ( !Abc_NtkPrepareTwoNtks( pErr, pNtk, pArgvNew, nArgcNew, &pNtk1, &pNtk2, &fDelete1, &fDelete2 ) )
+ if ( pNtk == NULL )
+ {
+ fprintf( pErr, "Empty network.\n" );
return 1;
+ }
+/*
+ if ( !Abc_NtkIsSeq(pNtk) )
+ {
+ fprintf( pErr, "Conversion to combinational AIG works only for sequential AIG (run \"seq\").\n" );
+ return 1;
+ }
+*/
+ // share the latches on the fanout edges
+// if ( fShare )
+// Seq_NtkShareFanouts(pNtk);
- // perform equivalence checking
- if ( fSat )
- Abc_NtkCecSat( pNtk1, pNtk2 );
- else
- Abc_NtkCecFraig( pNtk1, pNtk2, fVerbose );
-
- if ( fDelete1 ) Abc_NtkDelete( pNtk1 );
- if ( fDelete2 ) Abc_NtkDelete( pNtk2 );
+ // get the new network
+// pNtkRes = Abc_NtkSeqToLogicSop( pNtk );
+ pNtkRes = NULL;
+ if ( pNtkRes == NULL )
+ {
+ fprintf( pErr, "Converting sequential AIG into an SOP logic network has failed.\n" );
+ return 1;
+ }
+ // replace the current network
+ Abc_FrameReplaceCurrentNetwork( pAbc, pNtkRes );
return 0;
usage:
- fprintf( pErr, "usage: cec [-svh] <file1> <file2>\n" );
- fprintf( pErr, "\t performs combinational equivalence checking\n" );
- fprintf( pErr, "\t-s : toggle \"SAT only\" and \"FRAIG + SAT\" [default = %s]\n", fSat? "SAT only": "FRAIG + SAT" );
- fprintf( pErr, "\t-v : toggles verbose output [default = %s]\n", fVerbose? "yes": "no" );
+ fprintf( pErr, "usage: unseq [-sh]\n" );
+ fprintf( pErr, "\t converts sequential AIG into an SOP logic network\n" );
+ fprintf( pErr, "\t-s : toggle sharing latches [default = %s]\n", fShare? "yes": "no" );
fprintf( pErr, "\t-h : print the command usage\n");
- fprintf( pErr, "\tfile1 : (optional) the file with the first network\n");
- fprintf( pErr, "\tfile2 : (optional) the file with the second network\n");
- fprintf( pErr, "\t if no files are given, uses the current network and its spec\n");
- fprintf( pErr, "\t if one file is given, uses the current network and the file\n");
return 1;
}
@@ -4006,84 +10910,142 @@ usage:
SeeAlso []
***********************************************************************/
-int Abc_CommandSec( Abc_Frame_t * pAbc, int argc, char ** argv )
+int Abc_CommandRetime( Abc_Frame_t * pAbc, int argc, char ** argv )
{
FILE * pOut, * pErr;
- Abc_Ntk_t * pNtk, * pNtk1, * pNtk2;
- int fDelete1, fDelete2;
- char ** pArgvNew;
- int nArgcNew;
- int c;
- int fSat;
- int nFrames;
-
- extern void Abc_NtkSecSat( Abc_Ntk_t * pNtk1, Abc_Ntk_t * pNtk2, int nFrames );
- extern void Abc_NtkSecFraig( Abc_Ntk_t * pNtk1, Abc_Ntk_t * pNtk2, int nFrames );
-
+ Abc_Ntk_t * pNtk, * pNtkRes;
+ int c, nMaxIters;
+ int fForward;
+ int fBackward;
+ int fOneStep;
+ int fVerbose;
+ int Mode;
+ extern int Abc_NtkRetime( Abc_Ntk_t * pNtk, int Mode, int fForwardOnly, int fBackwardOnly, int fOneStep, int fVerbose );
- pNtk = Abc_FrameReadNet(pAbc);
+ pNtk = Abc_FrameReadNtk(pAbc);
pOut = Abc_FrameReadOut(pAbc);
pErr = Abc_FrameReadErr(pAbc);
// set defaults
- nFrames = 3;
- fSat = 0;
- util_getopt_reset();
- while ( ( c = util_getopt( argc, argv, "Fsh" ) ) != EOF )
+ Mode = 5;
+ fForward = 0;
+ fBackward = 0;
+ fOneStep = 0;
+ fVerbose = 0;
+ nMaxIters = 15;
+ Extra_UtilGetoptReset();
+ while ( ( c = Extra_UtilGetopt( argc, argv, "Mfbsvh" ) ) != EOF )
{
switch ( c )
{
- case 'F':
- if ( util_optind >= argc )
+ case 'M':
+ if ( globalUtilOptind >= argc )
{
- fprintf( pErr, "Command line switch \"-F\" should be followed by an integer.\n" );
+ fprintf( pErr, "Command line switch \"-M\" should be followed by a positive integer.\n" );
goto usage;
}
- nFrames = atoi(argv[util_optind]);
- util_optind++;
- if ( nFrames < 0 )
+ Mode = atoi(argv[globalUtilOptind]);
+ globalUtilOptind++;
+ if ( Mode < 0 )
goto usage;
break;
+ case 'f':
+ fForward ^= 1;
+ break;
+ case 'b':
+ fBackward ^= 1;
+ break;
case 's':
- fSat ^= 1;
+ fOneStep ^= 1;
+ break;
+ case 'v':
+ fVerbose ^= 1;
break;
+ case 'h':
+ goto usage;
default:
goto usage;
}
}
- pArgvNew = argv + util_optind;
- nArgcNew = argc - util_optind;
- if ( !Abc_NtkPrepareTwoNtks( pErr, pNtk, pArgvNew, nArgcNew, &pNtk1, &pNtk2, &fDelete1, &fDelete2 ) )
+ if ( pNtk == NULL )
+ {
+ fprintf( pErr, "Empty network.\n" );
return 1;
+ }
- // perform equivalence checking
- if ( fSat )
- Abc_NtkSecSat( pNtk1, pNtk2, nFrames );
- else
- Abc_NtkSecFraig( pNtk1, pNtk2, nFrames );
+ if ( fForward && fBackward )
+ {
+ fprintf( pErr, "Only one switch \"-f\" or \"-b\" can be selected at a time.\n" );
+ return 1;
+ }
- if ( fDelete1 ) Abc_NtkDelete( pNtk1 );
- if ( fDelete2 ) Abc_NtkDelete( pNtk2 );
- return 0;
+ if ( !Abc_NtkLatchNum(pNtk) )
+ {
+ fprintf( pErr, "The network has no latches. Retiming is not performed.\n" );
+ return 0;
+ }
-usage:
- fprintf( pErr, "usage: sec [-sh] [-F num] <file1> <file2>\n" );
- fprintf( pErr, "\t performs bounded sequential equivalence checking\n" );
- fprintf( pErr, "\t-s : toggle \"SAT only\" and \"FRAIG + SAT\" [default = %s]\n", fSat? "SAT only": "FRAIG + SAT" );
- fprintf( pErr, "\t-h : print the command usage\n");
- fprintf( pErr, "\t-F num : the number of time frames to use [default = %d]\n", nFrames );
- fprintf( pErr, "\tfile1 : (optional) the file with the first network\n");
- fprintf( pErr, "\tfile2 : (optional) the file with the second network\n");
- fprintf( pErr, "\t if no files are given, uses the current network and its spec\n");
- fprintf( pErr, "\t if one file is given, uses the current network and the file\n");
- return 1;
-}
+ if ( Mode < 0 || Mode > 6 )
+ {
+ fprintf( pErr, "The mode (%d) is incorrect. Retiming is not performed.\n", Mode );
+ return 0;
+ }
+ if ( Abc_NtkIsStrash(pNtk) )
+ {
+ if ( Abc_NtkGetChoiceNum(pNtk) )
+ {
+ fprintf( pErr, "Retiming with choice nodes is not implemented.\n" );
+ return 0;
+ }
+ // convert the network into an SOP network
+ pNtkRes = Abc_NtkToLogic( pNtk );
+ // perform the retiming
+ Abc_NtkRetime( pNtkRes, Mode, fForward, fBackward, fOneStep, fVerbose );
+ // replace the current network
+ Abc_FrameReplaceCurrentNetwork( pAbc, pNtkRes );
+ return 0;
+ }
+ // get the network in the SOP form
+ if ( !Abc_NtkToSop(pNtk, 0) )
+ {
+ printf( "Converting to SOPs has failed.\n" );
+ return 0;
+ }
+ if ( !Abc_NtkIsLogic(pNtk) )
+ {
+ fprintf( pErr, "The network is not a logic network. Retiming is not performed.\n" );
+ return 0;
+ }
+ // perform the retiming
+ Abc_NtkRetime( pNtk, Mode, fForward, fBackward, fOneStep, fVerbose );
+ return 0;
+usage:
+ fprintf( pErr, "usage: retime [-M num] [-fbvh]\n" );
+ fprintf( pErr, "\t retimes the current network using one of the algorithms:\n" );
+ fprintf( pErr, "\t 1: most forward retiming\n" );
+ fprintf( pErr, "\t 2: most backward retiming\n" );
+ fprintf( pErr, "\t 3: forward and backward min-area retiming\n" );
+ fprintf( pErr, "\t 4: forward and backward min-delay retiming\n" );
+ fprintf( pErr, "\t 5: mode 3 followed by mode 4\n" );
+ fprintf( pErr, "\t 6: Pan's optimum-delay retiming using binary search\n" );
+ fprintf( pErr, "\t-M num : the retiming algorithm to use [default = %d]\n", Mode );
+ fprintf( pErr, "\t-f : enables forward-only retiming in modes 3,4,5 [default = %s]\n", fForward? "yes": "no" );
+ fprintf( pErr, "\t-b : enables backward-only retiming in modes 3,4,5 [default = %s]\n", fBackward? "yes": "no" );
+ fprintf( pErr, "\t-s : enables retiming one step only in mode 4 [default = %s]\n", fOneStep? "yes": "no" );
+ fprintf( pErr, "\t-v : enables verbose output [default = %s]\n", fVerbose? "yes": "no" );
+ fprintf( pErr, "\t-h : print the command usage\n");
+ return 1;
+// fprintf( pErr, "\t-I num : max number of iterations of l-value computation [default = %d]\n", nMaxIters );
+// fprintf( pErr, "\t-f : toggle forward retiming (for AIGs) [default = %s]\n", fForward? "yes": "no" );
+// fprintf( pErr, "\t-b : toggle backward retiming (for AIGs) [default = %s]\n", fBackward? "yes": "no" );
+// fprintf( pErr, "\t-i : toggle computation of initial state [default = %s]\n", fInitial? "yes": "no" );
+}
/**Function*************************************************************
@@ -4096,35 +11058,43 @@ usage:
SeeAlso []
***********************************************************************/
-int Abc_CommandSeqCleanup( Abc_Frame_t * pAbc, int argc, char ** argv )
+int Abc_CommandDRetime( Abc_Frame_t * pAbc, int argc, char ** argv )
{
FILE * pOut, * pErr;
Abc_Ntk_t * pNtk, * pNtkRes;
- int c;
- int fLatchSweep;
- int fAutoSweep;
+ int nStepsMax;
+ int fFastAlgo;
int fVerbose;
- extern Abc_Ntk_t * Abc_NtkDarLatchSweep( Abc_Ntk_t * pNtk, int fLatchSweep, int fVerbose );
- extern Abc_Ntk_t * Abc_NtkDar( Abc_Ntk_t * pNtk );
+ int c;
+ extern Abc_Ntk_t * Abc_NtkDarRetime( Abc_Ntk_t * pNtk, int nStepsMax, int fVerbose );
+ extern Abc_Ntk_t * Abc_NtkDarRetimeF( Abc_Ntk_t * pNtk, int nStepsMax, int fVerbose );
- pNtk = Abc_FrameReadNet(pAbc);
+ pNtk = Abc_FrameReadNtk(pAbc);
pOut = Abc_FrameReadOut(pAbc);
pErr = Abc_FrameReadErr(pAbc);
// set defaults
- fLatchSweep = 0;
- fAutoSweep = 0;
- fVerbose = 0;
- util_getopt_reset();
- while ( ( c = util_getopt( argc, argv, "lavh" ) ) != EOF )
+ nStepsMax = 100000;
+ fFastAlgo = 0;
+ fVerbose = 0;
+ Extra_UtilGetoptReset();
+ while ( ( c = Extra_UtilGetopt( argc, argv, "Savh" ) ) != EOF )
{
switch ( c )
{
- case 'l':
- fLatchSweep ^= 1;
+ case 'S':
+ if ( globalUtilOptind >= argc )
+ {
+ fprintf( pErr, "Command line switch \"-S\" should be followed by a positive integer.\n" );
+ goto usage;
+ }
+ nStepsMax = atoi(argv[globalUtilOptind]);
+ globalUtilOptind++;
+ if ( nStepsMax < 0 )
+ goto usage;
break;
case 'a':
- fAutoSweep ^= 1;
+ fFastAlgo ^= 1;
break;
case 'v':
fVerbose ^= 1;
@@ -4135,27 +11105,33 @@ int Abc_CommandSeqCleanup( Abc_Frame_t * pAbc, int argc, char ** argv )
goto usage;
}
}
+
if ( pNtk == NULL )
{
fprintf( pErr, "Empty network.\n" );
return 1;
}
- if ( !Abc_NtkIsStrash(pNtk) )
+
+ if ( !Abc_NtkLatchNum(pNtk) )
{
- fprintf( pErr, "Only works for structrally hashed networks.\n" );
- return 1;
+ fprintf( pErr, "The network has no latches. Retiming is not performed.\n" );
+ return 0;
}
- if ( !Abc_NtkLatchNum(pNtk) )
+
+ if ( !Abc_NtkIsStrash(pNtk) )
{
- fprintf( pErr, "Only works for sequential networks.\n" );
- return 1;
+ printf( "This command works only for structrally hashed networks. Run \"st\".\n" );
+ return 0;
}
- // modify the current network
- pNtkRes = Abc_NtkDarLatchSweep( pNtk, fLatchSweep, fVerbose );
-// pNtkRes = Abc_NtkDar( pNtk );
+
+ // perform the retiming
+ if ( fFastAlgo )
+ pNtkRes = Abc_NtkDarRetime( pNtk, nStepsMax, fVerbose );
+ else
+ pNtkRes = Abc_NtkDarRetimeF( pNtk, nStepsMax, fVerbose );
if ( pNtkRes == NULL )
{
- fprintf( pErr, "Sequential cleanup has failed.\n" );
+ fprintf( pErr, "Retiming has failed.\n" );
return 1;
}
// replace the current network
@@ -4163,18 +11139,14 @@ int Abc_CommandSeqCleanup( Abc_Frame_t * pAbc, int argc, char ** argv )
return 0;
usage:
- fprintf( pErr, "usage: scleanup [-lvh]\n" );
- fprintf( pErr, "\t performs sequential cleanup\n" );
- fprintf( pErr, "\t - removes nodes/latches that do not feed into POs\n" );
- fprintf( pErr, "\t - removes stuck-at and identical latches (latch sweep)\n" );
-// fprintf( pErr, "\t - replaces autonomous logic by free PI variables\n" );
- fprintf( pErr, "\t-l : toggle sweeping latches [default = %s]\n", fLatchSweep? "yes": "no" );
-// fprintf( pErr, "\t-a : toggle removing autonomous logic [default = %s]\n", fAutoSweep? "yes": "no" );
- fprintf( pErr, "\t-v : toggle verbose output [default = %s]\n", fVerbose? "yes": "no" );
+ fprintf( pErr, "usage: dretime [-S num] [-avh]\n" );
+ fprintf( pErr, "\t retimes the current network forward\n" );
+ fprintf( pErr, "\t-S num : the max number of retiming steps to perform [default = %d]\n", nStepsMax );
+ fprintf( pErr, "\t-a : enables a fast algorithm [default = %s]\n", fFastAlgo? "yes": "no" );
+ fprintf( pErr, "\t-v : enables verbose output [default = %s]\n", fVerbose? "yes": "no" );
fprintf( pErr, "\t-h : print the command usage\n");
return 1;
}
-
/**Function*************************************************************
Synopsis []
@@ -4186,51 +11158,68 @@ usage:
SeeAlso []
***********************************************************************/
-int Abc_CommandLcorr( Abc_Frame_t * pAbc, int argc, char ** argv )
+int Abc_CommandFlowRetime( Abc_Frame_t * pAbc, int argc, char ** argv )
{
FILE * pOut, * pErr;
Abc_Ntk_t * pNtk, * pNtkRes;
- int c;
- int nFramesP;
- int nConfMax;
+ int c, nMaxIters;
+ int fForward;
+ int fBackward;
int fVerbose;
- extern Abc_Ntk_t * Abc_NtkDarLcorr( Abc_Ntk_t * pNtk, int nFramesP, int nConfMax, int fVerbose );
+ int fComputeInit;
+ int maxDelay;
+
+ extern Abc_Ntk_t* Abc_FlowRetime_MinReg( Abc_Ntk_t * pNtk, int fVerbose, int fComputeInit,
+ int fForward, int fBackward, int nMaxIters,
+ int maxDelay);
- pNtk = Abc_FrameReadNet(pAbc);
+ pNtk = Abc_FrameReadNtk(pAbc);
pOut = Abc_FrameReadOut(pAbc);
pErr = Abc_FrameReadErr(pAbc);
// set defaults
- nFramesP = 0;
- nConfMax = 10000;
- fVerbose = 0;
- util_getopt_reset();
- while ( ( c = util_getopt( argc, argv, "PCvh" ) ) != EOF )
+ fForward = 0;
+ fBackward = 0;
+ fComputeInit = 1;
+ fVerbose = 0;
+ nMaxIters = 999;
+ maxDelay = 0;
+ Extra_UtilGetoptReset();
+ while ( ( c = Extra_UtilGetopt( argc, argv, "MDfbivh" ) ) != EOF )
{
switch ( c )
{
- case 'P':
- if ( util_optind >= argc )
+ case 'M':
+ if ( globalUtilOptind >= argc )
{
- fprintf( pErr, "Command line switch \"-P\" should be followed by an integer.\n" );
+ fprintf( pErr, "Command line switch \"-M\" should be followed by a positive integer.\n" );
goto usage;
}
- nFramesP = atoi(argv[util_optind]);
- util_optind++;
- if ( nFramesP < 0 )
+ nMaxIters = atoi(argv[globalUtilOptind]);
+ globalUtilOptind++;
+ if ( nMaxIters < 0 )
goto usage;
break;
- case 'C':
- if ( util_optind >= argc )
+ case 'D':
+ if ( globalUtilOptind >= argc )
{
- fprintf( pErr, "Command line switch \"-C\" should be followed by an integer.\n" );
+ fprintf( pErr, "Command line switch \"-D\" should be followed by a positive integer.\n" );
goto usage;
}
- nConfMax = atoi(argv[util_optind]);
- util_optind++;
- if ( nConfMax < 0 )
+ maxDelay = atoi(argv[globalUtilOptind]);
+ globalUtilOptind++;
+ if ( maxDelay < 0 )
goto usage;
break;
+ case 'f':
+ fForward ^= 1;
+ break;
+ case 'i':
+ fComputeInit ^= 1;
+ break;
+ case 'b':
+ fBackward ^= 1;
+ break;
case 'v':
fVerbose ^= 1;
break;
@@ -4247,34 +11236,295 @@ int Abc_CommandLcorr( Abc_Frame_t * pAbc, int argc, char ** argv )
return 1;
}
- if ( Abc_NtkIsComb(pNtk) )
+ if ( fForward && fBackward )
{
- fprintf( pErr, "The network is combinational (run \"fraig\" or \"fraig_sweep\").\n" );
+ fprintf( pErr, "Only one switch \"-f\" or \"-b\" can be selected at a time.\n" );
return 1;
}
- if ( !Abc_NtkIsStrash(pNtk) )
+ if ( !Abc_NtkLatchNum(pNtk) )
{
- printf( "This command works only for structrally hashed networks. Run \"st\".\n" );
+ fprintf( pErr, "The network has no latches. Retiming is not performed.\n" );
return 0;
}
+ if ( Abc_NtkGetChoiceNum(pNtk) )
+ {
+ fprintf( pErr, "Retiming with choice nodes is not implemented.\n" );
+ return 0;
+ }
+
+ // perform the retiming
+ pNtkRes = Abc_FlowRetime_MinReg( pNtk, fVerbose, fComputeInit, fForward, fBackward, nMaxIters, maxDelay );
+
+ if (pNtkRes != pNtk)
+ Abc_FrameReplaceCurrentNetwork( pAbc, pNtkRes );
+
+ return 0;
+
+usage:
+ fprintf( pErr, "usage: fretime [-M num] [-D num] [-fbvih]\n" );
+ fprintf( pErr, "\t retimes the current network using flow-based algorithm\n" );
+ fprintf( pErr, "\t-M num : the maximum number of iterations [default = %d]\n", nMaxIters );
+ fprintf( pErr, "\t-D num : the maximum delay [default = none]\n" );
+ fprintf( pErr, "\t-i : enables init state computation [default = %s]\n", fComputeInit? "yes": "no" );
+ fprintf( pErr, "\t-f : enables forward-only retiming [default = %s]\n", fForward? "yes": "no" );
+ fprintf( pErr, "\t-b : enables backward-only retiming [default = %s]\n", fBackward? "yes": "no" );
+ fprintf( pErr, "\t-v : enables verbose output [default = %s]\n", fVerbose? "yes": "no" );
+ fprintf( pErr, "\t-h : print the command usage\n");
+ return 1;
+}
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Abc_CommandSeqFpga( Abc_Frame_t * pAbc, int argc, char ** argv )
+{
+ FILE * pOut, * pErr;
+ Abc_Ntk_t * pNtk, * pNtkNew, * pNtkRes;
+ int c, nMaxIters;
+ int fVerbose;
+
+ pNtk = Abc_FrameReadNtk(pAbc);
+ pOut = Abc_FrameReadOut(pAbc);
+ pErr = Abc_FrameReadErr(pAbc);
+
+ // set defaults
+ nMaxIters = 15;
+ fVerbose = 0;
+ Extra_UtilGetoptReset();
+ while ( ( c = Extra_UtilGetopt( argc, argv, "Ivh" ) ) != EOF )
+ {
+ switch ( c )
+ {
+ case 'I':
+ if ( globalUtilOptind >= argc )
+ {
+ fprintf( pErr, "Command line switch \"-I\" should be followed by a positive integer.\n" );
+ goto usage;
+ }
+ nMaxIters = atoi(argv[globalUtilOptind]);
+ globalUtilOptind++;
+ if ( nMaxIters < 0 )
+ goto usage;
+ break;
+ case 'v':
+ fVerbose ^= 1;
+ break;
+ case 'h':
+ goto usage;
+ default:
+ goto usage;
+ }
+ }
+
+ if ( pNtk == NULL )
+ {
+ fprintf( pErr, "Empty network.\n" );
+ return 1;
+ }
+
+ if ( Abc_NtkHasAig(pNtk) )
+ {
+/*
+ // quit if there are choice nodes
+ if ( Abc_NtkGetChoiceNum(pNtk) )
+ {
+ fprintf( pErr, "Currently cannot map/retime networks with choice nodes.\n" );
+ return 0;
+ }
+*/
+// if ( Abc_NtkIsStrash(pNtk) )
+// pNtkNew = Abc_NtkAigToSeq(pNtk);
+// else
+// pNtkNew = Abc_NtkDup(pNtk);
+ pNtkNew = NULL;
+ }
+ else
+ {
+ // strash and balance the network
+ pNtkNew = Abc_NtkStrash( pNtk, 0, 0, 0 );
+ if ( pNtkNew == NULL )
+ {
+ fprintf( pErr, "Strashing before FPGA mapping/retiming has failed.\n" );
+ return 1;
+ }
+
+ pNtkNew = Abc_NtkBalance( pNtkRes = pNtkNew, 0, 0, 1 );
+ Abc_NtkDelete( pNtkRes );
+ if ( pNtkNew == NULL )
+ {
+ fprintf( pErr, "Balancing before FPGA mapping has failed.\n" );
+ return 1;
+ }
+
+ // convert into a sequential AIG
+// pNtkNew = Abc_NtkAigToSeq( pNtkRes = pNtkNew );
+ pNtkNew = NULL;
+ Abc_NtkDelete( pNtkRes );
+ if ( pNtkNew == NULL )
+ {
+ fprintf( pErr, "Converting into a seq AIG before FPGA mapping/retiming has failed.\n" );
+ return 1;
+ }
+
+ fprintf( pOut, "The network was strashed and balanced before FPGA mapping/retiming.\n" );
+ }
+
// get the new network
- pNtkRes = Abc_NtkDarLcorr( pNtk, nFramesP, nConfMax, fVerbose );
+// pNtkRes = Seq_NtkFpgaMapRetime( pNtkNew, nMaxIters, fVerbose );
+ pNtkRes = NULL;
if ( pNtkRes == NULL )
{
- fprintf( pErr, "Sequential sweeping has failed.\n" );
+// fprintf( pErr, "Sequential FPGA mapping has failed.\n" );
+ Abc_NtkDelete( pNtkNew );
+ return 0;
+ }
+ Abc_NtkDelete( pNtkNew );
+ // replace the current network
+ Abc_FrameReplaceCurrentNetwork( pAbc, pNtkRes );
+ return 0;
+
+usage:
+ fprintf( pErr, "usage: sfpga [-I num] [-vh]\n" );
+ fprintf( pErr, "\t performs integrated sequential FPGA mapping/retiming\n" );
+ fprintf( pErr, "\t-I num : max number of iterations of l-value computation [default = %d]\n", nMaxIters );
+ fprintf( pErr, "\t-v : toggle verbose output [default = %s]\n", fVerbose? "yes": "no" );
+ fprintf( pErr, "\t-h : print the command usage\n");
+ return 1;
+}
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Abc_CommandSeqMap( Abc_Frame_t * pAbc, int argc, char ** argv )
+{
+ FILE * pOut, * pErr;
+ Abc_Ntk_t * pNtk, * pNtkNew, * pNtkRes;
+ int c, nMaxIters;
+ int fVerbose;
+
+ pNtk = Abc_FrameReadNtk(pAbc);
+ pOut = Abc_FrameReadOut(pAbc);
+ pErr = Abc_FrameReadErr(pAbc);
+
+ // set defaults
+ nMaxIters = 15;
+ fVerbose = 0;
+ Extra_UtilGetoptReset();
+ while ( ( c = Extra_UtilGetopt( argc, argv, "Ivh" ) ) != EOF )
+ {
+ switch ( c )
+ {
+ case 'I':
+ if ( globalUtilOptind >= argc )
+ {
+ fprintf( pErr, "Command line switch \"-I\" should be followed by a positive integer.\n" );
+ goto usage;
+ }
+ nMaxIters = atoi(argv[globalUtilOptind]);
+ globalUtilOptind++;
+ if ( nMaxIters < 0 )
+ goto usage;
+ break;
+ case 'v':
+ fVerbose ^= 1;
+ break;
+ case 'h':
+ goto usage;
+ default:
+ goto usage;
+ }
+ }
+
+ if ( pNtk == NULL )
+ {
+ fprintf( pErr, "Empty network.\n" );
return 1;
}
+
+ if ( Abc_NtkHasAig(pNtk) )
+ {
+/*
+ // quit if there are choice nodes
+ if ( Abc_NtkGetChoiceNum(pNtk) )
+ {
+ fprintf( pErr, "Currently cannot map/retime networks with choice nodes.\n" );
+ return 0;
+ }
+*/
+// if ( Abc_NtkIsStrash(pNtk) )
+// pNtkNew = Abc_NtkAigToSeq(pNtk);
+// else
+// pNtkNew = Abc_NtkDup(pNtk);
+ pNtkNew = NULL;
+ }
+ else
+ {
+ // strash and balance the network
+ pNtkNew = Abc_NtkStrash( pNtk, 0, 0, 0 );
+ if ( pNtkNew == NULL )
+ {
+ fprintf( pErr, "Strashing before SC mapping/retiming has failed.\n" );
+ return 1;
+ }
+
+ pNtkNew = Abc_NtkBalance( pNtkRes = pNtkNew, 0, 0, 1 );
+ Abc_NtkDelete( pNtkRes );
+ if ( pNtkNew == NULL )
+ {
+ fprintf( pErr, "Balancing before SC mapping/retiming has failed.\n" );
+ return 1;
+ }
+
+ // convert into a sequential AIG
+// pNtkNew = Abc_NtkAigToSeq( pNtkRes = pNtkNew );
+ pNtkNew = NULL;
+ Abc_NtkDelete( pNtkRes );
+ if ( pNtkNew == NULL )
+ {
+ fprintf( pErr, "Converting into a seq AIG before SC mapping/retiming has failed.\n" );
+ return 1;
+ }
+
+ fprintf( pOut, "The network was strashed and balanced before SC mapping/retiming.\n" );
+ }
+
+ // get the new network
+// pNtkRes = Seq_MapRetime( pNtkNew, nMaxIters, fVerbose );
+ pNtkRes = NULL;
+ if ( pNtkRes == NULL )
+ {
+// fprintf( pErr, "Sequential FPGA mapping has failed.\n" );
+ Abc_NtkDelete( pNtkNew );
+ return 0;
+ }
+ Abc_NtkDelete( pNtkNew );
+
// replace the current network
Abc_FrameReplaceCurrentNetwork( pAbc, pNtkRes );
return 0;
usage:
- fprintf( pErr, "usage: lcorr [-P num] [-C num] [-vh]\n" );
- fprintf( pErr, "\t computes latch correspondence using 1-step induction\n" );
- fprintf( pErr, "\t-P num : number of time frames to use as the prefix [default = %d]\n", nFramesP );
- fprintf( pErr, "\t-C num : max conflict number when proving latch equivalence [default = %d]\n", nConfMax );
+ fprintf( pErr, "usage: smap [-I num] [-vh]\n" );
+ fprintf( pErr, "\t performs integrated sequential standard-cell mapping/retiming\n" );
+ fprintf( pErr, "\t-I num : max number of iterations of l-value computation [default = %d]\n", nMaxIters );
fprintf( pErr, "\t-v : toggle verbose output [default = %s]\n", fVerbose? "yes": "no" );
fprintf( pErr, "\t-h : print the command usage\n");
return 1;
@@ -4307,7 +11557,7 @@ int Abc_CommandSeqSweep( Abc_Frame_t * pAbc, int argc, char ** argv )
int fVerbose;
extern Abc_Ntk_t * Abc_NtkDarSeqSweep( Abc_Ntk_t * pNtk, int nFramesP, int nFrames, int nMaxImps, int nMaxLevs, int fRewrite, int fUseImps, int fLatchCorr, int fWriteImps, int fVerbose );
- pNtk = Abc_FrameReadNet(pAbc);
+ pNtk = Abc_FrameReadNtk(pAbc);
pOut = Abc_FrameReadOut(pAbc);
pErr = Abc_FrameReadErr(pAbc);
@@ -4321,52 +11571,52 @@ int Abc_CommandSeqSweep( Abc_Frame_t * pAbc, int argc, char ** argv )
fLatchCorr = 0;
fWriteImps = 0;
fVerbose = 0;
- util_getopt_reset();
- while ( ( c = util_getopt( argc, argv, "PFILirlevh" ) ) != EOF )
+ Extra_UtilGetoptReset();
+ while ( ( c = Extra_UtilGetopt( argc, argv, "PFILirlevh" ) ) != EOF )
{
switch ( c )
{
case 'P':
- if ( util_optind >= argc )
+ if ( globalUtilOptind >= argc )
{
fprintf( pErr, "Command line switch \"-P\" should be followed by an integer.\n" );
goto usage;
}
- nFramesP = atoi(argv[util_optind]);
- util_optind++;
+ nFramesP = atoi(argv[globalUtilOptind]);
+ globalUtilOptind++;
if ( nFramesP < 0 )
goto usage;
break;
case 'F':
- if ( util_optind >= argc )
+ if ( globalUtilOptind >= argc )
{
fprintf( pErr, "Command line switch \"-F\" should be followed by an integer.\n" );
goto usage;
}
- nFramesK = atoi(argv[util_optind]);
- util_optind++;
+ nFramesK = atoi(argv[globalUtilOptind]);
+ globalUtilOptind++;
if ( nFramesK <= 0 )
goto usage;
break;
case 'I':
- if ( util_optind >= argc )
+ if ( globalUtilOptind >= argc )
{
fprintf( pErr, "Command line switch \"-I\" should be followed by an integer.\n" );
goto usage;
}
- nMaxImps = atoi(argv[util_optind]);
- util_optind++;
+ nMaxImps = atoi(argv[globalUtilOptind]);
+ globalUtilOptind++;
if ( nMaxImps <= 0 )
goto usage;
break;
case 'L':
- if ( util_optind >= argc )
+ if ( globalUtilOptind >= argc )
{
fprintf( pErr, "Command line switch \"-L\" should be followed by an integer.\n" );
goto usage;
}
- nMaxLevs = atoi(argv[util_optind]);
- util_optind++;
+ nMaxLevs = atoi(argv[globalUtilOptind]);
+ globalUtilOptind++;
if ( nMaxLevs <= 0 )
goto usage;
break;
@@ -4422,13 +11672,13 @@ int Abc_CommandSeqSweep( Abc_Frame_t * pAbc, int argc, char ** argv )
return 0;
usage:
- fprintf( pErr, "usage: ssweep [-P num] [-F num] [-lrevh]\n" );
+ fprintf( pErr, "usage: ssweep [-P num] [-F num] [-I num] [-ilrevh]\n" );
fprintf( pErr, "\t performs sequential sweep using K-step induction\n" );
fprintf( pErr, "\t-P num : number of time frames to use as the prefix [default = %d]\n", nFramesP );
fprintf( pErr, "\t-F num : number of time frames for induction (1=simple) [default = %d]\n", nFramesK );
-// fprintf( pErr, "\t-I num : max number of implications to consider [default = %d]\n", nMaxImps );
+ fprintf( pErr, "\t-I num : max number of implications to consider [default = %d]\n", nMaxImps );
fprintf( pErr, "\t-L num : max number of levels to consider (0=all) [default = %d]\n", nMaxLevs );
-// fprintf( pErr, "\t-i : toggle using implications [default = %s]\n", fUseImps? "yes": "no" );
+ fprintf( pErr, "\t-i : toggle using implications [default = %s]\n", fUseImps? "yes": "no" );
fprintf( pErr, "\t-l : toggle latch correspondence only [default = %s]\n", fLatchCorr? "yes": "no" );
fprintf( pErr, "\t-r : toggle AIG rewriting [default = %s]\n", fRewrite? "yes": "no" );
fprintf( pErr, "\t-e : toggle writing implications as assertions [default = %s]\n", fWriteImps? "yes": "no" );
@@ -4448,6 +11698,928 @@ usage:
SeeAlso []
***********************************************************************/
+int Abc_CommandLcorr( Abc_Frame_t * pAbc, int argc, char ** argv )
+{
+ FILE * pOut, * pErr;
+ Abc_Ntk_t * pNtk, * pNtkRes;
+ int c;
+ int nFramesP;
+ int nConfMax;
+ int fVerbose;
+ extern Abc_Ntk_t * Abc_NtkDarLcorr( Abc_Ntk_t * pNtk, int nFramesP, int nConfMax, int fVerbose );
+
+ pNtk = Abc_FrameReadNtk(pAbc);
+ pOut = Abc_FrameReadOut(pAbc);
+ pErr = Abc_FrameReadErr(pAbc);
+
+ // set defaults
+ nFramesP = 0;
+ nConfMax = 10000;
+ fVerbose = 0;
+ Extra_UtilGetoptReset();
+ while ( ( c = Extra_UtilGetopt( argc, argv, "PCvh" ) ) != EOF )
+ {
+ switch ( c )
+ {
+ case 'P':
+ if ( globalUtilOptind >= argc )
+ {
+ fprintf( pErr, "Command line switch \"-P\" should be followed by an integer.\n" );
+ goto usage;
+ }
+ nFramesP = atoi(argv[globalUtilOptind]);
+ globalUtilOptind++;
+ if ( nFramesP < 0 )
+ goto usage;
+ break;
+ case 'C':
+ if ( globalUtilOptind >= argc )
+ {
+ fprintf( pErr, "Command line switch \"-C\" should be followed by an integer.\n" );
+ goto usage;
+ }
+ nConfMax = atoi(argv[globalUtilOptind]);
+ globalUtilOptind++;
+ if ( nConfMax < 0 )
+ goto usage;
+ break;
+ case 'v':
+ fVerbose ^= 1;
+ break;
+ case 'h':
+ goto usage;
+ default:
+ goto usage;
+ }
+ }
+
+ if ( pNtk == NULL )
+ {
+ fprintf( pErr, "Empty network.\n" );
+ return 1;
+ }
+
+ if ( Abc_NtkIsComb(pNtk) )
+ {
+ fprintf( pErr, "The network is combinational (run \"fraig\" or \"fraig_sweep\").\n" );
+ return 1;
+ }
+
+ if ( !Abc_NtkIsStrash(pNtk) )
+ {
+ printf( "This command works only for structrally hashed networks. Run \"st\".\n" );
+ return 0;
+ }
+
+ // get the new network
+ pNtkRes = Abc_NtkDarLcorr( pNtk, nFramesP, nConfMax, fVerbose );
+ if ( pNtkRes == NULL )
+ {
+ fprintf( pErr, "Sequential sweeping has failed.\n" );
+ return 1;
+ }
+ // replace the current network
+ Abc_FrameReplaceCurrentNetwork( pAbc, pNtkRes );
+ return 0;
+
+usage:
+ fprintf( pErr, "usage: lcorr [-P num] [-C num] [-vh]\n" );
+ fprintf( pErr, "\t computes latch correspondence using 1-step induction\n" );
+ fprintf( pErr, "\t-P num : number of time frames to use as the prefix [default = %d]\n", nFramesP );
+ fprintf( pErr, "\t-C num : max conflict number when proving latch equivalence [default = %d]\n", nConfMax );
+ fprintf( pErr, "\t-v : toggle verbose output [default = %s]\n", fVerbose? "yes": "no" );
+ fprintf( pErr, "\t-h : print the command usage\n");
+ return 1;
+}
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Abc_CommandSeqCleanup( Abc_Frame_t * pAbc, int argc, char ** argv )
+{
+ FILE * pOut, * pErr;
+ Abc_Ntk_t * pNtk, * pNtkRes;
+ int c;
+ int fLatchSweep;
+ int fAutoSweep;
+ int fVerbose;
+ extern Abc_Ntk_t * Abc_NtkDarLatchSweep( Abc_Ntk_t * pNtk, int fLatchSweep, int fVerbose );
+
+ pNtk = Abc_FrameReadNtk(pAbc);
+ pOut = Abc_FrameReadOut(pAbc);
+ pErr = Abc_FrameReadErr(pAbc);
+
+ // set defaults
+ fLatchSweep = 0;
+ fAutoSweep = 0;
+ fVerbose = 0;
+ Extra_UtilGetoptReset();
+ while ( ( c = Extra_UtilGetopt( argc, argv, "lavh" ) ) != EOF )
+ {
+ switch ( c )
+ {
+ case 'l':
+ fLatchSweep ^= 1;
+ break;
+ case 'a':
+ fAutoSweep ^= 1;
+ break;
+ case 'v':
+ fVerbose ^= 1;
+ break;
+ case 'h':
+ goto usage;
+ default:
+ goto usage;
+ }
+ }
+ if ( pNtk == NULL )
+ {
+ fprintf( pErr, "Empty network.\n" );
+ return 1;
+ }
+ if ( !Abc_NtkIsStrash(pNtk) )
+ {
+ fprintf( pErr, "Only works for structrally hashed networks.\n" );
+ return 1;
+ }
+ if ( !Abc_NtkLatchNum(pNtk) )
+ {
+ fprintf( pErr, "Only works for sequential networks.\n" );
+ return 1;
+ }
+ // modify the current network
+ pNtkRes = Abc_NtkDarLatchSweep( pNtk, fLatchSweep, fVerbose );
+ if ( pNtkRes == NULL )
+ {
+ fprintf( pErr, "Sequential cleanup has failed.\n" );
+ return 1;
+ }
+ // replace the current network
+ Abc_FrameReplaceCurrentNetwork( pAbc, pNtkRes );
+ return 0;
+
+usage:
+ fprintf( pErr, "usage: scleanup [-lvh]\n" );
+ fprintf( pErr, "\t performs sequential cleanup\n" );
+ fprintf( pErr, "\t - removes nodes/latches that do not feed into POs\n" );
+ fprintf( pErr, "\t - removes stuck-at and identical latches (latch sweep)\n" );
+// fprintf( pErr, "\t - replaces autonomous logic by free PI variables\n" );
+ fprintf( pErr, "\t-l : toggle sweeping latches [default = %s]\n", fLatchSweep? "yes": "no" );
+// fprintf( pErr, "\t-a : toggle removing autonomous logic [default = %s]\n", fAutoSweep? "yes": "no" );
+ fprintf( pErr, "\t-v : toggle verbose output [default = %s]\n", fVerbose? "yes": "no" );
+ fprintf( pErr, "\t-h : print the command usage\n");
+ return 1;
+}
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Abc_CommandCycle( Abc_Frame_t * pAbc, int argc, char ** argv )
+{
+ FILE * pOut, * pErr;
+ Abc_Ntk_t * pNtk;
+ int c;
+ int nFrames;
+ int fVerbose;
+ extern void Abc_NtkCycleInitState( Abc_Ntk_t * pNtk, int nFrames, int fVerbose );
+ extern void Abc_NtkCycleInitStateSop( Abc_Ntk_t * pNtk, int nFrames, int fVerbose );
+
+ pNtk = Abc_FrameReadNtk(pAbc);
+ pOut = Abc_FrameReadOut(pAbc);
+ pErr = Abc_FrameReadErr(pAbc);
+
+ // set defaults
+ nFrames = 100;
+ fVerbose = 0;
+ Extra_UtilGetoptReset();
+ while ( ( c = Extra_UtilGetopt( argc, argv, "Fvh" ) ) != EOF )
+ {
+ switch ( c )
+ {
+ case 'F':
+ if ( globalUtilOptind >= argc )
+ {
+ fprintf( pErr, "Command line switch \"-F\" should be followed by an integer.\n" );
+ goto usage;
+ }
+ nFrames = atoi(argv[globalUtilOptind]);
+ globalUtilOptind++;
+ if ( nFrames < 0 )
+ goto usage;
+ break;
+ case 'v':
+ fVerbose ^= 1;
+ break;
+ case 'h':
+ goto usage;
+ default:
+ goto usage;
+ }
+ }
+ if ( pNtk == NULL )
+ {
+ fprintf( pErr, "Empty network.\n" );
+ return 1;
+ }
+
+ if ( !Abc_NtkIsStrash(pNtk) && !Abc_NtkIsSopLogic(pNtk) )
+ {
+ fprintf( pErr, "Only works for strashed networks or logic SOP networks.\n" );
+ return 1;
+ }
+ if ( !Abc_NtkLatchNum(pNtk) )
+ {
+ fprintf( pErr, "Only works for sequential networks.\n" );
+ return 1;
+ }
+
+ if ( Abc_NtkIsStrash(pNtk) )
+ Abc_NtkCycleInitState( pNtk, nFrames, fVerbose );
+ else
+ Abc_NtkCycleInitStateSop( pNtk, nFrames, fVerbose );
+ return 0;
+
+usage:
+ fprintf( pErr, "usage: cycle [-F num] [-vh]\n" );
+ fprintf( pErr, "\t cycles sequiential circuit for the given number of timeframes\n" );
+ fprintf( pErr, "\t to derive a new initial state (which may be on the envelope)\n" );
+ fprintf( pErr, "\t-F num : the number of frames to simulate [default = %d]\n", nFrames );
+ fprintf( pErr, "\t-v : toggle printing verbose information [default = %s]\n", fVerbose? "yes": "no" );
+ fprintf( pErr, "\t-h : print the command usage\n");
+ return 1;
+}
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Abc_CommandXsim( Abc_Frame_t * pAbc, int argc, char ** argv )
+{
+ FILE * pOut, * pErr;
+ Abc_Ntk_t * pNtk;
+ int c;
+ int nFrames;
+ int fXInputs;
+ int fXState;
+ int fVerbose;
+ extern void Abc_NtkXValueSimulate( Abc_Ntk_t * pNtk, int nFrames, int fXInputs, int fXState, int fVerbose );
+
+ pNtk = Abc_FrameReadNtk(pAbc);
+ pOut = Abc_FrameReadOut(pAbc);
+ pErr = Abc_FrameReadErr(pAbc);
+
+ // set defaults
+ nFrames = 10;
+ fXInputs = 0;
+ fXState = 0;
+ fVerbose = 0;
+ Extra_UtilGetoptReset();
+ while ( ( c = Extra_UtilGetopt( argc, argv, "Fisvh" ) ) != EOF )
+ {
+ switch ( c )
+ {
+ case 'F':
+ if ( globalUtilOptind >= argc )
+ {
+ fprintf( pErr, "Command line switch \"-F\" should be followed by an integer.\n" );
+ goto usage;
+ }
+ nFrames = atoi(argv[globalUtilOptind]);
+ globalUtilOptind++;
+ if ( nFrames < 0 )
+ goto usage;
+ break;
+ case 'i':
+ fXInputs ^= 1;
+ break;
+ case 's':
+ fXState ^= 1;
+ break;
+ case 'v':
+ fVerbose ^= 1;
+ break;
+ case 'h':
+ goto usage;
+ default:
+ goto usage;
+ }
+ }
+ if ( pNtk == NULL )
+ {
+ fprintf( pErr, "Empty network.\n" );
+ return 1;
+ }
+
+ if ( !Abc_NtkIsStrash(pNtk) )
+ {
+ fprintf( pErr, "Only works for strashed networks.\n" );
+ return 1;
+ }
+ if ( !Abc_NtkLatchNum(pNtk) )
+ {
+ fprintf( pErr, "Only works for sequential networks.\n" );
+ return 1;
+ }
+ Abc_NtkXValueSimulate( pNtk, nFrames, fXInputs, fXState, fVerbose );
+ return 0;
+
+usage:
+ fprintf( pErr, "usage: xsim [-F num] [-isvh]\n" );
+ fprintf( pErr, "\t performs X-valued simulation of the AIG\n" );
+ fprintf( pErr, "\t-F num : the number of frames to simulate [default = %d]\n", nFrames );
+ fprintf( pErr, "\t-i : toggle X-valued representation of inputs [default = %s]\n", fXInputs? "yes": "no" );
+ fprintf( pErr, "\t-s : toggle X-valued representation of state [default = %s]\n", fXState? "yes": "no" );
+ fprintf( pErr, "\t-v : toggle printing verbose information [default = %s]\n", fVerbose? "yes": "no" );
+ fprintf( pErr, "\t-h : print the command usage\n");
+ return 1;
+}
+
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Abc_CommandSim( Abc_Frame_t * pAbc, int argc, char ** argv )
+{
+ FILE * pOut, * pErr;
+ Abc_Ntk_t * pNtk;
+ int c;
+ int nFrames;
+ int nWords;
+ int fVerbose;
+ extern int Abc_NtkDarSeqSim( Abc_Ntk_t * pNtk, int nFrames, int nWords, int fVerbose );
+
+ pNtk = Abc_FrameReadNtk(pAbc);
+ pOut = Abc_FrameReadOut(pAbc);
+ pErr = Abc_FrameReadErr(pAbc);
+
+ // set defaults
+ nFrames = 32;
+ nWords = 8;
+ fVerbose = 0;
+ Extra_UtilGetoptReset();
+ while ( ( c = Extra_UtilGetopt( argc, argv, "FWvh" ) ) != EOF )
+ {
+ switch ( c )
+ {
+ case 'F':
+ if ( globalUtilOptind >= argc )
+ {
+ fprintf( pErr, "Command line switch \"-F\" should be followed by an integer.\n" );
+ goto usage;
+ }
+ nFrames = atoi(argv[globalUtilOptind]);
+ globalUtilOptind++;
+ if ( nFrames < 0 )
+ goto usage;
+ break;
+ case 'W':
+ if ( globalUtilOptind >= argc )
+ {
+ fprintf( pErr, "Command line switch \"-W\" should be followed by an integer.\n" );
+ goto usage;
+ }
+ nWords = atoi(argv[globalUtilOptind]);
+ globalUtilOptind++;
+ if ( nWords < 0 )
+ goto usage;
+ break;
+ case 'v':
+ fVerbose ^= 1;
+ break;
+ case 'h':
+ goto usage;
+ default:
+ goto usage;
+ }
+ }
+ if ( pNtk == NULL )
+ {
+ fprintf( pErr, "Empty network.\n" );
+ return 1;
+ }
+
+ if ( !Abc_NtkIsStrash(pNtk) )
+ {
+ fprintf( pErr, "Only works for strashed networks.\n" );
+ return 1;
+ }
+ if ( !Abc_NtkLatchNum(pNtk) )
+ {
+ fprintf( pErr, "Only works for sequential networks.\n" );
+ return 1;
+ }
+
+ FREE( pNtk->pSeqModel );
+ Abc_NtkDarSeqSim( pNtk, nFrames, nWords, fVerbose );
+ return 0;
+
+usage:
+ fprintf( pErr, "usage: sim [-F num] [-W num] [-vh]\n" );
+ fprintf( pErr, "\t performs random simulation of the sequentail miter\n" );
+ fprintf( pErr, "\t-F num : the number of frames to simulate [default = %d]\n", nFrames );
+ fprintf( pErr, "\t-W num : the number of words to simulate [default = %d]\n", nWords );
+ fprintf( pErr, "\t-v : toggle printing verbose information [default = %s]\n", fVerbose? "yes": "no" );
+ fprintf( pErr, "\t-h : print the command usage\n");
+ return 1;
+}
+
+
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Abc_CommandCec( Abc_Frame_t * pAbc, int argc, char ** argv )
+{
+ char Buffer[16];
+ FILE * pOut, * pErr;
+ Abc_Ntk_t * pNtk, * pNtk1, * pNtk2;
+ int fDelete1, fDelete2;
+ char ** pArgvNew;
+ int nArgcNew;
+ int c;
+ int fSat;
+ int fVerbose;
+ int nSeconds;
+ int nPartSize;
+ int nConfLimit;
+ int nInsLimit;
+ int fPartition;
+
+ extern void Abc_NtkCecSat( Abc_Ntk_t * pNtk1, Abc_Ntk_t * pNtk2, int nConfLimit, int nInsLimit );
+ extern void Abc_NtkCecFraig( Abc_Ntk_t * pNtk1, Abc_Ntk_t * pNtk2, int nSeconds, int fVerbose );
+ extern void Abc_NtkCecFraigPart( Abc_Ntk_t * pNtk1, Abc_Ntk_t * pNtk2, int nSeconds, int nPartSize, int fVerbose );
+ extern void Abc_NtkCecFraigPartAuto( Abc_Ntk_t * pNtk1, Abc_Ntk_t * pNtk2, int nSeconds, int fVerbose );
+
+ pNtk = Abc_FrameReadNtk(pAbc);
+ pOut = Abc_FrameReadOut(pAbc);
+ pErr = Abc_FrameReadErr(pAbc);
+
+ // set defaults
+ fSat = 0;
+ fVerbose = 0;
+ nSeconds = 20;
+ nPartSize = 0;
+ nConfLimit = 10000;
+ nInsLimit = 0;
+ fPartition = 0;
+ Extra_UtilGetoptReset();
+ while ( ( c = Extra_UtilGetopt( argc, argv, "TCIPpsvh" ) ) != EOF )
+ {
+ switch ( c )
+ {
+ case 'T':
+ if ( globalUtilOptind >= argc )
+ {
+ fprintf( pErr, "Command line switch \"-T\" should be followed by an integer.\n" );
+ goto usage;
+ }
+ nSeconds = atoi(argv[globalUtilOptind]);
+ globalUtilOptind++;
+ if ( nSeconds < 0 )
+ goto usage;
+ break;
+ case 'C':
+ if ( globalUtilOptind >= argc )
+ {
+ fprintf( pErr, "Command line switch \"-C\" should be followed by an integer.\n" );
+ goto usage;
+ }
+ nConfLimit = atoi(argv[globalUtilOptind]);
+ globalUtilOptind++;
+ if ( nConfLimit < 0 )
+ goto usage;
+ break;
+ case 'I':
+ if ( globalUtilOptind >= argc )
+ {
+ fprintf( pErr, "Command line switch \"-I\" should be followed by an integer.\n" );
+ goto usage;
+ }
+ nInsLimit = atoi(argv[globalUtilOptind]);
+ globalUtilOptind++;
+ if ( nInsLimit < 0 )
+ goto usage;
+ break;
+ case 'P':
+ if ( globalUtilOptind >= argc )
+ {
+ fprintf( pErr, "Command line switch \"-P\" should be followed by an integer.\n" );
+ goto usage;
+ }
+ nPartSize = atoi(argv[globalUtilOptind]);
+ globalUtilOptind++;
+ if ( nPartSize < 0 )
+ goto usage;
+ break;
+ case 'p':
+ fPartition ^= 1;
+ break;
+ case 's':
+ fSat ^= 1;
+ break;
+ case 'v':
+ fVerbose ^= 1;
+ break;
+ default:
+ goto usage;
+ }
+ }
+
+ pArgvNew = argv + globalUtilOptind;
+ nArgcNew = argc - globalUtilOptind;
+ if ( !Abc_NtkPrepareTwoNtks( pErr, pNtk, pArgvNew, nArgcNew, &pNtk1, &pNtk2, &fDelete1, &fDelete2 ) )
+ return 1;
+
+ // perform equivalence checking
+ if ( fPartition )
+ Abc_NtkCecFraigPartAuto( pNtk1, pNtk2, nSeconds, fVerbose );
+ else if ( nPartSize )
+ Abc_NtkCecFraigPart( pNtk1, pNtk2, nSeconds, nPartSize, fVerbose );
+ else if ( fSat )
+ Abc_NtkCecSat( pNtk1, pNtk2, nConfLimit, nInsLimit );
+ else
+ Abc_NtkCecFraig( pNtk1, pNtk2, nSeconds, fVerbose );
+
+ if ( fDelete1 ) Abc_NtkDelete( pNtk1 );
+ if ( fDelete2 ) Abc_NtkDelete( pNtk2 );
+ return 0;
+
+usage:
+ if ( nPartSize == 0 )
+ strcpy( Buffer, "unused" );
+ else
+ sprintf( Buffer, "%d", nPartSize );
+ fprintf( pErr, "usage: cec [-T num] [-C num] [-I num] [-P num] [-psvh] <file1> <file2>\n" );
+ fprintf( pErr, "\t performs combinational equivalence checking\n" );
+ fprintf( pErr, "\t-T num : approximate runtime limit in seconds [default = %d]\n", nSeconds );
+ fprintf( pErr, "\t-C num : limit on the number of conflicts [default = %d]\n", nConfLimit );
+ fprintf( pErr, "\t-I num : limit on the number of clause inspections [default = %d]\n", nInsLimit );
+ fprintf( pErr, "\t-P num : partition size for multi-output networks [default = %s]\n", Buffer );
+ fprintf( pErr, "\t-p : toggle automatic partitioning [default = %s]\n", fPartition? "yes": "no" );
+ fprintf( pErr, "\t-s : toggle \"SAT only\" and \"FRAIG + SAT\" [default = %s]\n", fSat? "SAT only": "FRAIG + SAT" );
+ fprintf( pErr, "\t-v : toggles verbose output [default = %s]\n", fVerbose? "yes": "no" );
+ fprintf( pErr, "\t-h : print the command usage\n");
+ fprintf( pErr, "\tfile1 : (optional) the file with the first network\n");
+ fprintf( pErr, "\tfile2 : (optional) the file with the second network\n");
+ fprintf( pErr, "\t if no files are given, uses the current network and its spec\n");
+ fprintf( pErr, "\t if one file is given, uses the current network and the file\n");
+ return 1;
+}
+
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Abc_CommandDCec( Abc_Frame_t * pAbc, int argc, char ** argv )
+{
+ FILE * pOut, * pErr;
+ Abc_Ntk_t * pNtk, * pNtk1, * pNtk2;
+ int fDelete1, fDelete2;
+ char ** pArgvNew;
+ int nArgcNew;
+ int c;
+ int fSat;
+ int fVerbose;
+ int nSeconds;
+ int nConfLimit;
+ int nInsLimit;
+ int fPartition;
+ int fMiter;
+
+ extern int Abc_NtkDSat( Abc_Ntk_t * pNtk, sint64 nConfLimit, sint64 nInsLimit, int fVerbose );
+ extern int Abc_NtkDarCec( Abc_Ntk_t * pNtk1, Abc_Ntk_t * pNtk2, int fPartition, int fVerbose );
+
+ pNtk = Abc_FrameReadNtk(pAbc);
+ pOut = Abc_FrameReadOut(pAbc);
+ pErr = Abc_FrameReadErr(pAbc);
+
+ // set defaults
+ fSat = 0;
+ fVerbose = 0;
+ nSeconds = 20;
+ nConfLimit = 10000;
+ nInsLimit = 0;
+ fPartition = 0;
+ fMiter = 0;
+ Extra_UtilGetoptReset();
+ while ( ( c = Extra_UtilGetopt( argc, argv, "TCIpmsvh" ) ) != EOF )
+ {
+ switch ( c )
+ {
+ case 'T':
+ if ( globalUtilOptind >= argc )
+ {
+ fprintf( pErr, "Command line switch \"-T\" should be followed by an integer.\n" );
+ goto usage;
+ }
+ nSeconds = atoi(argv[globalUtilOptind]);
+ globalUtilOptind++;
+ if ( nSeconds < 0 )
+ goto usage;
+ break;
+ case 'C':
+ if ( globalUtilOptind >= argc )
+ {
+ fprintf( pErr, "Command line switch \"-C\" should be followed by an integer.\n" );
+ goto usage;
+ }
+ nConfLimit = atoi(argv[globalUtilOptind]);
+ globalUtilOptind++;
+ if ( nConfLimit < 0 )
+ goto usage;
+ break;
+ case 'I':
+ if ( globalUtilOptind >= argc )
+ {
+ fprintf( pErr, "Command line switch \"-I\" should be followed by an integer.\n" );
+ goto usage;
+ }
+ nInsLimit = atoi(argv[globalUtilOptind]);
+ globalUtilOptind++;
+ if ( nInsLimit < 0 )
+ goto usage;
+ break;
+ case 'p':
+ fPartition ^= 1;
+ break;
+ case 'm':
+ fMiter ^= 1;
+ break;
+ case 's':
+ fSat ^= 1;
+ break;
+ case 'v':
+ fVerbose ^= 1;
+ break;
+ default:
+ goto usage;
+ }
+ }
+
+ pArgvNew = argv + globalUtilOptind;
+ nArgcNew = argc - globalUtilOptind;
+ if ( fMiter )
+ {
+ if ( pNtk == NULL )
+ {
+ fprintf( pErr, "Empty network.\n" );
+ return 1;
+ }
+ if ( Abc_NtkIsStrash(pNtk) )
+ {
+ pNtk1 = pNtk;
+ fDelete1 = 0;
+ }
+ else
+ {
+ pNtk1 = Abc_NtkStrash( pNtk, 0, 1, 0 );
+ fDelete1 = 1;
+ }
+ pNtk2 = NULL;
+ fDelete2 = 0;
+ }
+ else
+ {
+ if ( !Abc_NtkPrepareTwoNtks( pErr, pNtk, pArgvNew, nArgcNew, &pNtk1, &pNtk2, &fDelete1, &fDelete2 ) )
+ return 1;
+ }
+
+ // perform equivalence checking
+ if ( fSat && fMiter )
+ Abc_NtkDSat( pNtk1, nConfLimit, nInsLimit, fVerbose );
+ else
+ Abc_NtkDarCec( pNtk1, pNtk2, fPartition, fVerbose );
+
+ if ( fDelete1 ) Abc_NtkDelete( pNtk1 );
+ if ( fDelete2 ) Abc_NtkDelete( pNtk2 );
+ return 0;
+
+usage:
+ fprintf( pErr, "usage: dcec [-T num] [-C num] [-I num] [-mpsvh] <file1> <file2>\n" );
+ fprintf( pErr, "\t performs combinational equivalence checking\n" );
+ fprintf( pErr, "\t-T num : approximate runtime limit in seconds [default = %d]\n", nSeconds );
+ fprintf( pErr, "\t-C num : limit on the number of conflicts [default = %d]\n", nConfLimit );
+ fprintf( pErr, "\t-I num : limit on the number of clause inspections [default = %d]\n", nInsLimit );
+ fprintf( pErr, "\t-m : toggle working on two networks or a miter [default = %s]\n", fMiter? "miter": "two networks" );
+ fprintf( pErr, "\t-p : toggle automatic partitioning [default = %s]\n", fPartition? "yes": "no" );
+ fprintf( pErr, "\t-s : toggle \"SAT only\" (miter) or \"FRAIG + SAT\" [default = %s]\n", fSat? "SAT only": "FRAIG + SAT" );
+ fprintf( pErr, "\t-v : toggles verbose output [default = %s]\n", fVerbose? "yes": "no" );
+ fprintf( pErr, "\t-h : print the command usage\n");
+ fprintf( pErr, "\tfile1 : (optional) the file with the first network\n");
+ fprintf( pErr, "\tfile2 : (optional) the file with the second network\n");
+ fprintf( pErr, "\t if no files are given, uses the current network and its spec\n");
+ fprintf( pErr, "\t if one file is given, uses the current network and the file\n");
+ return 1;
+}
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Abc_CommandSec( Abc_Frame_t * pAbc, int argc, char ** argv )
+{
+ FILE * pOut, * pErr;
+ Abc_Ntk_t * pNtk, * pNtk1, * pNtk2;
+ int fDelete1, fDelete2;
+ char ** pArgvNew;
+ int nArgcNew;
+ int c;
+ int fRetime;
+ int fSat;
+ int fVerbose;
+ int nFrames;
+ int nSeconds;
+ int nConfLimit;
+ int nInsLimit;
+
+ extern void Abc_NtkSecSat( Abc_Ntk_t * pNtk1, Abc_Ntk_t * pNtk2, int nConfLimit, int nInsLimit, int nFrames );
+ extern int Abc_NtkSecFraig( Abc_Ntk_t * pNtk1, Abc_Ntk_t * pNtk2, int nSeconds, int nFrames, int fVerbose );
+ extern void Abc_NtkSecRetime( Abc_Ntk_t * pNtk1, Abc_Ntk_t * pNtk2 );
+
+
+ pNtk = Abc_FrameReadNtk(pAbc);
+ pOut = Abc_FrameReadOut(pAbc);
+ pErr = Abc_FrameReadErr(pAbc);
+
+ // set defaults
+ fRetime = 0; // verification after retiming
+ fSat = 0;
+ fVerbose = 0;
+ nFrames = 5;
+ nSeconds = 20;
+ nConfLimit = 10000;
+ nInsLimit = 0;
+ Extra_UtilGetoptReset();
+ while ( ( c = Extra_UtilGetopt( argc, argv, "FTCIsrvh" ) ) != EOF )
+ {
+ switch ( c )
+ {
+ case 'F':
+ if ( globalUtilOptind >= argc )
+ {
+ fprintf( pErr, "Command line switch \"-F\" should be followed by an integer.\n" );
+ goto usage;
+ }
+ nFrames = atoi(argv[globalUtilOptind]);
+ globalUtilOptind++;
+ if ( nFrames <= 0 )
+ goto usage;
+ break;
+ case 'T':
+ if ( globalUtilOptind >= argc )
+ {
+ fprintf( pErr, "Command line switch \"-T\" should be followed by an integer.\n" );
+ goto usage;
+ }
+ nSeconds = atoi(argv[globalUtilOptind]);
+ globalUtilOptind++;
+ if ( nSeconds < 0 )
+ goto usage;
+ break;
+ case 'C':
+ if ( globalUtilOptind >= argc )
+ {
+ fprintf( pErr, "Command line switch \"-C\" should be followed by an integer.\n" );
+ goto usage;
+ }
+ nConfLimit = atoi(argv[globalUtilOptind]);
+ globalUtilOptind++;
+ if ( nConfLimit < 0 )
+ goto usage;
+ break;
+ case 'I':
+ if ( globalUtilOptind >= argc )
+ {
+ fprintf( pErr, "Command line switch \"-I\" should be followed by an integer.\n" );
+ goto usage;
+ }
+ nInsLimit = atoi(argv[globalUtilOptind]);
+ globalUtilOptind++;
+ if ( nInsLimit < 0 )
+ goto usage;
+ break;
+ case 'r':
+ fRetime ^= 1;
+ break;
+ case 'v':
+ fVerbose ^= 1;
+ break;
+ case 's':
+ fSat ^= 1;
+ break;
+ default:
+ goto usage;
+ }
+ }
+
+ pArgvNew = argv + globalUtilOptind;
+ nArgcNew = argc - globalUtilOptind;
+ if ( !Abc_NtkPrepareTwoNtks( pErr, pNtk, pArgvNew, nArgcNew, &pNtk1, &pNtk2, &fDelete1, &fDelete2 ) )
+ return 1;
+
+ if ( Abc_NtkLatchNum(pNtk1) == 0 || Abc_NtkLatchNum(pNtk2) == 0 )
+ {
+ printf( "The network has no latches. Used combinational command \"cec\".\n" );
+ return 0;
+ }
+
+ // perform equivalence checking
+ if ( fRetime )
+ Abc_NtkSecRetime( pNtk1, pNtk2 );
+ else if ( fSat )
+ Abc_NtkSecSat( pNtk1, pNtk2, nConfLimit, nInsLimit, nFrames );
+ else
+ Abc_NtkSecFraig( pNtk1, pNtk2, nSeconds, nFrames, fVerbose );
+
+ if ( fDelete1 ) Abc_NtkDelete( pNtk1 );
+ if ( fDelete2 ) Abc_NtkDelete( pNtk2 );
+ return 0;
+
+usage:
+ fprintf( pErr, "usage: sec [-F num] [-T num] [-C num] [-I num] [-srvh] <file1> <file2>\n" );
+ fprintf( pErr, "\t performs bounded sequential equivalence checking\n" );
+ fprintf( pErr, "\t (there is also an unbounded SEC commands, \"dsec\" and \"dprove\")\n" );
+ fprintf( pErr, "\t-s : toggle \"SAT only\" and \"FRAIG + SAT\" [default = %s]\n", fSat? "SAT only": "FRAIG + SAT" );
+ fprintf( pErr, "\t-r : toggles retiming verification [default = %s]\n", fVerbose? "yes": "no" );
+ fprintf( pErr, "\t-v : toggles verbose output [default = %s]\n", fVerbose? "yes": "no" );
+ fprintf( pErr, "\t-h : print the command usage\n");
+ fprintf( pErr, "\t-F num : the number of time frames to use [default = %d]\n", nFrames );
+ fprintf( pErr, "\t-T num : approximate runtime limit in seconds [default = %d]\n", nSeconds );
+ fprintf( pErr, "\t-C num : limit on the number of conflicts [default = %d]\n", nConfLimit );
+ fprintf( pErr, "\t-I num : limit on the number of inspections [default = %d]\n", nInsLimit );
+ fprintf( pErr, "\tfile1 : (optional) the file with the first network\n");
+ fprintf( pErr, "\tfile2 : (optional) the file with the second network\n");
+ fprintf( pErr, "\t if no files are given, uses the current network and its spec\n");
+ fprintf( pErr, "\t if one file is given, uses the current network and the file\n");
+ return 1;
+}
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
int Abc_CommandDSec( Abc_Frame_t * pAbc, int argc, char ** argv )
{
FILE * pOut, * pErr;
@@ -4463,7 +12635,7 @@ int Abc_CommandDSec( Abc_Frame_t * pAbc, int argc, char ** argv )
extern int Abc_NtkDarSec( Abc_Ntk_t * pNtk1, Abc_Ntk_t * pNtk2, int nFrames, int fRetimeFirst, int fVerbose, int fVeryVerbose );
- pNtk = Abc_FrameReadNet(pAbc);
+ pNtk = Abc_FrameReadNtk(pAbc);
pOut = Abc_FrameReadOut(pAbc);
pErr = Abc_FrameReadErr(pAbc);
@@ -4472,19 +12644,19 @@ int Abc_CommandDSec( Abc_Frame_t * pAbc, int argc, char ** argv )
fRetimeFirst = 1;
fVerbose = 0;
fVeryVerbose = 0;
- util_getopt_reset();
- while ( ( c = util_getopt( argc, argv, "Krwvh" ) ) != EOF )
+ Extra_UtilGetoptReset();
+ while ( ( c = Extra_UtilGetopt( argc, argv, "Krwvh" ) ) != EOF )
{
switch ( c )
{
case 'K':
- if ( util_optind >= argc )
+ if ( globalUtilOptind >= argc )
{
fprintf( pErr, "Command line switch \"-K\" should be followed by an integer.\n" );
goto usage;
}
- nFrames = atoi(argv[util_optind]);
- util_optind++;
+ nFrames = atoi(argv[globalUtilOptind]);
+ globalUtilOptind++;
if ( nFrames < 0 )
goto usage;
break;
@@ -4502,8 +12674,8 @@ int Abc_CommandDSec( Abc_Frame_t * pAbc, int argc, char ** argv )
}
}
- pArgvNew = argv + util_optind;
- nArgcNew = argc - util_optind;
+ pArgvNew = argv + globalUtilOptind;
+ nArgcNew = argc - globalUtilOptind;
if ( !Abc_NtkPrepareTwoNtks( pErr, pNtk, pArgvNew, nArgcNew, &pNtk1, &pNtk2, &fDelete1, &fDelete2 ) )
return 1;
@@ -4535,6 +12707,1092 @@ usage:
return 1;
}
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Abc_CommandDProve( Abc_Frame_t * pAbc, int argc, char ** argv )
+{
+ FILE * pOut, * pErr;
+ Abc_Ntk_t * pNtk;
+ int c;
+ int fRetimeFirst;
+ int fVerbose;
+ int fVeryVerbose;
+ int nFrames;
+
+ extern int Abc_NtkDarProve( Abc_Ntk_t * pNtk, int nFrames, int fRetimeFirst, int fVerbose, int fVeryVerbose );
+
+ pNtk = Abc_FrameReadNtk(pAbc);
+ pOut = Abc_FrameReadOut(pAbc);
+ pErr = Abc_FrameReadErr(pAbc);
+
+ // set defaults
+ nFrames = 16;
+ fRetimeFirst = 1;
+ fVerbose = 0;
+ fVeryVerbose = 0;
+ Extra_UtilGetoptReset();
+ while ( ( c = Extra_UtilGetopt( argc, argv, "Frwvh" ) ) != EOF )
+ {
+ switch ( c )
+ {
+ case 'F':
+ if ( globalUtilOptind >= argc )
+ {
+ fprintf( pErr, "Command line switch \"-K\" should be followed by an integer.\n" );
+ goto usage;
+ }
+ nFrames = atoi(argv[globalUtilOptind]);
+ globalUtilOptind++;
+ if ( nFrames < 0 )
+ goto usage;
+ break;
+ case 'r':
+ fRetimeFirst ^= 1;
+ break;
+ case 'w':
+ fVeryVerbose ^= 1;
+ break;
+ case 'v':
+ fVerbose ^= 1;
+ break;
+ default:
+ goto usage;
+ }
+ }
+
+ if ( Abc_NtkLatchNum(pNtk) == 0 )
+ {
+ printf( "The network has no latches. Used combinational command \"iprove\".\n" );
+ return 0;
+ }
+ if ( !Abc_NtkIsStrash(pNtk) )
+ {
+ printf( "This command works only for structrally hashed networks. Run \"st\".\n" );
+ return 0;
+ }
+
+ // perform verification
+ Abc_NtkDarProve( pNtk, nFrames, fRetimeFirst, fVerbose, fVeryVerbose );
+ return 0;
+
+usage:
+ fprintf( pErr, "usage: dprove [-F num] [-rwvh]\n" );
+ fprintf( pErr, "\t performs SEC on the sequential miter\n" );
+ fprintf( pErr, "\t-F num : the limit on the depth of induction [default = %d]\n", nFrames );
+ fprintf( pErr, "\t-r : toggles forward retiming at the beginning [default = %s]\n", fRetimeFirst? "yes": "no" );
+ fprintf( pErr, "\t-v : toggles verbose output [default = %s]\n", fVerbose? "yes": "no" );
+ fprintf( pErr, "\t-w : toggles additional verbose output [default = %s]\n", fVeryVerbose? "yes": "no" );
+ fprintf( pErr, "\t-h : print the command usage\n");
+ return 1;
+}
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Abc_CommandSat( Abc_Frame_t * pAbc, int argc, char ** argv )
+{
+ FILE * pOut, * pErr;
+ Abc_Ntk_t * pNtk;
+ int c;
+ int RetValue;
+ int fVerbose;
+ int nConfLimit;
+ int nInsLimit;
+ int clk;
+
+ pNtk = Abc_FrameReadNtk(pAbc);
+ pOut = Abc_FrameReadOut(pAbc);
+ pErr = Abc_FrameReadErr(pAbc);
+
+ // set defaults
+ fVerbose = 0;
+ nConfLimit = 100000;
+ nInsLimit = 0;
+ Extra_UtilGetoptReset();
+ while ( ( c = Extra_UtilGetopt( argc, argv, "CIvh" ) ) != EOF )
+ {
+ switch ( c )
+ {
+ case 'C':
+ if ( globalUtilOptind >= argc )
+ {
+ fprintf( pErr, "Command line switch \"-C\" should be followed by an integer.\n" );
+ goto usage;
+ }
+ nConfLimit = atoi(argv[globalUtilOptind]);
+ globalUtilOptind++;
+ if ( nConfLimit < 0 )
+ goto usage;
+ break;
+ case 'I':
+ if ( globalUtilOptind >= argc )
+ {
+ fprintf( pErr, "Command line switch \"-I\" should be followed by an integer.\n" );
+ goto usage;
+ }
+ nInsLimit = atoi(argv[globalUtilOptind]);
+ globalUtilOptind++;
+ if ( nInsLimit < 0 )
+ goto usage;
+ break;
+ case 'v':
+ fVerbose ^= 1;
+ break;
+ case 'h':
+ goto usage;
+ default:
+ goto usage;
+ }
+ }
+
+ if ( pNtk == NULL )
+ {
+ fprintf( pErr, "Empty network.\n" );
+ return 1;
+ }
+ if ( Abc_NtkLatchNum(pNtk) > 0 )
+ {
+ fprintf( stdout, "Currently can only solve the miter for combinational circuits.\n" );
+ return 0;
+ }
+
+ clk = clock();
+ if ( Abc_NtkIsStrash(pNtk) )
+ {
+ RetValue = Abc_NtkMiterSat( pNtk, (sint64)nConfLimit, (sint64)nInsLimit, fVerbose, NULL, NULL );
+ }
+ else
+ {
+ assert( Abc_NtkIsLogic(pNtk) );
+ Abc_NtkToBdd( pNtk );
+ RetValue = Abc_NtkMiterSat( pNtk, (sint64)nConfLimit, (sint64)nInsLimit, fVerbose, NULL, NULL );
+ }
+
+ // verify that the pattern is correct
+ if ( RetValue == 0 && Abc_NtkPoNum(pNtk) == 1 )
+ {
+ //int i;
+ //Abc_Obj_t * pObj;
+ int * pSimInfo = Abc_NtkVerifySimulatePattern( pNtk, pNtk->pModel );
+ if ( pSimInfo[0] != 1 )
+ printf( "ERROR in Abc_NtkMiterSat(): Generated counter example is invalid.\n" );
+ free( pSimInfo );
+ /*
+ // print model
+ Abc_NtkForEachPi( pNtk, pObj, i )
+ {
+ printf( "%d", (int)(pNtk->pModel[i] > 0) );
+ if ( i == 70 )
+ break;
+ }
+ printf( "\n" );
+ */
+ }
+
+ if ( RetValue == -1 )
+ printf( "UNDECIDED " );
+ else if ( RetValue == 0 )
+ printf( "SATISFIABLE " );
+ else
+ printf( "UNSATISFIABLE " );
+ //printf( "\n" );
+ PRT( "Time", clock() - clk );
+ return 0;
+
+usage:
+ fprintf( pErr, "usage: sat [-C num] [-I num] [-vh]\n" );
+ fprintf( pErr, "\t solves the combinational miter using SAT solver MiniSat-1.14\n" );
+ fprintf( pErr, "\t derives CNF from the current network and leave it unchanged\n" );
+ fprintf( pErr, "\t (there is also a newer SAT solving command \"dsat\")\n" );
+ fprintf( pErr, "\t-C num : limit on the number of conflicts [default = %d]\n", nConfLimit );
+ fprintf( pErr, "\t-I num : limit on the number of inspections [default = %d]\n", nInsLimit );
+ fprintf( pErr, "\t-v : prints verbose information [default = %s]\n", fVerbose? "yes": "no" );
+ fprintf( pErr, "\t-h : print the command usage\n");
+ return 1;
+}
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Abc_CommandDSat( Abc_Frame_t * pAbc, int argc, char ** argv )
+{
+ FILE * pOut, * pErr;
+ Abc_Ntk_t * pNtk;
+ int c;
+ int RetValue;
+ int fVerbose;
+ int nConfLimit;
+ int nInsLimit;
+ int clk;
+
+ extern int Abc_NtkDSat( Abc_Ntk_t * pNtk, sint64 nConfLimit, sint64 nInsLimit, int fVerbose );
+
+
+ pNtk = Abc_FrameReadNtk(pAbc);
+ pOut = Abc_FrameReadOut(pAbc);
+ pErr = Abc_FrameReadErr(pAbc);
+
+ // set defaults
+ fVerbose = 0;
+ nConfLimit = 100000;
+ nInsLimit = 0;
+ Extra_UtilGetoptReset();
+ while ( ( c = Extra_UtilGetopt( argc, argv, "CIvh" ) ) != EOF )
+ {
+ switch ( c )
+ {
+ case 'C':
+ if ( globalUtilOptind >= argc )
+ {
+ fprintf( pErr, "Command line switch \"-C\" should be followed by an integer.\n" );
+ goto usage;
+ }
+ nConfLimit = atoi(argv[globalUtilOptind]);
+ globalUtilOptind++;
+ if ( nConfLimit < 0 )
+ goto usage;
+ break;
+ case 'I':
+ if ( globalUtilOptind >= argc )
+ {
+ fprintf( pErr, "Command line switch \"-I\" should be followed by an integer.\n" );
+ goto usage;
+ }
+ nInsLimit = atoi(argv[globalUtilOptind]);
+ globalUtilOptind++;
+ if ( nInsLimit < 0 )
+ goto usage;
+ break;
+ case 'v':
+ fVerbose ^= 1;
+ break;
+ case 'h':
+ goto usage;
+ default:
+ goto usage;
+ }
+ }
+
+ if ( pNtk == NULL )
+ {
+ fprintf( pErr, "Empty network.\n" );
+ return 1;
+ }
+ if ( Abc_NtkLatchNum(pNtk) > 0 )
+ {
+ fprintf( stdout, "Currently can only solve the miter for combinational circuits.\n" );
+ return 0;
+ }
+ if ( Abc_NtkPoNum(pNtk) != 1 )
+ {
+ fprintf( stdout, "Currently expects a single-output miter.\n" );
+ return 0;
+ }
+
+ if ( !Abc_NtkIsStrash(pNtk) )
+ {
+ fprintf( stdout, "Currently only works for structurally hashed circuits.\n" );
+ return 0;
+ }
+
+ clk = clock();
+ RetValue = Abc_NtkDSat( pNtk, (sint64)nConfLimit, (sint64)nInsLimit, fVerbose );
+ // verify that the pattern is correct
+ if ( RetValue == 0 && Abc_NtkPoNum(pNtk) == 1 )
+ {
+ //int i;
+ //Abc_Obj_t * pObj;
+ int * pSimInfo = Abc_NtkVerifySimulatePattern( pNtk, pNtk->pModel );
+ if ( pSimInfo[0] != 1 )
+ printf( "ERROR in Abc_NtkMiterSat(): Generated counter example is invalid.\n" );
+ free( pSimInfo );
+ /*
+ // print model
+ Abc_NtkForEachPi( pNtk, pObj, i )
+ {
+ printf( "%d", (int)(pNtk->pModel[i] > 0) );
+ if ( i == 70 )
+ break;
+ }
+ printf( "\n" );
+ */
+ }
+
+ if ( RetValue == -1 )
+ printf( "UNDECIDED " );
+ else if ( RetValue == 0 )
+ printf( "SATISFIABLE " );
+ else
+ printf( "UNSATISFIABLE " );
+ //printf( "\n" );
+ PRT( "Time", clock() - clk );
+ return 0;
+
+usage:
+ fprintf( pErr, "usage: dsat [-C num] [-I num] [-vh]\n" );
+ fprintf( pErr, "\t solves the combinational miter using SAT solver MiniSat-1.14\n" );
+ fprintf( pErr, "\t derives CNF from the current network and leave it unchanged\n" );
+ fprintf( pErr, "\t-C num : limit on the number of conflicts [default = %d]\n", nConfLimit );
+ fprintf( pErr, "\t-I num : limit on the number of inspections [default = %d]\n", nInsLimit );
+ fprintf( pErr, "\t-v : prints verbose information [default = %s]\n", fVerbose? "yes": "no" );
+ fprintf( pErr, "\t-h : print the command usage\n");
+ return 1;
+}
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Abc_CommandProve( Abc_Frame_t * pAbc, int argc, char ** argv )
+{
+ FILE * pOut, * pErr;
+ Abc_Ntk_t * pNtk, * pNtkTemp;
+ Prove_Params_t Params, * pParams = &Params;
+ int c, clk, RetValue;
+
+ pNtk = Abc_FrameReadNtk(pAbc);
+ pOut = Abc_FrameReadOut(pAbc);
+ pErr = Abc_FrameReadErr(pAbc);
+
+ // set defaults
+ Prove_ParamsSetDefault( pParams );
+ Extra_UtilGetoptReset();
+ while ( ( c = Extra_UtilGetopt( argc, argv, "NCFLIrfbvh" ) ) != EOF )
+ {
+ switch ( c )
+ {
+ case 'N':
+ if ( globalUtilOptind >= argc )
+ {
+ fprintf( pErr, "Command line switch \"-N\" should be followed by an integer.\n" );
+ goto usage;
+ }
+ pParams->nItersMax = atoi(argv[globalUtilOptind]);
+ globalUtilOptind++;
+ if ( pParams->nItersMax < 0 )
+ goto usage;
+ break;
+ case 'C':
+ if ( globalUtilOptind >= argc )
+ {
+ fprintf( pErr, "Command line switch \"-C\" should be followed by an integer.\n" );
+ goto usage;
+ }
+ pParams->nMiteringLimitStart = atoi(argv[globalUtilOptind]);
+ globalUtilOptind++;
+ if ( pParams->nMiteringLimitStart < 0 )
+ goto usage;
+ break;
+ case 'F':
+ if ( globalUtilOptind >= argc )
+ {
+ fprintf( pErr, "Command line switch \"-F\" should be followed by an integer.\n" );
+ goto usage;
+ }
+ pParams->nFraigingLimitStart = atoi(argv[globalUtilOptind]);
+ globalUtilOptind++;
+ if ( pParams->nFraigingLimitStart < 0 )
+ goto usage;
+ break;
+ case 'L':
+ if ( globalUtilOptind >= argc )
+ {
+ fprintf( pErr, "Command line switch \"-L\" should be followed by an integer.\n" );
+ goto usage;
+ }
+ pParams->nMiteringLimitLast = atoi(argv[globalUtilOptind]);
+ globalUtilOptind++;
+ if ( pParams->nMiteringLimitLast < 0 )
+ goto usage;
+ break;
+ case 'I':
+ if ( globalUtilOptind >= argc )
+ {
+ fprintf( pErr, "Command line switch \"-I\" should be followed by an integer.\n" );
+ goto usage;
+ }
+ pParams->nTotalInspectLimit = atoi(argv[globalUtilOptind]);
+ globalUtilOptind++;
+ if ( pParams->nTotalInspectLimit < 0 )
+ goto usage;
+ break;
+ case 'r':
+ pParams->fUseRewriting ^= 1;
+ break;
+ case 'f':
+ pParams->fUseFraiging ^= 1;
+ break;
+ case 'b':
+ pParams->fUseBdds ^= 1;
+ break;
+ case 'v':
+ pParams->fVerbose ^= 1;
+ break;
+ case 'h':
+ goto usage;
+ default:
+ goto usage;
+ }
+ }
+
+ if ( pNtk == NULL )
+ {
+ fprintf( pErr, "Empty network.\n" );
+ return 1;
+ }
+ if ( Abc_NtkLatchNum(pNtk) > 0 )
+ {
+ fprintf( stdout, "Currently can only solve the miter for combinational circuits.\n" );
+ return 0;
+ }
+ if ( Abc_NtkCoNum(pNtk) != 1 )
+ {
+ fprintf( stdout, "Currently can only solve the miter with one output.\n" );
+ return 0;
+ }
+ clk = clock();
+
+ if ( Abc_NtkIsStrash(pNtk) )
+ pNtkTemp = Abc_NtkDup( pNtk );
+ else
+ pNtkTemp = Abc_NtkStrash( pNtk, 0, 0, 0 );
+
+ RetValue = Abc_NtkMiterProve( &pNtkTemp, pParams );
+
+ // verify that the pattern is correct
+ if ( RetValue == 0 )
+ {
+ int * pSimInfo = Abc_NtkVerifySimulatePattern( pNtk, pNtkTemp->pModel );
+ if ( pSimInfo[0] != 1 )
+ printf( "ERROR in Abc_NtkMiterProve(): Generated counter-example is invalid.\n" );
+ free( pSimInfo );
+ }
+
+ if ( RetValue == -1 )
+ printf( "UNDECIDED " );
+ else if ( RetValue == 0 )
+ printf( "SATISFIABLE " );
+ else
+ printf( "UNSATISFIABLE " );
+ //printf( "\n" );
+
+ PRT( "Time", clock() - clk );
+ // replace the current network
+ Abc_FrameReplaceCurrentNetwork( pAbc, pNtkTemp );
+ return 0;
+
+usage:
+ fprintf( pErr, "usage: prove [-N num] [-C num] [-F num] [-L num] [-I num] [-rfbvh]\n" );
+ fprintf( pErr, "\t solves combinational miter by rewriting, FRAIGing, and SAT\n" );
+ fprintf( pErr, "\t replaces the current network by the cone modified by rewriting\n" );
+ fprintf( pErr, "\t (there are also newer CEC commands, \"iprove\" and \"dprove\")\n" );
+ fprintf( pErr, "\t-N num : max number of iterations [default = %d]\n", pParams->nItersMax );
+ fprintf( pErr, "\t-C num : max starting number of conflicts in mitering [default = %d]\n", pParams->nMiteringLimitStart );
+ fprintf( pErr, "\t-F num : max starting number of conflicts in fraiging [default = %d]\n", pParams->nFraigingLimitStart );
+ fprintf( pErr, "\t-L num : max last-gasp number of conflicts in mitering [default = %d]\n", pParams->nMiteringLimitLast );
+ fprintf( pErr, "\t-I num : max number of clause inspections in all SAT calls [default = %d]\n", (int)pParams->nTotalInspectLimit );
+ fprintf( pErr, "\t-r : toggle the use of rewriting [default = %s]\n", pParams->fUseRewriting? "yes": "no" );
+ fprintf( pErr, "\t-f : toggle the use of FRAIGing [default = %s]\n", pParams->fUseFraiging? "yes": "no" );
+ fprintf( pErr, "\t-b : toggle the use of BDDs [default = %s]\n", pParams->fUseBdds? "yes": "no" );
+ fprintf( pErr, "\t-v : prints verbose information [default = %s]\n", pParams->fVerbose? "yes": "no" );
+ fprintf( pErr, "\t-h : print the command usage\n");
+ return 1;
+}
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Abc_CommandDebug( Abc_Frame_t * pAbc, int argc, char ** argv )
+{
+ FILE * pOut, * pErr;
+ Abc_Ntk_t * pNtk;
+ int c;
+ extern void Abc_NtkAutoDebug( Abc_Ntk_t * pNtk, int (*pFuncError) (Abc_Ntk_t *) );
+ extern int Abc_NtkRetimeDebug( Abc_Ntk_t * pNtk );
+
+ pNtk = Abc_FrameReadNtk(pAbc);
+ pOut = Abc_FrameReadOut(pAbc);
+ pErr = Abc_FrameReadErr(pAbc);
+
+ // set defaults
+ Extra_UtilGetoptReset();
+ while ( ( c = Extra_UtilGetopt( argc, argv, "h" ) ) != EOF )
+ {
+ switch ( c )
+ {
+ case 'h':
+ goto usage;
+ default:
+ goto usage;
+ }
+ }
+
+ if ( pNtk == NULL )
+ {
+ fprintf( pErr, "Empty network.\n" );
+ return 1;
+ }
+ if ( !Abc_NtkIsLogic(pNtk) )
+ {
+ fprintf( pErr, "This command is applicable to logic networks.\n" );
+ return 1;
+ }
+
+ Abc_NtkAutoDebug( pNtk, Abc_NtkRetimeDebug );
+ return 0;
+
+usage:
+ fprintf( pErr, "usage: debug [-h]\n" );
+ fprintf( pErr, "\t performs automated debugging of the given procedure\n" );
+ fprintf( pErr, "\t-h : print the command usage\n");
+ return 1;
+}
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Abc_CommandBmc( Abc_Frame_t * pAbc, int argc, char ** argv )
+{
+ FILE * pOut, * pErr;
+ Abc_Ntk_t * pNtk;
+ int c;
+ int nFrames;
+ int nBTLimit;
+ int fRewrite;
+ int fVerbose;
+
+// extern void Abc_NtkBmc( Abc_Ntk_t * pNtk, int nFrames, int fInit, int fVerbose );
+ extern int Abc_NtkDarBmc( Abc_Ntk_t * pNtk, int nFrames, int nBTLimit, int fRewrite, int fVerbose );
+
+ pNtk = Abc_FrameReadNtk(pAbc);
+ pOut = Abc_FrameReadOut(pAbc);
+ pErr = Abc_FrameReadErr(pAbc);
+
+ // set defaults
+ nFrames = 5;
+ nBTLimit = 1000000;
+ fRewrite = 0;
+ fVerbose = 0;
+ Extra_UtilGetoptReset();
+ while ( ( c = Extra_UtilGetopt( argc, argv, "FCrvh" ) ) != EOF )
+ {
+ switch ( c )
+ {
+ case 'F':
+ if ( globalUtilOptind >= argc )
+ {
+ fprintf( pErr, "Command line switch \"-F\" should be followed by an integer.\n" );
+ goto usage;
+ }
+ nFrames = atoi(argv[globalUtilOptind]);
+ globalUtilOptind++;
+ if ( nFrames < 0 )
+ goto usage;
+ break;
+ case 'C':
+ if ( globalUtilOptind >= argc )
+ {
+ fprintf( pErr, "Command line switch \"-C\" should be followed by an integer.\n" );
+ goto usage;
+ }
+ nBTLimit = atoi(argv[globalUtilOptind]);
+ globalUtilOptind++;
+ if ( nBTLimit < 0 )
+ goto usage;
+ break;
+ case 'r':
+ fRewrite ^= 1;
+ break;
+ case 'v':
+ fVerbose ^= 1;
+ break;
+ case 'h':
+ goto usage;
+ default:
+ goto usage;
+ }
+ }
+ if ( pNtk == NULL )
+ {
+ fprintf( pErr, "Empty network.\n" );
+ return 1;
+ }
+ if ( !Abc_NtkIsStrash(pNtk) )
+ {
+ fprintf( stdout, "Currently only works for structurally hashed circuits.\n" );
+ return 0;
+ }
+ Abc_NtkDarBmc( pNtk, nFrames, nBTLimit, fRewrite, fVerbose );
+ return 0;
+
+usage:
+ fprintf( pErr, "usage: bmc [-F num] [-C num] [-rvh]\n" );
+ fprintf( pErr, "\t perform bounded model checking\n" );
+ fprintf( pErr, "\t-F num : number of time frames [default = %d]\n", nFrames );
+ fprintf( pErr, "\t-C num : the max number of conflicts at a node [default = %d]\n", nBTLimit );
+ fprintf( pErr, "\t-r : toggle initialization of the first frame [default = %s]\n", fRewrite? "yes": "no" );
+ fprintf( pErr, "\t-v : toggle verbose output [default = %s]\n", fVerbose? "yes": "no" );
+ fprintf( pErr, "\t-h : print the command usage\n");
+ return 1;
+}
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Abc_CommandIndcut( Abc_Frame_t * pAbc, int argc, char ** argv )
+{
+ FILE * pOut, * pErr;
+ Abc_Ntk_t * pNtk;
+ int nFrames;
+ int nPref;
+ int nClauses;
+ int nLutSize;
+ int nLevels;
+ int nCutsMax;
+ int nBatches;
+ int fStepUp;
+ int fBmc;
+ int fRegs;
+ int fTarget;
+ int fVerbose;
+ int fVeryVerbose;
+ int c;
+ extern int Abc_NtkDarClau( Abc_Ntk_t * pNtk, int nFrames, int nPref, int nClauses, int nLutSize, int nLevels, int nCutsMax, int nBatches, int fStepUp, int fBmc, int fRegs, int fTarget, int fVerbose, int fVeryVerbose );
+
+ pNtk = Abc_FrameReadNtk(pAbc);
+ pOut = Abc_FrameReadOut(pAbc);
+ pErr = Abc_FrameReadErr(pAbc);
+
+ // set defaults
+ nFrames = 1;
+ nPref = 0;
+ nClauses = 5000;
+ nLutSize = 4;
+ nLevels = 8;
+ nCutsMax = 16;
+ nBatches = 1;
+ fStepUp = 0;
+ fBmc = 1;
+ fRegs = 1;
+ fTarget = 1;
+ fVerbose = 0;
+ fVeryVerbose = 0;
+ Extra_UtilGetoptReset();
+ while ( ( c = Extra_UtilGetopt( argc, argv, "FPCMLNBsbrtvwh" ) ) != EOF )
+ {
+ switch ( c )
+ {
+ case 'F':
+ if ( globalUtilOptind >= argc )
+ {
+ fprintf( pErr, "Command line switch \"-F\" should be followed by an integer.\n" );
+ goto usage;
+ }
+ nFrames = atoi(argv[globalUtilOptind]);
+ globalUtilOptind++;
+ if ( nFrames < 0 )
+ goto usage;
+ break;
+ case 'P':
+ if ( globalUtilOptind >= argc )
+ {
+ fprintf( pErr, "Command line switch \"-P\" should be followed by an integer.\n" );
+ goto usage;
+ }
+ nPref = atoi(argv[globalUtilOptind]);
+ globalUtilOptind++;
+ if ( nPref < 0 )
+ goto usage;
+ break;
+ case 'C':
+ if ( globalUtilOptind >= argc )
+ {
+ fprintf( pErr, "Command line switch \"-C\" should be followed by an integer.\n" );
+ goto usage;
+ }
+ nClauses = atoi(argv[globalUtilOptind]);
+ globalUtilOptind++;
+ if ( nClauses < 0 )
+ goto usage;
+ break;
+ case 'M':
+ if ( globalUtilOptind >= argc )
+ {
+ fprintf( pErr, "Command line switch \"-K\" should be followed by an integer.\n" );
+ goto usage;
+ }
+ nLutSize = atoi(argv[globalUtilOptind]);
+ globalUtilOptind++;
+ if ( nLutSize < 0 )
+ goto usage;
+ break;
+ case 'L':
+ if ( globalUtilOptind >= argc )
+ {
+ fprintf( pErr, "Command line switch \"-L\" should be followed by an integer.\n" );
+ goto usage;
+ }
+ nLevels = atoi(argv[globalUtilOptind]);
+ globalUtilOptind++;
+ if ( nLevels < 0 )
+ goto usage;
+ break;
+ case 'N':
+ if ( globalUtilOptind >= argc )
+ {
+ fprintf( pErr, "Command line switch \"-N\" should be followed by an integer.\n" );
+ goto usage;
+ }
+ nCutsMax = atoi(argv[globalUtilOptind]);
+ globalUtilOptind++;
+ if ( nCutsMax < 0 )
+ goto usage;
+ break;
+ case 'B':
+ if ( globalUtilOptind >= argc )
+ {
+ fprintf( pErr, "Command line switch \"-B\" should be followed by an integer.\n" );
+ goto usage;
+ }
+ nBatches = atoi(argv[globalUtilOptind]);
+ globalUtilOptind++;
+ if ( nBatches < 0 )
+ goto usage;
+ break;
+ case 's':
+ fStepUp ^= 1;
+ break;
+ case 'b':
+ fBmc ^= 1;
+ break;
+ case 'r':
+ fRegs ^= 1;
+ break;
+ case 't':
+ fTarget ^= 1;
+ break;
+ case 'v':
+ fVerbose ^= 1;
+ break;
+ case 'w':
+ fVeryVerbose ^= 1;
+ break;
+ case 'h':
+ goto usage;
+ default:
+ goto usage;
+ }
+ }
+ if ( pNtk == NULL )
+ {
+ fprintf( pErr, "Empty network.\n" );
+ return 1;
+ }
+ if ( Abc_NtkIsComb(pNtk) )
+ {
+ fprintf( pErr, "Only works for sequential networks.\n" );
+ return 1;
+ }
+ if ( !Abc_NtkIsStrash(pNtk) )
+ {
+ fprintf( stdout, "Currently only works for structurally hashed circuits.\n" );
+ return 0;
+ }
+ if ( nLutSize > 12 )
+ {
+ fprintf( stdout, "The cut size should be not exceed 12.\n" );
+ return 0;
+ }
+ Abc_NtkDarClau( pNtk, nFrames, nPref, nClauses, nLutSize, nLevels, nCutsMax, nBatches, fStepUp, fBmc, fRegs, fTarget, fVerbose, fVeryVerbose );
+ return 0;
+usage:
+ fprintf( pErr, "usage: indcut [-FPCMLNB num] [-sbrtvh]\n" );
+ fprintf( pErr, "\t K-step induction strengthened with cut properties\n" );
+ fprintf( pErr, "\t-F num : number of time frames for induction (1=simple) [default = %d]\n", nFrames );
+ fprintf( pErr, "\t-P num : number of time frames in the prefix (0=no prefix) [default = %d]\n", nPref );
+ fprintf( pErr, "\t-C num : the max number of clauses to use for strengthening [default = %d]\n", nClauses );
+ fprintf( pErr, "\t-M num : the cut size (2 <= M <= 12) [default = %d]\n", nLutSize );
+ fprintf( pErr, "\t-L num : the max number of levels for cut computation [default = %d]\n", nLevels );
+ fprintf( pErr, "\t-N num : the max number of cuts to compute at a node [default = %d]\n", nCutsMax );
+ fprintf( pErr, "\t-B num : the max number of invariant batches to try [default = %d]\n", nBatches );
+ fprintf( pErr, "\t-s : toggle increment cut size in each batch [default = %s]\n", fStepUp? "yes": "no" );
+ fprintf( pErr, "\t-b : toggle enabling BMC check [default = %s]\n", fBmc? "yes": "no" );
+ fprintf( pErr, "\t-r : toggle enabling register clauses [default = %s]\n", fRegs? "yes": "no" );
+ fprintf( pErr, "\t-t : toggle proving target / computing don't-cares [default = %s]\n", fTarget? "yes": "no" );
+ fprintf( pErr, "\t-v : toggle printing verbose information [default = %s]\n", fVerbose? "yes": "no" );
+// fprintf( pErr, "\t-w : toggle printing very verbose information [default = %s]\n", fVeryVerbose? "yes": "no" );
+ fprintf( pErr, "\t-h : print the command usage\n");
+ return 1;
+}
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Abc_CommandEnlarge( Abc_Frame_t * pAbc, int argc, char ** argv )
+{
+ FILE * pOut, * pErr;
+ Abc_Ntk_t * pNtk, * pNtkRes;
+ int nFrames;
+ int fVerbose;
+ int c;
+ extern Abc_Ntk_t * Abc_NtkDarEnlarge( Abc_Ntk_t * pNtk, int nFrames, int fVerbose );
+
+ pNtk = Abc_FrameReadNtk(pAbc);
+ pOut = Abc_FrameReadOut(pAbc);
+ pErr = Abc_FrameReadErr(pAbc);
+
+ // set defaults
+ nFrames = 5;
+ fVerbose = 0;
+ Extra_UtilGetoptReset();
+ while ( ( c = Extra_UtilGetopt( argc, argv, "Fvh" ) ) != EOF )
+ {
+ switch ( c )
+ {
+ case 'F':
+ if ( globalUtilOptind >= argc )
+ {
+ fprintf( pErr, "Command line switch \"-F\" should be followed by an integer.\n" );
+ goto usage;
+ }
+ nFrames = atoi(argv[globalUtilOptind]);
+ globalUtilOptind++;
+ if ( nFrames < 0 )
+ goto usage;
+ break;
+ case 'v':
+ fVerbose ^= 1;
+ break;
+ case 'h':
+ goto usage;
+ default:
+ goto usage;
+ }
+ }
+ if ( pNtk == NULL )
+ {
+ fprintf( pErr, "Empty network.\n" );
+ return 1;
+ }
+ if ( Abc_NtkIsComb(pNtk) )
+ {
+ fprintf( pErr, "Only works for sequential networks.\n" );
+ return 1;
+ }
+ if ( !Abc_NtkIsStrash(pNtk) )
+ {
+ fprintf( stdout, "Currently only works for structurally hashed circuits.\n" );
+ return 0;
+ }
+
+ // modify the current network
+ pNtkRes = Abc_NtkDarEnlarge( pNtk, nFrames, fVerbose );
+ if ( pNtkRes == NULL )
+ {
+ fprintf( pErr, "Target enlargement has failed.\n" );
+ return 1;
+ }
+ // replace the current network
+ Abc_FrameReplaceCurrentNetwork( pAbc, pNtkRes );
+ return 0;
+usage:
+ fprintf( pErr, "usage: enlarge [-F num] [-vh]\n" );
+ fprintf( pErr, "\t performs structural K-step target enlargement\n" );
+ fprintf( pErr, "\t-F num : the number of timeframes for enlargement [default = %d]\n", nFrames );
+ fprintf( pErr, "\t-v : toggle printing verbose information [default = %s]\n", fVerbose? "yes": "no" );
+ fprintf( pErr, "\t-h : print the command usage\n");
+ return 1;
+}
+
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Abc_CommandTraceStart( Abc_Frame_t * pAbc, int argc, char ** argv )
+{
+ FILE * pOut, * pErr;
+ Abc_Ntk_t * pNtk;
+ int c;
+
+ pNtk = Abc_FrameReadNtk(pAbc);
+ pOut = Abc_FrameReadOut(pAbc);
+ pErr = Abc_FrameReadErr(pAbc);
+
+ // set defaults
+ Extra_UtilGetoptReset();
+ while ( ( c = Extra_UtilGetopt( argc, argv, "h" ) ) != EOF )
+ {
+ switch ( c )
+ {
+ case 'h':
+ goto usage;
+ default:
+ goto usage;
+ }
+ }
+
+ if ( pNtk == NULL )
+ {
+ fprintf( pErr, "Empty network.\n" );
+ return 1;
+ }
+ if ( !Abc_NtkIsStrash(pNtk) )
+ {
+ fprintf( pErr, "This command is applicable to AIGs.\n" );
+ return 1;
+ }
+/*
+ Abc_HManStart();
+ if ( !Abc_HManPopulate( pNtk ) )
+ {
+ fprintf( pErr, "Failed to start the tracing database.\n" );
+ return 1;
+ }
+*/
+ return 0;
+
+usage:
+ fprintf( pErr, "usage: trace_start [-h]\n" );
+ fprintf( pErr, "\t starts verification tracing\n" );
+ fprintf( pErr, "\t-h : print the command usage\n");
+ return 1;
+}
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Abc_CommandTraceCheck( Abc_Frame_t * pAbc, int argc, char ** argv )
+{
+ FILE * pOut, * pErr;
+ Abc_Ntk_t * pNtk;
+ int c;
+
+ pNtk = Abc_FrameReadNtk(pAbc);
+ pOut = Abc_FrameReadOut(pAbc);
+ pErr = Abc_FrameReadErr(pAbc);
+
+ // set defaults
+ Extra_UtilGetoptReset();
+ while ( ( c = Extra_UtilGetopt( argc, argv, "h" ) ) != EOF )
+ {
+ switch ( c )
+ {
+ case 'h':
+ goto usage;
+ default:
+ goto usage;
+ }
+ }
+
+ if ( pNtk == NULL )
+ {
+ fprintf( pErr, "Empty network.\n" );
+ return 1;
+ }
+ if ( !Abc_NtkIsStrash(pNtk) )
+ {
+ fprintf( pErr, "This command is applicable to AIGs.\n" );
+ return 1;
+ }
+/*
+ if ( !Abc_HManIsRunning(pNtk) )
+ {
+ fprintf( pErr, "The tracing database is not available.\n" );
+ return 1;
+ }
+
+ if ( !Abc_HManVerify( 1, pNtk->Id ) )
+ fprintf( pErr, "Verification failed.\n" );
+ Abc_HManStop();
+*/
+ return 0;
+
+usage:
+ fprintf( pErr, "usage: trace_check [-h]\n" );
+ fprintf( pErr, "\t checks the current network using verification trace\n" );
+ fprintf( pErr, "\t-h : print the command usage\n");
+ return 1;
+}
////////////////////////////////////////////////////////////////////////
/// END OF FILE ///
diff --git a/src/base/abci/abcAttach.c b/src/base/abci/abcAttach.c
index 6ee1fb90..d5d2aa16 100644
--- a/src/base/abci/abcAttach.c
+++ b/src/base/abci/abcAttach.c
@@ -40,7 +40,7 @@ static char ** s_pPerms = NULL;
static int s_nPerms;
////////////////////////////////////////////////////////////////////////
-/// FUNCTION DEFITIONS ///
+/// FUNCTION DEFINITIONS ///
////////////////////////////////////////////////////////////////////////
/**Function*************************************************************
@@ -66,7 +66,7 @@ int Abc_NtkAttach( Abc_Ntk_t * pNtk )
assert( Abc_NtkIsSopLogic(pNtk) );
// check that the library is available
- pGenlib = Abc_FrameReadLibGen(Abc_FrameGetGlobalFrame());
+ pGenlib = Abc_FrameReadLibGen();
if ( pGenlib == NULL )
{
printf( "The current library is not available.\n" );
@@ -142,7 +142,7 @@ int Abc_NtkAttach( Abc_Ntk_t * pNtk )
Abc_NtkForEachNode( pNtk, pNode, i )
pNode->pData = pNode->pCopy, pNode->pCopy = NULL;
pNtk->ntkFunc = ABC_FUNC_MAP;
- Extra_MmFlexStop( pNtk->pManFunc, 0 );
+ Extra_MmFlexStop( pNtk->pManFunc );
pNtk->pManFunc = pGenlib;
printf( "Library gates are successfully attached to the nodes.\n" );
@@ -187,7 +187,7 @@ int Abc_NodeAttach( Abc_Obj_t * pNode, Mio_Gate_t ** ppGates, unsigned ** puTrut
Abc_ObjForEachFanin( pNode, pFanin, i )
pTempInts[i] = pFanin->Id;
for ( i = 0; i < nFanins; i++ )
- pNode->vFanins.pArray[Perm[i]].iFan = pTempInts[i];
+ pNode->vFanins.pArray[Perm[i]] = pTempInts[i];
// set the gate
pNode->pCopy = (Abc_Obj_t *)pGate;
return 1;
@@ -387,13 +387,13 @@ void Abc_TruthPermute( char * pPerm, int nVars, unsigned * uTruthNode, unsigned
nMints = (1 << nVars);
for ( iMint = 0; iMint < nMints; iMint++ )
{
- if ( (uTruthNode[iMint/32] & (1 << (iMint%32))) == 0 )
+ if ( (uTruthNode[iMint>>5] & (1 << (iMint&31))) == 0 )
continue;
iMintPerm = 0;
for ( v = 0; v < nVars; v++ )
if ( iMint & (1 << v) )
iMintPerm |= (1 << pPerm[v]);
- uTruthPerm[iMintPerm/32] |= (1 << (iMintPerm%32));
+ uTruthPerm[iMintPerm>>5] |= (1 << (iMintPerm&31));
}
}
diff --git a/src/base/abci/abcAuto.c b/src/base/abci/abcAuto.c
new file mode 100644
index 00000000..40212c17
--- /dev/null
+++ b/src/base/abci/abcAuto.c
@@ -0,0 +1,239 @@
+/**CFile****************************************************************
+
+ FileName [abcAuto.c]
+
+ SystemName [ABC: Logic synthesis and verification system.]
+
+ PackageName [Network and node package.]
+
+ Synopsis [Computation of autosymmetries.]
+
+ Author [Alan Mishchenko]
+
+ Affiliation [UC Berkeley]
+
+ Date [Ver. 1.0. Started - June 20, 2005.]
+
+ Revision [$Id: abcAuto.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "abc.h"
+
+////////////////////////////////////////////////////////////////////////
+/// DECLARATIONS ///
+////////////////////////////////////////////////////////////////////////
+
+static void Abc_NtkAutoPrintAll( DdManager * dd, int nInputs, DdNode * pbOutputs[], int nOutputs, char * pInputNames[], char * pOutputNames[], int fNaive );
+static void Abc_NtkAutoPrintOne( DdManager * dd, int nInputs, DdNode * pbOutputs[], int Output, char * pInputNames[], char * pOutputNames[], int fNaive );
+
+////////////////////////////////////////////////////////////////////////
+/// FUNCTION DEFINITIONS ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Abc_NtkAutoPrint( Abc_Ntk_t * pNtk, int Output, int fNaive, int fVerbose )
+{
+ DdManager * dd; // the BDD manager used to hold shared BDDs
+ DdNode ** pbGlobal; // temporary storage for global BDDs
+ char ** pInputNames; // pointers to the CI names
+ char ** pOutputNames; // pointers to the CO names
+ int nOutputs, nInputs, i;
+ Vec_Ptr_t * vFuncsGlob;
+ Abc_Obj_t * pObj;
+
+ // compute the global BDDs
+ if ( Abc_NtkBuildGlobalBdds(pNtk, 10000000, 1, 1, fVerbose) == NULL )
+ return;
+
+ // get information about the network
+ nInputs = Abc_NtkCiNum(pNtk);
+ nOutputs = Abc_NtkCoNum(pNtk);
+// dd = pNtk->pManGlob;
+ dd = Abc_NtkGlobalBddMan( pNtk );
+
+ // complement the global functions
+ vFuncsGlob = Vec_PtrAlloc( Abc_NtkCoNum(pNtk) );
+ Abc_NtkForEachCo( pNtk, pObj, i )
+ Vec_PtrPush( vFuncsGlob, Abc_ObjGlobalBdd(pObj) );
+ pbGlobal = (DdNode **)Vec_PtrArray( vFuncsGlob );
+
+ // get the network names
+ pInputNames = Abc_NtkCollectCioNames( pNtk, 0 );
+ pOutputNames = Abc_NtkCollectCioNames( pNtk, 1 );
+
+ // print the size of the BDDs
+ if ( fVerbose )
+ printf( "Shared BDD size = %6d nodes.\n", Cudd_ReadKeys(dd) - Cudd_ReadDead(dd) );
+
+ // allocate additional variables
+ for ( i = 0; i < nInputs; i++ )
+ Cudd_bddNewVar( dd );
+ assert( Cudd_ReadSize(dd) == 2 * nInputs );
+
+ // create ZDD variables in the manager
+ Cudd_zddVarsFromBddVars( dd, 2 );
+
+ // perform the analysis of the primary output functions for auto-symmetry
+ if ( Output == -1 )
+ Abc_NtkAutoPrintAll( dd, nInputs, pbGlobal, nOutputs, pInputNames, pOutputNames, fNaive );
+ else
+ Abc_NtkAutoPrintOne( dd, nInputs, pbGlobal, Output, pInputNames, pOutputNames, fNaive );
+
+ // deref the PO functions
+// Abc_NtkFreeGlobalBdds( pNtk );
+ // stop the global BDD manager
+// Extra_StopManager( pNtk->pManGlob );
+// pNtk->pManGlob = NULL;
+ Abc_NtkFreeGlobalBdds( pNtk, 1 );
+ free( pInputNames );
+ free( pOutputNames );
+ Vec_PtrFree( vFuncsGlob );
+}
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Abc_NtkAutoPrintAll( DdManager * dd, int nInputs, DdNode * pbOutputs[], int nOutputs, char * pInputNames[], char * pOutputNames[], int fNaive )
+{
+ DdNode * bSpace1, * bSpace2, * bCanVars, * bReduced, * zEquations;
+ double nMints;
+ int nSupp, SigCounter, o;
+
+ int nAutos;
+ int nAutoSyms;
+ int nAutoSymsMax;
+ int nAutoSymsMaxSupp;
+ int nAutoSymOuts;
+ int nSuppSizeMax;
+ int clk;
+
+ nAutoSymOuts = 0;
+ nAutoSyms = 0;
+ nAutoSymsMax = 0;
+ nAutoSymsMaxSupp = 0;
+ nSuppSizeMax = 0;
+ clk = clock();
+
+ SigCounter = 0;
+ for ( o = 0; o < nOutputs; o++ )
+ {
+// bSpace1 = Extra_bddSpaceFromFunctionFast( dd, pbOutputs[o] ); Cudd_Ref( bSpace1 );
+ bSpace1 = Extra_bddSpaceFromFunction( dd, pbOutputs[o], pbOutputs[o] ); Cudd_Ref( bSpace1 );
+ bCanVars = Extra_bddSpaceCanonVars( dd, bSpace1 ); Cudd_Ref( bCanVars );
+ bReduced = Extra_bddSpaceReduce( dd, pbOutputs[o], bCanVars ); Cudd_Ref( bReduced );
+ zEquations = Extra_bddSpaceEquations( dd, bSpace1 ); Cudd_Ref( zEquations );
+
+ nSupp = Cudd_SupportSize( dd, bSpace1 );
+ nMints = Cudd_CountMinterm( dd, bSpace1, nSupp );
+ nAutos = Extra_Base2LogDouble(nMints);
+ printf( "Output #%3d: Inputs = %2d. AutoK = %2d.\n", o, nSupp, nAutos );
+
+ if ( nAutos > 0 )
+ {
+ nAutoSymOuts++;
+ nAutoSyms += nAutos;
+ if ( nAutoSymsMax < nAutos )
+ {
+ nAutoSymsMax = nAutos;
+ nAutoSymsMaxSupp = nSupp;
+ }
+ }
+ if ( nSuppSizeMax < nSupp )
+ nSuppSizeMax = nSupp;
+
+
+//PRB( dd, bCanVars );
+//PRB( dd, bReduced );
+//Cudd_PrintMinterm( dd, bReduced );
+//printf( "The equations are:\n" );
+//Cudd_zddPrintCover( dd, zEquations );
+//printf( "\n" );
+//fflush( stdout );
+
+ bSpace2 = Extra_bddSpaceFromMatrixPos( dd, zEquations ); Cudd_Ref( bSpace2 );
+//PRB( dd, bSpace1 );
+//PRB( dd, bSpace2 );
+ if ( bSpace1 != bSpace2 )
+ printf( "Spaces are NOT EQUAL!\n" );
+// else
+// printf( "Spaces are equal.\n" );
+
+ Cudd_RecursiveDeref( dd, bSpace1 );
+ Cudd_RecursiveDeref( dd, bSpace2 );
+ Cudd_RecursiveDeref( dd, bCanVars );
+ Cudd_RecursiveDeref( dd, bReduced );
+ Cudd_RecursiveDerefZdd( dd, zEquations );
+ }
+
+ printf( "The cumulative statistics for all outputs:\n" );
+ printf( "Ins=%3d ", nInputs );
+ printf( "InMax=%3d ", nSuppSizeMax );
+ printf( "Outs=%3d ", nOutputs );
+ printf( "Auto=%3d ", nAutoSymOuts );
+ printf( "SumK=%3d ", nAutoSyms );
+ printf( "KMax=%2d ", nAutoSymsMax );
+ printf( "Supp=%3d ", nAutoSymsMaxSupp );
+ printf( "Time=%4.2f ", (float)(clock() - clk)/(float)(CLOCKS_PER_SEC) );
+ printf( "\n" );
+}
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Abc_NtkAutoPrintOne( DdManager * dd, int nInputs, DdNode * pbOutputs[], int Output, char * pInputNames[], char * pOutputNames[], int fNaive )
+{
+ DdNode * bSpace1, * bCanVars, * bReduced, * zEquations;
+ double nMints;
+ int nSupp, SigCounter;
+ int nAutos;
+
+ SigCounter = 0;
+ bSpace1 = Extra_bddSpaceFromFunctionFast( dd, pbOutputs[Output] ); Cudd_Ref( bSpace1 );
+// bSpace1 = Extra_bddSpaceFromFunction( dd, pbOutputs[Output], pbOutputs[Output] ); Cudd_Ref( bSpace1 );
+ bCanVars = Extra_bddSpaceCanonVars( dd, bSpace1 ); Cudd_Ref( bCanVars );
+ bReduced = Extra_bddSpaceReduce( dd, pbOutputs[Output], bCanVars ); Cudd_Ref( bReduced );
+ zEquations = Extra_bddSpaceEquations( dd, bSpace1 ); Cudd_Ref( zEquations );
+
+ nSupp = Cudd_SupportSize( dd, bSpace1 );
+ nMints = Cudd_CountMinterm( dd, bSpace1, nSupp );
+ nAutos = Extra_Base2LogDouble(nMints);
+ printf( "Output #%3d: Inputs = %2d. AutoK = %2d.\n", Output, nSupp, nAutos );
+
+ Cudd_RecursiveDeref( dd, bSpace1 );
+ Cudd_RecursiveDeref( dd, bCanVars );
+ Cudd_RecursiveDeref( dd, bReduced );
+ Cudd_RecursiveDerefZdd( dd, zEquations );
+}
+
+////////////////////////////////////////////////////////////////////////
+/// END OF FILE ///
+////////////////////////////////////////////////////////////////////////
+
+
diff --git a/src/base/abci/abcBalance.c b/src/base/abci/abcBalance.c
index 40701e41..f9b3384e 100644
--- a/src/base/abci/abcBalance.c
+++ b/src/base/abci/abcBalance.c
@@ -24,13 +24,16 @@
/// DECLARATIONS ///
////////////////////////////////////////////////////////////////////////
-static void Abc_NtkBalancePerform( Abc_Ntk_t * pNtk, Abc_Ntk_t * pNtkAig, bool fDuplicate );
-static Abc_Obj_t * Abc_NodeBalance_rec( Abc_Ntk_t * pNtkNew, Abc_Obj_t * pNode, Vec_Vec_t * vStorage, bool fDuplicate );
-static Vec_Ptr_t * Abc_NodeBalanceCone( Abc_Obj_t * pNode, Vec_Vec_t * vSuper, int fDuplicate );
-static int Abc_NodeBalanceCone_rec( Abc_Obj_t * pNode, Vec_Ptr_t * vSuper, bool fFirst, bool fDuplicate );
+static void Abc_NtkBalancePerform( Abc_Ntk_t * pNtk, Abc_Ntk_t * pNtkAig, bool fDuplicate, bool fSelective, bool fUpdateLevel );
+static Abc_Obj_t * Abc_NodeBalance_rec( Abc_Ntk_t * pNtkNew, Abc_Obj_t * pNode, Vec_Vec_t * vStorage, int Level, bool fDuplicate, bool fSelective, bool fUpdateLevel );
+static Vec_Ptr_t * Abc_NodeBalanceCone( Abc_Obj_t * pNode, Vec_Vec_t * vSuper, int Level, int fDuplicate, bool fSelective );
+static int Abc_NodeBalanceCone_rec( Abc_Obj_t * pNode, Vec_Ptr_t * vSuper, bool fFirst, bool fDuplicate, bool fSelective );
+static void Abc_NtkMarkCriticalNodes( Abc_Ntk_t * pNtk );
+static Vec_Ptr_t * Abc_NodeBalanceConeExor( Abc_Obj_t * pNode );
+
////////////////////////////////////////////////////////////////////////
-/// FUNCTION DEFITIONS ///
+/// FUNCTION DEFINITIONS ///
////////////////////////////////////////////////////////////////////////
/**Function*************************************************************
@@ -44,14 +47,32 @@ static int Abc_NodeBalanceCone_rec( Abc_Obj_t * pNode, Vec_Ptr_t * vSupe
SeeAlso []
***********************************************************************/
-Abc_Ntk_t * Abc_NtkBalance( Abc_Ntk_t * pNtk, bool fDuplicate )
+Abc_Ntk_t * Abc_NtkBalance( Abc_Ntk_t * pNtk, bool fDuplicate, bool fSelective, bool fUpdateLevel )
{
+ extern void Abc_NtkHaigTranfer( Abc_Ntk_t * pNtkOld, Abc_Ntk_t * pNtkNew );
Abc_Ntk_t * pNtkAig;
assert( Abc_NtkIsStrash(pNtk) );
+ // compute the required times
+ if ( fSelective )
+ {
+ Abc_NtkStartReverseLevels( pNtk, 0 );
+ Abc_NtkMarkCriticalNodes( pNtk );
+ }
// perform balancing
- pNtkAig = Abc_NtkStartFrom( pNtk, ABC_TYPE_STRASH, ABC_FUNC_AIG );
- Abc_NtkBalancePerform( pNtk, pNtkAig, fDuplicate );
+ pNtkAig = Abc_NtkStartFrom( pNtk, ABC_NTK_STRASH, ABC_FUNC_AIG );
+ // transfer HAIG
+ Abc_NtkHaigTranfer( pNtk, pNtkAig );
+ // perform balancing
+ Abc_NtkBalancePerform( pNtk, pNtkAig, fDuplicate, fSelective, fUpdateLevel );
Abc_NtkFinalize( pNtk, pNtkAig );
+ // undo the required times
+ if ( fSelective )
+ {
+ Abc_NtkStopReverseLevels( pNtk );
+ Abc_NtkCleanMarkA( pNtk );
+ }
+ if ( pNtk->pExdc )
+ pNtkAig->pExdc = Abc_NtkDup( pNtk->pExdc );
// make sure everything is okay
if ( !Abc_NtkCheck( pNtkAig ) )
{
@@ -73,7 +94,7 @@ Abc_Ntk_t * Abc_NtkBalance( Abc_Ntk_t * pNtk, bool fDuplicate )
SeeAlso []
***********************************************************************/
-void Abc_NtkBalancePerform( Abc_Ntk_t * pNtk, Abc_Ntk_t * pNtkAig, bool fDuplicate )
+void Abc_NtkBalancePerform( Abc_Ntk_t * pNtk, Abc_Ntk_t * pNtkAig, bool fDuplicate, bool fSelective, bool fUpdateLevel )
{
int fCheck = 1;
ProgressBar * pProgress;
@@ -81,12 +102,10 @@ void Abc_NtkBalancePerform( Abc_Ntk_t * pNtk, Abc_Ntk_t * pNtkAig, bool fDuplica
Abc_Obj_t * pNode, * pDriver;
int i;
- // copy the constant node
- Abc_AigConst1(pNtk->pManFunc)->pCopy = Abc_AigConst1(pNtkAig->pManFunc);
// set the level of PIs of AIG according to the arrival times of the old network
Abc_NtkSetNodeLevelsArrival( pNtk );
// allocate temporary storage for supergates
- vStorage = Vec_VecStart( Abc_AigGetLevelNum(pNtk) + 1 );
+ vStorage = Vec_VecStart( 10 );
// perform balancing of POs
pProgress = Extra_ProgressBarStart( stdout, Abc_NtkCoNum(pNtk) );
Abc_NtkForEachCo( pNtk, pNode, i )
@@ -94,7 +113,7 @@ void Abc_NtkBalancePerform( Abc_Ntk_t * pNtk, Abc_Ntk_t * pNtkAig, bool fDuplica
Extra_ProgressBarUpdate( pProgress, i, NULL );
// strash the driver node
pDriver = Abc_ObjFanin0(pNode);
- Abc_NodeBalance_rec( pNtkAig, pDriver, vStorage, fDuplicate );
+ Abc_NodeBalance_rec( pNtkAig, pDriver, vStorage, 0, fDuplicate, fSelective, fUpdateLevel );
}
Extra_ProgressBarStop( pProgress );
Vec_VecFree( vStorage );
@@ -102,6 +121,97 @@ void Abc_NtkBalancePerform( Abc_Ntk_t * pNtk, Abc_Ntk_t * pNtkAig, bool fDuplica
/**Function*************************************************************
+ Synopsis [Finds the left bound on the next candidate to be paired.]
+
+ Description [The nodes in the array are in the decreasing order of levels.
+ The last node in the array has the smallest level. By default it would be paired
+ with the next node on the left. However, it may be possible to pair it with some
+ other node on the left, in such a way that the new node is shared. This procedure
+ finds the index of the left-most node, which can be paired with the last node.]
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Abc_NodeBalanceFindLeft( Vec_Ptr_t * vSuper )
+{
+ Abc_Obj_t * pNodeRight, * pNodeLeft;
+ int Current;
+ // if two or less nodes, pair with the first
+ if ( Vec_PtrSize(vSuper) < 3 )
+ return 0;
+ // set the pointer to the one before the last
+ Current = Vec_PtrSize(vSuper) - 2;
+ pNodeRight = Vec_PtrEntry( vSuper, Current );
+ // go through the nodes to the left of this one
+ for ( Current--; Current >= 0; Current-- )
+ {
+ // get the next node on the left
+ pNodeLeft = Vec_PtrEntry( vSuper, Current );
+ // if the level of this node is different, quit the loop
+ if ( Abc_ObjRegular(pNodeLeft)->Level != Abc_ObjRegular(pNodeRight)->Level )
+ break;
+ }
+ Current++;
+ // get the node, for which the equality holds
+ pNodeLeft = Vec_PtrEntry( vSuper, Current );
+ assert( Abc_ObjRegular(pNodeLeft)->Level == Abc_ObjRegular(pNodeRight)->Level );
+ return Current;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Moves closer to the end the node that is best for sharing.]
+
+ Description [If there is no node with sharing, randomly chooses one of
+ the legal nodes.]
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Abc_NodeBalancePermute( Abc_Ntk_t * pNtkNew, Vec_Ptr_t * vSuper, int LeftBound )
+{
+ Abc_Obj_t * pNode1, * pNode2, * pNode3;
+ int RightBound, i;
+ // get the right bound
+ RightBound = Vec_PtrSize(vSuper) - 2;
+ assert( LeftBound <= RightBound );
+ if ( LeftBound == RightBound )
+ return;
+ // get the two last nodes
+ pNode1 = Vec_PtrEntry( vSuper, RightBound + 1 );
+ pNode2 = Vec_PtrEntry( vSuper, RightBound );
+ // find the first node that can be shared
+ for ( i = RightBound; i >= LeftBound; i-- )
+ {
+ pNode3 = Vec_PtrEntry( vSuper, i );
+ if ( Abc_AigAndLookup( pNtkNew->pManFunc, pNode1, pNode3 ) )
+ {
+ if ( pNode3 == pNode2 )
+ return;
+ Vec_PtrWriteEntry( vSuper, i, pNode2 );
+ Vec_PtrWriteEntry( vSuper, RightBound, pNode3 );
+ return;
+ }
+ }
+/*
+ // we did not find the node to share, randomize choice
+ {
+ int Choice = rand() % (RightBound - LeftBound + 1);
+ pNode3 = Vec_PtrEntry( vSuper, LeftBound + Choice );
+ if ( pNode3 == pNode2 )
+ return;
+ Vec_PtrWriteEntry( vSuper, LeftBound + Choice, pNode2 );
+ Vec_PtrWriteEntry( vSuper, RightBound, pNode3 );
+ }
+*/
+}
+
+/**Function*************************************************************
+
Synopsis [Rebalances the multi-input node rooted at pNodeOld.]
Description []
@@ -111,36 +221,44 @@ void Abc_NtkBalancePerform( Abc_Ntk_t * pNtk, Abc_Ntk_t * pNtkAig, bool fDuplica
SeeAlso []
***********************************************************************/
-Abc_Obj_t * Abc_NodeBalance_rec( Abc_Ntk_t * pNtkNew, Abc_Obj_t * pNodeOld, Vec_Vec_t * vStorage, bool fDuplicate )
+Abc_Obj_t * Abc_NodeBalance_rec( Abc_Ntk_t * pNtkNew, Abc_Obj_t * pNodeOld, Vec_Vec_t * vStorage, int Level, bool fDuplicate, bool fSelective, bool fUpdateLevel )
{
Abc_Aig_t * pMan = pNtkNew->pManFunc;
Abc_Obj_t * pNodeNew, * pNode1, * pNode2;
Vec_Ptr_t * vSuper;
- int i;
+ int i, LeftBound;
assert( !Abc_ObjIsComplement(pNodeOld) );
// return if the result if known
if ( pNodeOld->pCopy )
return pNodeOld->pCopy;
assert( Abc_ObjIsNode(pNodeOld) );
// get the implication supergate
- vSuper = Abc_NodeBalanceCone( pNodeOld, vStorage, fDuplicate );
+// Abc_NodeBalanceConeExor( pNodeOld );
+ vSuper = Abc_NodeBalanceCone( pNodeOld, vStorage, Level, fDuplicate, fSelective );
if ( vSuper->nSize == 0 )
{ // it means that the supergate contains two nodes in the opposite polarity
- pNodeOld->pCopy = Abc_ObjNot(Abc_AigConst1(pMan));
+ pNodeOld->pCopy = Abc_ObjNot(Abc_AigConst1(pNtkNew));
return pNodeOld->pCopy;
}
// for each old node, derive the new well-balanced node
for ( i = 0; i < vSuper->nSize; i++ )
{
- pNodeNew = Abc_NodeBalance_rec( pNtkNew, Abc_ObjRegular(vSuper->pArray[i]), vStorage, fDuplicate );
+ pNodeNew = Abc_NodeBalance_rec( pNtkNew, Abc_ObjRegular(vSuper->pArray[i]), vStorage, Level + 1, fDuplicate, fSelective, fUpdateLevel );
vSuper->pArray[i] = Abc_ObjNotCond( pNodeNew, Abc_ObjIsComplement(vSuper->pArray[i]) );
}
+ if ( vSuper->nSize < 2 )
+ printf( "BUG!\n" );
// sort the new nodes by level in the decreasing order
Vec_PtrSort( vSuper, Abc_NodeCompareLevelsDecrease );
// balance the nodes
assert( vSuper->nSize > 1 );
while ( vSuper->nSize > 1 )
{
+ // find the left bound on the node to be paired
+ LeftBound = (!fUpdateLevel)? 0 : Abc_NodeBalanceFindLeft( vSuper );
+ // find the node that can be shared (if no such node, randomize choice)
+ Abc_NodeBalancePermute( pNtkNew, vSuper, LeftBound );
+ // pull out the last two nodes
pNode1 = Vec_PtrPop(vSuper);
pNode2 = Vec_PtrPop(vSuper);
Abc_VecObjPushUniqueOrderByLevel( vSuper, Abc_AigAnd(pMan, pNode1, pNode2) );
@@ -149,6 +267,13 @@ Abc_Obj_t * Abc_NodeBalance_rec( Abc_Ntk_t * pNtkNew, Abc_Obj_t * pNodeOld, Vec_
assert( pNodeOld->pCopy == NULL );
// mark the old node with the new node
pNodeOld->pCopy = vSuper->pArray[0];
+ vSuper->nSize = 0;
+// if ( Abc_ObjRegular(pNodeOld->pCopy) == Abc_AigConst1(pNtkNew) )
+// printf( "Constant node\n" );
+// assert( pNodeOld->Level >= Abc_ObjRegular(pNodeOld->pCopy)->Level );
+ // update HAIG
+ if ( Abc_ObjRegular(pNodeOld->pCopy)->pNtk->pHaig )
+ Hop_ObjCreateChoice( pNodeOld->pEquiv, Abc_ObjRegular(pNodeOld->pCopy)->pEquiv );
return pNodeOld->pCopy;
}
@@ -165,17 +290,25 @@ Abc_Obj_t * Abc_NodeBalance_rec( Abc_Ntk_t * pNtkNew, Abc_Obj_t * pNodeOld, Vec_
SeeAlso []
***********************************************************************/
-Vec_Ptr_t * Abc_NodeBalanceCone( Abc_Obj_t * pNode, Vec_Vec_t * vStorage, int fDuplicate )
+Vec_Ptr_t * Abc_NodeBalanceCone( Abc_Obj_t * pNode, Vec_Vec_t * vStorage, int Level, int fDuplicate, bool fSelective )
{
Vec_Ptr_t * vNodes;
int RetValue, i;
assert( !Abc_ObjIsComplement(pNode) );
- vNodes = Vec_VecEntry( vStorage, pNode->Level );
+ // extend the storage
+ if ( Vec_VecSize( vStorage ) <= Level )
+ Vec_VecPush( vStorage, Level, 0 );
+ // get the temporary array of nodes
+ vNodes = Vec_VecEntry( vStorage, Level );
Vec_PtrClear( vNodes );
- RetValue = Abc_NodeBalanceCone_rec( pNode, vNodes, 1, fDuplicate );
- assert( vNodes->nSize > 0 );
+ // collect the nodes in the implication supergate
+ RetValue = Abc_NodeBalanceCone_rec( pNode, vNodes, 1, fDuplicate, fSelective );
+ assert( vNodes->nSize > 1 );
+ // unmark the visited nodes
for ( i = 0; i < vNodes->nSize; i++ )
Abc_ObjRegular((Abc_Obj_t *)vNodes->pArray[i])->fMarkB = 0;
+ // if we found the node and its complement in the same implication supergate,
+ // return empty set of nodes (meaning that we should use constant-0 node)
if ( RetValue == -1 )
vNodes->nSize = 0;
return vNodes;
@@ -195,7 +328,7 @@ Vec_Ptr_t * Abc_NodeBalanceCone( Abc_Obj_t * pNode, Vec_Vec_t * vStorage, int fD
SeeAlso []
***********************************************************************/
-int Abc_NodeBalanceCone_rec( Abc_Obj_t * pNode, Vec_Ptr_t * vSuper, bool fFirst, bool fDuplicate )
+int Abc_NodeBalanceCone_rec( Abc_Obj_t * pNode, Vec_Ptr_t * vSuper, bool fFirst, bool fDuplicate, bool fSelective )
{
int RetValue1, RetValue2, i;
// check if the node is visited
@@ -213,7 +346,7 @@ int Abc_NodeBalanceCone_rec( Abc_Obj_t * pNode, Vec_Ptr_t * vSuper, bool fFirst,
return 0;
}
// if the new node is complemented or a PI, another gate begins
- if ( !fFirst && (Abc_ObjIsComplement(pNode) || !Abc_ObjIsNode(pNode) || !fDuplicate && (Abc_ObjFanoutNum(pNode) > 1)) )
+ if ( !fFirst && (Abc_ObjIsComplement(pNode) || !Abc_ObjIsNode(pNode) || !fDuplicate && !fSelective && (Abc_ObjFanoutNum(pNode) > 1)) )
{
Vec_PtrPush( vSuper, pNode );
Abc_ObjRegular(pNode)->fMarkB = 1;
@@ -222,8 +355,8 @@ int Abc_NodeBalanceCone_rec( Abc_Obj_t * pNode, Vec_Ptr_t * vSuper, bool fFirst,
assert( !Abc_ObjIsComplement(pNode) );
assert( Abc_ObjIsNode(pNode) );
// go through the branches
- RetValue1 = Abc_NodeBalanceCone_rec( Abc_ObjChild0(pNode), vSuper, 0, fDuplicate );
- RetValue2 = Abc_NodeBalanceCone_rec( Abc_ObjChild1(pNode), vSuper, 0, fDuplicate );
+ RetValue1 = Abc_NodeBalanceCone_rec( Abc_ObjChild0(pNode), vSuper, 0, fDuplicate, fSelective );
+ RetValue2 = Abc_NodeBalanceCone_rec( Abc_ObjChild1(pNode), vSuper, 0, fDuplicate, fSelective );
if ( RetValue1 == -1 || RetValue2 == -1 )
return -1;
// return 1 if at least one branch has a duplicate
@@ -231,6 +364,248 @@ int Abc_NodeBalanceCone_rec( Abc_Obj_t * pNode, Vec_Ptr_t * vSuper, bool fFirst,
}
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Abc_NodeBalanceConeExor_rec( Abc_Obj_t * pNode, Vec_Ptr_t * vSuper, bool fFirst )
+{
+ int RetValue1, RetValue2, i;
+ // check if the node occurs in the same polarity
+ for ( i = 0; i < vSuper->nSize; i++ )
+ if ( vSuper->pArray[i] == pNode )
+ return 1;
+ // if the new node is complemented or a PI, another gate begins
+ if ( !fFirst && (!pNode->fExor || !Abc_ObjIsNode(pNode)) )
+ {
+ Vec_PtrPush( vSuper, pNode );
+ return 0;
+ }
+ assert( !Abc_ObjIsComplement(pNode) );
+ assert( Abc_ObjIsNode(pNode) );
+ assert( pNode->fExor );
+ // go through the branches
+ RetValue1 = Abc_NodeBalanceConeExor_rec( Abc_ObjFanin0(Abc_ObjFanin0(pNode)), vSuper, 0 );
+ RetValue2 = Abc_NodeBalanceConeExor_rec( Abc_ObjFanin1(Abc_ObjFanin0(pNode)), vSuper, 0 );
+ if ( RetValue1 == -1 || RetValue2 == -1 )
+ return -1;
+ // return 1 if at least one branch has a duplicate
+ return RetValue1 || RetValue2;
+}
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Vec_Ptr_t * Abc_NodeBalanceConeExor( Abc_Obj_t * pNode )
+{
+ Vec_Ptr_t * vSuper;
+ if ( !pNode->fExor )
+ return NULL;
+ vSuper = Vec_PtrAlloc( 10 );
+ Abc_NodeBalanceConeExor_rec( pNode, vSuper, 1 );
+ printf( "%d ", Vec_PtrSize(vSuper) );
+ Vec_PtrFree( vSuper );
+ return NULL;
+}
+
+
+
+/**Function*************************************************************
+
+ Synopsis [Collects the nodes in the implication supergate.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Vec_Ptr_t * Abc_NodeFindCone_rec( Abc_Obj_t * pNode )
+{
+ Vec_Ptr_t * vNodes;
+ Abc_Obj_t * pNodeC, * pNodeT, * pNodeE;
+ int RetValue, i;
+ assert( !Abc_ObjIsComplement(pNode) );
+ if ( Abc_ObjIsCi(pNode) )
+ return NULL;
+ // start the new array
+ vNodes = Vec_PtrAlloc( 4 );
+ // if the node is the MUX collect its fanins
+ if ( Abc_NodeIsMuxType(pNode) )
+ {
+ pNodeC = Abc_NodeRecognizeMux( pNode, &pNodeT, &pNodeE );
+ Vec_PtrPush( vNodes, Abc_ObjRegular(pNodeC) );
+ Vec_PtrPushUnique( vNodes, Abc_ObjRegular(pNodeT) );
+ Vec_PtrPushUnique( vNodes, Abc_ObjRegular(pNodeE) );
+ }
+ else
+ {
+ // collect the nodes in the implication supergate
+ RetValue = Abc_NodeBalanceCone_rec( pNode, vNodes, 1, 1, 0 );
+ assert( vNodes->nSize > 1 );
+ // unmark the visited nodes
+ Vec_PtrForEachEntry( vNodes, pNode, i )
+ Abc_ObjRegular(pNode)->fMarkB = 0;
+ // if we found the node and its complement in the same implication supergate,
+ // return empty set of nodes (meaning that we should use constant-0 node)
+ if ( RetValue == -1 )
+ vNodes->nSize = 0;
+ }
+ // call for the fanin
+ Vec_PtrForEachEntry( vNodes, pNode, i )
+ {
+ pNode = Abc_ObjRegular(pNode);
+ if ( pNode->pCopy )
+ continue;
+ pNode->pCopy = (Abc_Obj_t *)Abc_NodeFindCone_rec( pNode );
+ }
+ return vNodes;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Attaches the implication supergates to internal nodes.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Abc_NtkBalanceAttach( Abc_Ntk_t * pNtk )
+{
+ Abc_Obj_t * pNode;
+ int i;
+ Abc_NtkCleanCopy( pNtk );
+ Abc_NtkForEachCo( pNtk, pNode, i )
+ {
+ pNode = Abc_ObjFanin0(pNode);
+ if ( pNode->pCopy )
+ continue;
+ pNode->pCopy = (Abc_Obj_t *)Abc_NodeFindCone_rec( pNode );
+ }
+}
+
+/**Function*************************************************************
+
+ Synopsis [Attaches the implication supergates to internal nodes.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Abc_NtkBalanceDetach( Abc_Ntk_t * pNtk )
+{
+ Abc_Obj_t * pNode;
+ int i;
+ Abc_NtkForEachNode( pNtk, pNode, i )
+ if ( pNode->pCopy )
+ {
+ Vec_PtrFree( (Vec_Ptr_t *)pNode->pCopy );
+ pNode->pCopy = NULL;
+ }
+}
+
+/**Function*************************************************************
+
+ Synopsis [Compute levels of implication supergates.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Abc_NtkBalanceLevel_rec( Abc_Obj_t * pNode )
+{
+ Vec_Ptr_t * vSuper;
+ Abc_Obj_t * pFanin;
+ int i, LevelMax;
+ assert( !Abc_ObjIsComplement(pNode) );
+ if ( pNode->Level > 0 )
+ return pNode->Level;
+ if ( Abc_ObjIsCi(pNode) )
+ return 0;
+ vSuper = (Vec_Ptr_t *)pNode->pCopy;
+ assert( vSuper != NULL );
+ LevelMax = 0;
+ Vec_PtrForEachEntry( vSuper, pFanin, i )
+ {
+ pFanin = Abc_ObjRegular(pFanin);
+ Abc_NtkBalanceLevel_rec(pFanin);
+ if ( LevelMax < (int)pFanin->Level )
+ LevelMax = pFanin->Level;
+ }
+ pNode->Level = LevelMax + 1;
+ return pNode->Level;
+}
+
+
+/**Function*************************************************************
+
+ Synopsis [Compute levels of implication supergates.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Abc_NtkBalanceLevel( Abc_Ntk_t * pNtk )
+{
+ Abc_Obj_t * pNode;
+ int i;
+ Abc_NtkForEachObj( pNtk, pNode, i )
+ pNode->Level = 0;
+ Abc_NtkForEachCo( pNtk, pNode, i )
+ Abc_NtkBalanceLevel_rec( Abc_ObjFanin0(pNode) );
+}
+
+
+/**Function*************************************************************
+
+ Synopsis [Marks the nodes on the critical and near critical paths.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Abc_NtkMarkCriticalNodes( Abc_Ntk_t * pNtk )
+{
+ Abc_Obj_t * pNode;
+ int i, Counter = 0;
+ Abc_NtkForEachNode( pNtk, pNode, i )
+ if ( Abc_ObjRequiredLevel(pNode) - pNode->Level <= 1 )
+ pNode->fMarkA = 1, Counter++;
+ printf( "The number of nodes on the critical paths = %6d (%5.2f %%)\n", Counter, 100.0 * Counter / Abc_NtkNodeNum(pNtk) );
+}
+
+
////////////////////////////////////////////////////////////////////////
/// END OF FILE ///
////////////////////////////////////////////////////////////////////////
diff --git a/src/base/abci/abcBmc.c b/src/base/abci/abcBmc.c
new file mode 100644
index 00000000..af6d237b
--- /dev/null
+++ b/src/base/abci/abcBmc.c
@@ -0,0 +1,115 @@
+/**CFile****************************************************************
+
+ FileName [abcBmc.c]
+
+ SystemName [ABC: Logic synthesis and verification system.]
+
+ PackageName [Network and node package.]
+
+ Synopsis [Performs bounded model check.]
+
+ Author [Alan Mishchenko]
+
+ Affiliation [UC Berkeley]
+
+ Date [Ver. 1.0. Started - June 20, 2005.]
+
+ Revision [$Id: abcBmc.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "abc.h"
+#include "ivy.h"
+
+////////////////////////////////////////////////////////////////////////
+/// DECLARATIONS ///
+////////////////////////////////////////////////////////////////////////
+
+extern Ivy_Man_t * Abc_NtkIvyBefore( Abc_Ntk_t * pNtk, int fSeq, int fUseDc );
+
+static void Abc_NtkBmcReport( Ivy_Man_t * pMan, Ivy_Man_t * pFrames, Ivy_Man_t * pFraig, Vec_Ptr_t * vMapping, int nFrames );
+
+////////////////////////////////////////////////////////////////////////
+/// FUNCTION DEFINITIONS ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Abc_NtkBmc( Abc_Ntk_t * pNtk, int nFrames, int fInit, int fVerbose )
+{
+ Ivy_FraigParams_t Params, * pParams = &Params;
+ Ivy_Man_t * pMan, * pFrames, * pFraig;
+ Vec_Ptr_t * vMapping;
+ // convert to IVY manager
+ pMan = Abc_NtkIvyBefore( pNtk, 0, 0 );
+ // generate timeframes
+ pFrames = Ivy_ManFrames( pMan, Abc_NtkLatchNum(pNtk), nFrames, fInit, &vMapping );
+ // fraig the timeframes
+ Ivy_FraigParamsDefault( pParams );
+ pParams->nBTLimitNode = ABC_INFINITY;
+ pParams->fVerbose = 0;
+ pParams->fProve = 0;
+ pFraig = Ivy_FraigPerform( pFrames, pParams );
+printf( "Frames have %6d nodes. ", Ivy_ManNodeNum(pFrames) );
+printf( "Fraig has %6d nodes.\n", Ivy_ManNodeNum(pFraig) );
+ // report the classes
+// if ( fVerbose )
+// Abc_NtkBmcReport( pMan, pFrames, pFraig, vMapping, nFrames );
+ // free stuff
+ Vec_PtrFree( vMapping );
+ Ivy_ManStop( pFraig );
+ Ivy_ManStop( pFrames );
+ Ivy_ManStop( pMan );
+}
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Abc_NtkBmcReport( Ivy_Man_t * pMan, Ivy_Man_t * pFrames, Ivy_Man_t * pFraig, Vec_Ptr_t * vMapping, int nFrames )
+{
+ Ivy_Obj_t * pFirst1, * pFirst2, * pFirst3;
+ int i, f, nIdMax, Prev2, Prev3;
+ nIdMax = Ivy_ManObjIdMax(pMan);
+ // check what is the number of nodes in each frame
+ Prev2 = Prev3 = 0;
+ for ( f = 0; f < nFrames; f++ )
+ {
+ Ivy_ManForEachNode( pMan, pFirst1, i )
+ {
+ pFirst2 = Ivy_Regular( Vec_PtrEntry(vMapping, f * nIdMax + pFirst1->Id) );
+ if ( Ivy_ObjIsConst1(pFirst2) || pFirst2->Type == 0 )
+ continue;
+ pFirst3 = Ivy_Regular( pFirst2->pEquiv );
+ if ( Ivy_ObjIsConst1(pFirst3) || pFirst3->Type == 0 )
+ continue;
+ break;
+ }
+ if ( f )
+ printf( "Frame %3d : Strash = %5d Fraig = %5d\n", f, pFirst2->Id - Prev2, pFirst3->Id - Prev3 );
+ Prev2 = pFirst2->Id;
+ Prev3 = pFirst3->Id;
+ }
+}
+
+////////////////////////////////////////////////////////////////////////
+/// END OF FILE ///
+////////////////////////////////////////////////////////////////////////
+
+
diff --git a/src/base/abci/abcCas.c b/src/base/abci/abcCas.c
new file mode 100644
index 00000000..4ed7a774
--- /dev/null
+++ b/src/base/abci/abcCas.c
@@ -0,0 +1,111 @@
+/**CFile****************************************************************
+
+ FileName [abcCas.c]
+
+ SystemName [ABC: Logic synthesis and verification system.]
+
+ PackageName [Network and node package.]
+
+ Synopsis [Decomposition of shared BDDs into LUT cascade.]
+
+ Author [Alan Mishchenko]
+
+ Affiliation [UC Berkeley]
+
+ Date [Ver. 1.0. Started - June 20, 2005.]
+
+ Revision [$Id: abcCas.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "abc.h"
+
+/*
+ This LUT cascade synthesis algorithm is described in the paper:
+ A. Mishchenko and T. Sasao, "Encoding of Boolean functions and its
+ application to LUT cascade synthesis", Proc. IWLS '02, pp. 115-120.
+ http://www.eecs.berkeley.edu/~alanmi/publications/2002/iwls02_enc.pdf
+*/
+
+////////////////////////////////////////////////////////////////////////
+/// DECLARATIONS ///
+////////////////////////////////////////////////////////////////////////
+
+extern int Abc_CascadeExperiment( char * pFileGeneric, DdManager * dd, DdNode ** pOutputs, int nInputs, int nOutputs, int nLutSize, int fCheck, int fVerbose );
+
+////////////////////////////////////////////////////////////////////////
+/// FUNCTION DEFINITIONS ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Abc_Ntk_t * Abc_NtkCascade( Abc_Ntk_t * pNtk, int nLutSize, int fCheck, int fVerbose )
+{
+ DdManager * dd;
+ DdNode ** ppOutputs;
+ Abc_Ntk_t * pNtkNew;
+ Abc_Obj_t * pNode;
+ char * pFileGeneric;
+ int fBddSizeMax = 500000;
+ int fReorder = 1;
+ int i, clk = clock();
+
+ assert( Abc_NtkIsStrash(pNtk) );
+ // compute the global BDDs
+ if ( Abc_NtkBuildGlobalBdds(pNtk, fBddSizeMax, 1, fReorder, fVerbose) == NULL )
+ return NULL;
+
+ if ( fVerbose )
+ {
+ DdManager * dd = Abc_NtkGlobalBddMan( pNtk );
+ printf( "Shared BDD size = %6d nodes. ", Cudd_ReadKeys(dd) - Cudd_ReadDead(dd) );
+ PRT( "BDD construction time", clock() - clk );
+ }
+
+ // collect global BDDs
+ dd = Abc_NtkGlobalBddMan( pNtk );
+ ppOutputs = ALLOC( DdNode *, Abc_NtkCoNum(pNtk) );
+ Abc_NtkForEachCo( pNtk, pNode, i )
+ ppOutputs[i] = Abc_ObjGlobalBdd(pNode);
+
+ // call the decomposition
+ pFileGeneric = Extra_FileNameGeneric( pNtk->pSpec );
+ if ( !Abc_CascadeExperiment( pFileGeneric, dd, ppOutputs, Abc_NtkCiNum(pNtk), Abc_NtkCoNum(pNtk), nLutSize, fCheck, fVerbose ) )
+ {
+ // the LUT size is too small
+ }
+
+ // for now, duplicate the network
+ pNtkNew = Abc_NtkDup( pNtk );
+
+ // cleanup
+ Abc_NtkFreeGlobalBdds( pNtk, 1 );
+ free( ppOutputs );
+ free( pFileGeneric );
+
+// if ( pNtk->pExdc )
+// pNtkNew->pExdc = Abc_NtkDup( pNtk->pExdc );
+ // make sure that everything is okay
+ if ( !Abc_NtkCheck( pNtkNew ) )
+ {
+ printf( "Abc_NtkCollapse: The network check has failed.\n" );
+ Abc_NtkDelete( pNtkNew );
+ return NULL;
+ }
+ return pNtkNew;
+}
+
+////////////////////////////////////////////////////////////////////////
+/// END OF FILE ///
+////////////////////////////////////////////////////////////////////////
+
+
diff --git a/src/base/abci/abcCollapse.c b/src/base/abci/abcClpBdd.c
index 40370eff..a6b3a770 100644
--- a/src/base/abci/abcCollapse.c
+++ b/src/base/abci/abcClpBdd.c
@@ -19,6 +19,7 @@
***********************************************************************/
#include "abc.h"
+//#include "reo.h"
////////////////////////////////////////////////////////////////////////
/// DECLARATIONS ///
@@ -28,7 +29,7 @@ static Abc_Ntk_t * Abc_NtkFromGlobalBdds( Abc_Ntk_t * pNtk );
static Abc_Obj_t * Abc_NodeFromGlobalBdds( Abc_Ntk_t * pNtkNew, DdManager * dd, DdNode * bFunc );
////////////////////////////////////////////////////////////////////////
-/// FUNCTION DEFITIONS ///
+/// FUNCTION DEFINITIONS ///
////////////////////////////////////////////////////////////////////////
/**Function*************************************************************
@@ -42,33 +43,41 @@ static Abc_Obj_t * Abc_NodeFromGlobalBdds( Abc_Ntk_t * pNtkNew, DdManager * dd,
SeeAlso []
***********************************************************************/
-Abc_Ntk_t * Abc_NtkCollapse( Abc_Ntk_t * pNtk, int fVerbose )
+Abc_Ntk_t * Abc_NtkCollapse( Abc_Ntk_t * pNtk, int fBddSizeMax, int fDualRail, int fReorder, int fVerbose )
{
Abc_Ntk_t * pNtkNew;
+ int clk = clock();
assert( Abc_NtkIsStrash(pNtk) );
-
// compute the global BDDs
- if ( Abc_NtkGlobalBdds(pNtk, 0) == NULL )
+ if ( Abc_NtkBuildGlobalBdds(pNtk, fBddSizeMax, 1, fReorder, fVerbose) == NULL )
return NULL;
if ( fVerbose )
- printf( "The shared BDD size is %d nodes.\n", Cudd_ReadKeys(pNtk->pManGlob) - Cudd_ReadDead(pNtk->pManGlob) );
+ {
+ DdManager * dd = Abc_NtkGlobalBddMan( pNtk );
+ printf( "Shared BDD size = %6d nodes. ", Cudd_ReadKeys(dd) - Cudd_ReadDead(dd) );
+ PRT( "BDD construction time", clock() - clk );
+ }
// create the new network
pNtkNew = Abc_NtkFromGlobalBdds( pNtk );
- Abc_NtkFreeGlobalBdds( pNtk );
+// Abc_NtkFreeGlobalBdds( pNtk );
+ Abc_NtkFreeGlobalBdds( pNtk, 1 );
if ( pNtkNew == NULL )
{
- Cudd_Quit( pNtk->pManGlob );
- pNtk->pManGlob = NULL;
+// Cudd_Quit( pNtk->pManGlob );
+// pNtk->pManGlob = NULL;
return NULL;
}
- Extra_StopManager( pNtk->pManGlob );
- pNtk->pManGlob = NULL;
+// Extra_StopManager( pNtk->pManGlob );
+// pNtk->pManGlob = NULL;
// make the network minimum base
Abc_NtkMinimumBase( pNtkNew );
+ if ( pNtk->pExdc )
+ pNtkNew->pExdc = Abc_NtkDup( pNtk->pExdc );
+
// make sure that everything is okay
if ( !Abc_NtkCheck( pNtkNew ) )
{
@@ -79,6 +88,9 @@ Abc_Ntk_t * Abc_NtkCollapse( Abc_Ntk_t * pNtk, int fVerbose )
return pNtkNew;
}
+
+//int runtime1, runtime2;
+
/**Function*************************************************************
Synopsis [Derives the network with the given global BDD.]
@@ -92,13 +104,21 @@ Abc_Ntk_t * Abc_NtkCollapse( Abc_Ntk_t * pNtk, int fVerbose )
***********************************************************************/
Abc_Ntk_t * Abc_NtkFromGlobalBdds( Abc_Ntk_t * pNtk )
{
+// extern void Extra_ShuffleTest( reo_man * p, DdManager * dd, DdNode * Func );
+// reo_man * pReo;
+
ProgressBar * pProgress;
Abc_Ntk_t * pNtkNew;
- Abc_Obj_t * pNode, * pNodeNew;
- DdManager * dd = pNtk->pManGlob;
+ Abc_Obj_t * pNode, * pDriver, * pNodeNew;
+// DdManager * dd = pNtk->pManGlob;
+ DdManager * dd = Abc_NtkGlobalBddMan( pNtk );
int i;
+
+// pReo = Extra_ReorderInit( Abc_NtkCiNum(pNtk), 1000 );
+// runtime1 = runtime2 = 0;
+
// start the new network
- pNtkNew = Abc_NtkStartFrom( pNtk, ABC_TYPE_LOGIC, ABC_FUNC_BDD );
+ pNtkNew = Abc_NtkStartFrom( pNtk, ABC_NTK_LOGIC, ABC_FUNC_BDD );
// make sure the new manager has the same number of inputs
Cudd_bddIthVar( pNtkNew->pManFunc, dd->size-1 );
// process the POs
@@ -106,10 +126,25 @@ Abc_Ntk_t * Abc_NtkFromGlobalBdds( Abc_Ntk_t * pNtk )
Abc_NtkForEachCo( pNtk, pNode, i )
{
Extra_ProgressBarUpdate( pProgress, i, NULL );
- pNodeNew = Abc_NodeFromGlobalBdds( pNtkNew, dd, Vec_PtrEntry(pNtk->vFuncsGlob, i) );
+ pDriver = Abc_ObjFanin0(pNode);
+ if ( Abc_ObjIsCi(pDriver) && !strcmp(Abc_ObjName(pNode), Abc_ObjName(pDriver)) )
+ {
+ Abc_ObjAddFanin( pNode->pCopy, pDriver->pCopy );
+ continue;
+ }
+// pNodeNew = Abc_NodeFromGlobalBdds( pNtkNew, dd, Vec_PtrEntry(pNtk->vFuncsGlob, i) );
+ pNodeNew = Abc_NodeFromGlobalBdds( pNtkNew, dd, Abc_ObjGlobalBdd(pNode) );
Abc_ObjAddFanin( pNode->pCopy, pNodeNew );
+
+// Extra_ShuffleTest( pReo, dd, Abc_ObjGlobalBdd(pNode) );
+
}
Extra_ProgressBarStop( pProgress );
+
+// Extra_ReorderQuit( pReo );
+//PRT( "Reo ", runtime1 );
+//PRT( "Cudd", runtime2 );
+
return pNtkNew;
}
diff --git a/src/base/abci/abcClpSop.c b/src/base/abci/abcClpSop.c
new file mode 100644
index 00000000..de92243f
--- /dev/null
+++ b/src/base/abci/abcClpSop.c
@@ -0,0 +1,53 @@
+/**CFile****************************************************************
+
+ FileName [abcCollapse.c]
+
+ SystemName [ABC: Logic synthesis and verification system.]
+
+ PackageName [Network and node package.]
+
+ Synopsis [Collapsing the network into two-levels.]
+
+ Author [Alan Mishchenko]
+
+ Affiliation [UC Berkeley]
+
+ Date [Ver. 1.0. Started - June 20, 2005.]
+
+ Revision [$Id: abcCollapse.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "abc.h"
+
+////////////////////////////////////////////////////////////////////////
+/// DECLARATIONS ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+/// FUNCTION DEFINITIONS ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+ Synopsis [Collapses the network.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Abc_Ntk_t * Abc_NtkCollapseSop( Abc_Ntk_t * pNtk, int fVerbose )
+{
+ Abc_Ntk_t * pNtkNew;
+ pNtkNew = NULL;
+ return pNtkNew;
+}
+
+////////////////////////////////////////////////////////////////////////
+/// END OF FILE ///
+////////////////////////////////////////////////////////////////////////
+
+
diff --git a/src/base/abci/abcCut.c b/src/base/abci/abcCut.c
index f487bd1b..d399ce5f 100644
--- a/src/base/abci/abcCut.c
+++ b/src/base/abci/abcCut.c
@@ -25,8 +25,16 @@
/// DECLARATIONS ///
////////////////////////////////////////////////////////////////////////
+static void Abc_NtkPrintCuts( void * p, Abc_Ntk_t * pNtk, int fSeq );
+static void Abc_NtkPrintCuts_( void * p, Abc_Ntk_t * pNtk, int fSeq );
+
+extern int nTotal, nGood, nEqual;
+
+static Vec_Int_t * Abc_NtkGetNodeAttributes( Abc_Ntk_t * pNtk );
+static int Abc_NtkComputeArea( Abc_Ntk_t * pNtk, Cut_Man_t * p );
+
////////////////////////////////////////////////////////////////////////
-/// FUNCTION DEFITIONS ///
+/// FUNCTION DEFINITIONS ///
////////////////////////////////////////////////////////////////////////
/**Function*************************************************************
@@ -42,18 +50,30 @@
***********************************************************************/
Cut_Man_t * Abc_NtkCuts( Abc_Ntk_t * pNtk, Cut_Params_t * pParams )
{
+ ProgressBar * pProgress;
Cut_Man_t * p;
- Abc_Obj_t * pObj, * pDriver, * pNode;
+ Abc_Obj_t * pObj, * pNode;
Vec_Ptr_t * vNodes;
Vec_Int_t * vChoices;
int i;
int clk = clock();
- assert( Abc_NtkIsStrash(pNtk) );
+ extern void Abc_NtkBalanceAttach( Abc_Ntk_t * pNtk );
+ extern void Abc_NtkBalanceDetach( Abc_Ntk_t * pNtk );
+ nTotal = nGood = nEqual = 0;
+
+ assert( Abc_NtkIsStrash(pNtk) );
// start the manager
pParams->nIdsMax = Abc_NtkObjNumMax( pNtk );
p = Cut_ManStart( pParams );
+ // compute node attributes if local or global cuts are requested
+ if ( pParams->fGlobal || pParams->fLocal )
+ {
+ extern Vec_Int_t * Abc_NtkGetNodeAttributes( Abc_Ntk_t * pNtk );
+ Cut_ManSetNodeAttrs( p, Abc_NtkGetNodeAttributes(pNtk) );
+ }
+ // prepare for cut dropping
if ( pParams->fDrop )
Cut_ManSetFanoutCounts( p, Abc_NtkFanoutCounts(pNtk) );
// set cuts for PIs
@@ -61,8 +81,9 @@ Cut_Man_t * Abc_NtkCuts( Abc_Ntk_t * pNtk, Cut_Params_t * pParams )
if ( Abc_ObjFanoutNum(pObj) > 0 )
Cut_NodeSetTriv( p, pObj->Id );
// compute cuts for internal nodes
- vNodes = Abc_AigDfs( pNtk, 0, 1 );
+ vNodes = Abc_AigDfs( pNtk, 0, 1 ); // collects POs
vChoices = Vec_IntAlloc( 100 );
+ pProgress = Extra_ProgressBarStart( stdout, Vec_PtrSize(vNodes) );
Vec_PtrForEachEntry( vNodes, pObj, i )
{
// when we reached a CO, it is time to deallocate the cuts
@@ -73,12 +94,19 @@ Cut_Man_t * Abc_NtkCuts( Abc_Ntk_t * pNtk, Cut_Params_t * pParams )
continue;
}
// skip constant node, it has no cuts
- if ( Abc_NodeIsConst(pObj) )
- continue;
+// if ( Abc_NodeIsConst(pObj) )
+// continue;
+ Extra_ProgressBarUpdate( pProgress, i, NULL );
// compute the cuts to the internal node
- Abc_NodeGetCuts( p, pObj );
+ Abc_NodeGetCuts( p, pObj, pParams->fDag, pParams->fTree );
+ // consider dropping the fanins cuts
+ if ( pParams->fDrop )
+ {
+ Cut_NodeTryDroppingCuts( p, Abc_ObjFaninId0(pObj) );
+ Cut_NodeTryDroppingCuts( p, Abc_ObjFaninId1(pObj) );
+ }
// add cuts due to choices
- if ( Abc_NodeIsAigChoice(pObj) )
+ if ( Abc_AigNodeIsChoice(pObj) )
{
Vec_IntClear( vChoices );
for ( pNode = pObj; pNode; pNode = pNode->pData )
@@ -86,31 +114,203 @@ Cut_Man_t * Abc_NtkCuts( Abc_Ntk_t * pNtk, Cut_Params_t * pParams )
Cut_NodeUnionCuts( p, vChoices );
}
}
- if ( !pParams->fSeq )
+ Extra_ProgressBarStop( pProgress );
+ Vec_PtrFree( vNodes );
+ Vec_IntFree( vChoices );
+ Cut_ManPrintStats( p );
+PRT( "TOTAL ", clock() - clk );
+ printf( "Area = %d.\n", Abc_NtkComputeArea( pNtk, p ) );
+//Abc_NtkPrintCuts( p, pNtk, 0 );
+// Cut_ManPrintStatsToFile( p, pNtk->pSpec, clock() - clk );
+
+ // temporary printout of stats
+ if ( nTotal )
+ printf( "Total cuts = %d. Good cuts = %d. Ratio = %5.2f\n", nTotal, nGood, ((double)nGood)/nTotal );
+ return p;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Cut computation using the oracle.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Abc_NtkCutsOracle( Abc_Ntk_t * pNtk, Cut_Oracle_t * p )
+{
+ Abc_Obj_t * pObj;
+ Vec_Ptr_t * vNodes;
+ int i, clk = clock();
+ int fDrop = Cut_OracleReadDrop(p);
+
+ assert( Abc_NtkIsStrash(pNtk) );
+
+ // prepare cut droppping
+ if ( fDrop )
+ Cut_OracleSetFanoutCounts( p, Abc_NtkFanoutCounts(pNtk) );
+
+ // set cuts for PIs
+ Abc_NtkForEachCi( pNtk, pObj, i )
+ if ( Abc_ObjFanoutNum(pObj) > 0 )
+ Cut_OracleNodeSetTriv( p, pObj->Id );
+
+ // compute cuts for internal nodes
+ vNodes = Abc_AigDfs( pNtk, 0, 1 ); // collects POs
+ Vec_PtrForEachEntry( vNodes, pObj, i )
{
- Vec_PtrFree( vNodes );
- Vec_IntFree( vChoices );
-PRT( "Total", clock() - clk );
- return p;
+ // when we reached a CO, it is time to deallocate the cuts
+ if ( Abc_ObjIsCo(pObj) )
+ {
+ if ( fDrop )
+ Cut_OracleTryDroppingCuts( p, Abc_ObjFaninId0(pObj) );
+ continue;
+ }
+ // skip constant node, it has no cuts
+// if ( Abc_NodeIsConst(pObj) )
+// continue;
+ // compute the cuts to the internal node
+ Cut_OracleComputeCuts( p, pObj->Id, Abc_ObjFaninId0(pObj), Abc_ObjFaninId1(pObj),
+ Abc_ObjFaninC0(pObj), Abc_ObjFaninC1(pObj) );
+ // consider dropping the fanins cuts
+ if ( fDrop )
+ {
+ Cut_OracleTryDroppingCuts( p, Abc_ObjFaninId0(pObj) );
+ Cut_OracleTryDroppingCuts( p, Abc_ObjFaninId1(pObj) );
+ }
}
- assert( 0 );
+ Vec_PtrFree( vNodes );
+//PRT( "Total", clock() - clk );
+//Abc_NtkPrintCuts_( p, pNtk, 0 );
+}
+
- // compute sequential cuts
- Abc_NtkIncrementTravId( pNtk );
- Abc_NtkForEachLatch( pNtk, pObj, i )
+/**Function*************************************************************
+
+ Synopsis [Computes the cuts for the network.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Cut_Man_t * Abc_NtkSeqCuts( Abc_Ntk_t * pNtk, Cut_Params_t * pParams )
+{
+/*
+ Cut_Man_t * p;
+ Abc_Obj_t * pObj, * pNode;
+ int i, nIters, fStatus;
+ Vec_Int_t * vChoices;
+ int clk = clock();
+
+ assert( Abc_NtkIsSeq(pNtk) );
+ assert( pParams->fSeq );
+// assert( Abc_NtkIsDfsOrdered(pNtk) );
+
+ // start the manager
+ pParams->nIdsMax = Abc_NtkObjNumMax( pNtk );
+ pParams->nCutSet = Abc_NtkCutSetNodeNum( pNtk );
+ p = Cut_ManStart( pParams );
+
+ // set cuts for the constant node and the PIs
+ pObj = Abc_AigConst1(pNtk);
+ if ( Abc_ObjFanoutNum(pObj) > 0 )
+ Cut_NodeSetTriv( p, pObj->Id );
+ Abc_NtkForEachPi( pNtk, pObj, i )
{
- pDriver = Abc_ObjFanin0(pObj);
- if ( !Abc_ObjIsNode(pDriver) )
- continue;
- if ( Abc_NodeIsTravIdCurrent(pDriver) )
- continue;
- Abc_NodeSetTravIdCurrent(pDriver);
- Cut_NodeSetComputedAsNew( p, pDriver->Id );
+//printf( "Setting trivial cut %d.\n", pObj->Id );
+ Cut_NodeSetTriv( p, pObj->Id );
+ }
+ // label the cutset nodes and set their number in the array
+ // assign the elementary cuts to the cutset nodes
+ Abc_SeqForEachCutsetNode( pNtk, pObj, i )
+ {
+ assert( pObj->fMarkC == 0 );
+ pObj->fMarkC = 1;
+ pObj->pCopy = (Abc_Obj_t *)i;
+ Cut_NodeSetTriv( p, pObj->Id );
+//printf( "Setting trivial cut %d.\n", pObj->Id );
}
- // compute as long as new cuts appear
+ // process the nodes
+ vChoices = Vec_IntAlloc( 100 );
+ for ( nIters = 0; nIters < 10; nIters++ )
+ {
+//printf( "ITERATION %d:\n", nIters );
+ // compute the cuts for the internal nodes
+ Abc_AigForEachAnd( pNtk, pObj, i )
+ {
+ Abc_NodeGetCutsSeq( p, pObj, nIters==0 );
+ // add cuts due to choices
+ if ( Abc_AigNodeIsChoice(pObj) )
+ {
+ Vec_IntClear( vChoices );
+ for ( pNode = pObj; pNode; pNode = pNode->pData )
+ Vec_IntPush( vChoices, pNode->Id );
+ Cut_NodeUnionCutsSeq( p, vChoices, (pObj->fMarkC ? (int)pObj->pCopy : -1), nIters==0 );
+ }
+ }
+ // merge the new cuts with the old cuts
+ Abc_NtkForEachPi( pNtk, pObj, i )
+ Cut_NodeNewMergeWithOld( p, pObj->Id );
+ Abc_AigForEachAnd( pNtk, pObj, i )
+ Cut_NodeNewMergeWithOld( p, pObj->Id );
+ // for the cutset, transfer temp cuts to new cuts
+ fStatus = 0;
+ Abc_SeqForEachCutsetNode( pNtk, pObj, i )
+ fStatus |= Cut_NodeTempTransferToNew( p, pObj->Id, i );
+ if ( fStatus == 0 )
+ break;
+ }
+ Vec_IntFree( vChoices );
+
+ // if the status is not finished, transfer new to old for the cutset
+ Abc_SeqForEachCutsetNode( pNtk, pObj, i )
+ Cut_NodeNewMergeWithOld( p, pObj->Id );
+ // transfer the old cuts to the new positions
+ Abc_NtkForEachObj( pNtk, pObj, i )
+ Cut_NodeOldTransferToNew( p, pObj->Id );
+
+ // unlabel the cutset nodes
+ Abc_SeqForEachCutsetNode( pNtk, pObj, i )
+ pObj->fMarkC = 0;
+if ( pParams->fVerbose )
+{
+ Cut_ManPrintStats( p );
+PRT( "TOTAL ", clock() - clk );
+printf( "Converged after %d iterations.\n", nIters );
+}
+//Abc_NtkPrintCuts( p, pNtk, 1 );
return p;
+*/
+ return NULL;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Computes area.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Abc_NtkComputeArea( Abc_Ntk_t * pNtk, Cut_Man_t * p )
+{
+ Abc_Obj_t * pObj;
+ int Counter, i;
+ Counter = 0;
+ Abc_NtkForEachCo( pNtk, pObj, i )
+ Counter += Cut_ManMappingArea_rec( p, Abc_ObjFaninId0(pObj) );
+ return Counter;
}
/**Function*************************************************************
@@ -124,14 +324,14 @@ PRT( "Total", clock() - clk );
SeeAlso []
***********************************************************************/
-void * Abc_NodeGetCutsRecursive( void * p, Abc_Obj_t * pObj )
+void * Abc_NodeGetCutsRecursive( void * p, Abc_Obj_t * pObj, int fDag, int fTree )
{
void * pList;
if ( pList = Abc_NodeReadCuts( p, pObj ) )
return pList;
- Abc_NodeGetCutsRecursive( p, Abc_ObjFanin0(pObj) );
- Abc_NodeGetCutsRecursive( p, Abc_ObjFanin1(pObj) );
- return Abc_NodeGetCuts( p, pObj );
+ Abc_NodeGetCutsRecursive( p, Abc_ObjFanin0(pObj), fDag, fTree );
+ Abc_NodeGetCutsRecursive( p, Abc_ObjFanin1(pObj), fDag, fTree );
+ return Abc_NodeGetCuts( p, pObj, fDag, fTree );
}
/**Function*************************************************************
@@ -145,10 +345,73 @@ void * Abc_NodeGetCutsRecursive( void * p, Abc_Obj_t * pObj )
SeeAlso []
***********************************************************************/
-void * Abc_NodeGetCuts( void * p, Abc_Obj_t * pObj )
+void * Abc_NodeGetCuts( void * p, Abc_Obj_t * pObj, int fDag, int fTree )
{
+ Abc_Obj_t * pFanin;
+ int fDagNode, fTriv, TreeCode = 0;
+// assert( Abc_NtkIsStrash(pObj->pNtk) );
+ assert( Abc_ObjFaninNum(pObj) == 2 );
+
+
+ // check if the node is a DAG node
+ fDagNode = (Abc_ObjFanoutNum(pObj) > 1 && !Abc_NodeIsMuxControlType(pObj));
+ // increment the counter of DAG nodes
+ if ( fDagNode ) Cut_ManIncrementDagNodes( p );
+ // add the trivial cut if the node is a DAG node, or if we compute all cuts
+ fTriv = fDagNode || !fDag;
+ // check if fanins are DAG nodes
+ if ( fTree )
+ {
+ pFanin = Abc_ObjFanin0(pObj);
+ TreeCode |= (Abc_ObjFanoutNum(pFanin) > 1 && !Abc_NodeIsMuxControlType(pFanin));
+ pFanin = Abc_ObjFanin1(pObj);
+ TreeCode |= ((Abc_ObjFanoutNum(pFanin) > 1 && !Abc_NodeIsMuxControlType(pFanin)) << 1);
+ }
+
+
+ // changes due to the global/local cut computation
+ {
+ Cut_Params_t * pParams = Cut_ManReadParams(p);
+ if ( pParams->fLocal )
+ {
+ Vec_Int_t * vNodeAttrs = Cut_ManReadNodeAttrs(p);
+ fDagNode = Vec_IntEntry( vNodeAttrs, pObj->Id );
+ if ( fDagNode ) Cut_ManIncrementDagNodes( p );
+// fTriv = fDagNode || !pParams->fGlobal;
+ fTriv = !Vec_IntEntry( vNodeAttrs, pObj->Id );
+ TreeCode = 0;
+ pFanin = Abc_ObjFanin0(pObj);
+ TreeCode |= Vec_IntEntry( vNodeAttrs, pFanin->Id );
+ pFanin = Abc_ObjFanin1(pObj);
+ TreeCode |= (Vec_IntEntry( vNodeAttrs, pFanin->Id ) << 1);
+ }
+ }
return Cut_NodeComputeCuts( p, pObj->Id, Abc_ObjFaninId0(pObj), Abc_ObjFaninId1(pObj),
- Abc_ObjFaninC0(pObj), Abc_ObjFaninC1(pObj) );
+ Abc_ObjFaninC0(pObj), Abc_ObjFaninC1(pObj), fTriv, TreeCode );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Computes the cuts for the network.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Abc_NodeGetCutsSeq( void * p, Abc_Obj_t * pObj, int fTriv )
+{
+/*
+ int CutSetNum;
+ assert( Abc_NtkIsSeq(pObj->pNtk) );
+ assert( Abc_ObjFaninNum(pObj) == 2 );
+ fTriv = pObj->fMarkC ? 0 : fTriv;
+ CutSetNum = pObj->fMarkC ? (int)pObj->pCopy : -1;
+ Cut_NodeComputeCutsSeq( p, pObj->Id, Abc_ObjFaninId0(pObj), Abc_ObjFaninId1(pObj),
+ Abc_ObjFaninC0(pObj), Abc_ObjFaninC1(pObj), Seq_ObjFaninL0(pObj), Seq_ObjFaninL1(pObj), fTriv, CutSetNum );
+*/
}
/**Function*************************************************************
@@ -164,7 +427,7 @@ void * Abc_NodeGetCuts( void * p, Abc_Obj_t * pObj )
***********************************************************************/
void * Abc_NodeReadCuts( void * p, Abc_Obj_t * pObj )
{
- return Cut_NodeReadCuts( p, pObj->Id );
+ return Cut_NodeReadCutsNew( p, pObj->Id );
}
/**Function*************************************************************
@@ -183,6 +446,173 @@ void Abc_NodeFreeCuts( void * p, Abc_Obj_t * pObj )
Cut_NodeFreeCuts( p, pObj->Id );
}
+/**Function*************************************************************
+
+ Synopsis [Computes the cuts for the network.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Abc_NtkPrintCuts( void * p, Abc_Ntk_t * pNtk, int fSeq )
+{
+ Cut_Man_t * pMan = p;
+ Cut_Cut_t * pList;
+ Abc_Obj_t * pObj;
+ int i;
+ printf( "Cuts of the network:\n" );
+ Abc_NtkForEachObj( pNtk, pObj, i )
+ {
+ pList = Abc_NodeReadCuts( p, pObj );
+ printf( "Node %s:\n", Abc_ObjName(pObj) );
+ Cut_CutPrintList( pList, fSeq );
+ }
+}
+
+/**Function*************************************************************
+
+ Synopsis [Computes the cuts for the network.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Abc_NtkPrintCuts_( void * p, Abc_Ntk_t * pNtk, int fSeq )
+{
+ Cut_Man_t * pMan = p;
+ Cut_Cut_t * pList;
+ Abc_Obj_t * pObj;
+ pObj = Abc_NtkObj( pNtk, 2 * Abc_NtkObjNum(pNtk) / 3 );
+ pList = Abc_NodeReadCuts( p, pObj );
+ printf( "Node %s:\n", Abc_ObjName(pObj) );
+ Cut_CutPrintList( pList, fSeq );
+}
+
+
+
+
+/**Function*************************************************************
+
+ Synopsis [Assigns global attributes randomly.]
+
+ Description [Old code.]
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Vec_Int_t * Abc_NtkGetNodeAttributes( Abc_Ntk_t * pNtk )
+{
+ Vec_Int_t * vAttrs;
+// Vec_Ptr_t * vNodes;
+ Abc_Obj_t * pObj;//, * pTemp;
+ int i;//, k;
+ int nNodesTotal = 0, nMffcsTotal = 0;
+ extern Vec_Ptr_t * Abc_NodeMffsInsideCollect( Abc_Obj_t * pNode );
+
+ vAttrs = Vec_IntStart( Abc_NtkObjNumMax(pNtk) + 1 );
+// Abc_NtkForEachCi( pNtk, pObj, i )
+// Vec_IntWriteEntry( vAttrs, pObj->Id, 1 );
+
+ Abc_NtkForEachObj( pNtk, pObj, i )
+ {
+ if ( Abc_ObjIsNode(pObj) )
+ nNodesTotal++;
+ if ( Abc_ObjIsCo(pObj) && Abc_ObjIsNode(Abc_ObjFanin0(pObj)) )
+ nMffcsTotal += Abc_NodeMffcSize( Abc_ObjFanin0(pObj) );
+// if ( Abc_ObjIsNode(pObj) && (rand() % 4 == 0) )
+// if ( Abc_ObjIsNode(pObj) && Abc_ObjFanoutNum(pObj) > 1 && !Abc_NodeIsMuxControlType(pObj) && (rand() % 3 == 0) )
+ if ( Abc_ObjIsNode(pObj) && Abc_ObjFanoutNum(pObj) > 1 && !Abc_NodeIsMuxControlType(pObj) )
+ {
+ int nMffc = Abc_NodeMffcSize(pObj);
+ nMffcsTotal += Abc_NodeMffcSize(pObj);
+// printf( "%d ", nMffc );
+
+ if ( nMffc > 2 || Abc_ObjFanoutNum(pObj) > 8 )
+ Vec_IntWriteEntry( vAttrs, pObj->Id, 1 );
+ }
+ }
+/*
+ Abc_NtkForEachObj( pNtk, pObj, i )
+ {
+ if ( Vec_IntEntry( vAttrs, pObj->Id ) )
+ {
+ vNodes = Abc_NodeMffsInsideCollect( pObj );
+ Vec_PtrForEachEntry( vNodes, pTemp, k )
+ if ( pTemp != pObj )
+ Vec_IntWriteEntry( vAttrs, pTemp->Id, 0 );
+ Vec_PtrFree( vNodes );
+ }
+ }
+*/
+ printf( "Total nodes = %d. Total MFFC nodes = %d.\n", nNodesTotal, nMffcsTotal );
+ return vAttrs;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Assigns global attributes randomly.]
+
+ Description [Old code.]
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Abc_NtkSubDagSize_rec( Abc_Obj_t * pObj, Vec_Int_t * vAttrs )
+{
+ if ( Abc_NodeIsTravIdCurrent(pObj) )
+ return 0;
+ Abc_NodeSetTravIdCurrent(pObj);
+ if ( Vec_IntEntry( vAttrs, pObj->Id ) )
+ return 0;
+ if ( Abc_ObjIsCi(pObj) )
+ return 1;
+ assert( Abc_ObjFaninNum(pObj) == 2 );
+ return 1 + Abc_NtkSubDagSize_rec(Abc_ObjFanin0(pObj), vAttrs) +
+ Abc_NtkSubDagSize_rec(Abc_ObjFanin1(pObj), vAttrs);
+}
+
+/**Function*************************************************************
+
+ Synopsis [Assigns global attributes randomly.]
+
+ Description [Old code.]
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Vec_Int_t * Abc_NtkGetNodeAttributes2( Abc_Ntk_t * pNtk )
+{
+ Vec_Int_t * vAttrs;
+ Abc_Obj_t * pObj;
+ int i, nSize;
+ assert( Abc_NtkIsDfsOrdered(pNtk) );
+ vAttrs = Vec_IntStart( Abc_NtkObjNumMax(pNtk) + 1 );
+ Abc_NtkForEachObj( pNtk, pObj, i )
+ {
+ // skip no-nodes and nodes without fanouts
+ if ( pObj->Id == 0 || !(Abc_ObjIsNode(pObj) && Abc_ObjFanoutNum(pObj) > 1 && !Abc_NodeIsMuxControlType(pObj)) )
+ continue;
+ // the node has more than one fanout - count its sub-DAG size
+ Abc_NtkIncrementTravId( pNtk );
+ nSize = Abc_NtkSubDagSize_rec( pObj, vAttrs );
+ if ( nSize > 15 )
+ Vec_IntWriteEntry( vAttrs, pObj->Id, 1 );
+ }
+ return vAttrs;
+}
+
////////////////////////////////////////////////////////////////////////
/// END OF FILE ///
////////////////////////////////////////////////////////////////////////
diff --git a/src/base/abci/abcDar.c b/src/base/abci/abcDar.c
index 39f58a4e..1563bdfe 100644
--- a/src/base/abci/abcDar.c
+++ b/src/base/abci/abcDar.c
@@ -22,16 +22,13 @@
#include "aig.h"
#include "dar.h"
#include "cnf.h"
-//#include "fra.h"
-//#include "fraig.h"
+#include "fra.h"
+#include "fraig.h"
////////////////////////////////////////////////////////////////////////
/// DECLARATIONS ///
////////////////////////////////////////////////////////////////////////
-#define Vec_PtrForEachEntryStop( vVec, pEntry, i, Stop ) \
- for ( i = 0; (i < Stop) && (((pEntry) = Vec_PtrEntry(vVec, i)), 1); i++ )
-
////////////////////////////////////////////////////////////////////////
/// FUNCTION DEFINITIONS ///
////////////////////////////////////////////////////////////////////////
@@ -56,6 +53,25 @@ Aig_Man_t * Abc_NtkToDar( Abc_Ntk_t * pNtk, int fRegisters )
// make sure the latches follow PIs/POs
if ( fRegisters )
{
+ assert( Abc_NtkBoxNum(pNtk) == Abc_NtkLatchNum(pNtk) );
+ Abc_NtkForEachCi( pNtk, pObj, i )
+ if ( i < Abc_NtkPiNum(pNtk) )
+ {
+ assert( Abc_ObjIsPi(pObj) );
+ if ( !Abc_ObjIsPi(pObj) )
+ printf( "Abc_NtkToDar(): Temporary bug: The PI ordering is wrong!\n" );
+ }
+ else
+ assert( Abc_ObjIsBo(pObj) );
+ Abc_NtkForEachCo( pNtk, pObj, i )
+ if ( i < Abc_NtkPoNum(pNtk) )
+ {
+ assert( Abc_ObjIsPo(pObj) );
+ if ( !Abc_ObjIsPo(pObj) )
+ printf( "Abc_NtkToDar(): Temporary bug: The PO ordering is wrong!\n" );
+ }
+ else
+ assert( Abc_ObjIsBi(pObj) );
// print warning about initial values
nDontCares = 0;
Abc_NtkForEachLatch( pNtk, pObj, i )
@@ -74,7 +90,7 @@ Aig_Man_t * Abc_NtkToDar( Abc_Ntk_t * pNtk, int fRegisters )
}
// create the manager
pMan = Aig_ManStart( Abc_NtkNodeNum(pNtk) + 100 );
- pMan->pName = util_strsav( pNtk->pName );
+ pMan->pName = Extra_UtilStrsav( pNtk->pName );
// save the number of registers
if ( fRegisters )
{
@@ -83,7 +99,7 @@ Aig_Man_t * Abc_NtkToDar( Abc_Ntk_t * pNtk, int fRegisters )
pMan->vFlopNums = NULL;
}
// transfer the pointers to the basic nodes
- Abc_AigConst1(pNtk->pManFunc)->pCopy = (Abc_Obj_t *)Aig_ManConst1(pMan);
+ Abc_AigConst1(pNtk)->pCopy = (Abc_Obj_t *)Aig_ManConst1(pMan);
Abc_NtkForEachCi( pNtk, pObj, i )
pObj->pCopy = (Abc_Obj_t *)Aig_ObjCreatePi(pMan);
// complement the 1-values registers
@@ -95,8 +111,6 @@ Aig_Man_t * Abc_NtkToDar( Abc_Ntk_t * pNtk, int fRegisters )
// pMan->fAddStrash = 1;
Abc_NtkForEachNode( pNtk, pObj, i )
{
- if ( Abc_ObjFaninNum(pObj) == 0 )
- continue;
pObj->pCopy = (Abc_Obj_t *)Aig_And( pMan, (Aig_Obj_t *)Abc_ObjChild0Copy(pObj), (Aig_Obj_t *)Abc_ObjChild1Copy(pObj) );
// printf( "%d->%d ", pObj->Id, ((Aig_Obj_t *)pObj->pCopy)->Id );
}
@@ -107,8 +121,7 @@ Aig_Man_t * Abc_NtkToDar( Abc_Ntk_t * pNtk, int fRegisters )
// complement the 1-valued registers
if ( fRegisters )
Aig_ManForEachLiSeq( pMan, pObjNew, i )
-// if ( Abc_LatchIsInit1(Abc_ObjFanout0(Abc_NtkCo(pNtk,i))) )
- if ( Abc_LatchIsInit1(Abc_NtkCo(pNtk,i)) )
+ if ( Abc_LatchIsInit1(Abc_ObjFanout0(Abc_NtkCo(pNtk,i))) )
pObjNew->pFanin0 = Aig_Not(pObjNew->pFanin0);
// remove dangling nodes
if ( nNodes = Aig_ManCleanup( pMan ) )
@@ -138,14 +151,14 @@ Abc_Ntk_t * Abc_NtkFromDar( Abc_Ntk_t * pNtkOld, Aig_Man_t * pMan )
{
Vec_Ptr_t * vNodes;
Abc_Ntk_t * pNtkNew;
-// Abc_Obj_t * pObjNew;
+ Abc_Obj_t * pObjNew;
Aig_Obj_t * pObj;
int i;
// assert( Aig_ManRegNum(pMan) == Abc_NtkLatchNum(pNtkOld) );
// perform strashing
- pNtkNew = Abc_NtkStartFrom( pNtkOld, ABC_TYPE_STRASH, ABC_FUNC_AIG );
+ pNtkNew = Abc_NtkStartFrom( pNtkOld, ABC_NTK_STRASH, ABC_FUNC_AIG );
// transfer the pointers to the basic nodes
- Aig_ManConst1(pMan)->pData = Abc_AigConst1(pNtkNew->pManFunc);
+ Aig_ManConst1(pMan)->pData = Abc_AigConst1(pNtkNew);
Aig_ManForEachPi( pMan, pObj, i )
pObj->pData = Abc_NtkCi(pNtkNew, i);
// rebuild the AIG
@@ -163,7 +176,6 @@ Abc_Ntk_t * Abc_NtkFromDar( Abc_Ntk_t * pNtkOld, Aig_Man_t * pMan )
break;
Abc_ObjAddFanin( Abc_NtkCo(pNtkNew, i), (Abc_Obj_t *)Aig_ObjChild0Copy(pObj) );
}
-/*
// if there are assertions, add them
if ( pMan->nAsserts > 0 )
Aig_ManForEachAssert( pMan, pObj, i )
@@ -172,7 +184,6 @@ Abc_Ntk_t * Abc_NtkFromDar( Abc_Ntk_t * pNtkOld, Aig_Man_t * pMan )
Abc_ObjAssignName( pObjNew, "assert_", Abc_ObjName(pObjNew) );
Abc_ObjAddFanin( pObjNew, (Abc_Obj_t *)Aig_ObjChild0Copy(pObj) );
}
-*/
if ( !Abc_NtkCheck( pNtkNew ) )
fprintf( stdout, "Abc_NtkFromDar(): Network check has failed.\n" );
return pNtkNew;
@@ -180,30 +191,6 @@ Abc_Ntk_t * Abc_NtkFromDar( Abc_Ntk_t * pNtkOld, Aig_Man_t * pMan )
/**Function*************************************************************
- Synopsis [Adds dummy names.]
-
- Description []
-
- SideEffects []
-
- SeeAlso []
-
-***********************************************************************/
-void Abc_NtkAddDummyLatchNames( Abc_Ntk_t * pNtk )
-{
- char Buffer[100];
- Abc_Obj_t * pObj;
- int nDigits, i;
- nDigits = Extra_Base10Log( Abc_NtkLatchNum(pNtk) );
- Abc_NtkForEachLatch( pNtk, pObj, i )
- {
- sprintf( Buffer, "L%0*d", nDigits, i );
- Abc_NtkLogicStoreName( pObj, Buffer );
- }
-}
-
-/**Function*************************************************************
-
Synopsis [Converts the network from the AIG manager into ABC.]
Description [This procedure should be called after seq sweeping,
@@ -217,38 +204,52 @@ void Abc_NtkAddDummyLatchNames( Abc_Ntk_t * pNtk )
Abc_Ntk_t * Abc_NtkFromDarSeqSweep( Abc_Ntk_t * pNtkOld, Aig_Man_t * pMan )
{
Vec_Ptr_t * vNodes;
- Abc_Ntk_t * pNtkNew;
- Abc_Obj_t * pObjOld, * pObjNew;
+ Abc_Ntk_t * pNtkNew;
+ Abc_Obj_t * pObjNew, * pLatch;
Aig_Obj_t * pObj, * pObjLo, * pObjLi;
- int i;
- // start the network
- pNtkNew = Abc_NtkAlloc( ABC_TYPE_STRASH, ABC_FUNC_AIG );
- // duplicate the name and the spec
- pNtkNew->pName = util_strsav(pNtkOld->pName);
- pNtkNew->pSpec = util_strsav(pNtkOld->pSpec);
- // create PIs/POs/latches
- Abc_NtkForEachPi( pNtkOld, pObjOld, i )
- {
- pObjNew = Abc_NtkDupObj( pNtkNew, pObjOld );
- Abc_NtkLogicStoreName( pObjNew, Abc_ObjName(pObjOld) );
- }
- Abc_NtkForEachPo( pNtkOld, pObjOld, i )
+ int i, iNodeId;
+// assert( Aig_ManRegNum(pMan) != Abc_NtkLatchNum(pNtkOld) );
+ // perform strashing
+ pNtkNew = Abc_NtkStartFromNoLatches( pNtkOld, ABC_NTK_STRASH, ABC_FUNC_AIG );
+ // consider the case of target enlargement
+ if ( Abc_NtkCiNum(pNtkNew) < Aig_ManPiNum(pMan) - Aig_ManRegNum(pMan) )
{
- pObjNew = Abc_NtkDupObj( pNtkNew, pObjOld );
- Abc_NtkLogicStoreName( pObjNew, Abc_ObjName(pObjOld) );
+ for ( i = Aig_ManPiNum(pMan) - Aig_ManRegNum(pMan) - Abc_NtkCiNum(pNtkNew); i > 0; i-- )
+ {
+ pObjNew = Abc_NtkCreatePi( pNtkNew );
+ Abc_ObjAssignName( pObjNew, Abc_ObjName(pObjNew), NULL );
+ }
+ Abc_NtkOrderCisCos( pNtkNew );
}
+ assert( Abc_NtkCiNum(pNtkNew) == Aig_ManPiNum(pMan) - Aig_ManRegNum(pMan) );
+ assert( Abc_NtkCoNum(pNtkNew) == Aig_ManPoNum(pMan) - Aig_ManRegNum(pMan) );
+ // transfer the pointers to the basic nodes
+ Aig_ManConst1(pMan)->pData = Abc_AigConst1(pNtkNew);
+ Aig_ManForEachPiSeq( pMan, pObj, i )
+ pObj->pData = Abc_NtkCi(pNtkNew, i);
+ // create as many latches as there are registers in the manager
Aig_ManForEachLiLoSeq( pMan, pObjLi, pObjLo, i )
{
pObjNew = Abc_NtkCreateLatch( pNtkNew );
- Vec_PtrPush( pNtkNew->vCis, pObjNew );
- Vec_PtrPush( pNtkNew->vCos, pObjNew );
+ pObjLi->pData = Abc_NtkCreateBi( pNtkNew );
+ pObjLo->pData = Abc_NtkCreateBo( pNtkNew );
+ Abc_ObjAddFanin( pObjNew, pObjLi->pData );
+ Abc_ObjAddFanin( pObjLo->pData, pObjNew );
Abc_LatchSetInit0( pObjNew );
}
- Abc_NtkAddDummyLatchNames( pNtkNew );
- // transfer the pointers to the basic nodes
- Aig_ManConst1(pMan)->pData = Abc_AigConst1(pNtkNew->pManFunc);
- Aig_ManForEachPi( pMan, pObj, i )
- pObj->pData = Abc_NtkCi(pNtkNew, i);
+ if ( pMan->vFlopNums == NULL )
+ Abc_NtkAddDummyBoxNames( pNtkNew );
+ else
+ {
+ assert( Abc_NtkBoxNum(pNtkOld) == Abc_NtkLatchNum(pNtkOld) );
+ Abc_NtkForEachLatch( pNtkNew, pObjNew, i )
+ {
+ pLatch = Abc_NtkBox( pNtkOld, Vec_IntEntry( pMan->vFlopNums, i ) );
+ Abc_ObjAssignName( pObjNew, Abc_ObjName(pLatch), NULL );
+ Abc_ObjAssignName( Abc_ObjFanin0(pObjNew), Abc_ObjName(Abc_ObjFanin0(pLatch)), NULL );
+ Abc_ObjAssignName( Abc_ObjFanout0(pObjNew), Abc_ObjName(Abc_ObjFanout0(pLatch)), NULL );
+ }
+ }
// rebuild the AIG
vNodes = Aig_ManDfs( pMan );
Vec_PtrForEachEntry( vNodes, pObj, i )
@@ -260,9 +261,23 @@ Abc_Ntk_t * Abc_NtkFromDarSeqSweep( Abc_Ntk_t * pNtkOld, Aig_Man_t * pMan )
// connect the PO nodes
Aig_ManForEachPo( pMan, pObj, i )
{
- pObjNew = (Abc_Obj_t *)Aig_ObjChild0Copy(pObj);
+ if ( pMan->nAsserts && i == Aig_ManPoNum(pMan) - pMan->nAsserts )
+ break;
+ iNodeId = Nm_ManFindIdByNameTwoTypes( pNtkNew->pManName, Abc_ObjName(Abc_NtkCo(pNtkNew, i)), ABC_OBJ_PI, ABC_OBJ_BO );
+ if ( iNodeId >= 0 )
+ pObjNew = Abc_NtkObj( pNtkNew, iNodeId );
+ else
+ pObjNew = (Abc_Obj_t *)Aig_ObjChild0Copy(pObj);
Abc_ObjAddFanin( Abc_NtkCo(pNtkNew, i), pObjNew );
}
+ // if there are assertions, add them
+ if ( pMan->nAsserts > 0 )
+ Aig_ManForEachAssert( pMan, pObj, i )
+ {
+ pObjNew = Abc_NtkCreateAssert(pNtkNew);
+ Abc_ObjAssignName( pObjNew, "assert_", Abc_ObjName(pObjNew) );
+ Abc_ObjAddFanin( pObjNew, (Abc_Obj_t *)Aig_ObjChild0Copy(pObj) );
+ }
if ( !Abc_NtkCheck( pNtkNew ) )
fprintf( stdout, "Abc_NtkFromDar(): Network check has failed.\n" );
return pNtkNew;
@@ -288,9 +303,9 @@ Abc_Ntk_t * Abc_NtkFromDarChoices( Abc_Ntk_t * pNtkOld, Aig_Man_t * pMan )
assert( pMan->pEquivs != NULL );
assert( Aig_ManBufNum(pMan) == 0 );
// perform strashing
- pNtkNew = Abc_NtkStartFrom( pNtkOld, ABC_TYPE_STRASH, ABC_FUNC_AIG );
+ pNtkNew = Abc_NtkStartFrom( pNtkOld, ABC_NTK_STRASH, ABC_FUNC_AIG );
// transfer the pointers to the basic nodes
- Aig_ManConst1(pMan)->pData = Abc_AigConst1(pNtkNew->pManFunc);
+ Aig_ManConst1(pMan)->pData = Abc_AigConst1(pNtkNew);
Aig_ManForEachPi( pMan, pObj, i )
pObj->pData = Abc_NtkCi(pNtkNew, i);
@@ -321,6 +336,154 @@ Abc_Ntk_t * Abc_NtkFromDarChoices( Abc_Ntk_t * pNtkOld, Aig_Man_t * pMan )
/**Function*************************************************************
+ Synopsis [Converts the network from the AIG manager into ABC.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Abc_Ntk_t * Abc_NtkFromDarSeq( Abc_Ntk_t * pNtkOld, Aig_Man_t * pMan )
+{
+ Vec_Ptr_t * vNodes;
+ Abc_Ntk_t * pNtkNew;
+ Abc_Obj_t * pObjNew, * pFaninNew, * pFaninNew0, * pFaninNew1;
+ Aig_Obj_t * pObj;
+ int i;
+// assert( Aig_ManLatchNum(pMan) > 0 );
+ // perform strashing
+ pNtkNew = Abc_NtkStartFromNoLatches( pNtkOld, ABC_NTK_STRASH, ABC_FUNC_AIG );
+ // transfer the pointers to the basic nodes
+ Aig_ManConst1(pMan)->pData = Abc_AigConst1(pNtkNew);
+ Aig_ManForEachPi( pMan, pObj, i )
+ pObj->pData = Abc_NtkPi(pNtkNew, i);
+ // create latches of the new network
+ Aig_ManForEachObj( pMan, pObj, i )
+ {
+ if ( !Aig_ObjIsLatch(pObj) )
+ continue;
+ pObjNew = Abc_NtkCreateLatch( pNtkNew );
+ pFaninNew0 = Abc_NtkCreateBi( pNtkNew );
+ pFaninNew1 = Abc_NtkCreateBo( pNtkNew );
+ Abc_ObjAddFanin( pObjNew, pFaninNew0 );
+ Abc_ObjAddFanin( pFaninNew1, pObjNew );
+ Abc_LatchSetInit0( pObjNew );
+ pObj->pData = Abc_ObjFanout0( pObjNew );
+ }
+ Abc_NtkAddDummyBoxNames( pNtkNew );
+ // rebuild the AIG
+ vNodes = Aig_ManDfs( pMan );
+ Vec_PtrForEachEntry( vNodes, pObj, i )
+ {
+ // add the first fanin
+ pObj->pData = pFaninNew0 = (Abc_Obj_t *)Aig_ObjChild0Copy(pObj);
+ if ( Aig_ObjIsBuf(pObj) )
+ continue;
+ // add the second fanin
+ pFaninNew1 = (Abc_Obj_t *)Aig_ObjChild1Copy(pObj);
+ // create the new node
+ if ( Aig_ObjIsExor(pObj) )
+ pObj->pData = pObjNew = Abc_AigXor( pNtkNew->pManFunc, pFaninNew0, pFaninNew1 );
+ else
+ pObj->pData = pObjNew = Abc_AigAnd( pNtkNew->pManFunc, pFaninNew0, pFaninNew1 );
+ }
+ Vec_PtrFree( vNodes );
+ // connect the PO nodes
+ Aig_ManForEachPo( pMan, pObj, i )
+ {
+ pFaninNew = (Abc_Obj_t *)Aig_ObjChild0Copy( pObj );
+ Abc_ObjAddFanin( Abc_NtkPo(pNtkNew, i), pFaninNew );
+ }
+ // connect the latches
+ Aig_ManForEachObj( pMan, pObj, i )
+ {
+ if ( !Aig_ObjIsLatch(pObj) )
+ continue;
+ pFaninNew = (Abc_Obj_t *)Aig_ObjChild0Copy( pObj );
+ Abc_ObjAddFanin( Abc_ObjFanin0(Abc_ObjFanin0(pObj->pData)), pFaninNew );
+ }
+ if ( !Abc_NtkCheck( pNtkNew ) )
+ fprintf( stdout, "Abc_NtkFromIvySeq(): Network check has failed.\n" );
+ return pNtkNew;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Collect latch values.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Vec_Int_t * Abc_NtkGetLatchValues( Abc_Ntk_t * pNtk )
+{
+ Vec_Int_t * vInits;
+ Abc_Obj_t * pLatch;
+ int i;
+ vInits = Vec_IntAlloc( Abc_NtkLatchNum(pNtk) );
+ Abc_NtkForEachLatch( pNtk, pLatch, i )
+ {
+ assert( Abc_LatchIsInit1(pLatch) == 0 );
+ Vec_IntPush( vInits, Abc_LatchIsInit1(pLatch) );
+ }
+ return vInits;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Performs verification after retiming.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Abc_NtkSecRetime( Abc_Ntk_t * pNtk1, Abc_Ntk_t * pNtk2 )
+{
+ int fRemove1, fRemove2;
+ Aig_Man_t * pMan1, * pMan2;
+ int * pArray;
+
+ fRemove1 = (!Abc_NtkIsStrash(pNtk1)) && (pNtk1 = Abc_NtkStrash(pNtk1, 0, 0, 0));
+ fRemove2 = (!Abc_NtkIsStrash(pNtk2)) && (pNtk2 = Abc_NtkStrash(pNtk2, 0, 0, 0));
+
+
+ pMan1 = Abc_NtkToDar( pNtk1, 0 );
+ pMan2 = Abc_NtkToDar( pNtk2, 0 );
+
+ Aig_ManPrintStats( pMan1 );
+ Aig_ManPrintStats( pMan2 );
+
+// pArray = Abc_NtkGetLatchValues(pNtk1);
+ pArray = NULL;
+ Aig_ManSeqStrash( pMan1, Abc_NtkLatchNum(pNtk1), pArray );
+ free( pArray );
+
+// pArray = Abc_NtkGetLatchValues(pNtk2);
+ pArray = NULL;
+ Aig_ManSeqStrash( pMan2, Abc_NtkLatchNum(pNtk2), pArray );
+ free( pArray );
+
+ Aig_ManPrintStats( pMan1 );
+ Aig_ManPrintStats( pMan2 );
+
+ Aig_ManStop( pMan1 );
+ Aig_ManStop( pMan2 );
+
+
+ if ( fRemove1 ) Abc_NtkDelete( pNtk1 );
+ if ( fRemove2 ) Abc_NtkDelete( pNtk2 );
+}
+
+/**Function*************************************************************
+
Synopsis [Gives the current ABC network to AIG manager for processing.]
Description []
@@ -357,6 +520,7 @@ Abc_Ntk_t * Abc_NtkDar( Abc_Ntk_t * pNtk )
return pNtkAig;
}
+
/**Function*************************************************************
Synopsis [Gives the current ABC network to AIG manager for processing.]
@@ -368,59 +532,483 @@ Abc_Ntk_t * Abc_NtkDar( Abc_Ntk_t * pNtk )
SeeAlso []
***********************************************************************/
-Abc_Ntk_t * Abc_NtkDarLatchSweep( Abc_Ntk_t * pNtk, int fLatchSweep, int fVerbose )
+Abc_Ntk_t * Abc_NtkDarFraig( Abc_Ntk_t * pNtk, int nConfLimit, int fDoSparse, int fProve, int fTransfer, int fSpeculate, int fChoicing, int fVerbose )
{
+ Fra_Par_t Pars, * pPars = &Pars;
Abc_Ntk_t * pNtkAig;
- Aig_Man_t * pMan;
- pMan = Abc_NtkToDar( pNtk, 1 );
+ Aig_Man_t * pMan, * pTemp;
+ pMan = Abc_NtkToDar( pNtk, 0 );
if ( pMan == NULL )
return NULL;
- Aig_ManSeqCleanup( pMan );
- if ( fLatchSweep )
+ Fra_ParamsDefault( pPars );
+ pPars->nBTLimitNode = nConfLimit;
+ pPars->fChoicing = fChoicing;
+ pPars->fDoSparse = fDoSparse;
+ pPars->fSpeculate = fSpeculate;
+ pPars->fProve = fProve;
+ pPars->fVerbose = fVerbose;
+ pMan = Fra_FraigPerform( pTemp = pMan, pPars );
+ if ( fChoicing )
+ pNtkAig = Abc_NtkFromDarChoices( pNtk, pMan );
+ else
+ pNtkAig = Abc_NtkFromDar( pNtk, pMan );
+ Aig_ManStop( pTemp );
+ Aig_ManStop( pMan );
+ return pNtkAig;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Gives the current ABC network to AIG manager for processing.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Abc_Ntk_t * Abc_NtkCSweep( Abc_Ntk_t * pNtk, int nCutsMax, int nLeafMax, int fVerbose )
+{
+ extern Aig_Man_t * Csw_Sweep( Aig_Man_t * pAig, int nCutsMax, int nLeafMax, int fVerbose );
+ Abc_Ntk_t * pNtkAig;
+ Aig_Man_t * pMan, * pTemp;
+ pMan = Abc_NtkToDar( pNtk, 0 );
+ if ( pMan == NULL )
+ return NULL;
+ pMan = Csw_Sweep( pTemp = pMan, nCutsMax, nLeafMax, fVerbose );
+ pNtkAig = Abc_NtkFromDar( pNtk, pMan );
+ Aig_ManStop( pTemp );
+ Aig_ManStop( pMan );
+ return pNtkAig;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Gives the current ABC network to AIG manager for processing.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Abc_Ntk_t * Abc_NtkDRewrite( Abc_Ntk_t * pNtk, Dar_RwrPar_t * pPars )
+{
+ Aig_Man_t * pMan, * pTemp;
+ Abc_Ntk_t * pNtkAig;
+ int clk;
+ assert( Abc_NtkIsStrash(pNtk) );
+ pMan = Abc_NtkToDar( pNtk, 0 );
+ if ( pMan == NULL )
+ return NULL;
+// Aig_ManPrintStats( pMan );
+/*
+// Aig_ManSupports( pMan );
{
- if ( pMan->nRegs )
- pMan = Aig_ManReduceLaches( pMan, fVerbose );
- if ( pMan->nRegs )
- pMan = Aig_ManConstReduce( pMan, fVerbose );
+ Vec_Vec_t * vParts;
+ vParts = Aig_ManPartitionSmart( pMan, 50, 1, NULL );
+ Vec_VecFree( vParts );
}
- pNtkAig = Abc_NtkFromDarSeqSweep( pNtk, pMan );
+*/
+ Dar_ManRewrite( pMan, pPars );
+// pMan = Dar_ManBalance( pTemp = pMan, pPars->fUpdateLevel );
+// Aig_ManStop( pTemp );
+
+clk = clock();
+ pMan = Aig_ManDup( pTemp = pMan, 0 );
+ Aig_ManStop( pTemp );
+//PRT( "time", clock() - clk );
+
+// Aig_ManPrintStats( pMan );
+ pNtkAig = Abc_NtkFromDar( pNtk, pMan );
Aig_ManStop( pMan );
return pNtkAig;
}
/**Function*************************************************************
- Synopsis [Computes latch correspondence.]
+ Synopsis [Gives the current ABC network to AIG manager for processing.]
Description []
SideEffects []
SeeAlso []
-
+
***********************************************************************/
-Abc_Ntk_t * Abc_NtkDarLcorr( Abc_Ntk_t * pNtk, int nFramesP, int nConfMax, int fVerbose )
+Abc_Ntk_t * Abc_NtkDRefactor( Abc_Ntk_t * pNtk, Dar_RefPar_t * pPars )
{
- extern Aig_Man_t * Fra_FraigLatchCorrespondence( Aig_Man_t * pAig, int nFramesP, int nConfMax, int fProve, int fVerbose, int * pnIter );
Aig_Man_t * pMan, * pTemp;
Abc_Ntk_t * pNtkAig;
- pMan = Abc_NtkToDar( pNtk, 1 );
+ int clk;
+ assert( Abc_NtkIsStrash(pNtk) );
+ pMan = Abc_NtkToDar( pNtk, 0 );
if ( pMan == NULL )
return NULL;
- pMan = Fra_FraigLatchCorrespondence( pTemp = pMan, nFramesP, nConfMax, 0, fVerbose, NULL );
+// Aig_ManPrintStats( pMan );
+
+ Dar_ManRefactor( pMan, pPars );
+// pMan = Dar_ManBalance( pTemp = pMan, pPars->fUpdateLevel );
+// Aig_ManStop( pTemp );
+
+clk = clock();
+ pMan = Aig_ManDup( pTemp = pMan, 0 );
Aig_ManStop( pTemp );
- if ( Aig_ManRegNum(pMan) < Abc_NtkLatchNum(pNtk) )
- pNtkAig = Abc_NtkFromDarSeqSweep( pNtk, pMan );
+//PRT( "time", clock() - clk );
+
+// Aig_ManPrintStats( pMan );
+ pNtkAig = Abc_NtkFromDar( pNtk, pMan );
+ Aig_ManStop( pMan );
+ return pNtkAig;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Gives the current ABC network to AIG manager for processing.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Abc_Ntk_t * Abc_NtkDCompress2( Abc_Ntk_t * pNtk, int fBalance, int fUpdateLevel, int fVerbose )
+{
+ Aig_Man_t * pMan, * pTemp;
+ Abc_Ntk_t * pNtkAig;
+ int clk;
+ assert( Abc_NtkIsStrash(pNtk) );
+ pMan = Abc_NtkToDar( pNtk, 0 );
+ if ( pMan == NULL )
+ return NULL;
+// Aig_ManPrintStats( pMan );
+
+clk = clock();
+ pMan = Dar_ManCompress2( pTemp = pMan, fBalance, fUpdateLevel, fVerbose );
+ Aig_ManStop( pTemp );
+//PRT( "time", clock() - clk );
+
+// Aig_ManPrintStats( pMan );
+ pNtkAig = Abc_NtkFromDar( pNtk, pMan );
+ Aig_ManStop( pMan );
+ return pNtkAig;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Gives the current ABC network to AIG manager for processing.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Abc_Ntk_t * Abc_NtkDChoice( Abc_Ntk_t * pNtk, int fBalance, int fUpdateLevel, int fVerbose )
+{
+ Aig_Man_t * pMan, * pTemp;
+ Abc_Ntk_t * pNtkAig;
+ assert( Abc_NtkIsStrash(pNtk) );
+ pMan = Abc_NtkToDar( pNtk, 0 );
+ if ( pMan == NULL )
+ return NULL;
+ pMan = Dar_ManChoice( pTemp = pMan, fBalance, fUpdateLevel, fVerbose );
+ Aig_ManStop( pTemp );
+ pNtkAig = Abc_NtkFromDarChoices( pNtk, pMan );
+ Aig_ManStop( pMan );
+ return pNtkAig;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Gives the current ABC network to AIG manager for processing.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Abc_Ntk_t * Abc_NtkDrwsat( Abc_Ntk_t * pNtk, int fBalance, int fVerbose )
+{
+ Aig_Man_t * pMan, * pTemp;
+ Abc_Ntk_t * pNtkAig;
+ int clk;
+ assert( Abc_NtkIsStrash(pNtk) );
+ pMan = Abc_NtkToDar( pNtk, 0 );
+ if ( pMan == NULL )
+ return NULL;
+// Aig_ManPrintStats( pMan );
+
+clk = clock();
+ pMan = Dar_ManRwsat( pTemp = pMan, fBalance, fVerbose );
+ Aig_ManStop( pTemp );
+//PRT( "time", clock() - clk );
+
+// Aig_ManPrintStats( pMan );
+ pNtkAig = Abc_NtkFromDar( pNtk, pMan );
+ Aig_ManStop( pMan );
+ return pNtkAig;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Gives the current ABC network to AIG manager for processing.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Abc_Ntk_t * Abc_NtkConstructFromCnf( Abc_Ntk_t * pNtk, Cnf_Man_t * p, Vec_Ptr_t * vMapped )
+{
+ Abc_Ntk_t * pNtkNew;
+ Abc_Obj_t * pNode, * pNodeNew;
+ Aig_Obj_t * pObj, * pLeaf;
+ Cnf_Cut_t * pCut;
+ Vec_Int_t * vCover;
+ unsigned uTruth;
+ int i, k, nDupGates;
+ // create the new network
+ pNtkNew = Abc_NtkStartFrom( pNtk, ABC_NTK_LOGIC, ABC_FUNC_SOP );
+ // make the mapper point to the new network
+ Aig_ManConst1(p->pManAig)->pData = Abc_NtkCreateNodeConst1(pNtkNew);
+ Abc_NtkForEachCi( pNtk, pNode, i )
+ Aig_ManPi(p->pManAig, i)->pData = pNode->pCopy;
+ // process the nodes in topological order
+ vCover = Vec_IntAlloc( 1 << 16 );
+ Vec_PtrForEachEntry( vMapped, pObj, i )
+ {
+ // create new node
+ pNodeNew = Abc_NtkCreateNode( pNtkNew );
+ // add fanins according to the cut
+ pCut = pObj->pData;
+ Cnf_CutForEachLeaf( p->pManAig, pCut, pLeaf, k )
+ Abc_ObjAddFanin( pNodeNew, pLeaf->pData );
+ // add logic function
+ if ( pCut->nFanins < 5 )
+ {
+ uTruth = 0xFFFF & *Cnf_CutTruth(pCut);
+ Cnf_SopConvertToVector( p->pSops[uTruth], p->pSopSizes[uTruth], vCover );
+ pNodeNew->pData = Abc_SopCreateFromIsop( pNtkNew->pManFunc, pCut->nFanins, vCover );
+ }
+ else
+ pNodeNew->pData = Abc_SopCreateFromIsop( pNtkNew->pManFunc, pCut->nFanins, pCut->vIsop[1] );
+ // save the node
+ pObj->pData = pNodeNew;
+ }
+ Vec_IntFree( vCover );
+ // add the CO drivers
+ Abc_NtkForEachCo( pNtk, pNode, i )
+ {
+ pObj = Aig_ManPo(p->pManAig, i);
+ pNodeNew = Abc_ObjNotCond( Aig_ObjFanin0(pObj)->pData, Aig_ObjFaninC0(pObj) );
+ Abc_ObjAddFanin( pNode->pCopy, pNodeNew );
+ }
+
+ // remove the constant node if not used
+ pNodeNew = (Abc_Obj_t *)Aig_ManConst1(p->pManAig)->pData;
+ if ( Abc_ObjFanoutNum(pNodeNew) == 0 )
+ Abc_NtkDeleteObj( pNodeNew );
+ // minimize the node
+// Abc_NtkSweep( pNtkNew, 0 );
+ // decouple the PO driver nodes to reduce the number of levels
+ nDupGates = Abc_NtkLogicMakeSimpleCos( pNtkNew, 1 );
+// if ( nDupGates && If_ManReadVerbose(pIfMan) )
+// printf( "Duplicated %d gates to decouple the CO drivers.\n", nDupGates );
+ if ( !Abc_NtkCheck( pNtkNew ) )
+ fprintf( stdout, "Abc_NtkConstructFromCnf(): Network check has failed.\n" );
+ return pNtkNew;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Gives the current ABC network to AIG manager for processing.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Abc_Ntk_t * Abc_NtkDarToCnf( Abc_Ntk_t * pNtk, char * pFileName )
+{
+ Vec_Ptr_t * vMapped;
+ Aig_Man_t * pMan;
+ Cnf_Man_t * pManCnf;
+ Cnf_Dat_t * pCnf;
+ Abc_Ntk_t * pNtkNew = NULL;
+ assert( Abc_NtkIsStrash(pNtk) );
+
+ // convert to the AIG manager
+ pMan = Abc_NtkToDar( pNtk, 0 );
+ if ( pMan == NULL )
+ return NULL;
+ if ( !Aig_ManCheck( pMan ) )
+ {
+ printf( "Abc_NtkDarToCnf: AIG check has failed.\n" );
+ Aig_ManStop( pMan );
+ return NULL;
+ }
+ // perform balance
+ Aig_ManPrintStats( pMan );
+
+ // derive CNF
+ pCnf = Cnf_Derive( pMan, 0 );
+ pManCnf = Cnf_ManRead();
+
+ // write the network for verification
+ vMapped = Cnf_ManScanMapping( pManCnf, 1, 0 );
+ pNtkNew = Abc_NtkConstructFromCnf( pNtk, pManCnf, vMapped );
+ Vec_PtrFree( vMapped );
+
+ // write CNF into a file
+ Cnf_DataWriteIntoFile( pCnf, pFileName, 0 );
+ Cnf_DataFree( pCnf );
+ Cnf_ClearMemory();
+
+ Aig_ManStop( pMan );
+ return pNtkNew;
+}
+
+
+/**Function*************************************************************
+
+ Synopsis [Solves combinational miter using a SAT solver.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Abc_NtkDSat( Abc_Ntk_t * pNtk, sint64 nConfLimit, sint64 nInsLimit, int fVerbose )
+{
+ Aig_Man_t * pMan;
+ int RetValue;//, clk = clock();
+ assert( Abc_NtkIsStrash(pNtk) );
+ assert( Abc_NtkLatchNum(pNtk) == 0 );
+ assert( Abc_NtkPoNum(pNtk) == 1 );
+ pMan = Abc_NtkToDar( pNtk, 0 );
+ RetValue = Fra_FraigSat( pMan, nConfLimit, nInsLimit, fVerbose );
+ pNtk->pModel = pMan->pData, pMan->pData = NULL;
+ Aig_ManStop( pMan );
+ return RetValue;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Gives the current ABC network to AIG manager for processing.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Abc_NtkDarCec( Abc_Ntk_t * pNtk1, Abc_Ntk_t * pNtk2, int fPartition, int fVerbose )
+{
+ Aig_Man_t * pMan, * pMan1, * pMan2;
+ Abc_Ntk_t * pMiter;
+ int RetValue, clkTotal = clock();
+
+ // cannot partition if it is already a miter
+ if ( pNtk2 == NULL && fPartition == 1 )
+ {
+ printf( "Abc_NtkDarCec(): Switching to non-partitioned CEC for the miter.\n" );
+ fPartition = 0;
+ }
+
+ // if partitioning is selected, call partitioned CEC
+ if ( fPartition )
+ {
+ pMan1 = Abc_NtkToDar( pNtk1, 0 );
+ pMan2 = Abc_NtkToDar( pNtk2, 0 );
+ RetValue = Fra_FraigCecPartitioned( pMan1, pMan2, fVerbose );
+ Aig_ManStop( pMan1 );
+ Aig_ManStop( pMan2 );
+ goto finish;
+ }
+
+ if ( pNtk2 != NULL )
+ {
+ // get the miter of the two networks
+ pMiter = Abc_NtkMiter( pNtk1, pNtk2, 0, 0 );
+ if ( pMiter == NULL )
+ {
+ printf( "Miter computation has failed.\n" );
+ return 0;
+ }
+ }
else
{
- Abc_Obj_t * pObj;
- int i;
- pNtkAig = Abc_NtkFromDar( pNtk, pMan );
- Abc_NtkForEachLatch( pNtkAig, pObj, i )
- Abc_LatchSetInit0( pObj );
+ pMiter = Abc_NtkDup( pNtk1 );
+ }
+ RetValue = Abc_NtkMiterIsConstant( pMiter );
+ if ( RetValue == 0 )
+ {
+// extern void Abc_NtkVerifyReportErrorSeq( Abc_Ntk_t * pNtk1, Abc_Ntk_t * pNtk2, int * pModel, int nFrames );
+ printf( "Networks are NOT EQUIVALENT after structural hashing.\n" );
+ // report the error
+ if ( pNtk2 == NULL )
+ pNtk1->pModel = Abc_NtkVerifyGetCleanModel( pNtk1, 1 );
+// pMiter->pModel = Abc_NtkVerifyGetCleanModel( pMiter, nFrames );
+// Abc_NtkVerifyReportErrorSeq( pNtk1, pNtk2, pMiter->pModel, nFrames );
+// FREE( pMiter->pModel );
+ Abc_NtkDelete( pMiter );
+ return 0;
}
+ if ( RetValue == 1 )
+ {
+ Abc_NtkDelete( pMiter );
+ printf( "Networks are equivalent after structural hashing.\n" );
+ return 1;
+ }
+
+ // derive the AIG manager
+ pMan = Abc_NtkToDar( pMiter, 0 );
+ Abc_NtkDelete( pMiter );
+ if ( pMan == NULL )
+ {
+ printf( "Converting miter into AIG has failed.\n" );
+ return -1;
+ }
+ // perform verification
+ RetValue = Fra_FraigCec( &pMan, fVerbose );
+ // transfer model if given
+ if ( pNtk2 == NULL )
+ pNtk1->pModel = pMan->pData, pMan->pData = NULL;
Aig_ManStop( pMan );
- return pNtkAig;
+
+finish:
+ // report the miter
+ if ( RetValue == 1 )
+ {
+ printf( "Networks are equivalent. " );
+PRT( "Time", clock() - clkTotal );
+ }
+ else if ( RetValue == 0 )
+ {
+ printf( "Networks are NOT EQUIVALENT. " );
+PRT( "Time", clock() - clkTotal );
+ }
+ else
+ {
+ printf( "Networks are UNDECIDED. " );
+PRT( "Time", clock() - clkTotal );
+ }
+ fflush( stdout );
+ return RetValue;
}
/**Function*************************************************************
@@ -436,8 +1024,7 @@ Abc_Ntk_t * Abc_NtkDarLcorr( Abc_Ntk_t * pNtk, int nFramesP, int nConfMax, int f
***********************************************************************/
Abc_Ntk_t * Abc_NtkDarSeqSweep( Abc_Ntk_t * pNtk, int nFramesP, int nFramesK, int nMaxImps, int nMaxLevs, int fRewrite, int fUseImps, int fLatchCorr, int fWriteImps, int fVerbose )
{
- extern Aig_Man_t * Fra_FraigInduction( Aig_Man_t * pManAig, int nFramesP, int nFramesK, int nMaxImps, int nMaxLevs, int fRewrite, int fUseImps, int fLatchCorr, int fWriteImps, int fVerbose, int * pnIter );
-// Fraig_Params_t Params;
+ Fraig_Params_t Params;
Abc_Ntk_t * pNtkAig, * pNtkFraig;
Aig_Man_t * pMan, * pTemp;
int clk = clock();
@@ -445,8 +1032,8 @@ Abc_Ntk_t * Abc_NtkDarSeqSweep( Abc_Ntk_t * pNtk, int nFramesP, int nFramesK, in
// preprocess the miter by fraiging it
// (note that for each functional class, fraiging leaves one representative;
// so fraiging does not reduce the number of functions represented by nodes
-// Fraig_ParamsSetDefault( &Params );
-// Params.nBTLimit = 100000;
+ Fraig_ParamsSetDefault( &Params );
+ Params.nBTLimit = 100000;
// pNtkFraig = Abc_NtkFraig( pNtk, &Params, 0, 0 );
pNtkFraig = Abc_NtkDup( pNtk );
if ( fVerbose )
@@ -478,6 +1065,113 @@ PRT( "Initial fraiging time", clock() - clk );
/**Function*************************************************************
+ Synopsis [Computes latch correspondence.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Abc_Ntk_t * Abc_NtkDarLcorr( Abc_Ntk_t * pNtk, int nFramesP, int nConfMax, int fVerbose )
+{
+ Aig_Man_t * pMan, * pTemp;
+ Abc_Ntk_t * pNtkAig;
+ pMan = Abc_NtkToDar( pNtk, 1 );
+ if ( pMan == NULL )
+ return NULL;
+ pMan = Fra_FraigLatchCorrespondence( pTemp = pMan, nFramesP, nConfMax, 0, fVerbose, NULL );
+ Aig_ManStop( pTemp );
+ if ( Aig_ManRegNum(pMan) < Abc_NtkLatchNum(pNtk) )
+ pNtkAig = Abc_NtkFromDarSeqSweep( pNtk, pMan );
+ else
+ {
+ Abc_Obj_t * pObj;
+ int i;
+ pNtkAig = Abc_NtkFromDar( pNtk, pMan );
+ Abc_NtkForEachLatch( pNtkAig, pObj, i )
+ Abc_LatchSetInit0( pObj );
+ }
+ Aig_ManStop( pMan );
+ return pNtkAig;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Gives the current ABC network to AIG manager for processing.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Abc_NtkDarBmc( Abc_Ntk_t * pNtk, int nFrames, int nBTLimit, int fRewrite, int fVerbose )
+{
+ Aig_Man_t * pMan;
+ int clk = clock();
+ // derive the AIG manager
+ pMan = Abc_NtkToDar( pNtk, 1 );
+ if ( pMan == NULL )
+ {
+ printf( "Converting miter into AIG has failed.\n" );
+ return -1;
+ }
+ assert( pMan->nRegs > 0 );
+ // perform verification
+ Fra_BmcPerformSimple( pMan, nFrames, nBTLimit, fRewrite, fVerbose );
+ pNtk->pSeqModel = pMan->pSeqModel; pMan->pSeqModel = NULL;
+ if ( pNtk->pSeqModel )
+ {
+ Fra_Cex_t * pCex = pNtk->pSeqModel;
+ printf( "Output %d was asserted in frame %d (use \"write_counter\" to dump the trace). ", pCex->iPo, pCex->iFrame );
+ }
+ else
+ printf( "No output was asserted after BMC with %d frames. ", nFrames );
+PRT( "Time", clock() - clk );
+ Aig_ManStop( pMan );
+ return 1;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Gives the current ABC network to AIG manager for processing.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Abc_NtkDarProve( Abc_Ntk_t * pNtk, int nFrames, int fRetimeFirst, int fVerbose, int fVeryVerbose )
+{
+ Aig_Man_t * pMan;
+ int RetValue;
+ // derive the AIG manager
+ pMan = Abc_NtkToDar( pNtk, 1 );
+ if ( pMan == NULL )
+ {
+ printf( "Converting miter into AIG has failed.\n" );
+ return -1;
+ }
+ assert( pMan->nRegs > 0 );
+ // perform verification
+ RetValue = Fra_FraigSec( pMan, nFrames, fRetimeFirst, fVerbose, fVeryVerbose );
+ pNtk->pSeqModel = pMan->pSeqModel; pMan->pSeqModel = NULL;
+ if ( pNtk->pSeqModel )
+ {
+ Fra_Cex_t * pCex = pNtk->pSeqModel;
+ printf( "Output %d was asserted in frame %d (use \"write_counter\" to dump the trace).\n", pCex->iPo, pCex->iFrame );
+ }
+ Aig_ManStop( pMan );
+ return RetValue;
+}
+
+/**Function*************************************************************
+
Synopsis [Gives the current ABC network to AIG manager for processing.]
Description []
@@ -489,14 +1183,13 @@ PRT( "Initial fraiging time", clock() - clk );
***********************************************************************/
int Abc_NtkDarSec( Abc_Ntk_t * pNtk1, Abc_Ntk_t * pNtk2, int nFrames, int fRetimeFirst, int fVerbose, int fVeryVerbose )
{
- extern int Fra_FraigSec( Aig_Man_t * p, int nFramesMax, int fRetimeFirst, int fVerbose, int fVeryVerbose );
// Fraig_Params_t Params;
Aig_Man_t * pMan;
Abc_Ntk_t * pMiter;//, * pTemp;
int RetValue;
// get the miter of the two networks
- pMiter = Abc_NtkMiter( pNtk1, pNtk2, 0 );
+ pMiter = Abc_NtkMiter( pNtk1, pNtk2, 0, 0 );
if ( pMiter == NULL )
{
printf( "Miter computation has failed.\n" );
@@ -507,12 +1200,10 @@ int Abc_NtkDarSec( Abc_Ntk_t * pNtk1, Abc_Ntk_t * pNtk2, int nFrames, int fRetim
{
extern void Abc_NtkVerifyReportErrorSeq( Abc_Ntk_t * pNtk1, Abc_Ntk_t * pNtk2, int * pModel, int nFrames );
printf( "Networks are NOT EQUIVALENT after structural hashing.\n" );
-/*
// report the error
pMiter->pModel = Abc_NtkVerifyGetCleanModel( pMiter, nFrames );
Abc_NtkVerifyReportErrorSeq( pNtk1, pNtk2, pMiter->pModel, nFrames );
FREE( pMiter->pModel );
-*/
Abc_NtkDelete( pMiter );
return 0;
}
@@ -567,7 +1258,314 @@ int Abc_NtkDarSec( Abc_Ntk_t * pNtk1, Abc_Ntk_t * pNtk2, int nFrames, int fRetim
return RetValue;
}
+/**Function*************************************************************
+
+ Synopsis [Gives the current ABC network to AIG manager for processing.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+***********************************************************************/
+Abc_Ntk_t * Abc_NtkDarLatchSweep( Abc_Ntk_t * pNtk, int fLatchSweep, int fVerbose )
+{
+ Abc_Ntk_t * pNtkAig;
+ Aig_Man_t * pMan;
+ pMan = Abc_NtkToDar( pNtk, 1 );
+ if ( pMan == NULL )
+ return NULL;
+ Aig_ManSeqCleanup( pMan );
+ if ( fLatchSweep )
+ {
+ if ( pMan->nRegs )
+ pMan = Aig_ManReduceLaches( pMan, fVerbose );
+ if ( pMan->nRegs )
+ pMan = Aig_ManConstReduce( pMan, fVerbose );
+ }
+ pNtkAig = Abc_NtkFromDarSeqSweep( pNtk, pMan );
+ Aig_ManStop( pMan );
+ return pNtkAig;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Gives the current ABC network to AIG manager for processing.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Abc_Ntk_t * Abc_NtkDarRetime( Abc_Ntk_t * pNtk, int nStepsMax, int fVerbose )
+{
+ Abc_Ntk_t * pNtkAig;
+ Aig_Man_t * pMan, * pTemp;
+ pMan = Abc_NtkToDar( pNtk, 1 );
+ if ( pMan == NULL )
+ return NULL;
+// Aig_ManReduceLachesCount( pMan );
+ if ( pMan->vFlopNums )
+ Vec_IntFree( pMan->vFlopNums );
+ pMan->vFlopNums = NULL;
+
+ pMan = Rtm_ManRetime( pTemp = pMan, 1, nStepsMax, 0 );
+ Aig_ManStop( pTemp );
+
+// pMan = Aig_ManReduceLaches( pMan, 1 );
+// pMan = Aig_ManConstReduce( pMan, 1 );
+
+ pNtkAig = Abc_NtkFromDarSeqSweep( pNtk, pMan );
+ Aig_ManStop( pMan );
+ return pNtkAig;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Gives the current ABC network to AIG manager for processing.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Abc_Ntk_t * Abc_NtkDarRetimeF( Abc_Ntk_t * pNtk, int nStepsMax, int fVerbose )
+{
+ Abc_Ntk_t * pNtkAig;
+ Aig_Man_t * pMan, * pTemp;
+ pMan = Abc_NtkToDar( pNtk, 1 );
+ if ( pMan == NULL )
+ return NULL;
+// Aig_ManReduceLachesCount( pMan );
+ if ( pMan->vFlopNums )
+ Vec_IntFree( pMan->vFlopNums );
+ pMan->vFlopNums = NULL;
+
+ pMan = Aig_ManRetimeFrontier( pTemp = pMan, nStepsMax );
+ Aig_ManStop( pTemp );
+
+// pMan = Aig_ManReduceLaches( pMan, 1 );
+// pMan = Aig_ManConstReduce( pMan, 1 );
+
+ pNtkAig = Abc_NtkFromDarSeqSweep( pNtk, pMan );
+ Aig_ManStop( pMan );
+ return pNtkAig;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Gives the current ABC network to AIG manager for processing.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Abc_NtkDarHaigRecord( Abc_Ntk_t * pNtk )
+{
+ Aig_Man_t * pMan;
+ pMan = Abc_NtkToDar( pNtk, 1 );
+ if ( pMan == NULL )
+ return;
+// Aig_ManReduceLachesCount( pMan );
+ if ( pMan->vFlopNums )
+ Vec_IntFree( pMan->vFlopNums );
+ pMan->vFlopNums = NULL;
+ Aig_ManHaigRecord( pMan );
+ Aig_ManStop( pMan );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Performs random simulation.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Abc_NtkDarSeqSim( Abc_Ntk_t * pNtk, int nFrames, int nWords, int fVerbose )
+{
+ Aig_Man_t * pMan;
+ Fra_Sml_t * pSml;
+ Fra_Cex_t * pCex;
+ int RetValue, clk = clock();
+ pMan = Abc_NtkToDar( pNtk, 1 );
+ pSml = Fra_SmlSimulateSeq( pMan, 0, nFrames, nWords );
+ if ( pSml->fNonConstOut )
+ {
+ pCex = Fra_SmlGetCounterExample( pSml );
+ if ( pCex )
+ printf( "Simulation of %d frames with %d words asserted output %d in frame %d. ",
+ nFrames, nWords, pCex->iPo, pCex->iFrame );
+ pNtk->pSeqModel = pCex;
+ RetValue = 1;
+ }
+ else
+ {
+ RetValue = 0;
+ printf( "Simulation of %d frames with %d words did not assert the outputs. ",
+ nFrames, nWords );
+ }
+ PRT( "Time", clock() - clk );
+ Fra_SmlStop( pSml );
+ Aig_ManStop( pMan );
+ return RetValue;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Gives the current ABC network to AIG manager for processing.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Abc_NtkDarClau( Abc_Ntk_t * pNtk, int nFrames, int nPref, int nClauses, int nLutSize, int nLevels, int nCutsMax, int nBatches, int fStepUp, int fBmc, int fRefs, int fTarget, int fVerbose, int fVeryVerbose )
+{
+ extern int Fra_Clau( Aig_Man_t * pMan, int nIters, int fVerbose, int fVeryVerbose );
+ extern int Fra_Claus( Aig_Man_t * pAig, int nFrames, int nPref, int nClauses, int nLutSize, int nLevels, int nCutsMax, int nBatches, int fStepUp, int fBmc, int fRefs, int fTarget, int fVerbose, int fVeryVerbose );
+ Aig_Man_t * pMan;
+ if ( fTarget && Abc_NtkPoNum(pNtk) != 1 )
+ {
+ printf( "The number of outputs should be 1.\n" );
+ return 1;
+ }
+ pMan = Abc_NtkToDar( pNtk, 1 );
+ if ( pMan == NULL )
+ return 1;
+// Aig_ManReduceLachesCount( pMan );
+ if ( pMan->vFlopNums )
+ Vec_IntFree( pMan->vFlopNums );
+ pMan->vFlopNums = NULL;
+
+// Fra_Clau( pMan, nStepsMax, fVerbose, fVeryVerbose );
+ Fra_Claus( pMan, nFrames, nPref, nClauses, nLutSize, nLevels, nCutsMax, nBatches, fStepUp, fBmc, fRefs, fTarget, fVerbose, fVeryVerbose );
+ Aig_ManStop( pMan );
+ return 1;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Performs targe enlargement.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Abc_Ntk_t * Abc_NtkDarEnlarge( Abc_Ntk_t * pNtk, int nFrames, int fVerbose )
+{
+ Abc_Ntk_t * pNtkAig;
+ Aig_Man_t * pMan, * pTemp;
+ pMan = Abc_NtkToDar( pNtk, 1 );
+ if ( pMan == NULL )
+ return NULL;
+ pMan = Aig_ManFrames( pTemp = pMan, nFrames, 0, 1, 1, 1, NULL );
+ Aig_ManStop( pTemp );
+ pNtkAig = Abc_NtkFromDarSeqSweep( pNtk, pMan );
+ Aig_ManStop( pMan );
+ return pNtkAig;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Interplates two networks.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Abc_Ntk_t * Abc_NtkInter( Abc_Ntk_t * pNtkOn, Abc_Ntk_t * pNtkOff, int fVerbose )
+{
+ extern Aig_Man_t * Aig_ManInter( Aig_Man_t * pManOn, Aig_Man_t * pManOff, int fVerbose );
+ Abc_Ntk_t * pNtkAig;
+ Aig_Man_t * pManOn, * pManOff, * pManAig;
+ if ( Abc_NtkCoNum(pNtkOn) != 1 || Abc_NtkCoNum(pNtkOff) != 1 )
+ {
+ printf( "Currently works only for single output networks.\n" );
+ return NULL;
+ }
+ if ( Abc_NtkCiNum(pNtkOn) != Abc_NtkCiNum(pNtkOff) )
+ {
+ printf( "The number of PIs should be the same.\n" );
+ return NULL;
+ }
+ // create internal AIGs
+ pManOn = Abc_NtkToDar( pNtkOn, 0 );
+ if ( pManOn == NULL )
+ return NULL;
+ pManOff = Abc_NtkToDar( pNtkOff, 0 );
+ if ( pManOff == NULL )
+ return NULL;
+ // derive the interpolant
+ pManAig = Aig_ManInter( pManOn, pManOff, fVerbose );
+ if ( pManAig == NULL )
+ {
+ printf( "Interpolant computation failed.\n" );
+ return NULL;
+ }
+ Aig_ManStop( pManOn );
+ Aig_ManStop( pManOff );
+ // create logic network
+ pNtkAig = Abc_NtkFromDar( pNtkOn, pManAig );
+ Aig_ManStop( pManAig );
+ return pNtkAig;
+}
+
+
+#include "ntl.h"
+
+/**Function*************************************************************
+
+ Synopsis [Performs targe enlargement.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Abc_NtkDarTestBlif( char * pFileName )
+{
+ char Buffer[1000];
+ Ntl_Man_t * p;
+ p = Ioa_ReadBlif( pFileName, 1 );
+ if ( p == NULL )
+ {
+ printf( "Abc_NtkDarTestBlif(): Reading BLIF has failed.\n" );
+ return;
+ }
+ Ntl_ManPrintStats( p );
+// if ( !Ntl_ManInsertTest( p ) )
+ if ( !Ntl_ManInsertTestIf( p ) )
+ {
+ printf( "Abc_NtkDarTestBlif(): Tranformation of the netlist has failed.\n" );
+ return;
+ }
+// sprintf( Buffer, "%s_.blif", p->pName );
+ sprintf( Buffer, "test_.blif", p->pName );
+ Ioa_WriteBlif( p, Buffer );
+ Ntl_ManFree( p );
+}
////////////////////////////////////////////////////////////////////////
/// END OF FILE ///
diff --git a/src/base/abci/abcDebug.c b/src/base/abci/abcDebug.c
new file mode 100644
index 00000000..95b95d89
--- /dev/null
+++ b/src/base/abci/abcDebug.c
@@ -0,0 +1,208 @@
+/**CFile****************************************************************
+
+ FileName [abcDebug.c]
+
+ SystemName [ABC: Logic synthesis and verification system.]
+
+ PackageName [Network and node package.]
+
+ Synopsis [Automated debugging procedures.]
+
+ Author [Alan Mishchenko]
+
+ Affiliation [UC Berkeley]
+
+ Date [Ver. 1.0. Started - June 20, 2005.]
+
+ Revision [$Id: abcDebug.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "abc.h"
+
+////////////////////////////////////////////////////////////////////////
+/// DECLARATIONS ///
+////////////////////////////////////////////////////////////////////////
+
+static int Abc_NtkCountFaninsTotal( Abc_Ntk_t * pNtk );
+static Abc_Ntk_t * Abc_NtkAutoDebugModify( Abc_Ntk_t * pNtk, int ObjNum, int fConst1 );
+
+extern void Io_WriteBlifLogic( Abc_Ntk_t * pNtk, char * FileName, int fWriteLatches );
+
+////////////////////////////////////////////////////////////////////////
+/// FUNCTION DEFINITIONS ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+ Synopsis [Takes a network and a procedure to test.]
+
+ Description [The network demonstrates the bug in the procedure.
+ Procedure should return 1 if the bug is demonstrated.]
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Abc_NtkAutoDebug( Abc_Ntk_t * pNtk, int (*pFuncError) (Abc_Ntk_t *) )
+{
+ Abc_Ntk_t * pNtkMod;
+ char * pFileName = "bug_found.blif";
+ int i, nSteps, nIter, ModNum, RandNum = 1, clk, clkTotal = clock();
+ assert( Abc_NtkIsLogic(pNtk) );
+ srand( 0x123123 );
+ // create internal copy of the network
+ pNtk = Abc_NtkDup(pNtk);
+ if ( !(*pFuncError)( pNtk ) )
+ {
+ printf( "The original network does not cause the bug. Quitting.\n" );
+ Abc_NtkDelete( pNtk );
+ return;
+ }
+ // perform incremental modifications
+ for ( nIter = 0; ; nIter++ )
+ {
+ clk = clock();
+ // count how many ways of modifying the network exists
+ nSteps = 2 * Abc_NtkCountFaninsTotal(pNtk);
+ // try modifying the network as many times
+ RandNum ^= rand();
+ for ( i = 0; i < nSteps; i++ )
+ {
+ // get the shifted number of bug
+ ModNum = (i + RandNum) % nSteps;
+ // get the modified network
+ pNtkMod = Abc_NtkAutoDebugModify( pNtk, ModNum/2, ModNum%2 );
+ // write the network
+ Io_WriteBlifLogic( pNtk, "bug_temp.blif", 1 );
+ // check if the bug is still there
+ if ( (*pFuncError)( pNtkMod ) ) // bug is still there
+ {
+ Abc_NtkDelete( pNtk );
+ pNtk = pNtkMod;
+ break;
+ }
+ else // no bug
+ Abc_NtkDelete( pNtkMod );
+ }
+ printf( "Iter %6d : Latches = %6d. Nodes = %6d. Steps = %6d. Error step = %3d. ",
+ nIter, Abc_NtkLatchNum(pNtk), Abc_NtkNodeNum(pNtk), nSteps, i );
+ PRT( "Time", clock() - clk );
+ if ( i == nSteps ) // could not modify it while preserving the bug
+ break;
+ }
+ // write out the final network
+ Io_WriteBlifLogic( pNtk, pFileName, 1 );
+ printf( "Final network written into file \"%s\". ", pFileName );
+ PRT( "Total time", clock() - clkTotal );
+ Abc_NtkDelete( pNtk );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Counts the total number of fanins.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Abc_NtkCountFaninsTotal( Abc_Ntk_t * pNtk )
+{
+ Abc_Obj_t * pObj, * pFanin;
+ int i, k, Counter = 0;
+ Abc_NtkForEachObj( pNtk, pObj, i )
+ Abc_ObjForEachFanin( pObj, pFanin, k )
+ {
+ if ( !Abc_ObjIsNode(pObj) && !Abc_ObjIsPo(pObj) )
+ continue;
+ if ( Abc_ObjIsPo(pObj) && Abc_NtkPoNum(pNtk) == 1 )
+ continue;
+ if ( Abc_ObjIsNode(pObj) && Abc_NodeIsConst(pFanin) )
+ continue;
+ Counter++;
+ }
+ return Counter;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Returns the node and fanin to be modified.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Abc_NtkFindGivenFanin( Abc_Ntk_t * pNtk, int Step, Abc_Obj_t ** ppObj, Abc_Obj_t ** ppFanin )
+{
+ Abc_Obj_t * pObj, * pFanin;
+ int i, k, Counter = 0;
+ Abc_NtkForEachObj( pNtk, pObj, i )
+ Abc_ObjForEachFanin( pObj, pFanin, k )
+ {
+ if ( !Abc_ObjIsNode(pObj) && !Abc_ObjIsPo(pObj) )
+ continue;
+ if ( Abc_ObjIsPo(pObj) && Abc_NtkPoNum(pNtk) == 1 )
+ continue;
+ if ( Abc_ObjIsNode(pObj) && Abc_NodeIsConst(pFanin) )
+ continue;
+ if ( Counter++ == Step )
+ {
+ *ppObj = pObj;
+ *ppFanin = pFanin;
+ return 1;
+ }
+ }
+ return 0;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Perform modification with the given number.]
+
+ Description [Modification consists of replacing the node by a constant.]
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Abc_Ntk_t * Abc_NtkAutoDebugModify( Abc_Ntk_t * pNtkInit, int Step, int fConst1 )
+{
+ extern void Abc_NtkCycleInitStateSop( Abc_Ntk_t * pNtk, int nFrames, int fVerbose );
+ Abc_Ntk_t * pNtk;
+ Abc_Obj_t * pObj, * pFanin, * pConst;
+ // copy the network
+ pNtk = Abc_NtkDup( pNtkInit );
+ assert( Abc_NtkNodeNum(pNtk) == Abc_NtkNodeNum(pNtkInit) );
+ // find the object number
+ Abc_NtkFindGivenFanin( pNtk, Step, &pObj, &pFanin );
+ // consider special case
+ if ( Abc_ObjIsPo(pObj) && Abc_NodeIsConst(pFanin) )
+ {
+ Abc_NtkDeleteAll_rec( pObj );
+ return pNtk;
+ }
+ // plug in a constant node
+ pConst = fConst1? Abc_NtkCreateNodeConst1(pNtk) : Abc_NtkCreateNodeConst0(pNtk);
+ Abc_ObjTransferFanout( pFanin, pConst );
+ Abc_NtkDeleteAll_rec( pFanin );
+
+ Abc_NtkSweep( pNtk, 0 );
+ Abc_NtkCleanupSeq( pNtk, 0, 0, 0 );
+ Abc_NtkToSop( pNtk, 0 );
+ Abc_NtkCycleInitStateSop( pNtk, 50, 0 );
+ return pNtk;
+}
+
+////////////////////////////////////////////////////////////////////////
+/// END OF FILE ///
+////////////////////////////////////////////////////////////////////////
+
+
diff --git a/src/base/abci/abcDress.c b/src/base/abci/abcDress.c
new file mode 100644
index 00000000..f8182532
--- /dev/null
+++ b/src/base/abci/abcDress.c
@@ -0,0 +1,209 @@
+/**CFile****************************************************************
+
+ FileName [abcDress.c]
+
+ SystemName [ABC: Logic synthesis and verification system.]
+
+ PackageName [Network and node package.]
+
+ Synopsis [Transfers names from one netlist to the other.]
+
+ Author [Alan Mishchenko]
+
+ Affiliation [UC Berkeley]
+
+ Date [Ver. 1.0. Started - June 20, 2005.]
+
+ Revision [$Id: abcDress.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "abc.h"
+#include "io.h"
+
+////////////////////////////////////////////////////////////////////////
+/// DECLARATIONS ///
+////////////////////////////////////////////////////////////////////////
+
+static stmm_table * Abc_NtkDressDeriveMapping( Abc_Ntk_t * pNtk );
+static void Abc_NtkDressTransferNames( Abc_Ntk_t * pNtk, stmm_table * tMapping, int fVerbose );
+
+extern Abc_Ntk_t * Abc_NtkIvyFraig( Abc_Ntk_t * pNtk, int nConfLimit, int fDoSparse, int fProve, int fTransfer, int fVerbose );
+
+////////////////////////////////////////////////////////////////////////
+/// FUNCTION DEFINITIONS ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+ Synopsis [Transfers names from one netlist to the other.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Abc_NtkDress( Abc_Ntk_t * pNtkLogic, char * pFileName, int fVerbose )
+{
+ Abc_Ntk_t * pNtkOrig, * pNtkLogicOrig;
+ Abc_Ntk_t * pMiter, * pMiterFraig;
+ stmm_table * tMapping;
+
+ assert( Abc_NtkIsLogic(pNtkLogic) );
+
+ // get the original netlist
+ pNtkOrig = Io_ReadNetlist( pFileName, Io_ReadFileType(pFileName), 1 );
+ if ( pNtkOrig == NULL )
+ return;
+ assert( Abc_NtkIsNetlist(pNtkOrig) );
+
+ Abc_NtkCleanCopy(pNtkLogic);
+ Abc_NtkCleanCopy(pNtkOrig);
+
+ // convert it into the logic network
+ pNtkLogicOrig = Abc_NtkToLogic( pNtkOrig );
+ // check that the networks have the same PIs/POs/latches
+ if ( !Abc_NtkCompareSignals( pNtkLogic, pNtkLogicOrig, 1, 1 ) )
+ {
+ Abc_NtkDelete( pNtkOrig );
+ Abc_NtkDelete( pNtkLogicOrig );
+ return;
+ }
+
+ // convert the current logic network into an AIG
+ pMiter = Abc_NtkStrash( pNtkLogic, 1, 0, 0 );
+
+ // convert it into the AIG and make the netlist point to the AIG
+ Abc_NtkAppend( pMiter, pNtkLogicOrig, 1 );
+ Abc_NtkTransferCopy( pNtkOrig );
+ Abc_NtkDelete( pNtkLogicOrig );
+
+if ( fVerbose )
+{
+printf( "After mitering:\n" );
+printf( "Logic: Nodes = %5d. Copy = %5d. \n", Abc_NtkNodeNum(pNtkLogic), Abc_NtkCountCopy(pNtkLogic) );
+printf( "Orig: Nodes = %5d. Copy = %5d. \n", Abc_NtkNodeNum(pNtkOrig), Abc_NtkCountCopy(pNtkOrig) );
+}
+
+ // fraig the miter (miter nodes point to the fraiged miter)
+ pMiterFraig = Abc_NtkIvyFraig( pMiter, 100, 1, 0, 1, 0 );
+ // make netlists point to the fraiged miter
+ Abc_NtkTransferCopy( pNtkLogic );
+ Abc_NtkTransferCopy( pNtkOrig );
+ Abc_NtkDelete( pMiter );
+
+if ( fVerbose )
+{
+printf( "After fraiging:\n" );
+printf( "Logic: Nodes = %5d. Copy = %5d. \n", Abc_NtkNodeNum(pNtkLogic), Abc_NtkCountCopy(pNtkLogic) );
+printf( "Orig: Nodes = %5d. Copy = %5d. \n", Abc_NtkNodeNum(pNtkOrig), Abc_NtkCountCopy(pNtkOrig) );
+}
+
+ // derive mapping from the fraiged nodes into their prototype nodes in the original netlist
+ tMapping = Abc_NtkDressDeriveMapping( pNtkOrig );
+
+ // transfer the names to the new netlist
+ Abc_NtkDressTransferNames( pNtkLogic, tMapping, fVerbose );
+
+ // clean up
+ stmm_free_table( tMapping );
+ Abc_NtkDelete( pMiterFraig );
+ Abc_NtkDelete( pNtkOrig );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Returns the mapping from the fraig nodes point into the nodes of the netlist.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+stmm_table * Abc_NtkDressDeriveMapping( Abc_Ntk_t * pNtk )
+{
+ stmm_table * tResult;
+ Abc_Obj_t * pNode, * pNodeMap, * pNodeFraig;
+ int i;
+ assert( Abc_NtkIsNetlist(pNtk) );
+ tResult = stmm_init_table(stmm_ptrcmp,stmm_ptrhash);
+ Abc_NtkForEachNode( pNtk, pNode, i )
+ {
+ // get the fraiged node
+ pNodeFraig = Abc_ObjRegular(pNode->pCopy);
+ // if this node is already mapped, skip
+ if ( stmm_is_member( tResult, (char *)pNodeFraig ) )
+ continue;
+ // get the mapping of this node
+ pNodeMap = Abc_ObjNotCond( pNode, Abc_ObjIsComplement(pNode->pCopy) );
+ // add the mapping
+ stmm_insert( tResult, (char *)pNodeFraig, (char *)pNodeMap );
+ }
+ return tResult;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Attaches the names of to the new netlist.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Abc_NtkDressTransferNames( Abc_Ntk_t * pNtk, stmm_table * tMapping, int fVerbose )
+{
+ Abc_Obj_t * pNet, * pNode, * pNodeMap, * pNodeFraig;
+ char * pName;
+ int i, Counter = 0, CounterInv = 0, CounterInit = stmm_count(tMapping);
+ assert( Abc_NtkIsLogic(pNtk) );
+ Abc_NtkForEachNode( pNtk, pNode, i )
+ {
+ // if the node already has a name, quit
+ pName = Nm_ManFindNameById( pNtk->pManName, pNode->Id );
+ if ( pName != NULL )
+ continue;
+ // get the fraiged node
+ pNodeFraig = Abc_ObjRegular(pNode->pCopy);
+ // find the matching node of the original netlist
+ if ( !stmm_lookup( tMapping, (char *)pNodeFraig, (char **)&pNodeMap ) )
+ continue;
+ // find the true match
+ pNodeMap = Abc_ObjNotCond( pNodeMap, Abc_ObjIsComplement(pNode->pCopy) );
+ // get the name
+ pNet = Abc_ObjFanout0(Abc_ObjRegular(pNodeMap));
+ pName = Nm_ManFindNameById( pNet->pNtk->pManName, pNet->Id );
+ assert( pName != NULL );
+ // set the name
+ if ( Abc_ObjIsComplement(pNodeMap) )
+ {
+ Abc_ObjAssignName( pNode, pName, "_inv" );
+ CounterInv++;
+ }
+ else
+ {
+ Abc_ObjAssignName( pNode, pName, NULL );
+ Counter++;
+ }
+ // remove the name
+ stmm_delete( tMapping, (char **)&pNodeFraig, (char **)&pNodeMap );
+ }
+ if ( fVerbose )
+ {
+ printf( "Total number of names collected = %5d.\n", CounterInit );
+ printf( "Total number of names assigned = %5d. (Dir = %5d. Compl = %5d.)\n",
+ Counter + CounterInv, Counter, CounterInv );
+ }
+}
+
+////////////////////////////////////////////////////////////////////////
+/// END OF FILE ///
+////////////////////////////////////////////////////////////////////////
+
+
diff --git a/src/base/abci/abcDsd.c b/src/base/abci/abcDsd.c
index 67665ad6..c00a7d7c 100644
--- a/src/base/abci/abcDsd.c
+++ b/src/base/abci/abcDsd.c
@@ -27,15 +27,15 @@
static Abc_Ntk_t * Abc_NtkDsdInternal( Abc_Ntk_t * pNtk, bool fVerbose, bool fPrint, bool fShort );
static void Abc_NtkDsdConstruct( Dsd_Manager_t * pManDsd, Abc_Ntk_t * pNtk, Abc_Ntk_t * pNtkNew );
-static Abc_Obj_t * Abc_NtkDsdConstructNode( Dsd_Manager_t * pManDsd, Dsd_Node_t * pNodeDsd, Abc_Ntk_t * pNtkNew );
+static Abc_Obj_t * Abc_NtkDsdConstructNode( Dsd_Manager_t * pManDsd, Dsd_Node_t * pNodeDsd, Abc_Ntk_t * pNtkNew, int * pCounters );
static Vec_Ptr_t * Abc_NtkCollectNodesForDsd( Abc_Ntk_t * pNtk );
-static void Abc_NodeDecompDsdAndMux( Abc_Obj_t * pNode, Vec_Ptr_t * vNodes, Dsd_Manager_t * pManDsd, bool fRecursive );
+static void Abc_NodeDecompDsdAndMux( Abc_Obj_t * pNode, Vec_Ptr_t * vNodes, Dsd_Manager_t * pManDsd, bool fRecursive, int * pCounters );
static bool Abc_NodeIsForDsd( Abc_Obj_t * pNode );
static int Abc_NodeFindMuxVar( DdManager * dd, DdNode * bFunc, int nVars );
////////////////////////////////////////////////////////////////////////
-/// FUNCTION DEFITIONS ///
+/// FUNCTION DEFINITIONS ///
////////////////////////////////////////////////////////////////////////
/**Function*************************************************************
@@ -55,28 +55,22 @@ static int Abc_NodeFindMuxVar( DdManager * dd, DdNode * bFunc, int n
***********************************************************************/
Abc_Ntk_t * Abc_NtkDsdGlobal( Abc_Ntk_t * pNtk, bool fVerbose, bool fPrint, bool fShort )
{
+ DdManager * dd;
Abc_Ntk_t * pNtkNew;
-
assert( Abc_NtkIsStrash(pNtk) );
-
- // perform FPGA mapping
- if ( Abc_NtkGlobalBdds(pNtk, 0) == NULL )
+ dd = Abc_NtkBuildGlobalBdds( pNtk, 10000000, 1, 1, fVerbose );
+ if ( dd == NULL )
return NULL;
if ( fVerbose )
- printf( "The shared BDD size is %d nodes.\n", Cudd_ReadKeys(pNtk->pManGlob) - Cudd_ReadDead(pNtk->pManGlob) );
-
+ printf( "Shared BDD size = %6d nodes.\n", Cudd_ReadKeys(dd) - Cudd_ReadDead(dd) );
// transform the result of mapping into a BDD network
pNtkNew = Abc_NtkDsdInternal( pNtk, fVerbose, fPrint, fShort );
+ Extra_StopManager( dd );
if ( pNtkNew == NULL )
- {
- Cudd_Quit( pNtk->pManGlob );
- pNtk->pManGlob = NULL;
return NULL;
- }
- Extra_StopManager( pNtk->pManGlob );
- pNtk->pManGlob = NULL;
-
- // make sure that everything is okay
+ // copy EXDC network
+ if ( pNtk->pExdc )
+ pNtkNew->pExdc = Abc_NtkDup( pNtk->pExdc );
if ( !Abc_NtkCheck( pNtkNew ) )
{
printf( "Abc_NtkDsdGlobal: The network check has failed.\n" );
@@ -99,26 +93,25 @@ Abc_Ntk_t * Abc_NtkDsdGlobal( Abc_Ntk_t * pNtk, bool fVerbose, bool fPrint, bool
***********************************************************************/
Abc_Ntk_t * Abc_NtkDsdInternal( Abc_Ntk_t * pNtk, bool fVerbose, bool fPrint, bool fShort )
{
- DdManager * dd = pNtk->pManGlob;
+ char ** ppNamesCi, ** ppNamesCo;
+ Vec_Ptr_t * vFuncsGlob;
Dsd_Manager_t * pManDsd;
Abc_Ntk_t * pNtkNew;
- DdNode * bFunc;
- char ** ppNamesCi, ** ppNamesCo;
+ DdManager * dd;
Abc_Obj_t * pObj;
int i;
// complement the global functions
+ vFuncsGlob = Vec_PtrAlloc( Abc_NtkCoNum(pNtk) );
Abc_NtkForEachCo( pNtk, pObj, i )
- {
- bFunc = Vec_PtrEntry(pNtk->vFuncsGlob, i);
- Vec_PtrWriteEntry(pNtk->vFuncsGlob, i, Cudd_NotCond(bFunc, Abc_ObjFaninC0(pObj)) );
- }
+ Vec_PtrPush( vFuncsGlob, Cudd_NotCond(Abc_ObjGlobalBdd(pObj), Abc_ObjFaninC0(pObj)) );
// perform the decomposition
- assert( Vec_PtrSize(pNtk->vFuncsGlob) == Abc_NtkCoNum(pNtk) );
+ dd = Abc_NtkGlobalBddMan(pNtk);
pManDsd = Dsd_ManagerStart( dd, Abc_NtkCiNum(pNtk), fVerbose );
- Dsd_Decompose( pManDsd, (DdNode **)pNtk->vFuncsGlob->pArray, Abc_NtkCoNum(pNtk) );
- Abc_NtkFreeGlobalBdds( pNtk );
+ Dsd_Decompose( pManDsd, (DdNode **)vFuncsGlob->pArray, Abc_NtkCoNum(pNtk) );
+ Vec_PtrFree( vFuncsGlob );
+ Abc_NtkFreeGlobalBdds( pNtk, 0 );
if ( pManDsd == NULL )
{
Cudd_Quit( dd );
@@ -126,7 +119,7 @@ Abc_Ntk_t * Abc_NtkDsdInternal( Abc_Ntk_t * pNtk, bool fVerbose, bool fPrint, bo
}
// start the new network
- pNtkNew = Abc_NtkStartFrom( pNtk, ABC_TYPE_LOGIC, ABC_FUNC_BDD );
+ pNtkNew = Abc_NtkStartFrom( pNtk, ABC_NTK_LOGIC, ABC_FUNC_BDD );
// make sure the new manager has enough inputs
Cudd_bddIthVar( pNtkNew->pManFunc, dd->size-1 );
// put the results into the new network (save new CO drivers in old CO drivers)
@@ -135,7 +128,6 @@ Abc_Ntk_t * Abc_NtkDsdInternal( Abc_Ntk_t * pNtk, bool fVerbose, bool fPrint, bo
Abc_NtkFinalize( pNtk, pNtkNew );
// fix the problem with complemented and duplicated CO edges
Abc_NtkLogicMakeSimpleCos( pNtkNew, 0 );
-
if ( fPrint )
{
ppNamesCi = Abc_NtkCollectCioNames( pNtk, 0 );
@@ -165,24 +157,21 @@ void Abc_NtkDsdConstruct( Dsd_Manager_t * pManDsd, Abc_Ntk_t * pNtk, Abc_Ntk_t *
{
Dsd_Node_t ** ppNodesDsd;
Dsd_Node_t * pNodeDsd;
- Abc_Obj_t * pNode, * pNodeNew, * pDriver, * pConst1;
+ Abc_Obj_t * pNode, * pNodeNew, * pDriver;
int i, nNodesDsd;
// save the CI nodes in the DSD nodes
+ Dsd_NodeSetMark( Dsd_ManagerReadConst1(pManDsd), (int)Abc_NtkCreateNodeConst1(pNtkNew) );
Abc_NtkForEachCi( pNtk, pNode, i )
{
pNodeDsd = Dsd_ManagerReadInput( pManDsd, i );
Dsd_NodeSetMark( pNodeDsd, (int)pNode->pCopy );
}
- // set the constant node
- pConst1 = Abc_AigConst1(pNtk->pManFunc);
- if ( Abc_ObjFanoutNum(pConst1) > 0 )
- pConst1->pCopy = Abc_NodeCreateConst1(pNtkNew);
// collect DSD nodes in DFS order (leaves and const1 are not collected)
ppNodesDsd = Dsd_TreeCollectNodesDfs( pManDsd, &nNodesDsd );
for ( i = 0; i < nNodesDsd; i++ )
- Abc_NtkDsdConstructNode( pManDsd, ppNodesDsd[i], pNtkNew );
+ Abc_NtkDsdConstructNode( pManDsd, ppNodesDsd[i], pNtkNew, NULL );
free( ppNodesDsd );
// set the pointers to the CO drivers
@@ -191,7 +180,7 @@ void Abc_NtkDsdConstruct( Dsd_Manager_t * pManDsd, Abc_Ntk_t * pNtk, Abc_Ntk_t *
pDriver = Abc_ObjFanin0( pNode );
if ( !Abc_ObjIsNode(pDriver) )
continue;
- if ( !Abc_NodeIsAigAnd(pDriver) )
+ if ( !Abc_AigNodeIsAnd(pDriver) )
continue;
pNodeDsd = Dsd_ManagerReadRoot( pManDsd, i );
pNodeNew = (Abc_Obj_t *)Dsd_NodeReadMark( Dsd_Regular(pNodeDsd) );
@@ -211,7 +200,7 @@ void Abc_NtkDsdConstruct( Dsd_Manager_t * pManDsd, Abc_Ntk_t * pNtk, Abc_Ntk_t *
SeeAlso []
***********************************************************************/
-Abc_Obj_t * Abc_NtkDsdConstructNode( Dsd_Manager_t * pManDsd, Dsd_Node_t * pNodeDsd, Abc_Ntk_t * pNtkNew )
+Abc_Obj_t * Abc_NtkDsdConstructNode( Dsd_Manager_t * pManDsd, Dsd_Node_t * pNodeDsd, Abc_Ntk_t * pNtkNew, int * pCounters )
{
DdManager * ddDsd = Dsd_ManagerReadDd( pManDsd );
DdManager * ddNew = pNtkNew->pManFunc;
@@ -268,8 +257,22 @@ Abc_Obj_t * Abc_NtkDsdConstructNode( Dsd_Manager_t * pManDsd, Dsd_Node_t * pNode
}
case DSD_NODE_PRIME:
{
+ if ( pCounters )
+ {
+ if ( nDecs < 10 )
+ pCounters[nDecs]++;
+ else
+ pCounters[10]++;
+ }
bLocal = Dsd_TreeGetPrimeFunction( ddDsd, pNodeDsd ); Cudd_Ref( bLocal );
bLocal = Extra_TransferLevelByLevel( ddDsd, ddNew, bTemp = bLocal ); Cudd_Ref( bLocal );
+/*
+if ( nDecs == 3 )
+{
+Extra_bddPrint( ddDsd, bTemp );
+printf( "\n" );
+}
+*/
Cudd_RecursiveDeref( ddDsd, bTemp );
// bLocal is now in the new BDD manager
break;
@@ -307,6 +310,7 @@ int Abc_NtkDsdLocal( Abc_Ntk_t * pNtk, bool fVerbose, bool fRecursive )
DdManager * dd = pNtk->pManFunc;
Vec_Ptr_t * vNodes;
int i;
+ int pCounters[11] = {0};
assert( Abc_NtkIsBddLogic(pNtk) );
@@ -319,9 +323,14 @@ int Abc_NtkDsdLocal( Abc_Ntk_t * pNtk, bool fVerbose, bool fRecursive )
// collect nodes for decomposition
vNodes = Abc_NtkCollectNodesForDsd( pNtk );
for ( i = 0; i < vNodes->nSize; i++ )
- Abc_NodeDecompDsdAndMux( vNodes->pArray[i], vNodes, pManDsd, fRecursive );
+ Abc_NodeDecompDsdAndMux( vNodes->pArray[i], vNodes, pManDsd, fRecursive, pCounters );
Vec_PtrFree( vNodes );
+ printf( "Number of non-decomposable functions:\n" );
+ for ( i = 3; i < 10; i++ )
+ printf( "Inputs = %d. Functions = %6d.\n", i, pCounters[i] );
+ printf( "Inputs > %d. Functions = %6d.\n", 9, pCounters[10] );
+
// stop the DSD manager
Dsd_ManagerStop( pManDsd );
@@ -371,7 +380,7 @@ Vec_Ptr_t * Abc_NtkCollectNodesForDsd( Abc_Ntk_t * pNtk )
SeeAlso []
***********************************************************************/
-void Abc_NodeDecompDsdAndMux( Abc_Obj_t * pNode, Vec_Ptr_t * vNodes, Dsd_Manager_t * pManDsd, bool fRecursive )
+void Abc_NodeDecompDsdAndMux( Abc_Obj_t * pNode, Vec_Ptr_t * vNodes, Dsd_Manager_t * pManDsd, bool fRecursive, int * pCounters )
{
DdManager * dd = pNode->pNtk->pManFunc;
Abc_Obj_t * pRoot, * pFanin, * pNode1, * pNode2, * pNodeC;
@@ -398,7 +407,7 @@ void Abc_NodeDecompDsdAndMux( Abc_Obj_t * pNode, Vec_Ptr_t * vNodes, Dsd_Manager
ppNodesDsd = Dsd_TreeCollectNodesDfsOne( pManDsd, pNodeDsd, &nNodesDsd );
for ( i = 0; i < nNodesDsd; i++ )
{
- pRoot = Abc_NtkDsdConstructNode( pManDsd, ppNodesDsd[i], pNode->pNtk );
+ pRoot = Abc_NtkDsdConstructNode( pManDsd, ppNodesDsd[i], pNode->pNtk, pCounters );
if ( Abc_NodeIsForDsd(pRoot) && fRecursive )
Vec_PtrPush( vNodes, pRoot );
}
@@ -419,14 +428,14 @@ void Abc_NodeDecompDsdAndMux( Abc_Obj_t * pNode, Vec_Ptr_t * vNodes, Dsd_Manager
pNodeC = Abc_ObjFanin( pNode, iVar );
// get the negative cofactor
- pNode1 = Abc_NodeClone( pNode );
+ pNode1 = Abc_NtkCloneObj( pNode );
pNode1->pData = Cudd_Cofactor( dd, pNode->pData, Cudd_Not(dd->vars[iVar]) ); Cudd_Ref( pNode1->pData );
Abc_NodeMinimumBase( pNode1 );
if ( Abc_NodeIsForDsd(pNode1) )
Vec_PtrPush( vNodes, pNode1 );
// get the positive cofactor
- pNode2 = Abc_NodeClone( pNode );
+ pNode2 = Abc_NtkCloneObj( pNode );
pNode2->pData = Cudd_Cofactor( dd, pNode->pData, dd->vars[iVar] ); Cudd_Ref( pNode2->pData );
Abc_NodeMinimumBase( pNode2 );
if ( Abc_NodeIsForDsd(pNode2) )
@@ -446,7 +455,7 @@ void Abc_NodeDecompDsdAndMux( Abc_Obj_t * pNode, Vec_Ptr_t * vNodes, Dsd_Manager
/**Function*************************************************************
- Synopsis [Performs decomposition of one node.]
+ Synopsis [Checks if the node should be decomposed by DSD.]
Description []
@@ -458,12 +467,14 @@ void Abc_NodeDecompDsdAndMux( Abc_Obj_t * pNode, Vec_Ptr_t * vNodes, Dsd_Manager
bool Abc_NodeIsForDsd( Abc_Obj_t * pNode )
{
DdManager * dd = pNode->pNtk->pManFunc;
- DdNode * bFunc, * bFunc0, * bFunc1;
+// DdNode * bFunc, * bFunc0, * bFunc1;
assert( Abc_ObjIsNode(pNode) );
// if ( Cudd_DagSize(pNode->pData)-1 > Abc_ObjFaninNum(pNode) )
// return 1;
// return 0;
+/*
+ // this does not catch things like a(b+c), which should be decomposed
for ( bFunc = Cudd_Regular(pNode->pData); !cuddIsConstant(bFunc); )
{
bFunc0 = Cudd_Regular( cuddE(bFunc) );
@@ -475,6 +486,9 @@ bool Abc_NodeIsForDsd( Abc_Obj_t * pNode )
else
return 1;
}
+*/
+ if ( Abc_ObjFaninNum(pNode) > 2 )
+ return 1;
return 0;
}
diff --git a/src/base/abci/abcEspresso.c b/src/base/abci/abcEspresso.c
new file mode 100644
index 00000000..8f9c7277
--- /dev/null
+++ b/src/base/abci/abcEspresso.c
@@ -0,0 +1,250 @@
+/**CFile****************************************************************
+
+ FileName [abcEspresso.c]
+
+ SystemName [ABC: Logic synthesis and verification system.]
+
+ PackageName [Network and node package.]
+
+ Synopsis [Procedures to minimize SOPs using Espresso.]
+
+ Author [Alan Mishchenko]
+
+ Affiliation [UC Berkeley]
+
+ Date [Ver. 1.0. Started - June 20, 2005.]
+
+ Revision [$Id: abcEspresso.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "abc.h"
+#include "espresso.h"
+
+////////////////////////////////////////////////////////////////////////
+/// DECLARATIONS ///
+////////////////////////////////////////////////////////////////////////
+
+static void Abc_NodeEspresso( Abc_Obj_t * pNode );
+static pset_family Abc_SopToEspresso( char * pSop );
+static char * Abc_SopFromEspresso( Extra_MmFlex_t * pMan, pset_family Cover );
+static pset_family Abc_EspressoMinimize( pset_family pOnset, pset_family pDcset );
+
+////////////////////////////////////////////////////////////////////////
+/// FUNCTION DEFINITIONS ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+ Synopsis [Minimizes SOP representations using Espresso.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Abc_NtkEspresso( Abc_Ntk_t * pNtk, int fVerbose )
+{
+ Abc_Obj_t * pNode;
+ int i;
+ assert( Abc_NtkIsLogic(pNtk) );
+ // convert the network to have SOPs
+ if ( Abc_NtkHasMapping(pNtk) )
+ Abc_NtkMapToSop(pNtk);
+ else if ( Abc_NtkHasBdd(pNtk) )
+ {
+ if ( !Abc_NtkBddToSop(pNtk, 0) )
+ {
+ printf( "Abc_NtkEspresso(): Converting to SOPs has failed.\n" );
+ return;
+ }
+ }
+ // minimize SOPs of all nodes
+ Abc_NtkForEachNode( pNtk, pNode, i )
+ if ( i ) Abc_NodeEspresso( pNode );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Minimizes SOP representation of one node.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Abc_NodeEspresso( Abc_Obj_t * pNode )
+{
+ extern void define_cube_size( int n );
+ pset_family Cover;
+ int fCompl;
+
+ assert( Abc_ObjIsNode(pNode) );
+ // define the cube for this node
+ define_cube_size( Abc_ObjFaninNum(pNode) );
+ // create the Espresso cover
+ fCompl = Abc_SopIsComplement( pNode->pData );
+ Cover = Abc_SopToEspresso( pNode->pData );
+ // perform minimization
+ Cover = Abc_EspressoMinimize( Cover, NULL ); // deletes also cover
+ // convert back onto the node's SOP representation
+ pNode->pData = Abc_SopFromEspresso( pNode->pNtk->pManFunc, Cover );
+ if ( fCompl ) Abc_SopComplement( pNode->pData );
+ sf_free(Cover);
+}
+
+/**Function*************************************************************
+
+ Synopsis [Converts SOP in ABC into SOP representation in Espresso.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+pset_family Abc_SopToEspresso( char * pSop )
+{
+ char * pCube;
+ pset_family Cover;
+ pset set;
+ int nCubes, nVars, Value, v;
+
+ if ( pSop == NULL )
+ return NULL;
+
+ nVars = Abc_SopGetVarNum(pSop);
+ nCubes = Abc_SopGetCubeNum(pSop);
+ assert( cube.size == 2 * nVars );
+
+ if ( Abc_SopIsConst0(pSop) )
+ {
+ Cover = sf_new(0, cube.size);
+ return Cover;
+ }
+ if ( Abc_SopIsConst1(pSop) )
+ {
+ Cover = sf_new(1, cube.size);
+ set = GETSET(Cover, Cover->count++);
+ set_copy( set, cube.fullset );
+ return Cover;
+ }
+
+ // create the cover
+ Cover = sf_new(nCubes, cube.size);
+ // fill in the cubes
+ Abc_SopForEachCube( pSop, nVars, pCube )
+ {
+ set = GETSET(Cover, Cover->count++);
+ set_copy( set, cube.fullset );
+ Abc_CubeForEachVar( pCube, Value, v )
+ {
+ if ( Value == '0' )
+ set_remove(set, 2*v+1);
+ else if ( Value == '1' )
+ set_remove(set, 2*v);
+ }
+ }
+ return Cover;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Converts SOP representation in Espresso into SOP in ABC.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+char * Abc_SopFromEspresso( Extra_MmFlex_t * pMan, pset_family Cover )
+{
+ pset set;
+ char * pSop, * pCube;
+ int Lit, nVars, nCubes, i, k;
+
+ nVars = Cover->sf_size/2;
+ nCubes = Cover->count;
+
+ pSop = Abc_SopStart( pMan, nCubes, nVars );
+
+ // go through the cubes
+ i = 0;
+ Abc_SopForEachCube( pSop, nVars, pCube )
+ {
+ set = GETSET(Cover, i++);
+ for ( k = 0; k < nVars; k++ )
+ {
+ Lit = GETINPUT(set, k);
+ if ( Lit == ZERO )
+ pCube[k] = '0';
+ else if ( Lit == ONE )
+ pCube[k] = '1';
+ }
+ }
+ return pSop;
+}
+
+
+/**Function*************************************************************
+
+ Synopsis [Minimizes the cover using Espresso.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+pset_family Abc_EspressoMinimize( pset_family pOnset, pset_family pDcset )
+{
+ pset_family pOffset;
+ int fNewDcset, i;
+ int fSimple = 0;
+ int fSparse = 0;
+
+ if ( fSimple )
+ {
+ for ( i = 0; i < cube.num_vars; i++ )
+ pOnset = d1merge( pOnset, i );
+ pOnset = sf_contain( pOnset );
+ return pOnset;
+ }
+
+ // create the dcset
+ fNewDcset = (pDcset == NULL);
+ if ( pDcset == NULL )
+ pDcset = sf_new( 1, cube.size );
+ pDcset->wsize = pOnset->wsize;
+ pDcset->sf_size = pOnset->sf_size;
+
+ // derive the offset
+ if ( pDcset->sf_size == 0 || pDcset->count == 0 )
+ pOffset = complement(cube1list(pOnset));
+ else
+ pOffset = complement(cube2list(pOnset, pDcset));
+
+ // perform minimization
+ skip_make_sparse = !fSparse;
+ pOnset = espresso( pOnset, pDcset, pOffset );
+
+ // free covers
+ sf_free( pOffset );
+ if ( fNewDcset )
+ sf_free( pDcset );
+ return pOnset;
+}
+
+////////////////////////////////////////////////////////////////////////
+/// END OF FILE ///
+////////////////////////////////////////////////////////////////////////
+
+
diff --git a/src/base/abcs/abc_.c b/src/base/abci/abcExtract.c
index bef3836f..52ea03a3 100644
--- a/src/base/abcs/abc_.c
+++ b/src/base/abci/abcExtract.c
@@ -1,12 +1,12 @@
/**CFile****************************************************************
- FileName [abc_.c]
+ FileName [abcMvCost.c]
SystemName [ABC: Logic synthesis and verification system.]
PackageName [Network and node package.]
- Synopsis []
+ Synopsis [Calculating the cost of one MV block.]
Author [Alan Mishchenko]
@@ -14,7 +14,7 @@
Date [Ver. 1.0. Started - June 20, 2005.]
- Revision [$Id: abc_.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
+ Revision [$Id: abcMvCost.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
***********************************************************************/
@@ -23,9 +23,9 @@
////////////////////////////////////////////////////////////////////////
/// DECLARATIONS ///
////////////////////////////////////////////////////////////////////////
-
+
////////////////////////////////////////////////////////////////////////
-/// FUNCTION DEFITIONS ///
+/// FUNCTION DEFINITIONS ///
////////////////////////////////////////////////////////////////////////
/**Function*************************************************************
@@ -39,6 +39,10 @@
SeeAlso []
***********************************************************************/
+void Abc_MvCostTest( Abc_Ntk_t * pNtk )
+{
+
+}
////////////////////////////////////////////////////////////////////////
/// END OF FILE ///
diff --git a/src/base/abci/abcFpga.c b/src/base/abci/abcFpga.c
index 55ae23ff..3bc9fbed 100644
--- a/src/base/abci/abcFpga.c
+++ b/src/base/abci/abcFpga.c
@@ -25,12 +25,12 @@
/// DECLARATIONS ///
////////////////////////////////////////////////////////////////////////
-static Fpga_Man_t * Abc_NtkToFpga( Abc_Ntk_t * pNtk, int fRecovery, float * pSwitching, int fVerbose );
+static Fpga_Man_t * Abc_NtkToFpga( Abc_Ntk_t * pNtk, int fRecovery, float * pSwitching, int fLatchPaths, int fVerbose );
static Abc_Ntk_t * Abc_NtkFromFpga( Fpga_Man_t * pMan, Abc_Ntk_t * pNtk );
static Abc_Obj_t * Abc_NodeFromFpga_rec( Abc_Ntk_t * pNtkNew, Fpga_Node_t * pNodeFpga );
////////////////////////////////////////////////////////////////////////
-/// FUNCTION DEFITIONS ///
+/// FUNCTION DEFINITIONS ///
////////////////////////////////////////////////////////////////////////
/**Function*************************************************************
@@ -44,7 +44,7 @@ static Abc_Obj_t * Abc_NodeFromFpga_rec( Abc_Ntk_t * pNtkNew, Fpga_Node_t * pNo
SeeAlso []
***********************************************************************/
-Abc_Ntk_t * Abc_NtkFpga( Abc_Ntk_t * pNtk, int fRecovery, int fSwitching, int fVerbose )
+Abc_Ntk_t * Abc_NtkFpga( Abc_Ntk_t * pNtk, float DelayTarget, int fRecovery, int fSwitching, int fLatchPaths, int fVerbose )
{
int fShowSwitching = 1;
Abc_Ntk_t * pNtkNew;
@@ -68,11 +68,14 @@ Abc_Ntk_t * Abc_NtkFpga( Abc_Ntk_t * pNtk, int fRecovery, int fSwitching, int fV
}
// perform FPGA mapping
- pMan = Abc_NtkToFpga( pNtk, fRecovery, pSwitching, fVerbose );
+ pMan = Abc_NtkToFpga( pNtk, fRecovery, pSwitching, fLatchPaths, fVerbose );
if ( pSwitching ) Vec_IntFree( vSwitching );
if ( pMan == NULL )
return NULL;
Fpga_ManSetSwitching( pMan, fSwitching );
+ Fpga_ManSetLatchPaths( pMan, fLatchPaths );
+ Fpga_ManSetLatchNum( pMan, Abc_NtkLatchNum(pNtk) );
+ Fpga_ManSetDelayTarget( pMan, DelayTarget );
if ( !Fpga_Mapping( pMan ) )
{
Fpga_ManFree( pMan );
@@ -88,6 +91,9 @@ Abc_Ntk_t * Abc_NtkFpga( Abc_Ntk_t * pNtk, int fRecovery, int fSwitching, int fV
// make the network minimum base
Abc_NtkMinimumBase( pNtkNew );
+ if ( pNtk->pExdc )
+ pNtkNew->pExdc = Abc_NtkDup( pNtk->pExdc );
+
// make sure that everything is okay
if ( !Abc_NtkCheck( pNtkNew ) )
{
@@ -109,13 +115,14 @@ Abc_Ntk_t * Abc_NtkFpga( Abc_Ntk_t * pNtk, int fRecovery, int fSwitching, int fV
SeeAlso []
***********************************************************************/
-Fpga_Man_t * Abc_NtkToFpga( Abc_Ntk_t * pNtk, int fRecovery, float * pSwitching, int fVerbose )
+Fpga_Man_t * Abc_NtkToFpga( Abc_Ntk_t * pNtk, int fRecovery, float * pSwitching, int fLatchPaths, int fVerbose )
{
Fpga_Man_t * pMan;
ProgressBar * pProgress;
Fpga_Node_t * pNodeFpga;
Vec_Ptr_t * vNodes;
Abc_Obj_t * pNode, * pFanin, * pPrev;
+ float * pfArrivals;
int i;
assert( Abc_NtkIsStrash(pNtk) );
@@ -126,10 +133,17 @@ Fpga_Man_t * Abc_NtkToFpga( Abc_Ntk_t * pNtk, int fRecovery, float * pSwitching,
return NULL;
Fpga_ManSetAreaRecovery( pMan, fRecovery );
Fpga_ManSetOutputNames( pMan, Abc_NtkCollectCioNames(pNtk, 1) );
- Fpga_ManSetInputArrivals( pMan, Abc_NtkGetCiArrivalFloats(pNtk) );
+ pfArrivals = Abc_NtkGetCiArrivalFloats(pNtk);
+ if ( fLatchPaths )
+ {
+ for ( i = 0; i < Abc_NtkPiNum(pNtk); i++ )
+ pfArrivals[i] = -FPGA_FLOAT_LARGE;
+ }
+ Fpga_ManSetInputArrivals( pMan, pfArrivals );
// create PIs and remember them in the old nodes
Abc_NtkCleanCopy( pNtk );
+ Abc_AigConst1(pNtk)->pCopy = (Abc_Obj_t *)Fpga_ManReadConst1(pMan);
Abc_NtkForEachCi( pNtk, pNode, i )
{
pNodeFpga = Fpga_ManReadInputs(pMan)[i];
@@ -144,12 +158,6 @@ Fpga_Man_t * Abc_NtkToFpga( Abc_Ntk_t * pNtk, int fRecovery, float * pSwitching,
Vec_PtrForEachEntry( vNodes, pNode, i )
{
Extra_ProgressBarUpdate( pProgress, i, NULL );
- // consider the case of a constant
- if ( Abc_NodeIsConst(pNode) )
- {
- Abc_AigConst1(pNtk->pManFunc)->pCopy = (Abc_Obj_t *)Fpga_ManReadConst1(pMan);
- continue;
- }
// add the node to the mapper
pNodeFpga = Fpga_NodeAnd( pMan,
Fpga_NotCond( Abc_ObjFanin0(pNode)->pCopy, Abc_ObjFaninC0(pNode) ),
@@ -160,7 +168,7 @@ Fpga_Man_t * Abc_NtkToFpga( Abc_Ntk_t * pNtk, int fRecovery, float * pSwitching,
if ( pSwitching )
Fpga_NodeSetSwitching( pNodeFpga, pSwitching[pNode->Id] );
// set up the choice node
- if ( Abc_NodeIsAigChoice( pNode ) )
+ if ( Abc_AigNodeIsChoice( pNode ) )
for ( pPrev = pNode, pFanin = pNode->pData; pFanin; pPrev = pFanin, pFanin = pFanin->pData )
{
Fpga_NodeSetNextE( (Fpga_Node_t *)pPrev->pCopy, (Fpga_Node_t *)pFanin->pCopy );
@@ -194,15 +202,15 @@ Abc_Ntk_t * Abc_NtkFromFpga( Fpga_Man_t * pMan, Abc_Ntk_t * pNtk )
Abc_Obj_t * pNode, * pNodeNew;
int i, nDupGates;
// create the new network
- pNtkNew = Abc_NtkStartFrom( pNtk, ABC_TYPE_LOGIC, ABC_FUNC_BDD );
+ pNtkNew = Abc_NtkStartFrom( pNtk, ABC_NTK_LOGIC, ABC_FUNC_BDD );
// make the mapper point to the new network
Fpga_CutsCleanSign( pMan );
Fpga_ManCleanData0( pMan );
Abc_NtkForEachCi( pNtk, pNode, i )
Fpga_NodeSetData0( Fpga_ManReadInputs(pMan)[i], (char *)pNode->pCopy );
// set the constant node
- if ( Abc_ObjFanoutNum( Abc_AigConst1(pNtk->pManFunc) ) > 0 )
- Fpga_NodeSetData0( Fpga_ManReadConst1(pMan), (char *)Abc_NodeCreateConst1(pNtkNew) );
+// if ( Fpga_NodeReadRefs(Fpga_ManReadConst1(pMan)) > 0 )
+ Fpga_NodeSetData0( Fpga_ManReadConst1(pMan), (char *)Abc_NtkCreateNodeConst1(pNtkNew) );
// process the nodes in topological order
pProgress = Extra_ProgressBarStart( stdout, Abc_NtkCoNum(pNtk) );
Abc_NtkForEachCo( pNtk, pNode, i )
@@ -215,6 +223,10 @@ Abc_Ntk_t * Abc_NtkFromFpga( Fpga_Man_t * pMan, Abc_Ntk_t * pNtk )
Extra_ProgressBarStop( pProgress );
// finalize the new network
Abc_NtkFinalize( pNtk, pNtkNew );
+ // remove the constant node if not used
+ pNodeNew = (Abc_Obj_t *)Fpga_NodeReadData0(Fpga_ManReadConst1(pMan));
+ if ( Abc_ObjFanoutNum(pNodeNew) == 0 )
+ Abc_NtkDeleteObj( pNodeNew );
// decouple the PO driver nodes to reduce the number of levels
nDupGates = Abc_NtkLogicMakeSimpleCos( pNtkNew, 1 );
// if ( nDupGates && Fpga_ManReadVerbose(pMan) )
diff --git a/src/base/abci/abcFpgaFast.c b/src/base/abci/abcFpgaFast.c
new file mode 100644
index 00000000..356b855e
--- /dev/null
+++ b/src/base/abci/abcFpgaFast.c
@@ -0,0 +1,190 @@
+/**CFile****************************************************************
+
+ FileName [abcFpgaFast.c]
+
+ SystemName [ABC: Logic synthesis and verification system.]
+
+ PackageName [Network and node package.]
+
+ Synopsis [Fast FPGA mapper.]
+
+ Author [Sungmin Cho]
+
+ Affiliation [UC Berkeley]
+
+ Date [Ver. 1.0. Started - June 20, 2005.]
+
+ Revision [$Id: abcFpgaFast.c,v 1.00 2006/09/02 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "abc.h"
+#include "ivy.h"
+
+////////////////////////////////////////////////////////////////////////
+/// DECLARATIONS ///
+////////////////////////////////////////////////////////////////////////
+
+extern Ivy_Man_t * Abc_NtkIvyBefore( Abc_Ntk_t * pNtk, int fSeq, int fUseDc );
+
+static Abc_Ntk_t * Ivy_ManFpgaToAbc( Abc_Ntk_t * pNtk, Ivy_Man_t * pMan );
+static Abc_Obj_t * Ivy_ManToAbcFast_rec( Abc_Ntk_t * pNtkNew, Ivy_Man_t * pMan, Ivy_Obj_t * pObjIvy, Vec_Int_t * vNodes );
+
+static inline void Abc_ObjSetIvy2Abc( Ivy_Man_t * p, int IvyId, Abc_Obj_t * pObjAbc ) { assert(Vec_PtrEntry(p->pCopy, IvyId) == NULL); assert(!Abc_ObjIsComplement(pObjAbc)); Vec_PtrWriteEntry( p->pCopy, IvyId, pObjAbc ); }
+static inline Abc_Obj_t * Abc_ObjGetIvy2Abc( Ivy_Man_t * p, int IvyId ) { return Vec_PtrEntry( p->pCopy, IvyId ); }
+
+////////////////////////////////////////////////////////////////////////
+/// FUNCTION DEFINITIONS ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+ Synopsis [Performs fast FPGA mapping of the network.]
+
+ Description [Takes the AIG to be mapped, the LUT size, and verbosity
+ flag. Produces the new network by fast FPGA mapping of the current
+ network. If the current network in ABC in not an AIG, the user should
+ run command "strash" to make sure that the current network into an AIG
+ before calling this procedure.]
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Abc_Ntk_t * Abc_NtkFpgaFast( Abc_Ntk_t * pNtk, int nLutSize, int fRecovery, int fVerbose )
+{
+ Ivy_Man_t * pMan;
+ Abc_Ntk_t * pNtkNew;
+ // make sure the network is an AIG
+ assert( Abc_NtkIsStrash(pNtk) );
+ // convert the network into the AIG
+ pMan = Abc_NtkIvyBefore( pNtk, 0, 0 );
+ // perform fast FPGA mapping
+ Ivy_FastMapPerform( pMan, nLutSize, fRecovery, fVerbose );
+ // convert back into the ABC network
+ pNtkNew = Ivy_ManFpgaToAbc( pNtk, pMan );
+ Ivy_FastMapStop( pMan );
+ Ivy_ManStop( pMan );
+ // make sure that the final network passes the test
+ if ( pNtkNew != NULL && !Abc_NtkCheck( pNtkNew ) )
+ {
+ printf( "Abc_NtkFastMap: The network check has failed.\n" );
+ Abc_NtkDelete( pNtkNew );
+ return NULL;
+ }
+ return pNtkNew;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Constructs the ABC network after mapping.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Abc_Ntk_t * Ivy_ManFpgaToAbc( Abc_Ntk_t * pNtk, Ivy_Man_t * pMan )
+{
+ Abc_Ntk_t * pNtkNew;
+ Abc_Obj_t * pObjAbc, * pObj;
+ Ivy_Obj_t * pObjIvy;
+ Vec_Int_t * vNodes;
+ int i;
+ // start mapping from Ivy into Abc
+ pMan->pCopy = Vec_PtrStart( Ivy_ManObjIdMax(pMan) + 1 );
+ // start the new ABC network
+ pNtkNew = Abc_NtkStartFrom( pNtk, ABC_NTK_LOGIC, ABC_FUNC_AIG );
+ // transfer the pointers to the basic nodes
+ Abc_ObjSetIvy2Abc( pMan, Ivy_ManConst1(pMan)->Id, Abc_NtkCreateNodeConst1(pNtkNew) );
+ Abc_NtkForEachCi( pNtkNew, pObjAbc, i )
+ Abc_ObjSetIvy2Abc( pMan, Ivy_ManPi(pMan, i)->Id, pObjAbc );
+ // recursively construct the network
+ vNodes = Vec_IntAlloc( 100 );
+ Ivy_ManForEachPo( pMan, pObjIvy, i )
+ {
+ // get the new ABC node corresponding to the old fanin of the PO in IVY
+ pObjAbc = Ivy_ManToAbcFast_rec( pNtkNew, pMan, Ivy_ObjFanin0(pObjIvy), vNodes );
+ // consider the case of complemented fanin of the PO
+ if ( Ivy_ObjFaninC0(pObjIvy) ) // complement
+ {
+ if ( Abc_ObjIsCi(pObjAbc) )
+ pObjAbc = Abc_NtkCreateNodeInv( pNtkNew, pObjAbc );
+ else
+ {
+ // clone the node
+ pObj = Abc_NtkCloneObj( pObjAbc );
+ // set complemented functions
+ pObj->pData = Hop_Not( pObjAbc->pData );
+ // return the new node
+ pObjAbc = pObj;
+ }
+ }
+ Abc_ObjAddFanin( Abc_NtkCo(pNtkNew, i), pObjAbc );
+ }
+ Vec_IntFree( vNodes );
+ Vec_PtrFree( pMan->pCopy );
+ pMan->pCopy = NULL;
+ // remove dangling nodes
+ Abc_NtkCleanup( pNtkNew, 0 );
+ // fix CIs feeding directly into COs
+ Abc_NtkLogicMakeSimpleCos( pNtkNew, 0 );
+ return pNtkNew;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Recursively construct the new node.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Abc_Obj_t * Ivy_ManToAbcFast_rec( Abc_Ntk_t * pNtkNew, Ivy_Man_t * pMan, Ivy_Obj_t * pObjIvy, Vec_Int_t * vNodes )
+{
+ Vec_Int_t Supp, * vSupp = &Supp;
+ Abc_Obj_t * pObjAbc, * pFaninAbc;
+ Ivy_Obj_t * pNodeIvy;
+ int i, Entry;
+ // skip the node if it is a constant or already processed
+ pObjAbc = Abc_ObjGetIvy2Abc( pMan, pObjIvy->Id );
+ if ( pObjAbc )
+ return pObjAbc;
+ assert( Ivy_ObjIsAnd(pObjIvy) || Ivy_ObjIsExor(pObjIvy) );
+ // get the support of K-LUT
+ Ivy_FastMapReadSupp( pMan, pObjIvy, vSupp );
+ // create new ABC node and its fanins
+ pObjAbc = Abc_NtkCreateNode( pNtkNew );
+ Vec_IntForEachEntry( vSupp, Entry, i )
+ {
+ pFaninAbc = Ivy_ManToAbcFast_rec( pNtkNew, pMan, Ivy_ManObj(pMan, Entry), vNodes );
+ Abc_ObjAddFanin( pObjAbc, pFaninAbc );
+ }
+ // collect the nodes used in the cut
+ Ivy_ManCollectCut( pMan, pObjIvy, vSupp, vNodes );
+ // create the local function
+ Ivy_ManForEachNodeVec( pMan, vNodes, pNodeIvy, i )
+ {
+ if ( i < Vec_IntSize(vSupp) )
+ pNodeIvy->pEquiv = (Ivy_Obj_t *)Hop_IthVar( pNtkNew->pManFunc, i );
+ else
+ pNodeIvy->pEquiv = (Ivy_Obj_t *)Hop_And( pNtkNew->pManFunc, (Hop_Obj_t *)Ivy_ObjChild0Equiv(pNodeIvy), (Hop_Obj_t *)Ivy_ObjChild1Equiv(pNodeIvy) );
+ }
+ // set the local function
+ pObjAbc->pData = (Abc_Obj_t *)pObjIvy->pEquiv;
+ // set the node
+ Abc_ObjSetIvy2Abc( pMan, pObjIvy->Id, pObjAbc );
+ return pObjAbc;
+}
+
+////////////////////////////////////////////////////////////////////////
+/// END OF FILE ///
+////////////////////////////////////////////////////////////////////////
+
+
diff --git a/src/base/abci/abcFraig.c b/src/base/abci/abcFraig.c
index a11e6eef..be8a25f1 100644
--- a/src/base/abci/abcFraig.c
+++ b/src/base/abci/abcFraig.c
@@ -26,16 +26,19 @@
/// DECLARATIONS ///
////////////////////////////////////////////////////////////////////////
-extern Fraig_Man_t * Abc_NtkToFraig( Abc_Ntk_t * pNtk, Fraig_Params_t * pParams, int fAllNodes );
-static Abc_Ntk_t * Abc_NtkFromFraig( Fraig_Man_t * pMan, Abc_Ntk_t * pNtk );
-static Abc_Obj_t * Abc_NodeFromFraig_rec( Abc_Ntk_t * pNtkNew, Fraig_Node_t * pNodeFraig );
-
-static int Abc_NtkFraigTrustCheck( Abc_Ntk_t * pNtk );
-static void Abc_NtkFraigTrustOne( Abc_Ntk_t * pNtk, Abc_Ntk_t * pNtkNew );
-static Abc_Obj_t * Abc_NodeFraigTrust( Abc_Aig_t * pMan, Abc_Obj_t * pNode );
+extern Abc_Ntk_t * Abc_NtkFromFraig( Fraig_Man_t * pMan, Abc_Ntk_t * pNtk );
+static Abc_Ntk_t * Abc_NtkFromFraig2( Fraig_Man_t * pMan, Abc_Ntk_t * pNtk );
+static Abc_Obj_t * Abc_NodeFromFraig_rec( Abc_Ntk_t * pNtkNew, Fraig_Node_t * pNodeFraig );
+static void Abc_NtkFromFraig2_rec( Abc_Ntk_t * pNtkNew, Abc_Obj_t * pNode, Vec_Ptr_t * vNodeReprs );
+extern Fraig_Node_t * Abc_NtkToFraigExdc( Fraig_Man_t * pMan, Abc_Ntk_t * pNtkMain, Abc_Ntk_t * pNtkExdc );
+static void Abc_NtkFraigRemapUsingExdc( Fraig_Man_t * pMan, Abc_Ntk_t * pNtk );
+
+static int Abc_NtkFraigTrustCheck( Abc_Ntk_t * pNtk );
+static void Abc_NtkFraigTrustOne( Abc_Ntk_t * pNtk, Abc_Ntk_t * pNtkNew );
+static Abc_Obj_t * Abc_NodeFraigTrust( Abc_Ntk_t * pNtkNew, Abc_Obj_t * pNode );
////////////////////////////////////////////////////////////////////////
-/// FUNCTION DEFITIONS ///
+/// FUNCTION DEFINITIONS ///
////////////////////////////////////////////////////////////////////////
/**Function*************************************************************
@@ -49,19 +52,30 @@ static Abc_Obj_t * Abc_NodeFraigTrust( Abc_Aig_t * pMan, Abc_Obj_t * pNode );
SeeAlso []
***********************************************************************/
-Abc_Ntk_t * Abc_NtkFraig( Abc_Ntk_t * pNtk, void * pParams, int fAllNodes )
+Abc_Ntk_t * Abc_NtkFraig( Abc_Ntk_t * pNtk, void * pParams, int fAllNodes, int fExdc )
{
Fraig_Params_t * pPars = pParams;
Abc_Ntk_t * pNtkNew;
- Fraig_Man_t * pMan;
+ Fraig_Man_t * pMan;
+ // check if EXDC is present
+ if ( fExdc && pNtk->pExdc == NULL )
+ fExdc = 0, printf( "Warning: Networks has no EXDC.\n" );
// perform fraiging
- pMan = Abc_NtkToFraig( pNtk, pParams, fAllNodes );
+ pMan = Abc_NtkToFraig( pNtk, pParams, fAllNodes, fExdc );
+ // add algebraic choices
+// if ( pPars->fChoicing )
+// Fraig_ManAddChoices( pMan, 0, 6 );
// prove the miter if asked to
if ( pPars->fTryProve )
Fraig_ManProveMiter( pMan );
// reconstruct FRAIG in the new network
- pNtkNew = Abc_NtkFromFraig( pMan, pNtk );
+ if ( fExdc )
+ pNtkNew = Abc_NtkFromFraig2( pMan, pNtk );
+ else
+ pNtkNew = Abc_NtkFromFraig( pMan, pNtk );
Fraig_ManFree( pMan );
+ if ( pNtk->pExdc )
+ pNtkNew->pExdc = Abc_NtkDup( pNtk->pExdc );
// make sure that everything is okay
if ( !Abc_NtkCheck( pNtkNew ) )
{
@@ -83,13 +97,13 @@ Abc_Ntk_t * Abc_NtkFraig( Abc_Ntk_t * pNtk, void * pParams, int fAllNodes )
SeeAlso []
***********************************************************************/
-Fraig_Man_t * Abc_NtkToFraig( Abc_Ntk_t * pNtk, Fraig_Params_t * pParams, int fAllNodes )
+void * Abc_NtkToFraig( Abc_Ntk_t * pNtk, void * pParams, int fAllNodes, int fExdc )
{
+ int fInternal = ((Fraig_Params_t *)pParams)->fInternal;
Fraig_Man_t * pMan;
ProgressBar * pProgress;
- Fraig_Node_t * pNodeFraig;
Vec_Ptr_t * vNodes;
- Abc_Obj_t * pNode, * pConst1, * pReset;
+ Abc_Obj_t * pNode;
int i;
assert( Abc_NtkIsStrash(pNtk) );
@@ -97,36 +111,35 @@ Fraig_Man_t * Abc_NtkToFraig( Abc_Ntk_t * pNtk, Fraig_Params_t * pParams, int fA
// create the FRAIG manager
pMan = Fraig_ManCreate( pParams );
- // create PIs and remember them in the old nodes
+ // map the constant node
Abc_NtkCleanCopy( pNtk );
+ Abc_AigConst1(pNtk)->pCopy = (Abc_Obj_t *)Fraig_ManReadConst1(pMan);
+ // create PIs and remember them in the old nodes
Abc_NtkForEachCi( pNtk, pNode, i )
pNode->pCopy = (Abc_Obj_t *)Fraig_ManReadIthVar(pMan, i);
- pConst1 = Abc_AigConst1( pNtk->pManFunc );
- pReset = Abc_AigReset( pNtk->pManFunc );
-
+
// perform strashing
vNodes = Abc_AigDfs( pNtk, fAllNodes, 0 );
- if ( !pParams->fInternal )
+ if ( !fInternal )
pProgress = Extra_ProgressBarStart( stdout, vNodes->nSize );
Vec_PtrForEachEntry( vNodes, pNode, i )
{
- if ( !pParams->fInternal )
- Extra_ProgressBarUpdate( pProgress, i, NULL );
- if ( pNode == pConst1 )
- pNodeFraig = Fraig_ManReadConst1(pMan);
- else if ( pNode == pReset )
+ if ( Abc_ObjFaninNum(pNode) == 0 )
continue;
- else
- pNodeFraig = Fraig_NodeAnd( pMan,
+ if ( !fInternal )
+ Extra_ProgressBarUpdate( pProgress, i, NULL );
+ pNode->pCopy = (Abc_Obj_t *)Fraig_NodeAnd( pMan,
Fraig_NotCond( Abc_ObjFanin0(pNode)->pCopy, Abc_ObjFaninC0(pNode) ),
Fraig_NotCond( Abc_ObjFanin1(pNode)->pCopy, Abc_ObjFaninC1(pNode) ) );
- assert( pNode->pCopy == NULL );
- pNode->pCopy = (Abc_Obj_t *)pNodeFraig;
}
- if ( !pParams->fInternal )
+ if ( !fInternal )
Extra_ProgressBarStop( pProgress );
Vec_PtrFree( vNodes );
+ // use EXDC to change the mapping of nodes into FRAIG nodes
+ if ( fExdc )
+ Abc_NtkFraigRemapUsingExdc( pMan, pNtk );
+
// set the primary outputs
Abc_NtkForEachCo( pNtk, pNode, i )
Fraig_ManSetPo( pMan, (Fraig_Node_t *)Abc_ObjNotCond( Abc_ObjFanin0(pNode)->pCopy, Abc_ObjFaninC0(pNode) ) );
@@ -135,7 +148,123 @@ Fraig_Man_t * Abc_NtkToFraig( Abc_Ntk_t * pNtk, Fraig_Params_t * pParams, int fA
/**Function*************************************************************
- Synopsis [Transforms FRAIG into what looks like a strashed network.]
+ Synopsis [Derives EXDC node for the given network.]
+
+ Description [Assumes that EXDCs of all POs are the same.
+ Returns the EXDC of the first PO.]
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Fraig_Node_t * Abc_NtkToFraigExdc( Fraig_Man_t * pMan, Abc_Ntk_t * pNtkMain, Abc_Ntk_t * pNtkExdc )
+{
+ Abc_Ntk_t * pNtkStrash;
+ Abc_Obj_t * pObj;
+ Fraig_Node_t * gResult;
+ char ** ppNames;
+ int i, k;
+ // strash the EXDC network
+ pNtkStrash = Abc_NtkStrash( pNtkExdc, 0, 0, 0 );
+ Abc_NtkCleanCopy( pNtkStrash );
+ Abc_AigConst1(pNtkStrash)->pCopy = (Abc_Obj_t *)Fraig_ManReadConst1(pMan);
+ // set the mapping of the PI nodes
+ ppNames = Abc_NtkCollectCioNames( pNtkMain, 0 );
+ Abc_NtkForEachCi( pNtkStrash, pObj, i )
+ {
+ for ( k = 0; k < Abc_NtkCiNum(pNtkMain); k++ )
+ if ( strcmp( Abc_ObjName(pObj), ppNames[k] ) == 0 )
+ {
+ pObj->pCopy = (Abc_Obj_t *)Fraig_ManReadIthVar(pMan, k);
+ break;
+ }
+ assert( pObj->pCopy != NULL );
+ }
+ free( ppNames );
+ // build FRAIG for each node
+ Abc_AigForEachAnd( pNtkStrash, pObj, i )
+ pObj->pCopy = (Abc_Obj_t *)Fraig_NodeAnd( pMan,
+ Fraig_NotCond( Abc_ObjFanin0(pObj)->pCopy, Abc_ObjFaninC0(pObj) ),
+ Fraig_NotCond( Abc_ObjFanin1(pObj)->pCopy, Abc_ObjFaninC1(pObj) ) );
+ // get the EXDC to be returned
+ pObj = Abc_NtkPo( pNtkStrash, 0 );
+ gResult = Fraig_NotCond( Abc_ObjFanin0(pObj)->pCopy, Abc_ObjFaninC0(pObj) );
+ Abc_NtkDelete( pNtkStrash );
+ return gResult;
+}
+
+
+/**Function*************************************************************
+
+ Synopsis [Changes mapping of the old nodes into FRAIG nodes using EXDC.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Abc_NtkFraigRemapUsingExdc( Fraig_Man_t * pMan, Abc_Ntk_t * pNtk )
+{
+ Fraig_Node_t * gNodeNew, * gNodeExdc;
+ stmm_table * tTable;
+ stmm_generator * gen;
+ Abc_Obj_t * pNode, * pNodeBest;
+ Abc_Obj_t * pClass, ** ppSlot;
+ Vec_Ptr_t * vNexts;
+ int i;
+
+ // get the global don't-cares
+ assert( pNtk->pExdc );
+ gNodeExdc = Abc_NtkToFraigExdc( pMan, pNtk, pNtk->pExdc );
+
+ // save the next pointers
+ vNexts = Vec_PtrStart( Abc_NtkObjNumMax(pNtk) );
+ Abc_NtkForEachNode( pNtk, pNode, i )
+ Vec_PtrWriteEntry( vNexts, pNode->Id, pNode->pNext );
+
+ // find the classes of AIG nodes which have FRAIG nodes assigned
+ Abc_NtkCleanNext( pNtk );
+ tTable = stmm_init_table(stmm_ptrcmp,stmm_ptrhash);
+ Abc_NtkForEachNode( pNtk, pNode, i )
+ if ( pNode->pCopy )
+ {
+ gNodeNew = Fraig_NodeAnd( pMan, (Fraig_Node_t *)pNode->pCopy, Fraig_Not(gNodeExdc) );
+ if ( !stmm_find_or_add( tTable, (char *)Fraig_Regular(gNodeNew), (char ***)&ppSlot ) )
+ *ppSlot = NULL;
+ pNode->pNext = *ppSlot;
+ *ppSlot = pNode;
+ }
+
+ // for reach non-trival class, find the node with minimum level, and replace other nodes by it
+ Abc_AigSetNodePhases( pNtk );
+ stmm_foreach_item( tTable, gen, (char **)&gNodeNew, (char **)&pClass )
+ {
+ if ( pClass->pNext == NULL )
+ continue;
+ // find the node with minimum level
+ pNodeBest = pClass;
+ for ( pNode = pClass->pNext; pNode; pNode = pNode->pNext )
+ if ( pNodeBest->Level > pNode->Level )
+ pNodeBest = pNode;
+ // remap the class nodes
+ for ( pNode = pClass; pNode; pNode = pNode->pNext )
+ pNode->pCopy = Abc_ObjNotCond( pNodeBest->pCopy, pNode->fPhase ^ pNodeBest->fPhase );
+ }
+ stmm_free_table( tTable );
+
+ // restore the next pointers
+ Abc_NtkCleanNext( pNtk );
+ Abc_NtkForEachNode( pNtk, pNode, i )
+ pNode->pNext = Vec_PtrEntry( vNexts, pNode->Id );
+ Vec_PtrFree( vNexts );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Transforms FRAIG into strashed network with choices.]
Description []
@@ -146,26 +275,27 @@ Fraig_Man_t * Abc_NtkToFraig( Abc_Ntk_t * pNtk, Fraig_Params_t * pParams, int fA
***********************************************************************/
Abc_Ntk_t * Abc_NtkFromFraig( Fraig_Man_t * pMan, Abc_Ntk_t * pNtk )
{
-// ProgressBar * pProgress;
+ ProgressBar * pProgress;
Abc_Ntk_t * pNtkNew;
Abc_Obj_t * pNode, * pNodeNew;
int i;
// create the new network
- pNtkNew = Abc_NtkStartFrom( pNtk, ABC_TYPE_STRASH, ABC_FUNC_AIG );
+ pNtkNew = Abc_NtkStartFrom( pNtk, ABC_NTK_STRASH, ABC_FUNC_AIG );
// make the mapper point to the new network
Abc_NtkForEachCi( pNtk, pNode, i )
Fraig_NodeSetData1( Fraig_ManReadIthVar(pMan, i), (Fraig_Node_t *)pNode->pCopy );
// set the constant node
- Fraig_NodeSetData1( Fraig_ManReadConst1(pMan), (Fraig_Node_t *)Abc_AigConst1(pNtkNew->pManFunc) );
+ Fraig_NodeSetData1( Fraig_ManReadConst1(pMan), (Fraig_Node_t *)Abc_AigConst1(pNtkNew) );
// process the nodes in topological order
-// pProgress = Extra_ProgressBarStart( stdout, Abc_NtkCoNum(pNtk) );
+ pProgress = Extra_ProgressBarStart( stdout, Abc_NtkCoNum(pNtk) );
Abc_NtkForEachCo( pNtk, pNode, i )
{
-// Extra_ProgressBarUpdate( pProgress, i, NULL );
+ Extra_ProgressBarUpdate( pProgress, i, NULL );
pNodeNew = Abc_NodeFromFraig_rec( pNtkNew, Fraig_ManReadOutputs(pMan)[i] );
Abc_ObjAddFanin( pNode->pCopy, pNodeNew );
}
-// Extra_ProgressBarStop( pProgress );
+ Extra_ProgressBarStop( pProgress );
+ Abc_NtkReassignIds( pNtkNew );
return pNtkNew;
}
@@ -232,6 +362,109 @@ Abc_Obj_t * Abc_NodeFromFraig_rec( Abc_Ntk_t * pNtkNew, Fraig_Node_t * pNodeFrai
return Abc_ObjNotCond( pRes, Fraig_IsComplement(pNodeFraig) );
}
+/**Function*************************************************************
+
+ Synopsis [Transforms FRAIG into strashed network without choices.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Abc_Ntk_t * Abc_NtkFromFraig2( Fraig_Man_t * pMan, Abc_Ntk_t * pNtk )
+{
+ ProgressBar * pProgress;
+ stmm_table * tTable;
+ Vec_Ptr_t * vNodeReprs;
+ Abc_Ntk_t * pNtkNew;
+ Abc_Obj_t * pNode, * pRepr, ** ppSlot;
+ int i;
+
+ // map the nodes into their lowest level representives
+ tTable = stmm_init_table(stmm_ptrcmp,stmm_ptrhash);
+ pNode = Abc_AigConst1(pNtk);
+ if ( !stmm_find_or_add( tTable, (char *)Fraig_Regular(pNode->pCopy), (char ***)&ppSlot ) )
+ *ppSlot = pNode;
+ Abc_NtkForEachCi( pNtk, pNode, i )
+ if ( !stmm_find_or_add( tTable, (char *)Fraig_Regular(pNode->pCopy), (char ***)&ppSlot ) )
+ *ppSlot = pNode;
+ Abc_NtkForEachNode( pNtk, pNode, i )
+ if ( pNode->pCopy )
+ {
+ if ( !stmm_find_or_add( tTable, (char *)Fraig_Regular(pNode->pCopy), (char ***)&ppSlot ) )
+ *ppSlot = pNode;
+ else if ( (*ppSlot)->Level > pNode->Level )
+ *ppSlot = pNode;
+ }
+ // save representatives for each node
+ vNodeReprs = Vec_PtrStart( Abc_NtkObjNumMax(pNtk) );
+ Abc_NtkForEachNode( pNtk, pNode, i )
+ if ( pNode->pCopy )
+ {
+ if ( !stmm_lookup( tTable, (char *)Fraig_Regular(pNode->pCopy), (char **)&pRepr ) )
+ assert( 0 );
+ if ( pNode != pRepr )
+ Vec_PtrWriteEntry( vNodeReprs, pNode->Id, pRepr );
+ }
+ stmm_free_table( tTable );
+
+ // create the new network
+ pNtkNew = Abc_NtkStartFrom( pNtk, ABC_NTK_STRASH, ABC_FUNC_AIG );
+
+ // perform strashing
+ Abc_AigSetNodePhases( pNtk );
+ Abc_NtkIncrementTravId( pNtk );
+ pProgress = Extra_ProgressBarStart( stdout, Abc_NtkCoNum(pNtk) );
+ Abc_NtkForEachCo( pNtk, pNode, i )
+ {
+ Extra_ProgressBarUpdate( pProgress, i, NULL );
+ Abc_NtkFromFraig2_rec( pNtkNew, Abc_ObjFanin0(pNode), vNodeReprs );
+ }
+ Extra_ProgressBarStop( pProgress );
+ Vec_PtrFree( vNodeReprs );
+
+ // finalize the network
+ Abc_NtkFinalize( pNtk, pNtkNew );
+ return pNtkNew;
+}
+
+
+/**Function*************************************************************
+
+ Synopsis [Transforms into AIG one node.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Abc_NtkFromFraig2_rec( Abc_Ntk_t * pNtkNew, Abc_Obj_t * pNode, Vec_Ptr_t * vNodeReprs )
+{
+ Abc_Obj_t * pRepr;
+ // skip the PIs and constants
+ if ( Abc_ObjFaninNum(pNode) < 2 )
+ return;
+ // if this node is already visited, skip
+ if ( Abc_NodeIsTravIdCurrent( pNode ) )
+ return;
+ // mark the node as visited
+ Abc_NodeSetTravIdCurrent( pNode );
+ assert( Abc_ObjIsNode( pNode ) );
+ // get the node's representative
+ if ( pRepr = Vec_PtrEntry(vNodeReprs, pNode->Id) )
+ {
+ Abc_NtkFromFraig2_rec( pNtkNew, pRepr, vNodeReprs );
+ pNode->pCopy = Abc_ObjNotCond( pRepr->pCopy, pRepr->fPhase ^ pNode->fPhase );
+ return;
+ }
+ Abc_NtkFromFraig2_rec( pNtkNew, Abc_ObjFanin0(pNode), vNodeReprs );
+ Abc_NtkFromFraig2_rec( pNtkNew, Abc_ObjFanin1(pNode), vNodeReprs );
+ pNode->pCopy = Abc_AigAnd( pNtkNew->pManFunc, Abc_ObjChild0Copy(pNode), Abc_ObjChild1Copy(pNode) );
+}
@@ -263,9 +496,10 @@ Abc_Ntk_t * Abc_NtkFraigTrust( Abc_Ntk_t * pNtk )
}
// perform strashing
- pNtkNew = Abc_NtkStartFrom( pNtk, ABC_TYPE_STRASH, ABC_FUNC_AIG );
+ pNtkNew = Abc_NtkStartFrom( pNtk, ABC_NTK_STRASH, ABC_FUNC_AIG );
Abc_NtkFraigTrustOne( pNtk, pNtkNew );
Abc_NtkFinalize( pNtk, pNtkNew );
+ Abc_NtkReassignIds( pNtkNew );
// print a warning about choice nodes
printf( "Warning: The resulting AIG contains %d choice nodes.\n", Abc_NtkGetChoiceNum( pNtkNew ) );
@@ -322,7 +556,6 @@ int Abc_NtkFraigTrustCheck( Abc_Ntk_t * pNtk )
void Abc_NtkFraigTrustOne( Abc_Ntk_t * pNtk, Abc_Ntk_t * pNtkNew )
{
ProgressBar * pProgress;
- Abc_Aig_t * pMan = pNtkNew->pManFunc;
Vec_Ptr_t * vNodes;
Abc_Obj_t * pNode, * pNodeNew, * pObj;
int i;
@@ -336,7 +569,7 @@ void Abc_NtkFraigTrustOne( Abc_Ntk_t * pNtk, Abc_Ntk_t * pNtkNew )
// get the node
assert( Abc_ObjIsNode(pNode) );
// strash the node
- pNodeNew = Abc_NodeFraigTrust( pMan, pNode );
+ pNodeNew = Abc_NodeFraigTrust( pNtkNew, pNode );
// get the old object
if ( Abc_NtkIsNetlist(pNtk) )
pObj = Abc_ObjFanout0( pNode ); // the fanout net
@@ -362,10 +595,9 @@ void Abc_NtkFraigTrustOne( Abc_Ntk_t * pNtk, Abc_Ntk_t * pNtkNew )
SeeAlso []
***********************************************************************/
-Abc_Obj_t * Abc_NodeFraigTrust( Abc_Aig_t * pMan, Abc_Obj_t * pNode )
+Abc_Obj_t * Abc_NodeFraigTrust( Abc_Ntk_t * pNtkNew, Abc_Obj_t * pNode )
{
Abc_Obj_t * pSum, * pFanin;
- Abc_Obj_t * pConst1 = Abc_AigConst1(pMan);
void ** ppTail;
int i, nFanins, fCompl;
@@ -375,11 +607,11 @@ Abc_Obj_t * Abc_NodeFraigTrust( Abc_Aig_t * pMan, Abc_Obj_t * pNode )
assert( nFanins == Abc_SopGetVarNum(pNode->pData) );
// check if it is a constant
if ( nFanins == 0 )
- return Abc_ObjNotCond( pConst1, Abc_SopIsConst0(pNode->pData) );
+ return Abc_ObjNotCond( Abc_AigConst1(pNtkNew), Abc_SopIsConst0(pNode->pData) );
if ( nFanins == 1 )
return Abc_ObjNotCond( Abc_ObjFanin0(pNode)->pCopy, Abc_SopIsInv(pNode->pData) );
if ( nFanins == 2 && Abc_SopIsAndType(pNode->pData) )
- return Abc_AigAnd( pMan,
+ return Abc_AigAnd( pNtkNew->pManFunc,
Abc_ObjNotCond( Abc_ObjFanin0(pNode)->pCopy, !Abc_SopGetIthCareLit(pNode->pData,0) ),
Abc_ObjNotCond( Abc_ObjFanin1(pNode)->pCopy, !Abc_SopGetIthCareLit(pNode->pData,1) ) );
assert( Abc_SopIsOrType(pNode->pData) );
@@ -416,49 +648,32 @@ Abc_Obj_t * Abc_NodeFraigTrust( Abc_Aig_t * pMan, Abc_Obj_t * pNode )
SeeAlso []
***********************************************************************/
-int Abc_NtkFraigStore( Abc_Ntk_t * pNtk )
+int Abc_NtkFraigStore( Abc_Ntk_t * pNtkAdd )
{
- extern int Abc_NtkAppendNew( Abc_Ntk_t * pNtk1, Abc_Ntk_t * pNtk2 );
-
- Abc_Ntk_t * pStore;
- int nAndsOld;
-
- if ( !Abc_NtkIsLogic(pNtk) && !Abc_NtkIsStrash(pNtk) )
+ Vec_Ptr_t * vStore;
+ Abc_Ntk_t * pNtk;
+ // create the network to be stored
+ pNtk = Abc_NtkStrash( pNtkAdd, 0, 0, 0 );
+ if ( pNtk == NULL )
{
- printf( "The netlist need to be converted into a logic network before adding it to storage.\n" );
+ printf( "Abc_NtkFraigStore: Initial strashing has failed.\n" );
return 0;
}
-
// get the network currently stored
- pStore = Abc_FrameReadNtkStore();
- if ( pStore == NULL )
+ vStore = Abc_FrameReadStore();
+ if ( Vec_PtrSize(vStore) > 0 )
{
- // start the stored network
- pStore = Abc_NtkStrash( pNtk, 0, 0 );
- if ( pStore == NULL )
+ // check that the networks have the same PIs
+ // reorder PIs of pNtk2 according to pNtk1
+ if ( !Abc_NtkCompareSignals( pNtk, Vec_PtrEntry(vStore, 0), 1, 1 ) )
{
- printf( "Abc_NtkFraigStore: Initial strashing has failed.\n" );
- return 0;
+ printf( "Trying to store the network with different primary inputs.\n" );
+ printf( "The previously stored networks are deleted and this one is added.\n" );
+ Abc_NtkFraigStoreClean();
}
- // save the parameters
- Abc_FrameSetNtkStore( pStore );
- Abc_FrameSetNtkStoreSize( 1 );
- nAndsOld = 0;
}
- else
- {
- // add the new network to storage
- nAndsOld = Abc_NtkNodeNum( pStore );
-// if ( !Abc_NtkAppend( pStore, pNtk ) )
- if ( !Abc_NtkAppendNew( pStore, pNtk ) )
- {
- printf( "The current network cannot be appended to the stored network.\n" );
- return 0;
- }
- // set the number of networks stored
- Abc_FrameSetNtkStoreSize( Abc_FrameReadNtkStoreSize() + 1 );
- }
- printf( "The number of AIG nodes added to storage = %5d.\n", Abc_NtkNodeNum(pStore) - nAndsOld );
+ Vec_PtrPush( vStore, pNtk );
+// printf( "The number of AIG nodes added to storage = %5d.\n", Abc_NtkNodeNum(pNtk) );
return 1;
}
@@ -475,56 +690,54 @@ int Abc_NtkFraigStore( Abc_Ntk_t * pNtk )
***********************************************************************/
Abc_Ntk_t * Abc_NtkFraigRestore()
{
- extern Abc_Ntk_t * Abc_NtkFraigPartitioned( Abc_Ntk_t * pNtk, void * pParams );
-
+ extern Abc_Ntk_t * Abc_NtkFraigPartitioned( Vec_Ptr_t * vStore, void * pParams );
Fraig_Params_t Params;
- Abc_Ntk_t * pStore, * pFraig;
+ Vec_Ptr_t * vStore;
+ Abc_Ntk_t * pNtk, * pFraig;
int nWords1, nWords2, nWordsMin;
int clk = clock();
// get the stored network
- pStore = Abc_FrameReadNtkStore();
- Abc_FrameSetNtkStore( NULL );
- if ( pStore == NULL )
+ vStore = Abc_FrameReadStore();
+ if ( Vec_PtrSize(vStore) == 0 )
{
printf( "There are no network currently in storage.\n" );
return NULL;
}
- printf( "Currently stored %d networks with %d nodes will be fraiged.\n",
- Abc_FrameReadNtkStoreSize(), Abc_NtkNodeNum(pStore) );
+// printf( "Currently stored %d networks will be fraiged.\n", Vec_PtrSize(vStore) );
+ pNtk = Vec_PtrEntry( vStore, 0 );
+
+ // swap the first and last network
+ // this should lead to the primary choice being "better" because of synthesis
+ pNtk = Vec_PtrPop( vStore );
+ Vec_PtrPush( vStore, Vec_PtrEntry(vStore,0) );
+ Vec_PtrWriteEntry( vStore, 0, pNtk );
// to determine the number of simulation patterns
// use the following strategy
// at least 64 words (32 words random and 32 words dynamic)
// no more than 256M for one circuit (128M + 128M)
nWords1 = 32;
- nWords2 = (1<<27) / (Abc_NtkNodeNum(pStore) + Abc_NtkCiNum(pStore));
+ nWords2 = (1<<27) / (Abc_NtkNodeNum(pNtk) + Abc_NtkCiNum(pNtk));
nWordsMin = ABC_MIN( nWords1, nWords2 );
// set parameters for fraiging
Fraig_ParamsSetDefault( &Params );
- Params.nPatsRand = nWordsMin * 32; // the number of words of random simulation info
- Params.nPatsDyna = nWordsMin * 32; // the number of words of dynamic simulation info
-// Params.nBTLimit = 99; // the max number of backtracks to perform
- Params.nBTLimit = 1000000; // the max number of backtracks to perform
- Params.fFuncRed = 1; // performs only one level hashing
- Params.fFeedBack = 1; // enables solver feedback
- Params.fDist1Pats = 1; // enables distance-1 patterns
- Params.fDoSparse = 1; // performs equiv tests for sparse functions
- Params.fChoicing = 1; // enables recording structural choices
- Params.fTryProve = 0; // tries to solve the final miter
- Params.fVerbose = 0; // the verbosiness flag
- Params.fInternal = 1; // the flag indicates the internal run
-
-// Fraig_ManReportChoices( p );
- // transform it into FRAIG
-// pFraig = Abc_NtkFraig( pStore, &Params, 1 );
- pFraig = Abc_NtkFraigPartitioned( pStore, &Params );
-
-PRT( "Total fraiging time", clock() - clk );
- if ( pFraig == NULL )
- return NULL;
- Abc_NtkDelete( pStore );
+ Params.nPatsRand = nWordsMin * 32; // the number of words of random simulation info
+ Params.nPatsDyna = nWordsMin * 32; // the number of words of dynamic simulation info
+ Params.nBTLimit = 1000; // the max number of backtracks to perform
+ Params.fFuncRed = 1; // performs only one level hashing
+ Params.fFeedBack = 1; // enables solver feedback
+ Params.fDist1Pats = 1; // enables distance-1 patterns
+ Params.fDoSparse = 1; // performs equiv tests for sparse functions
+ Params.fChoicing = 1; // enables recording structural choices
+ Params.fTryProve = 0; // tries to solve the final miter
+ Params.fVerbose = 0; // the verbosiness flag
+
+ // perform partitioned computation of structural choices
+ pFraig = Abc_NtkFraigPartitioned( vStore, &Params );
+ Abc_NtkFraigStoreClean();
+//PRT( "Total choicing time", clock() - clk );
return pFraig;
}
@@ -541,12 +754,13 @@ PRT( "Total fraiging time", clock() - clk );
***********************************************************************/
void Abc_NtkFraigStoreClean()
{
- Abc_Ntk_t * pStore;
- // get the stored network
- pStore = Abc_FrameReadNtkStore();
- if ( pStore )
- Abc_NtkDelete( pStore );
- Abc_FrameSetNtkStore( NULL );
+ Vec_Ptr_t * vStore;
+ Abc_Ntk_t * pNtk;
+ int i;
+ vStore = Abc_FrameReadStore();
+ Vec_PtrForEachEntry( vStore, pNtk, i )
+ Abc_NtkDelete( pNtk );
+ Vec_PtrClear( vStore );
}
/**Function*************************************************************
@@ -567,7 +781,7 @@ void Abc_NtkFraigStoreCheck( Abc_Ntk_t * pFraig )
int i, k;
// check that the PO functions are correct
nPoFinal = Abc_NtkPoNum(pFraig);
- nStored = Abc_FrameReadNtkStoreSize(Abc_FrameGetGlobalFrame());
+ nStored = Abc_FrameReadStoreSize();
assert( nPoFinal % nStored == 0 );
nPoOrig = nPoFinal / nStored;
for ( i = 0; i < nPoOrig; i++ )
diff --git a/src/base/abci/abcFxu.c b/src/base/abci/abcFxu.c
index 3a70862f..45515dd1 100644
--- a/src/base/abci/abcFxu.c
+++ b/src/base/abci/abcFxu.c
@@ -30,7 +30,7 @@ static void Abc_NtkFxuCollectInfo( Abc_Ntk_t * pNtk, Fxu_Data_t * p );
static void Abc_NtkFxuReconstruct( Abc_Ntk_t * pNtk, Fxu_Data_t * p );
////////////////////////////////////////////////////////////////////////
-/// FUNCTION DEFITIONS ///
+/// FUNCTION DEFINITIONS ///
////////////////////////////////////////////////////////////////////////
@@ -53,16 +53,19 @@ static void Abc_NtkFxuReconstruct( Abc_Ntk_t * pNtk, Fxu_Data_t * p );
bool Abc_NtkFastExtract( Abc_Ntk_t * pNtk, Fxu_Data_t * p )
{
assert( Abc_NtkIsLogic(pNtk) );
- // convert nodes to SOPs
- if ( Abc_NtkIsMappedLogic(pNtk) )
- Abc_NtkUnmap(pNtk);
- else if ( Abc_NtkIsBddLogic(pNtk) )
- Abc_NtkBddToSop(pNtk);
- else
+ // if the network is already in the SOP form, it may come from BLIF file
+ // and it may not be SCC-free, in which case FXU will not work correctly
+ if ( Abc_NtkIsSopLogic(pNtk) )
{ // to make sure the SOPs are SCC-free
// Abc_NtkSopToBdd(pNtk);
// Abc_NtkBddToSop(pNtk);
}
+ // get the network in the SOP form
+ if ( !Abc_NtkToSop(pNtk, 0) )
+ {
+ printf( "Abc_NtkFastExtract(): Converting to SOPs has failed.\n" );
+ return 0;
+ }
// check if the network meets the requirements
if ( !Abc_NtkFxuCheck(pNtk) )
{
@@ -108,7 +111,7 @@ bool Abc_NtkFxuCheck( Abc_Ntk_t * pNtk )
{
Abc_ObjForEachFanin( pNode, pFanin1, i )
{
- if ( Abc_ObjFaninC(pNode, i) )
+ if ( i < 2 && Abc_ObjFaninC(pNode, i) )
return 0;
Abc_ObjForEachFanin( pNode, pFanin2, k )
{
diff --git a/src/base/abci/abcGen.c b/src/base/abci/abcGen.c
new file mode 100644
index 00000000..bfb41374
--- /dev/null
+++ b/src/base/abci/abcGen.c
@@ -0,0 +1,511 @@
+/**CFile****************************************************************
+
+ FileName [abc_.c]
+
+ SystemName [ABC: Logic synthesis and verification system.]
+
+ PackageName [Network and node package.]
+
+ Synopsis []
+
+ Author [Alan Mishchenko]
+
+ Affiliation [UC Berkeley]
+
+ Date [Ver. 1.0. Started - June 20, 2005.]
+
+ Revision [$Id: abc_.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "abc.h"
+
+////////////////////////////////////////////////////////////////////////
+/// DECLARATIONS ///
+////////////////////////////////////////////////////////////////////////
+
+void Abc_WriteLayer( FILE * pFile, int nVars, int fSkip1 );
+void Abc_WriteComp( FILE * pFile );
+void Abc_WriteFullAdder( FILE * pFile );
+
+void Abc_GenAdder( char * pFileName, int nVars );
+void Abc_GenSorter( char * pFileName, int nVars );
+
+////////////////////////////////////////////////////////////////////////
+/// FUNCTION DEFINITIONS ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Abc_GenAdder( char * pFileName, int nVars )
+{
+ FILE * pFile;
+ int i;
+
+ assert( nVars > 0 );
+
+ pFile = fopen( pFileName, "w" );
+ fprintf( pFile, "# %d-bit ripple-carry adder generated by ABC on %s\n", nVars, Extra_TimeStamp() );
+ fprintf( pFile, ".model Adder%02d\n", nVars );
+
+ fprintf( pFile, ".inputs" );
+ for ( i = 0; i < nVars; i++ )
+ fprintf( pFile, " a%02d", i );
+ for ( i = 0; i < nVars; i++ )
+ fprintf( pFile, " b%02d", i );
+ fprintf( pFile, "\n" );
+
+ fprintf( pFile, ".outputs" );
+ for ( i = 0; i <= nVars; i++ )
+ fprintf( pFile, " y%02d", i );
+ fprintf( pFile, "\n" );
+
+ fprintf( pFile, ".names c\n" );
+ if ( nVars == 1 )
+ fprintf( pFile, ".subckt FA a=a00 b=b00 cin=c s=y00 cout=y01\n" );
+ else
+ {
+ fprintf( pFile, ".subckt FA a=a00 b=b00 cin=c s=y00 cout=%02d\n", 0 );
+ for ( i = 1; i < nVars-1; i++ )
+ fprintf( pFile, ".subckt FA a=a%02d b=b%02d cin=%02d s=y%02d cout=%02d\n", i, i, i-1, i, i );
+ fprintf( pFile, ".subckt FA a=a%02d b=b%02d cin=%02d s=y%02d cout=y%02d\n", i, i, i-1, i, i+1 );
+ }
+ fprintf( pFile, ".end\n" );
+ fprintf( pFile, "\n" );
+
+ Abc_WriteFullAdder( pFile );
+ fclose( pFile );
+}
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Abc_GenSorter( char * pFileName, int nVars )
+{
+ FILE * pFile;
+ int i, k, Counter, nDigits;
+
+ assert( nVars > 1 );
+
+ pFile = fopen( pFileName, "w" );
+ fprintf( pFile, "# %d-bit sorter generated by ABC on %s\n", nVars, Extra_TimeStamp() );
+ fprintf( pFile, ".model Sorter%02d\n", nVars );
+
+ fprintf( pFile, ".inputs" );
+ for ( i = 0; i < nVars; i++ )
+ fprintf( pFile, " x%02d", i );
+ fprintf( pFile, "\n" );
+
+ fprintf( pFile, ".outputs" );
+ for ( i = 0; i < nVars; i++ )
+ fprintf( pFile, " y%02d", i );
+ fprintf( pFile, "\n" );
+
+ Counter = 0;
+ nDigits = Extra_Base10Log( (nVars-2)*nVars );
+ if ( nVars == 2 )
+ fprintf( pFile, ".subckt Comp a=x00 b=x01 x=y00 y=y01\n" );
+ else
+ {
+ fprintf( pFile, ".subckt Layer0" );
+ for ( k = 0; k < nVars; k++ )
+ fprintf( pFile, " x%02d=x%02d", k, k );
+ for ( k = 0; k < nVars; k++ )
+ fprintf( pFile, " y%02d=%0*d", k, nDigits, Counter++ );
+ fprintf( pFile, "\n" );
+ Counter -= nVars;
+ for ( i = 1; i < nVars-2; i++ )
+ {
+ fprintf( pFile, ".subckt Layer%d", (i&1) );
+ for ( k = 0; k < nVars; k++ )
+ fprintf( pFile, " x%02d=%0*d", k, nDigits, Counter++ );
+ for ( k = 0; k < nVars; k++ )
+ fprintf( pFile, " y%02d=%0*d", k, nDigits, Counter++ );
+ fprintf( pFile, "\n" );
+ Counter -= nVars;
+ }
+ fprintf( pFile, ".subckt Layer%d", (i&1) );
+ for ( k = 0; k < nVars; k++ )
+ fprintf( pFile, " x%02d=%0*d", k, nDigits, Counter++ );
+ for ( k = 0; k < nVars; k++ )
+ fprintf( pFile, " y%02d=y%02d", k, k );
+ fprintf( pFile, "\n" );
+ }
+ fprintf( pFile, ".end\n" );
+ fprintf( pFile, "\n" );
+
+ Abc_WriteLayer( pFile, nVars, 0 );
+ Abc_WriteLayer( pFile, nVars, 1 );
+ Abc_WriteComp( pFile );
+ fclose( pFile );
+}
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Abc_WriteLayer( FILE * pFile, int nVars, int fSkip1 )
+{
+ int i;
+ fprintf( pFile, ".model Layer%d\n", fSkip1 );
+ fprintf( pFile, ".inputs" );
+ for ( i = 0; i < nVars; i++ )
+ fprintf( pFile, " x%02d", i );
+ fprintf( pFile, "\n" );
+ fprintf( pFile, ".outputs" );
+ for ( i = 0; i < nVars; i++ )
+ fprintf( pFile, " y%02d", i );
+ fprintf( pFile, "\n" );
+ if ( fSkip1 )
+ {
+ fprintf( pFile, ".names x00 y00\n" );
+ fprintf( pFile, "1 1\n" );
+ i = 1;
+ }
+ else
+ i = 0;
+ for ( ; i + 1 < nVars; i += 2 )
+ fprintf( pFile, ".subckt Comp a=x%02d b=x%02d x=y%02d y=y%02d\n", i, i+1, i, i+1 );
+ if ( i < nVars )
+ {
+ fprintf( pFile, ".names x%02d y%02d\n", i, i );
+ fprintf( pFile, "1 1\n" );
+ }
+ fprintf( pFile, ".end\n" );
+ fprintf( pFile, "\n" );
+}
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Abc_WriteComp( FILE * pFile )
+{
+ fprintf( pFile, ".model Comp\n" );
+ fprintf( pFile, ".inputs a b\n" );
+ fprintf( pFile, ".outputs x y\n" );
+ fprintf( pFile, ".names a b x\n" );
+ fprintf( pFile, "11 1\n" );
+ fprintf( pFile, ".names a b y\n" );
+ fprintf( pFile, "1- 1\n" );
+ fprintf( pFile, "-1 1\n" );
+ fprintf( pFile, ".end\n" );
+ fprintf( pFile, "\n" );
+}
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Abc_WriteFullAdder( FILE * pFile )
+{
+ fprintf( pFile, ".model FA\n" );
+ fprintf( pFile, ".inputs a b cin\n" );
+ fprintf( pFile, ".outputs s cout\n" );
+ fprintf( pFile, ".names a b k\n" );
+ fprintf( pFile, "10 1\n" );
+ fprintf( pFile, "01 1\n" );
+ fprintf( pFile, ".names k cin s\n" );
+ fprintf( pFile, "10 1\n" );
+ fprintf( pFile, "01 1\n" );
+ fprintf( pFile, ".names a b cin cout\n" );
+ fprintf( pFile, "11- 1\n" );
+ fprintf( pFile, "1-1 1\n" );
+ fprintf( pFile, "-11 1\n" );
+ fprintf( pFile, ".end\n" );
+ fprintf( pFile, "\n" );
+}
+
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Abc_WriteCell( FILE * pFile )
+{
+ fprintf( pFile, ".model cell\n" );
+ fprintf( pFile, ".inputs px1 px2 py1 py2 x y\n" );
+ fprintf( pFile, ".outputs fx fy\n" );
+ fprintf( pFile, ".names x y a\n" );
+ fprintf( pFile, "11 1\n" );
+ fprintf( pFile, ".names px1 a x nx\n" );
+ fprintf( pFile, "11- 1\n" );
+ fprintf( pFile, "0-1 1\n" );
+ fprintf( pFile, ".names py1 a y ny\n" );
+ fprintf( pFile, "11- 1\n" );
+ fprintf( pFile, "0-1 1\n" );
+ fprintf( pFile, ".names px2 nx fx\n" );
+ fprintf( pFile, "10 1\n" );
+ fprintf( pFile, "01 1\n" );
+ fprintf( pFile, ".names py2 ny fy\n" );
+ fprintf( pFile, "10 1\n" );
+ fprintf( pFile, "01 1\n" );
+ fprintf( pFile, ".end\n" );
+ fprintf( pFile, "\n" );
+}
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Abc_GenMesh( char * pFileName, int nVars )
+{
+ FILE * pFile;
+ int i, k;
+
+ assert( nVars > 0 );
+
+ pFile = fopen( pFileName, "w" );
+ fprintf( pFile, "# %dx%d mesh generated by ABC on %s\n", nVars, nVars, Extra_TimeStamp() );
+ fprintf( pFile, ".model mesh%d\n", nVars );
+
+ for ( i = 0; i < nVars; i++ )
+ for ( k = 0; k < nVars; k++ )
+ {
+ fprintf( pFile, ".inputs" );
+ fprintf( pFile, " p%d%dx1", i, k );
+ fprintf( pFile, " p%d%dx2", i, k );
+ fprintf( pFile, " p%d%dy1", i, k );
+ fprintf( pFile, " p%d%dy2", i, k );
+ fprintf( pFile, "\n" );
+ }
+ fprintf( pFile, ".inputs" );
+ for ( i = 0; i < nVars; i++ )
+ fprintf( pFile, " v%02d v%02d", 2*i, 2*i+1 );
+ fprintf( pFile, "\n" );
+
+ fprintf( pFile, ".outputs" );
+ fprintf( pFile, " fx00" );
+ fprintf( pFile, "\n" );
+
+ for ( i = 0; i < nVars; i++ ) // horizontal
+ for ( k = 0; k < nVars; k++ ) // vertical
+ {
+ fprintf( pFile, ".subckt cell" );
+ fprintf( pFile, " px1=p%d%dx1", i, k );
+ fprintf( pFile, " px2=p%d%dx2", i, k );
+ fprintf( pFile, " py1=p%d%dy1", i, k );
+ fprintf( pFile, " py2=p%d%dy2", i, k );
+ if ( k == nVars - 1 )
+ fprintf( pFile, " x=v%02d", i );
+ else
+ fprintf( pFile, " x=fx%d%d", i, k+1 );
+ if ( i == nVars - 1 )
+ fprintf( pFile, " y=v%02d", nVars+k );
+ else
+ fprintf( pFile, " y=fy%d%d", i+1, k );
+ // outputs
+ fprintf( pFile, " fx=fx%d%d", i, k );
+ fprintf( pFile, " fy=fy%d%d", i, k );
+ fprintf( pFile, "\n" );
+ }
+ fprintf( pFile, ".end\n" );
+ fprintf( pFile, "\n" );
+ fprintf( pFile, "\n" );
+
+ Abc_WriteCell( pFile );
+ fclose( pFile );
+}
+
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Abc_WriteKLut( FILE * pFile, int nLutSize )
+{
+ int i, iVar, iNext, nPars = (1 << nLutSize);
+ fprintf( pFile, "\n" );
+ fprintf( pFile, ".model lut%d\n", nLutSize );
+ fprintf( pFile, ".inputs" );
+ for ( i = 0; i < nPars; i++ )
+ fprintf( pFile, " p%02d", i );
+ fprintf( pFile, "\n" );
+ fprintf( pFile, ".inputs" );
+ for ( i = 0; i < nLutSize; i++ )
+ fprintf( pFile, " i%d", i );
+ fprintf( pFile, "\n" );
+ fprintf( pFile, ".outputs o\n" );
+ fprintf( pFile, ".names n01 o\n" );
+ fprintf( pFile, "1 1\n" );
+ // write internal MUXes
+ iVar = 0;
+ iNext = 2;
+ for ( i = 1; i < nPars; i++ )
+ {
+ if ( i == iNext )
+ {
+ iNext *= 2;
+ iVar++;
+ }
+ if ( iVar == nLutSize - 1 )
+ fprintf( pFile, ".names i%d p%02d p%02d n%02d\n", iVar, 2*(i-nPars/2), 2*(i-nPars/2)+1, i );
+ else
+ fprintf( pFile, ".names i%d n%02d n%02d n%02d\n", iVar, 2*i, 2*i+1, i );
+ fprintf( pFile, "01- 1\n" );
+ fprintf( pFile, "1-1 1\n" );
+ }
+ fprintf( pFile, ".end\n" );
+ fprintf( pFile, "\n" );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Generates structure of L K-LUTs implementing an N-var function.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Abc_GenFpga( char * pFileName, int nLutSize, int nLuts, int nVars )
+{
+ FILE * pFile;
+ int nVarsLut = (1 << nLutSize); // the number of LUT variables
+ int nVarsLog = Extra_Base2Log( nVars + nLuts - 1 ); // the number of encoding vars
+ int nVarsDeg = (1 << nVarsLog); // the number of LUT variables (total)
+ int nParsLut = nLuts * (1 << nLutSize); // the number of LUT params
+ int nParsVar = nLuts * nLutSize * nVarsLog; // the number of var params
+ int i, j, k;
+
+ assert( nVars > 0 );
+
+ pFile = fopen( pFileName, "w" );
+ fprintf( pFile, "# Structure with %d %d-LUTs for %d-var function generated by ABC on %s\n", nLuts, nLutSize, nVars, Extra_TimeStamp() );
+ fprintf( pFile, ".model struct%dx%d_%d\n", nLuts, nLutSize, nVars );
+
+ fprintf( pFile, ".inputs" );
+ for ( i = 0; i < nParsLut; i++ )
+ fprintf( pFile, " pl%02d", i );
+ fprintf( pFile, "\n" );
+
+ fprintf( pFile, ".inputs" );
+ for ( i = 0; i < nParsVar; i++ )
+ fprintf( pFile, " pv%02d", i );
+ fprintf( pFile, "\n" );
+
+ fprintf( pFile, ".inputs" );
+ for ( i = 0; i < nVars; i++ )
+ fprintf( pFile, " v%02d", i );
+ fprintf( pFile, "\n" );
+
+ fprintf( pFile, ".outputs" );
+ fprintf( pFile, " v%02d", nVars + nLuts - 1 );
+ fprintf( pFile, "\n" );
+ fprintf( pFile, ".names Gnd\n" );
+ fprintf( pFile, " 0\n" );
+
+ // generate LUTs
+ for ( i = 0; i < nLuts; i++ )
+ {
+ fprintf( pFile, ".subckt lut%d", nLutSize );
+ // generate config parameters
+ for ( k = 0; k < nVarsLut; k++ )
+ fprintf( pFile, " p%02d=pl%02d", k, i * nVarsLut + k );
+ // generate the inputs
+ for ( k = 0; k < nLutSize; k++ )
+ fprintf( pFile, " i%d=s%02d", k, i * nLutSize + k );
+ // generate the output
+ fprintf( pFile, " o=v%02d", nVars + i );
+ fprintf( pFile, "\n" );
+ }
+
+ // generate LUT inputs
+ for ( i = 0; i < nLuts; i++ )
+ {
+ for ( j = 0; j < nLutSize; j++ )
+ {
+ fprintf( pFile, ".subckt lut%d", nVarsLog );
+ // generate config parameters
+ for ( k = 0; k < nVarsDeg; k++ )
+ {
+ if ( k < nVars + nLuts - 1 && k < nVars + i )
+ fprintf( pFile, " p%02d=v%02d", k, k );
+ else
+ fprintf( pFile, " p%02d=Gnd", k );
+ }
+ // generate the inputs
+ for ( k = 0; k < nVarsLog; k++ )
+ fprintf( pFile, " i%d=pv%02d", k, (i * nLutSize + j) * nVarsLog + k );
+ // generate the output
+ fprintf( pFile, " o=s%02d", i * nLutSize + j );
+ fprintf( pFile, "\n" );
+ }
+ }
+
+ fprintf( pFile, ".end\n" );
+ fprintf( pFile, "\n" );
+
+ // generate LUTs
+ Abc_WriteKLut( pFile, nLutSize );
+ if ( nVarsLog != nLutSize )
+ Abc_WriteKLut( pFile, nVarsLog );
+ fclose( pFile );
+}
+
+////////////////////////////////////////////////////////////////////////
+/// END OF FILE ///
+////////////////////////////////////////////////////////////////////////
+
+
diff --git a/src/base/abci/abcHaig.c b/src/base/abci/abcHaig.c
index a4731095..d3513bbe 100644
--- a/src/base/abci/abcHaig.c
+++ b/src/base/abci/abcHaig.c
@@ -19,7 +19,6 @@
***********************************************************************/
#include "abc.h"
-#include "hop.h"
////////////////////////////////////////////////////////////////////////
/// DECLARATIONS ///
@@ -31,6 +30,127 @@
/**Function*************************************************************
+ Synopsis [Start history AIG.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Abc_NtkHaigStart( Abc_Ntk_t * pNtk )
+{
+ Hop_Man_t * p;
+ Abc_Obj_t * pObj, * pTemp;
+ int i;
+ assert( Abc_NtkIsStrash(pNtk) );
+ // check if the package is already started
+ if ( pNtk->pHaig )
+ {
+ Abc_NtkHaigStop( pNtk );
+ assert( pNtk->pHaig == NULL );
+ printf( "Warning: Previous history AIG was removed.\n" );
+ }
+ // make sure the data is clean
+ Abc_NtkForEachObj( pNtk, pObj, i )
+ assert( pObj->pEquiv == NULL );
+ // start the HOP package
+ p = Hop_ManStart();
+ p->vObjs = Vec_PtrAlloc( 4096 );
+ Vec_PtrPush( p->vObjs, Hop_ManConst1(p) );
+ // map the constant node
+ Abc_AigConst1(pNtk)->pEquiv = Hop_ManConst1(p);
+ // map the CIs
+ Abc_NtkForEachCi( pNtk, pObj, i )
+ pObj->pEquiv = Hop_ObjCreatePi(p);
+ // map the internal nodes
+ Abc_NtkForEachNode( pNtk, pObj, i )
+ pObj->pEquiv = Hop_And( p, Abc_ObjChild0Equiv(pObj), Abc_ObjChild1Equiv(pObj) );
+ // map the choice nodes
+ if ( Abc_NtkGetChoiceNum( pNtk ) )
+ {
+ // print warning about choice nodes
+ printf( "Warning: The choice nodes in the original AIG are converted into HAIG.\n" );
+ Abc_NtkForEachNode( pNtk, pObj, i )
+ {
+ if ( !Abc_AigNodeIsChoice( pObj ) )
+ continue;
+ for ( pTemp = pObj->pData; pTemp; pTemp = pTemp->pData )
+ Hop_ObjCreateChoice( pObj->pEquiv, pTemp->pEquiv );
+ }
+ }
+ // make sure everything is okay
+ if ( !Hop_ManCheck(p) )
+ {
+ printf( "Abc_NtkHaigStart: Check for History AIG has failed.\n" );
+ Hop_ManStop(p);
+ return 0;
+ }
+ pNtk->pHaig = p;
+ return 1;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Stops history AIG.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Abc_NtkHaigStop( Abc_Ntk_t * pNtk )
+{
+ Abc_Obj_t * pObj;
+ int i;
+ assert( Abc_NtkIsStrash(pNtk) );
+ if ( pNtk->pHaig == NULL )
+ {
+ printf( "Warning: History AIG is not allocated.\n" );
+ return 1;
+ }
+ Abc_NtkForEachObj( pNtk, pObj, i )
+ pObj->pEquiv = NULL;
+ Hop_ManStop( pNtk->pHaig );
+ pNtk->pHaig = NULL;
+ return 1;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Transfers the HAIG to the new network.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Abc_NtkHaigTranfer( Abc_Ntk_t * pNtkOld, Abc_Ntk_t * pNtkNew )
+{
+ Abc_Obj_t * pObj;
+ int i;
+ if ( pNtkOld->pHaig == NULL )
+ return;
+ // transfer the package
+ assert( pNtkNew->pHaig == NULL );
+ pNtkNew->pHaig = pNtkOld->pHaig;
+ pNtkOld->pHaig = NULL;
+ // transfer constant pointer
+ Abc_AigConst1(pNtkOld)->pCopy->pEquiv = Abc_AigConst1(pNtkOld)->pEquiv;
+ // transfer the CI pointers
+ Abc_NtkForEachCi( pNtkOld, pObj, i )
+ pObj->pCopy->pEquiv = pObj->pEquiv;
+}
+
+
+
+/**Function*************************************************************
+
Synopsis [Collects the nodes in the classes.]
Description []
@@ -347,10 +467,10 @@ Abc_Ntk_t * Abc_NtkHaigRecreateAig( Abc_Ntk_t * pNtk, Hop_Man_t * p )
assert( p->nCreated == Vec_PtrSize(p->vObjs) );
// start the new network
- pNtkAig = Abc_NtkStartFrom( pNtk, ABC_TYPE_STRASH, ABC_FUNC_AIG );
+ pNtkAig = Abc_NtkStartFrom( pNtk, ABC_NTK_STRASH, ABC_FUNC_AIG );
// transfer new nodes to the PIs of HOP
- Hop_ManConst1(p)->pNext = (Hop_Obj_t *)Abc_AigConst1( pNtkAig->pManFunc );
+ Hop_ManConst1(p)->pNext = (Hop_Obj_t *)Abc_AigConst1( pNtkAig );
Hop_ManForEachPi( p, pObj, i )
pObj->pNext = (Hop_Obj_t *)Abc_NtkCi( pNtkAig, i );
@@ -516,6 +636,59 @@ int Abc_NtkHaigResetReprs( Hop_Man_t * p )
return nFanouts;
}
+/**Function*************************************************************
+
+ Synopsis [Stops history AIG.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Abc_Ntk_t * Abc_NtkHaigUse( Abc_Ntk_t * pNtk )
+{
+ Hop_Man_t * pMan, * pManTemp;
+ Abc_Ntk_t * pNtkAig;
+ Abc_Obj_t * pObj;
+ int i;
+
+ // check if HAIG is available
+ assert( Abc_NtkIsStrash(pNtk) );
+ if ( pNtk->pHaig == NULL )
+ {
+ printf( "Warning: History AIG is not available.\n" );
+ return NULL;
+ }
+ // convert HOP package into AIG with choices
+ // print HAIG stats
+// Hop_ManPrintStats( pMan ); // USES DATA!!!
+
+ // add the POs
+ Abc_NtkForEachCo( pNtk, pObj, i )
+ Hop_ObjCreatePo( pNtk->pHaig, Abc_ObjChild0Equiv(pObj) );
+
+ // clean the old network
+ Abc_NtkForEachObj( pNtk, pObj, i )
+ pObj->pEquiv = NULL;
+ pMan = pNtk->pHaig;
+ pNtk->pHaig = 0;
+
+ // iteratively reconstruct the HOP manager to create choice nodes
+ while ( Abc_NtkHaigResetReprs( pMan ) )
+ {
+ pMan = Abc_NtkHaigReconstruct( pManTemp = pMan );
+ Hop_ManStop( pManTemp );
+ }
+
+ // traverse in the topological order and create new AIG
+ pNtkAig = Abc_NtkHaigRecreateAig( pNtk, pMan );
+ Hop_ManStop( pMan );
+
+ // free HAIG
+ return pNtkAig;
+}
/**Function*************************************************************
diff --git a/src/base/abci/abcIf.c b/src/base/abci/abcIf.c
new file mode 100644
index 00000000..bb56c22c
--- /dev/null
+++ b/src/base/abci/abcIf.c
@@ -0,0 +1,497 @@
+/**CFile****************************************************************
+
+ FileName [abcIf.c]
+
+ SystemName [ABC: Logic synthesis and verification system.]
+
+ PackageName [Network and node package.]
+
+ Synopsis [Interface with the FPGA mapping package.]
+
+ Author [Alan Mishchenko]
+
+ Affiliation [UC Berkeley]
+
+ Date [Ver. 1.0. Started - November 21, 2006.]
+
+ Revision [$Id: abcIf.c,v 1.00 2006/11/21 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "abc.h"
+#include "if.h"
+#include "kit.h"
+
+////////////////////////////////////////////////////////////////////////
+/// DECLARATIONS ///
+////////////////////////////////////////////////////////////////////////
+
+static If_Man_t * Abc_NtkToIf( Abc_Ntk_t * pNtk, If_Par_t * pPars );
+static Abc_Ntk_t * Abc_NtkFromIf( If_Man_t * pIfMan, Abc_Ntk_t * pNtk );
+extern Abc_Obj_t * Abc_NodeFromIf_rec( Abc_Ntk_t * pNtkNew, If_Man_t * pIfMan, If_Obj_t * pIfObj, Vec_Int_t * vCover );
+static Hop_Obj_t * Abc_NodeIfToHop( Hop_Man_t * pHopMan, If_Man_t * pIfMan, If_Obj_t * pIfObj );
+static Vec_Ptr_t * Abc_NtkFindGoodOrder( Abc_Ntk_t * pNtk );
+
+extern void Abc_NtkBddReorder( Abc_Ntk_t * pNtk, int fVerbose );
+
+////////////////////////////////////////////////////////////////////////
+/// FUNCTION DEFINITIONS ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+ Synopsis [Interface with the FPGA mapping package.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Abc_Ntk_t * Abc_NtkIf( Abc_Ntk_t * pNtk, If_Par_t * pPars )
+{
+ Abc_Ntk_t * pNtkNew;
+ If_Man_t * pIfMan;
+
+ assert( Abc_NtkIsStrash(pNtk) );
+
+ // get timing information
+ pPars->pTimesArr = Abc_NtkGetCiArrivalFloats(pNtk);
+ pPars->pTimesReq = NULL;
+
+ // set the latch paths
+ if ( pPars->fLatchPaths && pPars->pTimesArr )
+ {
+ int c;
+ for ( c = 0; c < Abc_NtkPiNum(pNtk); c++ )
+ pPars->pTimesArr[c] = -ABC_INFINITY;
+ }
+
+ // perform FPGA mapping
+ pIfMan = Abc_NtkToIf( pNtk, pPars );
+ if ( pIfMan == NULL )
+ return NULL;
+ if ( !If_ManPerformMapping( pIfMan ) )
+ {
+ If_ManStop( pIfMan );
+ return NULL;
+ }
+
+ // transform the result of mapping into the new network
+ pNtkNew = Abc_NtkFromIf( pIfMan, pNtk );
+ if ( pNtkNew == NULL )
+ return NULL;
+ If_ManStop( pIfMan );
+
+ // duplicate EXDC
+ if ( pNtk->pExdc )
+ pNtkNew->pExdc = Abc_NtkDup( pNtk->pExdc );
+
+ // make sure that everything is okay
+ if ( !Abc_NtkCheck( pNtkNew ) )
+ {
+ printf( "Abc_NtkIf: The network check has failed.\n" );
+ Abc_NtkDelete( pNtkNew );
+ return NULL;
+ }
+ return pNtkNew;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Load the network into FPGA manager.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+If_Man_t * Abc_NtkToIf( Abc_Ntk_t * pNtk, If_Par_t * pPars )
+{
+ ProgressBar * pProgress;
+ If_Man_t * pIfMan;
+ Abc_Obj_t * pNode, * pFanin, * pPrev;
+ Vec_Ptr_t * vNodes;
+ int i;
+
+ assert( Abc_NtkIsStrash(pNtk) );
+// vNodes = Abc_NtkFindGoodOrder( pNtk );
+ vNodes = Abc_AigDfs( pNtk, 0, 0 );
+
+ // start the mapping manager and set its parameters
+ pIfMan = If_ManStart( pPars );
+
+ // print warning about excessive memory usage
+ if ( 1.0 * Abc_NtkObjNum(pNtk) * pIfMan->nObjBytes / (1<<30) > 1.0 )
+ printf( "Warning: The mapper will allocate %.1f Gb for to represent the subject graph with %d AIG nodes.\n",
+ 1.0 * Abc_NtkObjNum(pNtk) * pIfMan->nObjBytes / (1<<30), Abc_NtkObjNum(pNtk) );
+
+ // create PIs and remember them in the old nodes
+ Abc_AigConst1(pNtk)->pCopy = (Abc_Obj_t *)If_ManConst1( pIfMan );
+ Abc_NtkForEachCi( pNtk, pNode, i )
+ {
+ pNode->pCopy = (Abc_Obj_t *)If_ManCreateCi( pIfMan );
+//printf( "AIG CI %2d -> IF CI %2d\n", pNode->Id, ((If_Obj_t *)pNode->pCopy)->Id );
+ }
+
+ // load the AIG into the mapper
+ pProgress = Extra_ProgressBarStart( stdout, Abc_NtkObjNumMax(pNtk) );
+// Abc_AigForEachAnd( pNtk, pNode, i )
+ Vec_PtrForEachEntry( vNodes, pNode, i )
+ {
+ Extra_ProgressBarUpdate( pProgress, i, "Initial" );
+ // add the node to the mapper
+ pNode->pCopy = (Abc_Obj_t *)If_ManCreateAnd( pIfMan,
+ If_NotCond( (If_Obj_t *)Abc_ObjFanin0(pNode)->pCopy, Abc_ObjFaninC0(pNode) ),
+ If_NotCond( (If_Obj_t *)Abc_ObjFanin1(pNode)->pCopy, Abc_ObjFaninC1(pNode) ) );
+ // set up the choice node
+ if ( Abc_AigNodeIsChoice( pNode ) )
+ {
+ pIfMan->nChoices++;
+ for ( pPrev = pNode, pFanin = pNode->pData; pFanin; pPrev = pFanin, pFanin = pFanin->pData )
+ If_ObjSetChoice( (If_Obj_t *)pPrev->pCopy, (If_Obj_t *)pFanin->pCopy );
+ If_ManCreateChoice( pIfMan, (If_Obj_t *)pNode->pCopy );
+ }
+//printf( "AIG node %2d -> IF node %2d\n", pNode->Id, ((If_Obj_t *)pNode->pCopy)->Id );
+ }
+ Extra_ProgressBarStop( pProgress );
+ Vec_PtrFree( vNodes );
+
+ // set the primary outputs without copying the phase
+ Abc_NtkForEachCo( pNtk, pNode, i )
+ If_ManCreateCo( pIfMan, If_NotCond( (If_Obj_t *)Abc_ObjFanin0(pNode)->pCopy, Abc_ObjFaninC0(pNode) ) );
+ return pIfMan;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Creates the mapped network.]
+
+ Description [Assuming the copy field of the mapped nodes are NULL.]
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Abc_Ntk_t * Abc_NtkFromIf( If_Man_t * pIfMan, Abc_Ntk_t * pNtk )
+{
+ ProgressBar * pProgress;
+ Abc_Ntk_t * pNtkNew;
+ Abc_Obj_t * pNode, * pNodeNew;
+ Vec_Int_t * vCover;
+ int i, nDupGates;
+ // create the new network
+ if ( pIfMan->pPars->fUseBdds || pIfMan->pPars->fUseCnfs || pIfMan->pPars->fUseMv )
+ pNtkNew = Abc_NtkStartFrom( pNtk, ABC_NTK_LOGIC, ABC_FUNC_BDD );
+ else if ( pIfMan->pPars->fUseSops )
+ pNtkNew = Abc_NtkStartFrom( pNtk, ABC_NTK_LOGIC, ABC_FUNC_SOP );
+ else
+ pNtkNew = Abc_NtkStartFrom( pNtk, ABC_NTK_LOGIC, ABC_FUNC_AIG );
+ // prepare the mapping manager
+ If_ManCleanNodeCopy( pIfMan );
+ If_ManCleanCutData( pIfMan );
+ // make the mapper point to the new network
+ If_ObjSetCopy( If_ManConst1(pIfMan), Abc_NtkCreateNodeConst1(pNtkNew) );
+ Abc_NtkForEachCi( pNtk, pNode, i )
+ If_ObjSetCopy( If_ManCi(pIfMan, i), pNode->pCopy );
+ // process the nodes in topological order
+ vCover = Vec_IntAlloc( 1 << 16 );
+ pProgress = Extra_ProgressBarStart( stdout, Abc_NtkCoNum(pNtk) );
+ Abc_NtkForEachCo( pNtk, pNode, i )
+ {
+ Extra_ProgressBarUpdate( pProgress, i, "Final" );
+ pNodeNew = Abc_NodeFromIf_rec( pNtkNew, pIfMan, If_ObjFanin0(If_ManCo(pIfMan, i)), vCover );
+ pNodeNew = Abc_ObjNotCond( pNodeNew, If_ObjFaninC0(If_ManCo(pIfMan, i)) );
+ Abc_ObjAddFanin( pNode->pCopy, pNodeNew );
+ }
+ Extra_ProgressBarStop( pProgress );
+ Vec_IntFree( vCover );
+ // remove the constant node if not used
+ pNodeNew = (Abc_Obj_t *)If_ObjCopy( If_ManConst1(pIfMan) );
+ if ( Abc_ObjFanoutNum(pNodeNew) == 0 )
+ Abc_NtkDeleteObj( pNodeNew );
+ // minimize the node
+ if ( pIfMan->pPars->fUseBdds || pIfMan->pPars->fUseCnfs || pIfMan->pPars->fUseMv )
+ Abc_NtkSweep( pNtkNew, 0 );
+ if ( pIfMan->pPars->fUseBdds )
+ Abc_NtkBddReorder( pNtkNew, 0 );
+ // decouple the PO driver nodes to reduce the number of levels
+ nDupGates = Abc_NtkLogicMakeSimpleCos( pNtkNew, 1 );
+// if ( nDupGates && If_ManReadVerbose(pIfMan) )
+// printf( "Duplicated %d gates to decouple the CO drivers.\n", nDupGates );
+ return pNtkNew;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Derive one node after FPGA mapping.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Abc_Obj_t * Abc_NodeFromIf_rec( Abc_Ntk_t * pNtkNew, If_Man_t * pIfMan, If_Obj_t * pIfObj, Vec_Int_t * vCover )
+{
+ Abc_Obj_t * pNodeNew;
+ If_Cut_t * pCutBest;
+ If_Obj_t * pIfLeaf;
+ int i;
+ // return if the result if known
+ pNodeNew = (Abc_Obj_t *)If_ObjCopy( pIfObj );
+ if ( pNodeNew )
+ return pNodeNew;
+ assert( pIfObj->Type == IF_AND );
+ // get the parameters of the best cut
+ // create a new node
+ pNodeNew = Abc_NtkCreateNode( pNtkNew );
+ pCutBest = If_ObjCutBest( pIfObj );
+ if ( pIfMan->pPars->fUseCnfs || pIfMan->pPars->fUseMv )
+ {
+ If_CutForEachLeafReverse( pIfMan, pCutBest, pIfLeaf, i )
+ Abc_ObjAddFanin( pNodeNew, Abc_NodeFromIf_rec(pNtkNew, pIfMan, pIfLeaf, vCover) );
+ }
+ else
+ {
+ If_CutForEachLeaf( pIfMan, pCutBest, pIfLeaf, i )
+ Abc_ObjAddFanin( pNodeNew, Abc_NodeFromIf_rec(pNtkNew, pIfMan, pIfLeaf, vCover) );
+ }
+ // set the level of the new node
+ pNodeNew->Level = Abc_ObjLevelNew( pNodeNew );
+ // derive the function of this node
+ if ( pIfMan->pPars->fTruth )
+ {
+ if ( pIfMan->pPars->fUseBdds )
+ {
+ // transform truth table into the BDD
+ pNodeNew->pData = Kit_TruthToBdd( pNtkNew->pManFunc, If_CutTruth(pCutBest), If_CutLeaveNum(pCutBest), 0 ); Cudd_Ref(pNodeNew->pData);
+ }
+ else if ( pIfMan->pPars->fUseCnfs || pIfMan->pPars->fUseMv )
+ {
+ // transform truth table into the BDD
+ pNodeNew->pData = Kit_TruthToBdd( pNtkNew->pManFunc, If_CutTruth(pCutBest), If_CutLeaveNum(pCutBest), 1 ); Cudd_Ref(pNodeNew->pData);
+ }
+ else if ( pIfMan->pPars->fUseSops )
+ {
+ // transform truth table into the SOP
+ int RetValue = Kit_TruthIsop( If_CutTruth(pCutBest), If_CutLeaveNum(pCutBest), vCover, 1 );
+ assert( RetValue == 0 || RetValue == 1 );
+ // check the case of constant cover
+ if ( Vec_IntSize(vCover) == 0 || (Vec_IntSize(vCover) == 1 && Vec_IntEntry(vCover,0) == 0) )
+ {
+ assert( RetValue == 0 );
+ pNodeNew->pData = Abc_SopCreateAnd( pNtkNew->pManFunc, If_CutLeaveNum(pCutBest), NULL );
+ pNodeNew = (Vec_IntSize(vCover) == 0) ? Abc_NtkCreateNodeConst0(pNtkNew) : Abc_NtkCreateNodeConst1(pNtkNew);
+ }
+ else
+ {
+ // derive the AIG for that tree
+ pNodeNew->pData = Abc_SopCreateFromIsop( pNtkNew->pManFunc, If_CutLeaveNum(pCutBest), vCover );
+ if ( RetValue )
+ Abc_SopComplement( pNodeNew->pData );
+ }
+ }
+ else
+ {
+ extern Hop_Obj_t * Kit_TruthToHop( Hop_Man_t * pMan, unsigned * pTruth, int nVars, Vec_Int_t * vMemory );
+ pNodeNew->pData = Kit_TruthToHop( pNtkNew->pManFunc, If_CutTruth(pCutBest), If_CutLeaveNum(pCutBest), vCover );
+ }
+ // complement the node if the cut was complemented
+ if ( pCutBest->fCompl )
+ Abc_NodeComplement( pNodeNew );
+ }
+ else
+ pNodeNew->pData = Abc_NodeIfToHop( pNtkNew->pManFunc, pIfMan, pIfObj );
+ If_ObjSetCopy( pIfObj, pNodeNew );
+ return pNodeNew;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Recursively derives the truth table for the cut.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Hop_Obj_t * Abc_NodeIfToHop_rec( Hop_Man_t * pHopMan, If_Man_t * pIfMan, If_Obj_t * pIfObj, Vec_Ptr_t * vVisited )
+{
+ If_Cut_t * pCut;
+ Hop_Obj_t * gFunc, * gFunc0, * gFunc1;
+ // get the best cut
+ pCut = If_ObjCutBest(pIfObj);
+ // if the cut is visited, return the result
+ if ( If_CutData(pCut) )
+ return If_CutData(pCut);
+ // compute the functions of the children
+ gFunc0 = Abc_NodeIfToHop_rec( pHopMan, pIfMan, pIfObj->pFanin0, vVisited );
+ gFunc1 = Abc_NodeIfToHop_rec( pHopMan, pIfMan, pIfObj->pFanin1, vVisited );
+ // get the function of the cut
+ gFunc = Hop_And( pHopMan, Hop_NotCond(gFunc0, pIfObj->fCompl0), Hop_NotCond(gFunc1, pIfObj->fCompl1) );
+ assert( If_CutData(pCut) == NULL );
+ If_CutSetData( pCut, gFunc );
+ // add this cut to the visited list
+ Vec_PtrPush( vVisited, pCut );
+ return gFunc;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Derives the truth table for one cut.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Hop_Obj_t * Abc_NodeIfToHop( Hop_Man_t * pHopMan, If_Man_t * pIfMan, If_Obj_t * pIfObj )
+{
+ If_Cut_t * pCut;
+ Hop_Obj_t * gFunc;
+ If_Obj_t * pLeaf;
+ int i;
+ // get the best cut
+ pCut = If_ObjCutBest(pIfObj);
+ assert( pCut->nLeaves > 1 );
+ // set the leaf variables
+ If_CutForEachLeaf( pIfMan, pCut, pLeaf, i )
+ If_CutSetData( If_ObjCutBest(pLeaf), Hop_IthVar(pHopMan, i) );
+ // recursively compute the function while collecting visited cuts
+ Vec_PtrClear( pIfMan->vTemp );
+ gFunc = Abc_NodeIfToHop_rec( pHopMan, pIfMan, pIfObj, pIfMan->vTemp );
+// printf( "%d ", Vec_PtrSize(p->vTemp) );
+ // clean the cuts
+ If_CutForEachLeaf( pIfMan, pCut, pLeaf, i )
+ If_CutSetData( If_ObjCutBest(pLeaf), NULL );
+ Vec_PtrForEachEntry( pIfMan->vTemp, pCut, i )
+ If_CutSetData( pCut, NULL );
+ return gFunc;
+}
+
+
+/**Function*************************************************************
+
+ Synopsis [Comparison for two nodes with the flow.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Abc_ObjCompareFlow( Abc_Obj_t ** ppNode0, Abc_Obj_t ** ppNode1 )
+{
+ float Flow0 = Abc_Int2Float((int)(*ppNode0)->pCopy);
+ float Flow1 = Abc_Int2Float((int)(*ppNode1)->pCopy);
+ if ( Flow0 > Flow1 )
+ return -1;
+ if ( Flow0 < Flow1 )
+ return 1;
+ return 0;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Orders AIG nodes so that nodes from larger cones go first.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Abc_NtkFindGoodOrder_rec( Abc_Obj_t * pNode, Vec_Ptr_t * vNodes )
+{
+ if ( !Abc_ObjIsNode(pNode) )
+ return;
+ assert( Abc_ObjIsNode( pNode ) );
+ // if this node is already visited, skip
+ if ( Abc_NodeIsTravIdCurrent( pNode ) )
+ return;
+ // mark the node as visited
+ Abc_NodeSetTravIdCurrent( pNode );
+ // visit the transitive fanin of the node
+ Abc_NtkFindGoodOrder_rec( Abc_ObjFanin0(pNode), vNodes );
+ Abc_NtkFindGoodOrder_rec( Abc_ObjFanin1(pNode), vNodes );
+ // add the node after the fanins have been added
+ Vec_PtrPush( vNodes, pNode );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Orders AIG nodes so that nodes from larger cones go first.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Vec_Ptr_t * Abc_NtkFindGoodOrder( Abc_Ntk_t * pNtk )
+{
+ Vec_Ptr_t * vNodes, * vCos;
+ Abc_Obj_t * pNode, * pFanin0, * pFanin1;
+ float Flow0, Flow1;
+ int i;
+
+ // initialize the flow
+ Abc_AigConst1(pNtk)->pCopy = NULL;
+ Abc_NtkForEachCi( pNtk, pNode, i )
+ pNode->pCopy = NULL;
+ // compute the flow
+ Abc_AigForEachAnd( pNtk, pNode, i )
+ {
+ pFanin0 = Abc_ObjFanin0(pNode);
+ pFanin1 = Abc_ObjFanin1(pNode);
+ Flow0 = Abc_Int2Float((int)pFanin0->pCopy)/Abc_ObjFanoutNum(pFanin0);
+ Flow1 = Abc_Int2Float((int)pFanin1->pCopy)/Abc_ObjFanoutNum(pFanin1);
+ pNode->pCopy = (Abc_Obj_t *)Abc_Float2Int(Flow0 + Flow1+(float)1.0);
+ }
+ // find the flow of the COs
+ vCos = Vec_PtrAlloc( Abc_NtkCoNum(pNtk) );
+ Abc_NtkForEachCo( pNtk, pNode, i )
+ {
+ pNode->pCopy = Abc_ObjFanin0(pNode)->pCopy;
+// pNode->pCopy = (Abc_Obj_t *)Abc_Float2Int((float)Abc_ObjFanin0(pNode)->Level);
+ Vec_PtrPush( vCos, pNode );
+ }
+
+ // sort nodes in the increasing order of the flow
+ qsort( (Abc_Obj_t **)Vec_PtrArray(vCos), Abc_NtkCoNum(pNtk),
+ sizeof(Abc_Obj_t *), (int (*)(const void *, const void *))Abc_ObjCompareFlow );
+ // verify sorting
+ pFanin0 = Vec_PtrEntry(vCos, 0);
+ pFanin1 = Vec_PtrEntryLast(vCos);
+ assert( Abc_Int2Float((int)pFanin0->pCopy) >= Abc_Int2Float((int)pFanin1->pCopy) );
+
+ // collect the nodes in the topological order from the new array
+ Abc_NtkIncrementTravId( pNtk );
+ vNodes = Vec_PtrAlloc( 100 );
+ Vec_PtrForEachEntry( vCos, pNode, i )
+ {
+ Abc_NtkFindGoodOrder_rec( Abc_ObjFanin0(pNode), vNodes );
+// printf( "%.2f ", Abc_Int2Float((int)pNode->pCopy) );
+ }
+ Vec_PtrFree( vCos );
+ return vNodes;
+}
+
+////////////////////////////////////////////////////////////////////////
+/// END OF FILE ///
+////////////////////////////////////////////////////////////////////////
+
+
diff --git a/src/base/abci/abcIvy.c b/src/base/abci/abcIvy.c
new file mode 100644
index 00000000..a470448e
--- /dev/null
+++ b/src/base/abci/abcIvy.c
@@ -0,0 +1,1105 @@
+/**CFile****************************************************************
+
+ FileName [abcIvy.c]
+
+ SystemName [ABC: Logic synthesis and verification system.]
+
+ PackageName [Network and node package.]
+
+ Synopsis [Strashing of the current network.]
+
+ Author [Alan Mishchenko]
+
+ Affiliation [UC Berkeley]
+
+ Date [Ver. 1.0. Started - June 20, 2005.]
+
+ Revision [$Id: abcIvy.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "abc.h"
+#include "dec.h"
+#include "ivy.h"
+#include "fraig.h"
+
+////////////////////////////////////////////////////////////////////////
+/// DECLARATIONS ///
+////////////////////////////////////////////////////////////////////////
+
+static Abc_Ntk_t * Abc_NtkFromIvy( Abc_Ntk_t * pNtkOld, Ivy_Man_t * pMan );
+static Abc_Ntk_t * Abc_NtkFromIvySeq( Abc_Ntk_t * pNtkOld, Ivy_Man_t * pMan, int fHaig );
+static Ivy_Man_t * Abc_NtkToIvy( Abc_Ntk_t * pNtkOld );
+
+static void Abc_NtkStrashPerformAig( Abc_Ntk_t * pNtk, Ivy_Man_t * pMan );
+static Ivy_Obj_t * Abc_NodeStrashAig( Ivy_Man_t * pMan, Abc_Obj_t * pNode );
+static Ivy_Obj_t * Abc_NodeStrashAigSopAig( Ivy_Man_t * pMan, Abc_Obj_t * pNode, char * pSop );
+static Ivy_Obj_t * Abc_NodeStrashAigExorAig( Ivy_Man_t * pMan, Abc_Obj_t * pNode, char * pSop );
+static Ivy_Obj_t * Abc_NodeStrashAigFactorAig( Ivy_Man_t * pMan, Abc_Obj_t * pNode, char * pSop );
+extern char * Mio_GateReadSop( void * pGate );
+
+typedef int Abc_Edge_t;
+static inline Abc_Edge_t Abc_EdgeCreate( int Id, int fCompl ) { return (Id << 1) | fCompl; }
+static inline int Abc_EdgeId( Abc_Edge_t Edge ) { return Edge >> 1; }
+static inline int Abc_EdgeIsComplement( Abc_Edge_t Edge ) { return Edge & 1; }
+static inline Abc_Edge_t Abc_EdgeRegular( Abc_Edge_t Edge ) { return (Edge >> 1) << 1; }
+static inline Abc_Edge_t Abc_EdgeNot( Abc_Edge_t Edge ) { return Edge ^ 1; }
+static inline Abc_Edge_t Abc_EdgeNotCond( Abc_Edge_t Edge, int fCond ) { return Edge ^ fCond; }
+static inline Abc_Edge_t Abc_EdgeFromNode( Abc_Obj_t * pNode ) { return Abc_EdgeCreate( Abc_ObjRegular(pNode)->Id, Abc_ObjIsComplement(pNode) ); }
+static inline Abc_Obj_t * Abc_EdgeToNode( Abc_Ntk_t * p, Abc_Edge_t Edge ) { return Abc_ObjNotCond( Abc_NtkObj(p, Abc_EdgeId(Edge)), Abc_EdgeIsComplement(Edge) ); }
+
+static inline Abc_Obj_t * Abc_ObjFanin0Ivy( Abc_Ntk_t * p, Ivy_Obj_t * pObj ) { return Abc_ObjNotCond( Abc_EdgeToNode(p, Ivy_ObjFanin0(pObj)->TravId), Ivy_ObjFaninC0(pObj) ); }
+static inline Abc_Obj_t * Abc_ObjFanin1Ivy( Abc_Ntk_t * p, Ivy_Obj_t * pObj ) { return Abc_ObjNotCond( Abc_EdgeToNode(p, Ivy_ObjFanin1(pObj)->TravId), Ivy_ObjFaninC1(pObj) ); }
+
+static Vec_Int_t * Abc_NtkCollectLatchValuesIvy( Abc_Ntk_t * pNtk, int fUseDcs );
+
+extern int timeRetime;
+
+////////////////////////////////////////////////////////////////////////
+/// FUNCTION DEFINITIONS ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+ Synopsis [Prepares the IVY package.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Ivy_Man_t * Abc_NtkIvyBefore( Abc_Ntk_t * pNtk, int fSeq, int fUseDc )
+{
+ Ivy_Man_t * pMan;
+ int fCleanup = 1;
+//timeRetime = clock();
+ assert( !Abc_NtkIsNetlist(pNtk) );
+ if ( Abc_NtkIsBddLogic(pNtk) )
+ {
+ if ( !Abc_NtkBddToSop(pNtk, 0) )
+ {
+ printf( "Abc_NtkIvyBefore(): Converting to SOPs has failed.\n" );
+ return NULL;
+ }
+ }
+ if ( fSeq && Abc_NtkCountSelfFeedLatches(pNtk) )
+ {
+ printf( "Warning: The network has %d self-feeding latches.\n", Abc_NtkCountSelfFeedLatches(pNtk) );
+// return NULL;
+ }
+ // print warning about choice nodes
+ if ( Abc_NtkGetChoiceNum( pNtk ) )
+ printf( "Warning: The choice nodes in the initial AIG are removed by strashing.\n" );
+ // convert to the AIG manager
+ pMan = Abc_NtkToIvy( pNtk );
+ if ( !Ivy_ManCheck( pMan ) )
+ {
+ printf( "AIG check has failed.\n" );
+ Ivy_ManStop( pMan );
+ return NULL;
+ }
+// Ivy_ManPrintStats( pMan );
+ if ( fSeq )
+ {
+ int nLatches = Abc_NtkLatchNum(pNtk);
+ Vec_Int_t * vInit = Abc_NtkCollectLatchValuesIvy( pNtk, fUseDc );
+ Ivy_ManMakeSeq( pMan, nLatches, vInit->pArray );
+ Vec_IntFree( vInit );
+// Ivy_ManPrintStats( pMan );
+ }
+//timeRetime = clock() - timeRetime;
+ return pMan;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Prepares the IVY package.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Abc_Ntk_t * Abc_NtkIvyAfter( Abc_Ntk_t * pNtk, Ivy_Man_t * pMan, int fSeq, int fHaig )
+{
+ Abc_Ntk_t * pNtkAig;
+ int nNodes, fCleanup = 1;
+ // convert from the AIG manager
+ if ( fSeq )
+ pNtkAig = Abc_NtkFromIvySeq( pNtk, pMan, fHaig );
+ else
+ pNtkAig = Abc_NtkFromIvy( pNtk, pMan );
+ // report the cleanup results
+ if ( !fHaig && fCleanup && (nNodes = Abc_AigCleanup(pNtkAig->pManFunc)) )
+ printf( "Warning: AIG cleanup removed %d nodes (this is not a bug).\n", nNodes );
+ // duplicate EXDC
+ if ( pNtk->pExdc )
+ pNtkAig->pExdc = Abc_NtkDup( pNtk->pExdc );
+ // make sure everything is okay
+ if ( !Abc_NtkCheck( pNtkAig ) )
+ {
+ printf( "Abc_NtkStrash: The network check has failed.\n" );
+ Abc_NtkDelete( pNtkAig );
+ return NULL;
+ }
+ return pNtkAig;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Gives the current ABC network to AIG manager for processing.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Abc_Ntk_t * Abc_NtkIvyStrash( Abc_Ntk_t * pNtk )
+{
+ Abc_Ntk_t * pNtkAig;
+ Ivy_Man_t * pMan;
+ pMan = Abc_NtkIvyBefore( pNtk, 1, 0 );
+ if ( pMan == NULL )
+ return NULL;
+ pNtkAig = Abc_NtkIvyAfter( pNtk, pMan, 1, 0 );
+ Ivy_ManStop( pMan );
+ return pNtkAig;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Gives the current ABC network to AIG manager for processing.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Abc_Ntk_t * Abc_NtkIvyHaig( Abc_Ntk_t * pNtk, int nIters, int fUseZeroCost, int fVerbose )
+{
+ Abc_Ntk_t * pNtkAig;
+ Ivy_Man_t * pMan;
+ int clk;
+// int i;
+/*
+extern int nMoves;
+extern int nMovesS;
+extern int nClauses;
+extern int timeInv;
+
+nMoves = 0;
+nMovesS = 0;
+nClauses = 0;
+timeInv = 0;
+*/
+ pMan = Abc_NtkIvyBefore( pNtk, 1, 1 );
+ if ( pMan == NULL )
+ return NULL;
+//timeRetime = clock();
+
+clk = clock();
+ Ivy_ManHaigStart( pMan, fVerbose );
+// Ivy_ManRewriteSeq( pMan, 0, 0 );
+// for ( i = 0; i < nIters; i++ )
+// Ivy_ManRewriteSeq( pMan, fUseZeroCost, 0 );
+
+//printf( "%d ", Ivy_ManNodeNum(pMan) );
+ Ivy_ManRewriteSeq( pMan, 0, 0 );
+ Ivy_ManRewriteSeq( pMan, 0, 0 );
+ Ivy_ManRewriteSeq( pMan, 1, 0 );
+//printf( "%d ", Ivy_ManNodeNum(pMan) );
+//printf( "%d ", Ivy_ManNodeNum(pMan->pHaig) );
+//PRT( " ", clock() - clk );
+//printf( "\n" );
+/*
+ printf( "Moves = %d. ", nMoves );
+ printf( "MovesS = %d. ", nMovesS );
+ printf( "Clauses = %d. ", nClauses );
+ PRT( "Time", timeInv );
+*/
+// Ivy_ManRewriteSeq( pMan, 1, 0 );
+//printf( "Haig size = %d.\n", Ivy_ManNodeNum(pMan->pHaig) );
+// Ivy_ManHaigPostprocess( pMan, fVerbose );
+//timeRetime = clock() - timeRetime;
+
+ // write working AIG into the current network
+// pNtkAig = Abc_NtkIvyAfter( pNtk, pMan, 1, 0 );
+ // write HAIG into the current network
+ pNtkAig = Abc_NtkIvyAfter( pNtk, pMan->pHaig, 1, 1 );
+
+ Ivy_ManHaigStop( pMan );
+ Ivy_ManStop( pMan );
+ return pNtkAig;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Gives the current ABC network to AIG manager for processing.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Abc_NtkIvyCuts( Abc_Ntk_t * pNtk, int nInputs )
+{
+ extern void Ivy_CutComputeAll( Ivy_Man_t * p, int nInputs );
+ Ivy_Man_t * pMan;
+ pMan = Abc_NtkIvyBefore( pNtk, 1, 0 );
+ if ( pMan == NULL )
+ return;
+ Ivy_CutComputeAll( pMan, nInputs );
+ Ivy_ManStop( pMan );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Gives the current ABC network to AIG manager for processing.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Abc_Ntk_t * Abc_NtkIvyRewrite( Abc_Ntk_t * pNtk, int fUpdateLevel, int fUseZeroCost, int fVerbose )
+{
+ Abc_Ntk_t * pNtkAig;
+ Ivy_Man_t * pMan;
+ pMan = Abc_NtkIvyBefore( pNtk, 0, 0 );
+ if ( pMan == NULL )
+ return NULL;
+//timeRetime = clock();
+ Ivy_ManRewritePre( pMan, fUpdateLevel, fUseZeroCost, fVerbose );
+//timeRetime = clock() - timeRetime;
+ pNtkAig = Abc_NtkIvyAfter( pNtk, pMan, 0, 0 );
+ Ivy_ManStop( pMan );
+ return pNtkAig;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Gives the current ABC network to AIG manager for processing.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Abc_Ntk_t * Abc_NtkIvyRewriteSeq( Abc_Ntk_t * pNtk, int fUseZeroCost, int fVerbose )
+{
+ Abc_Ntk_t * pNtkAig;
+ Ivy_Man_t * pMan;
+ pMan = Abc_NtkIvyBefore( pNtk, 1, 1 );
+ if ( pMan == NULL )
+ return NULL;
+//timeRetime = clock();
+ Ivy_ManRewriteSeq( pMan, fUseZeroCost, fVerbose );
+//timeRetime = clock() - timeRetime;
+// Ivy_ManRewriteSeq( pMan, 1, 0 );
+// Ivy_ManRewriteSeq( pMan, 1, 0 );
+ pNtkAig = Abc_NtkIvyAfter( pNtk, pMan, 1, 0 );
+ Ivy_ManStop( pMan );
+ return pNtkAig;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Gives the current ABC network to AIG manager for processing.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Abc_Ntk_t * Abc_NtkIvyResyn0( Abc_Ntk_t * pNtk, int fUpdateLevel, int fVerbose )
+{
+ Abc_Ntk_t * pNtkAig;
+ Ivy_Man_t * pMan, * pTemp;
+ pMan = Abc_NtkIvyBefore( pNtk, 0, 0 );
+ if ( pMan == NULL )
+ return NULL;
+ pMan = Ivy_ManResyn0( pTemp = pMan, fUpdateLevel, fVerbose );
+ Ivy_ManStop( pTemp );
+ pNtkAig = Abc_NtkIvyAfter( pNtk, pMan, 0, 0 );
+ Ivy_ManStop( pMan );
+ return pNtkAig;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Gives the current ABC network to AIG manager for processing.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Abc_Ntk_t * Abc_NtkIvyResyn( Abc_Ntk_t * pNtk, int fUpdateLevel, int fVerbose )
+{
+ Abc_Ntk_t * pNtkAig;
+ Ivy_Man_t * pMan, * pTemp;
+ pMan = Abc_NtkIvyBefore( pNtk, 0, 0 );
+ if ( pMan == NULL )
+ return NULL;
+ pMan = Ivy_ManResyn( pTemp = pMan, fUpdateLevel, fVerbose );
+ Ivy_ManStop( pTemp );
+ pNtkAig = Abc_NtkIvyAfter( pNtk, pMan, 0, 0 );
+ Ivy_ManStop( pMan );
+ return pNtkAig;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Gives the current ABC network to AIG manager for processing.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Abc_Ntk_t * Abc_NtkIvySat( Abc_Ntk_t * pNtk, int nConfLimit, int fVerbose )
+{
+ Ivy_FraigParams_t Params, * pParams = &Params;
+ Abc_Ntk_t * pNtkAig;
+ Ivy_Man_t * pMan, * pTemp;
+ pMan = Abc_NtkIvyBefore( pNtk, 0, 0 );
+ if ( pMan == NULL )
+ return NULL;
+ Ivy_FraigParamsDefault( pParams );
+ pParams->nBTLimitMiter = nConfLimit;
+ pParams->fVerbose = fVerbose;
+// pMan = Ivy_FraigPerform( pTemp = pMan, pParams );
+ pMan = Ivy_FraigMiter( pTemp = pMan, pParams );
+ Ivy_ManStop( pTemp );
+ pNtkAig = Abc_NtkIvyAfter( pNtk, pMan, 0, 0 );
+ Ivy_ManStop( pMan );
+ return pNtkAig;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Sets the final nodes to point to the original nodes.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Abc_NtkTransferPointers( Abc_Ntk_t * pNtk, Abc_Ntk_t * pNtkAig )
+{
+ Abc_Obj_t * pObj;
+ Ivy_Obj_t * pObjIvy, * pObjFraig;
+ int i;
+ pObj = Abc_AigConst1(pNtk);
+ pObj->pCopy = Abc_AigConst1(pNtkAig);
+ Abc_NtkForEachCi( pNtk, pObj, i )
+ pObj->pCopy = Abc_NtkCi(pNtkAig, i);
+ Abc_NtkForEachCo( pNtk, pObj, i )
+ pObj->pCopy = Abc_NtkCo(pNtkAig, i);
+ Abc_NtkForEachLatch( pNtk, pObj, i )
+ pObj->pCopy = Abc_NtkBox(pNtkAig, i);
+ Abc_NtkForEachNode( pNtk, pObj, i )
+ {
+ pObjIvy = (Ivy_Obj_t *)pObj->pCopy;
+ if ( pObjIvy == NULL )
+ continue;
+ pObjFraig = Ivy_ObjEquiv( pObjIvy );
+ if ( pObjFraig == NULL )
+ continue;
+ pObj->pCopy = Abc_EdgeToNode( pNtkAig, Ivy_Regular(pObjFraig)->TravId );
+ pObj->pCopy = Abc_ObjNotCond( pObj->pCopy, Ivy_IsComplement(pObjFraig) );
+ }
+}
+
+/**Function*************************************************************
+
+ Synopsis [Gives the current ABC network to AIG manager for processing.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Abc_Ntk_t * Abc_NtkIvyFraig( Abc_Ntk_t * pNtk, int nConfLimit, int fDoSparse, int fProve, int fTransfer, int fVerbose )
+{
+ Ivy_FraigParams_t Params, * pParams = &Params;
+ Abc_Ntk_t * pNtkAig;
+ Ivy_Man_t * pMan, * pTemp;
+ pMan = Abc_NtkIvyBefore( pNtk, 0, 0 );
+ if ( pMan == NULL )
+ return NULL;
+ Ivy_FraigParamsDefault( pParams );
+ pParams->nBTLimitNode = nConfLimit;
+ pParams->fVerbose = fVerbose;
+ pParams->fProve = fProve;
+ pParams->fDoSparse = fDoSparse;
+ pMan = Ivy_FraigPerform( pTemp = pMan, pParams );
+ // transfer the pointers
+ if ( fTransfer == 1 )
+ {
+ Vec_Ptr_t * vCopies;
+ vCopies = Abc_NtkSaveCopy( pNtk );
+ pNtkAig = Abc_NtkIvyAfter( pNtk, pMan, 0, 0 );
+ Abc_NtkLoadCopy( pNtk, vCopies );
+ Vec_PtrFree( vCopies );
+ Abc_NtkTransferPointers( pNtk, pNtkAig );
+ }
+ else
+ pNtkAig = Abc_NtkIvyAfter( pNtk, pMan, 0, 0 );
+ Ivy_ManStop( pTemp );
+ Ivy_ManStop( pMan );
+ return pNtkAig;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Gives the current ABC network to AIG manager for processing.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Abc_NtkIvyProve( Abc_Ntk_t ** ppNtk, void * pPars )
+{
+ Prove_Params_t * pParams = pPars;
+ Abc_Ntk_t * pNtk = *ppNtk, * pNtkTemp;
+ Abc_Obj_t * pObj, * pFanin;
+ Ivy_Man_t * pMan;
+ int RetValue;
+ assert( Abc_NtkIsStrash(pNtk) || Abc_NtkIsLogic(pNtk) );
+ // experiment with various parameters settings
+// pParams->fUseBdds = 1;
+// pParams->fBddReorder = 1;
+// pParams->nTotalBacktrackLimit = 10000;
+
+ // strash the network if it is not strashed already
+ if ( !Abc_NtkIsStrash(pNtk) )
+ {
+ pNtk = Abc_NtkStrash( pNtkTemp = pNtk, 0, 1, 0 );
+ Abc_NtkDelete( pNtkTemp );
+ }
+
+ // check the case when the 0000 simulation pattern detect the bug
+ pObj = Abc_NtkPo(pNtk,0);
+ pFanin = Abc_ObjFanin0(pObj);
+ if ( Abc_ObjFanin0(pObj)->fPhase != (unsigned)Abc_ObjFaninC0(pObj) )
+ {
+ pNtk->pModel = ALLOC( int, Abc_NtkPiNum(pNtk) );
+ memset( pNtk->pModel, 0, sizeof(int) * Abc_NtkPiNum(pNtk) );
+ return 0;
+ }
+
+ // if SAT only, solve without iteration
+ RetValue = Abc_NtkMiterSat( pNtk, 2*(sint64)pParams->nMiteringLimitStart, (sint64)0, 0, NULL, NULL );
+ if ( RetValue >= 0 )
+ return RetValue;
+
+ // apply AIG rewriting
+ if ( pParams->fUseRewriting && Abc_NtkNodeNum(pNtk) > 500 )
+ {
+// int clk = clock();
+//printf( "Before rwsat = %d. ", Abc_NtkNodeNum(pNtk) );
+ pParams->fUseRewriting = 0;
+ pNtk = Abc_NtkBalance( pNtkTemp = pNtk, 0, 0, 0 );
+ Abc_NtkDelete( pNtkTemp );
+ Abc_NtkRewrite( pNtk, 0, 0, 0, 0, 0 );
+ pNtk = Abc_NtkBalance( pNtkTemp = pNtk, 0, 0, 0 );
+ Abc_NtkDelete( pNtkTemp );
+ Abc_NtkRewrite( pNtk, 0, 0, 0, 0, 0 );
+ Abc_NtkRefactor( pNtk, 10, 16, 0, 0, 0, 0 );
+//printf( "After rwsat = %d. ", Abc_NtkNodeNum(pNtk) );
+//PRT( "Time", clock() - clk );
+ }
+
+ // convert ABC network into IVY network
+ pMan = Abc_NtkIvyBefore( pNtk, 0, 0 );
+
+ // solve the CEC problem
+ RetValue = Ivy_FraigProve( &pMan, pParams );
+ // convert IVY network into ABC network
+ pNtk = Abc_NtkIvyAfter( pNtkTemp = pNtk, pMan, 0, 0 );
+ Abc_NtkDelete( pNtkTemp );
+ // transfer model if given
+ pNtk->pModel = pMan->pData; pMan->pData = NULL;
+ Ivy_ManStop( pMan );
+
+ // try to prove it using brute force SAT
+ if ( RetValue < 0 && pParams->fUseBdds )
+ {
+ if ( pParams->fVerbose )
+ {
+ printf( "Attempting BDDs with node limit %d ...\n", pParams->nBddSizeLimit );
+ fflush( stdout );
+ }
+ pNtk = Abc_NtkCollapse( pNtkTemp = pNtk, pParams->nBddSizeLimit, 0, pParams->fBddReorder, 0 );
+ if ( pNtk )
+ {
+ Abc_NtkDelete( pNtkTemp );
+ RetValue = ( (Abc_NtkNodeNum(pNtk) == 1) && (Abc_ObjFanin0(Abc_NtkPo(pNtk,0))->pData == Cudd_ReadLogicZero(pNtk->pManFunc)) );
+ }
+ else
+ pNtk = pNtkTemp;
+ }
+
+ // return the result
+ *ppNtk = pNtk;
+ return RetValue;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Gives the current ABC network to AIG manager for processing.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Abc_Ntk_t * Abc_NtkIvy( Abc_Ntk_t * pNtk )
+{
+// Abc_Ntk_t * pNtkAig;
+ Ivy_Man_t * pMan;//, * pTemp;
+ int fCleanup = 1;
+// int nNodes;
+ int nLatches = Abc_NtkLatchNum(pNtk);
+ Vec_Int_t * vInit = Abc_NtkCollectLatchValuesIvy( pNtk, 0 );
+
+ assert( !Abc_NtkIsNetlist(pNtk) );
+ if ( Abc_NtkIsBddLogic(pNtk) )
+ {
+ if ( !Abc_NtkBddToSop(pNtk, 0) )
+ {
+ Vec_IntFree( vInit );
+ printf( "Abc_NtkIvy(): Converting to SOPs has failed.\n" );
+ return NULL;
+ }
+ }
+ if ( Abc_NtkCountSelfFeedLatches(pNtk) )
+ {
+ printf( "Warning: The network has %d self-feeding latches. Quitting.\n", Abc_NtkCountSelfFeedLatches(pNtk) );
+ return NULL;
+ }
+
+ // print warning about choice nodes
+ if ( Abc_NtkGetChoiceNum( pNtk ) )
+ printf( "Warning: The choice nodes in the initial AIG are removed by strashing.\n" );
+
+ // convert to the AIG manager
+ pMan = Abc_NtkToIvy( pNtk );
+ if ( !Ivy_ManCheck( pMan ) )
+ {
+ Vec_IntFree( vInit );
+ printf( "AIG check has failed.\n" );
+ Ivy_ManStop( pMan );
+ return NULL;
+ }
+
+// Ivy_MffcTest( pMan );
+// Ivy_ManPrintStats( pMan );
+
+// pMan = Ivy_ManBalance( pTemp = pMan, 1 );
+// Ivy_ManStop( pTemp );
+
+// Ivy_ManSeqRewrite( pMan, 0, 0 );
+// Ivy_ManTestCutsAlg( pMan );
+// Ivy_ManTestCutsBool( pMan );
+// Ivy_ManRewriteAlg( pMan, 1, 1 );
+
+// pMan = Ivy_ManResyn( pTemp = pMan, 1, 0 );
+// Ivy_ManStop( pTemp );
+
+// Ivy_ManTestCutsAll( pMan );
+// Ivy_ManTestCutsTravAll( pMan );
+
+// Ivy_ManPrintStats( pMan );
+
+// Ivy_ManPrintStats( pMan );
+// Ivy_ManRewritePre( pMan, 1, 0, 0 );
+// Ivy_ManPrintStats( pMan );
+// printf( "\n" );
+
+// Ivy_ManPrintStats( pMan );
+// Ivy_ManMakeSeq( pMan, nLatches, pInit );
+// Ivy_ManPrintStats( pMan );
+
+// Ivy_ManRequiredLevels( pMan );
+
+// Ivy_FastMapPerform( pMan, 8 );
+ Ivy_ManStop( pMan );
+ return NULL;
+
+
+/*
+ // convert from the AIG manager
+ pNtkAig = Abc_NtkFromIvy( pNtk, pMan );
+// pNtkAig = Abc_NtkFromIvySeq( pNtk, pMan );
+ Ivy_ManStop( pMan );
+
+ // report the cleanup results
+ if ( fCleanup && (nNodes = Abc_AigCleanup(pNtkAig->pManFunc)) )
+ printf( "Warning: AIG cleanup removed %d nodes (this is not a bug).\n", nNodes );
+ // duplicate EXDC
+ if ( pNtk->pExdc )
+ pNtkAig->pExdc = Abc_NtkDup( pNtk->pExdc );
+ // make sure everything is okay
+ if ( !Abc_NtkCheck( pNtkAig ) )
+ {
+ FREE( pInit );
+ printf( "Abc_NtkStrash: The network check has failed.\n" );
+ Abc_NtkDelete( pNtkAig );
+ return NULL;
+ }
+
+ FREE( pInit );
+ return pNtkAig;
+*/
+}
+
+
+
+/**Function*************************************************************
+
+ Synopsis [Converts the network from the AIG manager into ABC.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Abc_Ntk_t * Abc_NtkFromIvy( Abc_Ntk_t * pNtkOld, Ivy_Man_t * pMan )
+{
+ Vec_Int_t * vNodes;
+ Abc_Ntk_t * pNtk;
+ Abc_Obj_t * pObj, * pObjNew, * pFaninNew, * pFaninNew0, * pFaninNew1;
+ Ivy_Obj_t * pNode;
+ int i;
+ // perform strashing
+ pNtk = Abc_NtkStartFrom( pNtkOld, ABC_NTK_STRASH, ABC_FUNC_AIG );
+ // transfer the pointers to the basic nodes
+ Ivy_ManConst1(pMan)->TravId = Abc_EdgeFromNode( Abc_AigConst1(pNtk) );
+ Abc_NtkForEachCi( pNtkOld, pObj, i )
+ Ivy_ManPi(pMan, i)->TravId = Abc_EdgeFromNode( pObj->pCopy );
+ // rebuild the AIG
+ vNodes = Ivy_ManDfs( pMan );
+ Ivy_ManForEachNodeVec( pMan, vNodes, pNode, i )
+ {
+ // add the first fanin
+ pFaninNew0 = Abc_ObjFanin0Ivy( pNtk, pNode );
+ if ( Ivy_ObjIsBuf(pNode) )
+ {
+ pNode->TravId = Abc_EdgeFromNode( pFaninNew0 );
+ continue;
+ }
+ // add the second fanin
+ pFaninNew1 = Abc_ObjFanin1Ivy( pNtk, pNode );
+ // create the new node
+ if ( Ivy_ObjIsExor(pNode) )
+ pObjNew = Abc_AigXor( pNtk->pManFunc, pFaninNew0, pFaninNew1 );
+ else
+ pObjNew = Abc_AigAnd( pNtk->pManFunc, pFaninNew0, pFaninNew1 );
+ pNode->TravId = Abc_EdgeFromNode( pObjNew );
+ }
+ // connect the PO nodes
+ Abc_NtkForEachCo( pNtkOld, pObj, i )
+ {
+ pFaninNew = Abc_ObjFanin0Ivy( pNtk, Ivy_ManPo(pMan, i) );
+ Abc_ObjAddFanin( pObj->pCopy, pFaninNew );
+ }
+ Vec_IntFree( vNodes );
+ if ( !Abc_NtkCheck( pNtk ) )
+ fprintf( stdout, "Abc_NtkFromIvy(): Network check has failed.\n" );
+ return pNtk;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Converts the network from the AIG manager into ABC.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Abc_Ntk_t * Abc_NtkFromIvySeq( Abc_Ntk_t * pNtkOld, Ivy_Man_t * pMan, int fHaig )
+{
+ Vec_Int_t * vNodes, * vLatches;
+ Abc_Ntk_t * pNtk;
+ Abc_Obj_t * pObj, * pObjNew, * pFaninNew, * pFaninNew0, * pFaninNew1;
+ Ivy_Obj_t * pNode, * pTemp;
+ int i;
+// assert( Ivy_ManLatchNum(pMan) > 0 );
+ // perform strashing
+ pNtk = Abc_NtkStartFromNoLatches( pNtkOld, ABC_NTK_STRASH, ABC_FUNC_AIG );
+ // transfer the pointers to the basic nodes
+ Ivy_ManConst1(pMan)->TravId = Abc_EdgeFromNode( Abc_AigConst1(pNtk) );
+ Abc_NtkForEachPi( pNtkOld, pObj, i )
+ Ivy_ManPi(pMan, i)->TravId = Abc_EdgeFromNode( pObj->pCopy );
+ // create latches of the new network
+ vNodes = Ivy_ManDfsSeq( pMan, &vLatches );
+ Ivy_ManForEachNodeVec( pMan, vLatches, pNode, i )
+ {
+ pObjNew = Abc_NtkCreateLatch( pNtk );
+ pFaninNew0 = Abc_NtkCreateBi( pNtk );
+ pFaninNew1 = Abc_NtkCreateBo( pNtk );
+ Abc_ObjAddFanin( pObjNew, pFaninNew0 );
+ Abc_ObjAddFanin( pFaninNew1, pObjNew );
+ if ( fHaig || Ivy_ObjInit(pNode) == IVY_INIT_DC )
+ Abc_LatchSetInitDc( pObjNew );
+ else if ( Ivy_ObjInit(pNode) == IVY_INIT_1 )
+ Abc_LatchSetInit1( pObjNew );
+ else if ( Ivy_ObjInit(pNode) == IVY_INIT_0 )
+ Abc_LatchSetInit0( pObjNew );
+ else assert( 0 );
+ pNode->TravId = Abc_EdgeFromNode( pFaninNew1 );
+ }
+ Abc_NtkAddDummyBoxNames( pNtk );
+ // rebuild the AIG
+ Ivy_ManForEachNodeVec( pMan, vNodes, pNode, i )
+ {
+ // add the first fanin
+ pFaninNew0 = Abc_ObjFanin0Ivy( pNtk, pNode );
+ if ( Ivy_ObjIsBuf(pNode) )
+ {
+ pNode->TravId = Abc_EdgeFromNode( pFaninNew0 );
+ continue;
+ }
+ // add the second fanin
+ pFaninNew1 = Abc_ObjFanin1Ivy( pNtk, pNode );
+ // create the new node
+ if ( Ivy_ObjIsExor(pNode) )
+ pObjNew = Abc_AigXor( pNtk->pManFunc, pFaninNew0, pFaninNew1 );
+ else
+ pObjNew = Abc_AigAnd( pNtk->pManFunc, pFaninNew0, pFaninNew1 );
+ pNode->TravId = Abc_EdgeFromNode( pObjNew );
+ // process the choice nodes
+ if ( fHaig && pNode->pEquiv && Ivy_ObjRefs(pNode) > 0 )
+ {
+ pFaninNew = Abc_EdgeToNode( pNtk, pNode->TravId );
+// pFaninNew->fPhase = 0;
+ assert( !Ivy_IsComplement(pNode->pEquiv) );
+ for ( pTemp = pNode->pEquiv; pTemp != pNode; pTemp = Ivy_Regular(pTemp->pEquiv) )
+ {
+ pFaninNew1 = Abc_EdgeToNode( pNtk, pTemp->TravId );
+// pFaninNew1->fPhase = Ivy_IsComplement( pTemp->pEquiv );
+ pFaninNew->pData = pFaninNew1;
+ pFaninNew = pFaninNew1;
+ }
+ pFaninNew->pData = NULL;
+// printf( "Writing choice node %d.\n", pNode->Id );
+ }
+ }
+ // connect the PO nodes
+ Abc_NtkForEachPo( pNtkOld, pObj, i )
+ {
+ pFaninNew = Abc_ObjFanin0Ivy( pNtk, Ivy_ManPo(pMan, i) );
+ Abc_ObjAddFanin( pObj->pCopy, pFaninNew );
+ }
+ // connect the latches
+ Ivy_ManForEachNodeVec( pMan, vLatches, pNode, i )
+ {
+ pFaninNew = Abc_ObjFanin0Ivy( pNtk, pNode );
+ Abc_ObjAddFanin( Abc_ObjFanin0(Abc_NtkBox(pNtk, i)), pFaninNew );
+ }
+ Vec_IntFree( vLatches );
+ Vec_IntFree( vNodes );
+ if ( !Abc_NtkCheck( pNtk ) )
+ fprintf( stdout, "Abc_NtkFromIvySeq(): Network check has failed.\n" );
+ return pNtk;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Converts the network from the AIG manager into ABC.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Ivy_Man_t * Abc_NtkToIvy( Abc_Ntk_t * pNtkOld )
+{
+ Ivy_Man_t * pMan;
+ Abc_Obj_t * pObj;
+ Ivy_Obj_t * pFanin;
+ int i;
+ // create the manager
+ assert( Abc_NtkHasSop(pNtkOld) || Abc_NtkIsStrash(pNtkOld) );
+ pMan = Ivy_ManStart();
+ // create the PIs
+ if ( Abc_NtkIsStrash(pNtkOld) )
+ Abc_AigConst1(pNtkOld)->pCopy = (Abc_Obj_t *)Ivy_ManConst1(pMan);
+ Abc_NtkForEachCi( pNtkOld, pObj, i )
+ pObj->pCopy = (Abc_Obj_t *)Ivy_ObjCreatePi(pMan);
+ // perform the conversion of the internal nodes
+ Abc_NtkStrashPerformAig( pNtkOld, pMan );
+ // create the POs
+ Abc_NtkForEachCo( pNtkOld, pObj, i )
+ {
+ pFanin = (Ivy_Obj_t *)Abc_ObjFanin0(pObj)->pCopy;
+ pFanin = Ivy_NotCond( pFanin, Abc_ObjFaninC0(pObj) );
+ Ivy_ObjCreatePo( pMan, pFanin );
+ }
+ Ivy_ManCleanup( pMan );
+ return pMan;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Prepares the network for strashing.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Abc_NtkStrashPerformAig( Abc_Ntk_t * pNtk, Ivy_Man_t * pMan )
+{
+// ProgressBar * pProgress;
+ Vec_Ptr_t * vNodes;
+ Abc_Obj_t * pNode;
+ int i;
+ vNodes = Abc_NtkDfs( pNtk, 0 );
+// pProgress = Extra_ProgressBarStart( stdout, vNodes->nSize );
+ Vec_PtrForEachEntry( vNodes, pNode, i )
+ {
+// Extra_ProgressBarUpdate( pProgress, i, NULL );
+ pNode->pCopy = (Abc_Obj_t *)Abc_NodeStrashAig( pMan, pNode );
+ }
+// Extra_ProgressBarStop( pProgress );
+ Vec_PtrFree( vNodes );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Strashes one logic node.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Ivy_Obj_t * Abc_NodeStrashAig( Ivy_Man_t * pMan, Abc_Obj_t * pNode )
+{
+ int fUseFactor = 1;
+ char * pSop;
+ Ivy_Obj_t * pFanin0, * pFanin1;
+
+ assert( Abc_ObjIsNode(pNode) );
+
+ // consider the case when the graph is an AIG
+ if ( Abc_NtkIsStrash(pNode->pNtk) )
+ {
+ if ( Abc_AigNodeIsConst(pNode) )
+ return Ivy_ManConst1(pMan);
+ pFanin0 = (Ivy_Obj_t *)Abc_ObjFanin0(pNode)->pCopy;
+ pFanin0 = Ivy_NotCond( pFanin0, Abc_ObjFaninC0(pNode) );
+ pFanin1 = (Ivy_Obj_t *)Abc_ObjFanin1(pNode)->pCopy;
+ pFanin1 = Ivy_NotCond( pFanin1, Abc_ObjFaninC1(pNode) );
+ return Ivy_And( pMan, pFanin0, pFanin1 );
+ }
+
+ // get the SOP of the node
+ if ( Abc_NtkHasMapping(pNode->pNtk) )
+ pSop = Mio_GateReadSop(pNode->pData);
+ else
+ pSop = pNode->pData;
+
+ // consider the constant node
+ if ( Abc_NodeIsConst(pNode) )
+ return Ivy_NotCond( Ivy_ManConst1(pMan), Abc_SopIsConst0(pSop) );
+
+ // consider the special case of EXOR function
+ if ( Abc_SopIsExorType(pSop) )
+ return Abc_NodeStrashAigExorAig( pMan, pNode, pSop );
+
+ // decide when to use factoring
+ if ( fUseFactor && Abc_ObjFaninNum(pNode) > 2 && Abc_SopGetCubeNum(pSop) > 1 )
+ return Abc_NodeStrashAigFactorAig( pMan, pNode, pSop );
+ return Abc_NodeStrashAigSopAig( pMan, pNode, pSop );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Strashes one logic node using its SOP.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Ivy_Obj_t * Abc_NodeStrashAigSopAig( Ivy_Man_t * pMan, Abc_Obj_t * pNode, char * pSop )
+{
+ Abc_Obj_t * pFanin;
+ Ivy_Obj_t * pAnd, * pSum;
+ char * pCube;
+ int i, nFanins;
+
+ // get the number of node's fanins
+ nFanins = Abc_ObjFaninNum( pNode );
+ assert( nFanins == Abc_SopGetVarNum(pSop) );
+ // go through the cubes of the node's SOP
+ pSum = Ivy_Not( Ivy_ManConst1(pMan) );
+ Abc_SopForEachCube( pSop, nFanins, pCube )
+ {
+ // create the AND of literals
+ pAnd = Ivy_ManConst1(pMan);
+ Abc_ObjForEachFanin( pNode, pFanin, i ) // pFanin can be a net
+ {
+ if ( pCube[i] == '1' )
+ pAnd = Ivy_And( pMan, pAnd, (Ivy_Obj_t *)pFanin->pCopy );
+ else if ( pCube[i] == '0' )
+ pAnd = Ivy_And( pMan, pAnd, Ivy_Not((Ivy_Obj_t *)pFanin->pCopy) );
+ }
+ // add to the sum of cubes
+ pSum = Ivy_Or( pMan, pSum, pAnd );
+ }
+ // decide whether to complement the result
+ if ( Abc_SopIsComplement(pSop) )
+ pSum = Ivy_Not(pSum);
+ return pSum;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Strashed n-input XOR function.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Ivy_Obj_t * Abc_NodeStrashAigExorAig( Ivy_Man_t * pMan, Abc_Obj_t * pNode, char * pSop )
+{
+ Abc_Obj_t * pFanin;
+ Ivy_Obj_t * pSum;
+ int i, nFanins;
+ // get the number of node's fanins
+ nFanins = Abc_ObjFaninNum( pNode );
+ assert( nFanins == Abc_SopGetVarNum(pSop) );
+ // go through the cubes of the node's SOP
+ pSum = Ivy_Not( Ivy_ManConst1(pMan) );
+ for ( i = 0; i < nFanins; i++ )
+ {
+ pFanin = Abc_ObjFanin( pNode, i );
+ pSum = Ivy_Exor( pMan, pSum, (Ivy_Obj_t *)pFanin->pCopy );
+ }
+ if ( Abc_SopIsComplement(pSop) )
+ pSum = Ivy_Not(pSum);
+ return pSum;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Strashes one logic node using its SOP.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Ivy_Obj_t * Abc_NodeStrashAigFactorAig( Ivy_Man_t * pMan, Abc_Obj_t * pRoot, char * pSop )
+{
+ Dec_Graph_t * pFForm;
+ Dec_Node_t * pNode;
+ Ivy_Obj_t * pAnd;
+ int i;
+
+// extern Ivy_Obj_t * Dec_GraphToNetworkAig( Ivy_Man_t * pMan, Dec_Graph_t * pGraph );
+ extern Ivy_Obj_t * Dec_GraphToNetworkIvy( Ivy_Man_t * pMan, Dec_Graph_t * pGraph );
+
+// assert( 0 );
+
+ // perform factoring
+ pFForm = Dec_Factor( pSop );
+ // collect the fanins
+ Dec_GraphForEachLeaf( pFForm, pNode, i )
+ pNode->pFunc = Abc_ObjFanin(pRoot,i)->pCopy;
+ // perform strashing
+// pAnd = Dec_GraphToNetworkAig( pMan, pFForm );
+ pAnd = Dec_GraphToNetworkIvy( pMan, pFForm );
+// pAnd = NULL;
+
+ Dec_GraphFree( pFForm );
+ return pAnd;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Strashes one logic node using its SOP.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Vec_Int_t * Abc_NtkCollectLatchValuesIvy( Abc_Ntk_t * pNtk, int fUseDcs )
+{
+ Abc_Obj_t * pLatch;
+ Vec_Int_t * vArray;
+ int i;
+ vArray = Vec_IntAlloc( Abc_NtkLatchNum(pNtk) );
+ Abc_NtkForEachLatch( pNtk, pLatch, i )
+ {
+ if ( fUseDcs || Abc_LatchIsInitDc(pLatch) )
+ Vec_IntPush( vArray, IVY_INIT_DC );
+ else if ( Abc_LatchIsInit1(pLatch) )
+ Vec_IntPush( vArray, IVY_INIT_1 );
+ else if ( Abc_LatchIsInit0(pLatch) )
+ Vec_IntPush( vArray, IVY_INIT_0 );
+ else assert( 0 );
+ }
+ return vArray;
+}
+
+////////////////////////////////////////////////////////////////////////
+/// END OF FILE ///
+////////////////////////////////////////////////////////////////////////
+
+
diff --git a/src/base/abci/abcLut.c b/src/base/abci/abcLut.c
new file mode 100644
index 00000000..afa76cc8
--- /dev/null
+++ b/src/base/abci/abcLut.c
@@ -0,0 +1,786 @@
+/**CFile****************************************************************
+
+ FileName [abcLut.c]
+
+ SystemName [ABC: Logic synthesis and verification system.]
+
+ PackageName [Network and node package.]
+
+ Synopsis [Superchoicing for K-LUTs.]
+
+ Author [Alan Mishchenko]
+
+ Affiliation [UC Berkeley]
+
+ Date [Ver. 1.0. Started - June 20, 2005.]
+
+ Revision [$Id: abcLut.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "abc.h"
+#include "cut.h"
+
+////////////////////////////////////////////////////////////////////////
+/// DECLARATIONS ///
+////////////////////////////////////////////////////////////////////////
+
+#define SCL_LUT_MAX 6 // the maximum LUT size
+#define SCL_VARS_MAX 15 // the maximum number of variables
+#define SCL_NODE_MAX 1000 // the maximum number of nodes
+
+typedef struct Abc_ManScl_t_ Abc_ManScl_t;
+struct Abc_ManScl_t_
+{
+ // paramers
+ int nLutSize; // the LUT size
+ int nCutSizeMax; // the max number of leaves of the cone
+ int nNodesMax; // the max number of divisors in the cone
+ int nWords; // the number of machine words in sim info
+ // structural representation of the cone
+ Vec_Ptr_t * vLeaves; // leaves of the cut
+ Vec_Ptr_t * vVolume; // volume of the cut
+ int pBSet[SCL_VARS_MAX]; // bound set
+ // functional representation of the cone
+ unsigned * uTruth; // truth table of the cone
+ // representation of truth tables
+ unsigned ** uVars; // elementary truth tables
+ unsigned ** uSims; // truth tables of the nodes
+ unsigned ** uCofs; // truth tables of the cofactors
+};
+
+static Vec_Ptr_t * s_pLeaves = NULL;
+
+static Cut_Man_t * Abc_NtkStartCutManForScl( Abc_Ntk_t * pNtk, int nLutSize );
+static Abc_ManScl_t * Abc_ManSclStart( int nLutSize, int nCutSizeMax, int nNodesMax );
+static void Abc_ManSclStop( Abc_ManScl_t * p );
+static void Abc_NodeLutMap( Cut_Man_t * pManCuts, Abc_Obj_t * pObj );
+
+static Abc_Obj_t * Abc_NodeSuperChoiceLut( Abc_ManScl_t * pManScl, Abc_Obj_t * pObj );
+static int Abc_NodeDecomposeStep( Abc_ManScl_t * pManScl );
+
+////////////////////////////////////////////////////////////////////////
+/// FUNCTION DEFINITIONS ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+ Synopsis [Performs superchoicing for K-LUTs.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Abc_NtkSuperChoiceLut( Abc_Ntk_t * pNtk, int nLutSize, int nCutSizeMax, int fVerbose )
+{
+ ProgressBar * pProgress;
+ Abc_ManCut_t * pManCut;
+ Abc_ManScl_t * pManScl;
+ Cut_Man_t * pManCuts;
+ Abc_Obj_t * pObj, * pFanin, * pObjTop;
+ int i, LevelMax, nNodes;
+ int nNodesTried, nNodesDec, nNodesExist, nNodesUsed;
+
+ assert( Abc_NtkIsSopLogic(pNtk) );
+ if ( nLutSize < 3 || nLutSize > SCL_LUT_MAX )
+ {
+ printf( "LUT size (%d) does not belong to the interval: 3 <= LUT size <= %d\n", nLutSize, SCL_LUT_MAX );
+ return 0;
+ }
+ if ( nCutSizeMax <= nLutSize || nCutSizeMax > SCL_VARS_MAX )
+ {
+ printf( "Cut size (%d) does not belong to the interval: LUT size (%d) < Cut size <= %d\n", nCutSizeMax, nLutSize, SCL_VARS_MAX );
+ return 0;
+ }
+
+ assert( nLutSize <= SCL_LUT_MAX );
+ assert( nCutSizeMax <= SCL_VARS_MAX );
+ nNodesTried = nNodesDec = nNodesExist = nNodesUsed = 0;
+
+ // set the delays of the CIs
+ Abc_NtkForEachCi( pNtk, pObj, i )
+ pObj->Level = 0;
+
+//Abc_NtkLevel( pNtk );
+
+ // start the managers
+ pManScl = Abc_ManSclStart( nLutSize, nCutSizeMax, 1000 );
+ pManCuts = Abc_NtkStartCutManForScl( pNtk, nLutSize );
+ pManCut = Abc_NtkManCutStart( nCutSizeMax, 100000, 100000, 100000 );
+ s_pLeaves = Abc_NtkManCutReadCutSmall( pManCut );
+ pManScl->vVolume = Abc_NtkManCutReadVisited( pManCut );
+
+ // process each internal node (assuming topological order of nodes!!!)
+ nNodes = Abc_NtkObjNumMax(pNtk);
+ pProgress = Extra_ProgressBarStart( stdout, nNodes );
+ Abc_NtkForEachObj( pNtk, pObj, i )
+ {
+// if ( i != nNodes-1 )
+// continue;
+ Extra_ProgressBarUpdate( pProgress, i, NULL );
+ if ( i >= nNodes )
+ break;
+ if ( Abc_ObjFaninNum(pObj) != 2 )
+ continue;
+ nNodesTried++;
+
+ // map this node using regular cuts
+// pObj->Level = 0;
+ Abc_NodeLutMap( pManCuts, pObj );
+ // compute the cut
+ pManScl->vLeaves = Abc_NodeFindCut( pManCut, pObj, 0 );
+ if ( Vec_PtrSize(pManScl->vLeaves) <= nLutSize )
+ continue;
+ // get the volume of the cut
+ if ( Vec_PtrSize(pManScl->vVolume) > SCL_NODE_MAX )
+ continue;
+ nNodesDec++;
+
+ // decompose the cut
+ pObjTop = Abc_NodeSuperChoiceLut( pManScl, pObj );
+ if ( pObjTop == NULL )
+ continue;
+ nNodesExist++;
+
+ // if there is no delay improvement, skip; otherwise, update level
+ if ( pObjTop->Level >= pObj->Level )
+ {
+ Abc_NtkDeleteObj_rec( pObjTop, 1 );
+ continue;
+ }
+ pObj->Level = pObjTop->Level;
+ nNodesUsed++;
+ }
+ Extra_ProgressBarStop( pProgress );
+
+ // delete the managers
+ Abc_ManSclStop( pManScl );
+ Abc_NtkManCutStop( pManCut );
+ Cut_ManStop( pManCuts );
+
+ // get the largest arrival time
+ LevelMax = 0;
+ Abc_NtkForEachCo( pNtk, pObj, i )
+ {
+ pFanin = Abc_ObjFanin0( pObj );
+ // skip inv/buf
+ if ( Abc_ObjFaninNum(pFanin) == 1 )
+ pFanin = Abc_ObjFanin0( pFanin );
+ // get the new level
+ LevelMax = ABC_MAX( LevelMax, (int)pFanin->Level );
+ }
+
+ if ( fVerbose )
+ printf( "Try = %d. Dec = %d. Exist = %d. Use = %d. SUPER = %d levels of %d-LUTs.\n",
+ nNodesTried, nNodesDec, nNodesExist, nNodesUsed, LevelMax, nLutSize );
+// if ( fVerbose )
+// printf( "The network is superchoiced for %d levels of %d-LUTs.\n", LevelMax, nLutSize );
+
+ // clean the data field
+ Abc_NtkForEachObj( pNtk, pObj, i )
+ pObj->pNext = NULL;
+
+ // check
+ if ( !Abc_NtkCheck( pNtk ) )
+ {
+ printf( "Abc_NtkSuperChoiceLut: The network check has failed.\n" );
+ return 0;
+ }
+ return 1;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Performs LUT mapping of the node.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Abc_NodeLutMap( Cut_Man_t * pManCuts, Abc_Obj_t * pObj )
+{
+ Cut_Cut_t * pCut;
+ Abc_Obj_t * pFanin;
+ int i, DelayMax;
+ pCut = (Cut_Cut_t *)Abc_NodeGetCutsRecursive( pManCuts, pObj, 0, 0 );
+ assert( pCut != NULL );
+ assert( pObj->Level == 0 );
+ // go through the cuts
+ pObj->Level = ABC_INFINITY;
+ for ( pCut = pCut->pNext; pCut; pCut = pCut->pNext )
+ {
+ DelayMax = 0;
+ for ( i = 0; i < (int)pCut->nLeaves; i++ )
+ {
+ pFanin = Abc_NtkObj( pObj->pNtk, pCut->pLeaves[i] );
+// assert( Abc_ObjIsCi(pFanin) || pFanin->Level > 0 ); // should hold if node ordering is topological
+ if ( DelayMax < (int)pFanin->Level )
+ DelayMax = pFanin->Level;
+ }
+ if ( (int)pObj->Level > DelayMax )
+ pObj->Level = DelayMax;
+ }
+ assert( pObj->Level < ABC_INFINITY );
+ pObj->Level++;
+// printf( "%d(%d) ", pObj->Id, pObj->Level );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Starts the cut manager for rewriting.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Cut_Man_t * Abc_NtkStartCutManForScl( Abc_Ntk_t * pNtk, int nLutSize )
+{
+ static Cut_Params_t Params, * pParams = &Params;
+ Cut_Man_t * pManCut;
+ Abc_Obj_t * pObj;
+ int i;
+ // start the cut manager
+ memset( pParams, 0, sizeof(Cut_Params_t) );
+ pParams->nVarsMax = nLutSize; // the max cut size ("k" of the k-feasible cuts)
+ pParams->nKeepMax = 500; // the max number of cuts kept at a node
+ pParams->fTruth = 0; // compute truth tables
+ pParams->fFilter = 1; // filter dominated cuts
+ pParams->fSeq = 0; // compute sequential cuts
+ pParams->fDrop = 0; // drop cuts on the fly
+ pParams->fVerbose = 0; // the verbosiness flag
+ pParams->nIdsMax = Abc_NtkObjNumMax( pNtk );
+ pManCut = Cut_ManStart( pParams );
+ if ( pParams->fDrop )
+ Cut_ManSetFanoutCounts( pManCut, Abc_NtkFanoutCounts(pNtk) );
+ // set cuts for PIs
+ Abc_NtkForEachCi( pNtk, pObj, i )
+ if ( Abc_ObjFanoutNum(pObj) > 0 )
+ Cut_NodeSetTriv( pManCut, pObj->Id );
+ return pManCut;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Starts the manager.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Abc_ManScl_t * Abc_ManSclStart( int nLutSize, int nCutSizeMax, int nNodesMax )
+{
+ Abc_ManScl_t * p;
+ int i, k;
+ assert( sizeof(unsigned) == 4 );
+ p = ALLOC( Abc_ManScl_t, 1 );
+ memset( p, 0, sizeof(Abc_ManScl_t) );
+ p->nLutSize = nLutSize;
+ p->nCutSizeMax = nCutSizeMax;
+ p->nNodesMax = nNodesMax;
+ p->nWords = Extra_TruthWordNum(nCutSizeMax);
+ // allocate simulation info
+ p->uVars = (unsigned **)Extra_ArrayAlloc( nCutSizeMax, p->nWords, 4 );
+ p->uSims = (unsigned **)Extra_ArrayAlloc( nNodesMax, p->nWords, 4 );
+ p->uCofs = (unsigned **)Extra_ArrayAlloc( 2 << nLutSize, p->nWords, 4 );
+ memset( p->uVars[0], 0, nCutSizeMax * p->nWords * 4 );
+ // assign elementary truth tables
+ for ( k = 0; k < p->nCutSizeMax; k++ )
+ for ( i = 0; i < p->nWords * 32; i++ )
+ if ( i & (1 << k) )
+ p->uVars[k][i>>5] |= (1 << (i&31));
+ // other data structures
+// p->vBound = Vec_IntAlloc( nCutSizeMax );
+ return p;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Stops the manager.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Abc_ManSclStop( Abc_ManScl_t * p )
+{
+// Vec_IntFree( p->vBound );
+ free( p->uVars );
+ free( p->uSims );
+ free( p->uCofs );
+ free( p );
+}
+
+
+/**Function*************************************************************
+
+ Synopsis [Performs superchoicing for one node.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+unsigned * Abc_NodeSuperChoiceTruth( Abc_ManScl_t * pManScl )
+{
+ Abc_Obj_t * pObj;
+ unsigned * puData0, * puData1, * puData;
+ char * pSop;
+ int i, k;
+ // set elementary truth tables
+ Vec_PtrForEachEntry( pManScl->vLeaves, pObj, i )
+ pObj->pNext = (Abc_Obj_t *)pManScl->uVars[i];
+ // compute truth tables for internal nodes
+ Vec_PtrForEachEntry( pManScl->vVolume, pObj, i )
+ {
+ // set storage for the node's simulation info
+ pObj->pNext = (Abc_Obj_t *)pManScl->uSims[i];
+ // get pointer to the simulation info
+ puData = (unsigned *)pObj->pNext;
+ puData0 = (unsigned *)Abc_ObjFanin0(pObj)->pNext;
+ puData1 = (unsigned *)Abc_ObjFanin1(pObj)->pNext;
+ // simulate
+ pSop = pObj->pData;
+ if ( pSop[0] == '0' && pSop[1] == '0' )
+ for ( k = 0; k < pManScl->nWords; k++ )
+ puData[k] = ~puData0[k] & ~puData1[k];
+ else if ( pSop[0] == '0' )
+ for ( k = 0; k < pManScl->nWords; k++ )
+ puData[k] = ~puData0[k] & puData1[k];
+ else if ( pSop[1] == '0' )
+ for ( k = 0; k < pManScl->nWords; k++ )
+ puData[k] = puData0[k] & ~puData1[k];
+ else
+ for ( k = 0; k < pManScl->nWords; k++ )
+ puData[k] = puData0[k] & puData1[k];
+ }
+ return puData;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Performs superchoicing for one node.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Abc_NodeSuperChoiceCollect2_rec( Abc_Obj_t * pObj, Vec_Ptr_t * vVolume )
+{
+ if ( pObj->fMarkC )
+ return;
+ pObj->fMarkC = 1;
+ assert( Abc_ObjFaninNum(pObj) == 2 );
+ Abc_NodeSuperChoiceCollect2_rec( Abc_ObjFanin0(pObj), vVolume );
+ Abc_NodeSuperChoiceCollect2_rec( Abc_ObjFanin1(pObj), vVolume );
+ Vec_PtrPush( vVolume, pObj );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Performs superchoicing for one node.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Abc_NodeSuperChoiceCollect2( Abc_Obj_t * pRoot, Vec_Ptr_t * vLeaves, Vec_Ptr_t * vVolume )
+{
+ Abc_Obj_t * pObj;
+ int i;
+ Vec_PtrForEachEntry( vLeaves, pObj, i )
+ pObj->fMarkC = 1;
+ Vec_PtrClear( vVolume );
+ Abc_NodeSuperChoiceCollect2_rec( pRoot, vVolume );
+ Vec_PtrForEachEntry( vLeaves, pObj, i )
+ pObj->fMarkC = 0;
+ Vec_PtrForEachEntry( vVolume, pObj, i )
+ pObj->fMarkC = 0;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Performs superchoicing for one node.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Abc_NodeSuperChoiceCollect_rec( Abc_Obj_t * pObj, Vec_Ptr_t * vLeaves, Vec_Ptr_t * vVolume )
+{
+ if ( pObj->fMarkB )
+ {
+ Vec_PtrPush( vLeaves, pObj );
+ pObj->fMarkB = 0;
+ }
+ if ( pObj->fMarkC )
+ return;
+ pObj->fMarkC = 1;
+ assert( Abc_ObjFaninNum(pObj) == 2 );
+ Abc_NodeSuperChoiceCollect_rec( Abc_ObjFanin0(pObj), vLeaves, vVolume );
+ Abc_NodeSuperChoiceCollect_rec( Abc_ObjFanin1(pObj), vLeaves, vVolume );
+ Vec_PtrPush( vVolume, pObj );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Performs superchoicing for one node.]
+
+ Description [Orders the leaves topologically.]
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Abc_NodeSuperChoiceCollect( Abc_Obj_t * pRoot, Vec_Ptr_t * vLeaves, Vec_Ptr_t * vVolume )
+{
+ Abc_Obj_t * pObj;
+ int i, nLeaves;
+ nLeaves = Vec_PtrSize(vLeaves);
+ Vec_PtrForEachEntry( vLeaves, pObj, i )
+ pObj->fMarkB = pObj->fMarkC = 1;
+ Vec_PtrClear( vVolume );
+ Vec_PtrClear( vLeaves );
+ Abc_NodeSuperChoiceCollect_rec( pRoot, vLeaves, vVolume );
+ assert( Vec_PtrSize(vLeaves) == nLeaves );
+ Vec_PtrForEachEntry( vLeaves, pObj, i )
+ pObj->fMarkC = 0;
+ Vec_PtrForEachEntry( vVolume, pObj, i )
+ pObj->fMarkC = 0;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Performs superchoicing for one node.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Abc_NodeLeavesRemove( Vec_Ptr_t * vLeaves, unsigned uPhase, int nVars )
+{
+ int i;
+ for ( i = nVars - 1; i >= 0; i-- )
+ if ( uPhase & (1 << i) )
+ Vec_PtrRemove( vLeaves, Vec_PtrEntry(vLeaves, i) );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Performs superchoicing for one node.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Abc_NodeGetLevel( Abc_Obj_t * pObj )
+{
+ Abc_Obj_t * pFanin;
+ int i, Level;
+ Level = 0;
+ Abc_ObjForEachFanin( pObj, pFanin, i )
+ Level = ABC_MAX( Level, (int)pFanin->Level );
+ return Level + 1;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Performs superchoicing for one node.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Abc_Obj_t * Abc_NodeSuperChoiceLut( Abc_ManScl_t * p, Abc_Obj_t * pObj )
+{
+ Abc_Obj_t * pFanin, * pObjNew;
+ int i, nVars, uSupport, nSuppVars;
+ // collect the cone using DFS (excluding leaves)
+ Abc_NodeSuperChoiceCollect2( pObj, p->vLeaves, p->vVolume );
+ assert( Vec_PtrEntryLast(p->vVolume) == pObj );
+ // compute the truth table
+ p->uTruth = Abc_NodeSuperChoiceTruth( p );
+ // get the support of this truth table
+ nVars = Vec_PtrSize(p->vLeaves);
+ uSupport = Extra_TruthSupport(p->uTruth, nVars);
+ nSuppVars = Extra_WordCountOnes(uSupport);
+ assert( nSuppVars <= nVars );
+ if ( nSuppVars == 0 )
+ {
+ pObj->Level = 0;
+ return NULL;
+ }
+ if ( nSuppVars == 1 )
+ {
+ // find the variable
+ for ( i = 0; i < nVars; i++ )
+ if ( uSupport & (1 << i) )
+ break;
+ assert( i < nVars );
+ pFanin = Vec_PtrEntry( p->vLeaves, i );
+ pObj->Level = pFanin->Level;
+ return NULL;
+ }
+ // support-minimize the truth table
+ if ( nSuppVars != nVars )
+ {
+ Extra_TruthShrink( p->uCofs[0], p->uTruth, nSuppVars, nVars, uSupport );
+ Extra_TruthCopy( p->uTruth, p->uCofs[0], nVars );
+ Abc_NodeLeavesRemove( p->vLeaves, ((1 << nVars) - 1) & ~uSupport, nVars );
+ }
+// return NULL;
+ // decompose the truth table recursively
+ while ( Vec_PtrSize(p->vLeaves) > p->nLutSize )
+ if ( !Abc_NodeDecomposeStep( p ) )
+ {
+ Vec_PtrForEachEntry( p->vLeaves, pFanin, i )
+ if ( Abc_ObjIsNode(pFanin) && Abc_ObjFanoutNum(pFanin) == 0 )
+ Abc_NtkDeleteObj_rec( pFanin, 1 );
+ return NULL;
+ }
+ // create the topmost node
+ pObjNew = Abc_NtkCreateNode( pObj->pNtk );
+ Vec_PtrForEachEntry( p->vLeaves, pFanin, i )
+ Abc_ObjAddFanin( pObjNew, pFanin );
+ // create the function
+ pObjNew->pData = Abc_SopCreateFromTruth( pObj->pNtk->pManFunc, Vec_PtrSize(p->vLeaves), p->uTruth ); // need ISOP
+ pObjNew->Level = Abc_NodeGetLevel( pObjNew );
+ return pObjNew;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Procedure used for sorting the nodes in increasing order of levels.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Abc_NodeCompareLevelsInc( int * pp1, int * pp2 )
+{
+ Abc_Obj_t * pNode1, * pNode2;
+ pNode1 = Vec_PtrEntry(s_pLeaves, *pp1);
+ pNode2 = Vec_PtrEntry(s_pLeaves, *pp2);
+ if ( pNode1->Level < pNode2->Level )
+ return -1;
+ if ( pNode1->Level > pNode2->Level )
+ return 1;
+ return 0;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Selects the earliest arriving nodes from the array.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Abc_NodeDecomposeSort( Abc_Obj_t ** pLeaves, int nVars, int * pBSet, int nLutSize )
+{
+ Abc_Obj_t * pTemp[SCL_VARS_MAX];
+ int i, k, kBest, LevelMin;
+ assert( nLutSize < nVars );
+ assert( nVars <= SCL_VARS_MAX );
+ // copy nodes into the internal storage
+// printf( "(" );
+ for ( i = 0; i < nVars; i++ )
+ {
+ pTemp[i] = pLeaves[i];
+// printf( " %d", pLeaves[i]->Level );
+ }
+// printf( " )\n" );
+ // choose one node at a time
+ for ( i = 0; i < nLutSize; i++ )
+ {
+ kBest = -1;
+ LevelMin = ABC_INFINITY;
+ for ( k = 0; k < nVars; k++ )
+ if ( pTemp[k] && LevelMin > (int)pTemp[k]->Level )
+ {
+ LevelMin = pTemp[k]->Level;
+ kBest = k;
+ }
+ pBSet[i] = kBest;
+ pTemp[kBest] = NULL;
+ }
+}
+
+/**Function*************************************************************
+
+ Synopsis [Performs superchoicing for one node.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Abc_NodeDecomposeStep( Abc_ManScl_t * p )
+{
+ static char pCofClasses[1<<SCL_LUT_MAX][1<<SCL_LUT_MAX];
+ static char nCofClasses[1<<SCL_LUT_MAX];
+ Abc_Ntk_t * pNtk;
+ Abc_Obj_t * pObjNew, * pFanin, * pNodesNew[SCL_LUT_MAX];
+ unsigned * pTruthCof, * pTruthClass, * pTruth, uPhase;
+ int i, k, c, v, w, nVars, nVarsNew, nClasses, nCofs;
+ // set the network
+ pNtk = ((Abc_Obj_t *)Vec_PtrEntry(p->vLeaves, 0))->pNtk;
+ // find the earliest nodes
+ nVars = Vec_PtrSize(p->vLeaves);
+ assert( nVars > p->nLutSize );
+/*
+ for ( v = 0; v < nVars; v++ )
+ p->pBSet[v] = v;
+ qsort( (void *)p->pBSet, nVars, sizeof(int),
+ (int (*)(const void *, const void *)) Abc_NodeCompareLevelsInc );
+*/
+ Abc_NodeDecomposeSort( (Abc_Obj_t **)Vec_PtrArray(p->vLeaves), Vec_PtrSize(p->vLeaves), p->pBSet, p->nLutSize );
+ assert( ((Abc_Obj_t *)Vec_PtrEntry(p->vLeaves, p->pBSet[0]))->Level <=
+ ((Abc_Obj_t *)Vec_PtrEntry(p->vLeaves, p->pBSet[1]))->Level );
+ // cofactor w.r.t. the selected variables
+ Extra_TruthCopy( p->uCofs[1], p->uTruth, nVars );
+ c = 2;
+ for ( v = 0; v < p->nLutSize; v++ )
+ for ( k = 0; k < (1<<v); k++ )
+ {
+ Extra_TruthCopy( p->uCofs[c], p->uCofs[c/2], nVars );
+ Extra_TruthCopy( p->uCofs[c+1], p->uCofs[c/2], nVars );
+ Extra_TruthCofactor0( p->uCofs[c], nVars, p->pBSet[v] );
+ Extra_TruthCofactor1( p->uCofs[c+1], nVars, p->pBSet[v] );
+ c += 2;
+ }
+ assert( c == (2 << p->nLutSize) );
+ // count unique cofactors
+ nClasses = 0;
+ nCofs = (1 << p->nLutSize);
+ for ( i = 0; i < nCofs; i++ )
+ {
+ pTruthCof = p->uCofs[ nCofs + i ];
+ for ( k = 0; k < nClasses; k++ )
+ {
+ pTruthClass = p->uCofs[ nCofs + pCofClasses[k][0] ];
+ if ( Extra_TruthIsEqual( pTruthCof, pTruthClass, nVars ) )
+ {
+ pCofClasses[k][ nCofClasses[k]++ ] = i;
+ break;
+ }
+ }
+ if ( k != nClasses )
+ continue;
+ // not found
+ pCofClasses[nClasses][0] = i;
+ nCofClasses[nClasses] = 1;
+ nClasses++;
+ if ( nClasses > nCofs/2 )
+ return 0;
+ }
+ // the number of cofactors is acceptable
+ nVarsNew = Extra_Base2Log( nClasses );
+ assert( nVarsNew < p->nLutSize );
+ // create the remainder truth table
+ // for each class of cofactors, multiply cofactor truth table by its code
+ Extra_TruthClear( p->uTruth, nVars );
+ for ( k = 0; k < nClasses; k++ )
+ {
+ pTruthClass = p->uCofs[ nCofs + pCofClasses[k][0] ];
+ for ( v = 0; v < nVarsNew; v++ )
+ if ( k & (1 << v) )
+ Extra_TruthAnd( pTruthClass, pTruthClass, p->uVars[p->pBSet[v]], nVars );
+ else
+ Extra_TruthSharp( pTruthClass, pTruthClass, p->uVars[p->pBSet[v]], nVars );
+ Extra_TruthOr( p->uTruth, p->uTruth, pTruthClass, nVars );
+ }
+ // create nodes
+ pTruth = p->uCofs[0];
+ for ( v = 0; v < nVarsNew; v++ )
+ {
+ Extra_TruthClear( pTruth, p->nLutSize );
+ for ( k = 0; k < nClasses; k++ )
+ if ( k & (1 << v) )
+ for ( i = 0; i < nCofClasses[k]; i++ )
+ {
+ pTruthCof = p->uCofs[1];
+ Extra_TruthFill( pTruthCof, p->nLutSize );
+ for ( w = 0; w < p->nLutSize; w++ )
+ if ( pCofClasses[k][i] & (1 << (p->nLutSize-1-w)) )
+ Extra_TruthAnd( pTruthCof, pTruthCof, p->uVars[w], p->nLutSize );
+ else
+ Extra_TruthSharp( pTruthCof, pTruthCof, p->uVars[w], p->nLutSize );
+ Extra_TruthOr( pTruth, pTruth, pTruthCof, p->nLutSize );
+ }
+ // implement the node
+ pObjNew = Abc_NtkCreateNode( pNtk );
+ for ( i = 0; i < p->nLutSize; i++ )
+ {
+ pFanin = Vec_PtrEntry( p->vLeaves, p->pBSet[i] );
+ Abc_ObjAddFanin( pObjNew, pFanin );
+ }
+ // create the function
+ pObjNew->pData = Abc_SopCreateFromTruth( pNtk->pManFunc, p->nLutSize, pTruth ); // need ISOP
+ pObjNew->Level = Abc_NodeGetLevel( pObjNew );
+ pNodesNew[v] = pObjNew;
+ }
+ // put the new nodes back into the list
+ for ( v = 0; v < nVarsNew; v++ )
+ Vec_PtrWriteEntry( p->vLeaves, p->pBSet[v], pNodesNew[v] );
+ // compute the variables that should be removed
+ uPhase = 0;
+ for ( v = nVarsNew; v < p->nLutSize; v++ )
+ uPhase |= (1 << p->pBSet[v]);
+ // remove entries from the array
+ Abc_NodeLeavesRemove( p->vLeaves, uPhase, nVars );
+ // update truth table
+ Extra_TruthShrink( p->uCofs[0], p->uTruth, nVars - p->nLutSize + nVarsNew, nVars, ((1 << nVars) - 1) & ~uPhase );
+ Extra_TruthCopy( p->uTruth, p->uCofs[0], nVars );
+ assert( !Extra_TruthVarInSupport( p->uTruth, nVars, nVars - p->nLutSize + nVarsNew ) );
+ return 1;
+}
+
+////////////////////////////////////////////////////////////////////////
+/// END OF FILE ///
+////////////////////////////////////////////////////////////////////////
+
+
diff --git a/src/base/abci/abcMap.c b/src/base/abci/abcMap.c
index ec5352cb..d4d50923 100644
--- a/src/base/abci/abcMap.c
+++ b/src/base/abci/abcMap.c
@@ -40,7 +40,7 @@ static Abc_Obj_t * Abc_NodeFromMapSuperChoice_rec( Abc_Ntk_t * pNtkNew, Map_Sup
////////////////////////////////////////////////////////////////////////
-/// FUNCTION DEFITIONS ///
+/// FUNCTION DEFINITIONS ///
////////////////////////////////////////////////////////////////////////
/**Function*************************************************************
@@ -56,28 +56,28 @@ static Abc_Obj_t * Abc_NodeFromMapSuperChoice_rec( Abc_Ntk_t * pNtkNew, Map_Sup
***********************************************************************/
Abc_Ntk_t * Abc_NtkMap( Abc_Ntk_t * pNtk, double DelayTarget, int fRecovery, int fSwitching, int fVerbose )
{
+ int fShowSwitching = 1;
Abc_Ntk_t * pNtkNew;
Map_Man_t * pMan;
Vec_Int_t * vSwitching;
float * pSwitching = NULL;
- int fShowSwitching = 0;
int clk;
assert( Abc_NtkIsStrash(pNtk) );
// check that the library is available
- if ( Abc_FrameReadLibGen(Abc_FrameGetGlobalFrame()) == NULL )
+ if ( Abc_FrameReadLibGen() == NULL )
{
printf( "The current library is not available.\n" );
return 0;
}
// derive the supergate library
- if ( Abc_FrameReadLibSuper(Abc_FrameGetGlobalFrame()) == NULL && Abc_FrameReadLibGen(Abc_FrameGetGlobalFrame()) )
+ if ( Abc_FrameReadLibSuper() == NULL && Abc_FrameReadLibGen() )
{
printf( "A simple supergate library is derived from gate library \"%s\".\n",
- Mio_LibraryReadName(Abc_FrameReadLibGen(Abc_FrameGetGlobalFrame())) );
- Map_SuperLibDeriveFromGenlib( Abc_FrameReadLibGen(Abc_FrameGetGlobalFrame()) );
+ Mio_LibraryReadName(Abc_FrameReadLibGen()) );
+ Map_SuperLibDeriveFromGenlib( Abc_FrameReadLibGen() );
}
// print a warning about choice nodes
@@ -113,6 +113,9 @@ clk = clock();
return NULL;
Map_ManFree( pMan );
+ if ( pNtk->pExdc )
+ pNtkNew->pExdc = Abc_NtkDup( pNtk->pExdc );
+
// make sure that everything is okay
if ( !Abc_NtkCheck( pNtkNew ) )
{
@@ -156,6 +159,7 @@ Map_Man_t * Abc_NtkToMap( Abc_Ntk_t * pNtk, double DelayTarget, int fRecovery, f
// create PIs and remember them in the old nodes
Abc_NtkCleanCopy( pNtk );
+ Abc_AigConst1(pNtk)->pCopy = (Abc_Obj_t *)Map_ManReadConst1(pMan);
Abc_NtkForEachCi( pNtk, pNode, i )
{
pNodeMap = Map_ManReadInputs(pMan)[i];
@@ -170,12 +174,6 @@ Map_Man_t * Abc_NtkToMap( Abc_Ntk_t * pNtk, double DelayTarget, int fRecovery, f
Vec_PtrForEachEntry( vNodes, pNode, i )
{
Extra_ProgressBarUpdate( pProgress, i, NULL );
- // consider the case of a constant
- if ( Abc_NodeIsConst(pNode) )
- {
- Abc_AigConst1(pNtk->pManFunc)->pCopy = (Abc_Obj_t *)Map_ManReadConst1(pMan);
- continue;
- }
// add the node to the mapper
pNodeMap = Map_NodeAnd( pMan,
Map_NotCond( Abc_ObjFanin0(pNode)->pCopy, Abc_ObjFaninC0(pNode) ),
@@ -186,7 +184,7 @@ Map_Man_t * Abc_NtkToMap( Abc_Ntk_t * pNtk, double DelayTarget, int fRecovery, f
if ( pSwitching )
Map_NodeSetSwitching( pNodeMap, pSwitching[pNode->Id] );
// set up the choice node
- if ( Abc_NodeIsAigChoice( pNode ) )
+ if ( Abc_AigNodeIsChoice( pNode ) )
for ( pPrev = pNode, pFanin = pNode->pData; pFanin; pPrev = pFanin, pFanin = pFanin->pData )
{
Map_NodeSetNextE( (Map_Node_t *)pPrev->pCopy, (Map_Node_t *)pFanin->pCopy );
@@ -220,17 +218,12 @@ Abc_Ntk_t * Abc_NtkFromMap( Map_Man_t * pMan, Abc_Ntk_t * pNtk )
Map_Node_t * pNodeMap;
Abc_Obj_t * pNode, * pNodeNew;
int i, nDupGates;
-
// create the new network
- pNtkNew = Abc_NtkStartFrom( pNtk, ABC_TYPE_LOGIC, ABC_FUNC_MAP );
+ pNtkNew = Abc_NtkStartFrom( pNtk, ABC_NTK_LOGIC, ABC_FUNC_MAP );
// make the mapper point to the new network
Map_ManCleanData( pMan );
Abc_NtkForEachCi( pNtk, pNode, i )
Map_NodeSetData( Map_ManReadInputs(pMan)[i], 1, (char *)pNode->pCopy );
- // set the constant node
- if ( Abc_ObjFanoutNum( Abc_AigConst1(pNtk->pManFunc) ) > 0 )
- Map_NodeSetData( Map_ManReadConst1(pMan), 1, (char *)Abc_NodeCreateConst1(pNtkNew) );
-
// assign the mapping of the required phase to the POs
pProgress = Extra_ProgressBarStart( stdout, Abc_NtkCoNum(pNtk) );
Abc_NtkForEachCo( pNtk, pNode, i )
@@ -264,6 +257,10 @@ Abc_Obj_t * Abc_NodeFromMap_rec( Abc_Ntk_t * pNtkNew, Map_Node_t * pNodeMap, int
{
Abc_Obj_t * pNodeNew, * pNodeInv;
+ // check the case of constant node
+ if ( Map_NodeIsConst(pNodeMap) )
+ return fPhase? Abc_NtkCreateNodeConst1(pNtkNew) : Abc_NtkCreateNodeConst0(pNtkNew);
+
// check if the phase is already implemented
pNodeNew = (Abc_Obj_t *)Map_NodeReadData( pNodeMap, fPhase );
if ( pNodeNew )
@@ -372,7 +369,7 @@ Abc_Obj_t * Abc_NodeFromMapSuper_rec( Abc_Ntk_t * pNtkNew, Map_Node_t * pNodeMap
* (since the cut only has 4 variables). An interesting question is what
* if the first variable (and not the fifth one is the redundant one;
* can that happen?) */
- return Abc_NodeCreateConst0(pNtkNew);
+ return Abc_NtkCreateNodeConst0(pNtkNew);
}
}
@@ -391,38 +388,6 @@ Abc_Obj_t * Abc_NodeFromMapSuper_rec( Abc_Ntk_t * pNtkNew, Map_Node_t * pNodeMap
}
-/**Function*************************************************************
-
- Synopsis [Unmaps the network.]
-
- Description []
-
- SideEffects []
-
- SeeAlso []
-
-***********************************************************************/
-int Abc_NtkUnmap( Abc_Ntk_t * pNtk )
-{
- Abc_Obj_t * pNode;
- char * pSop;
- int i;
-
- assert( Abc_NtkIsMappedLogic(pNtk) );
- // update the functionality manager
- assert( pNtk->pManFunc == Abc_FrameReadLibGen(Abc_FrameGetGlobalFrame()) );
- pNtk->pManFunc = Extra_MmFlexStart();
- pNtk->ntkFunc = ABC_FUNC_SOP;
- // update the nodes
- Abc_NtkForEachNode( pNtk, pNode, i )
- {
- pSop = Mio_GateReadSop(pNode->pData);
- assert( Abc_SopGetVarNum(pSop) == Abc_ObjFaninNum(pNode) );
- pNode->pData = Abc_SopRegister( pNtk->pManFunc, pSop );
- }
- return 1;
-}
-
@@ -446,18 +411,18 @@ Abc_Ntk_t * Abc_NtkSuperChoice( Abc_Ntk_t * pNtk )
assert( Abc_NtkIsStrash(pNtk) );
// check that the library is available
- if ( Abc_FrameReadLibGen(Abc_FrameGetGlobalFrame()) == NULL )
+ if ( Abc_FrameReadLibGen() == NULL )
{
printf( "The current library is not available.\n" );
return 0;
}
// derive the supergate library
- if ( Abc_FrameReadLibSuper(Abc_FrameGetGlobalFrame()) == NULL && Abc_FrameReadLibGen(Abc_FrameGetGlobalFrame()) )
+ if ( Abc_FrameReadLibSuper() == NULL && Abc_FrameReadLibGen() )
{
printf( "A simple supergate library is derived from gate library \"%s\".\n",
- Mio_LibraryReadName(Abc_FrameReadLibGen(Abc_FrameGetGlobalFrame())) );
- Map_SuperLibDeriveFromGenlib( Abc_FrameReadLibGen(Abc_FrameGetGlobalFrame()) );
+ Mio_LibraryReadName(Abc_FrameReadLibGen()) );
+ Map_SuperLibDeriveFromGenlib( Abc_FrameReadLibGen() );
}
// print a warning about choice nodes
@@ -504,6 +469,7 @@ Abc_Ntk_t * Abc_NtkSuperChoice( Abc_Ntk_t * pNtk )
***********************************************************************/
Abc_Ntk_t * Abc_NtkFromMapSuperChoice( Map_Man_t * pMan, Abc_Ntk_t * pNtk )
{
+ extern Abc_Ntk_t * Abc_NtkMulti( Abc_Ntk_t * pNtk, int nThresh, int nFaninMax, int fCnf, int fMulti, int fSimple, int fFactor );
ProgressBar * pProgress;
Abc_Ntk_t * pNtkNew, * pNtkNew2;
Abc_Obj_t * pNode;
@@ -519,8 +485,12 @@ Abc_Ntk_t * Abc_NtkFromMapSuperChoice( Map_Man_t * pMan, Abc_Ntk_t * pNtk )
// duplicate the network
pNtkNew2 = Abc_NtkDup( pNtk );
- pNtkNew = Abc_NtkRenode( pNtkNew2, 0, 20, 0, 0, 1 );
- Abc_NtkBddToSop( pNtkNew );
+ pNtkNew = Abc_NtkMulti( pNtkNew2, 0, 20, 0, 0, 1, 0 );
+ if ( !Abc_NtkBddToSop( pNtkNew, 0 ) )
+ {
+ printf( "Abc_NtkFromMapSuperChoice(): Converting to SOPs has failed.\n" );
+ return NULL;
+ }
// set the old network to point to the new network
Abc_NtkForEachCi( pNtk, pNode, i )
@@ -534,14 +504,14 @@ Abc_Ntk_t * Abc_NtkFromMapSuperChoice( Map_Man_t * pMan, Abc_Ntk_t * pNtk )
// set the pointers from the mapper to the new nodes
Abc_NtkForEachCi( pNtk, pNode, i )
{
- Map_NodeSetData( Map_ManReadInputs(pMan)[i], 0, (char *)Abc_NodeCreateInv(pNtkNew,pNode->pCopy) );
+ Map_NodeSetData( Map_ManReadInputs(pMan)[i], 0, (char *)Abc_NtkCreateNodeInv(pNtkNew,pNode->pCopy) );
Map_NodeSetData( Map_ManReadInputs(pMan)[i], 1, (char *)pNode->pCopy );
}
Abc_NtkForEachNode( pNtk, pNode, i )
{
- if ( Abc_NodeIsConst(pNode) )
- continue;
- Map_NodeSetData( (Map_Node_t *)pNode->pNext, 0, (char *)Abc_NodeCreateInv(pNtkNew,pNode->pCopy) );
+// if ( Abc_NodeIsConst(pNode) )
+// continue;
+ Map_NodeSetData( (Map_Node_t *)pNode->pNext, 0, (char *)Abc_NtkCreateNodeInv(pNtkNew,pNode->pCopy) );
Map_NodeSetData( (Map_Node_t *)pNode->pNext, 1, (char *)pNode->pCopy );
}
@@ -550,8 +520,8 @@ Abc_Ntk_t * Abc_NtkFromMapSuperChoice( Map_Man_t * pMan, Abc_Ntk_t * pNtk )
Abc_NtkForEachNode( pNtk, pNode, i )
{
Extra_ProgressBarUpdate( pProgress, i, NULL );
- if ( Abc_NodeIsConst(pNode) )
- continue;
+// if ( Abc_NodeIsConst(pNode) )
+// continue;
Abc_NodeSuperChoice( pNtkNew, pNode );
}
Extra_ProgressBarStop( pProgress );
@@ -661,7 +631,7 @@ Abc_Obj_t * Abc_NodeFromMapSuperChoice_rec( Abc_Ntk_t * pNtkNew, Map_Super_t * p
* (since the cut only has 4 variables). An interesting question is what
* if the first variable (and not the fifth one is the redundant one;
* can that happen?) */
- return Abc_NodeCreateConst0(pNtkNew);
+ return Abc_NtkCreateNodeConst0(pNtkNew);
}
}
diff --git a/src/base/abci/abcMeasure.c b/src/base/abci/abcMeasure.c
new file mode 100644
index 00000000..6604a0c4
--- /dev/null
+++ b/src/base/abci/abcMeasure.c
@@ -0,0 +1,478 @@
+/**CFile****************************************************************
+
+ FileName [abc_.c]
+
+ SystemName [ABC: Logic synthesis and verification system.]
+
+ PackageName [Network and node package.]
+
+ Synopsis []
+
+ Author [Alan Mishchenko]
+
+ Affiliation [UC Berkeley]
+
+ Date [Ver. 1.0. Started - June 20, 2005.]
+
+ Revision [$Id: abc_.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "abc.h"
+#include "kit.h"
+
+////////////////////////////////////////////////////////////////////////
+/// DECLARATIONS ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+/// FUNCTION DEFINITIONS ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Abc_NtkPrintMeasures( unsigned * pTruth, int nVars )
+{
+ unsigned uCofs[10][32];
+ int i, k, nOnes;
+
+ // total pairs
+ nOnes = Kit_TruthCountOnes( uCofs[0], nVars );
+ printf( "Total = %d.\n", nOnes * ((1 << nVars) - nOnes) );
+
+ // print measures for individual variables
+ for ( i = 0; i < nVars; i++ )
+ {
+ Kit_TruthUniqueNew( uCofs[0], pTruth, nVars, i );
+ nOnes = Kit_TruthCountOnes( uCofs[0], nVars );
+ printf( "%7d ", nOnes );
+ }
+ printf( "\n" );
+
+ // consider pairs
+ for ( i = 0; i < nVars; i++ )
+ for ( k = 0; k < nVars; k++ )
+ {
+ if ( i == k )
+ {
+ printf( " " );
+ continue;
+ }
+ Kit_TruthCofactor0New( uCofs[0], pTruth, nVars, i );
+ Kit_TruthCofactor1New( uCofs[1], pTruth, nVars, i );
+
+ Kit_TruthCofactor0New( uCofs[2], uCofs[0], nVars, k ); // 00
+ Kit_TruthCofactor1New( uCofs[3], uCofs[0], nVars, k ); // 01
+ Kit_TruthCofactor0New( uCofs[4], uCofs[1], nVars, k ); // 10
+ Kit_TruthCofactor1New( uCofs[5], uCofs[1], nVars, k ); // 11
+
+ Kit_TruthAndPhase( uCofs[6], uCofs[2], uCofs[5], nVars, 0, 1 ); // 00 & 11'
+ Kit_TruthAndPhase( uCofs[7], uCofs[2], uCofs[5], nVars, 1, 0 ); // 00' & 11
+ Kit_TruthAndPhase( uCofs[8], uCofs[3], uCofs[4], nVars, 0, 1 ); // 01 & 10'
+ Kit_TruthAndPhase( uCofs[9], uCofs[3], uCofs[4], nVars, 1, 0 ); // 01' & 10
+
+ nOnes = Kit_TruthCountOnes( uCofs[6], nVars ) +
+ Kit_TruthCountOnes( uCofs[7], nVars ) +
+ Kit_TruthCountOnes( uCofs[8], nVars ) +
+ Kit_TruthCountOnes( uCofs[9], nVars );
+
+ printf( "%7d ", nOnes );
+ if ( k == nVars - 1 )
+ printf( "\n" );
+ }
+ printf( "\n" );
+}
+
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Abc_Ntk4VarObjPrint_rec( Abc_Obj_t * pObj )
+{
+ if ( pObj == Abc_AigConst1(pObj->pNtk) )
+ {
+ printf( "1" );
+ return;
+ }
+ if ( Abc_ObjIsPi(pObj) )
+ {
+ printf( "%c", pObj->Id - 1 + 'a' );
+ return;
+ }
+
+ printf( "(" );
+ Abc_Ntk4VarObjPrint_rec( Abc_ObjFanin0(pObj) );
+ if ( Abc_ObjFaninC0(pObj) )
+ printf( "\'" );
+ Abc_Ntk4VarObjPrint_rec( Abc_ObjFanin1(pObj) );
+ if ( Abc_ObjFaninC1(pObj) )
+ printf( "\'" );
+ printf( ")" );
+}
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+unsigned Abc_Ntk4VarObj( Vec_Ptr_t * vNodes )
+{
+ Abc_Obj_t * pObj;
+ unsigned uTruth0, uTruth1;
+ int i;
+ Vec_PtrForEachEntry( vNodes, pObj, i )
+ {
+ uTruth0 = (unsigned)(Abc_ObjFanin0(pObj)->pCopy);
+ uTruth1 = (unsigned)(Abc_ObjFanin1(pObj)->pCopy);
+ if ( Abc_ObjFaninC0(pObj) )
+ uTruth0 = ~uTruth0;
+ if ( Abc_ObjFaninC1(pObj) )
+ uTruth1 = ~uTruth1;
+ pObj->pCopy = (void *)(uTruth0 & uTruth1);
+ }
+ return uTruth0 & uTruth1;
+}
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Abc_Ntk4VarTable( Abc_Ntk_t * pNtk )
+{
+ static unsigned u4VarTruths[4] = { 0xAAAAAAAA, 0xCCCCCCCC, 0xF0F0F0F0, 0xFF00FF00 };
+ static unsigned u4VarTts[222] = {
+ 0x0000, 0x0001, 0x0003, 0x0006, 0x0007, 0x000f, 0x0016, 0x0017, 0x0018, 0x0019,
+ 0x001b, 0x001e, 0x001f, 0x003c, 0x003d, 0x003f, 0x0069, 0x006b, 0x006f, 0x007e,
+ 0x007f, 0x00ff, 0x0116, 0x0117, 0x0118, 0x0119, 0x011a, 0x011b, 0x011e, 0x011f,
+ 0x012c, 0x012d, 0x012f, 0x013c, 0x013d, 0x013e, 0x013f, 0x0168, 0x0169, 0x016a,
+ 0x016b, 0x016e, 0x016f, 0x017e, 0x017f, 0x0180, 0x0181, 0x0182, 0x0183, 0x0186,
+ 0x0187, 0x0189, 0x018b, 0x018f, 0x0196, 0x0197, 0x0198, 0x0199, 0x019a, 0x019b,
+ 0x019e, 0x019f, 0x01a8, 0x01a9, 0x01aa, 0x01ab, 0x01ac, 0x01ad, 0x01ae, 0x01af,
+ 0x01bc, 0x01bd, 0x01be, 0x01bf, 0x01e8, 0x01e9, 0x01ea, 0x01eb, 0x01ee, 0x01ef,
+ 0x01fe, 0x033c, 0x033d, 0x033f, 0x0356, 0x0357, 0x0358, 0x0359, 0x035a, 0x035b,
+ 0x035e, 0x035f, 0x0368, 0x0369, 0x036a, 0x036b, 0x036c, 0x036d, 0x036e, 0x036f,
+ 0x037c, 0x037d, 0x037e, 0x03c0, 0x03c1, 0x03c3, 0x03c5, 0x03c6, 0x03c7, 0x03cf,
+ 0x03d4, 0x03d5, 0x03d6, 0x03d7, 0x03d8, 0x03d9, 0x03db, 0x03dc, 0x03dd, 0x03de,
+ 0x03fc, 0x0660, 0x0661, 0x0662, 0x0663, 0x0666, 0x0667, 0x0669, 0x066b, 0x066f,
+ 0x0672, 0x0673, 0x0676, 0x0678, 0x0679, 0x067a, 0x067b, 0x067e, 0x0690, 0x0691,
+ 0x0693, 0x0696, 0x0697, 0x069f, 0x06b0, 0x06b1, 0x06b2, 0x06b3, 0x06b4, 0x06b5,
+ 0x06b6, 0x06b7, 0x06b9, 0x06bd, 0x06f0, 0x06f1, 0x06f2, 0x06f6, 0x06f9, 0x0776,
+ 0x0778, 0x0779, 0x077a, 0x077e, 0x07b0, 0x07b1, 0x07b4, 0x07b5, 0x07b6, 0x07bc,
+ 0x07e0, 0x07e1, 0x07e2, 0x07e3, 0x07e6, 0x07e9, 0x07f0, 0x07f1, 0x07f2, 0x07f8,
+ 0x0ff0, 0x1668, 0x1669, 0x166a, 0x166b, 0x166e, 0x167e, 0x1681, 0x1683, 0x1686,
+ 0x1687, 0x1689, 0x168b, 0x168e, 0x1696, 0x1697, 0x1698, 0x1699, 0x169a, 0x169b,
+ 0x169e, 0x16a9, 0x16ac, 0x16ad, 0x16bc, 0x16e9, 0x177e, 0x178e, 0x1796, 0x1798,
+ 0x179a, 0x17ac, 0x17e8, 0x18e7, 0x19e1, 0x19e3, 0x19e6, 0x1bd8, 0x1be4, 0x1ee1,
+ 0x3cc3, 0x6996
+ };
+ int Counters[222] = {0};
+ Vec_Ptr_t * vNodes;
+ Abc_Obj_t * pObj;
+ unsigned uTruth;
+ int i, k, Count = 0;
+
+ unsigned short * puCanons = NULL;
+ unsigned char * puMap = NULL;
+ Extra_Truth4VarNPN( &puCanons, NULL, NULL, &puMap );
+
+ // set elementary truth tables
+ assert( Abc_NtkPiNum(pNtk) == 4 );
+ Abc_AigConst1(pNtk)->pCopy = (void *)0xFFFFFFFF;
+ Abc_NtkForEachPi( pNtk, pObj, i )
+ pObj->pCopy = (void *)u4VarTruths[i];
+
+ // create truth tables
+ Abc_NtkForEachPo( pNtk, pObj, i )
+ {
+ vNodes = Abc_NtkDfsNodes( pNtk, &pObj, 1 );
+ if ( Vec_PtrSize(vNodes) == 0 )
+ uTruth = (unsigned)Abc_ObjFanin0(pObj)->pCopy;
+ else
+ uTruth = Abc_Ntk4VarObj( vNodes );
+
+ if ( (uTruth & 0xFFFF) < (~uTruth & 0xFFFF) )
+ uTruth = uTruth & 0xFFFF;
+ else
+ uTruth = ~uTruth & 0xFFFF;
+
+ for ( k = 0; k < 222; k++ )
+ if ( u4VarTts[k] == uTruth )
+ break;
+ if ( k == 222 )
+ continue;
+/*
+// if ( uTruth == 1725 )
+ if ( k == 96 )
+ {
+ printf( "%d : ", Vec_PtrSize(vNodes) );
+ Abc_Ntk4VarObjPrint_rec( Abc_ObjFanin0(pObj) );
+ printf( "\n" );
+ }
+*/
+ Counters[k]++;
+
+// Counters[ puMap[uTruth & 0xFFFF] ]++;
+ Vec_PtrFree( vNodes );
+ }
+ free( puCanons );
+ free( puMap );
+
+ Count = 0;
+ for ( k = 0; k < 222; k++ )
+ {
+ printf( "%d/%x/%d ", k, u4VarTts[k], Counters[k] );
+ Count += Counters[k];
+ }
+ printf( " Total = %d\n", Count );
+}
+
+
+
+
+/**Function*************************************************************
+
+ Synopsis [Returns 1 if there are no more than 2 unique cofactors.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Abc_NtkPrintOneDecompCheckCofList( unsigned * uCofs, int nCofs )
+{
+ int i, Ind = -1;
+ assert( nCofs > 2 );
+ for ( i = 1; i < nCofs; i++ )
+ {
+ if ( uCofs[i] == uCofs[0] )
+ continue;
+ if ( Ind == -1 )
+ {
+ Ind = i;
+ continue;
+ }
+ if ( uCofs[i] == uCofs[Ind] )
+ continue;
+ return 0;
+ }
+ return 1;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Checks all cofactors with the given mask.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Abc_NtkPrintOneDecompCheck( unsigned * uCofs, int nCofs, unsigned uMask )
+{
+ unsigned pCofs[32][32];
+ int nCofNums[32] = {0};
+ int uMasks[32];
+ int nGroups = 0;
+ int i, k;
+ for ( i = 0; i < nCofs; i++ )
+ {
+ // find group of this cof
+ for ( k = 0; k < nGroups; k++ )
+ if ( (int)(i & uMask) == uMasks[k] )
+ break;
+ if ( k == nGroups )
+ {
+ uMasks[k] = (i & uMask);
+ nGroups++;
+ }
+ // save cof in the group
+ pCofs[k][ nCofNums[k]++ ] = uCofs[i];
+ assert( nCofNums[k] <= 32 );
+ assert( nGroups <= 32 );
+ }
+ // check the groups
+ for ( i = 0; i < nGroups; i++ )
+ if ( !Abc_NtkPrintOneDecompCheckCofList(pCofs[i], nCofNums[i]) )
+ return 0;
+ return 1;
+}
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Abc_NtkPrintOneDecomp_rec( unsigned * uCofs, int nCofs, int nVars, unsigned uMask, int * pBestSize, unsigned * puBestMask )
+{
+ unsigned uMaskNew;
+ int v, last, Counter = 0;
+ // find the last variable in the mask
+ for ( v = 0; v < nVars; v++ )
+ if ( uMask & (1<<v) )
+ {
+ last = v;
+ Counter++;
+ }
+ if ( Counter > 3 )
+ return;
+ // try adding one variable after the last
+ for ( v = last + 1; v < nVars; v++ )
+ {
+ uMaskNew = uMask | (1 << v);
+ if ( !Abc_NtkPrintOneDecompCheck( uCofs, nCofs, uMaskNew ) )
+ continue;
+ if ( *pBestSize < Counter + 1 )
+ {
+ *pBestSize = Counter + 1;
+ *puBestMask = uMaskNew;
+ }
+ // try other masks
+ Abc_NtkPrintOneDecomp_rec( uCofs, nCofs, nVars, uMaskNew, pBestSize, puBestMask );
+ }
+}
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Abc_NtkPrintOneDecomp( unsigned * pTruth, int nVars )
+{
+ int BoundSet = 6;
+ unsigned uCofs[64], uMask, uBestMask = 0;
+ int i, nCofs, nMints, nMintShift, BestSize = 1;
+
+ assert( nVars > BoundSet );
+ assert( nVars <= BoundSet + 5 ); // at most 5 variable cofactors
+
+ // collect the cofactors
+ nCofs = (1 << BoundSet);
+ nMints = (1 << (nVars-BoundSet));
+ nMintShift = 0;
+ uMask = Kit_CubeMask( nMints );
+ for ( i = 0; i < nCofs; i++ )
+ {
+ uCofs[i] = (pTruth[nMintShift/32] >> (nMintShift % 32)) & uMask;
+ nMintShift += nMints;
+ }
+
+ // try removing variables
+ for ( i = 0; i < BoundSet; i++ )
+ Abc_NtkPrintOneDecomp_rec( uCofs, nCofs, nVars, (1 << i), &BestSize, &uBestMask );
+
+ printf( "Best size = %d ", BestSize );
+ printf( "Best mask = " );
+ Extra_PrintBinary( stdout, &uBestMask, nVars );
+ printf( "\n" );
+}
+
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Abc_NtkPrintOneDec( unsigned * pTruth, int nVars )
+{
+ unsigned uCof[(1<<11)], * pOut = uCof, * pIn = pTruth, * pTemp;
+ int nDiffs[16];
+ int Order[16];
+ int i, fChange, Temp, Counter;
+
+ // find the ordering
+ for ( i = 0; i < nVars; i++ )
+ {
+ Kit_TruthUniqueNew( uCof, pTruth, nVars, i );
+ nDiffs[i] = Kit_TruthCountOnes( uCof, nVars );
+ Order[i] = i;
+ }
+
+ // permute truth table to least active variable first
+ Counter = 0;
+ do {
+ fChange = 0;
+ for ( i = 0; i < nVars-1; i++ )
+ {
+ if ( nDiffs[i] <= nDiffs[i+1] )
+ continue;
+ fChange = 1;
+ Counter++;
+
+ Temp = nDiffs[i];
+ nDiffs[i] = nDiffs[i+1];
+ nDiffs[i+1] = Temp;
+
+ Temp = Order[i];
+ Order[i] = Order[i+1];
+ Order[i+1] = Temp;
+
+ Extra_TruthSwapAdjacentVars( pOut, pIn, nVars, i );
+ pTemp = pIn; pIn = pOut; pOut = pTemp;
+ }
+ } while ( fChange );
+
+ // swap if it was moved an even number of times
+ if ( Counter & 1 )
+ Extra_TruthCopy( pOut, pIn, nVars );
+
+ // call the decomposition
+ Abc_NtkPrintOneDecomp( pTruth, nVars );
+}
+
+////////////////////////////////////////////////////////////////////////
+/// END OF FILE ///
+////////////////////////////////////////////////////////////////////////
+
+
diff --git a/src/base/abci/abcMini.c b/src/base/abci/abcMini.c
new file mode 100644
index 00000000..92985423
--- /dev/null
+++ b/src/base/abci/abcMini.c
@@ -0,0 +1,153 @@
+/**CFile****************************************************************
+
+ FileName [abcMini.c]
+
+ SystemName [ABC: Logic synthesis and verification system.]
+
+ PackageName [Network and node package.]
+
+ Synopsis [Interface to the minimalistic AIG package.]
+
+ Author [Alan Mishchenko]
+
+ Affiliation [UC Berkeley]
+
+ Date [Ver. 1.0. Started - June 20, 2005.]
+
+ Revision [$Id: abcMini.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "abc.h"
+
+////////////////////////////////////////////////////////////////////////
+/// DECLARATIONS ///
+////////////////////////////////////////////////////////////////////////
+
+static Hop_Man_t * Abc_NtkToMini( Abc_Ntk_t * pNtk );
+static Abc_Ntk_t * Abc_NtkFromMini( Abc_Ntk_t * pNtkOld, Hop_Man_t * pMan );
+
+////////////////////////////////////////////////////////////////////////
+/// FUNCTION DEFINITIONS ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+ Synopsis [Gives the current ABC network to AIG manager for processing.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Abc_Ntk_t * Abc_NtkMiniBalance( Abc_Ntk_t * pNtk )
+{
+ Abc_Ntk_t * pNtkAig;
+ Hop_Man_t * pMan, * pTemp;
+ assert( Abc_NtkIsStrash(pNtk) );
+ // convert to the AIG manager
+ pMan = Abc_NtkToMini( pNtk );
+ if ( pMan == NULL )
+ return NULL;
+ if ( !Hop_ManCheck( pMan ) )
+ {
+ printf( "AIG check has failed.\n" );
+ Hop_ManStop( pMan );
+ return NULL;
+ }
+ // perform balance
+ Hop_ManPrintStats( pMan );
+// Hop_ManDumpBlif( pMan, "aig_temp.blif" );
+ pMan = Hop_ManBalance( pTemp = pMan, 1 );
+ Hop_ManStop( pTemp );
+ Hop_ManPrintStats( pMan );
+ // convert from the AIG manager
+ pNtkAig = Abc_NtkFromMini( pNtk, pMan );
+ if ( pNtkAig == NULL )
+ return NULL;
+ Hop_ManStop( pMan );
+ // make sure everything is okay
+ if ( !Abc_NtkCheck( pNtkAig ) )
+ {
+ printf( "Abc_NtkStrash: The network check has failed.\n" );
+ Abc_NtkDelete( pNtkAig );
+ return NULL;
+ }
+ return pNtkAig;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Converts the network from the AIG manager into ABC.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Hop_Man_t * Abc_NtkToMini( Abc_Ntk_t * pNtk )
+{
+ Hop_Man_t * pMan;
+ Abc_Obj_t * pObj;
+ int i;
+ // create the manager
+ pMan = Hop_ManStart();
+ // transfer the pointers to the basic nodes
+ Abc_AigConst1(pNtk)->pCopy = (Abc_Obj_t *)Hop_ManConst1(pMan);
+ Abc_NtkForEachCi( pNtk, pObj, i )
+ pObj->pCopy = (Abc_Obj_t *)Hop_ObjCreatePi(pMan);
+ // perform the conversion of the internal nodes (assumes DFS ordering)
+ Abc_NtkForEachNode( pNtk, pObj, i )
+ pObj->pCopy = (Abc_Obj_t *)Hop_And( pMan, (Hop_Obj_t *)Abc_ObjChild0Copy(pObj), (Hop_Obj_t *)Abc_ObjChild1Copy(pObj) );
+ // create the POs
+ Abc_NtkForEachCo( pNtk, pObj, i )
+ Hop_ObjCreatePo( pMan, (Hop_Obj_t *)Abc_ObjChild0Copy(pObj) );
+ Hop_ManCleanup( pMan );
+ return pMan;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Converts the network from the AIG manager into ABC.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Abc_Ntk_t * Abc_NtkFromMini( Abc_Ntk_t * pNtk, Hop_Man_t * pMan )
+{
+ Vec_Ptr_t * vNodes;
+ Abc_Ntk_t * pNtkNew;
+ Hop_Obj_t * pObj;
+ int i;
+ // perform strashing
+ pNtkNew = Abc_NtkStartFrom( pNtk, ABC_NTK_STRASH, ABC_FUNC_AIG );
+ // transfer the pointers to the basic nodes
+ Hop_ManConst1(pMan)->pData = Abc_AigConst1(pNtkNew);
+ Hop_ManForEachPi( pMan, pObj, i )
+ pObj->pData = Abc_NtkCi(pNtkNew, i);
+ // rebuild the AIG
+ vNodes = Hop_ManDfs( pMan );
+ Vec_PtrForEachEntry( vNodes, pObj, i )
+ pObj->pData = Abc_AigAnd( pNtkNew->pManFunc, (Abc_Obj_t *)Hop_ObjChild0Copy(pObj), (Abc_Obj_t *)Hop_ObjChild1Copy(pObj) );
+ Vec_PtrFree( vNodes );
+ // connect the PO nodes
+ Hop_ManForEachPo( pMan, pObj, i )
+ Abc_ObjAddFanin( Abc_NtkCo(pNtkNew, i), (Abc_Obj_t *)Hop_ObjChild0Copy(pObj) );
+ if ( !Abc_NtkCheck( pNtkNew ) )
+ fprintf( stdout, "Abc_NtkFromMini(): Network check has failed.\n" );
+ return pNtkNew;
+}
+
+////////////////////////////////////////////////////////////////////////
+/// END OF FILE ///
+////////////////////////////////////////////////////////////////////////
+
+
diff --git a/src/base/abci/abcMiter.c b/src/base/abci/abcMiter.c
index 1e728d92..257d930f 100644
--- a/src/base/abci/abcMiter.c
+++ b/src/base/abci/abcMiter.c
@@ -24,16 +24,19 @@
/// DECLARATIONS ///
////////////////////////////////////////////////////////////////////////
-static Abc_Ntk_t * Abc_NtkMiterInt( Abc_Ntk_t * pNtk1, Abc_Ntk_t * pNtk2, int fComb );
-static void Abc_NtkMiterPrepare( Abc_Ntk_t * pNtk1, Abc_Ntk_t * pNtk2, Abc_Ntk_t * pNtkMiter, int fComb );
+static Abc_Ntk_t * Abc_NtkMiterInt( Abc_Ntk_t * pNtk1, Abc_Ntk_t * pNtk2, int fComb, int nPartSize );
+static void Abc_NtkMiterPrepare( Abc_Ntk_t * pNtk1, Abc_Ntk_t * pNtk2, Abc_Ntk_t * pNtkMiter, int fComb, int nPartSize );
static void Abc_NtkMiterAddOne( Abc_Ntk_t * pNtk, Abc_Ntk_t * pNtkMiter );
-static void Abc_NtkMiterAddCone( Abc_Ntk_t * pNtk, Abc_Ntk_t * pNtkMiter, Abc_Obj_t * pNode );
-static void Abc_NtkMiterFinalize( Abc_Ntk_t * pNtk1, Abc_Ntk_t * pNtk2, Abc_Ntk_t * pNtkMiter, int fComb );
-static void Abc_NtkAddFrame( Abc_Ntk_t * pNetNew, Abc_Ntk_t * pNet, int iFrame, Vec_Ptr_t * vNodes );
+static void Abc_NtkMiterFinalize( Abc_Ntk_t * pNtk1, Abc_Ntk_t * pNtk2, Abc_Ntk_t * pNtkMiter, int fComb, int nPartSize );
+static void Abc_NtkAddFrame( Abc_Ntk_t * pNetNew, Abc_Ntk_t * pNet, int iFrame );
+// to be exported
+typedef void (*AddFrameMapping)( Abc_Obj_t*, Abc_Obj_t*, int, void*);
+extern Abc_Ntk_t * Abc_NtkFrames2( Abc_Ntk_t * pNtk, int nFrames, int fInitial, AddFrameMapping addFrameMapping, void* arg );
+static void Abc_NtkAddFrame2( Abc_Ntk_t * pNtkFrames, Abc_Ntk_t * pNtk, int iFrame, Vec_Ptr_t * vNodes, AddFrameMapping addFrameMapping, void* arg );
////////////////////////////////////////////////////////////////////////
-/// FUNCTION DEFITIONS ///
+/// FUNCTION DEFINITIONS ///
////////////////////////////////////////////////////////////////////////
/**Function*************************************************************
@@ -47,18 +50,20 @@ static void Abc_NtkAddFrame( Abc_Ntk_t * pNetNew, Abc_Ntk_t * pNet, int i
SeeAlso []
***********************************************************************/
-Abc_Ntk_t * Abc_NtkMiter( Abc_Ntk_t * pNtk1, Abc_Ntk_t * pNtk2, int fComb )
+Abc_Ntk_t * Abc_NtkMiter( Abc_Ntk_t * pNtk1, Abc_Ntk_t * pNtk2, int fComb, int nPartSize )
{
Abc_Ntk_t * pTemp = NULL;
int fRemove1, fRemove2;
+ assert( Abc_NtkHasOnlyLatchBoxes(pNtk1) );
+ assert( Abc_NtkHasOnlyLatchBoxes(pNtk2) );
// check that the networks have the same PIs/POs/latches
- if ( !Abc_NtkCompareSignals( pNtk1, pNtk2, fComb ) )
+ if ( !Abc_NtkCompareSignals( pNtk1, pNtk2, 0, fComb ) )
return NULL;
// make sure the circuits are strashed
- fRemove1 = (!Abc_NtkIsStrash(pNtk1)) && (pNtk1 = Abc_NtkStrash(pNtk1, 0, 0));
- fRemove2 = (!Abc_NtkIsStrash(pNtk2)) && (pNtk2 = Abc_NtkStrash(pNtk2, 0, 0));
+ fRemove1 = (!Abc_NtkIsStrash(pNtk1)) && (pNtk1 = Abc_NtkStrash(pNtk1, 0, 0, 0));
+ fRemove2 = (!Abc_NtkIsStrash(pNtk2)) && (pNtk2 = Abc_NtkStrash(pNtk2, 0, 0, 0));
if ( pNtk1 && pNtk2 )
- pTemp = Abc_NtkMiterInt( pNtk1, pNtk2, fComb );
+ pTemp = Abc_NtkMiterInt( pNtk1, pNtk2, fComb, nPartSize );
if ( fRemove1 ) Abc_NtkDelete( pNtk1 );
if ( fRemove2 ) Abc_NtkDelete( pNtk2 );
return pTemp;
@@ -75,24 +80,24 @@ Abc_Ntk_t * Abc_NtkMiter( Abc_Ntk_t * pNtk1, Abc_Ntk_t * pNtk2, int fComb )
SeeAlso []
***********************************************************************/
-Abc_Ntk_t * Abc_NtkMiterInt( Abc_Ntk_t * pNtk1, Abc_Ntk_t * pNtk2, int fComb )
+Abc_Ntk_t * Abc_NtkMiterInt( Abc_Ntk_t * pNtk1, Abc_Ntk_t * pNtk2, int fComb, int nPartSize )
{
- char Buffer[100];
+ char Buffer[1000];
Abc_Ntk_t * pNtkMiter;
assert( Abc_NtkIsStrash(pNtk1) );
assert( Abc_NtkIsStrash(pNtk2) );
// start the new network
- pNtkMiter = Abc_NtkAlloc( ABC_TYPE_STRASH, ABC_FUNC_AIG );
+ pNtkMiter = Abc_NtkAlloc( ABC_NTK_STRASH, ABC_FUNC_AIG, 1 );
sprintf( Buffer, "%s_%s_miter", pNtk1->pName, pNtk2->pName );
- pNtkMiter->pName = util_strsav(Buffer);
+ pNtkMiter->pName = Extra_UtilStrsav(Buffer);
// perform strashing
- Abc_NtkMiterPrepare( pNtk1, pNtk2, pNtkMiter, fComb );
+ Abc_NtkMiterPrepare( pNtk1, pNtk2, pNtkMiter, fComb, nPartSize );
Abc_NtkMiterAddOne( pNtk1, pNtkMiter );
Abc_NtkMiterAddOne( pNtk2, pNtkMiter );
- Abc_NtkMiterFinalize( pNtk1, pNtk2, pNtkMiter, fComb );
+ Abc_NtkMiterFinalize( pNtk1, pNtk2, pNtkMiter, fComb, nPartSize );
Abc_AigCleanup(pNtkMiter->pManFunc);
// make sure that everything is okay
@@ -116,13 +121,16 @@ Abc_Ntk_t * Abc_NtkMiterInt( Abc_Ntk_t * pNtk1, Abc_Ntk_t * pNtk2, int fComb )
SeeAlso []
***********************************************************************/
-void Abc_NtkMiterPrepare( Abc_Ntk_t * pNtk1, Abc_Ntk_t * pNtk2, Abc_Ntk_t * pNtkMiter, int fComb )
+void Abc_NtkMiterPrepare( Abc_Ntk_t * pNtk1, Abc_Ntk_t * pNtk2, Abc_Ntk_t * pNtkMiter, int fComb, int nPartSize )
{
Abc_Obj_t * pObj, * pObjNew;
int i;
// clean the copy field in all objects
// Abc_NtkCleanCopy( pNtk1 );
// Abc_NtkCleanCopy( pNtk2 );
+ Abc_AigConst1(pNtk1)->pCopy = Abc_AigConst1(pNtkMiter);
+ Abc_AigConst1(pNtk2)->pCopy = Abc_AigConst1(pNtkMiter);
+
if ( fComb )
{
// create new PIs and remember them in the old PIs
@@ -134,12 +142,15 @@ void Abc_NtkMiterPrepare( Abc_Ntk_t * pNtk1, Abc_Ntk_t * pNtk2, Abc_Ntk_t * pNtk
pObj = Abc_NtkCi(pNtk2, i);
pObj->pCopy = pObjNew;
// add name
- Abc_NtkLogicStoreName( pObjNew, Abc_ObjName(pObj) );
+ Abc_ObjAssignName( pObjNew, Abc_ObjName(pObj), NULL );
+ }
+ if ( nPartSize <= 0 )
+ {
+ // create the only PO
+ pObjNew = Abc_NtkCreatePo( pNtkMiter );
+ // add the PO name
+ Abc_ObjAssignName( pObjNew, "miter", NULL );
}
- // create the only PO
- pObjNew = Abc_NtkCreatePo( pNtkMiter );
- // add the PO name
- Abc_NtkLogicStoreName( pObjNew, "miter" );
}
else
{
@@ -152,28 +163,31 @@ void Abc_NtkMiterPrepare( Abc_Ntk_t * pNtk1, Abc_Ntk_t * pNtk2, Abc_Ntk_t * pNtk
pObj = Abc_NtkPi(pNtk2, i);
pObj->pCopy = pObjNew;
// add name
- Abc_NtkLogicStoreName( pObjNew, Abc_ObjName(pObj) );
+ Abc_ObjAssignName( pObjNew, Abc_ObjName(pObj), NULL );
+ }
+ if ( nPartSize <= 0 )
+ {
+ // create the only PO
+ pObjNew = Abc_NtkCreatePo( pNtkMiter );
+ // add the PO name
+ Abc_ObjAssignName( pObjNew, "miter", NULL );
}
- // create the only PO
- pObjNew = Abc_NtkCreatePo( pNtkMiter );
- // add the PO name
- Abc_NtkLogicStoreName( pObjNew, "miter" );
// create the latches
Abc_NtkForEachLatch( pNtk1, pObj, i )
{
- pObjNew = Abc_NtkDupObj( pNtkMiter, pObj );
- Vec_PtrPush( pNtkMiter->vCis, pObjNew );
- Vec_PtrPush( pNtkMiter->vCos, pObjNew );
- // add name
- Abc_NtkLogicStoreNamePlus( pObjNew, Abc_ObjName(pObj), "_1" );
+ pObjNew = Abc_NtkDupBox( pNtkMiter, pObj, 0 );
+ // add names
+ Abc_ObjAssignName( pObjNew, Abc_ObjName(pObj), "_1" );
+ Abc_ObjAssignName( Abc_ObjFanin0(pObjNew), Abc_ObjName(Abc_ObjFanin0(pObj)), "_1" );
+ Abc_ObjAssignName( Abc_ObjFanout0(pObjNew), Abc_ObjName(Abc_ObjFanout0(pObj)), "_1" );
}
Abc_NtkForEachLatch( pNtk2, pObj, i )
{
- pObjNew = Abc_NtkDupObj( pNtkMiter, pObj );
- Vec_PtrPush( pNtkMiter->vCis, pObjNew );
- Vec_PtrPush( pNtkMiter->vCos, pObjNew );
+ pObjNew = Abc_NtkDupBox( pNtkMiter, pObj, 0 );
// add name
- Abc_NtkLogicStoreNamePlus( pObjNew, Abc_ObjName(pObj), "_2" );
+ Abc_ObjAssignName( pObjNew, Abc_ObjName(pObj), "_2" );
+ Abc_ObjAssignName( Abc_ObjFanin0(pObjNew), Abc_ObjName(Abc_ObjFanin0(pObj)), "_2" );
+ Abc_ObjAssignName( Abc_ObjFanout0(pObjNew), Abc_ObjName(Abc_ObjFanout0(pObj)), "_2" );
}
}
}
@@ -191,26 +205,11 @@ void Abc_NtkMiterPrepare( Abc_Ntk_t * pNtk1, Abc_Ntk_t * pNtk2, Abc_Ntk_t * pNtk
***********************************************************************/
void Abc_NtkMiterAddOne( Abc_Ntk_t * pNtk, Abc_Ntk_t * pNtkMiter )
{
- ProgressBar * pProgress;
- Vec_Ptr_t * vNodes;
- Abc_Obj_t * pNode, * pConst1, * pConst1New;
+ Abc_Obj_t * pNode;
int i;
- // get the constant nodes
- pConst1 = Abc_AigConst1( pNtk->pManFunc );
- pConst1New = Abc_AigConst1( pNtkMiter->pManFunc );
- // perform strashing
- vNodes = Abc_NtkDfs( pNtk, 0 );
- pProgress = Extra_ProgressBarStart( stdout, vNodes->nSize );
- Vec_PtrForEachEntry( vNodes, pNode, i )
- {
- Extra_ProgressBarUpdate( pProgress, i, NULL );
- if ( pNode == pConst1 )
- pNode->pCopy = pConst1New;
- else
- pNode->pCopy = Abc_AigAnd( pNtkMiter->pManFunc, Abc_ObjChild0Copy(pNode), Abc_ObjChild1Copy(pNode) );
- }
- Vec_PtrFree( vNodes );
- Extra_ProgressBarStop( pProgress );
+ assert( Abc_NtkIsDfsOrdered(pNtk) );
+ Abc_AigForEachAnd( pNtk, pNode, i )
+ pNode->pCopy = Abc_AigAnd( pNtkMiter->pManFunc, Abc_ObjChild0Copy(pNode), Abc_ObjChild1Copy(pNode) );
}
/**Function*************************************************************
@@ -227,22 +226,15 @@ void Abc_NtkMiterAddOne( Abc_Ntk_t * pNtk, Abc_Ntk_t * pNtkMiter )
void Abc_NtkMiterAddCone( Abc_Ntk_t * pNtk, Abc_Ntk_t * pNtkMiter, Abc_Obj_t * pRoot )
{
Vec_Ptr_t * vNodes;
- Abc_Obj_t * pNode, * pNodeNew, * pConst1, * pConst1New;
+ Abc_Obj_t * pNode;
int i;
- // get the constant nodes
- pConst1 = Abc_AigConst1( pNtk->pManFunc );
- pConst1New = Abc_AigConst1( pNtkMiter->pManFunc );
+ // map the constant nodes
+ Abc_AigConst1(pNtk)->pCopy = Abc_AigConst1(pNtkMiter);
// perform strashing
vNodes = Abc_NtkDfsNodes( pNtk, &pRoot, 1 );
- for ( i = 0; i < vNodes->nSize; i++ )
- {
- pNode = vNodes->pArray[i];
- if ( pNode == pConst1 )
- pNodeNew = pConst1New;
- else
- pNodeNew = Abc_AigAnd( pNtkMiter->pManFunc, Abc_ObjChild0Copy(pNode), Abc_ObjChild1Copy(pNode) );
- pNode->pCopy = pNodeNew;
- }
+ Vec_PtrForEachEntry( vNodes, pNode, i )
+ if ( Abc_AigNodeIsAnd(pNode) )
+ pNode->pCopy = Abc_AigAnd( pNtkMiter->pManFunc, Abc_ObjChild0Copy(pNode), Abc_ObjChild1Copy(pNode) );
Vec_PtrFree( vNodes );
}
@@ -258,7 +250,7 @@ void Abc_NtkMiterAddCone( Abc_Ntk_t * pNtk, Abc_Ntk_t * pNtkMiter, Abc_Obj_t * p
SeeAlso []
***********************************************************************/
-void Abc_NtkMiterFinalize( Abc_Ntk_t * pNtk1, Abc_Ntk_t * pNtk2, Abc_Ntk_t * pNtkMiter, int fComb )
+void Abc_NtkMiterFinalize( Abc_Ntk_t * pNtk1, Abc_Ntk_t * pNtk2, Abc_Ntk_t * pNtkMiter, int fComb, int nPartSize )
{
Vec_Ptr_t * vPairs;
Abc_Obj_t * pMiter, * pNode;
@@ -286,19 +278,184 @@ void Abc_NtkMiterFinalize( Abc_Ntk_t * pNtk1, Abc_Ntk_t * pNtk2, Abc_Ntk_t * pNt
}
// connect new latches
Abc_NtkForEachLatch( pNtk1, pNode, i )
- Abc_ObjAddFanin( pNode->pCopy, Abc_ObjChild0Copy(pNode) );
+ Abc_ObjAddFanin( Abc_ObjFanin0(pNode)->pCopy, Abc_ObjChild0Copy(Abc_ObjFanin0(pNode)) );
Abc_NtkForEachLatch( pNtk2, pNode, i )
- Abc_ObjAddFanin( pNode->pCopy, Abc_ObjChild0Copy(pNode) );
+ Abc_ObjAddFanin( Abc_ObjFanin0(pNode)->pCopy, Abc_ObjChild0Copy(Abc_ObjFanin0(pNode)) );
}
// add the miter
- pMiter = Abc_AigMiter( pNtkMiter->pManFunc, vPairs );
+ if ( nPartSize <= 0 )
+ {
+ pMiter = Abc_AigMiter( pNtkMiter->pManFunc, vPairs );
+ Abc_ObjAddFanin( Abc_NtkPo(pNtkMiter,0), pMiter );
+ Vec_PtrFree( vPairs );
+ }
+ else
+ {
+ char Buffer[1024];
+ Vec_Ptr_t * vPairsPart;
+ int nParts, i, k, iCur;
+ assert( Vec_PtrSize(vPairs) == 2 * Abc_NtkCoNum(pNtk1) );
+ // create partitions
+ nParts = Abc_NtkCoNum(pNtk1) / nPartSize + (int)((Abc_NtkCoNum(pNtk1) % nPartSize) > 0);
+ vPairsPart = Vec_PtrAlloc( nPartSize );
+ for ( i = 0; i < nParts; i++ )
+ {
+ Vec_PtrClear( vPairsPart );
+ for ( k = 0; k < nPartSize; k++ )
+ {
+ iCur = i * nPartSize + k;
+ if ( iCur >= Abc_NtkCoNum(pNtk1) )
+ break;
+ Vec_PtrPush( vPairsPart, Vec_PtrEntry(vPairs, 2*iCur ) );
+ Vec_PtrPush( vPairsPart, Vec_PtrEntry(vPairs, 2*iCur+1) );
+ }
+ pMiter = Abc_AigMiter( pNtkMiter->pManFunc, vPairsPart );
+ pNode = Abc_NtkCreatePo( pNtkMiter );
+ Abc_ObjAddFanin( pNode, pMiter );
+ // assign the name to the node
+ if ( nPartSize == 1 )
+ sprintf( Buffer, "%s", Abc_ObjName(Abc_NtkCo(pNtk1,i)) );
+ else
+ sprintf( Buffer, "%d", i );
+ Abc_ObjAssignName( pNode, "miter_", Buffer );
+ }
+ Vec_PtrFree( vPairsPart );
+ Vec_PtrFree( vPairs );
+ }
+}
+
+
+
+/**Function*************************************************************
+
+ Synopsis [Derives the AND of two miters.]
+
+ Description [The network should have the same names of PIs.]
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Abc_Ntk_t * Abc_NtkMiterAnd( Abc_Ntk_t * pNtk1, Abc_Ntk_t * pNtk2, int fOr, int fCompl2 )
+{
+ char Buffer[1000];
+ Abc_Ntk_t * pNtkMiter;
+ Abc_Obj_t * pOutput1, * pOutput2;
+ Abc_Obj_t * pRoot1, * pRoot2, * pMiter;
+
+ assert( Abc_NtkIsStrash(pNtk1) );
+ assert( Abc_NtkIsStrash(pNtk2) );
+ assert( 1 == Abc_NtkCoNum(pNtk1) );
+ assert( 1 == Abc_NtkCoNum(pNtk2) );
+ assert( 0 == Abc_NtkLatchNum(pNtk1) );
+ assert( 0 == Abc_NtkLatchNum(pNtk2) );
+ assert( Abc_NtkCiNum(pNtk1) == Abc_NtkCiNum(pNtk2) );
+ assert( Abc_NtkHasOnlyLatchBoxes(pNtk1) );
+ assert( Abc_NtkHasOnlyLatchBoxes(pNtk2) );
+
+ // start the new network
+ pNtkMiter = Abc_NtkAlloc( ABC_NTK_STRASH, ABC_FUNC_AIG, 1 );
+// sprintf( Buffer, "%s_%s_miter", pNtk1->pName, pNtk2->pName );
+ sprintf( Buffer, "product" );
+ pNtkMiter->pName = Extra_UtilStrsav(Buffer);
+
+ // perform strashing
+ Abc_NtkMiterPrepare( pNtk1, pNtk2, pNtkMiter, 1, -1 );
+ Abc_NtkMiterAddOne( pNtk1, pNtkMiter );
+ Abc_NtkMiterAddOne( pNtk2, pNtkMiter );
+// Abc_NtkMiterFinalize( pNtk1, pNtk2, pNtkMiter, 1 );
+ pRoot1 = Abc_NtkPo(pNtk1,0);
+ pRoot2 = Abc_NtkPo(pNtk2,0);
+ pOutput1 = Abc_ObjNotCond( Abc_ObjFanin0(pRoot1)->pCopy, Abc_ObjFaninC0(pRoot1) );
+ pOutput2 = Abc_ObjNotCond( Abc_ObjFanin0(pRoot2)->pCopy, Abc_ObjFaninC0(pRoot2) ^ fCompl2 );
+
+ // create the miter of the two outputs
+ if ( fOr )
+ pMiter = Abc_AigOr( pNtkMiter->pManFunc, pOutput1, pOutput2 );
+ else
+ pMiter = Abc_AigAnd( pNtkMiter->pManFunc, pOutput1, pOutput2 );
Abc_ObjAddFanin( Abc_NtkPo(pNtkMiter,0), pMiter );
- Vec_PtrFree( vPairs );
+
+ // make sure that everything is okay
+ if ( !Abc_NtkCheck( pNtkMiter ) )
+ {
+ printf( "Abc_NtkMiterAnd: The network check has failed.\n" );
+ Abc_NtkDelete( pNtkMiter );
+ return NULL;
+ }
+ return pNtkMiter;
}
+/**Function*************************************************************
+
+ Synopsis [Derives the cofactor of the miter w.r.t. the set of vars.]
+
+ Description [The array of variable values contains -1/0/1 for each PI.
+ -1 means this PI remains, 0/1 means this PI is set to 0/1.]
+
+ SideEffects []
+ SeeAlso []
+
+***********************************************************************/
+Abc_Ntk_t * Abc_NtkMiterCofactor( Abc_Ntk_t * pNtk, Vec_Int_t * vPiValues )
+{
+ char Buffer[1000];
+ Abc_Ntk_t * pNtkMiter;
+ Abc_Obj_t * pRoot, * pOutput1;
+ int Value, i;
+ assert( Abc_NtkIsStrash(pNtk) );
+ assert( 1 == Abc_NtkCoNum(pNtk) );
+ assert( Abc_NtkHasOnlyLatchBoxes(pNtk) );
+
+ // start the new network
+ pNtkMiter = Abc_NtkAlloc( ABC_NTK_STRASH, ABC_FUNC_AIG, 1 );
+ sprintf( Buffer, "%s_miter", pNtk->pName );
+ pNtkMiter->pName = Extra_UtilStrsav(Buffer);
+
+ // get the root output
+ pRoot = Abc_NtkCo( pNtk, 0 );
+
+ // perform strashing
+ Abc_NtkMiterPrepare( pNtk, pNtk, pNtkMiter, 1, -1 );
+ // set the first cofactor
+ Vec_IntForEachEntry( vPiValues, Value, i )
+ {
+ if ( Value == -1 )
+ continue;
+ if ( Value == 0 )
+ {
+ Abc_NtkCi(pNtk, i)->pCopy = Abc_ObjNot( Abc_AigConst1(pNtkMiter) );
+ continue;
+ }
+ if ( Value == 1 )
+ {
+ Abc_NtkCi(pNtk, i)->pCopy = Abc_AigConst1(pNtkMiter);
+ continue;
+ }
+ assert( 0 );
+ }
+ // add the first cofactor
+ Abc_NtkMiterAddCone( pNtk, pNtkMiter, pRoot );
+
+ // save the output
+ pOutput1 = Abc_ObjNotCond( Abc_ObjFanin0(pRoot)->pCopy, Abc_ObjFaninC0(pRoot) );
+
+ // create the miter of the two outputs
+ Abc_ObjAddFanin( Abc_NtkPo(pNtkMiter,0), pOutput1 );
+
+ // make sure that everything is okay
+ if ( !Abc_NtkCheck( pNtkMiter ) )
+ {
+ printf( "Abc_NtkMiterCofactor: The network check has failed.\n" );
+ Abc_NtkDelete( pNtkMiter );
+ return NULL;
+ }
+ return pNtkMiter;
+}
/**Function*************************************************************
Synopsis [Derives the miter of two cofactors of one output.]
@@ -312,7 +469,7 @@ void Abc_NtkMiterFinalize( Abc_Ntk_t * pNtk1, Abc_Ntk_t * pNtk2, Abc_Ntk_t * pNt
***********************************************************************/
Abc_Ntk_t * Abc_NtkMiterForCofactors( Abc_Ntk_t * pNtk, int Out, int In1, int In2 )
{
- char Buffer[100];
+ char Buffer[1000];
Abc_Ntk_t * pNtkMiter;
Abc_Obj_t * pRoot, * pOutput1, * pOutput2, * pMiter;
@@ -320,21 +477,22 @@ Abc_Ntk_t * Abc_NtkMiterForCofactors( Abc_Ntk_t * pNtk, int Out, int In1, int In
assert( Out < Abc_NtkCoNum(pNtk) );
assert( In1 < Abc_NtkCiNum(pNtk) );
assert( In2 < Abc_NtkCiNum(pNtk) );
+ assert( Abc_NtkHasOnlyLatchBoxes(pNtk) );
// start the new network
- pNtkMiter = Abc_NtkAlloc( ABC_TYPE_STRASH, ABC_FUNC_AIG );
+ pNtkMiter = Abc_NtkAlloc( ABC_NTK_STRASH, ABC_FUNC_AIG, 1 );
sprintf( Buffer, "%s_miter", Abc_ObjName(Abc_NtkCo(pNtk, Out)) );
- pNtkMiter->pName = util_strsav(Buffer);
+ pNtkMiter->pName = Extra_UtilStrsav(Buffer);
// get the root output
pRoot = Abc_NtkCo( pNtk, Out );
// perform strashing
- Abc_NtkMiterPrepare( pNtk, pNtk, pNtkMiter, 1 );
+ Abc_NtkMiterPrepare( pNtk, pNtk, pNtkMiter, 1, -1 );
// set the first cofactor
- Abc_NtkCi(pNtk, In1)->pCopy = Abc_ObjNot( Abc_AigConst1(pNtkMiter->pManFunc) );
+ Abc_NtkCi(pNtk, In1)->pCopy = Abc_ObjNot( Abc_AigConst1(pNtkMiter) );
if ( In2 >= 0 )
- Abc_NtkCi(pNtk, In2)->pCopy = Abc_AigConst1( pNtkMiter->pManFunc );
+ Abc_NtkCi(pNtk, In2)->pCopy = Abc_AigConst1(pNtkMiter);
// add the first cofactor
Abc_NtkMiterAddCone( pNtk, pNtkMiter, pRoot );
@@ -342,9 +500,9 @@ Abc_Ntk_t * Abc_NtkMiterForCofactors( Abc_Ntk_t * pNtk, int Out, int In1, int In
pOutput1 = Abc_ObjFanin0(pRoot)->pCopy;
// set the second cofactor
- Abc_NtkCi(pNtk, In1)->pCopy = Abc_AigConst1( pNtkMiter->pManFunc );
+ Abc_NtkCi(pNtk, In1)->pCopy = Abc_AigConst1(pNtkMiter);
if ( In2 >= 0 )
- Abc_NtkCi(pNtk, In2)->pCopy = Abc_ObjNot( Abc_AigConst1(pNtkMiter->pManFunc) );
+ Abc_NtkCi(pNtk, In2)->pCopy = Abc_ObjNot( Abc_AigConst1(pNtkMiter) );
// add the second cofactor
Abc_NtkMiterAddCone( pNtk, pNtkMiter, pRoot );
@@ -366,6 +524,98 @@ Abc_Ntk_t * Abc_NtkMiterForCofactors( Abc_Ntk_t * pNtk, int Out, int In1, int In
}
+/**Function*************************************************************
+
+ Synopsis [Derives the miter of two cofactors of one output.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Abc_Ntk_t * Abc_NtkMiterQuantify( Abc_Ntk_t * pNtk, int In, int fExist )
+{
+ Abc_Ntk_t * pNtkMiter;
+ Abc_Obj_t * pRoot, * pOutput1, * pOutput2, * pMiter;
+
+ assert( Abc_NtkIsStrash(pNtk) );
+ assert( 1 == Abc_NtkCoNum(pNtk) );
+ assert( In < Abc_NtkCiNum(pNtk) );
+ assert( Abc_NtkHasOnlyLatchBoxes(pNtk) );
+
+ // start the new network
+ pNtkMiter = Abc_NtkAlloc( ABC_NTK_STRASH, ABC_FUNC_AIG, 1 );
+ pNtkMiter->pName = Extra_UtilStrsav( Abc_ObjName(Abc_NtkCo(pNtk, 0)) );
+
+ // get the root output
+ pRoot = Abc_NtkCo( pNtk, 0 );
+
+ // perform strashing
+ Abc_NtkMiterPrepare( pNtk, pNtk, pNtkMiter, 1, -1 );
+ // set the first cofactor
+ Abc_NtkCi(pNtk, In)->pCopy = Abc_ObjNot( Abc_AigConst1(pNtkMiter) );
+ // add the first cofactor
+ Abc_NtkMiterAddCone( pNtk, pNtkMiter, pRoot );
+ // save the output
+// pOutput1 = Abc_ObjFanin0(pRoot)->pCopy;
+ pOutput1 = Abc_ObjNotCond( Abc_ObjFanin0(pRoot)->pCopy, Abc_ObjFaninC0(pRoot) );
+
+ // set the second cofactor
+ Abc_NtkCi(pNtk, In)->pCopy = Abc_AigConst1(pNtkMiter);
+ // add the second cofactor
+ Abc_NtkMiterAddCone( pNtk, pNtkMiter, pRoot );
+ // save the output
+// pOutput2 = Abc_ObjFanin0(pRoot)->pCopy;
+ pOutput2 = Abc_ObjNotCond( Abc_ObjFanin0(pRoot)->pCopy, Abc_ObjFaninC0(pRoot) );
+
+ // create the miter of the two outputs
+ if ( fExist )
+ pMiter = Abc_AigOr( pNtkMiter->pManFunc, pOutput1, pOutput2 );
+ else
+ pMiter = Abc_AigAnd( pNtkMiter->pManFunc, pOutput1, pOutput2 );
+ Abc_ObjAddFanin( Abc_NtkPo(pNtkMiter,0), pMiter );
+
+ // make sure that everything is okay
+ if ( !Abc_NtkCheck( pNtkMiter ) )
+ {
+ printf( "Abc_NtkMiter: The network check has failed.\n" );
+ Abc_NtkDelete( pNtkMiter );
+ return NULL;
+ }
+ return pNtkMiter;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Quantifies all the PIs existentially from the only PO of the network.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Abc_Ntk_t * Abc_NtkMiterQuantifyPis( Abc_Ntk_t * pNtk )
+{
+ Abc_Ntk_t * pNtkTemp;
+ Abc_Obj_t * pObj;
+ int i;
+ assert( Abc_NtkHasOnlyLatchBoxes(pNtk) );
+
+ Abc_NtkForEachPi( pNtk, pObj, i )
+ {
+ if ( Abc_ObjFanoutNum(pObj) == 0 )
+ continue;
+ pNtk = Abc_NtkMiterQuantify( pNtkTemp = pNtk, i, 1 );
+ Abc_NtkDelete( pNtkTemp );
+ }
+
+ return pNtk;
+}
+
@@ -373,8 +623,8 @@ Abc_Ntk_t * Abc_NtkMiterForCofactors( Abc_Ntk_t * pNtk, int Out, int In1, int In
Synopsis [Checks the status of the miter.]
- Description [Return 1 if the miter is sat for at least one output.
- Return 0 if the miter is unsat for all its outputs. Returns -1 if the
+ Description [Return 0 if the miter is sat for at least one output.
+ Return 1 if the miter is unsat for all its outputs. Returns -1 if the
miter is undecided for some outputs.]
SideEffects []
@@ -389,23 +639,31 @@ int Abc_NtkMiterIsConstant( Abc_Ntk_t * pMiter )
assert( Abc_NtkIsStrash(pMiter) );
Abc_NtkForEachPo( pMiter, pNodePo, i )
{
- pChild = Abc_ObjChild0( Abc_NtkPo(pMiter,i) );
- if ( Abc_ObjIsNode(Abc_ObjRegular(pChild)) && Abc_NodeIsConst(pChild) )
+ pChild = Abc_ObjChild0( pNodePo );
+ // check if the output is constant 1
+ if ( Abc_AigNodeIsConst(pChild) )
{
- assert( Abc_ObjRegular(pChild) == Abc_AigConst1(pMiter->pManFunc) );
+ assert( Abc_ObjRegular(pChild) == Abc_AigConst1(pMiter) );
if ( !Abc_ObjIsComplement(pChild) )
{
// if the miter is constant 1, return immediately
- printf( "MITER IS CONSTANT 1!\n" );
- return 1;
+// printf( "MITER IS CONSTANT 1!\n" );
+ return 0;
}
}
+/*
+ // check if the output is not constant 0
+ else if ( Abc_ObjRegular(pChild)->fPhase != (unsigned)Abc_ObjIsComplement(pChild) )
+ {
+ return 0;
+ }
+*/
// if the miter is undecided (or satisfiable), return immediately
else
return -1;
}
- // return 0, meaning all outputs are constant zero
- return 0;
+ // return 1, meaning all outputs are constant zero
+ return 1;
}
/**Function*************************************************************
@@ -426,7 +684,7 @@ void Abc_NtkMiterReport( Abc_Ntk_t * pMiter )
if ( Abc_NtkPoNum(pMiter) == 1 )
{
pChild = Abc_ObjChild0( Abc_NtkPo(pMiter,0) );
- if ( Abc_ObjIsNode(Abc_ObjRegular(pChild)) && Abc_NodeIsConst(pChild) )
+ if ( Abc_AigNodeIsConst(pChild) )
{
if ( Abc_ObjIsComplement(pChild) )
printf( "Unsatisfiable.\n" );
@@ -442,7 +700,7 @@ void Abc_NtkMiterReport( Abc_Ntk_t * pMiter )
{
pChild = Abc_ObjChild0( Abc_NtkPo(pMiter,i) );
printf( "Output #%2d : ", i );
- if ( Abc_ObjIsNode(Abc_ObjRegular(pChild)) && Abc_NodeIsConst(pChild) )
+ if ( Abc_AigNodeIsConst(pChild) )
{
if ( Abc_ObjIsComplement(pChild) )
printf( "Unsatisfiable.\n" );
@@ -469,23 +727,158 @@ void Abc_NtkMiterReport( Abc_Ntk_t * pMiter )
***********************************************************************/
Abc_Ntk_t * Abc_NtkFrames( Abc_Ntk_t * pNtk, int nFrames, int fInitial )
{
- char Buffer[100];
+ char Buffer[1000];
ProgressBar * pProgress;
Abc_Ntk_t * pNtkFrames;
- Vec_Ptr_t * vNodes;
- Abc_Obj_t * pLatch, * pLatchNew;
+ Abc_Obj_t * pLatch, * pLatchOut;
int i, Counter;
assert( nFrames > 0 );
assert( Abc_NtkIsStrash(pNtk) );
+ assert( Abc_NtkIsDfsOrdered(pNtk) );
+ assert( Abc_NtkHasOnlyLatchBoxes(pNtk) );
// start the new network
- pNtkFrames = Abc_NtkAlloc( ABC_TYPE_STRASH, ABC_FUNC_AIG );
+ pNtkFrames = Abc_NtkAlloc( ABC_NTK_STRASH, ABC_FUNC_AIG, 1 );
sprintf( Buffer, "%s_%d_frames", pNtk->pName, nFrames );
- pNtkFrames->pName = util_strsav(Buffer);
+ pNtkFrames->pName = Extra_UtilStrsav(Buffer);
+ // map the constant nodes
+ Abc_AigConst1(pNtk)->pCopy = Abc_AigConst1(pNtkFrames);
// create new latches (or their initial values) and remember them in the new latches
if ( !fInitial )
{
Abc_NtkForEachLatch( pNtk, pLatch, i )
+ Abc_NtkDupBox( pNtkFrames, pLatch, 1 );
+ }
+ else
+ {
+ Counter = 0;
+ Abc_NtkForEachLatch( pNtk, pLatch, i )
+ {
+ pLatchOut = Abc_ObjFanout0(pLatch);
+ if ( Abc_LatchIsInitNone(pLatch) || Abc_LatchIsInitDc(pLatch) ) // don't-care initial value - create a new PI
+ {
+ pLatchOut->pCopy = Abc_NtkCreatePi(pNtkFrames);
+ Abc_ObjAssignName( pLatchOut->pCopy, Abc_ObjName(pLatchOut), NULL );
+ Counter++;
+ }
+ else
+ pLatchOut->pCopy = Abc_ObjNotCond( Abc_AigConst1(pNtkFrames), Abc_LatchIsInit0(pLatch) );
+ }
+ if ( Counter )
+ printf( "Warning: %d uninitialized latches are replaced by free PI variables.\n", Counter );
+ }
+
+ // create the timeframes
+ pProgress = Extra_ProgressBarStart( stdout, nFrames );
+ for ( i = 0; i < nFrames; i++ )
+ {
+ Extra_ProgressBarUpdate( pProgress, i, NULL );
+ Abc_NtkAddFrame( pNtkFrames, pNtk, i );
+ }
+ Extra_ProgressBarStop( pProgress );
+
+ // connect the new latches to the outputs of the last frame
+ if ( !fInitial )
+ {
+ // we cannot use pLatch->pCopy here because pLatch->pCopy is used for temporary storage of strashed values
+ Abc_NtkForEachLatch( pNtk, pLatch, i )
+ Abc_ObjAddFanin( Abc_ObjFanin0(pLatch)->pCopy, Abc_ObjFanout0(pLatch)->pCopy );
+ }
+
+ // remove dangling nodes
+ Abc_AigCleanup( pNtkFrames->pManFunc );
+ // reorder the latches
+ Abc_NtkOrderCisCos( pNtkFrames );
+ // make sure that everything is okay
+ if ( !Abc_NtkCheck( pNtkFrames ) )
+ {
+ printf( "Abc_NtkFrames: The network check has failed.\n" );
+ Abc_NtkDelete( pNtkFrames );
+ return NULL;
+ }
+ return pNtkFrames;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Adds one time frame to the new network.]
+
+ Description [Assumes that the latches of the old network point
+ to the outputs of the previous frame of the new network (pLatch->pCopy).
+ In the end, updates the latches of the old network to point to the
+ outputs of the current frame of the new network.]
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Abc_NtkAddFrame( Abc_Ntk_t * pNtkFrames, Abc_Ntk_t * pNtk, int iFrame )
+{
+ char Buffer[10];
+ Abc_Obj_t * pNode, * pLatch;
+ int i;
+ // create the prefix to be added to the node names
+ sprintf( Buffer, "_%02d", iFrame );
+ // add the new PI nodes
+ Abc_NtkForEachPi( pNtk, pNode, i )
+ Abc_ObjAssignName( Abc_NtkDupObj(pNtkFrames, pNode, 0), Abc_ObjName(pNode), Buffer );
+ // add the internal nodes
+ Abc_AigForEachAnd( pNtk, pNode, i )
+ pNode->pCopy = Abc_AigAnd( pNtkFrames->pManFunc, Abc_ObjChild0Copy(pNode), Abc_ObjChild1Copy(pNode) );
+ // add the new POs
+ Abc_NtkForEachPo( pNtk, pNode, i )
+ {
+ Abc_ObjAssignName( Abc_NtkDupObj(pNtkFrames, pNode, 0), Abc_ObjName(pNode), Buffer );
+ Abc_ObjAddFanin( pNode->pCopy, Abc_ObjChild0Copy(pNode) );
+ }
+ // add the new asserts
+ Abc_NtkForEachAssert( pNtk, pNode, i )
+ {
+ Abc_ObjAssignName( Abc_NtkDupObj(pNtkFrames, pNode, 0), Abc_ObjName(pNode), Buffer );
+ Abc_ObjAddFanin( pNode->pCopy, Abc_ObjChild0Copy(pNode) );
+ }
+ // transfer the implementation of the latch inputs to the latch outputs
+ Abc_NtkForEachLatch( pNtk, pLatch, i )
+ pLatch->pCopy = Abc_ObjChild0Copy(Abc_ObjFanin0(pLatch));
+ Abc_NtkForEachLatch( pNtk, pLatch, i )
+ Abc_ObjFanout0(pLatch)->pCopy = pLatch->pCopy;
+}
+
+
+
+/**Function*************************************************************
+
+ Synopsis [Derives the timeframes of the network.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Abc_Ntk_t * Abc_NtkFrames2( Abc_Ntk_t * pNtk, int nFrames, int fInitial, AddFrameMapping addFrameMapping, void* arg )
+{
+/*
+ char Buffer[1000];
+ ProgressBar * pProgress;
+ Abc_Ntk_t * pNtkFrames;
+ Vec_Ptr_t * vNodes;
+ Abc_Obj_t * pLatch, * pLatchNew;
+ int i, Counter;
+ assert( nFrames > 0 );
+ assert( Abc_NtkIsStrash(pNtk) );
+ // start the new network
+ pNtkFrames = Abc_NtkAlloc( ABC_NTK_STRASH, ABC_FUNC_AIG, 1 );
+ sprintf( Buffer, "%s_%d_frames", pNtk->pName, nFrames );
+ pNtkFrames->pName = Extra_UtilStrsav(Buffer);
+ // create new latches (or their initial values) and remember them in the new latches
+ if ( !fInitial )
+ {
+ Abc_NtkForEachLatch( pNtk, pLatch, i ) {
Abc_NtkDupObj( pNtkFrames, pLatch );
+ if (addFrameMapping) addFrameMapping(pLatch->pCopy, pLatch, 0, arg);
+ }
}
else
{
@@ -495,14 +888,17 @@ Abc_Ntk_t * Abc_NtkFrames( Abc_Ntk_t * pNtk, int nFrames, int fInitial )
if ( Abc_LatchIsInitDc(pLatch) ) // don't-care initial value - create a new PI
{
pLatch->pCopy = Abc_NtkCreatePi(pNtkFrames);
- Abc_NtkLogicStoreName( pLatch->pCopy, Abc_ObjName(pLatch) );
+ Abc_ObjAssignName( pLatch->pCopy, Abc_ObjName(pLatch), NULL );
Counter++;
}
- else
- pLatch->pCopy = Abc_ObjNotCond( Abc_AigConst1(pNtkFrames->pManFunc), Abc_LatchIsInit0(pLatch) );
+ else {
+ pLatch->pCopy = Abc_ObjNotCond( Abc_AigConst1(pNtkFrames), Abc_LatchIsInit0(pLatch) );
+ }
+
+ if (addFrameMapping) addFrameMapping(pLatch->pCopy, pLatch, 0, arg);
}
if ( Counter )
- printf( "Warning: %d uninitialized latches are replaced by free variables.\n", Counter );
+ printf( "Warning: %d uninitialized latches are replaced by free PI variables.\n", Counter );
}
// create the timeframes
@@ -511,7 +907,7 @@ Abc_Ntk_t * Abc_NtkFrames( Abc_Ntk_t * pNtk, int nFrames, int fInitial )
for ( i = 0; i < nFrames; i++ )
{
Extra_ProgressBarUpdate( pProgress, i, NULL );
- Abc_NtkAddFrame( pNtkFrames, pNtk, i, vNodes );
+ Abc_NtkAddFrame2( pNtkFrames, pNtk, i, vNodes, addFrameMapping, arg );
}
Extra_ProgressBarStop( pProgress );
Vec_PtrFree( vNodes );
@@ -521,13 +917,20 @@ Abc_Ntk_t * Abc_NtkFrames( Abc_Ntk_t * pNtk, int nFrames, int fInitial )
{
Abc_NtkForEachLatch( pNtk, pLatch, i )
{
- pLatchNew = Abc_NtkLatch(pNtkFrames, i);
- Abc_ObjAddFanin( pLatchNew, Abc_ObjFanin0(pLatch)->pCopy );
- Vec_PtrPush( pNtkFrames->vCis, pLatchNew );
- Vec_PtrPush( pNtkFrames->vCos, pLatchNew );
- Abc_NtkLogicStoreName( pLatchNew, Abc_ObjName(pLatch) );
+ pLatchNew = Abc_NtkBox(pNtkFrames, i);
+ Abc_ObjAddFanin( pLatchNew, pLatch->pCopy );
+ Abc_ObjAssignName( pLatchNew, Abc_ObjName(pLatch), NULL );
}
}
+ Abc_NtkForEachLatch( pNtk, pLatch, i )
+ pLatch->pNext = NULL;
+
+ // remove dangling nodes
+ Abc_AigCleanup( pNtkFrames->pManFunc );
+
+ // reorder the latches
+ Abc_NtkOrderCisCos( pNtkFrames );
+
// make sure that everything is okay
if ( !Abc_NtkCheck( pNtkFrames ) )
{
@@ -536,6 +939,8 @@ Abc_Ntk_t * Abc_NtkFrames( Abc_Ntk_t * pNtk, int nFrames, int fInitial )
return NULL;
}
return pNtkFrames;
+*/
+ return NULL;
}
/**Function*************************************************************
@@ -552,22 +957,24 @@ Abc_Ntk_t * Abc_NtkFrames( Abc_Ntk_t * pNtk, int nFrames, int fInitial )
SeeAlso []
***********************************************************************/
-void Abc_NtkAddFrame( Abc_Ntk_t * pNtkFrames, Abc_Ntk_t * pNtk, int iFrame, Vec_Ptr_t * vNodes )
+void Abc_NtkAddFrame2( Abc_Ntk_t * pNtkFrames, Abc_Ntk_t * pNtk, int iFrame, Vec_Ptr_t * vNodes, AddFrameMapping addFrameMapping, void* arg )
{
+/*
char Buffer[10];
Abc_Obj_t * pNode, * pNodeNew, * pLatch;
Abc_Obj_t * pConst1, * pConst1New;
int i;
// get the constant nodes
- pConst1 = Abc_AigConst1( pNtk->pManFunc );
- pConst1New = Abc_AigConst1( pNtkFrames->pManFunc );
+ pConst1 = Abc_AigConst1(pNtk);
+ pConst1New = Abc_AigConst1(pNtkFrames);
// create the prefix to be added to the node names
sprintf( Buffer, "_%02d", iFrame );
// add the new PI nodes
Abc_NtkForEachPi( pNtk, pNode, i )
{
pNodeNew = Abc_NtkDupObj( pNtkFrames, pNode );
- Abc_NtkLogicStoreNamePlus( pNodeNew, Abc_ObjName(pNode), Buffer );
+ Abc_ObjAssignName( pNodeNew, Abc_ObjName(pNode), Buffer );
+ if (addFrameMapping) addFrameMapping(pNodeNew, pNode, iFrame, arg);
}
// add the internal nodes
Vec_PtrForEachEntry( vNodes, pNode, i )
@@ -577,20 +984,161 @@ void Abc_NtkAddFrame( Abc_Ntk_t * pNtkFrames, Abc_Ntk_t * pNtk, int iFrame, Vec_
else
pNodeNew = Abc_AigAnd( pNtkFrames->pManFunc, Abc_ObjChild0Copy(pNode), Abc_ObjChild1Copy(pNode) );
pNode->pCopy = pNodeNew;
+ if (addFrameMapping) addFrameMapping(pNodeNew, pNode, iFrame, arg);
}
// add the new POs
Abc_NtkForEachPo( pNtk, pNode, i )
{
pNodeNew = Abc_NtkDupObj( pNtkFrames, pNode );
Abc_ObjAddFanin( pNodeNew, Abc_ObjChild0Copy(pNode) );
- Abc_NtkLogicStoreNamePlus( pNodeNew, Abc_ObjName(pNode), Buffer );
+ Abc_ObjAssignName( pNodeNew, Abc_ObjName(pNode), Buffer );
+ if (addFrameMapping) addFrameMapping(pNodeNew, pNode, iFrame, arg);
}
// transfer the implementation of the latch drivers to the latches
- Abc_NtkForEachLatch( pNtk, pLatch, i )
- pLatch->pCopy = Abc_ObjChild0Copy(pLatch);
+
+ // it is important that these two steps are performed it two loops
+ // and not in the same loop
+ Abc_NtkForEachLatch( pNtk, pLatch, i )
+ pLatch->pNext = Abc_ObjChild0Copy(pLatch);
+ Abc_NtkForEachLatch( pNtk, pLatch, i )
+ pLatch->pCopy = pLatch->pNext;
+
+ Abc_NtkForEachLatch( pNtk, pLatch, i )
+ {
+ if (addFrameMapping) {
+ // don't give Mike complemented pointers because he doesn't like it
+ if (Abc_ObjIsComplement(pLatch->pCopy)) {
+ pNodeNew = Abc_NtkCreateNode( pNtkFrames );
+ Abc_ObjAddFanin( pNodeNew, pLatch->pCopy );
+ assert(Abc_ObjFaninNum(pNodeNew) == 1);
+ pNodeNew->Level = 1 + Abc_ObjRegular(pLatch->pCopy)->Level;
+
+ pLatch->pNext = pNodeNew;
+ pLatch->pCopy = pNodeNew;
+ }
+ addFrameMapping(pLatch->pCopy, pLatch, iFrame+1, arg);
+ }
+ }
+*/
}
+
+/**Function*************************************************************
+
+ Synopsis [Splits the miter into two logic cones combined by an EXOR]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Abc_NtkDemiter( Abc_Ntk_t * pNtk )
+{
+ Abc_Obj_t * pNodeC, * pNodeA, * pNodeB, * pNode;
+ Abc_Obj_t * pPoNew;
+ Vec_Ptr_t * vNodes1, * vNodes2;
+ int nCommon, i;
+
+ assert( Abc_NtkIsStrash(pNtk) );
+ assert( Abc_NtkPoNum(pNtk) == 1 );
+ if ( !Abc_NodeIsExorType(Abc_ObjFanin0(Abc_NtkPo(pNtk,0))) )
+ {
+ printf( "The root of the miter is not an EXOR gate.\n" );
+ return 0;
+ }
+ pNodeC = Abc_NodeRecognizeMux( Abc_ObjFanin0(Abc_NtkPo(pNtk,0)), &pNodeA, &pNodeB );
+ assert( Abc_ObjRegular(pNodeA) == Abc_ObjRegular(pNodeB) );
+ if ( Abc_ObjFaninC0(Abc_NtkPo(pNtk,0)) )
+ {
+ pNodeA = Abc_ObjNot(pNodeA);
+ pNodeB = Abc_ObjNot(pNodeB);
+ }
+
+ // add the PO corresponding to control input
+ pPoNew = Abc_NtkCreatePo( pNtk );
+ Abc_ObjAddFanin( pPoNew, pNodeC );
+ Abc_ObjAssignName( pPoNew, "addOut1", NULL );
+
+ // add the PO corresponding to other input
+ pPoNew = Abc_NtkCreatePo( pNtk );
+ Abc_ObjAddFanin( pPoNew, pNodeB );
+ Abc_ObjAssignName( pPoNew, "addOut2", NULL );
+
+ // mark the nodes in the first cone
+ pNodeB = Abc_ObjRegular(pNodeB);
+ vNodes1 = Abc_NtkDfsNodes( pNtk, &pNodeC, 1 );
+ vNodes2 = Abc_NtkDfsNodes( pNtk, &pNodeB, 1 );
+
+ Vec_PtrForEachEntry( vNodes1, pNode, i )
+ pNode->fMarkA = 1;
+ nCommon = 0;
+ Vec_PtrForEachEntry( vNodes2, pNode, i )
+ nCommon += pNode->fMarkA;
+ Vec_PtrForEachEntry( vNodes1, pNode, i )
+ pNode->fMarkA = 0;
+
+ printf( "First cone = %6d. Second cone = %6d. Common = %6d.\n", vNodes1->nSize, vNodes2->nSize, nCommon );
+ Vec_PtrFree( vNodes1 );
+ Vec_PtrFree( vNodes2 );
+
+ // reorder the latches
+ Abc_NtkOrderCisCos( pNtk );
+ // make sure that everything is okay
+ if ( !Abc_NtkCheck( pNtk ) )
+ printf( "Abc_NtkDemiter: The network check has failed.\n" );
+ return 1;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Computes OR or AND of the POs.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Abc_NtkCombinePos( Abc_Ntk_t * pNtk, int fAnd )
+{
+ Abc_Obj_t * pNode, * pMiter;
+ int i;
+ assert( Abc_NtkIsStrash(pNtk) );
+// assert( Abc_NtkLatchNum(pNtk) == 0 );
+ if ( Abc_NtkPoNum(pNtk) == 1 )
+ return 1;
+ // start the result
+ if ( fAnd )
+ pMiter = Abc_AigConst1(pNtk);
+ else
+ pMiter = Abc_ObjNot( Abc_AigConst1(pNtk) );
+ // perform operations on the POs
+ Abc_NtkForEachPo( pNtk, pNode, i )
+ if ( fAnd )
+ pMiter = Abc_AigAnd( pNtk->pManFunc, pMiter, Abc_ObjChild0(pNode) );
+ else
+ pMiter = Abc_AigOr( pNtk->pManFunc, pMiter, Abc_ObjChild0(pNode) );
+ // remove the POs and their names
+ for ( i = Abc_NtkPoNum(pNtk) - 1; i >= 0; i-- )
+ Abc_NtkDeleteObj( Abc_NtkPo(pNtk, i) );
+ assert( Abc_NtkPoNum(pNtk) == 0 );
+ // create the new PO
+ pNode = Abc_NtkCreatePo( pNtk );
+ Abc_ObjAddFanin( pNode, pMiter );
+ Abc_ObjAssignName( pNode, "miter", NULL );
+ // make sure that everything is okay
+ if ( !Abc_NtkCheck( pNtk ) )
+ {
+ printf( "Abc_NtkOrPos: The network check has failed.\n" );
+ return 0;
+ }
+ return 1;
+}
+
////////////////////////////////////////////////////////////////////////
/// END OF FILE ///
////////////////////////////////////////////////////////////////////////
diff --git a/src/base/abci/abcMulti.c b/src/base/abci/abcMulti.c
new file mode 100644
index 00000000..e93360a0
--- /dev/null
+++ b/src/base/abci/abcMulti.c
@@ -0,0 +1,643 @@
+/**CFile****************************************************************
+
+ FileName [abcMulti.c]
+
+ SystemName [ABC: Logic synthesis and verification system.]
+
+ PackageName [Network and node package.]
+
+ Synopsis [Procedures which transform an AIG into multi-input AND-graph.]
+
+ Author [Alan Mishchenko]
+
+ Affiliation [UC Berkeley]
+
+ Date [Ver. 1.0. Started - June 20, 2005.]
+
+ Revision [$Id: abcMulti.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "abc.h"
+
+////////////////////////////////////////////////////////////////////////
+/// DECLARATIONS ///
+////////////////////////////////////////////////////////////////////////
+
+static void Abc_NtkMultiInt( Abc_Ntk_t * pNtk, Abc_Ntk_t * pNtkNew );
+static Abc_Obj_t * Abc_NtkMulti_rec( Abc_Ntk_t * pNtkNew, Abc_Obj_t * pNodeOld );
+
+static DdNode * Abc_NtkMultiDeriveBdd_rec( DdManager * dd, Abc_Obj_t * pNodeOld, Vec_Ptr_t * vFanins );
+static DdNode * Abc_NtkMultiDeriveBdd( DdManager * dd, Abc_Obj_t * pNodeOld, Vec_Ptr_t * vFaninsOld );
+
+static void Abc_NtkMultiSetBounds( Abc_Ntk_t * pNtk, int nThresh, int nFaninMax );
+static void Abc_NtkMultiSetBoundsCnf( Abc_Ntk_t * pNtk );
+static void Abc_NtkMultiSetBoundsMulti( Abc_Ntk_t * pNtk, int nThresh );
+static void Abc_NtkMultiSetBoundsSimple( Abc_Ntk_t * pNtk );
+static void Abc_NtkMultiSetBoundsFactor( Abc_Ntk_t * pNtk );
+static void Abc_NtkMultiCone( Abc_Obj_t * pNode, Vec_Ptr_t * vCone );
+
+////////////////////////////////////////////////////////////////////////
+/// FUNCTION DEFINITIONS ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+ Synopsis [Transforms the AIG into nodes.]
+
+ Description [Threhold is the max number of nodes duplicated at a node.]
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Abc_Ntk_t * Abc_NtkMulti( Abc_Ntk_t * pNtk, int nThresh, int nFaninMax, int fCnf, int fMulti, int fSimple, int fFactor )
+{
+ Abc_Ntk_t * pNtkNew;
+
+ assert( Abc_NtkIsStrash(pNtk) );
+ assert( nThresh >= 0 );
+ assert( nFaninMax > 1 );
+
+ // print a warning about choice nodes
+ if ( Abc_NtkGetChoiceNum( pNtk ) )
+ printf( "Warning: The choice nodes in the AIG are removed by renoding.\n" );
+
+ // define the boundary
+ if ( fCnf )
+ Abc_NtkMultiSetBoundsCnf( pNtk );
+ else if ( fMulti )
+ Abc_NtkMultiSetBoundsMulti( pNtk, nThresh );
+ else if ( fSimple )
+ Abc_NtkMultiSetBoundsSimple( pNtk );
+ else if ( fFactor )
+ Abc_NtkMultiSetBoundsFactor( pNtk );
+ else
+ Abc_NtkMultiSetBounds( pNtk, nThresh, nFaninMax );
+
+ // perform renoding for this boundary
+ pNtkNew = Abc_NtkStartFrom( pNtk, ABC_NTK_LOGIC, ABC_FUNC_BDD );
+ Abc_NtkMultiInt( pNtk, pNtkNew );
+ Abc_NtkFinalize( pNtk, pNtkNew );
+
+ // make the network minimum base
+ Abc_NtkMinimumBase( pNtkNew );
+
+ // fix the problem with complemented and duplicated CO edges
+ Abc_NtkLogicMakeSimpleCos( pNtkNew, 0 );
+
+ // report the number of CNF objects
+ if ( fCnf )
+ {
+// int nClauses = Abc_NtkGetClauseNum(pNtkNew) + 2*Abc_NtkPoNum(pNtkNew) + 2*Abc_NtkLatchNum(pNtkNew);
+// printf( "CNF variables = %d. CNF clauses = %d.\n", Abc_NtkNodeNum(pNtkNew), nClauses );
+ }
+//printf( "Maximum fanin = %d.\n", Abc_NtkGetFaninMax(pNtkNew) );
+
+ if ( pNtk->pExdc )
+ pNtkNew->pExdc = Abc_NtkDup( pNtk->pExdc );
+ // make sure everything is okay
+ if ( !Abc_NtkCheck( pNtkNew ) )
+ {
+ printf( "Abc_NtkMulti: The network check has failed.\n" );
+ Abc_NtkDelete( pNtkNew );
+ return NULL;
+ }
+ return pNtkNew;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Transforms the AIG into nodes.]
+
+ Description [Threhold is the max number of nodes duplicated at a node.]
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Abc_NtkMultiInt( Abc_Ntk_t * pNtk, Abc_Ntk_t * pNtkNew )
+{
+ ProgressBar * pProgress;
+ Abc_Obj_t * pNode, * pConst1, * pNodeNew;
+ int i;
+
+ // set the constant node
+ pConst1 = Abc_AigConst1(pNtk);
+ if ( Abc_ObjFanoutNum(pConst1) > 0 )
+ {
+ pNodeNew = Abc_NtkCreateNode( pNtkNew );
+ pNodeNew->pData = Cudd_ReadOne( pNtkNew->pManFunc ); Cudd_Ref( pNodeNew->pData );
+ pConst1->pCopy = pNodeNew;
+ }
+
+ // perform renoding for POs
+ pProgress = Extra_ProgressBarStart( stdout, Abc_NtkCoNum(pNtk) );
+ Abc_NtkForEachCo( pNtk, pNode, i )
+ {
+ Extra_ProgressBarUpdate( pProgress, i, NULL );
+ if ( Abc_ObjIsCi(Abc_ObjFanin0(pNode)) )
+ continue;
+ Abc_NtkMulti_rec( pNtkNew, Abc_ObjFanin0(pNode) );
+ }
+ Extra_ProgressBarStop( pProgress );
+
+ // clean the boundaries and data field in the old network
+ Abc_NtkForEachObj( pNtk, pNode, i )
+ {
+ pNode->fMarkA = 0;
+ pNode->pData = NULL;
+ }
+}
+
+/**Function*************************************************************
+
+ Synopsis [Find the best multi-input node rooted at the given node.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Abc_Obj_t * Abc_NtkMulti_rec( Abc_Ntk_t * pNtkNew, Abc_Obj_t * pNodeOld )
+{
+ Vec_Ptr_t * vCone;
+ Abc_Obj_t * pNodeNew;
+ int i;
+
+ assert( !Abc_ObjIsComplement(pNodeOld) );
+ // return if the result if known
+ if ( pNodeOld->pCopy )
+ return pNodeOld->pCopy;
+ assert( Abc_ObjIsNode(pNodeOld) );
+ assert( !Abc_AigNodeIsConst(pNodeOld) );
+ assert( pNodeOld->fMarkA );
+
+//printf( "%d ", Abc_NodeMffcSizeSupp(pNodeOld) );
+
+ // collect the renoding cone
+ vCone = Vec_PtrAlloc( 10 );
+ Abc_NtkMultiCone( pNodeOld, vCone );
+
+ // create a new node
+ pNodeNew = Abc_NtkCreateNode( pNtkNew );
+ for ( i = 0; i < vCone->nSize; i++ )
+ Abc_ObjAddFanin( pNodeNew, Abc_NtkMulti_rec(pNtkNew, vCone->pArray[i]) );
+
+ // derive the function of this node
+ pNodeNew->pData = Abc_NtkMultiDeriveBdd( pNtkNew->pManFunc, pNodeOld, vCone );
+ Cudd_Ref( pNodeNew->pData );
+ Vec_PtrFree( vCone );
+
+ // remember the node
+ pNodeOld->pCopy = pNodeNew;
+ return pNodeOld->pCopy;
+}
+
+
+/**Function*************************************************************
+
+ Synopsis [Derives the local BDD of the node.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+DdNode * Abc_NtkMultiDeriveBdd( DdManager * dd, Abc_Obj_t * pNodeOld, Vec_Ptr_t * vFaninsOld )
+{
+ Abc_Obj_t * pFaninOld;
+ DdNode * bFunc;
+ int i;
+ assert( !Abc_AigNodeIsConst(pNodeOld) );
+ assert( Abc_ObjIsNode(pNodeOld) );
+ // set the elementary BDD variables for the input nodes
+ for ( i = 0; i < vFaninsOld->nSize; i++ )
+ {
+ pFaninOld = vFaninsOld->pArray[i];
+ pFaninOld->pData = Cudd_bddIthVar( dd, i ); Cudd_Ref( pFaninOld->pData );
+ pFaninOld->fMarkC = 1;
+ }
+ // call the recursive BDD computation
+ bFunc = Abc_NtkMultiDeriveBdd_rec( dd, pNodeOld, vFaninsOld ); Cudd_Ref( bFunc );
+ // dereference the intermediate nodes
+ for ( i = 0; i < vFaninsOld->nSize; i++ )
+ {
+ pFaninOld = vFaninsOld->pArray[i];
+ Cudd_RecursiveDeref( dd, pFaninOld->pData );
+ pFaninOld->fMarkC = 0;
+ }
+ Cudd_Deref( bFunc );
+ return bFunc;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Derives the local BDD of the node.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+DdNode * Abc_NtkMultiDeriveBdd_rec( DdManager * dd, Abc_Obj_t * pNode, Vec_Ptr_t * vFanins )
+{
+ DdNode * bFunc, * bFunc0, * bFunc1;
+ assert( !Abc_ObjIsComplement(pNode) );
+ // if the result is available return
+ if ( pNode->fMarkC )
+ {
+ assert( pNode->pData ); // network has a cycle
+ return pNode->pData;
+ }
+ // mark the node as visited
+ pNode->fMarkC = 1;
+ Vec_PtrPush( vFanins, pNode );
+ // compute the result for both branches
+ bFunc0 = Abc_NtkMultiDeriveBdd_rec( dd, Abc_ObjFanin(pNode,0), vFanins ); Cudd_Ref( bFunc0 );
+ bFunc1 = Abc_NtkMultiDeriveBdd_rec( dd, Abc_ObjFanin(pNode,1), vFanins ); Cudd_Ref( bFunc1 );
+ bFunc0 = Cudd_NotCond( bFunc0, Abc_ObjFaninC0(pNode) );
+ bFunc1 = Cudd_NotCond( bFunc1, Abc_ObjFaninC1(pNode) );
+ // get the final result
+ bFunc = Cudd_bddAnd( dd, bFunc0, bFunc1 ); Cudd_Ref( bFunc );
+ Cudd_RecursiveDeref( dd, bFunc0 );
+ Cudd_RecursiveDeref( dd, bFunc1 );
+ // set the result
+ pNode->pData = bFunc;
+ assert( pNode->pData );
+ return bFunc;
+}
+
+
+
+/**Function*************************************************************
+
+ Synopsis [Limits the cones to be no more than the given size.]
+
+ Description [Returns 1 if the last cone was limited. Returns 0 if no changes.]
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Abc_NtkMultiLimit_rec( Abc_Obj_t * pNode, Vec_Ptr_t * vCone, int nFaninMax, int fCanStop, int fFirst )
+{
+ int nNodes0, nNodes1;
+ assert( !Abc_ObjIsComplement(pNode) );
+ // check if the node should be added to the fanins
+ if ( !fFirst && (pNode->fMarkA || !Abc_ObjIsNode(pNode)) )
+ {
+ Vec_PtrPushUnique( vCone, pNode );
+ return 0;
+ }
+ // if we cannot stop in this branch, collect all nodes
+ if ( !fCanStop )
+ {
+ Abc_NtkMultiLimit_rec( Abc_ObjFanin(pNode,0), vCone, nFaninMax, 0, 0 );
+ Abc_NtkMultiLimit_rec( Abc_ObjFanin(pNode,1), vCone, nFaninMax, 0, 0 );
+ return 0;
+ }
+ // if we can stop, try the left branch first, and return if we stopped
+ assert( vCone->nSize == 0 );
+ if ( Abc_NtkMultiLimit_rec( Abc_ObjFanin(pNode,0), vCone, nFaninMax, 1, 0 ) )
+ return 1;
+ // save the number of nodes in the left branch and call for the right branch
+ nNodes0 = vCone->nSize;
+ assert( nNodes0 <= nFaninMax );
+ Abc_NtkMultiLimit_rec( Abc_ObjFanin(pNode,1), vCone, nFaninMax, 0, 0 );
+ // check the number of nodes
+ if ( vCone->nSize <= nFaninMax )
+ return 0;
+ // the number of nodes exceeds the limit
+
+ // get the number of nodes in the right branch
+ vCone->nSize = 0;
+ Abc_NtkMultiLimit_rec( Abc_ObjFanin(pNode,1), vCone, nFaninMax, 0, 0 );
+ // if this number exceeds the limit, solve the problem for this branch
+ if ( vCone->nSize > nFaninMax )
+ {
+ int RetValue;
+ vCone->nSize = 0;
+ RetValue = Abc_NtkMultiLimit_rec( Abc_ObjFanin(pNode,1), vCone, nFaninMax, 1, 0 );
+ assert( RetValue == 1 );
+ return 1;
+ }
+
+ nNodes1 = vCone->nSize;
+ assert( nNodes1 <= nFaninMax );
+ if ( nNodes0 >= nNodes1 )
+ { // the left branch is larger - cut it
+ assert( Abc_ObjFanin(pNode,0)->fMarkA == 0 );
+ Abc_ObjFanin(pNode,0)->fMarkA = 1;
+ }
+ else
+ { // the right branch is larger - cut it
+ assert( Abc_ObjFanin(pNode,1)->fMarkA == 0 );
+ Abc_ObjFanin(pNode,1)->fMarkA = 1;
+ }
+ return 1;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Limits the cones to be no more than the given size.]
+
+ Description [Returns 1 if the last cone was limited. Returns 0 if no changes.]
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Abc_NtkMultiLimit( Abc_Obj_t * pNode, Vec_Ptr_t * vCone, int nFaninMax )
+{
+ vCone->nSize = 0;
+ return Abc_NtkMultiLimit_rec( pNode, vCone, nFaninMax, 1, 1 );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Sets the expansion boundary for multi-input nodes.]
+
+ Description [The boundary includes the set of PIs and all nodes such that
+ when expanding over the node we duplicate no more than nThresh nodes.]
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Abc_NtkMultiSetBounds( Abc_Ntk_t * pNtk, int nThresh, int nFaninMax )
+{
+ Vec_Ptr_t * vCone = Vec_PtrAlloc(10);
+ Abc_Obj_t * pNode;
+ int i, nFanouts, nConeSize;
+
+ // make sure the mark is not set
+ Abc_NtkForEachObj( pNtk, pNode, i )
+ assert( pNode->fMarkA == 0 );
+
+ // mark the nodes where expansion stops using pNode->fMarkA
+ Abc_NtkForEachNode( pNtk, pNode, i )
+ {
+ // skip PI/PO nodes
+// if ( Abc_NodeIsConst(pNode) )
+// continue;
+ // mark the nodes with multiple fanouts
+ nFanouts = Abc_ObjFanoutNum(pNode);
+ nConeSize = Abc_NodeMffcSize(pNode);
+ if ( (nFanouts - 1) * nConeSize > nThresh )
+ pNode->fMarkA = 1;
+ }
+
+ // mark the PO drivers
+ Abc_NtkForEachCo( pNtk, pNode, i )
+ Abc_ObjFanin0(pNode)->fMarkA = 1;
+
+ // make sure the fanin limit is met
+ Abc_NtkForEachNode( pNtk, pNode, i )
+ {
+ // skip PI/PO nodes
+// if ( Abc_NodeIsConst(pNode) )
+// continue;
+ if ( pNode->fMarkA == 0 )
+ continue;
+ // continue cutting branches until it meets the fanin limit
+ while ( Abc_NtkMultiLimit(pNode, vCone, nFaninMax) );
+ assert( vCone->nSize <= nFaninMax );
+ }
+ Vec_PtrFree(vCone);
+/*
+ // make sure the fanin limit is met
+ Abc_NtkForEachNode( pNtk, pNode, i )
+ {
+ // skip PI/PO nodes
+// if ( Abc_NodeIsConst(pNode) )
+// continue;
+ if ( pNode->fMarkA == 0 )
+ continue;
+ Abc_NtkMultiCone( pNode, vCone );
+ assert( vCone->nSize <= nFaninMax );
+ }
+*/
+}
+
+/**Function*************************************************************
+
+ Synopsis [Sets the expansion boundary for conversion into CNF.]
+
+ Description [The boundary includes the set of PIs, the roots of MUXes,
+ the nodes with multiple fanouts and the nodes with complemented outputs.]
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Abc_NtkMultiSetBoundsCnf( Abc_Ntk_t * pNtk )
+{
+ Abc_Obj_t * pNode;
+ int i, nMuxes;
+
+ // make sure the mark is not set
+ Abc_NtkForEachObj( pNtk, pNode, i )
+ assert( pNode->fMarkA == 0 );
+
+ // mark the nodes where expansion stops using pNode->fMarkA
+ Abc_NtkForEachNode( pNtk, pNode, i )
+ {
+ // skip PI/PO nodes
+// if ( Abc_NodeIsConst(pNode) )
+// continue;
+ // mark the nodes with multiple fanouts
+ if ( Abc_ObjFanoutNum(pNode) > 1 )
+ pNode->fMarkA = 1;
+ // mark the nodes that are roots of MUXes
+ if ( Abc_NodeIsMuxType( pNode ) )
+ {
+ pNode->fMarkA = 1;
+ Abc_ObjFanin0( Abc_ObjFanin0(pNode) )->fMarkA = 1;
+ Abc_ObjFanin0( Abc_ObjFanin1(pNode) )->fMarkA = 1;
+ Abc_ObjFanin1( Abc_ObjFanin0(pNode) )->fMarkA = 1;
+ Abc_ObjFanin1( Abc_ObjFanin1(pNode) )->fMarkA = 1;
+ }
+ else // mark the complemented edges
+ {
+ if ( Abc_ObjFaninC0(pNode) )
+ Abc_ObjFanin0(pNode)->fMarkA = 1;
+ if ( Abc_ObjFaninC1(pNode) )
+ Abc_ObjFanin1(pNode)->fMarkA = 1;
+ }
+ }
+
+ // mark the PO drivers
+ Abc_NtkForEachCo( pNtk, pNode, i )
+ Abc_ObjFanin0(pNode)->fMarkA = 1;
+
+ // count the number of MUXes
+ nMuxes = 0;
+ Abc_NtkForEachNode( pNtk, pNode, i )
+ {
+ // skip PI/PO nodes
+// if ( Abc_NodeIsConst(pNode) )
+// continue;
+ if ( Abc_NodeIsMuxType(pNode) &&
+ Abc_ObjFanin0(pNode)->fMarkA == 0 &&
+ Abc_ObjFanin1(pNode)->fMarkA == 0 )
+ nMuxes++;
+ }
+// printf( "The number of MUXes detected = %d (%5.2f %% of logic).\n", nMuxes, 300.0*nMuxes/Abc_NtkNodeNum(pNtk) );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Sets the expansion boundary for conversion into multi-input AND graph.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Abc_NtkMultiSetBoundsMulti( Abc_Ntk_t * pNtk, int nThresh )
+{
+ Abc_Obj_t * pNode;
+ int i, nFanouts, nConeSize;
+
+ // make sure the mark is not set
+ Abc_NtkForEachObj( pNtk, pNode, i )
+ assert( pNode->fMarkA == 0 );
+
+ // mark the nodes where expansion stops using pNode->fMarkA
+ Abc_NtkForEachNode( pNtk, pNode, i )
+ {
+ // skip PI/PO nodes
+// if ( Abc_NodeIsConst(pNode) )
+// continue;
+ // mark the nodes with multiple fanouts
+// if ( Abc_ObjFanoutNum(pNode) > 1 )
+// pNode->fMarkA = 1;
+ // mark the nodes with multiple fanouts
+ nFanouts = Abc_ObjFanoutNum(pNode);
+ nConeSize = Abc_NodeMffcSizeStop(pNode);
+ if ( (nFanouts - 1) * nConeSize > nThresh )
+ pNode->fMarkA = 1;
+ // mark the children if they are pointed by the complemented edges
+ if ( Abc_ObjFaninC0(pNode) )
+ Abc_ObjFanin0(pNode)->fMarkA = 1;
+ if ( Abc_ObjFaninC1(pNode) )
+ Abc_ObjFanin1(pNode)->fMarkA = 1;
+ }
+
+ // mark the PO drivers
+ Abc_NtkForEachCo( pNtk, pNode, i )
+ Abc_ObjFanin0(pNode)->fMarkA = 1;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Sets a simple boundary.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Abc_NtkMultiSetBoundsSimple( Abc_Ntk_t * pNtk )
+{
+ Abc_Obj_t * pNode;
+ int i;
+ // make sure the mark is not set
+ Abc_NtkForEachObj( pNtk, pNode, i )
+ assert( pNode->fMarkA == 0 );
+ // mark the nodes where expansion stops using pNode->fMarkA
+ Abc_NtkForEachNode( pNtk, pNode, i )
+ pNode->fMarkA = 1;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Sets a factor-cut boundary.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Abc_NtkMultiSetBoundsFactor( Abc_Ntk_t * pNtk )
+{
+ Abc_Obj_t * pNode;
+ int i;
+ // make sure the mark is not set
+ Abc_NtkForEachObj( pNtk, pNode, i )
+ assert( pNode->fMarkA == 0 );
+ // mark the nodes where expansion stops using pNode->fMarkA
+ Abc_NtkForEachNode( pNtk, pNode, i )
+ pNode->fMarkA = (pNode->vFanouts.nSize > 1 && !Abc_NodeIsMuxControlType(pNode));
+ // mark the PO drivers
+ Abc_NtkForEachCo( pNtk, pNode, i )
+ Abc_ObjFanin0(pNode)->fMarkA = 1;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Collects the fanins of a large node.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Abc_NtkMultiCone_rec( Abc_Obj_t * pNode, Vec_Ptr_t * vCone )
+{
+ assert( !Abc_ObjIsComplement(pNode) );
+ if ( pNode->fMarkA || !Abc_ObjIsNode(pNode) )
+ {
+ Vec_PtrPushUnique( vCone, pNode );
+ return;
+ }
+ Abc_NtkMultiCone_rec( Abc_ObjFanin(pNode,0), vCone );
+ Abc_NtkMultiCone_rec( Abc_ObjFanin(pNode,1), vCone );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Collects the fanins of a large node.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Abc_NtkMultiCone( Abc_Obj_t * pNode, Vec_Ptr_t * vCone )
+{
+ assert( !Abc_ObjIsComplement(pNode) );
+ assert( Abc_ObjIsNode(pNode) );
+ vCone->nSize = 0;
+ Abc_NtkMultiCone_rec( Abc_ObjFanin(pNode,0), vCone );
+ Abc_NtkMultiCone_rec( Abc_ObjFanin(pNode,1), vCone );
+}
+
+////////////////////////////////////////////////////////////////////////
+/// END OF FILE ///
+////////////////////////////////////////////////////////////////////////
+
+
diff --git a/src/base/abci/abcMv.c b/src/base/abci/abcMv.c
new file mode 100644
index 00000000..2858b8a7
--- /dev/null
+++ b/src/base/abci/abcMv.c
@@ -0,0 +1,369 @@
+/**CFile****************************************************************
+
+ FileName [abcMv.c]
+
+ SystemName [ABC: Logic synthesis and verification system.]
+
+ PackageName [Network and node package.]
+
+ Synopsis [Multi-valued decomposition.]
+
+ Author [Alan Mishchenko]
+
+ Affiliation [UC Berkeley]
+
+ Date [Ver. 1.0. Started - June 20, 2005.]
+
+ Revision [$Id: abcMv.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "abc.h"
+
+////////////////////////////////////////////////////////////////////////
+/// DECLARATIONS ///
+////////////////////////////////////////////////////////////////////////
+
+typedef struct Mv_Man_t_ Mv_Man_t;
+struct Mv_Man_t_
+{
+ int nInputs; // the number of 4-valued input variables
+ int nFuncs; // the number of 4-valued functions
+ DdManager * dd; // representation of functions
+ DdNode * bValues[15][4]; // representation of i-sets
+ DdNode * bValueDcs[15][4]; // representation of i-sets don't-cares
+ DdNode * bFuncs[15]; // representation of functions
+};
+
+static void Abc_MvDecompose( Mv_Man_t * p );
+static void Abc_MvPrintStats( Mv_Man_t * p );
+static void Abc_MvRead( Mv_Man_t * p );
+static void Abc_MvDeref( Mv_Man_t * p );
+static DdNode * Abc_MvReadCube( DdManager * dd, char * pLine, int nVars );
+
+////////////////////////////////////////////////////////////////////////
+/// FUNCTION DEFINITIONS ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Abc_MvExperiment()
+{
+ Mv_Man_t * p;
+ // get the functions
+ p = ALLOC( Mv_Man_t, 1 );
+ memset( p, 0, sizeof(Mv_Man_t) );
+ p->dd = Cudd_Init( 32, 0, CUDD_UNIQUE_SLOTS, CUDD_CACHE_SLOTS, 0 );
+ p->nFuncs = 15;
+ p->nInputs = 9;
+ Abc_MvRead( p );
+ // process the functions
+ Abc_MvPrintStats( p );
+// Cudd_ReduceHeap( p->dd, CUDD_REORDER_SYMM_SIFT, 1 );
+// Abc_MvPrintStats( p );
+ // try detecting support reducing bound set
+ Abc_MvDecompose( p );
+
+ // remove the manager
+ Abc_MvDeref( p );
+ Extra_StopManager( p->dd );
+ free( p );
+}
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Abc_MvPrintStats( Mv_Man_t * p )
+{
+ int i, v;
+ for ( i = 0; i < 15; i++ )
+ {
+ printf( "%2d : ", i );
+ printf( "%3d (%2d) ", Cudd_DagSize(p->bFuncs[i])-1, Cudd_SupportSize(p->dd, p->bFuncs[i]) );
+ for ( v = 0; v < 4; v++ )
+ printf( "%d = %3d (%2d) ", v, Cudd_DagSize(p->bValues[i][v])-1, Cudd_SupportSize(p->dd, p->bValues[i][v]) );
+ printf( "\n" );
+ }
+}
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+DdNode * Abc_MvReadCube( DdManager * dd, char * pLine, int nVars )
+{
+ DdNode * bCube, * bVar, * bTemp;
+ int i;
+ bCube = Cudd_ReadOne(dd); Cudd_Ref( bCube );
+ for ( i = 0; i < nVars; i++ )
+ {
+ if ( pLine[i] == '-' )
+ continue;
+ else if ( pLine[i] == '0' ) // 0
+ bVar = Cudd_Not( Cudd_bddIthVar(dd, 29-i) );
+ else if ( pLine[i] == '1' ) // 1
+ bVar = Cudd_bddIthVar(dd, 29-i);
+ else assert(0);
+ bCube = Cudd_bddAnd( dd, bTemp = bCube, bVar ); Cudd_Ref( bCube );
+ Cudd_RecursiveDeref( dd, bTemp );
+ }
+ Cudd_Deref( bCube );
+ return bCube;
+}
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Abc_MvRead( Mv_Man_t * p )
+{
+ FILE * pFile;
+ char Buffer[1000], * pLine;
+ DdNode * bCube, * bTemp, * bProd, * bVar0, * bVar1, * bCubeSum;
+ int i, v;
+
+ // start the cube
+ bCubeSum = Cudd_ReadLogicZero(p->dd); Cudd_Ref( bCubeSum );
+
+ // start the values
+ for ( i = 0; i < 15; i++ )
+ for ( v = 0; v < 4; v++ )
+ {
+ p->bValues[i][v] = Cudd_ReadLogicZero(p->dd); Cudd_Ref( p->bValues[i][v] );
+ p->bValueDcs[i][v] = Cudd_ReadLogicZero(p->dd); Cudd_Ref( p->bValueDcs[i][v] );
+ }
+
+ // read the file
+ pFile = fopen( "input.pla", "r" );
+ while ( fgets( Buffer, 1000, pFile ) )
+ {
+ if ( Buffer[0] == '#' )
+ continue;
+ if ( Buffer[0] == '.' )
+ {
+ if ( Buffer[1] == 'e' )
+ break;
+ continue;
+ }
+
+ // get the cube
+ bCube = Abc_MvReadCube( p->dd, Buffer, 18 ); Cudd_Ref( bCube );
+
+ // add it to the values of the output functions
+ pLine = Buffer + 19;
+ for ( i = 0; i < 15; i++ )
+ {
+ if ( pLine[2*i] == '-' && pLine[2*i+1] == '-' )
+ {
+ for ( v = 0; v < 4; v++ )
+ {
+ p->bValueDcs[i][v] = Cudd_bddOr( p->dd, bTemp = p->bValueDcs[i][v], bCube ); Cudd_Ref( p->bValueDcs[i][v] );
+ Cudd_RecursiveDeref( p->dd, bTemp );
+ }
+ continue;
+ }
+ else if ( pLine[2*i] == '0' && pLine[2*i+1] == '0' ) // 0
+ v = 0;
+ else if ( pLine[2*i] == '1' && pLine[2*i+1] == '0' ) // 1
+ v = 1;
+ else if ( pLine[2*i] == '0' && pLine[2*i+1] == '1' ) // 2
+ v = 2;
+ else if ( pLine[2*i] == '1' && pLine[2*i+1] == '1' ) // 3
+ v = 3;
+ else assert( 0 );
+ // add the value
+ p->bValues[i][v] = Cudd_bddOr( p->dd, bTemp = p->bValues[i][v], bCube ); Cudd_Ref( p->bValues[i][v] );
+ Cudd_RecursiveDeref( p->dd, bTemp );
+ }
+
+ // add the cube
+ bCubeSum = Cudd_bddOr( p->dd, bTemp = bCubeSum, bCube ); Cudd_Ref( bCubeSum );
+ Cudd_RecursiveDeref( p->dd, bTemp );
+ Cudd_RecursiveDeref( p->dd, bCube );
+ }
+
+ // add the complement of the domain to all values
+ for ( i = 0; i < 15; i++ )
+ for ( v = 0; v < 4; v++ )
+ {
+ if ( p->bValues[i][v] == Cudd_Not(Cudd_ReadOne(p->dd)) )
+ continue;
+ p->bValues[i][v] = Cudd_bddOr( p->dd, bTemp = p->bValues[i][v], p->bValueDcs[i][v] ); Cudd_Ref( p->bValues[i][v] );
+ Cudd_RecursiveDeref( p->dd, bTemp );
+ p->bValues[i][v] = Cudd_bddOr( p->dd, bTemp = p->bValues[i][v], Cudd_Not(bCubeSum) ); Cudd_Ref( p->bValues[i][v] );
+ Cudd_RecursiveDeref( p->dd, bTemp );
+ }
+ printf( "Domain = %5.2f %%.\n", 100.0*Cudd_CountMinterm(p->dd, bCubeSum, 32)/Cudd_CountMinterm(p->dd, Cudd_ReadOne(p->dd), 32) );
+ Cudd_RecursiveDeref( p->dd, bCubeSum );
+
+ // create each output function
+ for ( i = 0; i < 15; i++ )
+ {
+ p->bFuncs[i] = Cudd_ReadLogicZero(p->dd); Cudd_Ref( p->bFuncs[i] );
+ for ( v = 0; v < 4; v++ )
+ {
+ bVar0 = Cudd_NotCond( Cudd_bddIthVar(p->dd, 30), ((v & 1) == 0) );
+ bVar1 = Cudd_NotCond( Cudd_bddIthVar(p->dd, 31), ((v & 2) == 0) );
+ bCube = Cudd_bddAnd( p->dd, bVar0, bVar1 ); Cudd_Ref( bCube );
+ bProd = Cudd_bddAnd( p->dd, p->bValues[i][v], bCube ); Cudd_Ref( bProd );
+ Cudd_RecursiveDeref( p->dd, bCube );
+ // add the value
+ p->bFuncs[i] = Cudd_bddOr( p->dd, bTemp = p->bFuncs[i], bProd ); Cudd_Ref( p->bFuncs[i] );
+ Cudd_RecursiveDeref( p->dd, bTemp );
+ Cudd_RecursiveDeref( p->dd, bProd );
+ }
+ }
+}
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Abc_MvDeref( Mv_Man_t * p )
+{
+ int i, v;
+ for ( i = 0; i < 15; i++ )
+ for ( v = 0; v < 4; v++ )
+ {
+ Cudd_RecursiveDeref( p->dd, p->bValues[i][v] );
+ Cudd_RecursiveDeref( p->dd, p->bValueDcs[i][v] );
+ }
+ for ( i = 0; i < 15; i++ )
+ Cudd_RecursiveDeref( p->dd, p->bFuncs[i] );
+}
+
+
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Abc_MvDecompose( Mv_Man_t * p )
+{
+ DdNode * bCofs[16], * bVarCube1, * bVarCube2, * bVarCube, * bCube, * bVar0, * bVar1;//, * bRes;
+ int k, i1, i2, v1, v2;//, c1, c2, Counter;
+
+ bVar0 = Cudd_bddIthVar(p->dd, 30);
+ bVar1 = Cudd_bddIthVar(p->dd, 31);
+ bCube = Cudd_bddAnd( p->dd, bVar0, bVar1 ); Cudd_Ref( bCube );
+
+ for ( k = 0; k < p->nFuncs; k++ )
+ {
+ printf( "FUNCTION %d\n", k );
+ for ( i1 = 0; i1 < p->nFuncs; i1++ )
+ for ( i2 = i1+1; i2 < p->nFuncs; i2++ )
+ {
+ Vec_Ptr_t * vCofs;
+
+ for ( v1 = 0; v1 < 4; v1++ )
+ {
+ bVar0 = Cudd_NotCond( Cudd_bddIthVar(p->dd, 29-2*i1 ), ((v1 & 1) == 0) );
+ bVar1 = Cudd_NotCond( Cudd_bddIthVar(p->dd, 29-2*i1-1), ((v1 & 2) == 0) );
+ bVarCube1 = Cudd_bddAnd( p->dd, bVar0, bVar1 ); Cudd_Ref( bVarCube1 );
+ for ( v2 = 0; v2 < 4; v2++ )
+ {
+ bVar0 = Cudd_NotCond( Cudd_bddIthVar(p->dd, 29-2*i2 ), ((v2 & 1) == 0) );
+ bVar1 = Cudd_NotCond( Cudd_bddIthVar(p->dd, 29-2*i2-1), ((v2 & 2) == 0) );
+ bVarCube2 = Cudd_bddAnd( p->dd, bVar0, bVar1 ); Cudd_Ref( bVarCube2 );
+ bVarCube = Cudd_bddAnd( p->dd, bVarCube1, bVarCube2 ); Cudd_Ref( bVarCube );
+ bCofs[v1 * 4 + v2] = Cudd_Cofactor( p->dd, p->bFuncs[k], bVarCube ); Cudd_Ref( bCofs[v1 * 4 + v2] );
+ Cudd_RecursiveDeref( p->dd, bVarCube );
+ Cudd_RecursiveDeref( p->dd, bVarCube2 );
+ }
+ Cudd_RecursiveDeref( p->dd, bVarCube1 );
+ }
+/*
+ // check the compatibility of cofactors
+ Counter = 0;
+ for ( c1 = 0; c1 < 16; c1++ )
+ {
+ for ( c2 = 0; c2 <= c1; c2++ )
+ printf( " " );
+ for ( c2 = c1+1; c2 < 16; c2++ )
+ {
+ bRes = Cudd_bddAndAbstract( p->dd, bCofs[c1], bCofs[c2], bCube ); Cudd_Ref( bRes );
+ if ( bRes == Cudd_ReadOne(p->dd) )
+ {
+ printf( "+" );
+ Counter++;
+ }
+ else
+ {
+ printf( " " );
+ }
+ Cudd_RecursiveDeref( p->dd, bRes );
+ }
+ printf( "\n" );
+ }
+*/
+
+ vCofs = Vec_PtrAlloc( 16 );
+ for ( v1 = 0; v1 < 4; v1++ )
+ for ( v2 = 0; v2 < 4; v2++ )
+ Vec_PtrPushUnique( vCofs, bCofs[v1 * 4 + v2] );
+ printf( "%d ", Vec_PtrSize(vCofs) );
+ Vec_PtrFree( vCofs );
+
+ // free the cofactors
+ for ( v1 = 0; v1 < 4; v1++ )
+ for ( v2 = 0; v2 < 4; v2++ )
+ Cudd_RecursiveDeref( p->dd, bCofs[v1 * 4 + v2] );
+
+ printf( "\n" );
+// printf( "%2d, %2d : %3d\n", i1, i2, Counter );
+ }
+ }
+
+ Cudd_RecursiveDeref( p->dd, bCube );
+}
+
+////////////////////////////////////////////////////////////////////////
+/// END OF FILE ///
+////////////////////////////////////////////////////////////////////////
+
+
diff --git a/src/base/abci/abcNtbdd.c b/src/base/abci/abcNtbdd.c
index 6362a925..f127811e 100644
--- a/src/base/abci/abcNtbdd.c
+++ b/src/base/abci/abcNtbdd.c
@@ -25,12 +25,12 @@
////////////////////////////////////////////////////////////////////////
static void Abc_NtkBddToMuxesPerform( Abc_Ntk_t * pNtk, Abc_Ntk_t * pNtkNew );
-static Abc_Obj_t * Abc_NodeBddToMuxes( Abc_Obj_t * pNodeOld, Abc_Ntk_t * pNtkNew, Abc_Obj_t * pConst1 );
+static Abc_Obj_t * Abc_NodeBddToMuxes( Abc_Obj_t * pNodeOld, Abc_Ntk_t * pNtkNew );
static Abc_Obj_t * Abc_NodeBddToMuxes_rec( DdManager * dd, DdNode * bFunc, Abc_Ntk_t * pNtkNew, st_table * tBdd2Node );
-static DdNode * Abc_NodeGlobalBdds_rec( DdManager * dd, Abc_Obj_t * pNode );
+static DdNode * Abc_NodeGlobalBdds_rec( DdManager * dd, Abc_Obj_t * pNode, int nBddSizeMax, int fDropInternal, ProgressBar * pProgress, int * pCounter, int fVerbose );
////////////////////////////////////////////////////////////////////////
-/// FUNCTION DEFITIONS ///
+/// FUNCTION DEFINITIONS ///
////////////////////////////////////////////////////////////////////////
/**Function*************************************************************
@@ -78,13 +78,13 @@ Abc_Ntk_t * Abc_NtkDeriveFromBdd( DdManager * dd, DdNode * bFunc, char * pNamePo
return NULL;
// start the network
- pNtk = Abc_NtkAlloc( ABC_TYPE_LOGIC, ABC_FUNC_BDD );
- pNtk->pName = util_strsav(pNamePo);
+ pNtk = Abc_NtkAlloc( ABC_NTK_LOGIC, ABC_FUNC_BDD, 1 );
+ pNtk->pName = Extra_UtilStrsav(pNamePo);
// make sure the new manager has enough inputs
Cudd_bddIthVar( pNtk->pManFunc, Vec_PtrSize(vNamesPi) );
// add the PIs corresponding to the names
Vec_PtrForEachEntry( vNamesPi, pName, i )
- Abc_NtkLogicStoreName( Abc_NtkCreatePi(pNtk), pName );
+ Abc_ObjAssignName( Abc_NtkCreatePi(pNtk), pName, NULL );
// create the node
pNode = Abc_NtkCreateNode( pNtk );
pNode->pData = Cudd_bddTransfer( dd, pNtk->pManFunc, bFunc ); Cudd_Ref(pNode->pData);
@@ -93,7 +93,7 @@ Abc_Ntk_t * Abc_NtkDeriveFromBdd( DdManager * dd, DdNode * bFunc, char * pNamePo
// create the only PO
pNodePo = Abc_NtkCreatePo( pNtk );
Abc_ObjAddFanin( pNodePo, pNode );
- Abc_NtkLogicStoreName( pNodePo, pNamePo );
+ Abc_ObjAssignName( pNodePo, pNamePo, NULL );
// make the network minimum base
Abc_NtkMinimumBase( pNtk );
if ( vNamesPiFake )
@@ -121,7 +121,7 @@ Abc_Ntk_t * Abc_NtkBddToMuxes( Abc_Ntk_t * pNtk )
{
Abc_Ntk_t * pNtkNew;
assert( Abc_NtkIsBddLogic(pNtk) );
- pNtkNew = Abc_NtkStartFrom( pNtk, ABC_TYPE_LOGIC, ABC_FUNC_SOP );
+ pNtkNew = Abc_NtkStartFrom( pNtk, ABC_NTK_LOGIC, ABC_FUNC_SOP );
Abc_NtkBddToMuxesPerform( pNtk, pNtkNew );
Abc_NtkFinalize( pNtk, pNtkNew );
// make sure everything is okay
@@ -148,12 +148,9 @@ Abc_Ntk_t * Abc_NtkBddToMuxes( Abc_Ntk_t * pNtk )
void Abc_NtkBddToMuxesPerform( Abc_Ntk_t * pNtk, Abc_Ntk_t * pNtkNew )
{
ProgressBar * pProgress;
- DdManager * dd = pNtk->pManFunc;
- Abc_Obj_t * pNode, * pNodeNew, * pConst1;
+ Abc_Obj_t * pNode, * pNodeNew;
Vec_Ptr_t * vNodes;
int i;
- // create the constant one node
- pConst1 = Abc_NodeCreateConst1( pNtkNew );
// perform conversion in the topological order
vNodes = Abc_NtkDfs( pNtk, 0 );
pProgress = Extra_ProgressBarStart( stdout, vNodes->nSize );
@@ -162,7 +159,7 @@ void Abc_NtkBddToMuxesPerform( Abc_Ntk_t * pNtk, Abc_Ntk_t * pNtkNew )
Extra_ProgressBarUpdate( pProgress, i, NULL );
// convert one node
assert( Abc_ObjIsNode(pNode) );
- pNodeNew = Abc_NodeBddToMuxes( pNode, pNtkNew, pConst1 );
+ pNodeNew = Abc_NodeBddToMuxes( pNode, pNtkNew );
// mark the old node with the new one
assert( pNode->pCopy == NULL );
pNode->pCopy = pNodeNew;
@@ -182,7 +179,7 @@ void Abc_NtkBddToMuxesPerform( Abc_Ntk_t * pNtk, Abc_Ntk_t * pNtkNew )
SeeAlso []
***********************************************************************/
-Abc_Obj_t * Abc_NodeBddToMuxes( Abc_Obj_t * pNodeOld, Abc_Ntk_t * pNtkNew, Abc_Obj_t * pConst1 )
+Abc_Obj_t * Abc_NodeBddToMuxes( Abc_Obj_t * pNodeOld, Abc_Ntk_t * pNtkNew )
{
DdManager * dd = pNodeOld->pNtk->pManFunc;
DdNode * bFunc = pNodeOld->pData;
@@ -192,14 +189,13 @@ Abc_Obj_t * Abc_NodeBddToMuxes( Abc_Obj_t * pNodeOld, Abc_Ntk_t * pNtkNew, Abc_O
// create the table mapping BDD nodes into the ABC nodes
tBdd2Node = st_init_table( st_ptrcmp, st_ptrhash );
// add the constant and the elementary vars
- st_insert( tBdd2Node, (char *)b1, (char *)pConst1 );
Abc_ObjForEachFanin( pNodeOld, pFaninOld, i )
st_insert( tBdd2Node, (char *)Cudd_bddIthVar(dd, i), (char *)pFaninOld->pCopy );
// create the new nodes recursively
pNodeNew = Abc_NodeBddToMuxes_rec( dd, Cudd_Regular(bFunc), pNtkNew, tBdd2Node );
st_free_table( tBdd2Node );
if ( Cudd_IsComplement(bFunc) )
- pNodeNew = Abc_NodeCreateInv( pNtkNew, pNodeNew );
+ pNodeNew = Abc_NtkCreateNodeInv( pNtkNew, pNodeNew );
return pNodeNew;
}
@@ -218,17 +214,19 @@ Abc_Obj_t * Abc_NodeBddToMuxes_rec( DdManager * dd, DdNode * bFunc, Abc_Ntk_t *
{
Abc_Obj_t * pNodeNew, * pNodeNew0, * pNodeNew1, * pNodeNewC;
assert( !Cudd_IsComplement(bFunc) );
+ if ( bFunc == b1 )
+ return Abc_NtkCreateNodeConst1(pNtkNew);
if ( st_lookup( tBdd2Node, (char *)bFunc, (char **)&pNodeNew ) )
return pNodeNew;
// solve for the children nodes
pNodeNew0 = Abc_NodeBddToMuxes_rec( dd, Cudd_Regular(cuddE(bFunc)), pNtkNew, tBdd2Node );
if ( Cudd_IsComplement(cuddE(bFunc)) )
- pNodeNew0 = Abc_NodeCreateInv( pNtkNew, pNodeNew0 );
+ pNodeNew0 = Abc_NtkCreateNodeInv( pNtkNew, pNodeNew0 );
pNodeNew1 = Abc_NodeBddToMuxes_rec( dd, cuddT(bFunc), pNtkNew, tBdd2Node );
if ( !st_lookup( tBdd2Node, (char *)Cudd_bddIthVar(dd, bFunc->index), (char **)&pNodeNewC ) )
assert( 0 );
// create the MUX node
- pNodeNew = Abc_NodeCreateMux( pNtkNew, pNodeNewC, pNodeNew1, pNodeNew0 );
+ pNodeNew = Abc_NtkCreateNodeMux( pNtkNew, pNodeNewC, pNodeNew1, pNodeNew0 );
st_insert( tBdd2Node, (char *)bFunc, (char *)pNodeNew );
return pNodeNew;
}
@@ -245,88 +243,96 @@ Abc_Obj_t * Abc_NodeBddToMuxes_rec( DdManager * dd, DdNode * bFunc, Abc_Ntk_t *
SeeAlso []
***********************************************************************/
-DdManager * Abc_NtkGlobalBdds( Abc_Ntk_t * pNtk, int fLatchOnly )
+DdManager * Abc_NtkBuildGlobalBdds( Abc_Ntk_t * pNtk, int nBddSizeMax, int fDropInternal, int fReorder, int fVerbose )
{
- int fReorder = 1;
ProgressBar * pProgress;
- Vec_Ptr_t * vFuncsGlob;
- Abc_Obj_t * pNode;
- DdNode * bFunc;
+ Abc_Obj_t * pObj, * pFanin;
+ Vec_Att_t * pAttMan;
DdManager * dd;
- int i;
+ DdNode * bFunc;
+ int i, k, Counter;
+
+ // remove dangling nodes
+ Abc_AigCleanup( pNtk->pManFunc );
// start the manager
- assert( pNtk->pManGlob == NULL );
+ assert( Abc_NtkGlobalBdd(pNtk) == NULL );
dd = Cudd_Init( Abc_NtkCiNum(pNtk), 0, CUDD_UNIQUE_SLOTS, CUDD_CACHE_SLOTS, 0 );
+ pAttMan = Vec_AttAlloc( 0, Abc_NtkObjNumMax(pNtk) + 1, dd, Extra_StopManager, NULL, Cudd_RecursiveDeref );
+ Vec_PtrWriteEntry( pNtk->vAttrs, VEC_ATTR_GLOBAL_BDD, pAttMan );
+
+ // set reordering
if ( fReorder )
Cudd_AutodynEnable( dd, CUDD_REORDER_SYMM_SIFT );
- // set the elementary variables
- Abc_NtkCleanCopy( pNtk );
- Abc_NtkForEachCi( pNtk, pNode, i )
- pNode->pCopy = (Abc_Obj_t *)dd->vars[i];
// assign the constant node BDD
- pNode = Abc_AigConst1( pNtk->pManFunc );
- pNode->pCopy = (Abc_Obj_t *)dd->one; Cudd_Ref( dd->one );
-
- // collect the global functions of the COs
- vFuncsGlob = Vec_PtrAlloc( 100 );
- if ( fLatchOnly )
+ pObj = Abc_AigConst1(pNtk);
+ if ( Abc_ObjFanoutNum(pObj) > 0 )
{
- // construct the BDDs
- pProgress = Extra_ProgressBarStart( stdout, Abc_NtkLatchNum(pNtk) );
- Abc_NtkForEachLatch( pNtk, pNode, i )
+ bFunc = dd->one;
+ Abc_ObjSetGlobalBdd( pObj, bFunc ); Cudd_Ref( bFunc );
+ }
+ // set the elementary variables
+ Abc_NtkForEachCi( pNtk, pObj, i )
+ if ( Abc_ObjFanoutNum(pObj) > 0 )
{
- Extra_ProgressBarUpdate( pProgress, i, NULL );
- bFunc = Abc_NodeGlobalBdds_rec( dd, Abc_ObjFanin0(pNode) );
- if ( bFunc == NULL )
- {
- printf( "Constructing global BDDs timed out.\n" );
- Extra_ProgressBarStop( pProgress );
- Cudd_Quit( dd );
- return NULL;
- }
- bFunc = Cudd_NotCond( bFunc, Abc_ObjFaninC0(pNode) ); Cudd_Ref( bFunc );
- Vec_PtrPush( vFuncsGlob, bFunc );
+ bFunc = dd->vars[i];
+// bFunc = dd->vars[Abc_NtkCiNum(pNtk) - 1 - i];
+ Abc_ObjSetGlobalBdd( pObj, bFunc ); Cudd_Ref( bFunc );
}
- Extra_ProgressBarStop( pProgress );
- }
- else
+
+ // collect the global functions of the COs
+ Counter = 0;
+ // construct the BDDs
+ pProgress = Extra_ProgressBarStart( stdout, Abc_NtkNodeNum(pNtk) );
+ Abc_NtkForEachCo( pNtk, pObj, i )
{
- // construct the BDDs
- pProgress = Extra_ProgressBarStart( stdout, Abc_NtkCoNum(pNtk) );
- Abc_NtkForEachCo( pNtk, pNode, i )
+ bFunc = Abc_NodeGlobalBdds_rec( dd, Abc_ObjFanin0(pObj), nBddSizeMax, fDropInternal, pProgress, &Counter, fVerbose );
+ if ( bFunc == NULL )
{
- Extra_ProgressBarUpdate( pProgress, i, NULL );
- bFunc = Abc_NodeGlobalBdds_rec( dd, Abc_ObjFanin0(pNode) );
- if ( bFunc == NULL )
- {
- printf( "Constructing global BDDs timed out.\n" );
- Extra_ProgressBarStop( pProgress );
- Cudd_Quit( dd );
- return NULL;
- }
- bFunc = Cudd_NotCond( bFunc, Abc_ObjFaninC0(pNode) ); Cudd_Ref( bFunc );
- Vec_PtrPush( vFuncsGlob, bFunc );
+ if ( fVerbose )
+ printf( "Constructing global BDDs is aborted.\n" );
+ Abc_NtkFreeGlobalBdds( pNtk, 0 );
+ Cudd_Quit( dd );
+ return NULL;
}
- Extra_ProgressBarStop( pProgress );
+ bFunc = Cudd_NotCond( bFunc, Abc_ObjFaninC0(pObj) ); Cudd_Ref( bFunc );
+ Abc_ObjSetGlobalBdd( pObj, bFunc );
}
+ Extra_ProgressBarStop( pProgress );
+/*
// derefence the intermediate BDDs
- Abc_NtkForEachNode( pNtk, pNode, i )
- if ( pNode->pCopy )
+ Abc_NtkForEachNode( pNtk, pObj, i )
+ if ( pObj->pCopy )
{
- Cudd_RecursiveDeref( dd, (DdNode *)pNode->pCopy );
- pNode->pCopy = NULL;
+ Cudd_RecursiveDeref( dd, (DdNode *)pObj->pCopy );
+ pObj->pCopy = NULL;
}
+*/
+/*
+ // make sure all nodes are derefed
+ Abc_NtkForEachObj( pNtk, pObj, i )
+ {
+ if ( pObj->pCopy != NULL )
+ printf( "Abc_NtkBuildGlobalBdds() error: Node %d has BDD assigned\n", pObj->Id );
+ if ( pObj->vFanouts.nSize > 0 )
+ printf( "Abc_NtkBuildGlobalBdds() error: Node %d has refs assigned\n", pObj->Id );
+ }
+*/
+ // reset references
+ Abc_NtkForEachObj( pNtk, pObj, i )
+ if ( !Abc_ObjIsBox(pObj) && !Abc_ObjIsBo(pObj) )
+ Abc_ObjForEachFanin( pObj, pFanin, k )
+ pFanin->vFanouts.nSize++;
+
// reorder one more time
if ( fReorder )
{
Cudd_ReduceHeap( dd, CUDD_REORDER_SYMM_SIFT, 1 );
Cudd_AutodynDisable( dd );
}
- pNtk->pManGlob = dd;
- pNtk->vFuncsGlob = vFuncsGlob;
+// Cudd_PrintInfo( dd, stdout );
return dd;
}
@@ -341,39 +347,107 @@ DdManager * Abc_NtkGlobalBdds( Abc_Ntk_t * pNtk, int fLatchOnly )
SeeAlso []
***********************************************************************/
-DdNode * Abc_NodeGlobalBdds_rec( DdManager * dd, Abc_Obj_t * pNode )
+DdNode * Abc_NodeGlobalBdds_rec( DdManager * dd, Abc_Obj_t * pNode, int nBddSizeMax, int fDropInternal, ProgressBar * pProgress, int * pCounter, int fVerbose )
{
- DdNode * bFunc, * bFunc0, * bFunc1;
+ DdNode * bFunc, * bFunc0, * bFunc1, * bFuncC;
+ int fDetectMuxes = 1;
assert( !Abc_ObjIsComplement(pNode) );
- if ( Cudd_ReadKeys(dd) > 500000 )
+ 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 ( pNode->pCopy )
- return (DdNode *)pNode->pCopy;
- // compute the result for both branches
- bFunc0 = Abc_NodeGlobalBdds_rec( dd, Abc_ObjFanin(pNode,0) );
- if ( bFunc0 == NULL )
- return NULL;
- Cudd_Ref( bFunc0 );
- bFunc1 = Abc_NodeGlobalBdds_rec( dd, Abc_ObjFanin(pNode,1) );
- if ( bFunc1 == NULL )
- return NULL;
- Cudd_Ref( bFunc1 );
- bFunc0 = Cudd_NotCond( bFunc0, Abc_ObjFaninC0(pNode) );
- bFunc1 = Cudd_NotCond( bFunc1, Abc_ObjFaninC1(pNode) );
- // get the final result
- bFunc = Cudd_bddAnd( dd, bFunc0, bFunc1 ); Cudd_Ref( bFunc );
- Cudd_RecursiveDeref( dd, bFunc0 );
- Cudd_RecursiveDeref( dd, bFunc1 );
- // set the result
- assert( pNode->pCopy == NULL );
- pNode->pCopy = (Abc_Obj_t *)bFunc;
+ if ( Abc_ObjGlobalBdd(pNode) == NULL )
+ {
+ Abc_Obj_t * pNodeC, * pNode0, * pNode1;
+ pNode0 = Abc_ObjFanin0(pNode);
+ pNode1 = Abc_ObjFanin1(pNode);
+ // check for the special case when it is MUX/EXOR
+ if ( fDetectMuxes &&
+ Abc_ObjGlobalBdd(pNode0) == NULL && Abc_ObjGlobalBdd(pNode1) == NULL &&
+ Abc_ObjIsNode(pNode0) && Abc_ObjFanoutNum(pNode0) == 1 &&
+ Abc_ObjIsNode(pNode1) && Abc_ObjFanoutNum(pNode1) == 1 &&
+ Abc_NodeIsMuxType(pNode) )
+ {
+ // deref the fanins
+ pNode0->vFanouts.nSize--;
+ pNode1->vFanouts.nSize--;
+ // recognize the MUX
+ pNodeC = Abc_NodeRecognizeMux( pNode, &pNode1, &pNode0 );
+ assert( Abc_ObjFanoutNum(pNodeC) > 1 );
+ // dereference the control once (the second time it will be derefed when BDDs are computed)
+ pNodeC->vFanouts.nSize--;
+
+ // compute the result for all branches
+ bFuncC = Abc_NodeGlobalBdds_rec( dd, pNodeC, nBddSizeMax, fDropInternal, pProgress, pCounter, fVerbose );
+ if ( bFuncC == NULL )
+ return NULL;
+ Cudd_Ref( bFuncC );
+ bFunc0 = Abc_NodeGlobalBdds_rec( dd, Abc_ObjRegular(pNode0), nBddSizeMax, fDropInternal, pProgress, pCounter, fVerbose );
+ if ( bFunc0 == NULL )
+ return NULL;
+ Cudd_Ref( bFunc0 );
+ bFunc1 = Abc_NodeGlobalBdds_rec( dd, Abc_ObjRegular(pNode1), nBddSizeMax, fDropInternal, pProgress, pCounter, fVerbose );
+ if ( bFunc1 == NULL )
+ return NULL;
+ Cudd_Ref( bFunc1 );
+
+ // complement the branch BDDs
+ bFunc0 = Cudd_NotCond( bFunc0, Abc_ObjIsComplement(pNode0) );
+ bFunc1 = Cudd_NotCond( bFunc1, Abc_ObjIsComplement(pNode1) );
+ // get the final result
+ bFunc = Cudd_bddIte( dd, bFuncC, bFunc1, bFunc0 ); Cudd_Ref( bFunc );
+ Cudd_RecursiveDeref( dd, bFunc0 );
+ Cudd_RecursiveDeref( dd, bFunc1 );
+ Cudd_RecursiveDeref( dd, bFuncC );
+ // add the number of used nodes
+ (*pCounter) += 3;
+ }
+ else
+ {
+ // compute the result for both branches
+ bFunc0 = Abc_NodeGlobalBdds_rec( dd, Abc_ObjFanin(pNode,0), nBddSizeMax, fDropInternal, pProgress, pCounter, fVerbose );
+ if ( bFunc0 == NULL )
+ return NULL;
+ Cudd_Ref( bFunc0 );
+ bFunc1 = Abc_NodeGlobalBdds_rec( dd, Abc_ObjFanin(pNode,1), nBddSizeMax, fDropInternal, pProgress, pCounter, fVerbose );
+ if ( bFunc1 == NULL )
+ return NULL;
+ Cudd_Ref( bFunc1 );
+ bFunc0 = Cudd_NotCond( bFunc0, Abc_ObjFaninC0(pNode) );
+ bFunc1 = Cudd_NotCond( bFunc1, Abc_ObjFaninC1(pNode) );
+ // get the final result
+ bFunc = Cudd_bddAnd( dd, bFunc0, bFunc1 ); Cudd_Ref( bFunc );
+ Cudd_RecursiveDeref( dd, bFunc0 );
+ Cudd_RecursiveDeref( dd, bFunc1 );
+ // add the number of used nodes
+ (*pCounter)++;
+ }
+ // set the result
+ assert( Abc_ObjGlobalBdd(pNode) == NULL );
+ Abc_ObjSetGlobalBdd( pNode, bFunc );
+ // increment the progress bar
+ if ( pProgress )
+ Extra_ProgressBarUpdate( pProgress, *pCounter, NULL );
+ }
+ // prepare the return value
+ bFunc = Abc_ObjGlobalBdd(pNode);
+ // dereference BDD at the node
+ if ( --pNode->vFanouts.nSize == 0 && fDropInternal )
+ {
+ Cudd_Deref( bFunc );
+ Abc_ObjSetGlobalBdd( pNode, NULL );
+ }
return bFunc;
}
/**Function*************************************************************
- Synopsis [Dereferences global BDDs of the network.]
+ Synopsis [Frees the global BDDs of the network.]
Description []
@@ -382,16 +456,123 @@ DdNode * Abc_NodeGlobalBdds_rec( DdManager * dd, Abc_Obj_t * pNode )
SeeAlso []
***********************************************************************/
-void Abc_NtkFreeGlobalBdds( Abc_Ntk_t * pNtk )
+DdManager * Abc_NtkFreeGlobalBdds( Abc_Ntk_t * pNtk, int fFreeMan )
+{
+ return Abc_NtkAttrFree( pNtk, VEC_ATTR_GLOBAL_BDD, fFreeMan );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Returns the shared size of global BDDs of the COs.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Abc_NtkSizeOfGlobalBdds( Abc_Ntk_t * pNtk )
+{
+ Vec_Ptr_t * vFuncsGlob;
+ Abc_Obj_t * pObj;
+ int RetValue, i;
+ // complement the global functions
+ vFuncsGlob = Vec_PtrAlloc( Abc_NtkCoNum(pNtk) );
+ Abc_NtkForEachCo( pNtk, pObj, i )
+ Vec_PtrPush( vFuncsGlob, Abc_ObjGlobalBdd(pObj) );
+ RetValue = Cudd_SharingSize( (DdNode **)Vec_PtrArray(vFuncsGlob), Vec_PtrSize(vFuncsGlob) );
+ Vec_PtrFree( vFuncsGlob );
+ return RetValue;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Computes the BDD of the logic cone of the node.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+double Abc_NtkSpacePercentage( Abc_Obj_t * pNode )
{
+ /*
+ Vec_Ptr_t * vNodes;
+ Abc_Obj_t * pObj, * pNodeR;
+ DdManager * dd;
DdNode * bFunc;
+ double Result;
int i;
- assert( pNtk->pManGlob );
- assert( pNtk->vFuncsGlob );
- Vec_PtrForEachEntry( pNtk->vFuncsGlob, bFunc, i )
- Cudd_RecursiveDeref( pNtk->pManGlob, bFunc );
- Vec_PtrFree( pNtk->vFuncsGlob );
- pNtk->vFuncsGlob = NULL;
+ pNodeR = Abc_ObjRegular(pNode);
+ assert( Abc_NtkIsStrash(pNodeR->pNtk) );
+ Abc_NtkCleanCopy( pNodeR->pNtk );
+ // get the CIs in the support of the node
+ vNodes = Abc_NtkNodeSupport( pNodeR->pNtk, &pNodeR, 1 );
+ // start the manager
+ dd = Cudd_Init( Vec_PtrSize(vNodes), 0, CUDD_UNIQUE_SLOTS, CUDD_CACHE_SLOTS, 0 );
+ Cudd_AutodynEnable( dd, CUDD_REORDER_SYMM_SIFT );
+ // assign elementary BDDs for the CIs
+ Vec_PtrForEachEntry( vNodes, pObj, i )
+ pObj->pCopy = (Abc_Obj_t *)dd->vars[i];
+ // build the BDD of the cone
+ bFunc = Abc_NodeGlobalBdds_rec( dd, pNodeR, 10000000, 1, NULL, NULL, 1 ); Cudd_Ref( bFunc );
+ bFunc = Cudd_NotCond( bFunc, pNode != pNodeR );
+ // count minterms
+ Result = Cudd_CountMinterm( dd, bFunc, dd->size );
+ // get the percentagle
+ Result *= 100.0;
+ for ( i = 0; i < dd->size; i++ )
+ Result /= 2;
+ // clean up
+ Cudd_Quit( dd );
+ Vec_PtrFree( vNodes );
+ return Result;
+ */
+ return 0.0;
+}
+
+
+
+
+/**Function*************************************************************
+
+ Synopsis [Experiment with BDD-based representation of implications.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Abc_NtkBddImplicationTest()
+{
+ DdManager * dd;
+ DdNode * bImp, * bSum, * bTemp;
+ int nVars = 200;
+ int nImps = 200;
+ int i, clk;
+clk = clock();
+ dd = Cudd_Init( nVars, 0, CUDD_UNIQUE_SLOTS, CUDD_CACHE_SLOTS, 0 );
+ Cudd_AutodynEnable( dd, CUDD_REORDER_SIFT );
+ bSum = b0; Cudd_Ref( bSum );
+ for ( i = 0; i < nImps; i++ )
+ {
+ printf( "." );
+ bImp = Cudd_bddAnd( dd, dd->vars[rand()%nVars], dd->vars[rand()%nVars] ); Cudd_Ref( bImp );
+ bSum = Cudd_bddOr( dd, bTemp = bSum, bImp ); Cudd_Ref( bSum );
+ Cudd_RecursiveDeref( dd, bTemp );
+ Cudd_RecursiveDeref( dd, bImp );
+ }
+ printf( "The BDD before = %d.\n", Cudd_DagSize(bSum) );
+ Cudd_ReduceHeap( dd, CUDD_REORDER_SIFT, 1 );
+ printf( "The BDD after = %d.\n", Cudd_DagSize(bSum) );
+PRT( "Time", clock() - clk );
+ Cudd_RecursiveDeref( dd, bSum );
+ Cudd_Quit( dd );
}
////////////////////////////////////////////////////////////////////////
diff --git a/src/base/abci/abcOdc.c b/src/base/abci/abcOdc.c
new file mode 100644
index 00000000..d6e59328
--- /dev/null
+++ b/src/base/abci/abcOdc.c
@@ -0,0 +1,1134 @@
+/**CFile****************************************************************
+
+ FileName [abcOdc.c]
+
+ SystemName [ABC: Logic synthesis and verification system.]
+
+ PackageName [Network and node package.]
+
+ Synopsis [Scalable computation of observability don't-cares.]
+
+ Author [Alan Mishchenko]
+
+ Affiliation [UC Berkeley]
+
+ Date [Ver. 1.0. Started - June 20, 2005.]
+
+ Revision [$Id: abcOdc.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "abc.h"
+
+////////////////////////////////////////////////////////////////////////
+/// DECLARATIONS ///
+////////////////////////////////////////////////////////////////////////
+
+#define ABC_DC_MAX_NODES (1<<15)
+
+typedef unsigned short Odc_Lit_t;
+
+typedef struct Odc_Obj_t_ Odc_Obj_t; // 16 bytes
+struct Odc_Obj_t_
+{
+ Odc_Lit_t iFan0; // first fanin
+ Odc_Lit_t iFan1; // second fanin
+ Odc_Lit_t iNext; // next node in the hash table
+ unsigned short TravId; // the traversal ID
+ unsigned uData; // the computed data
+ unsigned uMask; // the variable mask
+};
+
+typedef struct Odc_Man_t_ Odc_Man_t;
+struct Odc_Man_t_
+{
+ // dont'-care parameters
+ int nVarsMax; // the max number of cut variables
+ int nLevels; // the number of ODC levels
+ int fVerbose; // the verbosiness flag
+ int fVeryVerbose;// the verbosiness flag to print per-node stats
+ int nPercCutoff; // cutoff percentage
+
+ // windowing
+ Abc_Obj_t * pNode; // the node for windowing
+ Vec_Ptr_t * vLeaves; // the number of the cut
+ Vec_Ptr_t * vRoots; // the roots of the cut
+ Vec_Ptr_t * vBranches; // additional inputs
+
+ // internal AIG package
+ // objects
+ int nPis; // number of PIs (nVarsMax + 32)
+ int nObjs; // number of objects (Const1, PIs, ANDs)
+ int nObjsAlloc; // number of objects allocated
+ Odc_Obj_t * pObjs; // objects
+ Odc_Lit_t iRoot; // the root object
+ unsigned short nTravIds; // the number of travIDs
+ // structural hashing
+ Odc_Lit_t * pTable; // hash table
+ int nTableSize; // hash table size
+ Vec_Int_t * vUsedSpots; // the used spots
+
+ // truth tables
+ int nBits; // the number of bits
+ int nWords; // the number of words
+ Vec_Ptr_t * vTruths; // truth tables for each node
+ Vec_Ptr_t * vTruthsElem; // elementary truth tables for the PIs
+ unsigned * puTruth; // the place where the resulting truth table does
+
+ // statistics
+ int nWins; // the number of windows processed
+ int nWinsEmpty; // the number of empty windows
+ int nSimsEmpty; // the number of empty simulation infos
+ int nQuantsOver; // the number of quantification overflows
+ int nWinsFinish; // the number of windows that finished
+ int nTotalDcs; // total percentage of DCs
+
+ // runtime
+ int timeClean; // windowing
+ int timeWin; // windowing
+ int timeMiter; // computing the miter
+ int timeSim; // simulation
+ int timeQuant; // quantification
+ int timeTruth; // truth table
+ int timeTotal; // useful runtime
+ int timeAbort; // aborted runtime
+};
+
+
+// quantity of different objects
+static inline int Odc_PiNum( Odc_Man_t * p ) { return p->nPis; }
+static inline int Odc_NodeNum( Odc_Man_t * p ) { return p->nObjs - p->nPis - 1; }
+static inline int Odc_ObjNum( Odc_Man_t * p ) { return p->nObjs; }
+
+// complemented attributes of objects
+static inline int Odc_IsComplement( Odc_Lit_t Lit ) { return Lit & (Odc_Lit_t)1; }
+static inline Odc_Lit_t Odc_Regular( Odc_Lit_t Lit ) { return Lit & ~(Odc_Lit_t)1; }
+static inline Odc_Lit_t Odc_Not( Odc_Lit_t Lit ) { return Lit ^ (Odc_Lit_t)1; }
+static inline Odc_Lit_t Odc_NotCond( Odc_Lit_t Lit, int c ) { return Lit ^ (Odc_Lit_t)(c!=0); }
+
+// specialized Literals
+static inline Odc_Lit_t Odc_Const0() { return 1; }
+static inline Odc_Lit_t Odc_Const1() { return 0; }
+static inline Odc_Lit_t Odc_Var( Odc_Man_t * p, int i ) { assert( i >= 0 && i < p->nPis ); return (i+1) << 1; }
+static inline int Odc_IsConst( Odc_Lit_t Lit ) { return Lit < (Odc_Lit_t)2; }
+static inline int Odc_IsTerm( Odc_Man_t * p, Odc_Lit_t Lit ) { return (int)(Lit>>1) <= p->nPis; }
+
+// accessing internal storage
+static inline Odc_Obj_t * Odc_ObjNew( Odc_Man_t * p ) { assert( p->nObjs < p->nObjsAlloc ); return p->pObjs + p->nObjs++; }
+static inline Odc_Lit_t Odc_Obj2Lit( Odc_Man_t * p, Odc_Obj_t * pObj ) { assert( pObj ); return (pObj - p->pObjs) << 1; }
+static inline Odc_Obj_t * Odc_Lit2Obj( Odc_Man_t * p, Odc_Lit_t Lit ) { assert( !(Lit & 1) && (int)(Lit>>1) < p->nObjs ); return p->pObjs + (Lit>>1); }
+
+// fanins and their complements
+static inline Odc_Lit_t Odc_ObjChild0( Odc_Obj_t * pObj ) { return pObj->iFan0; }
+static inline Odc_Lit_t Odc_ObjChild1( Odc_Obj_t * pObj ) { return pObj->iFan1; }
+static inline Odc_Lit_t Odc_ObjFanin0( Odc_Obj_t * pObj ) { return Odc_Regular(pObj->iFan0); }
+static inline Odc_Lit_t Odc_ObjFanin1( Odc_Obj_t * pObj ) { return Odc_Regular(pObj->iFan1); }
+static inline int Odc_ObjFaninC0( Odc_Obj_t * pObj ) { return Odc_IsComplement(pObj->iFan0); }
+static inline int Odc_ObjFaninC1( Odc_Obj_t * pObj ) { return Odc_IsComplement(pObj->iFan1); }
+
+// traversal IDs
+static inline void Odc_ManIncrementTravId( Odc_Man_t * p ) { p->nTravIds++; }
+static inline void Odc_ObjSetTravIdCurrent( Odc_Man_t * p, Odc_Obj_t * pObj ) { pObj->TravId = p->nTravIds; }
+static inline int Odc_ObjIsTravIdCurrent( Odc_Man_t * p, Odc_Obj_t * pObj ) { return (int )((int)pObj->TravId == p->nTravIds); }
+
+// truth tables
+static inline unsigned * Odc_ObjTruth( Odc_Man_t * p, Odc_Lit_t Lit ) { assert( !(Lit & 1) ); return Vec_PtrEntry(p->vTruths, Lit >> 1); }
+
+// iterators
+#define Odc_ForEachPi( p, Lit, i ) \
+ for ( i = 0; (i < Odc_PiNum(p)) && (((Lit) = Odc_Var(p, i)), 1); i++ )
+#define Odc_ForEachAnd( p, pObj, i ) \
+ for ( i = 1 + Odc_CiNum(p); (i < Odc_ObjNum(p)) && ((pObj) = (p)->pObjs + i); i++ )
+
+
+// exported functions
+extern Odc_Man_t * Abc_NtkDontCareAlloc( int nVarsMax, int nLevels, int fVerbose, int fVeryVerbose );
+extern void Abc_NtkDontCareClear( Odc_Man_t * p );
+extern void Abc_NtkDontCareFree( Odc_Man_t * p );
+extern int Abc_NtkDontCareCompute( Odc_Man_t * p, Abc_Obj_t * pNode, Vec_Ptr_t * vLeaves, unsigned * puTruth );
+
+////////////////////////////////////////////////////////////////////////
+/// FUNCTION DEFINITIONS ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+ Synopsis [Allocates the don't-care manager.]
+
+ Description [The parameters are the max number of cut variables,
+ the number of fanout levels used for the ODC computation, and verbosiness.]
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Odc_Man_t * Abc_NtkDontCareAlloc( int nVarsMax, int nLevels, int fVerbose, int fVeryVerbose )
+{
+ Odc_Man_t * p;
+ unsigned * pData;
+ int i, k;
+ p = ALLOC( Odc_Man_t, 1 );
+ memset( p, 0, sizeof(Odc_Man_t) );
+ assert( nVarsMax > 4 && nVarsMax < 16 );
+ assert( nLevels > 0 && nLevels < 10 );
+
+ srand( 0xABC );
+
+ // dont'-care parameters
+ p->nVarsMax = nVarsMax;
+ p->nLevels = nLevels;
+ p->fVerbose = fVerbose;
+ p->fVeryVerbose = fVeryVerbose;
+ p->nPercCutoff = 10;
+
+ // windowing
+ p->vRoots = Vec_PtrAlloc( 128 );
+ p->vBranches = Vec_PtrAlloc( 128 );
+
+ // internal AIG package
+ // allocate room for objects
+ p->nObjsAlloc = ABC_DC_MAX_NODES;
+ p->pObjs = ALLOC( Odc_Obj_t, p->nObjsAlloc * sizeof(Odc_Obj_t) );
+ p->nPis = nVarsMax + 32;
+ p->nObjs = 1 + p->nPis;
+ memset( p->pObjs, 0, p->nObjs * sizeof(Odc_Obj_t) );
+ // set the PI masks
+ for ( i = 0; i < 32; i++ )
+ p->pObjs[1 + p->nVarsMax + i].uMask = (1 << i);
+ // allocate hash table
+ p->nTableSize = p->nObjsAlloc/3 + 1;
+ p->pTable = ALLOC( Odc_Lit_t, p->nTableSize * sizeof(Odc_Lit_t) );
+ memset( p->pTable, 0, p->nTableSize * sizeof(Odc_Lit_t) );
+ p->vUsedSpots = Vec_IntAlloc( 1000 );
+
+ // truth tables
+ p->nWords = Abc_TruthWordNum( p->nVarsMax );
+ p->nBits = p->nWords * 8 * sizeof(unsigned);
+ p->vTruths = Vec_PtrAllocSimInfo( p->nObjsAlloc, p->nWords );
+ p->vTruthsElem = Vec_PtrAllocSimInfo( p->nVarsMax, p->nWords );
+
+ // set elementary truth tables
+ Abc_InfoFill( Vec_PtrEntry(p->vTruths, 0), p->nWords );
+ for ( k = 0; k < p->nVarsMax; k++ )
+ {
+// pData = Odc_ObjTruth( p, Odc_Var(p, k) );
+ pData = Vec_PtrEntry( p->vTruthsElem, k );
+ Abc_InfoClear( pData, p->nWords );
+ for ( i = 0; i < p->nBits; i++ )
+ if ( i & (1 << k) )
+ pData[i>>5] |= (1 << (i&31));
+ }
+
+ // set random truth table for the additional inputs
+ for ( k = p->nVarsMax; k < p->nPis; k++ )
+ {
+ pData = Odc_ObjTruth( p, Odc_Var(p, k) );
+ Abc_InfoRandom( pData, p->nWords );
+ }
+
+ // set the miter to the unused value
+ p->iRoot = 0xffff;
+ return p;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Clears the manager.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Abc_NtkDontCareClear( Odc_Man_t * p )
+{
+ int clk = clock();
+ // clean the structural hashing table
+ if ( Vec_IntSize(p->vUsedSpots) > p->nTableSize/3 ) // more than one third
+ memset( p->pTable, 0, sizeof(Odc_Lit_t) * p->nTableSize );
+ else
+ {
+ int iSpot, i;
+ Vec_IntForEachEntry( p->vUsedSpots, iSpot, i )
+ p->pTable[iSpot] = 0;
+ }
+ Vec_IntClear( p->vUsedSpots );
+ // reset the number of nodes
+ p->nObjs = 1 + p->nPis;
+ // reset the root node
+ p->iRoot = 0xffff;
+
+p->timeClean += clock() - clk;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Frees the don't-care manager.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Abc_NtkDontCareFree( Odc_Man_t * p )
+{
+ if ( p->fVerbose )
+ {
+ printf( "Wins = %5d. Empty = %5d. SimsEmpty = %5d. QuantOver = %5d. WinsFinish = %5d.\n",
+ p->nWins, p->nWinsEmpty, p->nSimsEmpty, p->nQuantsOver, p->nWinsFinish );
+ printf( "Ave DCs per window = %6.2f %%. Ave DCs per finished window = %6.2f %%.\n",
+ 1.0*p->nTotalDcs/p->nWins, 1.0*p->nTotalDcs/p->nWinsFinish );
+ printf( "Runtime stats of the ODC manager:\n" );
+ PRT( "Cleaning ", p->timeClean );
+ PRT( "Windowing ", p->timeWin );
+ PRT( "Miter ", p->timeMiter );
+ PRT( "Simulation ", p->timeSim );
+ PRT( "Quantifying ", p->timeQuant );
+ PRT( "Truth table ", p->timeTruth );
+ PRT( "TOTAL ", p->timeTotal );
+ PRT( "Aborted ", p->timeAbort );
+ }
+ Vec_PtrFree( p->vRoots );
+ Vec_PtrFree( p->vBranches );
+ Vec_PtrFree( p->vTruths );
+ Vec_PtrFree( p->vTruthsElem );
+ Vec_IntFree( p->vUsedSpots );
+ free( p->pObjs );
+ free( p->pTable );
+ free( p );
+}
+
+
+
+/**Function*************************************************************
+
+ Synopsis [Marks the TFO of the collected nodes up to the given level.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Abc_NtkDontCareWinSweepLeafTfo_rec( Abc_Obj_t * pObj, int nLevelLimit, Abc_Obj_t * pNode )
+{
+ Abc_Obj_t * pFanout;
+ int i;
+ if ( Abc_ObjIsCo(pObj) || (int)pObj->Level > nLevelLimit || pObj == pNode )
+ return;
+ if ( Abc_NodeIsTravIdCurrent(pObj) )
+ return;
+ Abc_NodeSetTravIdCurrent( pObj );
+ ////////////////////////////////////////
+ // try to reduce the runtime
+ if ( Abc_ObjFanoutNum(pObj) > 100 )
+ return;
+ ////////////////////////////////////////
+ Abc_ObjForEachFanout( pObj, pFanout, i )
+ Abc_NtkDontCareWinSweepLeafTfo_rec( pFanout, nLevelLimit, pNode );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Marks the TFO of the collected nodes up to the given level.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Abc_NtkDontCareWinSweepLeafTfo( Odc_Man_t * p )
+{
+ Abc_Obj_t * pObj;
+ int i;
+ Abc_NtkIncrementTravId( p->pNode->pNtk );
+ Vec_PtrForEachEntry( p->vLeaves, pObj, i )
+ Abc_NtkDontCareWinSweepLeafTfo_rec( pObj, p->pNode->Level + p->nLevels, p->pNode );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Recursively collects the roots.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Abc_NtkDontCareWinCollectRoots_rec( Abc_Obj_t * pObj, Vec_Ptr_t * vRoots )
+{
+ Abc_Obj_t * pFanout;
+ int i;
+ assert( Abc_ObjIsNode(pObj) );
+ assert( Abc_NodeIsTravIdCurrent(pObj) );
+ // check if the node has all fanouts marked
+ Abc_ObjForEachFanout( pObj, pFanout, i )
+ if ( !Abc_NodeIsTravIdCurrent(pFanout) )
+ break;
+ // if some of the fanouts are unmarked, add the node to the root
+ if ( i < Abc_ObjFanoutNum(pObj) )
+ {
+ Vec_PtrPushUnique( vRoots, pObj );
+ return;
+ }
+ // otherwise, call recursively
+ Abc_ObjForEachFanout( pObj, pFanout, i )
+ Abc_NtkDontCareWinCollectRoots_rec( pFanout, vRoots );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Collects the roots of the window.]
+
+ Description [Roots of the window are the nodes that have at least
+ one fanout that it not in the TFO of the leaves.]
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Abc_NtkDontCareWinCollectRoots( Odc_Man_t * p )
+{
+ assert( !Abc_NodeIsTravIdCurrent(p->pNode) );
+ // mark the node with the old traversal ID
+ Abc_NodeSetTravIdCurrent( p->pNode );
+ // collect the roots
+ Vec_PtrClear( p->vRoots );
+ Abc_NtkDontCareWinCollectRoots_rec( p->pNode, p->vRoots );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Recursively adds missing nodes and leaves.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Abc_NtkDontCareWinAddMissing_rec( Odc_Man_t * p, Abc_Obj_t * pObj )
+{
+ Abc_Obj_t * pFanin;
+ int i;
+ // skip the already collected leaves and branches
+ if ( Abc_NodeIsTravIdCurrent(pObj) )
+ return 1;
+ // if this is not an internal node - make it a new branch
+ if ( !Abc_NodeIsTravIdPrevious(pObj) || Abc_ObjIsCi(pObj) ) //|| (int)pObj->Level <= p->nLevLeaves )
+ {
+ Abc_NodeSetTravIdCurrent( pObj );
+ Vec_PtrPush( p->vBranches, pObj );
+ return Vec_PtrSize(p->vBranches) <= 32;
+ }
+ // visit the fanins of the node
+ Abc_ObjForEachFanin( pObj, pFanin, i )
+ if ( !Abc_NtkDontCareWinAddMissing_rec( p, pFanin ) )
+ return 0;
+ return 1;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Adds to the window nodes and leaves in the TFI of the roots.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Abc_NtkDontCareWinAddMissing( Odc_Man_t * p )
+{
+ Abc_Obj_t * pObj;
+ int i;
+ // set the leaves
+ Abc_NtkIncrementTravId( p->pNode->pNtk );
+ Vec_PtrForEachEntry( p->vLeaves, pObj, i )
+ Abc_NodeSetTravIdCurrent( pObj );
+ // explore from the roots
+ Vec_PtrClear( p->vBranches );
+ Vec_PtrForEachEntry( p->vRoots, pObj, i )
+ if ( !Abc_NtkDontCareWinAddMissing_rec( p, pObj ) )
+ return 0;
+ return 1;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Computes window for the node.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Abc_NtkDontCareWindow( Odc_Man_t * p )
+{
+ // mark the TFO of the collected nodes up to the given level (p->pNode->Level + p->nWinTfoMax)
+ Abc_NtkDontCareWinSweepLeafTfo( p );
+ // find the roots of the window
+ Abc_NtkDontCareWinCollectRoots( p );
+ if ( Vec_PtrSize(p->vRoots) == 1 && Vec_PtrEntry(p->vRoots, 0) == p->pNode )
+ {
+// printf( "Empty window\n" );
+ return 0;
+ }
+ // add the nodes in the TFI of the roots that are not yet in the window
+ if ( !Abc_NtkDontCareWinAddMissing( p ) )
+ {
+// printf( "Too many branches (%d)\n", Vec_PtrSize(p->vBranches) );
+ return 0;
+ }
+ return 1;
+}
+
+
+
+
+
+/**Function*************************************************************
+
+ Synopsis [Performing hashing of two AIG Literals.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+static inline unsigned Odc_HashKey( Odc_Lit_t iFan0, Odc_Lit_t iFan1, int TableSize )
+{
+ unsigned Key = 0;
+ Key ^= Odc_Regular(iFan0) * 7937;
+ Key ^= Odc_Regular(iFan1) * 2971;
+ Key ^= Odc_IsComplement(iFan0) * 911;
+ Key ^= Odc_IsComplement(iFan1) * 353;
+ return Key % TableSize;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Checks if the given name node already exists in the table.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+static inline Odc_Lit_t * Odc_HashLookup( Odc_Man_t * p, Odc_Lit_t iFan0, Odc_Lit_t iFan1 )
+{
+ Odc_Obj_t * pObj;
+ Odc_Lit_t * pEntry;
+ unsigned uHashKey;
+ assert( iFan0 < iFan1 );
+ // get the hash key for this node
+ uHashKey = Odc_HashKey( iFan0, iFan1, p->nTableSize );
+ // remember the spot in the hash table that will be used
+ if ( p->pTable[uHashKey] == 0 )
+ Vec_IntPush( p->vUsedSpots, uHashKey );
+ // find the entry
+ for ( pEntry = p->pTable + uHashKey; *pEntry; pEntry = &pObj->iNext )
+ {
+ pObj = Odc_Lit2Obj( p, *pEntry );
+ if ( pObj->iFan0 == iFan0 && pObj->iFan1 == iFan1 )
+ return pEntry;
+ }
+ return pEntry;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Finds node by structural hashing or creates a new node.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+static inline Odc_Lit_t Odc_And( Odc_Man_t * p, Odc_Lit_t iFan0, Odc_Lit_t iFan1 )
+{
+ Odc_Obj_t * pObj;
+ Odc_Lit_t * pEntry;
+ unsigned uMask0, uMask1;
+ int Temp;
+ // consider trivial cases
+ if ( iFan0 == iFan1 )
+ return iFan0;
+ if ( iFan0 == Odc_Not(iFan1) )
+ return Odc_Const0();
+ if ( Odc_Regular(iFan0) == Odc_Const1() )
+ return iFan0 == Odc_Const1() ? iFan1 : Odc_Const0();
+ if ( Odc_Regular(iFan1) == Odc_Const1() )
+ return iFan1 == Odc_Const1() ? iFan0 : Odc_Const0();
+ // canonicize the fanin order
+ if ( iFan0 > iFan1 )
+ Temp = iFan0, iFan0 = iFan1, iFan1 = Temp;
+ // check if a node with these fanins exists
+ pEntry = Odc_HashLookup( p, iFan0, iFan1 );
+ if ( *pEntry )
+ return *pEntry;
+ // create a new node
+ pObj = Odc_ObjNew( p );
+ pObj->iFan0 = iFan0;
+ pObj->iFan1 = iFan1;
+ pObj->iNext = 0;
+ pObj->TravId = 0;
+ // set the mask
+ uMask0 = Odc_Lit2Obj(p, Odc_Regular(iFan0))->uMask;
+ uMask1 = Odc_Lit2Obj(p, Odc_Regular(iFan1))->uMask;
+ pObj->uMask = uMask0 | uMask1;
+ // add to the table
+ *pEntry = Odc_Obj2Lit( p, pObj );
+ return *pEntry;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Boolean OR.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+static inline Odc_Lit_t Odc_Or( Odc_Man_t * p, Odc_Lit_t iFan0, Odc_Lit_t iFan1 )
+{
+ return Odc_Not( Odc_And(p, Odc_Not(iFan0), Odc_Not(iFan1)) );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Boolean XOR.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+static inline Odc_Lit_t Odc_Xor( Odc_Man_t * p, Odc_Lit_t iFan0, Odc_Lit_t iFan1 )
+{
+ return Odc_Or( p, Odc_And(p, iFan0, Odc_Not(iFan1)), Odc_And(p, Odc_Not(iFan0), iFan1) );
+}
+
+
+
+
+
+/**Function*************************************************************
+
+ Synopsis [Transfers the window into the AIG package.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void * Abc_NtkDontCareTransfer_rec( Odc_Man_t * p, Abc_Obj_t * pNode, Abc_Obj_t * pPivot )
+{
+ unsigned uData0, uData1;
+ Odc_Lit_t uLit0, uLit1, uRes0, uRes1;
+ assert( !Abc_ObjIsComplement(pNode) );
+ // skip visited objects
+ if ( Abc_NodeIsTravIdCurrent(pNode) )
+ return pNode->pCopy;
+ Abc_NodeSetTravIdCurrent(pNode);
+ assert( Abc_ObjIsNode(pNode) );
+ // consider the case when the node is the pivot
+ if ( pNode == pPivot )
+ return pNode->pCopy = (void *)((Odc_Const1() << 16) | Odc_Const0());
+ // compute the cofactors
+ uData0 = (unsigned)Abc_NtkDontCareTransfer_rec( p, Abc_ObjFanin0(pNode), pPivot );
+ uData1 = (unsigned)Abc_NtkDontCareTransfer_rec( p, Abc_ObjFanin1(pNode), pPivot );
+ // find the 0-cofactor
+ uLit0 = Odc_NotCond( (Odc_Lit_t)(uData0 & 0xffff), Abc_ObjFaninC0(pNode) );
+ uLit1 = Odc_NotCond( (Odc_Lit_t)(uData1 & 0xffff), Abc_ObjFaninC1(pNode) );
+ uRes0 = Odc_And( p, uLit0, uLit1 );
+ // find the 1-cofactor
+ uLit0 = Odc_NotCond( (Odc_Lit_t)(uData0 >> 16), Abc_ObjFaninC0(pNode) );
+ uLit1 = Odc_NotCond( (Odc_Lit_t)(uData1 >> 16), Abc_ObjFaninC1(pNode) );
+ uRes1 = Odc_And( p, uLit0, uLit1 );
+ // find the result
+ return pNode->pCopy = (void *)((uRes1 << 16) | uRes0);
+}
+
+/**Function*************************************************************
+
+ Synopsis [Transfers the window into the AIG package.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Abc_NtkDontCareTransfer( Odc_Man_t * p )
+{
+ Abc_Obj_t * pObj;
+ Odc_Lit_t uRes0, uRes1;
+ Odc_Lit_t uLit;
+ unsigned uData;
+ int i;
+ Abc_NtkIncrementTravId( p->pNode->pNtk );
+ // set elementary variables at the leaves
+ Vec_PtrForEachEntry( p->vLeaves, pObj, i )
+ {
+ uLit = Odc_Var( p, i );
+ pObj->pCopy = (void *)((uLit << 16) | uLit);
+ Abc_NodeSetTravIdCurrent(pObj);
+ }
+ // set elementary variables at the branched
+ Vec_PtrForEachEntry( p->vBranches, pObj, i )
+ {
+ uLit = Odc_Var( p, i+p->nVarsMax );
+ pObj->pCopy = (void *)((uLit << 16) | uLit);
+ Abc_NodeSetTravIdCurrent(pObj);
+ }
+ // compute the AIG for the window
+ p->iRoot = Odc_Const0();
+ Vec_PtrForEachEntry( p->vRoots, pObj, i )
+ {
+ uData = (unsigned)Abc_NtkDontCareTransfer_rec( p, pObj, p->pNode );
+ // get the cofactors
+ uRes0 = uData & 0xffff;
+ uRes1 = uData >> 16;
+ // compute the miter
+// assert( uRes0 != uRes1 ); // may be false if the node is redundant w.r.t. this root
+ uLit = Odc_Xor( p, uRes0, uRes1 );
+ p->iRoot = Odc_Or( p, p->iRoot, uLit );
+ }
+ return 1;
+}
+
+
+/**Function*************************************************************
+
+ Synopsis [Recursively computes the pair of cofactors.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+unsigned Abc_NtkDontCareCofactors_rec( Odc_Man_t * p, Odc_Lit_t Lit, unsigned uMask )
+{
+ Odc_Obj_t * pObj;
+ unsigned uData0, uData1;
+ Odc_Lit_t uLit0, uLit1, uRes0, uRes1;
+ assert( !Odc_IsComplement(Lit) );
+ // skip visited objects
+ pObj = Odc_Lit2Obj( p, Lit );
+ if ( Odc_ObjIsTravIdCurrent(p, pObj) )
+ return pObj->uData;
+ Odc_ObjSetTravIdCurrent(p, pObj);
+ // skip objects out of the cone
+ if ( (pObj->uMask & uMask) == 0 )
+ return pObj->uData = ((Lit << 16) | Lit);
+ // consider the case when the node is the var
+ if ( pObj->uMask == uMask && Odc_IsTerm(p, Lit) )
+ return pObj->uData = ((Odc_Const1() << 16) | Odc_Const0());
+ // compute the cofactors
+ uData0 = Abc_NtkDontCareCofactors_rec( p, Odc_ObjFanin0(pObj), uMask );
+ uData1 = Abc_NtkDontCareCofactors_rec( p, Odc_ObjFanin1(pObj), uMask );
+ // find the 0-cofactor
+ uLit0 = Odc_NotCond( (Odc_Lit_t)(uData0 & 0xffff), Odc_ObjFaninC0(pObj) );
+ uLit1 = Odc_NotCond( (Odc_Lit_t)(uData1 & 0xffff), Odc_ObjFaninC1(pObj) );
+ uRes0 = Odc_And( p, uLit0, uLit1 );
+ // find the 1-cofactor
+ uLit0 = Odc_NotCond( (Odc_Lit_t)(uData0 >> 16), Odc_ObjFaninC0(pObj) );
+ uLit1 = Odc_NotCond( (Odc_Lit_t)(uData1 >> 16), Odc_ObjFaninC1(pObj) );
+ uRes1 = Odc_And( p, uLit0, uLit1 );
+ // find the result
+ return pObj->uData = ((uRes1 << 16) | uRes0);
+}
+
+/**Function*************************************************************
+
+ Synopsis [Quantifies the branch variables.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Abc_NtkDontCareQuantify( Odc_Man_t * p )
+{
+ Odc_Lit_t uRes0, uRes1;
+ unsigned uData;
+ int i;
+ assert( p->iRoot < 0xffff );
+ assert( Vec_PtrSize(p->vBranches) <= 32 ); // the mask size
+ for ( i = 0; i < Vec_PtrSize(p->vBranches); i++ )
+ {
+ // compute the cofactors w.r.t. this variable
+ Odc_ManIncrementTravId( p );
+ uData = Abc_NtkDontCareCofactors_rec( p, Odc_Regular(p->iRoot), (1 << i) );
+ uRes0 = Odc_NotCond( (Odc_Lit_t)(uData & 0xffff), Odc_IsComplement(p->iRoot) );
+ uRes1 = Odc_NotCond( (Odc_Lit_t)(uData >> 16), Odc_IsComplement(p->iRoot) );
+ // quantify this variable existentially
+ p->iRoot = Odc_Or( p, uRes0, uRes1 );
+ // check the limit
+ if ( Odc_ObjNum(p) > ABC_DC_MAX_NODES/2 )
+ return 0;
+ }
+ assert( p->nObjs <= p->nObjsAlloc );
+ return 1;
+}
+
+
+
+/**Function*************************************************************
+
+ Synopsis [Set elementary truth tables for PIs.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Abc_NtkDontCareSimulateSetElem2( Odc_Man_t * p )
+{
+ unsigned * pData;
+ int i, k;
+ for ( k = 0; k < p->nVarsMax; k++ )
+ {
+ pData = Odc_ObjTruth( p, Odc_Var(p, k) );
+ Abc_InfoClear( pData, p->nWords );
+ for ( i = 0; i < p->nBits; i++ )
+ if ( i & (1 << k) )
+ pData[i>>5] |= (1 << (i&31));
+ }
+}
+
+/**Function*************************************************************
+
+ Synopsis [Set elementary truth tables for PIs.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Abc_NtkDontCareSimulateSetElem( Odc_Man_t * p )
+{
+ unsigned * pData, * pData2;
+ int k;
+ for ( k = 0; k < p->nVarsMax; k++ )
+ {
+ pData = Odc_ObjTruth( p, Odc_Var(p, k) );
+ pData2 = Vec_PtrEntry( p->vTruthsElem, k );
+ Abc_InfoCopy( pData, pData2, p->nWords );
+ }
+}
+
+/**Function*************************************************************
+
+ Synopsis [Set random simulation words for PIs.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Abc_NtkDontCareSimulateSetRand( Odc_Man_t * p )
+{
+ unsigned * pData;
+ int w, k, Number;
+ for ( w = 0; w < p->nWords; w++ )
+ {
+ Number = rand();
+ for ( k = 0; k < p->nVarsMax; k++ )
+ {
+ pData = Odc_ObjTruth( p, Odc_Var(p, k) );
+ pData[w] = (Number & (1<<k)) ? ~0 : 0;
+ }
+ }
+}
+
+/**Function*************************************************************
+
+ Synopsis [Set random simulation words for PIs.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Abc_NtkDontCareCountMintsWord( Odc_Man_t * p, unsigned * puTruth )
+{
+ int w, Counter = 0;
+ for ( w = 0; w < p->nWords; w++ )
+ if ( puTruth[w] )
+ Counter++;
+ return Counter;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Simulates one node.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Abc_NtkDontCareTruthOne( Odc_Man_t * p, Odc_Lit_t Lit )
+{
+ Odc_Obj_t * pObj;
+ unsigned * pInfo, * pInfo1, * pInfo2;
+ int k, fComp1, fComp2;
+ assert( !Odc_IsComplement( Lit ) );
+ assert( !Odc_IsTerm( p, Lit ) );
+ // get the truth tables
+ pObj = Odc_Lit2Obj( p, Lit );
+ pInfo = Odc_ObjTruth( p, Lit );
+ pInfo1 = Odc_ObjTruth( p, Odc_ObjFanin0(pObj) );
+ pInfo2 = Odc_ObjTruth( p, Odc_ObjFanin1(pObj) );
+ fComp1 = Odc_ObjFaninC0( pObj );
+ fComp2 = Odc_ObjFaninC1( pObj );
+ // simulate
+ if ( fComp1 && fComp2 )
+ for ( k = 0; k < p->nWords; k++ )
+ pInfo[k] = ~pInfo1[k] & ~pInfo2[k];
+ else if ( fComp1 && !fComp2 )
+ for ( k = 0; k < p->nWords; k++ )
+ pInfo[k] = ~pInfo1[k] & pInfo2[k];
+ else if ( !fComp1 && fComp2 )
+ for ( k = 0; k < p->nWords; k++ )
+ pInfo[k] = pInfo1[k] & ~pInfo2[k];
+ else // if ( fComp1 && fComp2 )
+ for ( k = 0; k < p->nWords; k++ )
+ pInfo[k] = pInfo1[k] & pInfo2[k];
+}
+
+/**Function*************************************************************
+
+ Synopsis [Computes the truth table.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Abc_NtkDontCareSimulate_rec( Odc_Man_t * p, Odc_Lit_t Lit )
+{
+ Odc_Obj_t * pObj;
+ assert( !Odc_IsComplement(Lit) );
+ // skip terminals
+ if ( Odc_IsTerm(p, Lit) )
+ return;
+ // skip visited objects
+ pObj = Odc_Lit2Obj( p, Lit );
+ if ( Odc_ObjIsTravIdCurrent(p, pObj) )
+ return;
+ Odc_ObjSetTravIdCurrent(p, pObj);
+ // call recursively
+ Abc_NtkDontCareSimulate_rec( p, Odc_ObjFanin0(pObj) );
+ Abc_NtkDontCareSimulate_rec( p, Odc_ObjFanin1(pObj) );
+ // construct the truth table
+ Abc_NtkDontCareTruthOne( p, Lit );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Computes the truth table of the care set.]
+
+ Description [Returns the number of ones in the simulation info.]
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Abc_NtkDontCareSimulate( Odc_Man_t * p, unsigned * puTruth )
+{
+ Odc_ManIncrementTravId( p );
+ Abc_NtkDontCareSimulate_rec( p, Odc_Regular(p->iRoot) );
+ Abc_InfoCopy( puTruth, Odc_ObjTruth(p, Odc_Regular(p->iRoot)), p->nWords );
+ if ( Odc_IsComplement(p->iRoot) )
+ Abc_InfoNot( puTruth, p->nWords );
+ return Extra_TruthCountOnes( puTruth, p->nVarsMax );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Computes the truth table of the care set.]
+
+ Description [Returns the number of ones in the simulation info.]
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Abc_NtkDontCareSimulateBefore( Odc_Man_t * p, unsigned * puTruth )
+{
+ int nIters = 2;
+ int nRounds, Counter, r;
+ // decide how many rounds to simulate
+ nRounds = p->nBits / p->nWords;
+ Counter = 0;
+ for ( r = 0; r < nIters; r++ )
+ {
+ Abc_NtkDontCareSimulateSetRand( p );
+ Abc_NtkDontCareSimulate( p, puTruth );
+ Counter += Abc_NtkDontCareCountMintsWord( p, puTruth );
+ }
+ // normalize
+ Counter = Counter * nRounds / nIters;
+ return Counter;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Computes ODCs for the node in terms of the cut variables.]
+
+ Description [Returns the number of don't care minterms in the truth table.
+ In particular, this procedure returns 0 if there is no don't-cares.]
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Abc_NtkDontCareCompute( Odc_Man_t * p, Abc_Obj_t * pNode, Vec_Ptr_t * vLeaves, unsigned * puTruth )
+{
+ int nMints, RetValue;
+ int clk, clkTotal = clock();
+
+ p->nWins++;
+
+ // set the parameters
+ assert( !Abc_ObjIsComplement(pNode) );
+ assert( Abc_ObjIsNode(pNode) );
+ assert( Vec_PtrSize(vLeaves) <= p->nVarsMax );
+ p->vLeaves = vLeaves;
+ p->pNode = pNode;
+
+ // compute the window
+clk = clock();
+ RetValue = Abc_NtkDontCareWindow( p );
+p->timeWin += clock() - clk;
+ if ( !RetValue )
+ {
+p->timeAbort += clock() - clkTotal;
+ Abc_InfoFill( puTruth, p->nWords );
+ p->nWinsEmpty++;
+ return 0;
+ }
+
+ if ( p->fVeryVerbose )
+ {
+ printf( " %5d : ", pNode->Id );
+ printf( "Leaf = %2d ", Vec_PtrSize(p->vLeaves) );
+ printf( "Root = %2d ", Vec_PtrSize(p->vRoots) );
+ printf( "Bran = %2d ", Vec_PtrSize(p->vBranches) );
+ printf( " | " );
+ }
+
+ // transfer the window into the AIG package
+clk = clock();
+ Abc_NtkDontCareTransfer( p );
+p->timeMiter += clock() - clk;
+
+ // simulate to estimate the amount of don't-cares
+clk = clock();
+ nMints = Abc_NtkDontCareSimulateBefore( p, puTruth );
+p->timeSim += clock() - clk;
+ if ( p->fVeryVerbose )
+ {
+ printf( "AIG = %5d ", Odc_NodeNum(p) );
+ printf( "%6.2f %% ", 100.0 * (p->nBits - nMints) / p->nBits );
+ }
+
+ // if there is less then the given percentage of don't-cares, skip
+ if ( 100.0 * (p->nBits - nMints) / p->nBits < 1.0 * p->nPercCutoff )
+ {
+p->timeAbort += clock() - clkTotal;
+ if ( p->fVeryVerbose )
+ printf( "Simulation cutoff.\n" );
+ Abc_InfoFill( puTruth, p->nWords );
+ p->nSimsEmpty++;
+ return 0;
+ }
+
+ // quantify external variables
+clk = clock();
+ RetValue = Abc_NtkDontCareQuantify( p );
+p->timeQuant += clock() - clk;
+ if ( !RetValue )
+ {
+p->timeAbort += clock() - clkTotal;
+ if ( p->fVeryVerbose )
+ printf( "=== Overflow! ===\n" );
+ Abc_InfoFill( puTruth, p->nWords );
+ p->nQuantsOver++;
+ return 0;
+ }
+
+ // get the truth table
+clk = clock();
+ Abc_NtkDontCareSimulateSetElem( p );
+ nMints = Abc_NtkDontCareSimulate( p, puTruth );
+p->timeTruth += clock() - clk;
+ if ( p->fVeryVerbose )
+ {
+ printf( "AIG = %5d ", Odc_NodeNum(p) );
+ printf( "%6.2f %% ", 100.0 * (p->nBits - nMints) / p->nBits );
+ printf( "\n" );
+ }
+p->timeTotal += clock() - clkTotal;
+ p->nWinsFinish++;
+ p->nTotalDcs += (int)(100.0 * (p->nBits - nMints) / p->nBits);
+ return nMints;
+}
+
+
+////////////////////////////////////////////////////////////////////////
+/// END OF FILE ///
+////////////////////////////////////////////////////////////////////////
+
+
diff --git a/src/base/abci/abcOrder.c b/src/base/abci/abcOrder.c
new file mode 100644
index 00000000..04417f77
--- /dev/null
+++ b/src/base/abci/abcOrder.c
@@ -0,0 +1,131 @@
+/**CFile****************************************************************
+
+ FileName [abcOrder.c]
+
+ SystemName [ABC: Logic synthesis and verification system.]
+
+ PackageName [Network and node package.]
+
+ Synopsis [Exploring static BDD variable orders.]
+
+ Author [Alan Mishchenko]
+
+ Affiliation [UC Berkeley]
+
+ Date [Ver. 1.0. Started - June 20, 2005.]
+
+ Revision [$Id: abcOrder.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "abc.h"
+
+////////////////////////////////////////////////////////////////////////
+/// DECLARATIONS ///
+////////////////////////////////////////////////////////////////////////
+
+static void Abc_NtkChangeCiOrder( Abc_Ntk_t * pNtk, Vec_Ptr_t * vSupp, int fReverse );
+
+////////////////////////////////////////////////////////////////////////
+/// FUNCTION DEFINITIONS ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+ Synopsis [Changes the order of primary inputs.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Abc_NtkFindCiOrder( Abc_Ntk_t * pNtk, int fReverse, int fVerbose )
+{
+ Vec_Ptr_t * vSupp;
+ vSupp = Abc_NtkSupport( pNtk );
+ Abc_NtkChangeCiOrder( pNtk, vSupp, fReverse );
+ Vec_PtrFree( vSupp );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Implements the given variable order.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Abc_NtkImplementCiOrder( Abc_Ntk_t * pNtk, char * pFileName, int fReverse, int fVerbose )
+{
+ char Buffer[1000];
+ FILE * pFile;
+ Vec_Ptr_t * vSupp;
+ Abc_Obj_t * pObj;
+ pFile = fopen( pFileName, "r" );
+ vSupp = Vec_PtrAlloc( Abc_NtkCiNum(pNtk) );
+ while ( fscanf( pFile, "%s", Buffer ) == 1 )
+ {
+ pObj = Abc_NtkFindCi( pNtk, Buffer );
+ if ( pObj == NULL || !Abc_ObjIsCi(pObj) )
+ {
+ printf( "Name \"%s\" is not a PI name. Cannot use this order.\n", Buffer );
+ Vec_PtrFree( vSupp );
+ fclose( pFile );
+ return;
+ }
+ Vec_PtrPush( vSupp, pObj );
+ }
+ fclose( pFile );
+ if ( Vec_PtrSize(vSupp) != Abc_NtkCiNum(pNtk) )
+ {
+ printf( "The number of names in the order (%d) is not the same as the number of PIs (%d).\n", Vec_PtrSize(vSupp), Abc_NtkCiNum(pNtk) );
+ Vec_PtrFree( vSupp );
+ return;
+ }
+ Abc_NtkChangeCiOrder( pNtk, vSupp, fReverse );
+ Vec_PtrFree( vSupp );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Changes the order of primary inputs.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Abc_NtkChangeCiOrder( Abc_Ntk_t * pNtk, Vec_Ptr_t * vSupp, int fReverse )
+{
+ Abc_Obj_t * pObj;
+ int i;
+ assert( Vec_PtrSize(vSupp) == Abc_NtkCiNum(pNtk) );
+ // order CIs using the array
+ if ( fReverse )
+ Vec_PtrForEachEntry( vSupp, pObj, i )
+ Vec_PtrWriteEntry( pNtk->vCis, Vec_PtrSize(vSupp)-1-i, pObj );
+ else
+ Vec_PtrForEachEntry( vSupp, pObj, i )
+ Vec_PtrWriteEntry( pNtk->vCis, i, pObj );
+ // order PIs accordingly
+ Vec_PtrClear( pNtk->vPis );
+ Abc_NtkForEachCi( pNtk, pObj, i )
+ if ( Abc_ObjIsPi(pObj) )
+ Vec_PtrPush( pNtk->vPis, pObj );
+// Abc_NtkForEachCi( pNtk, pObj, i )
+// printf( "%s ", Abc_ObjName(pObj) );
+// printf( "\n" );
+}
+
+////////////////////////////////////////////////////////////////////////
+/// END OF FILE ///
+////////////////////////////////////////////////////////////////////////
+
+
diff --git a/src/base/abci/abcPart.c b/src/base/abci/abcPart.c
index 506010c7..85c4e918 100644
--- a/src/base/abci/abcPart.c
+++ b/src/base/abci/abcPart.c
@@ -19,77 +19,87 @@
***********************************************************************/
#include "abc.h"
-#include "hop.h"
////////////////////////////////////////////////////////////////////////
/// DECLARATIONS ///
////////////////////////////////////////////////////////////////////////
+typedef struct Supp_Man_t_ Supp_Man_t;
+struct Supp_Man_t_
+{
+ int nChunkSize; // the size of one chunk of memory (~1 Mb)
+ int nStepSize; // the step size in saving memory (~64 bytes)
+ char * pFreeBuf; // the pointer to free memory
+ int nFreeSize; // the size of remaining free memory
+ Vec_Ptr_t * vMemory; // the memory allocated
+ Vec_Ptr_t * vFree; // the vector of free pieces of memory
+};
+
+typedef struct Supp_One_t_ Supp_One_t;
+struct Supp_One_t_
+{
+ int nRefs; // the number of references
+ int nOuts; // the number of outputs
+ int nOutsAlloc; // the array size
+ int pOuts[0]; // the array of outputs
+};
+
+static inline int Supp_SizeType( int nSize, int nStepSize ) { return nSize / nStepSize + ((nSize % nStepSize) > 0); }
+static inline char * Supp_OneNext( char * pPart ) { return *((char **)pPart); }
+static inline void Supp_OneSetNext( char * pPart, char * pNext ) { *((char **)pPart) = pNext; }
+
////////////////////////////////////////////////////////////////////////
/// FUNCTION DEFINITIONS ///
////////////////////////////////////////////////////////////////////////
/**Function*************************************************************
- Synopsis [Returns the number of common entries.]
+ Synopsis [Start the memory manager.]
- Description [Assumes that the vectors are sorted in the increasing order.]
+ Description []
SideEffects []
SeeAlso []
***********************************************************************/
-static inline int Vec_IntTwoCountCommon( Vec_Int_t * vArr1, Vec_Int_t * vArr2 )
+Supp_Man_t * Supp_ManStart( int nChunkSize, int nStepSize )
{
- int i, k, Counter = 0;
- for ( i = k = 0; i < Vec_IntSize(vArr1) && k < Vec_IntSize(vArr2); )
- {
- if ( Vec_IntEntry(vArr1,i) == Vec_IntEntry(vArr2,k) )
- Counter++, i++, k++;
- else if ( Vec_IntEntry(vArr1,i) < Vec_IntEntry(vArr2,k) )
- i++;
- else
- k++;
- }
- return Counter;
+ Supp_Man_t * p;
+ p = ALLOC( Supp_Man_t, 1 );
+ memset( p, 0, sizeof(Supp_Man_t) );
+ p->nChunkSize = nChunkSize;
+ p->nStepSize = nStepSize;
+ p->vMemory = Vec_PtrAlloc( 1000 );
+ p->vFree = Vec_PtrAlloc( 1000 );
+ return p;
}
/**Function*************************************************************
- Synopsis [Returns the result of merging the two vectors.]
+ Synopsis [Stops the memory manager.]
- Description [Assumes that the vectors are sorted in the increasing order.]
+ Description []
SideEffects []
SeeAlso []
***********************************************************************/
-static inline Vec_Int_t * Vec_IntTwoMerge( Vec_Int_t * vArr1, Vec_Int_t * vArr2 )
+void Supp_ManStop( Supp_Man_t * p )
{
- Vec_Int_t * vArr;
- int i, k;
- vArr = Vec_IntAlloc( Vec_IntSize(vArr1) );
- for ( i = k = 0; i < Vec_IntSize(vArr1) && k < Vec_IntSize(vArr2); )
- {
- if ( Vec_IntEntry(vArr1,i) == Vec_IntEntry(vArr2,k) )
- Vec_IntPush( vArr, Vec_IntEntry(vArr1,i) ), i++, k++;
- else if ( Vec_IntEntry(vArr1,i) < Vec_IntEntry(vArr2,k) )
- Vec_IntPush( vArr, Vec_IntEntry(vArr1,i) ), i++;
- else
- Vec_IntPush( vArr, Vec_IntEntry(vArr2,k) ), k++;
- }
- for ( ; i < Vec_IntSize(vArr1); i++ )
- Vec_IntPush( vArr, Vec_IntEntry(vArr1,i) );
- for ( ; k < Vec_IntSize(vArr2); k++ )
- Vec_IntPush( vArr, Vec_IntEntry(vArr2,k) );
- return vArr;
+ void * pMemory;
+ int i;
+ Vec_PtrForEachEntry( p->vMemory, pMemory, i )
+ free( pMemory );
+ Vec_PtrFree( p->vMemory );
+ Vec_PtrFree( p->vFree );
+ free( p );
}
/**Function*************************************************************
- Synopsis [Comparison procedure for two arrays.]
+ Synopsis [Fetches the memory entry of the given size.]
Description []
@@ -98,18 +108,35 @@ static inline Vec_Int_t * Vec_IntTwoMerge( Vec_Int_t * vArr1, Vec_Int_t * vArr2
SeeAlso []
***********************************************************************/
-static inline int Vec_VecSortCompare1( Vec_Ptr_t ** pp1, Vec_Ptr_t ** pp2 )
+char * Supp_ManFetch( Supp_Man_t * p, int nSize )
{
- if ( Vec_PtrSize(*pp1) < Vec_PtrSize(*pp2) )
- return -1;
- if ( Vec_PtrSize(*pp1) > Vec_PtrSize(*pp2) )
- return 1;
- return 0;
+ int Type, nSizeReal;
+ char * pMemory;
+ assert( nSize > 0 );
+ Type = Supp_SizeType( nSize, p->nStepSize );
+ Vec_PtrFillExtra( p->vFree, Type + 1, NULL );
+ if ( pMemory = Vec_PtrEntry( p->vFree, Type ) )
+ {
+ Vec_PtrWriteEntry( p->vFree, Type, Supp_OneNext(pMemory) );
+ return pMemory;
+ }
+ nSizeReal = p->nStepSize * Type;
+ if ( p->nFreeSize < nSizeReal )
+ {
+ p->pFreeBuf = ALLOC( char, p->nChunkSize );
+ p->nFreeSize = p->nChunkSize;
+ Vec_PtrPush( p->vMemory, p->pFreeBuf );
+ }
+ assert( p->nFreeSize >= nSizeReal );
+ pMemory = p->pFreeBuf;
+ p->pFreeBuf += nSizeReal;
+ p->nFreeSize -= nSizeReal;
+ return pMemory;
}
/**Function*************************************************************
- Synopsis [Comparison procedure for two integers.]
+ Synopsis [Recycles the memory entry of the given size.]
Description []
@@ -118,18 +145,18 @@ static inline int Vec_VecSortCompare1( Vec_Ptr_t ** pp1, Vec_Ptr_t ** pp2 )
SeeAlso []
***********************************************************************/
-static inline int Vec_VecSortCompare2( Vec_Ptr_t ** pp1, Vec_Ptr_t ** pp2 )
+void Supp_ManRecycle( Supp_Man_t * p, char * pMemory, int nSize )
{
- if ( Vec_PtrSize(*pp1) > Vec_PtrSize(*pp2) )
- return -1;
- if ( Vec_PtrSize(*pp1) < Vec_PtrSize(*pp2) )
- return 1;
- return 0;
+ int Type;
+ Type = Supp_SizeType( nSize, p->nStepSize );
+ Vec_PtrFillExtra( p->vFree, Type + 1, NULL );
+ Supp_OneSetNext( pMemory, Vec_PtrEntry(p->vFree, Type) );
+ Vec_PtrWriteEntry( p->vFree, Type, pMemory );
}
/**Function*************************************************************
- Synopsis [Sorting the entries by their integer value.]
+ Synopsis [Fetches the memory entry of the given size.]
Description []
@@ -138,19 +165,19 @@ static inline int Vec_VecSortCompare2( Vec_Ptr_t ** pp1, Vec_Ptr_t ** pp2 )
SeeAlso []
***********************************************************************/
-static inline void Vec_VecSort( Vec_Vec_t * p, int fReverse )
+static inline Supp_One_t * Supp_ManFetchEntry( Supp_Man_t * p, int nWords, int nRefs )
{
- if ( fReverse )
- qsort( (void *)p->pArray, p->nSize, sizeof(void *),
- (int (*)(const void *, const void *)) Vec_VecSortCompare2 );
- else
- qsort( (void *)p->pArray, p->nSize, sizeof(void *),
- (int (*)(const void *, const void *)) Vec_VecSortCompare1 );
+ Supp_One_t * pPart;
+ pPart = (Supp_One_t *)Supp_ManFetch( p, sizeof(Supp_One_t) + sizeof(int) * nWords );
+ pPart->nRefs = nRefs;
+ pPart->nOuts = 0;
+ pPart->nOutsAlloc = nWords;
+ return pPart;
}
/**Function*************************************************************
- Synopsis [Performs DFS for one node.]
+ Synopsis [Recycles the memory entry of the given size.]
Description []
@@ -159,31 +186,16 @@ static inline void Vec_VecSort( Vec_Vec_t * p, int fReverse )
SeeAlso []
***********************************************************************/
-void Abc_NtkNodeSupport_rec( Abc_Obj_t * pNode, Vec_Ptr_t * vNodes )
+static inline void Supp_ManRecycleEntry( Supp_Man_t * p, Supp_One_t * pEntry )
{
- Abc_Obj_t * pFanin;
- int i;
- assert( !Abc_ObjIsNet(pNode) );
- // if this node is already visited, skip
- if ( Abc_NodeIsTravIdCurrent( pNode ) )
- return;
- // mark the node as visited
- Abc_NodeSetTravIdCurrent( pNode );
- // collect the CI
- if ( Abc_ObjIsCi(pNode) || Abc_ObjFaninNum(pNode) == 0 )
- {
- Vec_PtrPush( vNodes, pNode );
- return;
- }
- assert( Abc_ObjIsNode( pNode ) );
- // visit the transitive fanin of the node
- Abc_ObjForEachFanin( pNode, pFanin, i )
- Abc_NtkNodeSupport_rec( Abc_ObjFanin0Ntk(pFanin), vNodes );
+ assert( pEntry->nOuts <= pEntry->nOutsAlloc );
+ assert( pEntry->nOuts >= pEntry->nOutsAlloc/2 );
+ Supp_ManRecycle( p, (char *)pEntry, sizeof(Supp_One_t) + sizeof(int) * pEntry->nOutsAlloc );
}
/**Function*************************************************************
- Synopsis [Returns the set of CI nodes in the support of the given nodes.]
+ Synopsis [Merges two entries.]
Description []
@@ -192,26 +204,37 @@ void Abc_NtkNodeSupport_rec( Abc_Obj_t * pNode, Vec_Ptr_t * vNodes )
SeeAlso []
***********************************************************************/
-Vec_Ptr_t * Abc_NtkNodeSupport( Abc_Ntk_t * pNtk, Abc_Obj_t ** ppNodes, int nNodes )
+Supp_One_t * Supp_ManMergeEntry( Supp_Man_t * pMan, Supp_One_t * p1, Supp_One_t * p2, int nRefs )
{
- Vec_Ptr_t * vNodes;
- int i;
- // set the traversal ID
- Abc_NtkIncrementTravId( pNtk );
- // start the array of nodes
- vNodes = Vec_PtrAlloc( 100 );
- // go through the PO nodes and call for each of them
- for ( i = 0; i < nNodes; i++ )
- if ( Abc_ObjIsCo(ppNodes[i]) )
- Abc_NtkNodeSupport_rec( Abc_ObjFanin0(ppNodes[i]), vNodes );
- else
- Abc_NtkNodeSupport_rec( ppNodes[i], vNodes );
- return vNodes;
+ Supp_One_t * p = Supp_ManFetchEntry( pMan, p1->nOuts + p2->nOuts, nRefs );
+ int * pBeg1 = p1->pOuts;
+ int * pBeg2 = p2->pOuts;
+ int * pBeg = p->pOuts;
+ int * pEnd1 = p1->pOuts + p1->nOuts;
+ int * pEnd2 = p2->pOuts + p2->nOuts;
+ while ( pBeg1 < pEnd1 && pBeg2 < pEnd2 )
+ {
+ if ( *pBeg1 == *pBeg2 )
+ *pBeg++ = *pBeg1++, pBeg2++;
+ else if ( *pBeg1 < *pBeg2 )
+ *pBeg++ = *pBeg1++;
+ else
+ *pBeg++ = *pBeg2++;
+ }
+ while ( pBeg1 < pEnd1 )
+ *pBeg++ = *pBeg1++;
+ while ( pBeg2 < pEnd2 )
+ *pBeg++ = *pBeg2++;
+ p->nOuts = pBeg - p->pOuts;
+ assert( p->nOuts <= p->nOutsAlloc );
+ assert( p->nOuts >= p1->nOuts );
+ assert( p->nOuts >= p2->nOuts );
+ return p;
}
/**Function*************************************************************
- Synopsis [Extra_UtilStrsav()]
+ Synopsis [Tranfers the entry.]
Description []
@@ -220,16 +243,19 @@ Vec_Ptr_t * Abc_NtkNodeSupport( Abc_Ntk_t * pNtk, Abc_Obj_t ** ppNodes, int nNod
SeeAlso []
***********************************************************************/
-char * Extra_UtilStrsav( char * s )
+Vec_Int_t * Supp_ManTransferEntry( Supp_One_t * p )
{
- if ( s == NULL )
- return s;
- return strcpy(ALLOC(char, strlen(s)+1), s);
+ Vec_Int_t * vSupp;
+ int i;
+ vSupp = Vec_IntAlloc( p->nOuts );
+ for ( i = 0; i < p->nOuts; i++ )
+ Vec_IntPush( vSupp, p->pOuts[i] );
+ return vSupp;
}
/**Function*************************************************************
- Synopsis [Creates the network composed of several logic cones.]
+ Synopsis [Computes supports of the POs in the multi-output AIG.]
Description []
@@ -238,198 +264,257 @@ char * Extra_UtilStrsav( char * s )
SeeAlso []
***********************************************************************/
-Abc_Ntk_t * Abc_NtkCreateConeArray( Abc_Ntk_t * pNtk, Vec_Ptr_t * vRoots, int fUseAllCis )
+Vec_Ptr_t * Abc_NtkDfsNatural( Abc_Ntk_t * pNtk )
{
- Abc_Ntk_t * pNtkNew;
Vec_Ptr_t * vNodes;
- Abc_Obj_t * pObj, * pFanin, * pNodeCoNew;
- char Buffer[1000];
+ Abc_Obj_t * pObj, * pNext;
int i, k;
-
- assert( Abc_NtkIsLogic(pNtk) || Abc_NtkIsStrash(pNtk) );
-
- // start the network
- pNtkNew = Abc_NtkAlloc( pNtk->ntkType, pNtk->ntkFunc );
- // set the name
- sprintf( Buffer, "%s_part", pNtk->pName );
- pNtkNew->pName = Extra_UtilStrsav(Buffer);
-
- // establish connection between the constant nodes
- if ( Abc_NtkIsStrash(pNtk) )
- Abc_AigConst1(pNtk->pManFunc)->pCopy = Abc_AigConst1(pNtkNew->pManFunc);
-
- // collect the nodes in the TFI of the output (mark the TFI)
- vNodes = Abc_NtkDfsNodes( pNtk, (Abc_Obj_t **)Vec_PtrArray(vRoots), Vec_PtrSize(vRoots) );
-
- // create the PIs
- Abc_NtkForEachCi( pNtk, pObj, i )
- {
- if ( fUseAllCis || Abc_NodeIsTravIdCurrent(pObj) ) // TravId is set by DFS
- {
- pObj->pCopy = Abc_NtkCreatePi(pNtkNew);
-// Abc_ObjAssignName( pObj->pCopy, Abc_ObjName(pObj), NULL );
- Abc_NtkLogicStoreName( pObj->pCopy, Abc_ObjName(pObj) );
- }
- }
-
- // copy the nodes
- Vec_PtrForEachEntry( vNodes, pObj, i )
- {
- // if it is an AIG, add to the hash table
- if ( Abc_NtkIsStrash(pNtk) )
- {
- pObj->pCopy = Abc_AigAnd( pNtkNew->pManFunc, Abc_ObjChild0Copy(pObj), Abc_ObjChild1Copy(pObj) );
- }
- else
- {
- Abc_NtkDupObj( pNtkNew, pObj );
- Abc_ObjForEachFanin( pObj, pFanin, k )
- Abc_ObjAddFanin( pObj->pCopy, pFanin->pCopy );
- }
- }
- Vec_PtrFree( vNodes );
-
- // add the PO corresponding to the nodes
- Vec_PtrForEachEntry( vRoots, pObj, i )
+ assert( Abc_NtkIsStrash(pNtk) );
+ vNodes = Vec_PtrAlloc( Abc_NtkObjNum(pNtk) );
+ Abc_NtkIncrementTravId( pNtk );
+ // add the constant-1 nodes
+ pObj = Abc_AigConst1(pNtk);
+ Abc_NodeSetTravIdCurrent( pObj );
+ Vec_PtrPush( vNodes, pObj );
+ // add the CIs/nodes/COs in the topological order
+ Abc_NtkForEachNode( pNtk, pObj, i )
{
- // create the PO node
- pNodeCoNew = Abc_NtkCreatePo( pNtkNew );
- // connect the internal nodes to the new CO
- if ( Abc_ObjIsCo(pObj) )
- Abc_ObjAddFanin( pNodeCoNew, Abc_ObjChild0Copy(pObj) );
- else
- Abc_ObjAddFanin( pNodeCoNew, pObj->pCopy );
- // assign the name
-// Abc_ObjAssignName( pNodeCoNew, Abc_ObjName(pObj), NULL );
- Abc_NtkLogicStoreName( pNodeCoNew, Abc_ObjName(pObj) );
+ // check the fanins and add CIs
+ Abc_ObjForEachFanin( pObj, pNext, k )
+ if ( Abc_ObjIsCi(pNext) && !Abc_NodeIsTravIdCurrent(pNext) )
+ {
+ Abc_NodeSetTravIdCurrent( pNext );
+ Vec_PtrPush( vNodes, pNext );
+ }
+ // add the node
+ Vec_PtrPush( vNodes, pObj );
+ // check the fanouts and add COs
+ Abc_ObjForEachFanout( pObj, pNext, k )
+ if ( Abc_ObjIsCo(pNext) && !Abc_NodeIsTravIdCurrent(pNext) )
+ {
+ Abc_NodeSetTravIdCurrent( pNext );
+ Vec_PtrPush( vNodes, pNext );
+ }
}
-
- if ( !Abc_NtkCheck( pNtkNew ) )
- fprintf( stdout, "Abc_NtkCreateConeArray(): Network check has failed.\n" );
- return pNtkNew;
+ return vNodes;
}
/**Function*************************************************************
- Synopsis [Appends the second network to the first.]
+ Synopsis [Computes supports of the POs.]
- Description [Modifies the first network by adding the logic of the second.
- Performs structural hashing while appending the networks. Does not change
- the second network. Returns 0 if the appending failed, 1 otherise.]
+ Description [Returns the ptr-vector of int-vectors.]
SideEffects []
SeeAlso []
***********************************************************************/
-int Abc_NtkAppendNew( Abc_Ntk_t * pNtk1, Abc_Ntk_t * pNtk2 )
+Vec_Ptr_t * Abc_NtkComputeSupportsSmart( Abc_Ntk_t * pNtk )
{
+ Vec_Ptr_t * vSupports;
+ Vec_Ptr_t * vNodes;
+ Vec_Int_t * vSupp;
+ Supp_Man_t * p;
+ Supp_One_t * pPart0, * pPart1;
Abc_Obj_t * pObj;
-// char * pName;
- int i, nNewCis;
- // the first network should be an AIG
- assert( Abc_NtkIsStrash(pNtk1) );
- assert( Abc_NtkIsStrash(pNtk2) );
- // check that the networks have the same PIs
- // reorder PIs of pNtk2 according to pNtk1
-// if ( !Abc_NtkCompareSignals( pNtk1, pNtk2, 1, 1 ) )
-// printf( "Abc_NtkAppend(): The union of the network PIs is computed (warning).\n" );
- // perform strashing
- nNewCis = 0;
- Abc_NtkCleanCopy( pNtk2 );
- Abc_AigConst1(pNtk2->pManFunc)->pCopy = Abc_AigConst1(pNtk1->pManFunc);
- Abc_NtkForEachCi( pNtk2, pObj, i )
+ int i;
+ // set the number of PIs/POs
+ Abc_NtkForEachCi( pNtk, pObj, i )
+ pObj->pNext = (Abc_Obj_t *)i;
+ Abc_NtkForEachCo( pNtk, pObj, i )
+ pObj->pNext = (Abc_Obj_t *)i;
+ // start the support computation manager
+ p = Supp_ManStart( 1 << 20, 1 << 6 );
+ // consider objects in the topological order
+ vSupports = Vec_PtrAlloc( Abc_NtkCoNum(pNtk) );
+ Abc_NtkCleanCopy(pNtk);
+ // order the nodes so that the PIs and POs follow naturally
+ vNodes = Abc_NtkDfsNatural( pNtk );
+ Vec_PtrForEachEntry( vNodes, pObj, i )
{
-// pName = Abc_ObjName(pObj);
-// pObj->pCopy = Abc_NtkFindCi(pNtk1, Abc_ObjName(pObj));
- pObj->pCopy = Abc_NtkCi( pNtk1, i );
- if ( pObj->pCopy == NULL )
+ if ( Abc_ObjIsNode(pObj) )
{
- pObj->pCopy = Abc_NtkDupObj( pNtk1, pObj );
- nNewCis++;
+ pPart0 = (Supp_One_t *)Abc_ObjFanin0(pObj)->pCopy;
+ pPart1 = (Supp_One_t *)Abc_ObjFanin1(pObj)->pCopy;
+ pObj->pCopy = (Abc_Obj_t *)Supp_ManMergeEntry( p, pPart0, pPart1, Abc_ObjFanoutNum(pObj) );
+ assert( pPart0->nRefs > 0 );
+ if ( --pPart0->nRefs == 0 )
+ Supp_ManRecycleEntry( p, pPart0 );
+ assert( pPart1->nRefs > 0 );
+ if ( --pPart1->nRefs == 0 )
+ Supp_ManRecycleEntry( p, pPart1 );
+ continue;
}
- }
- if ( nNewCis )
- printf( "Warning: Procedure Abc_NtkAppend() added %d new CIs.\n", nNewCis );
- // add pNtk2 to pNtk1 while strashing
- Abc_NtkForEachNode( pNtk2, pObj, i )
- {
- if ( Abc_ObjFaninNum(pObj) == 0 )
+ if ( Abc_ObjIsCo(pObj) )
+ {
+ pPart0 = (Supp_One_t *)Abc_ObjFanin0(pObj)->pCopy;
+ // only save the CO if it is non-trivial
+ if ( Abc_ObjIsNode(Abc_ObjFanin0(pObj)) )
+ {
+ vSupp = Supp_ManTransferEntry(pPart0);
+ Vec_IntPush( vSupp, (int)pObj->pNext );
+ Vec_PtrPush( vSupports, vSupp );
+ }
+ assert( pPart0->nRefs > 0 );
+ if ( --pPart0->nRefs == 0 )
+ Supp_ManRecycleEntry( p, pPart0 );
continue;
- pObj->pCopy = Abc_AigAnd( pNtk1->pManFunc, Abc_ObjChild0Copy(pObj), Abc_ObjChild1Copy(pObj) );
- }
- // add the COs of the second network
- {
- Abc_Obj_t * pObjOld, * pDriverOld, * pDriverNew;
- int fCompl;//, iNodeId;
- // OR the choices
- Abc_NtkForEachCo( pNtk2, pObj, i )
+ }
+ if ( Abc_ObjIsCi(pObj) )
{
-// iNodeId = Nm_ManFindIdByNameTwoTypes( pNtk1->pManName, Abc_ObjName(pObj), ABC_OBJ_PO, ABC_OBJ_BI );
-// assert( iNodeId >= 0 );
-// pObjOld = Abc_NtkObj( pNtk1, iNodeId );
- pObjOld = Abc_NtkCo( pNtk1, i );
-
- // derive the new driver
- pDriverOld = Abc_ObjChild0( pObjOld );
- pDriverNew = Abc_ObjChild0Copy( pObj );
- pDriverNew = Abc_AigOr( pNtk1->pManFunc, pDriverOld, pDriverNew );
- if ( Abc_ObjRegular(pDriverOld) == Abc_ObjRegular(pDriverNew) )
- continue;
- // replace the old driver by the new driver
- fCompl = Abc_ObjRegular(pDriverOld)->fPhase ^ Abc_ObjRegular(pDriverNew)->fPhase;
- Abc_ObjPatchFanin( pObjOld, Abc_ObjRegular(pDriverOld), Abc_ObjNotCond(Abc_ObjRegular(pDriverNew), fCompl) );
+ if ( Abc_ObjFanoutNum(pObj) )
+ {
+ pPart0 = (Supp_One_t *)Supp_ManFetchEntry( p, 1, Abc_ObjFanoutNum(pObj) );
+ pPart0->pOuts[ pPart0->nOuts++ ] = (int)pObj->pNext;
+ pObj->pCopy = (Abc_Obj_t *)pPart0;
+ }
+ continue;
}
+ if ( pObj == Abc_AigConst1(pNtk) )
+ {
+ if ( Abc_ObjFanoutNum(pObj) )
+ pObj->pCopy = (Abc_Obj_t *)Supp_ManFetchEntry( p, 0, Abc_ObjFanoutNum(pObj) );
+ continue;
+ }
+ assert( 0 );
}
- // make sure that everything is okay
- if ( !Abc_NtkCheck( pNtk1 ) )
- {
- printf( "Abc_NtkAppend: The network check has failed.\n" );
- return 0;
- }
- return 1;
+ Vec_PtrFree( vNodes );
+//printf( "Memory usage = %d Mb.\n", Vec_PtrSize(p->vMemory) * p->nChunkSize / (1<<20) );
+ Supp_ManStop( p );
+ // sort supports by size
+ Vec_VecSort( (Vec_Vec_t *)vSupports, 1 );
+ // clear the number of PIs/POs
+ Abc_NtkForEachCi( pNtk, pObj, i )
+ pObj->pNext = NULL;
+ Abc_NtkForEachCo( pNtk, pObj, i )
+ pObj->pNext = NULL;
+/*
+ Vec_PtrForEachEntry( vSupports, vSupp, i )
+ printf( "%d ", Vec_IntSize(vSupp) );
+ printf( "\n" );
+*/
+ return vSupports;
}
-
-
/**Function*************************************************************
- Synopsis [Prepare supports.]
+ Synopsis [Computes supports of the POs using naive method.]
- Description []
+ Description [Returns the ptr-vector of int-vectors.]
SideEffects []
SeeAlso []
***********************************************************************/
-Vec_Ptr_t * Abc_NtkPartitionCollectSupps( Abc_Ntk_t * pNtk )
+Vec_Ptr_t * Abc_NtkComputeSupportsNaive( Abc_Ntk_t * pNtk )
{
Vec_Ptr_t * vSupp, * vSupports;
Vec_Int_t * vSuppI;
Abc_Obj_t * pObj, * pTemp;
int i, k;
+ // set the PI numbers
+ Abc_NtkForEachCi( pNtk, pObj, i )
+ pObj->pNext = (void *)i;
+ // save the CI numbers
vSupports = Vec_PtrAlloc( Abc_NtkCoNum(pNtk) );
Abc_NtkForEachCo( pNtk, pObj, i )
{
+ if ( !Abc_ObjIsNode(Abc_ObjFanin0(pObj)) )
+ continue;
vSupp = Abc_NtkNodeSupport( pNtk, &pObj, 1 );
vSuppI = (Vec_Int_t *)vSupp;
Vec_PtrForEachEntry( vSupp, pTemp, k )
- Vec_IntWriteEntry( vSuppI, k, pTemp->Id );
+ Vec_IntWriteEntry( vSuppI, k, (int)pTemp->pNext );
Vec_IntSort( vSuppI, 0 );
// append the number of this output
Vec_IntPush( vSuppI, i );
// save the support in the vector
Vec_PtrPush( vSupports, vSuppI );
}
+ // clean the CI numbers
+ Abc_NtkForEachCi( pNtk, pObj, i )
+ pObj->pNext = NULL;
// sort supports by size
Vec_VecSort( (Vec_Vec_t *)vSupports, 1 );
+/*
+ Vec_PtrForEachEntry( vSupports, vSuppI, i )
+ printf( "%d ", Vec_IntSize(vSuppI) );
+ printf( "\n" );
+*/
return vSupports;
}
/**Function*************************************************************
+ Synopsis [Start bitwise support representation.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+unsigned * Abc_NtkSuppCharStart( Vec_Int_t * vOne, int nPis )
+{
+ unsigned * pBuffer;
+ int i, Entry;
+ int nWords = Abc_BitWordNum(nPis);
+ pBuffer = ALLOC( unsigned, nWords );
+ memset( pBuffer, 0, sizeof(unsigned) * nWords );
+ Vec_IntForEachEntry( vOne, Entry, i )
+ {
+ assert( Entry < nPis );
+ Abc_InfoSetBit( pBuffer, Entry );
+ }
+ return pBuffer;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Add to bitwise support representation.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Abc_NtkSuppCharAdd( unsigned * pBuffer, Vec_Int_t * vOne, int nPis )
+{
+ int i, Entry;
+ Vec_IntForEachEntry( vOne, Entry, i )
+ {
+ assert( Entry < nPis );
+ Abc_InfoSetBit( pBuffer, Entry );
+ }
+}
+
+/**Function*************************************************************
+
+ Synopsis [Find the common variables using bitwise support representation.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Abc_NtkSuppCharCommon( unsigned * pBuffer, Vec_Int_t * vOne )
+{
+ int i, Entry, nCommon = 0;
+ Vec_IntForEachEntry( vOne, Entry, i )
+ nCommon += Abc_InfoHasBit(pBuffer, Entry);
+ return nCommon;
+}
+
+/**Function*************************************************************
+
Synopsis [Find the best partition.]
Description []
@@ -439,8 +524,9 @@ Vec_Ptr_t * Abc_NtkPartitionCollectSupps( Abc_Ntk_t * pNtk )
SeeAlso []
***********************************************************************/
-int Abc_NtkPartitionSmartFindPart( Vec_Ptr_t * vPartSuppsAll, Vec_Ptr_t * vPartsAll, int nPartSizeLimit, Vec_Int_t * vOne )
+int Abc_NtkPartitionSmartFindPart( Vec_Ptr_t * vPartSuppsAll, Vec_Ptr_t * vPartsAll, Vec_Ptr_t * vPartSuppsChar, int nSuppSizeLimit, Vec_Int_t * vOne )
{
+/*
Vec_Int_t * vPartSupp, * vPart;
double Attract, Repulse, Cost, CostBest;
int i, nCommon, iBest;
@@ -448,12 +534,12 @@ int Abc_NtkPartitionSmartFindPart( Vec_Ptr_t * vPartSuppsAll, Vec_Ptr_t * vParts
CostBest = 0.0;
Vec_PtrForEachEntry( vPartSuppsAll, vPartSupp, i )
{
+ vPart = Vec_PtrEntry( vPartsAll, i );
+ if ( nPartSizeLimit > 0 && Vec_IntSize(vPart) >= nPartSizeLimit )
+ continue;
nCommon = Vec_IntTwoCountCommon( vPartSupp, vOne );
if ( nCommon == 0 )
continue;
- vPart = Vec_PtrEntry( vPartsAll, i );
- if ( nPartSizeLimit > 0 && Vec_IntSize(vPart) > nPartSizeLimit )
- continue;
if ( nCommon == Vec_IntSize(vOne) )
return i;
Attract = 1.0 * nCommon / Vec_IntSize(vOne);
@@ -471,6 +557,49 @@ int Abc_NtkPartitionSmartFindPart( Vec_Ptr_t * vPartSuppsAll, Vec_Ptr_t * vParts
if ( CostBest < 0.6 )
return -1;
return iBest;
+*/
+
+ Vec_Int_t * vPartSupp;//, * vPart;
+ int Attract, Repulse, Value, ValueBest;
+ int i, nCommon, iBest;
+// int nCommon2;
+ iBest = -1;
+ ValueBest = 0;
+ Vec_PtrForEachEntry( vPartSuppsAll, vPartSupp, i )
+ {
+ // skip partitions with too many outputs
+// vPart = Vec_PtrEntry( vPartsAll, i );
+// if ( nSuppSizeLimit > 0 && Vec_IntSize(vPart) >= nSuppSizeLimit )
+// continue;
+ // find the number of common variables between this output and the partitions
+// nCommon2 = Vec_IntTwoCountCommon( vPartSupp, vOne );
+ nCommon = Abc_NtkSuppCharCommon( Vec_PtrEntry(vPartSuppsChar, i), vOne );
+// assert( nCommon2 == nCommon );
+ // if no common variables, continue searching
+ if ( nCommon == 0 )
+ continue;
+ // if all variables are common, the best partition if found
+ if ( nCommon == Vec_IntSize(vOne) )
+ return i;
+ // skip partitions whose size exceeds the limit
+ if ( nSuppSizeLimit > 0 && Vec_IntSize(vPartSupp) >= 2 * nSuppSizeLimit )
+ continue;
+ // figure out might be the good partition for this one
+ Attract = 1000 * nCommon / Vec_IntSize(vOne);
+ if ( Vec_IntSize(vPartSupp) < 100 )
+ Repulse = 1;
+ else
+ Repulse = 1+Extra_Base2Log(Vec_IntSize(vPartSupp)-100);
+ Value = Attract/Repulse;
+ if ( ValueBest < Value )
+ {
+ ValueBest = Value;
+ iBest = i;
+ }
+ }
+ if ( ValueBest < 75 )
+ return -1;
+ return iBest;
}
/**Function*************************************************************
@@ -498,7 +627,7 @@ void Abc_NtkPartitionPrint( Abc_Ntk_t * pNtk, Vec_Ptr_t * vPartsAll, Vec_Ptr_t *
if ( i == Vec_PtrSize(vPartsAll) - 1 )
break;
}
- assert( Counter == Abc_NtkCoNum(pNtk) );
+// assert( Counter == Abc_NtkCoNum(pNtk) );
printf( "\nTotal = %d. Outputs = %d.\n", Counter, Abc_NtkCoNum(pNtk) );
}
@@ -513,20 +642,20 @@ void Abc_NtkPartitionPrint( Abc_Ntk_t * pNtk, Vec_Ptr_t * vPartsAll, Vec_Ptr_t *
SeeAlso []
***********************************************************************/
-void Abc_NtkPartitionCompact( Vec_Ptr_t * vPartsAll, Vec_Ptr_t * vPartSuppsAll, int nPartSizeLimit )
+void Abc_NtkPartitionCompact( Vec_Ptr_t * vPartsAll, Vec_Ptr_t * vPartSuppsAll, int nSuppSizeLimit )
{
Vec_Int_t * vOne, * vPart, * vPartSupp, * vTemp;
int i, iPart;
- if ( nPartSizeLimit == 0 )
- nPartSizeLimit = 200;
+ if ( nSuppSizeLimit == 0 )
+ nSuppSizeLimit = 200;
// pack smaller partitions into larger blocks
iPart = 0;
vPart = vPartSupp = NULL;
Vec_PtrForEachEntry( vPartSuppsAll, vOne, i )
{
- if ( Vec_IntSize(vOne) < nPartSizeLimit )
+ if ( Vec_IntSize(vOne) < nSuppSizeLimit )
{
if ( vPartSupp == NULL )
{
@@ -542,7 +671,7 @@ void Abc_NtkPartitionCompact( Vec_Ptr_t * vPartsAll, Vec_Ptr_t * vPartSuppsAll,
Vec_IntFree( vTemp );
Vec_IntFree( Vec_PtrEntry(vPartsAll, i) );
}
- if ( Vec_IntSize(vPartSupp) < nPartSizeLimit )
+ if ( Vec_IntSize(vPartSupp) < nSuppSizeLimit )
continue;
}
else
@@ -578,37 +707,49 @@ void Abc_NtkPartitionCompact( Vec_Ptr_t * vPartsAll, Vec_Ptr_t * vPartSuppsAll,
Synopsis [Perform the smart partitioning.]
- Description []
+ Description [Returns the ptr-vector of int-vectors.]
SideEffects []
SeeAlso []
***********************************************************************/
-Vec_Vec_t * Abc_NtkPartitionSmart( Abc_Ntk_t * pNtk, int nPartSizeLimit, int fVerbose )
+Vec_Ptr_t * Abc_NtkPartitionSmart( Abc_Ntk_t * pNtk, int nSuppSizeLimit, int fVerbose )
{
- Vec_Ptr_t * vSupps, * vPartsAll, * vPartsAll2, * vPartSuppsAll, * vPartPtr;
+ ProgressBar * pProgress;
+ Vec_Ptr_t * vPartSuppsChar;
+ Vec_Ptr_t * vSupps, * vPartsAll, * vPartsAll2, * vPartSuppsAll;
Vec_Int_t * vOne, * vPart, * vPartSupp, * vTemp;
- int i, iPart, iOut, clk;
+ int i, iPart, iOut, clk, clk2, timeFind = 0;
// compute the supports for all outputs
clk = clock();
- vSupps = Abc_NtkPartitionCollectSupps( pNtk );
+// vSupps = Abc_NtkComputeSupportsNaive( pNtk );
+ vSupps = Abc_NtkComputeSupportsSmart( pNtk );
if ( fVerbose )
{
PRT( "Supps", clock() - clk );
}
+ // start char-based support representation
+ vPartSuppsChar = Vec_PtrAlloc( 1000 );
// create partitions
clk = clock();
vPartsAll = Vec_PtrAlloc( 256 );
vPartSuppsAll = Vec_PtrAlloc( 256 );
+ pProgress = Extra_ProgressBarStart( stdout, Vec_PtrSize(vSupps) );
Vec_PtrForEachEntry( vSupps, vOne, i )
{
+ Extra_ProgressBarUpdate( pProgress, i, NULL );
+// if ( i % 1000 == 0 )
+// printf( "CIs = %6d. COs = %6d. Processed = %6d (out of %6d). Parts = %6d.\r",
+// Abc_NtkCiNum(pNtk), Abc_NtkCoNum(pNtk), i, Vec_PtrSize(vSupps), Vec_PtrSize(vPartsAll) );
// get the output number
iOut = Vec_IntPop(vOne);
// find closely matching part
- iPart = Abc_NtkPartitionSmartFindPart( vPartSuppsAll, vPartsAll, nPartSizeLimit, vOne );
+clk2 = clock();
+ iPart = Abc_NtkPartitionSmartFindPart( vPartSuppsAll, vPartsAll, vPartSuppsChar, nSuppSizeLimit, vOne );
+timeFind += clock() - clk2;
if ( iPart == -1 )
{
// create new partition
@@ -619,6 +760,8 @@ clk = clock();
// add this partition and its support
Vec_PtrPush( vPartsAll, vPart );
Vec_PtrPush( vPartSuppsAll, vPartSupp );
+
+ Vec_PtrPush( vPartSuppsChar, Abc_NtkSuppCharStart(vOne, Abc_NtkCiNum(pNtk)) );
}
else
{
@@ -631,11 +774,22 @@ clk = clock();
Vec_IntFree( vTemp );
// reinsert new support
Vec_PtrWriteEntry( vPartSuppsAll, iPart, vPartSupp );
+
+ Abc_NtkSuppCharAdd( Vec_PtrEntry(vPartSuppsChar, iPart), vOne, Abc_NtkCiNum(pNtk) );
}
}
+ Extra_ProgressBarStop( pProgress );
+
+ // stop char-based support representation
+ Vec_PtrForEachEntry( vPartSuppsChar, vTemp, i )
+ free( vTemp );
+ Vec_PtrFree( vPartSuppsChar );
+
+//printf( "\n" );
if ( fVerbose )
{
PRT( "Parts", clock() - clk );
+//PRT( "Find ", timeFind );
}
clk = clock();
@@ -653,18 +807,20 @@ clk = clock();
// compact small partitions
// Abc_NtkPartitionPrint( pNtk, vPartsAll, vPartSuppsAll );
- Abc_NtkPartitionCompact( vPartsAll, vPartSuppsAll, nPartSizeLimit );
- if ( fVerbose )
- Abc_NtkPartitionPrint( pNtk, vPartsAll, vPartSuppsAll );
+ Abc_NtkPartitionCompact( vPartsAll, vPartSuppsAll, nSuppSizeLimit );
+
if ( fVerbose )
{
PRT( "Comps", clock() - clk );
}
+ if ( fVerbose )
+ printf( "Created %d partitions.\n", Vec_PtrSize(vPartsAll) );
+// Abc_NtkPartitionPrint( pNtk, vPartsAll, vPartSuppsAll );
// cleanup
Vec_VecFree( (Vec_Vec_t *)vSupps );
Vec_VecFree( (Vec_Vec_t *)vPartSuppsAll );
-
+/*
// converts from intergers to nodes
Vec_PtrForEachEntry( vPartsAll, vPart, iPart )
{
@@ -674,34 +830,54 @@ PRT( "Comps", clock() - clk );
Vec_IntFree( vPart );
Vec_PtrWriteEntry( vPartsAll, iPart, vPartPtr );
}
- return (Vec_Vec_t *)vPartsAll;
+*/
+ return vPartsAll;
}
/**Function*************************************************************
Synopsis [Perform the naive partitioning.]
- Description []
+ Description [Returns the ptr-vector of int-vectors.]
SideEffects []
SeeAlso []
***********************************************************************/
-Vec_Vec_t * Abc_NtkPartitionNaive( Abc_Ntk_t * pNtk, int nPartSize )
+Vec_Ptr_t * Abc_NtkPartitionNaive( Abc_Ntk_t * pNtk, int nPartSize )
{
- Vec_Vec_t * vParts;
+ Vec_Ptr_t * vParts;
Abc_Obj_t * pObj;
int nParts, i;
nParts = (Abc_NtkCoNum(pNtk) / nPartSize) + ((Abc_NtkCoNum(pNtk) % nPartSize) > 0);
- vParts = Vec_VecStart( nParts );
+ vParts = (Vec_Ptr_t *)Vec_VecStart( nParts );
Abc_NtkForEachCo( pNtk, pObj, i )
- Vec_VecPush( vParts, i / nPartSize, pObj );
+ Vec_IntPush( Vec_PtrEntry(vParts, i / nPartSize), i );
return vParts;
}
/**Function*************************************************************
+ Synopsis [Converts from intergers to pointers for the given network.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Abc_NtkConvertCos( Abc_Ntk_t * pNtk, Vec_Int_t * vOuts, Vec_Ptr_t * vOutsPtr )
+{
+ int Out, i;
+ Vec_PtrClear( vOutsPtr );
+ Vec_IntForEachEntry( vOuts, Out, i )
+ Vec_PtrPush( vOutsPtr, Abc_NtkCo(pNtk, Out) );
+}
+
+/**Function*************************************************************
+
Synopsis [Returns representative of the given node.]
Description []
@@ -744,7 +920,6 @@ static inline Abc_Obj_t * Abc_NtkPartStitchCopy1( Vec_Ptr_t * vEquiv, Abc_Obj_t
return Abc_ObjNotCond( pRepr->pCopy, pRepr->fPhase ^ pFan->fPhase ^ Abc_ObjFaninC1(pObj) );
}
-
/**Function*************************************************************
Synopsis []
@@ -781,24 +956,18 @@ Hop_Man_t * Abc_NtkPartStartHop( Abc_Ntk_t * pNtk )
pMan->vObjs = Vec_PtrAlloc( Abc_NtkObjNumMax(pNtk) + 1 );
Vec_PtrPush( pMan->vObjs, Hop_ManConst1(pMan) );
// map constant node and PIs
- Abc_AigConst1(pNtk->pManFunc)->pNext = (Abc_Obj_t *)Hop_ManConst1(pMan);
+ Abc_AigConst1(pNtk)->pNext = (Abc_Obj_t *)Hop_ManConst1(pMan);
Abc_NtkForEachCi( pNtk, pObj, i )
pObj->pNext = (Abc_Obj_t *)Hop_ObjCreatePi(pMan);
// map the internal nodes
-// Abc_AigForEachAnd( pNtk, pObj, i )
- Abc_NtkForEachNode( pNtk, pObj, i )
+ Abc_AigForEachAnd( pNtk, pObj, i )
{
- if ( Abc_ObjFaninNum(pObj) == 0 )
- continue;
pObj->pNext = (Abc_Obj_t *)Hop_And( pMan, Hop_ObjChild0Next(pObj), Hop_ObjChild1Next(pObj) );
assert( !Abc_ObjIsComplement(pObj->pNext) );
}
// set the choice nodes
-// Abc_AigForEachAnd( pNtk, pObj, i )
- Abc_NtkForEachNode( pNtk, pObj, i )
+ Abc_AigForEachAnd( pNtk, pObj, i )
{
- if ( Abc_ObjFaninNum(pObj) == 0 )
- continue;
if ( pObj->pCopy )
((Hop_Obj_t *)pObj->pNext)->pData = pObj->pCopy->pNext;
}
@@ -813,58 +982,6 @@ Hop_Man_t * Abc_NtkPartStartHop( Abc_Ntk_t * pNtk )
/**Function*************************************************************
- Synopsis [Maps terminals of the old networks into those of the new network.]
-
- Description []
-
- SideEffects []
-
- SeeAlso []
-
-***********************************************************************/
-void Abc_NtkPartMapTerminals( Vec_Ptr_t * vParts, Abc_Ntk_t * pNtkOld )
-{
- Abc_Ntk_t * pNtkNew;
- stmm_table * tTablePi, * tTablePo;
- Abc_Obj_t * pObj, * pTemp;
- int i, k;
-
- // map names into old nodes
- tTablePi = stmm_init_table( strcmp, stmm_strhash );
- tTablePo = stmm_init_table( strcmp, stmm_strhash );
- Abc_NtkForEachPi( pNtkOld, pObj, i )
- stmm_insert( tTablePi, Abc_ObjName(pObj), (char *)pObj );
- Abc_NtkForEachPo( pNtkOld, pObj, i )
- stmm_insert( tTablePo, Abc_ObjName(pObj), (char *)pObj );
-
- // map new nodes into old nodes
- Vec_PtrForEachEntry( vParts, pNtkNew, k )
- {
- Abc_NtkForEachPi( pNtkNew, pObj, i )
- {
- if ( !stmm_lookup(tTablePi, Abc_ObjName(pObj), (char **)&pTemp) )
- {
- printf( "Cannot find PI node %s in the original network.\n", Abc_ObjName(pObj) );
- return;
- }
- pObj->pCopy = pTemp;
- }
- Abc_NtkForEachPo( pNtkNew, pObj, i )
- {
- if ( !stmm_lookup(tTablePo, Abc_ObjName(pObj), (char **)&pTemp) )
- {
- printf( "Cannot find PO node %s in the original network.\n", Abc_ObjName(pObj) );
- return;
- }
- pObj->pCopy = pTemp;
- }
- }
- stmm_free_table( tTablePi );
- stmm_free_table( tTablePo );
-}
-
-/**Function*************************************************************
-
Synopsis [Stitches together several networks with choice nodes.]
Description []
@@ -879,36 +996,23 @@ Abc_Ntk_t * Abc_NtkPartStitchChoices( Abc_Ntk_t * pNtk, Vec_Ptr_t * vParts )
extern Abc_Ntk_t * Abc_NtkHopRemoveLoops( Abc_Ntk_t * pNtk, Hop_Man_t * pMan );
Hop_Man_t * pMan;
- Abc_Ntk_t * pNtkNew, * pNtkTemp;
Vec_Ptr_t * vNodes;
+ Abc_Ntk_t * pNtkNew, * pNtkTemp;
Abc_Obj_t * pObj, * pFanin;
- int i, k;
+ int i, k, iNodeId;
// start a new network similar to the original one
assert( Abc_NtkIsStrash(pNtk) );
- pNtkNew = Abc_NtkStartFrom( pNtk, ABC_TYPE_STRASH, ABC_FUNC_AIG );
-
+ pNtkNew = Abc_NtkStartFrom( pNtk, ABC_NTK_STRASH, ABC_FUNC_AIG );
// annotate parts to point to the new network
Vec_PtrForEachEntry( vParts, pNtkTemp, i )
{
assert( Abc_NtkIsStrash(pNtkTemp) );
Abc_NtkCleanCopy( pNtkTemp );
- }
-
- // perform mapping of terminals
- Abc_NtkPartMapTerminals( vParts, pNtkNew );
-
-
- // annotate parts to point to the new network
- Vec_PtrForEachEntry( vParts, pNtkTemp, i )
- {
-// assert( Abc_NtkIsStrash(pNtkTemp) );
-// Abc_NtkCleanCopy( pNtkTemp );
// map the CI nodes
- Abc_AigConst1(pNtkTemp->pManFunc)->pCopy = Abc_AigConst1(pNtkNew->pManFunc);
-/*
+ Abc_AigConst1(pNtkTemp)->pCopy = Abc_AigConst1(pNtkNew);
Abc_NtkForEachCi( pNtkTemp, pObj, k )
{
iNodeId = Nm_ManFindIdByNameTwoTypes( pNtkNew->pManName, Abc_ObjName(pObj), ABC_OBJ_PI, ABC_OBJ_BO );
@@ -919,16 +1023,14 @@ Abc_Ntk_t * Abc_NtkPartStitchChoices( Abc_Ntk_t * pNtk, Vec_Ptr_t * vParts )
}
pObj->pCopy = Abc_NtkObj( pNtkNew, iNodeId );
}
-*/
+
// add the internal nodes while saving representatives
vNodes = Abc_AigDfs( pNtkTemp, 1, 0 );
Vec_PtrForEachEntry( vNodes, pObj, k )
{
- if ( Abc_ObjFaninNum(pObj) == 0 )
- continue;
pObj->pCopy = Abc_AigAnd( pNtkNew->pManFunc, Abc_ObjChild0Copy(pObj), Abc_ObjChild1Copy(pObj) );
assert( !Abc_ObjIsComplement(pObj->pCopy) );
- if ( Abc_NodeIsAigChoice(pObj) )
+ if ( Abc_AigNodeIsChoice(pObj) )
for ( pFanin = pObj->pData; pFanin; pFanin = pFanin->pData )
pFanin->pCopy->pCopy = pObj->pCopy;
}
@@ -937,7 +1039,6 @@ Abc_Ntk_t * Abc_NtkPartStitchChoices( Abc_Ntk_t * pNtk, Vec_Ptr_t * vParts )
// map the CO nodes
Abc_NtkForEachCo( pNtkTemp, pObj, k )
{
-/*
iNodeId = Nm_ManFindIdByNameTwoTypes( pNtkNew->pManName, Abc_ObjName(pObj), ABC_OBJ_PO, ABC_OBJ_BI );
if ( iNodeId == -1 )
{
@@ -945,11 +1046,23 @@ Abc_Ntk_t * Abc_NtkPartStitchChoices( Abc_Ntk_t * pNtk, Vec_Ptr_t * vParts )
return NULL;
}
pObj->pCopy = Abc_NtkObj( pNtkNew, iNodeId );
-*/
Abc_ObjAddFanin( pObj->pCopy, Abc_ObjChild0Copy(pObj) );
}
}
+ // connect the remaining POs
+/*
+ Abc_AigConst1(pNtk)->pCopy = Abc_AigConst1(pNtkNew);
+ Abc_NtkForEachCi( pNtk, pObj, i )
+ pObj->pCopy = Abc_NtkCi( pNtkNew, i );
+ Abc_NtkForEachCo( pNtk, pObj, i )
+ pObj->pCopy = Abc_NtkCo( pNtkNew, i );
+*/
+ Abc_NtkForEachCo( pNtk, pObj, i )
+ {
+ if ( Abc_ObjFaninNum(pObj->pCopy) == 0 )
+ Abc_ObjAddFanin( pObj->pCopy, Abc_ObjChild0Copy(pObj) );
+ }
// transform into the HOP manager
pMan = Abc_NtkPartStartHop( pNtkNew );
@@ -977,49 +1090,112 @@ Abc_Ntk_t * Abc_NtkPartStitchChoices( Abc_Ntk_t * pNtk, Vec_Ptr_t * vParts )
SeeAlso []
***********************************************************************/
-Abc_Ntk_t * Abc_NtkFraigPartitioned( Abc_Ntk_t * pNtk, void * pParams )
+Abc_Ntk_t * Abc_NtkFraigPartitioned( Vec_Ptr_t * vStore, void * pParams )
{
extern int Cmd_CommandExecute( void * pAbc, char * sCommand );
extern void * Abc_FrameGetGlobalFrame();
- Vec_Vec_t * vParts;
- Vec_Ptr_t * vFraigs, * vOne;
- Abc_Ntk_t * pNtkAig, * pNtkFraig;
- int i;
+ Vec_Ptr_t * vParts, * vFraigs, * vOnePtr;
+ Vec_Int_t * vOne;
+ Abc_Ntk_t * pNtk, * pNtk2, * pNtkAig, * pNtkFraig;
+ int i, k;
// perform partitioning
+ pNtk = Vec_PtrEntry( vStore, 0 );
assert( Abc_NtkIsStrash(pNtk) );
// vParts = Abc_NtkPartitionNaive( pNtk, 20 );
- vParts = Abc_NtkPartitionSmart( pNtk, 0, 0 );
+ vParts = Abc_NtkPartitionSmart( pNtk, 300, 0 );
Cmd_CommandExecute( Abc_FrameGetGlobalFrame(), "unset progressbar" );
// fraig each partition
- vFraigs = Vec_PtrAlloc( Vec_VecSize(vParts) );
- Vec_VecForEachLevel( vParts, vOne, i )
+ vOnePtr = Vec_PtrAlloc( 1000 );
+ vFraigs = Vec_PtrAlloc( Vec_PtrSize(vParts) );
+ Vec_PtrForEachEntry( vParts, vOne, i )
{
- pNtkAig = Abc_NtkCreateConeArray( pNtk, vOne, 0 );
- pNtkFraig = Abc_NtkFraig( pNtkAig, pParams, 0 );
+ // start the partition
+ Abc_NtkConvertCos( pNtk, vOne, vOnePtr );
+ pNtkAig = Abc_NtkCreateConeArray( pNtk, vOnePtr, 0 );
+ // add nodes to the partition
+ Vec_PtrForEachEntryStart( vStore, pNtk2, k, 1 )
+ {
+ Abc_NtkConvertCos( pNtk2, vOne, vOnePtr );
+ Abc_NtkAppendToCone( pNtkAig, pNtk2, vOnePtr );
+ }
+ printf( "Fraiging part %4d (out of %4d) PI = %5d. PO = %5d. And = %6d. Lev = %4d.\r",
+ i+1, Vec_PtrSize(vParts), Abc_NtkPiNum(pNtkAig), Abc_NtkPoNum(pNtkAig),
+ Abc_NtkNodeNum(pNtkAig), Abc_AigLevel(pNtkAig) );
+ // fraig the partition
+ pNtkFraig = Abc_NtkFraig( pNtkAig, pParams, 1, 0 );
Vec_PtrPush( vFraigs, pNtkFraig );
Abc_NtkDelete( pNtkAig );
-
- printf( "Finished part %d (out of %d)\r", i+1, Vec_VecSize(vParts) );
}
- Vec_VecFree( vParts );
- printf( " \r" );
+ printf( " \r" );
+ Vec_VecFree( (Vec_Vec_t *)vParts );
Cmd_CommandExecute( Abc_FrameGetGlobalFrame(), "set progressbar" );
// derive the final network
pNtkFraig = Abc_NtkPartStitchChoices( pNtk, vFraigs );
Vec_PtrForEachEntry( vFraigs, pNtkAig, i )
+ Abc_NtkDelete( pNtkAig );
+ Vec_PtrFree( vFraigs );
+ Vec_PtrFree( vOnePtr );
+ return pNtkFraig;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Stitches together several networks with choice nodes.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Abc_NtkFraigPartitionedTime( Abc_Ntk_t * pNtk, void * pParams )
+{
+ extern int Cmd_CommandExecute( void * pAbc, char * sCommand );
+ extern void * Abc_FrameGetGlobalFrame();
+
+ Vec_Ptr_t * vParts, * vFraigs, * vOnePtr;
+ Vec_Int_t * vOne;
+ Abc_Ntk_t * pNtkAig, * pNtkFraig;
+ int i;
+ int clk = clock();
+
+ // perform partitioning
+ assert( Abc_NtkIsStrash(pNtk) );
+// vParts = Abc_NtkPartitionNaive( pNtk, 20 );
+ vParts = Abc_NtkPartitionSmart( pNtk, 300, 0 );
+
+ Cmd_CommandExecute( Abc_FrameGetGlobalFrame(), "unset progressbar" );
+
+ // fraig each partition
+ vOnePtr = Vec_PtrAlloc( 1000 );
+ vFraigs = Vec_PtrAlloc( Vec_PtrSize(vParts) );
+ Vec_PtrForEachEntry( vParts, vOne, i )
{
-// Abc_NtkPrintStats( stdout, pNtkAig, 0 );
+ Abc_NtkConvertCos( pNtk, vOne, vOnePtr );
+ pNtkAig = Abc_NtkCreateConeArray( pNtk, vOnePtr, 0 );
+ pNtkFraig = Abc_NtkFraig( pNtkAig, pParams, 0, 0 );
+ Vec_PtrPush( vFraigs, pNtkFraig );
Abc_NtkDelete( pNtkAig );
+
+ printf( "Finished part %5d (out of %5d)\r", i+1, Vec_PtrSize(vParts) );
}
- Vec_PtrFree( vFraigs );
+ Vec_VecFree( (Vec_Vec_t *)vParts );
- return pNtkFraig;
+ Cmd_CommandExecute( Abc_FrameGetGlobalFrame(), "set progressbar" );
+
+ // derive the final network
+ Vec_PtrForEachEntry( vFraigs, pNtkAig, i )
+ Abc_NtkDelete( pNtkAig );
+ Vec_PtrFree( vFraigs );
+ Vec_PtrFree( vOnePtr );
+ PRT( "Partitioned fraiging time", clock() - clk );
}
////////////////////////////////////////////////////////////////////////
diff --git a/src/base/abci/abcPlace.c b/src/base/abci/abcPlace.c
new file mode 100644
index 00000000..87c99e99
--- /dev/null
+++ b/src/base/abci/abcPlace.c
@@ -0,0 +1,255 @@
+/**CFile****************************************************************
+
+ FileName [abcPlace.c]
+
+ SystemName [ABC: Logic synthesis and verification system.]
+
+ PackageName [Network and node package.]
+
+ Synopsis [Interface with a placer.]
+
+ Author [Alan Mishchenko]
+
+ Affiliation [UC Berkeley]
+
+ Date [Ver. 1.0. Started - June 20, 2005.]
+
+ Revision [$Id: abcPlace.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "abc.h"
+
+// placement includes
+#include "place_base.h"
+
+////////////////////////////////////////////////////////////////////////
+/// DECLARATIONS ///
+////////////////////////////////////////////////////////////////////////
+
+AbstractCell *abstractCells = NULL;
+ConcreteCell *cells = NULL;
+ConcreteNet *nets = NULL;
+int nAllocSize = 0;
+
+////////////////////////////////////////////////////////////////////////
+/// FUNCTION DEFINITIONS ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+ Synopsis [Creates a new cell.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+static inline void Abc_PlaceCreateCell( Abc_Obj_t * pObj, int fAnd )
+{
+ assert( cells[pObj->Id].m_id == 0 );
+
+ cells[pObj->Id].m_id = pObj->Id;
+ cells[pObj->Id].m_label = "";
+ cells[pObj->Id].m_parent = &(abstractCells[fAnd]);
+ cells[pObj->Id].m_fixed = 0;
+ addConcreteCell(&(cells[pObj->Id]));
+}
+
+/**Function*************************************************************
+
+ Synopsis [Updates the net.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+static inline void Abc_PlaceUpdateNet( Abc_Obj_t * pObj )
+{
+ Abc_Obj_t * pFanout;
+ int k;
+ // free the old array of net terminals
+ if ( nets[pObj->Id].m_terms )
+ free( nets[pObj->Id].m_terms );
+ // fill in the net with the new information
+ nets[pObj->Id].m_id = pObj->Id;
+ nets[pObj->Id].m_weight = 1.0;
+ nets[pObj->Id].m_numTerms = Abc_ObjFanoutNum(pObj); //fanout
+ nets[pObj->Id].m_terms = ALLOC(ConcreteCell*, Abc_ObjFanoutNum(pObj));
+ Abc_ObjForEachFanout( pObj, pFanout, k )
+ nets[pObj->Id].m_terms[k] = &(cells[pFanout->Id]);
+ addConcreteNet(&(nets[pObj->Id]));
+}
+
+/**Function*************************************************************
+
+ Synopsis [Returns the placement cost of the cut.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+float Abc_PlaceEvaluateCut( Abc_Obj_t * pRoot, Vec_Ptr_t * vFanins )
+{
+ Abc_Obj_t * pObj;
+// double x, y;
+ int i;
+ Vec_PtrForEachEntry( vFanins, pObj, i )
+ {
+// pObj->Id
+ }
+ return 0.0;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Updates placement after one step of rewriting.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Abc_PlaceUpdate( Vec_Ptr_t * vAddedCells, Vec_Ptr_t * vUpdatedNets )
+{
+ Abc_Obj_t * pObj, * pFanin;
+ int i, k;
+ Vec_Ptr_t * vCells, * vNets;
+
+ // start the arrays of new cells and nets
+ vCells = Vec_PtrAlloc( 16 );
+ vNets = Vec_PtrAlloc( 32 );
+
+ // go through the new nodes
+ Vec_PtrForEachEntry( vAddedCells, pObj, i )
+ {
+ assert( !Abc_ObjIsComplement(pObj) );
+ Abc_PlaceCreateCell( pObj, 1 );
+ Abc_PlaceUpdateNet( pObj );
+
+ // add the new cell and its fanin nets to temporary storage
+ Vec_PtrPush( vCells, &(cells[pObj->Id]) );
+ Abc_ObjForEachFanin( pObj, pFanin, k )
+ Vec_PtrPushUnique( vNets, &(nets[pFanin->Id]) );
+ }
+
+ // go through the modified nets
+ Vec_PtrForEachEntry( vUpdatedNets, pObj, i )
+ {
+ assert( !Abc_ObjIsComplement(pObj) );
+ if ( Abc_ObjType(pObj) == ABC_OBJ_NONE ) // dead node
+ continue;
+ Abc_PlaceUpdateNet( pObj );
+ }
+
+ // update the placement
+// fastPlace( Vec_PtrSize(vCells), (ConcreteCell **)Vec_PtrArray(vCells),
+// Vec_PtrSize(vNets), (ConcreteNet **)Vec_PtrArray(vNets) );
+
+ // clean up
+ Vec_PtrFree( vCells );
+ Vec_PtrFree( vNets );
+}
+
+/**Function*************************************************************
+
+ Synopsis [This procedure is called before the writing start.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Abc_PlaceBegin( Abc_Ntk_t * pNtk )
+{
+ Abc_Obj_t * pObj;
+ int i;
+
+ // allocate and clean internal storage
+ nAllocSize = 5 * Abc_NtkObjNumMax(pNtk);
+ cells = REALLOC(ConcreteCell, cells, nAllocSize);
+ nets = REALLOC(ConcreteNet, nets, nAllocSize);
+ memset( cells, 0, sizeof(ConcreteCell) * nAllocSize );
+ memset( nets, 0, sizeof(ConcreteNet) * nAllocSize );
+
+ // create AbstractCells
+ // 1: pad
+ // 2: and
+ if (!abstractCells)
+ abstractCells = ALLOC(AbstractCell,2);
+
+ abstractCells[0].m_height = 1.0;
+ abstractCells[0].m_width = 1.0;
+ abstractCells[0].m_label = "pio";
+ abstractCells[0].m_pad = 1;
+
+ abstractCells[1].m_height = 1.0;
+ abstractCells[1].m_width = 1.0;
+ abstractCells[1].m_label = "and";
+ abstractCells[1].m_pad = 0;
+
+ // input pads
+ Abc_NtkForEachCi( pNtk, pObj, i )
+ Abc_PlaceCreateCell( pObj, 0 );
+
+ // ouput pads
+ Abc_NtkForEachCo( pNtk, pObj, i )
+ Abc_PlaceCreateCell( pObj, 0 );
+
+ // AND nodes
+ Abc_AigForEachAnd( pNtk, pObj, i )
+ Abc_PlaceCreateCell( pObj, 1 );
+
+ // all nets
+ Abc_NtkForEachObj( pNtk, pObj, i )
+ {
+ if ( !Abc_ObjIsCi(pObj) && !Abc_ObjIsNode(pObj) )
+ continue;
+ Abc_PlaceUpdateNet( pObj );
+ }
+
+ globalPreplace((float)0.8);
+ globalPlace();
+}
+
+/**Function*************************************************************
+
+ Synopsis [This procedure is called after the writing completes.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Abc_PlaceEnd( Abc_Ntk_t * pNtk )
+{
+ int i;
+
+
+ // clean up
+ for ( i = 0; i < nAllocSize; i++ )
+ FREE( nets[i].m_terms );
+ FREE( abstractCells );
+ FREE( cells );
+ FREE( nets );
+}
+
+////////////////////////////////////////////////////////////////////////
+/// END OF FILE ///
+////////////////////////////////////////////////////////////////////////
+
+
diff --git a/src/base/abci/abcPrint.c b/src/base/abci/abcPrint.c
index 41b9288e..4003a6d6 100644
--- a/src/base/abci/abcPrint.c
+++ b/src/base/abci/abcPrint.c
@@ -20,13 +20,24 @@
#include "abc.h"
#include "dec.h"
+#include "main.h"
+#include "mio.h"
+//#include "seq.h"
////////////////////////////////////////////////////////////////////////
/// DECLARATIONS ///
////////////////////////////////////////////////////////////////////////
+//extern int s_TotalNodes = 0;
+//extern int s_TotalChanges = 0;
+
+int s_MappingTime = 0;
+int s_MappingMem = 0;
+int s_ResubTime = 0;
+int s_ResynTime = 0;
+
////////////////////////////////////////////////////////////////////////
-/// FUNCTION DEFITIONS ///
+/// FUNCTION DEFINITIONS ///
////////////////////////////////////////////////////////////////////////
/**Function*************************************************************
@@ -44,57 +55,171 @@ void Abc_NtkPrintStats( FILE * pFile, Abc_Ntk_t * pNtk, int fFactored )
{
int Num;
- fprintf( pFile, "%-13s:", pNtk->pName );
- fprintf( pFile, " i/o = %4d/%4d", Abc_NtkPiNum(pNtk), Abc_NtkPoNum(pNtk) );
+// if ( Abc_NtkIsStrash(pNtk) )
+// Abc_AigCountNext( pNtk->pManFunc );
- if ( !Abc_NtkIsSeq(pNtk) )
- fprintf( pFile, " lat = %4d", Abc_NtkLatchNum(pNtk) );
+ fprintf( pFile, "%-13s:", pNtk->pName );
+ if ( Abc_NtkAssertNum(pNtk) )
+ fprintf( pFile, " i/o/a = %5d/%5d/%5d", Abc_NtkPiNum(pNtk), Abc_NtkPoNum(pNtk), Abc_NtkAssertNum(pNtk) );
else
- fprintf( pFile, " lat = %4d", Abc_NtkSeqLatchNum(pNtk) );
-
+ fprintf( pFile, " i/o = %5d/%5d", Abc_NtkPiNum(pNtk), Abc_NtkPoNum(pNtk) );
+ fprintf( pFile, " lat = %4d", Abc_NtkLatchNum(pNtk) );
if ( Abc_NtkIsNetlist(pNtk) )
{
fprintf( pFile, " net = %5d", Abc_NtkNetNum(pNtk) );
- fprintf( pFile, " nd = %5d", Abc_NtkNodeNum(pNtk) );
+ fprintf( pFile, " nd = %5d", Abc_NtkNodeNum(pNtk) );
+ fprintf( pFile, " wbox = %3d", Abc_NtkWhiteboxNum(pNtk) );
+ fprintf( pFile, " bbox = %3d", Abc_NtkBlackboxNum(pNtk) );
}
else if ( Abc_NtkIsStrash(pNtk) )
- {
+ {
fprintf( pFile, " and = %5d", Abc_NtkNodeNum(pNtk) );
if ( Num = Abc_NtkGetChoiceNum(pNtk) )
fprintf( pFile, " (choice = %d)", Num );
if ( Num = Abc_NtkGetExorNum(pNtk) )
fprintf( pFile, " (exor = %d)", Num );
+// if ( Num2 = Abc_NtkGetMuxNum(pNtk) )
+// fprintf( pFile, " (mux = %d)", Num2-Num );
+// if ( Num2 )
+// fprintf( pFile, " (other = %d)", Abc_NtkNodeNum(pNtk)-3*Num2 );
}
- else if ( Abc_NtkIsSeq(pNtk) )
- fprintf( pFile, " and = %5d", Abc_NtkNodeNum(pNtk) );
else
+ {
fprintf( pFile, " nd = %5d", Abc_NtkNodeNum(pNtk) );
+ fprintf( pFile, " edge = %6d", Abc_NtkGetTotalFanins(pNtk) );
+ }
- if ( Abc_NtkHasSop(pNtk) )
+ if ( Abc_NtkIsStrash(pNtk) || Abc_NtkIsNetlist(pNtk) )
+ {
+ }
+ else if ( Abc_NtkHasSop(pNtk) )
{
+
fprintf( pFile, " cube = %5d", Abc_NtkGetCubeNum(pNtk) );
// fprintf( pFile, " lit(sop) = %5d", Abc_NtkGetLitNum(pNtk) );
if ( fFactored )
fprintf( pFile, " lit(fac) = %5d", Abc_NtkGetLitFactNum(pNtk) );
}
+ else if ( Abc_NtkHasAig(pNtk) )
+ fprintf( pFile, " aig = %5d", Abc_NtkGetAigNodeNum(pNtk) );
else if ( Abc_NtkHasBdd(pNtk) )
- fprintf( pFile, " bdd = %5d", Abc_NtkGetBddNodeNum(pNtk) );
+ fprintf( pFile, " bdd = %5d", Abc_NtkGetBddNodeNum(pNtk) );
else if ( Abc_NtkHasMapping(pNtk) )
{
fprintf( pFile, " area = %5.2f", Abc_NtkGetMappedArea(pNtk) );
fprintf( pFile, " delay = %5.2f", Abc_NtkDelayTrace(pNtk) );
}
- else if ( !Abc_NtkHasAig(pNtk) )
+ else if ( !Abc_NtkHasBlackbox(pNtk) )
{
assert( 0 );
}
if ( Abc_NtkIsStrash(pNtk) )
- fprintf( pFile, " lev = %3d", Abc_AigGetLevelNum(pNtk) );
- else if ( !Abc_NtkIsSeq(pNtk) )
- fprintf( pFile, " lev = %3d", Abc_NtkGetLevelNum(pNtk) );
+ fprintf( pFile, " lev = %3d", Abc_AigLevel(pNtk) );
+ else
+ fprintf( pFile, " lev = %3d", Abc_NtkLevel(pNtk) );
fprintf( pFile, "\n" );
+
+// Abc_NtkCrossCut( pNtk );
+
+ // print the statistic into a file
+/*
+ {
+ FILE * pTable;
+ pTable = fopen( "ibm/seq_stats.txt", "a+" );
+// fprintf( pTable, "%s ", pNtk->pName );
+// fprintf( pTable, "%d ", Abc_NtkPiNum(pNtk) );
+// fprintf( pTable, "%d ", Abc_NtkPoNum(pNtk) );
+ fprintf( pTable, "%d ", Abc_NtkNodeNum(pNtk) );
+ fprintf( pTable, "%d ", Abc_NtkLatchNum(pNtk) );
+ fprintf( pTable, "%d ", Abc_NtkLevel(pNtk) );
+ fprintf( pTable, "\n" );
+ fclose( pTable );
+ }
+*/
+
+/*
+ // print the statistic into a file
+ {
+ FILE * pTable;
+ pTable = fopen( "stats.txt", "a+" );
+ fprintf( pTable, "%s ", pNtk->pSpec );
+ fprintf( pTable, "%.0f ", Abc_NtkGetMappedArea(pNtk) );
+ fprintf( pTable, "%.2f ", Abc_NtkDelayTrace(pNtk) );
+ fprintf( pTable, "\n" );
+ fclose( pTable );
+ }
+*/
+
+/*
+ // print the statistic into a file
+ {
+ FILE * pTable;
+ pTable = fopen( "x/stats_new.txt", "a+" );
+ fprintf( pTable, "%s ", pNtk->pName );
+// fprintf( pTable, "%d ", Abc_NtkPiNum(pNtk) );
+// fprintf( pTable, "%d ", Abc_NtkPoNum(pNtk) );
+// fprintf( pTable, "%d ", Abc_NtkLevel(pNtk) );
+// fprintf( pTable, "%d ", Abc_NtkNodeNum(pNtk) );
+// fprintf( pTable, "%d ", Abc_NtkGetTotalFanins(pNtk) );
+// fprintf( pTable, "%d ", Abc_NtkLatchNum(pNtk) );
+// fprintf( pTable, "%.2f ", (float)(s_MappingMem)/(float)(1<<20) );
+ fprintf( pTable, "%.2f", (float)(s_MappingTime)/(float)(CLOCKS_PER_SEC) );
+// fprintf( pTable, "%.2f", (float)(s_ResynTime)/(float)(CLOCKS_PER_SEC) );
+ fprintf( pTable, "\n" );
+ fclose( pTable );
+
+ s_ResynTime = 0;
+ }
+*/
+
+/*
+ // print the statistic into a file
+ {
+ static int Counter = 0;
+ extern int timeRetime;
+ FILE * pTable;
+ Counter++;
+ pTable = fopen( "a/ret__stats.txt", "a+" );
+ fprintf( pTable, "%s ", pNtk->pName );
+ fprintf( pTable, "%d ", Abc_NtkNodeNum(pNtk) );
+ fprintf( pTable, "%d ", Abc_NtkLatchNum(pNtk) );
+ fprintf( pTable, "%d ", Abc_NtkLevel(pNtk) );
+ fprintf( pTable, "%.2f ", (float)(timeRetime)/(float)(CLOCKS_PER_SEC) );
+ if ( Counter % 4 == 0 )
+ fprintf( pTable, "\n" );
+ fclose( pTable );
+ }
+*/
+
+/*
+ // print the statistic into a file
+ {
+ static int Counter = 0;
+ extern int timeRetime;
+ FILE * pTable;
+ Counter++;
+ pTable = fopen( "d/stats.txt", "a+" );
+ fprintf( pTable, "%s ", pNtk->pName );
+// fprintf( pTable, "%d ", Abc_NtkPiNum(pNtk) );
+// fprintf( pTable, "%d ", Abc_NtkPoNum(pNtk) );
+// fprintf( pTable, "%d ", Abc_NtkLatchNum(pNtk) );
+ fprintf( pTable, "%d ", Abc_NtkNodeNum(pNtk) );
+ fprintf( pTable, "%.2f ", (float)(timeRetime)/(float)(CLOCKS_PER_SEC) );
+ fprintf( pTable, "\n" );
+ fclose( pTable );
+ }
+*/
+
+/*
+ s_TotalNodes += Abc_NtkNodeNum(pNtk);
+ printf( "Total nodes = %6d %6.2f Mb Changes = %6d.\n",
+ s_TotalNodes, s_TotalNodes * 20.0 / (1<<20), s_TotalChanges );
+*/
+
+// if ( Abc_NtkHasSop(pNtk) )
+// printf( "The total number of cube pairs = %d.\n", Abc_NtkGetCubePairNum(pNtk) );
}
/**Function*************************************************************
@@ -116,6 +241,7 @@ void Abc_NtkPrintIo( FILE * pFile, Abc_Ntk_t * pNtk )
fprintf( pFile, "Primary inputs (%d): ", Abc_NtkPiNum(pNtk) );
Abc_NtkForEachPi( pNtk, pObj, i )
fprintf( pFile, " %s", Abc_ObjName(pObj) );
+// fprintf( pFile, " %s(%d)", Abc_ObjName(pObj), Abc_ObjFanoutNum(pObj) );
fprintf( pFile, "\n" );
fprintf( pFile, "Primary outputs (%d):", Abc_NtkPoNum(pNtk) );
@@ -125,7 +251,8 @@ void Abc_NtkPrintIo( FILE * pFile, Abc_Ntk_t * pNtk )
fprintf( pFile, "Latches (%d): ", Abc_NtkLatchNum(pNtk) );
Abc_NtkForEachLatch( pNtk, pObj, i )
- fprintf( pFile, " %s", Abc_ObjName(pObj) );
+ fprintf( pFile, " %s(%s=%s)", Abc_ObjName(pObj),
+ Abc_ObjName(Abc_ObjFanout0(pObj)), Abc_ObjName(Abc_ObjFanin0(pObj)) );
fprintf( pFile, "\n" );
}
@@ -144,34 +271,38 @@ void Abc_NtkPrintLatch( FILE * pFile, Abc_Ntk_t * pNtk )
{
Abc_Obj_t * pLatch, * pFanin;
int i, Counter0, Counter1, Counter2;
- int Init0, Init1, Init2;
+ int InitNums[4], Init;
+ assert( !Abc_NtkIsNetlist(pNtk) );
if ( Abc_NtkLatchNum(pNtk) == 0 )
{
fprintf( pFile, "The network is combinational.\n" );
return;
}
- assert( !Abc_NtkIsNetlist(pNtk) );
-
- Init0 = Init1 = Init2 = 0;
+ for ( i = 0; i < 4; i++ )
+ InitNums[i] = 0;
Counter0 = Counter1 = Counter2 = 0;
-
Abc_NtkForEachLatch( pNtk, pLatch, i )
{
- if ( Abc_LatchIsInit0(pLatch) )
- Init0++;
- else if ( Abc_LatchIsInit1(pLatch) )
- Init1++;
- else if ( Abc_LatchIsInitDc(pLatch) )
- Init2++;
+ Init = Abc_LatchInit( pLatch );
+ assert( Init < 4 );
+ InitNums[Init]++;
+
+ pFanin = Abc_ObjFanin0(Abc_ObjFanin0(pLatch));
+ if ( Abc_NtkIsLogic(pNtk) )
+ {
+ if ( !Abc_NodeIsConst(pFanin) )
+ continue;
+ }
+ else if ( Abc_NtkIsStrash(pNtk) )
+ {
+ if ( !Abc_AigNodeIsConst(pFanin) )
+ continue;
+ }
else
assert( 0 );
- pFanin = Abc_ObjFanin0(pLatch);
- if ( !Abc_ObjIsNode(pFanin) || !Abc_NodeIsConst(pFanin) )
- continue;
-
// the latch input is a constant node
Counter0++;
if ( Abc_LatchIsInitDc(pLatch) )
@@ -187,18 +318,15 @@ void Abc_NtkPrintLatch( FILE * pFile, Abc_Ntk_t * pNtk )
}
else
{
- if ( Abc_LatchIsInit1(pLatch) == Abc_NodeIsConst1(pLatch) )
+ if ( Abc_LatchIsInit1(pLatch) == Abc_NodeIsConst1(Abc_ObjFanin0(Abc_ObjFanin0(pLatch))) )
Counter2++;
}
}
-// fprintf( pFile, "%-15s: ", pNtk->pName );
-// fprintf( pFile, "L = %5d: 0 = %4d. 1 = %3d. DC = %4d. ", Abc_NtkLatchNum(pNtk), Init0, Init1, Init2 );
-// fprintf( pFile, "Con = %3d. DC = %3d. Mat = %3d. ", Counter0, Counter1, Counter2 );
-// fprintf( pFile, "SFeed = %2d.\n", Abc_NtkCountSelfFeedLatches(pNtk) );
fprintf( pFile, "%-15s: ", pNtk->pName );
- fprintf( pFile, "Lat = %5d: 0 = %4d. 1 = %3d. DC = %4d. \n", Abc_NtkLatchNum(pNtk), Init0, Init1, Init2 );
- fprintf( pFile, "Con = %3d. DC = %3d. Mat = %3d. ", Counter0, Counter1, Counter2 );
- fprintf( pFile, "SFeed = %2d.\n", Abc_NtkCountSelfFeedLatches(pNtk) );
+ fprintf( pFile, "Latch = %6d. No = %4d. Zero = %4d. One = %4d. DC = %4d.\n",
+ Abc_NtkLatchNum(pNtk), InitNums[0], InitNums[1], InitNums[2], InitNums[3] );
+ fprintf( pFile, "Const fanin = %3d. DC init = %3d. Matching init = %3d. ", Counter0, Counter1, Counter2 );
+ fprintf( pFile, "Self-feed latches = %2d.\n", -1 ); //Abc_NtkCountSelfFeedLatches(pNtk) );
}
/**Function*************************************************************
@@ -230,6 +358,7 @@ void Abc_NtkPrintFanio( FILE * pFile, Abc_Ntk_t * pNtk )
nFanouts = Abc_ObjFanoutNum( Abc_ObjFanout0(pNode) );
else
nFanouts = Abc_ObjFanoutNum(pNode);
+// nFanouts = Abc_NodeMffcSize(pNode);
if ( nFanins > vFanins->nSize || nFanouts > vFanouts->nSize )
{
nOldSize = vFanins->nSize;
@@ -301,6 +430,26 @@ void Abc_NodePrintFanio( FILE * pFile, Abc_Obj_t * pNode )
/**Function*************************************************************
+ Synopsis [Prints the MFFCs of the nodes.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Abc_NtkPrintMffc( FILE * pFile, Abc_Ntk_t * pNtk )
+{
+ Abc_Obj_t * pNode;
+ int i;
+ extern void Abc_NodeMffsConeSuppPrint( Abc_Obj_t * pNode );
+ Abc_NtkForEachNode( pNtk, pNode, i )
+ Abc_NodeMffsConeSuppPrint( pNode );
+}
+
+/**Function*************************************************************
+
Synopsis [Prints the factored form of one node.]
Description []
@@ -371,10 +520,26 @@ void Abc_NodePrintFactor( FILE * pFile, Abc_Obj_t * pNode, int fUseRealNames )
SeeAlso []
***********************************************************************/
-void Abc_NtkPrintLevel( FILE * pFile, Abc_Ntk_t * pNtk, int fProfile )
+void Abc_NtkPrintLevel( FILE * pFile, Abc_Ntk_t * pNtk, int fProfile, int fListNodes )
{
Abc_Obj_t * pNode;
- int i, Length;
+ int i, k, Length;
+
+ if ( fListNodes )
+ {
+ int nLevels;
+ nLevels = Abc_NtkLevel(pNtk);
+ printf( "Nodes by level:\n" );
+ for ( i = 0; i <= nLevels; i++ )
+ {
+ printf( "%2d : ", i );
+ Abc_NtkForEachNode( pNtk, pNode, k )
+ if ( (int)pNode->Level == i )
+ printf( " %s", Abc_ObjName(pNode) );
+ printf( "\n" );
+ }
+ return;
+ }
// print the delay profile
if ( fProfile && Abc_NtkHasMapping(pNtk) )
@@ -416,7 +581,7 @@ void Abc_NtkPrintLevel( FILE * pFile, Abc_Ntk_t * pNtk, int fProfile )
int nOutsSum, nOutsTotal;
if ( !Abc_NtkIsStrash(pNtk) )
- Abc_NtkGetLevelNum(pNtk);
+ Abc_NtkLevel(pNtk);
LevelMax = 0;
Abc_NtkForEachCo( pNtk, pNode, i )
@@ -498,6 +663,289 @@ void Abc_NodePrintLevel( FILE * pFile, Abc_Obj_t * pNode )
fprintf( pFile, "\n" );
}
+/**Function*************************************************************
+
+ Synopsis [Prints the factored form of one node.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Abc_NodePrintKMap( Abc_Obj_t * pNode, int fUseRealNames )
+{
+ Vec_Ptr_t * vNamesIn;
+ if ( fUseRealNames )
+ {
+ vNamesIn = Abc_NodeGetFaninNames(pNode);
+ Extra_PrintKMap( stdout, pNode->pNtk->pManFunc, pNode->pData, Cudd_Not(pNode->pData),
+ Abc_ObjFaninNum(pNode), NULL, 0, (char **)vNamesIn->pArray );
+ Abc_NodeFreeNames( vNamesIn );
+ }
+ else
+ Extra_PrintKMap( stdout, pNode->pNtk->pManFunc, pNode->pData, Cudd_Not(pNode->pData),
+ Abc_ObjFaninNum(pNode), NULL, 0, NULL );
+
+}
+
+/**Function*************************************************************
+
+ Synopsis [Prints statistics about gates used in the network.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Abc_NtkPrintGates( Abc_Ntk_t * pNtk, int fUseLibrary )
+{
+ Abc_Obj_t * pObj;
+ int fHasBdds, i;
+ int CountConst, CountBuf, CountInv, CountAnd, CountOr, CountOther, CounterTotal;
+ char * pSop;
+
+ if ( fUseLibrary && Abc_NtkHasMapping(pNtk) )
+ {
+ stmm_table * tTable;
+ stmm_generator * gen;
+ char * pName;
+ int * pCounter, Counter;
+ double Area, AreaTotal;
+
+ // count the gates by name
+ CounterTotal = 0;
+ tTable = stmm_init_table(strcmp, stmm_strhash);
+ Abc_NtkForEachNode( pNtk, pObj, i )
+ {
+ if ( i == 0 ) continue;
+ if ( !stmm_find_or_add( tTable, Mio_GateReadName(pObj->pData), (char ***)&pCounter ) )
+ *pCounter = 0;
+ (*pCounter)++;
+ CounterTotal++;
+ }
+ // print the gates
+ AreaTotal = Abc_NtkGetMappedArea(pNtk);
+ stmm_foreach_item( tTable, gen, (char **)&pName, (char **)&Counter )
+ {
+ Area = Counter * Mio_GateReadArea(Mio_LibraryReadGateByName(pNtk->pManFunc,pName));
+ printf( "%-12s = %8d %10.2f %6.2f %%\n", pName, Counter, Area, 100.0 * Area / AreaTotal );
+ }
+ printf( "%-12s = %8d %10.2f %6.2f %%\n", "TOTAL", CounterTotal, AreaTotal, 100.0 );
+ stmm_free_table( tTable );
+ return;
+ }
+
+ if ( Abc_NtkIsAigLogic(pNtk) )
+ return;
+
+ // transform logic functions from BDD to SOP
+ if ( fHasBdds = Abc_NtkIsBddLogic(pNtk) )
+ {
+ if ( !Abc_NtkBddToSop(pNtk, 0) )
+ {
+ printf( "Abc_NtkPrintGates(): Converting to SOPs has failed.\n" );
+ return;
+ }
+ }
+
+ // get hold of the SOP of the node
+ CountConst = CountBuf = CountInv = CountAnd = CountOr = CountOther = CounterTotal = 0;
+ Abc_NtkForEachNode( pNtk, pObj, i )
+ {
+ if ( i == 0 ) continue;
+ if ( Abc_NtkHasMapping(pNtk) )
+ pSop = Mio_GateReadSop(pObj->pData);
+ else
+ pSop = pObj->pData;
+ // collect the stats
+ if ( Abc_SopIsConst0(pSop) || Abc_SopIsConst1(pSop) )
+ CountConst++;
+ else if ( Abc_SopIsBuf(pSop) )
+ CountBuf++;
+ else if ( Abc_SopIsInv(pSop) )
+ CountInv++;
+ else if ( !Abc_SopIsComplement(pSop) && Abc_SopIsAndType(pSop) || Abc_SopIsComplement(pSop) && Abc_SopIsOrType(pSop) )
+ CountAnd++;
+ else if ( Abc_SopIsComplement(pSop) && Abc_SopIsAndType(pSop) || !Abc_SopIsComplement(pSop) && Abc_SopIsOrType(pSop) )
+ CountOr++;
+ else
+ CountOther++;
+ CounterTotal++;
+ }
+ printf( "Const = %8d %6.2f %%\n", CountConst , 100.0 * CountConst / CounterTotal );
+ printf( "Buffer = %8d %6.2f %%\n", CountBuf , 100.0 * CountBuf / CounterTotal );
+ printf( "Inverter = %8d %6.2f %%\n", CountInv , 100.0 * CountInv / CounterTotal );
+ printf( "And = %8d %6.2f %%\n", CountAnd , 100.0 * CountAnd / CounterTotal );
+ printf( "Or = %8d %6.2f %%\n", CountOr , 100.0 * CountOr / CounterTotal );
+ printf( "Other = %8d %6.2f %%\n", CountOther , 100.0 * CountOther / CounterTotal );
+ printf( "TOTAL = %8d %6.2f %%\n", CounterTotal, 100.0 * CounterTotal / CounterTotal );
+
+ // convert the network back into BDDs if this is how it was
+ if ( fHasBdds )
+ Abc_NtkSopToBdd(pNtk);
+}
+
+/**Function*************************************************************
+
+ Synopsis [Prints statistics about gates used in the network.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Abc_NtkPrintSharing( Abc_Ntk_t * pNtk )
+{
+ Vec_Ptr_t * vNodes1, * vNodes2;
+ Abc_Obj_t * pObj1, * pObj2, * pNode1, * pNode2;
+ int i, k, m, n, Counter;
+
+ // print the template
+ printf( "Statistics about sharing of logic nodes among the CO pairs.\n" );
+ printf( "(CO1,CO2)=NumShared : " );
+ // go though the CO pairs
+ Abc_NtkForEachCo( pNtk, pObj1, i )
+ {
+ vNodes1 = Abc_NtkDfsNodes( pNtk, &pObj1, 1 );
+ // mark the nodes
+ Vec_PtrForEachEntry( vNodes1, pNode1, m )
+ pNode1->fMarkA = 1;
+ // go through the second COs
+ Abc_NtkForEachCo( pNtk, pObj2, k )
+ {
+ if ( i >= k )
+ continue;
+ vNodes2 = Abc_NtkDfsNodes( pNtk, &pObj2, 1 );
+ // count the number of marked
+ Counter = 0;
+ Vec_PtrForEachEntry( vNodes2, pNode2, n )
+ Counter += pNode2->fMarkA;
+ // print
+ printf( "(%d,%d)=%d ", i, k, Counter );
+ Vec_PtrFree( vNodes2 );
+ }
+ // unmark the nodes
+ Vec_PtrForEachEntry( vNodes1, pNode1, m )
+ pNode1->fMarkA = 0;
+ Vec_PtrFree( vNodes1 );
+ }
+ printf( "\n" );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Prints info for each output cone.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Abc_NtkPrintStrSupports( Abc_Ntk_t * pNtk )
+{
+ Vec_Ptr_t * vSupp, * vNodes;
+ Abc_Obj_t * pObj;
+ int i;
+ printf( "Structural support info:\n" );
+ Abc_NtkForEachCo( pNtk, pObj, i )
+ {
+ vSupp = Abc_NtkNodeSupport( pNtk, &pObj, 1 );
+ vNodes = Abc_NtkDfsNodes( pNtk, &pObj, 1 );
+ printf( "%20s : Cone = %5d. Supp = %5d.\n",
+ Abc_ObjName(pObj), vNodes->nSize, vSupp->nSize );
+ Vec_PtrFree( vNodes );
+ Vec_PtrFree( vSupp );
+ }
+}
+
+/**Function*************************************************************
+
+ Synopsis [Prints information about the object.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Abc_ObjPrint( FILE * pFile, Abc_Obj_t * pObj )
+{
+ Abc_Obj_t * pFanin;
+ int i;
+ fprintf( pFile, "Object %5d : ", pObj->Id );
+ switch ( pObj->Type )
+ {
+ case ABC_OBJ_NONE:
+ fprintf( pFile, "NONE " );
+ break;
+ case ABC_OBJ_CONST1:
+ fprintf( pFile, "Const1 " );
+ break;
+ case ABC_OBJ_PIO:
+ fprintf( pFile, "PIO " );
+ break;
+ case ABC_OBJ_PI:
+ fprintf( pFile, "PI " );
+ break;
+ case ABC_OBJ_PO:
+ fprintf( pFile, "PO " );
+ break;
+ case ABC_OBJ_BI:
+ fprintf( pFile, "BI " );
+ break;
+ case ABC_OBJ_BO:
+ fprintf( pFile, "BO " );
+ break;
+ case ABC_OBJ_ASSERT:
+ fprintf( pFile, "Assert " );
+ break;
+ case ABC_OBJ_NET:
+ fprintf( pFile, "Net " );
+ break;
+ case ABC_OBJ_NODE:
+ fprintf( pFile, "Node " );
+ break;
+ case ABC_OBJ_LATCH:
+ fprintf( pFile, "Latch " );
+ break;
+ case ABC_OBJ_WHITEBOX:
+ fprintf( pFile, "Whitebox" );
+ break;
+ case ABC_OBJ_BLACKBOX:
+ fprintf( pFile, "Blackbox" );
+ break;
+ default:
+ assert(0);
+ break;
+ }
+ // print the fanins
+ fprintf( pFile, " Fanins ( " );
+ Abc_ObjForEachFanin( pObj, pFanin, i )
+ fprintf( pFile, "%d ", pFanin->Id );
+ fprintf( pFile, ") " );
+/*
+ fprintf( pFile, " Fanouts ( " );
+ Abc_ObjForEachFanout( pObj, pFanin, i )
+ fprintf( pFile, "%d(%c) ", pFanin->Id, Abc_NodeIsTravIdCurrent(pFanin)? '+' : '-' );
+ fprintf( pFile, ") " );
+*/
+ // print the logic function
+ if ( Abc_ObjIsNode(pObj) && Abc_NtkIsSopLogic(pObj->pNtk) )
+ fprintf( pFile, " %s", pObj->pData );
+ else
+ fprintf( pFile, "\n" );
+}
+
+
////////////////////////////////////////////////////////////////////////
/// END OF FILE ///
////////////////////////////////////////////////////////////////////////
diff --git a/src/base/abci/abcProve.c b/src/base/abci/abcProve.c
new file mode 100644
index 00000000..618b6a0f
--- /dev/null
+++ b/src/base/abci/abcProve.c
@@ -0,0 +1,341 @@
+/**CFile****************************************************************
+
+ FileName [abcProve.c]
+
+ SystemName [ABC: Logic synthesis and verification system.]
+
+ PackageName [Network and node package.]
+
+ Synopsis [Proves the miter using AIG rewriting, FRAIGing, and SAT solving.]
+
+ Author [Alan Mishchenko]
+
+ Affiliation [UC Berkeley]
+
+ Date [Ver. 1.0. Started - June 20, 2005.]
+
+ Revision [$Id: abcProve.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "abc.h"
+#include "fraig.h"
+#include "math.h"
+
+////////////////////////////////////////////////////////////////////////
+/// DECLARATIONS ///
+////////////////////////////////////////////////////////////////////////
+
+extern int Abc_NtkRefactor( Abc_Ntk_t * pNtk, int nNodeSizeMax, int nConeSizeMax, bool fUpdateLevel, bool fUseZeros, bool fUseDcs, bool fVerbose );
+extern Abc_Ntk_t * Abc_NtkFromFraig( Fraig_Man_t * pMan, Abc_Ntk_t * pNtk );
+
+static Abc_Ntk_t * Abc_NtkMiterFraig( Abc_Ntk_t * pNtk, int nBTLimit, sint64 nInspLimit, int * pRetValue, int * pNumFails, sint64 * pNumConfs, sint64 * pNumInspects );
+static void Abc_NtkMiterPrint( Abc_Ntk_t * pNtk, char * pString, int clk, int fVerbose );
+
+
+////////////////////////////////////////////////////////////////////////
+/// FUNCTION DEFINITIONS ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+ Synopsis [Attempts to solve the miter using a number of tricks.]
+
+ Description [Returns -1 if timed out; 0 if SAT; 1 if UNSAT. Returns
+ a simplified version of the original network (or a constant 0 network).
+ In case the network is not a constant zero and a SAT assignment is found,
+ pNtk->pModel contains a satisfying assignment.]
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Abc_NtkMiterProve( Abc_Ntk_t ** ppNtk, void * pPars )
+{
+ Prove_Params_t * pParams = pPars;
+ Abc_Ntk_t * pNtk, * pNtkTemp;
+ int RetValue, nIter, nSatFails, Counter, clk, timeStart = clock();
+ sint64 nSatConfs, nSatInspects, nInspectLimit;
+
+ // get the starting network
+ pNtk = *ppNtk;
+ assert( Abc_NtkIsStrash(pNtk) );
+ assert( Abc_NtkPoNum(pNtk) == 1 );
+
+ if ( pParams->fVerbose )
+ {
+ printf( "RESOURCE LIMITS: Iterations = %d. Rewriting = %s. Fraiging = %s.\n",
+ pParams->nItersMax, pParams->fUseRewriting? "yes":"no", pParams->fUseFraiging? "yes":"no" );
+ printf( "Miter = %d (%3.1f). Rwr = %d (%3.1f). Fraig = %d (%3.1f). Last = %d.\n",
+ pParams->nMiteringLimitStart, pParams->nMiteringLimitMulti,
+ pParams->nRewritingLimitStart, pParams->nRewritingLimitMulti,
+ pParams->nFraigingLimitStart, pParams->nFraigingLimitMulti, pParams->nMiteringLimitLast );
+ }
+
+ // if SAT only, solve without iteration
+ if ( !pParams->fUseRewriting && !pParams->fUseFraiging )
+ {
+ clk = clock();
+ RetValue = Abc_NtkMiterSat( pNtk, (sint64)pParams->nMiteringLimitLast, (sint64)0, 0, NULL, NULL );
+ Abc_NtkMiterPrint( pNtk, "SAT solving", clk, pParams->fVerbose );
+ *ppNtk = pNtk;
+ return RetValue;
+ }
+
+ // check the current resource limits
+ for ( nIter = 0; nIter < pParams->nItersMax; nIter++ )
+ {
+ if ( pParams->fVerbose )
+ {
+ printf( "ITERATION %2d : Confs = %6d. FraigBTL = %3d. \n", nIter+1,
+ (int)(pParams->nMiteringLimitStart * pow(pParams->nMiteringLimitMulti,nIter)),
+ (int)(pParams->nFraigingLimitStart * pow(pParams->nFraigingLimitMulti,nIter)) );
+ fflush( stdout );
+ }
+
+ // try brute-force SAT
+ clk = clock();
+ nInspectLimit = pParams->nTotalInspectLimit? pParams->nTotalInspectLimit - pParams->nTotalInspectsMade : 0;
+ RetValue = Abc_NtkMiterSat( pNtk, (sint64)(pParams->nMiteringLimitStart * pow(pParams->nMiteringLimitMulti,nIter)), (sint64)nInspectLimit, 0, &nSatConfs, &nSatInspects );
+ Abc_NtkMiterPrint( pNtk, "SAT solving", clk, pParams->fVerbose );
+ if ( RetValue >= 0 )
+ break;
+
+ // add to the number of backtracks and inspects
+ pParams->nTotalBacktracksMade += nSatConfs;
+ pParams->nTotalInspectsMade += nSatInspects;
+ // check if global resource limit is reached
+ if ( (pParams->nTotalBacktrackLimit && pParams->nTotalBacktracksMade >= pParams->nTotalBacktrackLimit) ||
+ (pParams->nTotalInspectLimit && pParams->nTotalInspectsMade >= pParams->nTotalInspectLimit) )
+ {
+ printf( "Reached global limit on conflicts/inspects. Quitting.\n" );
+ *ppNtk = pNtk;
+ return -1;
+ }
+
+ // try rewriting
+ if ( pParams->fUseRewriting )
+ {
+ clk = clock();
+ Counter = (int)(pParams->nRewritingLimitStart * pow(pParams->nRewritingLimitMulti,nIter));
+// Counter = 1;
+ while ( 1 )
+ {
+/*
+ extern Abc_Ntk_t * Abc_NtkIvyResyn( Abc_Ntk_t * pNtk, int fUpdateLevel, int fVerbose );
+ pNtk = Abc_NtkIvyResyn( pNtkTemp = pNtk, 0, 0 ); Abc_NtkDelete( pNtkTemp );
+ if ( (RetValue = Abc_NtkMiterIsConstant(pNtk)) >= 0 )
+ break;
+ if ( --Counter == 0 )
+ break;
+*/
+/*
+ Abc_NtkRewrite( pNtk, 0, 0, 0, 0, 0 );
+ if ( (RetValue = Abc_NtkMiterIsConstant(pNtk)) >= 0 )
+ break;
+ if ( --Counter == 0 )
+ break;
+*/
+ Abc_NtkRewrite( pNtk, 0, 0, 0, 0, 0 );
+ if ( (RetValue = Abc_NtkMiterIsConstant(pNtk)) >= 0 )
+ break;
+ if ( --Counter == 0 )
+ break;
+ Abc_NtkRefactor( pNtk, 10, 16, 0, 0, 0, 0 );
+ if ( (RetValue = Abc_NtkMiterIsConstant(pNtk)) >= 0 )
+ break;
+ if ( --Counter == 0 )
+ break;
+ pNtk = Abc_NtkBalance( pNtkTemp = pNtk, 0, 0, 0 ); Abc_NtkDelete( pNtkTemp );
+ if ( (RetValue = Abc_NtkMiterIsConstant(pNtk)) >= 0 )
+ break;
+ if ( --Counter == 0 )
+ break;
+ }
+ Abc_NtkMiterPrint( pNtk, "Rewriting ", clk, pParams->fVerbose );
+ }
+
+ if ( pParams->fUseFraiging )
+ {
+ // try FRAIGing
+ clk = clock();
+ nInspectLimit = pParams->nTotalInspectLimit? pParams->nTotalInspectLimit - pParams->nTotalInspectsMade : 0;
+ pNtk = Abc_NtkMiterFraig( pNtkTemp = pNtk, (int)(pParams->nFraigingLimitStart * pow(pParams->nFraigingLimitMulti,nIter)), nInspectLimit, &RetValue, &nSatFails, &nSatConfs, &nSatInspects ); Abc_NtkDelete( pNtkTemp );
+ Abc_NtkMiterPrint( pNtk, "FRAIGing ", clk, pParams->fVerbose );
+// printf( "NumFails = %d\n", nSatFails );
+ if ( RetValue >= 0 )
+ break;
+
+ // add to the number of backtracks and inspects
+ pParams->nTotalBacktracksMade += nSatConfs;
+ pParams->nTotalInspectsMade += nSatInspects;
+ // check if global resource limit is reached
+ if ( (pParams->nTotalBacktrackLimit && pParams->nTotalBacktracksMade >= pParams->nTotalBacktrackLimit) ||
+ (pParams->nTotalInspectLimit && pParams->nTotalInspectsMade >= pParams->nTotalInspectLimit) )
+ {
+ printf( "Reached global limit on conflicts/inspects. Quitting.\n" );
+ *ppNtk = pNtk;
+ return -1;
+ }
+ }
+
+ }
+
+ // try to prove it using brute force SAT
+ if ( RetValue < 0 && pParams->fUseBdds )
+ {
+ if ( pParams->fVerbose )
+ {
+ printf( "Attempting BDDs with node limit %d ...\n", pParams->nBddSizeLimit );
+ fflush( stdout );
+ }
+ clk = clock();
+ pNtk = Abc_NtkCollapse( pNtkTemp = pNtk, pParams->nBddSizeLimit, 0, pParams->fBddReorder, 0 );
+ if ( pNtk )
+ {
+ Abc_NtkDelete( pNtkTemp );
+ RetValue = ( (Abc_NtkNodeNum(pNtk) == 1) && (Abc_ObjFanin0(Abc_NtkPo(pNtk,0))->pData == Cudd_ReadLogicZero(pNtk->pManFunc)) );
+ }
+ else
+ pNtk = pNtkTemp;
+ Abc_NtkMiterPrint( pNtk, "BDD building", clk, pParams->fVerbose );
+ }
+
+ if ( RetValue < 0 )
+ {
+ if ( pParams->fVerbose )
+ {
+ printf( "Attempting SAT with conflict limit %d ...\n", pParams->nMiteringLimitLast );
+ fflush( stdout );
+ }
+ clk = clock();
+ nInspectLimit = pParams->nTotalInspectLimit? pParams->nTotalInspectLimit - pParams->nTotalInspectsMade : 0;
+ RetValue = Abc_NtkMiterSat( pNtk, (sint64)pParams->nMiteringLimitLast, (sint64)nInspectLimit, 0, NULL, NULL );
+ Abc_NtkMiterPrint( pNtk, "SAT solving", clk, pParams->fVerbose );
+ }
+
+ // assign the model if it was proved by rewriting (const 1 miter)
+ if ( RetValue == 0 && pNtk->pModel == NULL )
+ {
+ pNtk->pModel = ALLOC( int, Abc_NtkCiNum(pNtk) );
+ memset( pNtk->pModel, 0, sizeof(int) * Abc_NtkCiNum(pNtk) );
+ }
+ *ppNtk = pNtk;
+ return RetValue;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Attempts to solve the miter using a number of tricks.]
+
+ Description [Returns -1 if timed out; 0 if SAT; 1 if UNSAT.]
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Abc_Ntk_t * Abc_NtkMiterFraig( Abc_Ntk_t * pNtk, int nBTLimit, sint64 nInspLimit, int * pRetValue, int * pNumFails, sint64 * pNumConfs, sint64 * pNumInspects )
+{
+ Abc_Ntk_t * pNtkNew;
+ Fraig_Params_t Params, * pParams = &Params;
+ Fraig_Man_t * pMan;
+ int nWords1, nWords2, nWordsMin, RetValue;
+ int * pModel;
+
+ // to determine the number of simulation patterns
+ // use the following strategy
+ // at least 64 words (32 words random and 32 words dynamic)
+ // no more than 256M for one circuit (128M + 128M)
+ nWords1 = 32;
+ nWords2 = (1<<27) / (Abc_NtkNodeNum(pNtk) + Abc_NtkCiNum(pNtk));
+ nWordsMin = ABC_MIN( nWords1, nWords2 );
+
+ // set the FRAIGing parameters
+ Fraig_ParamsSetDefault( pParams );
+ pParams->nPatsRand = nWordsMin * 32; // the number of words of random simulation info
+ pParams->nPatsDyna = nWordsMin * 32; // the number of words of dynamic simulation info
+ pParams->nBTLimit = nBTLimit; // the max number of backtracks
+ pParams->nSeconds = -1; // the runtime limit
+ pParams->fTryProve = 0; // do not try to prove the final miter
+ pParams->fDoSparse = 1; // try proving sparse functions
+ pParams->fVerbose = 0;
+ pParams->nInspLimit = nInspLimit;
+
+ // transform the target into a fraig
+ pMan = Abc_NtkToFraig( pNtk, pParams, 0, 0 );
+ Fraig_ManProveMiter( pMan );
+ RetValue = Fraig_ManCheckMiter( pMan );
+
+ // create the network
+ pNtkNew = Abc_NtkFromFraig( pMan, pNtk );
+
+ // save model
+ if ( RetValue == 0 )
+ {
+ pModel = Fraig_ManReadModel( pMan );
+ FREE( pNtkNew->pModel );
+ pNtkNew->pModel = ALLOC( int, Abc_NtkCiNum(pNtkNew) );
+ memcpy( pNtkNew->pModel, pModel, sizeof(int) * Abc_NtkCiNum(pNtkNew) );
+ }
+
+ // save the return values
+ *pRetValue = RetValue;
+ *pNumFails = Fraig_ManReadSatFails( pMan );
+ *pNumConfs = Fraig_ManReadConflicts( pMan );
+ *pNumInspects = Fraig_ManReadInspects( pMan );
+
+ // delete the fraig manager
+ Fraig_ManFree( pMan );
+ return pNtkNew;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Attempts to solve the miter using a number of tricks.]
+
+ Description [Returns -1 if timed out; 0 if SAT; 1 if UNSAT.]
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Abc_NtkMiterPrint( Abc_Ntk_t * pNtk, char * pString, int clk, int fVerbose )
+{
+ if ( !fVerbose )
+ return;
+ printf( "Nodes = %7d. Levels = %4d. ", Abc_NtkNodeNum(pNtk),
+ Abc_NtkIsStrash(pNtk)? Abc_AigLevel(pNtk) : Abc_NtkLevel(pNtk) );
+ PRT( pString, clock() - clk );
+}
+
+
+/**Function*************************************************************
+
+ Synopsis [Implements resynthesis for CEC.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Abc_Ntk_t * Abc_NtkMiterRwsat( Abc_Ntk_t * pNtk )
+{
+ Abc_Ntk_t * pNtkTemp;
+ Abc_NtkRewrite( pNtk, 0, 0, 0, 0, 0 );
+ pNtk = Abc_NtkBalance( pNtkTemp = pNtk, 0, 0, 0 ); Abc_NtkDelete( pNtkTemp );
+ Abc_NtkRewrite( pNtk, 0, 0, 0, 0, 0 );
+ Abc_NtkRefactor( pNtk, 10, 16, 0, 0, 0, 0 );
+ return pNtk;
+}
+
+
+////////////////////////////////////////////////////////////////////////
+/// END OF FILE ///
+////////////////////////////////////////////////////////////////////////
+
+
diff --git a/src/base/abci/abcQbf.c b/src/base/abci/abcQbf.c
new file mode 100644
index 00000000..b839f812
--- /dev/null
+++ b/src/base/abci/abcQbf.c
@@ -0,0 +1,260 @@
+/**CFile****************************************************************
+
+ FileName [abcQbf.c]
+
+ SystemName [ABC: Logic synthesis and verification system.]
+
+ PackageName [Network and node package.]
+
+ Synopsis [Implementation of a simple QBF solver.]
+
+ Author [Alan Mishchenko]
+
+ Affiliation [UC Berkeley]
+
+ Date [Ver. 1.0. Started - June 20, 2005.]
+
+ Revision [$Id: abcQbf.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "abc.h"
+
+/*
+ Implementation of a simple QBF solver along the lines of
+ A. Solar-Lezama, L. Tancau, R. Bodik, V. Saraswat, and S. Seshia,
+ "Combinatorial sketching for finite programs", 12th International
+ Conference on Architectural Support for Programming Languages and
+ Operating Systems (ASPLOS 2006), San Jose, CA, October 2006.
+*/
+
+////////////////////////////////////////////////////////////////////////
+/// DECLARATIONS ///
+////////////////////////////////////////////////////////////////////////
+
+static void Abc_NtkModelToVector( Abc_Ntk_t * pNtk, Vec_Int_t * vPiValues );
+static void Abc_NtkVectorClearPars( Vec_Int_t * vPiValues, int nPars );
+static void Abc_NtkVectorClearVars( Abc_Ntk_t * pNtk, Vec_Int_t * vPiValues, int nPars );
+static void Abc_NtkVectorPrintPars( Vec_Int_t * vPiValues, int nPars );
+static void Abc_NtkVectorPrintVars( Abc_Ntk_t * pNtk, Vec_Int_t * vPiValues, int nPars );
+
+////////////////////////////////////////////////////////////////////////
+/// FUNCTION DEFINITIONS ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+ Synopsis [Solve the QBF problem EpAx[M(p,x)].]
+
+ Description [Variables p go first, followed by variable x.
+ The number of parameters is nPars. The miter is in pNtk.
+ The miter expresses EQUALITY of the implementation and spec.]
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Abc_NtkQbf( Abc_Ntk_t * pNtk, int nPars, int fVerbose )
+{
+ Abc_Ntk_t * pNtkVer, * pNtkSyn, * pNtkSyn2, * pNtkTemp;
+ Vec_Int_t * vPiValues;
+ int clkTotal = clock(), clkS, clkV;
+ int nIters, nIterMax = 500, nInputs, RetValue, fFound = 0;
+
+ assert( Abc_NtkIsStrash(pNtk) );
+ assert( Abc_NtkIsComb(pNtk) );
+ assert( Abc_NtkPoNum(pNtk) == 1 );
+ assert( nPars > 0 && nPars < Abc_NtkPiNum(pNtk) );
+ assert( Abc_NtkPiNum(pNtk)-nPars < 32 );
+ nInputs = Abc_NtkPiNum(pNtk) - nPars;
+
+ // initialize the synthesized network with 0000-combination
+ vPiValues = Vec_IntStart( Abc_NtkPiNum(pNtk) );
+ Abc_NtkVectorClearPars( vPiValues, nPars );
+ pNtkSyn = Abc_NtkMiterCofactor( pNtk, vPiValues );
+ if ( fVerbose )
+ {
+ printf( "Iter %2d : ", 0 );
+ printf( "AIG = %6d ", Abc_NtkNodeNum(pNtkSyn) );
+ Abc_NtkVectorPrintVars( pNtk, vPiValues, nPars );
+ printf( "\n" );
+ }
+
+ // iteratively solve
+ for ( nIters = 0; nIters < nIterMax; nIters++ )
+ {
+ // solve the synthesis instance
+clkS = clock();
+ RetValue = Abc_NtkMiterSat( pNtkSyn, 0, 0, 0, NULL, NULL );
+clkS = clock() - clkS;
+ if ( RetValue == 0 )
+ Abc_NtkModelToVector( pNtkSyn, vPiValues );
+ if ( RetValue == 1 )
+ {
+ break;
+ }
+ if ( RetValue == -1 )
+ {
+ printf( "Synthesis timed out.\n" );
+ break;
+ }
+ // there is a counter-example
+
+ // construct the verification instance
+ Abc_NtkVectorClearVars( pNtk, vPiValues, nPars );
+ pNtkVer = Abc_NtkMiterCofactor( pNtk, vPiValues );
+ // complement the output
+ Abc_ObjXorFaninC( Abc_NtkPo(pNtkVer,0), 0 );
+
+ // solve the verification instance
+clkV = clock();
+ RetValue = Abc_NtkMiterSat( pNtkVer, 0, 0, 0, NULL, NULL );
+clkV = clock() - clkV;
+ if ( RetValue == 0 )
+ Abc_NtkModelToVector( pNtkVer, vPiValues );
+ Abc_NtkDelete( pNtkVer );
+ if ( RetValue == 1 )
+ {
+ fFound = 1;
+ break;
+ }
+ if ( RetValue == -1 )
+ {
+ printf( "Verification timed out.\n" );
+ break;
+ }
+ // there is a counter-example
+
+ // create a new synthesis network
+ Abc_NtkVectorClearPars( vPiValues, nPars );
+ pNtkSyn2 = Abc_NtkMiterCofactor( pNtk, vPiValues );
+ // add to the synthesis instance
+ pNtkSyn = Abc_NtkMiterAnd( pNtkTemp = pNtkSyn, pNtkSyn2, 0, 0 );
+ Abc_NtkDelete( pNtkSyn2 );
+ Abc_NtkDelete( pNtkTemp );
+
+ if ( fVerbose )
+ {
+ printf( "Iter %2d : ", nIters+1 );
+ printf( "AIG = %6d ", Abc_NtkNodeNum(pNtkSyn) );
+ Abc_NtkVectorPrintVars( pNtk, vPiValues, nPars );
+ printf( " " );
+// PRTn( "Syn", clkS );
+ PRT( "Ver", clkV );
+ }
+ }
+ Abc_NtkDelete( pNtkSyn );
+ // report the results
+ if ( fFound )
+ {
+ printf( "Parameters: " );
+ Abc_NtkVectorPrintPars( vPiValues, nPars );
+ printf( "\n" );
+ printf( "Solved after %d interations. ", nIters );
+ }
+ else if ( nIters == nIterMax )
+ printf( "Unsolved after %d interations. ", nIters );
+ else
+ printf( "Implementation does not exist. " );
+ PRT( "Total runtime", clock() - clkTotal );
+ Vec_IntFree( vPiValues );
+}
+
+
+/**Function*************************************************************
+
+ Synopsis [Translates model into the vector of values.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Abc_NtkModelToVector( Abc_Ntk_t * pNtk, Vec_Int_t * vPiValues )
+{
+ int * pModel, i;
+ pModel = pNtk->pModel;
+ for ( i = 0; i < Abc_NtkPiNum(pNtk); i++ )
+ Vec_IntWriteEntry( vPiValues, i, pModel[i] );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Clears parameters.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Abc_NtkVectorClearPars( Vec_Int_t * vPiValues, int nPars )
+{
+ int i;
+ for ( i = 0; i < nPars; i++ )
+ Vec_IntWriteEntry( vPiValues, i, -1 );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Clears variables.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Abc_NtkVectorClearVars( Abc_Ntk_t * pNtk, Vec_Int_t * vPiValues, int nPars )
+{
+ int i;
+ for ( i = nPars; i < Abc_NtkPiNum(pNtk); i++ )
+ Vec_IntWriteEntry( vPiValues, i, -1 );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Clears variables.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Abc_NtkVectorPrintPars( Vec_Int_t * vPiValues, int nPars )
+{
+ int i;
+ for ( i = 0; i < nPars; i++ )
+ printf( "%d", Vec_IntEntry(vPiValues,i) );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Clears variables.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Abc_NtkVectorPrintVars( Abc_Ntk_t * pNtk, Vec_Int_t * vPiValues, int nPars )
+{
+ int i;
+ for ( i = nPars; i < Abc_NtkPiNum(pNtk); i++ )
+ printf( "%d", Vec_IntEntry(vPiValues,i) );
+}
+
+////////////////////////////////////////////////////////////////////////
+/// END OF FILE ///
+////////////////////////////////////////////////////////////////////////
+
+
diff --git a/src/base/abci/abcQuant.c b/src/base/abci/abcQuant.c
new file mode 100644
index 00000000..0f2bd72f
--- /dev/null
+++ b/src/base/abci/abcQuant.c
@@ -0,0 +1,419 @@
+/**CFile****************************************************************
+
+ FileName [abcQuant.c]
+
+ SystemName [ABC: Logic synthesis and verification system.]
+
+ PackageName [Network and node package.]
+
+ Synopsis [AIG-based variable quantification.]
+
+ Author [Alan Mishchenko]
+
+ Affiliation [UC Berkeley]
+
+ Date [Ver. 1.0. Started - June 20, 2005.]
+
+ Revision [$Id: abcQuant.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "abc.h"
+
+////////////////////////////////////////////////////////////////////////
+/// DECLARATIONS ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+/// FUNCTION DEFINITIONS ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+ Synopsis [Performs fast synthesis.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Abc_NtkSynthesize( Abc_Ntk_t ** ppNtk, int fMoreEffort )
+{
+ Abc_Ntk_t * pNtk, * pNtkTemp;
+
+ pNtk = *ppNtk;
+
+ Abc_NtkRewrite( pNtk, 0, 0, 0, 0, 0 );
+ Abc_NtkRefactor( pNtk, 10, 16, 0, 0, 0, 0 );
+ pNtk = Abc_NtkBalance( pNtkTemp = pNtk, 0, 0, 0 );
+ Abc_NtkDelete( pNtkTemp );
+
+ if ( fMoreEffort )
+ {
+ Abc_NtkRewrite( pNtk, 0, 0, 0, 0, 0 );
+ Abc_NtkRefactor( pNtk, 10, 16, 0, 0, 0, 0 );
+ pNtk = Abc_NtkBalance( pNtkTemp = pNtk, 0, 0, 0 );
+ Abc_NtkDelete( pNtkTemp );
+ }
+
+ *ppNtk = pNtk;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Existentially quantifies one variable.]
+
+ Description []
+
+ SideEffects [This procedure creates dangling nodes in the AIG.]
+
+ SeeAlso []
+
+***********************************************************************/
+int Abc_NtkQuantify( Abc_Ntk_t * pNtk, int fUniv, int iVar, int fVerbose )
+{
+ Vec_Ptr_t * vNodes;
+ Abc_Obj_t * pObj, * pNext, * pFanin;
+ int i;
+ assert( Abc_NtkIsStrash(pNtk) );
+ assert( iVar < Abc_NtkCiNum(pNtk) );
+
+ // collect the internal nodes
+ pObj = Abc_NtkCi( pNtk, iVar );
+ vNodes = Abc_NtkDfsReverseNodes( pNtk, &pObj, 1 );
+
+ // assign the cofactors of the CI node to be constants
+ pObj->pCopy = Abc_ObjNot( Abc_AigConst1(pNtk) );
+ pObj->pData = Abc_AigConst1(pNtk);
+
+ // quantify the nodes
+ Vec_PtrForEachEntry( vNodes, pObj, i )
+ {
+ for ( pNext = pObj? pObj->pCopy : pObj; pObj; pObj = pNext, pNext = pObj? pObj->pCopy : pObj )
+ {
+ pFanin = Abc_ObjFanin0(pObj);
+ if ( !Abc_NodeIsTravIdCurrent(pFanin) )
+ pFanin->pCopy = pFanin->pData = pFanin;
+ pFanin = Abc_ObjFanin1(pObj);
+ if ( !Abc_NodeIsTravIdCurrent(pFanin) )
+ pFanin->pCopy = pFanin->pData = pFanin;
+ pObj->pCopy = Abc_AigAnd( pNtk->pManFunc, Abc_ObjChild0Copy(pObj), Abc_ObjChild1Copy(pObj) );
+ pObj->pData = Abc_AigAnd( pNtk->pManFunc, Abc_ObjChild0Data(pObj), Abc_ObjChild1Data(pObj) );
+ }
+ }
+ Vec_PtrFree( vNodes );
+
+ // update the affected COs
+ Abc_NtkForEachCo( pNtk, pObj, i )
+ {
+ if ( !Abc_NodeIsTravIdCurrent(pObj) )
+ continue;
+ pFanin = Abc_ObjFanin0(pObj);
+ // get the result of quantification
+ if ( fUniv )
+ pNext = Abc_AigAnd( pNtk->pManFunc, Abc_ObjChild0Copy(pObj), Abc_ObjChild0Data(pObj) );
+ else
+ pNext = Abc_AigOr( pNtk->pManFunc, Abc_ObjChild0Copy(pObj), Abc_ObjChild0Data(pObj) );
+ pNext = Abc_ObjNotCond( pNext, Abc_ObjFaninC0(pObj) );
+ if ( Abc_ObjRegular(pNext) == pFanin )
+ continue;
+ // update the fanins of the CO
+ Abc_ObjPatchFanin( pObj, pFanin, pNext );
+// if ( Abc_ObjFanoutNum(pFanin) == 0 )
+// Abc_AigDeleteNode( pNtk->pManFunc, pFanin );
+ }
+
+ // make sure the node has no fanouts
+// pObj = Abc_NtkCi( pNtk, iVar );
+// assert( Abc_ObjFanoutNum(pObj) == 0 );
+ return 1;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Constructs the transition relation.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Abc_Ntk_t * Abc_NtkTransRel( Abc_Ntk_t * pNtk, int fInputs, int fVerbose )
+{
+ char Buffer[1000];
+ Vec_Ptr_t * vPairs;
+ Abc_Ntk_t * pNtkNew;
+ Abc_Obj_t * pObj, * pMiter;
+ int i, nLatches;
+ int fSynthesis = 1;
+
+ assert( Abc_NtkIsStrash(pNtk) );
+ assert( Abc_NtkLatchNum(pNtk) );
+ nLatches = Abc_NtkLatchNum(pNtk);
+ // start the network
+ pNtkNew = Abc_NtkAlloc( ABC_NTK_STRASH, ABC_FUNC_AIG, 1 );
+ // duplicate the name and the spec
+ sprintf( Buffer, "%s_TR", pNtk->pName );
+ pNtkNew->pName = Extra_UtilStrsav(pNtk->pName);
+// pNtkNew->pSpec = Extra_UtilStrsav(pNtk->pSpec);
+ Abc_NtkCleanCopy( pNtk );
+ // create current state variables
+ Abc_NtkForEachLatchOutput( pNtk, pObj, i )
+ {
+ pObj->pCopy = Abc_NtkCreatePi(pNtkNew);
+ Abc_ObjAssignName( pObj->pCopy, Abc_ObjName(pObj), NULL );
+ }
+ // create next state variables
+ Abc_NtkForEachLatchInput( pNtk, pObj, i )
+ Abc_ObjAssignName( Abc_NtkCreatePi(pNtkNew), Abc_ObjName(pObj), NULL );
+ // create PI variables
+ Abc_NtkForEachPi( pNtk, pObj, i )
+ Abc_NtkDupObj( pNtkNew, pObj, 1 );
+ // create the PO
+ Abc_NtkCreatePo( pNtkNew );
+ // restrash the nodes (assuming a topological order of the old network)
+ Abc_AigConst1(pNtk)->pCopy = Abc_AigConst1(pNtkNew);
+ Abc_NtkForEachNode( pNtk, pObj, i )
+ pObj->pCopy = Abc_AigAnd( pNtkNew->pManFunc, Abc_ObjChild0Copy(pObj), Abc_ObjChild1Copy(pObj) );
+ // create the function of the primary output
+ assert( Abc_NtkBoxNum(pNtk) == Abc_NtkLatchNum(pNtk) );
+ vPairs = Vec_PtrAlloc( 2*nLatches );
+ Abc_NtkForEachLatchInput( pNtk, pObj, i )
+ {
+ Vec_PtrPush( vPairs, Abc_ObjChild0Copy(pObj) );
+ Vec_PtrPush( vPairs, Abc_NtkPi(pNtkNew, i+nLatches) );
+ }
+ pMiter = Abc_AigMiter( pNtkNew->pManFunc, vPairs );
+ Vec_PtrFree( vPairs );
+ // add the primary output
+ Abc_ObjAddFanin( Abc_NtkPo(pNtkNew,0), Abc_ObjNot(pMiter) );
+ Abc_ObjAssignName( Abc_NtkPo(pNtkNew,0), "rel", NULL );
+
+ // quantify inputs
+ if ( fInputs )
+ {
+ assert( Abc_NtkPiNum(pNtkNew) == Abc_NtkPiNum(pNtk) + 2*nLatches );
+ for ( i = Abc_NtkPiNum(pNtkNew) - 1; i >= 2*nLatches; i-- )
+// for ( i = 2*nLatches; i < Abc_NtkPiNum(pNtkNew); i++ )
+ {
+ Abc_NtkQuantify( pNtkNew, 0, i, fVerbose );
+// if ( fSynthesis && (i % 3 == 2) )
+ if ( fSynthesis )
+ {
+ Abc_NtkCleanData( pNtkNew );
+ Abc_AigCleanup( pNtkNew->pManFunc );
+ Abc_NtkSynthesize( &pNtkNew, 1 );
+ }
+// printf( "Var = %3d. Nodes = %6d. ", Abc_NtkPiNum(pNtkNew) - 1 - i, Abc_NtkNodeNum(pNtkNew) );
+// printf( "Var = %3d. Nodes = %6d. ", i - 2*nLatches, Abc_NtkNodeNum(pNtkNew) );
+ }
+// printf( "\n" );
+ Abc_NtkCleanData( pNtkNew );
+ Abc_AigCleanup( pNtkNew->pManFunc );
+ for ( i = Abc_NtkPiNum(pNtkNew) - 1; i >= 2*nLatches; i-- )
+ {
+ pObj = Abc_NtkPi( pNtkNew, i );
+ assert( Abc_ObjFanoutNum(pObj) == 0 );
+ Abc_NtkDeleteObj( pObj );
+ }
+ }
+
+ // check consistency of the network
+ if ( !Abc_NtkCheck( pNtkNew ) )
+ {
+ printf( "Abc_NtkTransRel: The network check has failed.\n" );
+ Abc_NtkDelete( pNtkNew );
+ return NULL;
+ }
+ return pNtkNew;
+}
+
+
+/**Function*************************************************************
+
+ Synopsis [Performs one image computation.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Abc_Ntk_t * Abc_NtkInitialState( Abc_Ntk_t * pNtk )
+{
+ Abc_Ntk_t * pNtkNew;
+ Abc_Obj_t * pMiter;
+ int i, nVars = Abc_NtkPiNum(pNtk)/2;
+ assert( Abc_NtkIsStrash(pNtk) );
+ // start the new network
+ pNtkNew = Abc_NtkStartFrom( pNtk, ABC_NTK_STRASH, ABC_FUNC_AIG );
+ // compute the all-zero state in terms of the CS variables
+ pMiter = Abc_AigConst1(pNtkNew);
+ for ( i = 0; i < nVars; i++ )
+ pMiter = Abc_AigAnd( pNtkNew->pManFunc, pMiter, Abc_ObjNot( Abc_NtkPi(pNtkNew, i) ) );
+ // add the PO
+ Abc_ObjAddFanin( Abc_NtkPo(pNtkNew,0), pMiter );
+ return pNtkNew;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Swaps current state and next state variables.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Abc_Ntk_t * Abc_NtkSwapVariables( Abc_Ntk_t * pNtk )
+{
+ Abc_Ntk_t * pNtkNew;
+ Abc_Obj_t * pMiter, * pObj, * pObj0, * pObj1;
+ int i, nVars = Abc_NtkPiNum(pNtk)/2;
+ assert( Abc_NtkIsStrash(pNtk) );
+ // start the new network
+ pNtkNew = Abc_NtkStartFrom( pNtk, ABC_NTK_STRASH, ABC_FUNC_AIG );
+ // update the PIs
+ for ( i = 0; i < nVars; i++ )
+ {
+ pObj0 = Abc_NtkPi( pNtk, i );
+ pObj1 = Abc_NtkPi( pNtk, i+nVars );
+ pMiter = pObj0->pCopy;
+ pObj0->pCopy = pObj1->pCopy;
+ pObj1->pCopy = pMiter;
+ }
+ // restrash
+ Abc_NtkForEachNode( pNtk, pObj, i )
+ pObj->pCopy = Abc_AigAnd( pNtkNew->pManFunc, Abc_ObjChild0Copy(pObj), Abc_ObjChild1Copy(pObj) );
+ // add the PO
+ pMiter = Abc_ObjChild0Copy( Abc_NtkPo(pNtk,0) );
+ Abc_ObjAddFanin( Abc_NtkPo(pNtkNew,0), pMiter );
+ return pNtkNew;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Performs reachability analisys.]
+
+ Description [Assumes that the input is the transition relation.]
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Abc_Ntk_t * Abc_NtkReachability( Abc_Ntk_t * pNtkRel, int nIters, int fVerbose )
+{
+ Abc_Obj_t * pObj;
+ Abc_Ntk_t * pNtkFront, * pNtkReached, * pNtkNext, * pNtkTemp;
+ int clk, i, v, nVars, nNodesOld, nNodesNew, nNodesPrev;
+ int fFixedPoint = 0;
+ int fSynthesis = 1;
+ int fMoreEffort = 1;
+
+ assert( Abc_NtkIsStrash(pNtkRel) );
+ assert( Abc_NtkLatchNum(pNtkRel) == 0 );
+ assert( Abc_NtkPiNum(pNtkRel) % 2 == 0 );
+
+ // compute the network composed of the initial states
+ pNtkFront = Abc_NtkInitialState( pNtkRel );
+ pNtkReached = Abc_NtkDup( pNtkFront );
+//Abc_NtkShow( pNtkReached, 0, 0, 0 );
+
+// if ( fVerbose )
+// printf( "Transition relation = %6d.\n", Abc_NtkNodeNum(pNtkRel) );
+
+ // perform iterations of reachability analysis
+ nNodesPrev = Abc_NtkNodeNum(pNtkFront);
+ nVars = Abc_NtkPiNum(pNtkRel)/2;
+ for ( i = 0; i < nIters; i++ )
+ {
+ clk = clock();
+ // get the set of next states
+ pNtkNext = Abc_NtkMiterAnd( pNtkRel, pNtkFront, 0, 0 );
+ Abc_NtkDelete( pNtkFront );
+ // quantify the current state variables
+ for ( v = 0; v < nVars; v++ )
+ {
+ Abc_NtkQuantify( pNtkNext, 0, v, fVerbose );
+ if ( fSynthesis && (v % 3 == 2) )
+ {
+ Abc_NtkCleanData( pNtkNext );
+ Abc_AigCleanup( pNtkNext->pManFunc );
+ Abc_NtkSynthesize( &pNtkNext, fMoreEffort );
+ }
+ }
+ Abc_NtkCleanData( pNtkNext );
+ Abc_AigCleanup( pNtkNext->pManFunc );
+ if ( fSynthesis )
+ Abc_NtkSynthesize( &pNtkNext, 1 );
+ // map the next states into the current states
+ pNtkNext = Abc_NtkSwapVariables( pNtkTemp = pNtkNext );
+ Abc_NtkDelete( pNtkTemp );
+ // check the termination condition
+ if ( Abc_ObjFanin0(Abc_NtkPo(pNtkNext,0)) == Abc_AigConst1(pNtkNext) )
+ {
+ fFixedPoint = 1;
+ printf( "Fixed point is reached!\n" );
+ Abc_NtkDelete( pNtkNext );
+ break;
+ }
+ // compute new front
+ pNtkFront = Abc_NtkMiterAnd( pNtkNext, pNtkReached, 0, 1 );
+ Abc_NtkDelete( pNtkNext );
+ // add the reached states
+ pNtkReached = Abc_NtkMiterAnd( pNtkTemp = pNtkReached, pNtkFront, 1, 0 );
+ Abc_NtkDelete( pNtkTemp );
+ // compress the size of Front
+ nNodesOld = Abc_NtkNodeNum(pNtkFront);
+ if ( fSynthesis )
+ {
+ Abc_NtkSynthesize( &pNtkFront, fMoreEffort );
+ Abc_NtkSynthesize( &pNtkReached, fMoreEffort );
+ }
+ nNodesNew = Abc_NtkNodeNum(pNtkFront);
+ // print statistics
+ if ( fVerbose )
+ {
+ printf( "I = %3d : Reach = %6d Fr = %6d FrM = %6d %7.2f %% ",
+ i + 1, Abc_NtkNodeNum(pNtkReached), nNodesOld, nNodesNew, 100.0*(nNodesNew-nNodesPrev)/nNodesPrev );
+ PRT( "T", clock() - clk );
+ }
+ nNodesPrev = Abc_NtkNodeNum(pNtkFront);
+ }
+ if ( !fFixedPoint )
+ fprintf( stdout, "Reachability analysis stopped after %d iterations.\n", nIters );
+
+ // complement the output to represent the set of unreachable states
+ Abc_ObjXorFaninC( Abc_NtkPo(pNtkReached,0), 0 );
+
+ // remove next state variables
+ for ( i = 2*nVars - 1; i >= nVars; i-- )
+ {
+ pObj = Abc_NtkPi( pNtkReached, i );
+ assert( Abc_ObjFanoutNum(pObj) == 0 );
+ Abc_NtkDeleteObj( pObj );
+ }
+
+ // check consistency of the network
+ if ( !Abc_NtkCheck( pNtkReached ) )
+ {
+ printf( "Abc_NtkReachability: The network check has failed.\n" );
+ Abc_NtkDelete( pNtkReached );
+ return NULL;
+ }
+ return pNtkReached;
+}
+
+////////////////////////////////////////////////////////////////////////
+/// END OF FILE ///
+////////////////////////////////////////////////////////////////////////
+
+
diff --git a/src/base/abci/abcRec.c b/src/base/abci/abcRec.c
new file mode 100644
index 00000000..a6ec6981
--- /dev/null
+++ b/src/base/abci/abcRec.c
@@ -0,0 +1,1173 @@
+/**CFile****************************************************************
+
+ FileName [abcRec.c]
+
+ SystemName [ABC: Logic synthesis and verification system.]
+
+ PackageName [Network and node package.]
+
+ Synopsis [Record of semi-canonical AIG subgraphs.]
+
+ Author [Alan Mishchenko]
+
+ Affiliation [UC Berkeley]
+
+ Date [Ver. 1.0. Started - June 20, 2005.]
+
+ Revision [$Id: abcRec.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "abc.h"
+#include "if.h"
+#include "kit.h"
+
+////////////////////////////////////////////////////////////////////////
+/// DECLARATIONS ///
+////////////////////////////////////////////////////////////////////////
+
+typedef struct Abc_ManRec_t_ Abc_ManRec_t;
+struct Abc_ManRec_t_
+{
+ Abc_Ntk_t * pNtk; // the record
+ Vec_Ptr_t * vTtElems; // the elementary truth tables
+ Vec_Ptr_t * vTtNodes; // the node truth tables
+ Abc_Obj_t ** pBins; // hash table mapping truth tables into nodes
+ int nBins; // the number of allocated bins
+ int nVars; // the number of variables
+ int nVarsInit; // the number of variables requested initially
+ int nWords; // the number of TT words
+ int nCuts; // the max number of cuts to use
+ // temporaries
+ int * pBytes; // temporary storage for minterms
+ int * pMints; // temporary storage for minterm counters
+ unsigned * pTemp1; // temporary truth table
+ unsigned * pTemp2; // temporary truth table
+ Vec_Ptr_t * vNodes; // the temporary nodes
+ Vec_Ptr_t * vTtTemps; // the truth tables for the internal nodes of the cut
+ Vec_Ptr_t * vLabels; // temporary storage for AIG node labels
+ Vec_Str_t * vCosts; // temporary storage for costs
+ Vec_Int_t * vMemory; // temporary memory for truth tables
+ // statistics
+ int nTried; // the number of cuts tried
+ int nFilterSize; // the number of same structures
+ int nFilterRedund; // the number of same structures
+ int nFilterVolume; // the number of same structures
+ int nFilterTruth; // the number of same structures
+ int nFilterError; // the number of same structures
+ int nFilterSame; // the number of same structures
+ int nAdded; // the number of subgraphs added
+ int nAddedFuncs; // the number of functions added
+ // rewriting
+ int nFunsFound; // the found functions
+ int nFunsNotFound; // the missing functions
+ // runtime
+ int timeCollect; // the runtime to canonicize
+ int timeTruth; // the runtime to canonicize
+ int timeCanon; // the runtime to canonicize
+ int timeOther; // the runtime to canonicize
+ int timeTotal; // the runtime to canonicize
+};
+
+// the truth table is canonicized in such a way that for (00000) its value is 0
+
+static Abc_Obj_t ** Abc_NtkRecTableLookup( Abc_ManRec_t * p, unsigned * pTruth, int nVars );
+static int Abc_NtkRecComputeTruth( Abc_Obj_t * pObj, Vec_Ptr_t * vTtNodes, int nVars );
+static int Abc_NtkRecAddCutCheckCycle_rec( Abc_Obj_t * pRoot, Abc_Obj_t * pObj );
+
+static Abc_ManRec_t * s_pMan = NULL;
+
+////////////////////////////////////////////////////////////////////////
+/// FUNCTION DEFINITIONS ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+ Synopsis [Starts the record for the given network.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Abc_NtkRecIsRunning()
+{
+ return s_pMan != NULL;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Starts the record for the given network.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Abc_NtkRecVarNum()
+{
+ return (s_pMan != NULL)? s_pMan->nVars : -1;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Starts the record for the given network.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Vec_Int_t * Abc_NtkRecMemory()
+{
+ return s_pMan->vMemory;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Starts the record for the given network.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Abc_NtkRecStart( Abc_Ntk_t * pNtk, int nVars, int nCuts )
+{
+ Abc_ManRec_t * p;
+ Abc_Obj_t * pObj, ** ppSpot;
+ char Buffer[10];
+ unsigned * pTruth;
+ int i, RetValue;
+ int clkTotal = clock(), clk;
+
+ assert( s_pMan == NULL );
+ if ( pNtk == NULL )
+ {
+ assert( nVars > 2 && nVars <= 16 );
+ pNtk = Abc_NtkAlloc( ABC_NTK_STRASH, ABC_FUNC_AIG, 1 );
+ pNtk->pName = Extra_UtilStrsav( "record" );
+ }
+ else
+ {
+ if ( Abc_NtkGetChoiceNum(pNtk) > 0 )
+ {
+ printf( "The starting record should be a network without choice nodes.\n" );
+ return;
+ }
+ if ( Abc_NtkPiNum(pNtk) > 16 )
+ {
+ printf( "The starting record should be a network with no more than %d primary inputs.\n", 16 );
+ return;
+ }
+ if ( Abc_NtkPiNum(pNtk) > nVars )
+ printf( "The starting record has %d inputs (warning only).\n", Abc_NtkPiNum(pNtk) );
+ pNtk = Abc_NtkDup( pNtk );
+ }
+ // create the primary inputs
+ for ( i = Abc_NtkPiNum(pNtk); i < nVars; i++ )
+ {
+ pObj = Abc_NtkCreatePi( pNtk );
+ Buffer[0] = 'a' + i;
+ Buffer[1] = 0;
+ Abc_ObjAssignName( pObj, Buffer, NULL );
+ }
+ Abc_NtkCleanCopy( pNtk );
+ Abc_NtkCleanEquiv( pNtk );
+
+ // start the manager
+ p = ALLOC( Abc_ManRec_t, 1 );
+ memset( p, 0, sizeof(Abc_ManRec_t) );
+ p->pNtk = pNtk;
+ p->nVars = Abc_NtkPiNum(pNtk);
+ p->nWords = Kit_TruthWordNum( p->nVars );
+ p->nCuts = nCuts;
+ p->nVarsInit = nVars;
+
+ // create elementary truth tables
+ p->vTtElems = Vec_PtrAlloc( 0 ); assert( p->vTtElems->pArray == NULL );
+ p->vTtElems->nSize = p->nVars;
+ p->vTtElems->nCap = p->nVars;
+ p->vTtElems->pArray = (void *)Extra_TruthElementary( p->nVars );
+
+ // allocate room for node truth tables
+ if ( Abc_NtkObjNum(pNtk) > (1<<14) )
+ p->vTtNodes = Vec_PtrAllocSimInfo( 2 * Abc_NtkObjNum(pNtk), p->nWords );
+ else
+ p->vTtNodes = Vec_PtrAllocSimInfo( 1<<14, p->nWords );
+
+ // create hash table
+ p->nBins = 50011;
+ p->pBins = ALLOC( Abc_Obj_t *, p->nBins );
+ memset( p->pBins, 0, sizeof(Abc_Obj_t *) * p->nBins );
+
+ // set elementary tables
+ Kit_TruthFill( Vec_PtrEntry(p->vTtNodes, 0), p->nVars );
+ Abc_NtkForEachPi( pNtk, pObj, i )
+ Kit_TruthCopy( Vec_PtrEntry(p->vTtNodes, pObj->Id), Vec_PtrEntry(p->vTtElems, i), p->nVars );
+
+ // compute the tables
+clk = clock();
+ Abc_AigForEachAnd( pNtk, pObj, i )
+ {
+ RetValue = Abc_NtkRecComputeTruth( pObj, p->vTtNodes, p->nVars );
+ assert( RetValue );
+ }
+p->timeTruth += clock() - clk;
+
+ // insert the PO nodes into the table
+ Abc_NtkForEachPo( pNtk, pObj, i )
+ {
+ p->nTried++;
+ p->nAdded++;
+
+ pObj = Abc_ObjFanin0(pObj);
+ pTruth = Vec_PtrEntry( p->vTtNodes, pObj->Id );
+
+ if ( pTruth[0] == 1128481603 )
+ {
+ int x = 0;
+ }
+
+ // add the resulting truth table to the hash table
+ ppSpot = Abc_NtkRecTableLookup( p, pTruth, p->nVars );
+ assert( pObj->pEquiv == NULL );
+ assert( pObj->pCopy == NULL );
+ if ( *ppSpot == NULL )
+ {
+ p->nAddedFuncs++;
+ *ppSpot = pObj;
+ }
+ else
+ {
+ pObj->pEquiv = (*ppSpot)->pEquiv;
+ (*ppSpot)->pEquiv = (Hop_Obj_t *)pObj;
+ if ( !Abc_NtkRecAddCutCheckCycle_rec(*ppSpot, pObj) )
+ printf( "Loop!\n" );
+ }
+ }
+
+ // temporaries
+ p->pBytes = ALLOC( int, 4*p->nWords );
+ p->pMints = ALLOC( int, 2*p->nVars );
+ p->pTemp1 = ALLOC( unsigned, p->nWords );
+ p->pTemp2 = ALLOC( unsigned, p->nWords );
+ p->vNodes = Vec_PtrAlloc( 100 );
+ p->vTtTemps = Vec_PtrAllocSimInfo( 64, p->nWords );
+ p->vMemory = Vec_IntAlloc( Abc_TruthWordNum(p->nVars) * 1000 );
+
+ // set the manager
+ s_pMan = p;
+p->timeTotal += clock() - clkTotal;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Returns the given record.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Abc_NtkRecStop()
+{
+ assert( s_pMan != NULL );
+ if ( s_pMan->pNtk )
+ Abc_NtkDelete( s_pMan->pNtk );
+ Vec_PtrFree( s_pMan->vTtNodes );
+ Vec_PtrFree( s_pMan->vTtElems );
+ free( s_pMan->pBins );
+
+ // temporaries
+ free( s_pMan->pBytes );
+ free( s_pMan->pMints );
+ free( s_pMan->pTemp1 );
+ free( s_pMan->pTemp2 );
+ Vec_PtrFree( s_pMan->vNodes );
+ Vec_PtrFree( s_pMan->vTtTemps );
+ if ( s_pMan->vLabels )
+ Vec_PtrFree( s_pMan->vLabels );
+ if ( s_pMan->vCosts )
+ Vec_StrFree( s_pMan->vCosts );
+ Vec_IntFree( s_pMan->vMemory );
+
+ free( s_pMan );
+ s_pMan = NULL;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Returns the given record.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Abc_Ntk_t * Abc_NtkRecUse()
+{
+ Abc_ManRec_t * p = s_pMan;
+ Abc_Ntk_t * pNtk = p->pNtk;
+ assert( p != NULL );
+ Abc_NtkRecPs();
+ p->pNtk = NULL;
+ Abc_NtkRecStop();
+ return pNtk;
+}
+
+static inline void Abc_ObjSetMax( Abc_Obj_t * pObj, int Value ) { assert( pObj->Level < 0xff ); pObj->Level = (Value << 8) | (pObj->Level & 0xff); }
+static inline void Abc_ObjClearMax( Abc_Obj_t * pObj ) { pObj->Level = (pObj->Level & 0xff); }
+static inline int Abc_ObjGetMax( Abc_Obj_t * pObj ) { return (pObj->Level >> 8) & 0xff; }
+
+/**Function*************************************************************
+
+ Synopsis [Print statistics about the current record.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Abc_NtkRecPs()
+{
+ int Counter, Counters[17] = {0};
+ int CounterS, CountersS[17] = {0};
+ Abc_ManRec_t * p = s_pMan;
+ Abc_Ntk_t * pNtk = p->pNtk;
+ Abc_Obj_t * pObj, * pEntry, * pTemp;
+ int i;
+
+ // set the max PI number
+ Abc_NtkForEachPi( pNtk, pObj, i )
+ Abc_ObjSetMax( pObj, i+1 );
+ Abc_AigForEachAnd( pNtk, pObj, i )
+ Abc_ObjSetMax( pObj, ABC_MAX( Abc_ObjGetMax(Abc_ObjFanin0(pObj)), Abc_ObjGetMax(Abc_ObjFanin1(pObj)) ) );
+ // go through the table
+ Counter = CounterS = 0;
+ for ( i = 0; i < p->nBins; i++ )
+ for ( pEntry = p->pBins[i]; pEntry; pEntry = pEntry->pCopy )
+ {
+ Counters[ Abc_ObjGetMax(pEntry) ]++;
+ Counter++;
+ for ( pTemp = pEntry; pTemp; pTemp = (Abc_Obj_t *)pTemp->pEquiv )
+ {
+ assert( Abc_ObjGetMax(pTemp) == Abc_ObjGetMax(pEntry) );
+ CountersS[ Abc_ObjGetMax(pTemp) ]++;
+ CounterS++;
+ }
+ }
+// printf( "Functions = %d. Expected = %d.\n", Counter, p->nAddedFuncs );
+// printf( "Subgraphs = %d. Expected = %d.\n", CounterS, p->nAdded );
+ assert( Counter == p->nAddedFuncs );
+ assert( CounterS == p->nAdded );
+
+ // clean
+ Abc_NtkForEachObj( pNtk, pObj, i )
+ {
+ Abc_ObjClearMax( pObj );
+ }
+
+ printf( "The record with %d AND nodes in %d subgraphs for %d functions with %d inputs:\n",
+ Abc_NtkNodeNum(pNtk), Abc_NtkPoNum(pNtk), p->nAddedFuncs, Abc_NtkPiNum(pNtk) );
+ for ( i = 0; i <= 16; i++ )
+ {
+ if ( Counters[i] )
+ printf( "Inputs = %2d. Funcs = %8d. Subgrs = %8d. Ratio = %6.2f.\n", i, Counters[i], CountersS[i], 1.0*CountersS[i]/Counters[i] );
+ }
+
+ printf( "Subgraphs tried = %8d. (%6.2f %%)\n", p->nTried, !p->nTried? 0 : 100.0*p->nTried/p->nTried );
+ printf( "Subgraphs filtered by support size = %8d. (%6.2f %%)\n", p->nFilterSize, !p->nTried? 0 : 100.0*p->nFilterSize/p->nTried );
+ printf( "Subgraphs filtered by structural redundancy = %8d. (%6.2f %%)\n", p->nFilterRedund, !p->nTried? 0 : 100.0*p->nFilterRedund/p->nTried );
+ printf( "Subgraphs filtered by volume = %8d. (%6.2f %%)\n", p->nFilterVolume, !p->nTried? 0 : 100.0*p->nFilterVolume/p->nTried );
+ printf( "Subgraphs filtered by TT redundancy = %8d. (%6.2f %%)\n", p->nFilterTruth, !p->nTried? 0 : 100.0*p->nFilterTruth/p->nTried );
+ printf( "Subgraphs filtered by error = %8d. (%6.2f %%)\n", p->nFilterError, !p->nTried? 0 : 100.0*p->nFilterError/p->nTried );
+ printf( "Subgraphs filtered by isomorphism = %8d. (%6.2f %%)\n", p->nFilterSame, !p->nTried? 0 : 100.0*p->nFilterSame/p->nTried );
+ printf( "Subgraphs added = %8d. (%6.2f %%)\n", p->nAdded, !p->nTried? 0 : 100.0*p->nAdded/p->nTried );
+ printf( "Functions added = %8d. (%6.2f %%)\n", p->nAddedFuncs, !p->nTried? 0 : 100.0*p->nAddedFuncs/p->nTried );
+
+ p->timeOther = p->timeTotal - p->timeCollect - p->timeTruth - p->timeCanon;
+ PRTP( "Collecting nodes ", p->timeCollect, p->timeTotal );
+ PRTP( "Computing truth ", p->timeTruth, p->timeTotal );
+ PRTP( "Canonicizing ", p->timeCanon, p->timeTotal );
+ PRTP( "Other ", p->timeOther, p->timeTotal );
+ PRTP( "TOTAL ", p->timeTotal, p->timeTotal );
+ if ( p->nFunsFound )
+ printf( "During rewriting found = %d and not found = %d functions.\n", p->nFunsFound, p->nFunsNotFound );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Filters the current record.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Abc_NtkRecFilter( int iVar, int iPlus )
+{
+}
+
+/**Function*************************************************************
+
+ Synopsis [Returns the hash key.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+static inline unsigned Abc_NtkRecTableHash( unsigned * pTruth, int nVars, int nBins, int * pPrimes )
+{
+ int i, nWords = Kit_TruthWordNum( nVars );
+ unsigned uHash = 0;
+ for ( i = 0; i < nWords; i++ )
+ uHash ^= pTruth[i] * pPrimes[i & 0x7];
+ return uHash % nBins;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Returns the given record.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Abc_Obj_t ** Abc_NtkRecTableLookup( Abc_ManRec_t * p, unsigned * pTruth, int nVars )
+{
+ static int s_Primes[10] = { 1291, 1699, 2357, 4177, 5147, 5647, 6343, 7103, 7873, 8147 };
+ Abc_Obj_t ** ppSpot, * pEntry;
+ ppSpot = p->pBins + Abc_NtkRecTableHash( pTruth, nVars, p->nBins, s_Primes );
+ for ( pEntry = *ppSpot; pEntry; ppSpot = &pEntry->pCopy, pEntry = pEntry->pCopy )
+ if ( Kit_TruthIsEqualWithPhase(Vec_PtrEntry(p->vTtNodes, pEntry->Id), pTruth, nVars) )
+ return ppSpot;
+ return ppSpot;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Computes the truth table of the node.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Abc_NtkRecComputeTruth( Abc_Obj_t * pObj, Vec_Ptr_t * vTtNodes, int nVars )
+{
+ unsigned * pTruth, * pTruth0, * pTruth1;
+ int RetValue;
+ assert( Abc_ObjIsNode(pObj) );
+ pTruth = Vec_PtrEntry( vTtNodes, pObj->Id );
+ pTruth0 = Vec_PtrEntry( vTtNodes, Abc_ObjFaninId0(pObj) );
+ pTruth1 = Vec_PtrEntry( vTtNodes, Abc_ObjFaninId1(pObj) );
+ Kit_TruthAndPhase( pTruth, pTruth0, pTruth1, nVars, Abc_ObjFaninC0(pObj), Abc_ObjFaninC1(pObj) );
+ assert( (pTruth[0] & 1) == pObj->fPhase );
+ RetValue = ((pTruth[0] & 1) == pObj->fPhase);
+ return RetValue;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Performs renoding as technology mapping.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Abc_NtkRecAdd( Abc_Ntk_t * pNtk )
+{
+ extern Abc_Ntk_t * Abc_NtkIf( Abc_Ntk_t * pNtk, If_Par_t * pPars );
+ extern int Abc_NtkRecAddCut( If_Man_t * pIfMan, If_Obj_t * pRoot, If_Cut_t * pCut );
+
+ If_Par_t Pars, * pPars = &Pars;
+ Abc_Ntk_t * pNtkNew;
+ int clk = clock();
+
+ if ( Abc_NtkGetChoiceNum( pNtk ) )
+ printf( "Performing renoding with choices.\n" );
+
+ // set defaults
+ memset( pPars, 0, sizeof(If_Par_t) );
+ // user-controlable paramters
+ pPars->nLutSize = s_pMan->nVarsInit;
+ pPars->nCutsMax = s_pMan->nCuts;
+ pPars->nFlowIters = 0;
+ pPars->nAreaIters = 0;
+ pPars->DelayTarget = -1;
+ pPars->fPreprocess = 0;
+ pPars->fArea = 1;
+ pPars->fFancy = 0;
+ pPars->fExpRed = 0;
+ pPars->fLatchPaths = 0;
+ pPars->fSeqMap = 0;
+ pPars->fVerbose = 0;
+ // internal parameters
+ pPars->fTruth = 0;
+ pPars->fUsePerm = 0;
+ pPars->nLatches = 0;
+ pPars->pLutLib = NULL; // Abc_FrameReadLibLut();
+ pPars->pTimesArr = NULL;
+ pPars->pTimesArr = NULL;
+ pPars->fUseBdds = 0;
+ pPars->fUseSops = 0;
+ pPars->fUseCnfs = 0;
+ pPars->fUseMv = 0;
+ pPars->pFuncCost = NULL;
+ pPars->pFuncUser = Abc_NtkRecAddCut;
+
+ // perform recording
+ pNtkNew = Abc_NtkIf( pNtk, pPars );
+ Abc_NtkDelete( pNtkNew );
+s_pMan->timeTotal += clock() - clk;
+
+// if ( !Abc_NtkCheck( s_pMan->pNtk ) )
+// printf( "Abc_NtkRecAdd: The network check has failed.\n" );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Adds the cut function to the internal storage.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Abc_NtkRecCollectNodes_rec( If_Obj_t * pNode, Vec_Ptr_t * vNodes )
+{
+ if ( pNode->fMark )
+ return;
+ pNode->fMark = 1;
+ assert( If_ObjIsAnd(pNode) );
+ Abc_NtkRecCollectNodes_rec( If_ObjFanin0(pNode), vNodes );
+ Abc_NtkRecCollectNodes_rec( If_ObjFanin1(pNode), vNodes );
+ Vec_PtrPush( vNodes, pNode );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Adds the cut function to the internal storage.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Abc_NtkRecCollectNodes( If_Man_t * pIfMan, If_Obj_t * pRoot, If_Cut_t * pCut, Vec_Ptr_t * vNodes )
+{
+ If_Obj_t * pLeaf;
+ int i, RetValue = 1;
+
+ // collect the internal nodes of the cut
+ Vec_PtrClear( vNodes );
+ If_CutForEachLeaf( pIfMan, pCut, pLeaf, i )
+ {
+ Vec_PtrPush( vNodes, pLeaf );
+ assert( pLeaf->fMark == 0 );
+ pLeaf->fMark = 1;
+ }
+
+ // collect other nodes
+ Abc_NtkRecCollectNodes_rec( pRoot, vNodes );
+
+ // check if there are leaves, such that both of their fanins are marked
+ // this indicates a redundant cut
+ If_CutForEachLeaf( pIfMan, pCut, pLeaf, i )
+ {
+ if ( !If_ObjIsAnd(pLeaf) )
+ continue;
+ if ( If_ObjFanin0(pLeaf)->fMark && If_ObjFanin1(pLeaf)->fMark )
+ {
+ RetValue = 0;
+ break;
+ }
+ }
+
+ // clean the mark
+ Vec_PtrForEachEntry( vNodes, pLeaf, i )
+ pLeaf->fMark = 0;
+/*
+ if ( pRoot->Id == 2639 )
+ {
+ // print the cut
+ Vec_PtrForEachEntry( vNodes, pLeaf, i )
+ {
+ if ( If_ObjIsAnd(pLeaf) )
+ printf( "%4d = %c%4d & %c%4d\n", pLeaf->Id,
+ (If_ObjFaninC0(pLeaf)? '-':'+'), If_ObjFanin0(pLeaf)->Id,
+ (If_ObjFaninC1(pLeaf)? '-':'+'), If_ObjFanin1(pLeaf)->Id );
+ else
+ printf( "%4d = pi\n", pLeaf->Id );
+ }
+ printf( "\n" );
+ }
+*/
+ return RetValue;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Computes truth tables of nodes in the cut.]
+
+ Description [Returns 0 if the TT does not depend on some cut variables.
+ Or if the TT can be expressed simpler using other nodes.]
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Abc_NtkRecCutTruth( Vec_Ptr_t * vNodes, int nLeaves, Vec_Ptr_t * vTtTemps, Vec_Ptr_t * vTtElems )
+{
+ unsigned * pSims, * pSims0, * pSims1;
+ unsigned * pTemp = s_pMan->pTemp2;
+ unsigned uWord;
+ If_Obj_t * pObj, * pObj2, * pRoot;
+ int i, k, nLimit, nInputs = s_pMan->nVars;
+
+ assert( Vec_PtrSize(vNodes) > nLeaves );
+
+ // set the elementary truth tables and compute the truth tables of the nodes
+ Vec_PtrForEachEntry( vNodes, pObj, i )
+ {
+ pObj->pCopy = Vec_PtrEntry(vTtTemps, i);
+ pSims = (unsigned *)pObj->pCopy;
+ if ( i < nLeaves )
+ {
+ Kit_TruthCopy( pSims, Vec_PtrEntry(vTtElems, i), nInputs );
+ continue;
+ }
+ assert( If_ObjIsAnd(pObj) );
+ // get hold of the simulation information
+ pSims0 = (unsigned *)If_ObjFanin0(pObj)->pCopy;
+ pSims1 = (unsigned *)If_ObjFanin1(pObj)->pCopy;
+ // simulate the node
+ Kit_TruthAndPhase( pSims, pSims0, pSims1, nInputs, If_ObjFaninC0(pObj), If_ObjFaninC1(pObj) );
+ }
+
+ // check the support size
+ pRoot = Vec_PtrEntryLast( vNodes );
+ pSims = (unsigned *)pRoot->pCopy;
+ if ( Kit_TruthSupport(pSims, nInputs) != Kit_BitMask(nLeaves) )
+ return 0;
+
+ // make sure none of the nodes has the same simulation info as the output
+ // check pairwise comparisons
+ nLimit = Vec_PtrSize(vNodes) - 1;
+ Vec_PtrForEachEntryStop( vNodes, pObj, i, nLimit )
+ {
+ pSims0 = (unsigned *)pObj->pCopy;
+ if ( Kit_TruthIsEqualWithPhase(pSims, pSims0, nInputs) )
+ return 0;
+ Vec_PtrForEachEntryStop( vNodes, pObj2, k, i )
+ {
+ if ( (If_ObjFanin0(pRoot) == pObj && If_ObjFanin1(pRoot) == pObj2) ||
+ (If_ObjFanin1(pRoot) == pObj && If_ObjFanin0(pRoot) == pObj2) )
+ continue;
+ pSims1 = (unsigned *)pObj2->pCopy;
+
+ uWord = pSims0[0] & pSims1[0];
+ if ( pSims[0] == uWord || pSims[0] == ~uWord )
+ {
+ Kit_TruthAndPhase( pTemp, pSims0, pSims1, nInputs, 0, 0 );
+ if ( Kit_TruthIsEqualWithPhase(pSims, pTemp, nInputs) )
+ return 0;
+ }
+
+ uWord = pSims0[0] & ~pSims1[0];
+ if ( pSims[0] == uWord || pSims[0] == ~uWord )
+ {
+ Kit_TruthAndPhase( pTemp, pSims0, pSims1, nInputs, 0, 1 );
+ if ( Kit_TruthIsEqualWithPhase(pSims, pTemp, nInputs) )
+ return 0;
+ }
+
+ uWord = ~pSims0[0] & pSims1[0];
+ if ( pSims[0] == uWord || pSims[0] == ~uWord )
+ {
+ Kit_TruthAndPhase( pTemp, pSims0, pSims1, nInputs, 1, 0 );
+ if ( Kit_TruthIsEqualWithPhase(pSims, pTemp, nInputs) )
+ return 0;
+ }
+
+ uWord = ~pSims0[0] & ~pSims1[0];
+ if ( pSims[0] == uWord || pSims[0] == ~uWord )
+ {
+ Kit_TruthAndPhase( pTemp, pSims0, pSims1, nInputs, 1, 1 );
+ if ( Kit_TruthIsEqualWithPhase(pSims, pTemp, nInputs) )
+ return 0;
+ }
+ }
+ }
+ return 1;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Adds the cut function to the internal storage.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Abc_NtkRecAddCutCheckCycle_rec( Abc_Obj_t * pRoot, Abc_Obj_t * pObj )
+{
+ assert( pRoot->Level > 0 );
+ if ( pObj->Level < pRoot->Level )
+ return 1;
+ if ( pObj == pRoot )
+ return 0;
+ if ( !Abc_NtkRecAddCutCheckCycle_rec(pRoot, Abc_ObjFanin0(pObj)) )
+ return 0;
+ if ( !Abc_NtkRecAddCutCheckCycle_rec(pRoot, Abc_ObjFanin1(pObj)) )
+ return 0;
+ return 1;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Adds the cut function to the internal storage.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Abc_NtkRecAddCut( If_Man_t * pIfMan, If_Obj_t * pRoot, If_Cut_t * pCut )
+{
+ static int s_MaxSize[16] = { 0 };
+ char Buffer[40], Name[20], Truth[20];
+ char pCanonPerm[16];
+ Abc_Obj_t * pObj, * pFanin0, * pFanin1, ** ppSpot, * pObjPo;
+ Abc_Ntk_t * pAig = s_pMan->pNtk;
+ If_Obj_t * pIfObj;
+ Vec_Ptr_t * vNodes = s_pMan->vNodes;
+ unsigned * pInOut = s_pMan->pTemp1;
+ unsigned * pTemp = s_pMan->pTemp2;
+ unsigned * pTruth;
+ int i, RetValue, nNodes, nNodesBeg, nInputs = s_pMan->nVars, nLeaves = If_CutLeaveNum(pCut);
+ unsigned uCanonPhase;
+ int clk;
+
+ if ( pRoot->Id == 2639 )
+ {
+ int y = 0;
+ }
+
+ assert( nInputs <= 16 );
+ assert( nInputs == (int)pCut->nLimit );
+ s_pMan->nTried++;
+
+ // skip small cuts
+ if ( nLeaves < 3 )
+ {
+ s_pMan->nFilterSize++;
+ return 1;
+ }
+
+ // collect internal nodes and skip redundant cuts
+clk = clock();
+ RetValue = Abc_NtkRecCollectNodes( pIfMan, pRoot, pCut, vNodes );
+s_pMan->timeCollect += clock() - clk;
+ if ( !RetValue )
+ {
+ s_pMan->nFilterRedund++;
+ return 1;
+ }
+
+ // skip cuts with very large volume
+ if ( Vec_PtrSize(vNodes) > nLeaves + 3*(nLeaves-1) + s_MaxSize[nLeaves] )
+ {
+ s_pMan->nFilterVolume++;
+ return 1;
+ }
+
+ // compute truth table and skip the redundant structures
+clk = clock();
+ RetValue = Abc_NtkRecCutTruth( vNodes, nLeaves, s_pMan->vTtTemps, s_pMan->vTtElems );
+s_pMan->timeTruth += clock() - clk;
+ if ( !RetValue )
+ {
+ s_pMan->nFilterTruth++;
+ return 1;
+ }
+
+ // copy the truth table
+ Kit_TruthCopy( pInOut, (unsigned *)pRoot->pCopy, nInputs );
+
+ // set permutation
+ for ( i = 0; i < nInputs; i++ )
+ pCanonPerm[i] = i;
+
+ // semi-canonicize the truth table
+clk = clock();
+ uCanonPhase = Kit_TruthSemiCanonicize( pInOut, pTemp, nInputs, pCanonPerm, (short *)s_pMan->pMints );
+s_pMan->timeCanon += clock() - clk;
+ // pCanonPerm and uCanonPhase show what was the variable corresponding to each var in the current truth
+
+ // go through the variables in the new truth table
+ for ( i = 0; i < nLeaves; i++ )
+ {
+ // get hold of the corresponding leaf
+ pIfObj = If_ManObj( pIfMan, pCut->pLeaves[pCanonPerm[i]] );
+ // get hold of the corresponding new node
+ pObj = Abc_NtkPi( pAig, i );
+ pObj = Abc_ObjNotCond( pObj, (uCanonPhase & (1 << i)) );
+ // map them
+ pIfObj->pCopy = pObj;
+/*
+ if ( pRoot->Id == 2639 )
+ {
+ unsigned uSupp;
+ printf( "Node %6d : ", pIfObj->Id );
+ printf( "Support " );
+ uSupp = Kit_TruthSupport(Vec_PtrEntry( s_pMan->vTtNodes, Abc_ObjRegular(pObj)->Id ), nInputs);
+ Extra_PrintBinary( stdout, &uSupp, nInputs );
+ printf( " " );
+ Extra_PrintBinary( stdout, Vec_PtrEntry( s_pMan->vTtNodes, Abc_ObjRegular(pObj)->Id ), 1<<6 );
+ printf( "\n" );
+ }
+*/
+ }
+
+ // build the node and compute its truth table
+ nNodesBeg = Abc_NtkObjNumMax( pAig );
+ Vec_PtrForEachEntryStart( vNodes, pIfObj, i, nLeaves )
+ {
+ pFanin0 = Abc_ObjNotCond( If_ObjFanin0(pIfObj)->pCopy, If_ObjFaninC0(pIfObj) );
+ pFanin1 = Abc_ObjNotCond( If_ObjFanin1(pIfObj)->pCopy, If_ObjFaninC1(pIfObj) );
+
+ nNodes = Abc_NtkObjNumMax( pAig );
+ pObj = Abc_AigAnd( pAig->pManFunc, pFanin0, pFanin1 );
+ assert( !Abc_ObjIsComplement(pObj) );
+ pIfObj->pCopy = pObj;
+
+ if ( pObj->Id == nNodes )
+ {
+ // increase storage for truth tables
+ if ( Vec_PtrSize(s_pMan->vTtNodes) <= pObj->Id )
+ Vec_PtrDoubleSimInfo(s_pMan->vTtNodes);
+ // compute the truth table
+ RetValue = Abc_NtkRecComputeTruth( pObj, s_pMan->vTtNodes, nInputs );
+ if ( RetValue == 0 )
+ {
+ s_pMan->nFilterError++;
+ printf( "T" );
+ return 1;
+ }
+ }
+ }
+
+ pTruth = Vec_PtrEntry( s_pMan->vTtNodes, pObj->Id );
+ if ( Kit_TruthSupport(pTruth, nInputs) != Kit_BitMask(nLeaves) )
+ {
+ s_pMan->nFilterError++;
+ printf( "S" );
+ return 1;
+ }
+
+ // compare the truth tables
+ if ( !Kit_TruthIsEqualWithPhase( pTruth, pInOut, nInputs ) )
+ {
+ s_pMan->nFilterError++;
+ printf( "F" );
+ return 1;
+ }
+// Extra_PrintBinary( stdout, pInOut, 8 ); printf( "\n" );
+
+ // if not new nodes were added and the node has a CO fanout
+ if ( nNodesBeg == Abc_NtkObjNumMax(pAig) && Abc_NodeFindCoFanout(pObj) != NULL )
+ {
+ s_pMan->nFilterSame++;
+ return 1;
+ }
+ s_pMan->nAdded++;
+
+ // create PO for this node
+ pObjPo = Abc_NtkCreatePo(pAig);
+ Abc_ObjAddFanin( pObjPo, pObj );
+
+ // assign the name to this PO
+ sprintf( Name, "%d_%06d", nLeaves, Abc_NtkPoNum(pAig) );
+ if ( (nInputs <= 6) && 0 )
+ {
+ Extra_PrintHexadecimalString( Truth, pInOut, nInputs );
+ sprintf( Buffer, "%s_%s", Name, Truth );
+ }
+ else
+ {
+ sprintf( Buffer, "%s", Name );
+ }
+ Abc_ObjAssignName( pObjPo, Buffer, NULL );
+
+ // add the resulting truth table to the hash table
+ ppSpot = Abc_NtkRecTableLookup( s_pMan, pTruth, nInputs );
+ assert( pObj->pEquiv == NULL );
+ assert( pObj->pCopy == NULL );
+ if ( *ppSpot == NULL )
+ {
+ s_pMan->nAddedFuncs++;
+ *ppSpot = pObj;
+ }
+ else
+ {
+ pObj->pEquiv = (*ppSpot)->pEquiv;
+ (*ppSpot)->pEquiv = (Hop_Obj_t *)pObj;
+ if ( !Abc_NtkRecAddCutCheckCycle_rec(*ppSpot, pObj) )
+ printf( "Loop!\n" );
+ }
+ return 1;
+}
+
+
+/**Function*************************************************************
+
+ Synopsis [Labels the record AIG with the corresponding new AIG nodes.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Abc_Obj_t * Abc_NtkRecStrashNodeLabel_rec( Abc_Ntk_t * pNtkNew, Abc_Obj_t * pObj, int fBuild, Vec_Ptr_t * vLabels )
+{
+ Abc_Obj_t * pFanin0New, * pFanin1New, * pLabel;
+ assert( !Abc_ObjIsComplement(pObj) );
+ // if this node is already visited, skip
+ if ( Abc_NodeIsTravIdCurrent( pObj ) )
+ return Vec_PtrEntry( vLabels, pObj->Id );
+ assert( Abc_ObjIsNode(pObj) );
+ // mark the node as visited
+ Abc_NodeSetTravIdCurrent( pObj );
+ // label the fanins
+ pFanin0New = Abc_NtkRecStrashNodeLabel_rec( pNtkNew, Abc_ObjFanin0(pObj), fBuild, vLabels );
+ pFanin1New = Abc_NtkRecStrashNodeLabel_rec( pNtkNew, Abc_ObjFanin1(pObj), fBuild, vLabels );
+ // label the node if possible
+ pLabel = NULL;
+ if ( pFanin0New && pFanin1New )
+ {
+ pFanin0New = Abc_ObjNotCond( pFanin0New, Abc_ObjFaninC0(pObj) );
+ pFanin1New = Abc_ObjNotCond( pFanin1New, Abc_ObjFaninC1(pObj) );
+ if ( fBuild )
+ pLabel = Abc_AigAnd( pNtkNew->pManFunc, pFanin0New, pFanin1New );
+ else
+ pLabel = Abc_AigAndLookup( pNtkNew->pManFunc, pFanin0New, pFanin1New );
+ }
+ Vec_PtrWriteEntry( vLabels, pObj->Id, pLabel );
+ return pLabel;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Counts the area of the given node.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Abc_NtkRecStrashNodeCount_rec( Abc_Obj_t * pObj, Vec_Str_t * vCosts, Vec_Ptr_t * vLabels )
+{
+ int Cost0, Cost1;
+ if ( Vec_PtrEntry( vLabels, pObj->Id ) )
+ return 0;
+ assert( Abc_ObjIsNode(pObj) );
+ // if this node is already visited, skip
+ if ( Abc_NodeIsTravIdCurrent( pObj ) )
+ return Vec_StrEntry( vCosts, pObj->Id );
+ // mark the node as visited
+ Abc_NodeSetTravIdCurrent( pObj );
+ // count for the fanins
+ Cost0 = Abc_NtkRecStrashNodeCount_rec( Abc_ObjFanin0(pObj), vCosts, vLabels );
+ Cost1 = Abc_NtkRecStrashNodeCount_rec( Abc_ObjFanin1(pObj), vCosts, vLabels );
+ Vec_StrWriteEntry( vCosts, pObj->Id, (char)(Cost0 + Cost1 + 1) );
+ return Cost0 + Cost1 + 1;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Strashes the given node using its local function.]
+
+ Description [Assumes that the fanins are already strashed.
+ Returns 0 if the function is not found in the table.]
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Abc_NtkRecStrashNode( Abc_Ntk_t * pNtkNew, Abc_Obj_t * pObj, unsigned * pTruth, int nVars )
+{
+ char pCanonPerm[16];
+ Abc_Ntk_t * pAig = s_pMan->pNtk;
+ unsigned * pInOut = s_pMan->pTemp1;
+ unsigned * pTemp = s_pMan->pTemp2;
+ unsigned * pTruthRec;
+ Abc_Obj_t * pCand, * pCandMin, * pLeaf, * pFanin, ** ppSpot;
+ unsigned uCanonPhase;
+ int i, nLeaves, CostMin, Cost, nOnes, fCompl;
+
+ // check if the record works
+ nLeaves = Abc_ObjFaninNum(pObj);
+ assert( nLeaves >= 3 && nLeaves <= s_pMan->nVars );
+ pFanin = Abc_ObjFanin0(pObj);
+ assert( Abc_ObjRegular(pFanin->pCopy)->pNtk == pNtkNew );
+ assert( s_pMan != NULL );
+ assert( nVars == s_pMan->nVars );
+
+ // copy the truth table
+ Kit_TruthCopy( pInOut, pTruth, nVars );
+
+ // set permutation
+ for ( i = 0; i < nVars; i++ )
+ pCanonPerm[i] = i;
+
+ // canonicize the truth table
+ uCanonPhase = Kit_TruthSemiCanonicize( pInOut, pTemp, nVars, pCanonPerm, (short *)s_pMan->pMints );
+
+ // get hold of the curresponding class
+ ppSpot = Abc_NtkRecTableLookup( s_pMan, pInOut, nVars );
+ if ( *ppSpot == NULL )
+ {
+ s_pMan->nFunsNotFound++;
+// printf( "The class of a function with %d inputs is not found.\n", nLeaves );
+ return 0;
+ }
+ s_pMan->nFunsFound++;
+
+ // make sure the truth table is the same
+ pTruthRec = Vec_PtrEntry( s_pMan->vTtNodes, (*ppSpot)->Id );
+ if ( !Kit_TruthIsEqualWithPhase( pTruthRec, pInOut, nVars ) )
+ {
+ assert( 0 );
+ return 0;
+ }
+
+
+ // allocate storage for costs
+ if ( s_pMan->vLabels && Vec_PtrSize(s_pMan->vLabels) < Abc_NtkObjNumMax(pAig) )
+ {
+ Vec_PtrFree( s_pMan->vLabels );
+ s_pMan->vLabels = NULL;
+ }
+ if ( s_pMan->vLabels == NULL )
+ s_pMan->vLabels = Vec_PtrStart( Abc_NtkObjNumMax(pAig) );
+
+ // go through the variables in the new truth table
+ Abc_NtkIncrementTravId( pAig );
+ for ( i = 0; i < nLeaves; i++ )
+ {
+ // get hold of the corresponding fanin
+ pFanin = Abc_ObjFanin( pObj, pCanonPerm[i] )->pCopy;
+ pFanin = Abc_ObjNotCond( pFanin, (uCanonPhase & (1 << i)) );
+ // label the PI of the AIG subgraphs with this fanin
+ pLeaf = Abc_NtkPi( pAig, i );
+ Vec_PtrWriteEntry( s_pMan->vLabels, pLeaf->Id, pFanin );
+ Abc_NodeSetTravIdCurrent( pLeaf );
+ }
+
+ // go through the candidates - and recursively label them
+ for ( pCand = *ppSpot; pCand; pCand = (Abc_Obj_t *)pCand->pEquiv )
+ Abc_NtkRecStrashNodeLabel_rec( pNtkNew, pCand, 0, s_pMan->vLabels );
+
+
+ // allocate storage for costs
+ if ( s_pMan->vCosts && Vec_StrSize(s_pMan->vCosts) < Abc_NtkObjNumMax(pAig) )
+ {
+ Vec_StrFree( s_pMan->vCosts );
+ s_pMan->vCosts = NULL;
+ }
+ if ( s_pMan->vCosts == NULL )
+ s_pMan->vCosts = Vec_StrStart( Abc_NtkObjNumMax(pAig) );
+
+ // find the best subgraph
+ CostMin = ABC_INFINITY;
+ pCandMin = NULL;
+ for ( pCand = *ppSpot; pCand; pCand = (Abc_Obj_t *)pCand->pEquiv )
+ {
+ // label the leaves
+ Abc_NtkIncrementTravId( pAig );
+ // count the number of non-labeled nodes
+ Cost = Abc_NtkRecStrashNodeCount_rec( pCand, s_pMan->vCosts, s_pMan->vLabels );
+ if ( CostMin > Cost )
+ {
+// printf( "%d ", Cost );
+ CostMin = Cost;
+ pCandMin = pCand;
+ }
+ }
+// printf( "\n" );
+ assert( pCandMin != NULL );
+ if ( pCandMin == NULL )
+ return 0;
+
+
+ // label the leaves
+ Abc_NtkIncrementTravId( pAig );
+ for ( i = 0; i < nLeaves; i++ )
+ Abc_NodeSetTravIdCurrent( Abc_NtkPi(pAig, i) );
+
+ // implement the subgraph
+ pObj->pCopy = Abc_NtkRecStrashNodeLabel_rec( pNtkNew, pCandMin, 1, s_pMan->vLabels );
+ assert( Abc_ObjRegular(pObj->pCopy)->pNtk == pNtkNew );
+
+ // determine phase difference
+ nOnes = Kit_TruthCountOnes(pTruth, nVars);
+ fCompl = (nOnes > (1<< nVars)/2);
+// assert( fCompl == ((uCanonPhase & (1 << nVars)) > 0) );
+
+ nOnes = Kit_TruthCountOnes(pTruthRec, nVars);
+ fCompl ^= (nOnes > (1<< nVars)/2);
+ // complement
+ pObj->pCopy = Abc_ObjNotCond( pObj->pCopy, fCompl );
+ return 1;
+}
+
+
+////////////////////////////////////////////////////////////////////////
+/// END OF FILE ///
+////////////////////////////////////////////////////////////////////////
+
+
diff --git a/src/base/abci/abcReconv.c b/src/base/abci/abcReconv.c
index 60a02aed..e77f055a 100644
--- a/src/base/abci/abcReconv.c
+++ b/src/base/abci/abcReconv.c
@@ -44,7 +44,7 @@ static int Abc_NodeBuildCutLevelTwo_int( Vec_Ptr_t * vVisited, Vec_Ptr_t * vLe
static void Abc_NodeConeMarkCollect_rec( Abc_Obj_t * pNode, Vec_Ptr_t * vVisited );
////////////////////////////////////////////////////////////////////////
-/// FUNCTION DEFITIONS ///
+/// FUNCTION DEFINITIONS ///
////////////////////////////////////////////////////////////////////////
/**Function*************************************************************
@@ -321,7 +321,9 @@ int Abc_NodeBuildCutLevelOne_int( Vec_Ptr_t * vVisited, Vec_Ptr_t * vLeaves, int
{
CostCur = Abc_NodeGetLeafCostOne( pNode, nFaninLimit );
//printf( " Fanin %s has cost %d.\n", Abc_ObjName(pNode), CostCur );
- if ( CostBest > CostCur )
+// if ( CostBest > CostCur ) // performance improvement: expand the variable with the smallest level
+ if ( CostBest > CostCur ||
+ (CostBest == CostCur && pNode->Level > pFaninBest->Level) )
{
CostBest = CostCur;
pFaninBest = pNode;
@@ -489,18 +491,20 @@ void Abc_NodeConeMarkCollect_rec( Abc_Obj_t * pNode, Vec_Ptr_t * vVisited )
SeeAlso []
***********************************************************************/
-DdNode * Abc_NodeConeBdd( DdManager * dd, DdNode ** pbVars, Abc_Obj_t * pNode, Vec_Ptr_t * vLeaves, Vec_Ptr_t * vVisited )
+DdNode * Abc_NodeConeBdd( DdManager * dd, DdNode ** pbVars, Abc_Obj_t * pRoot, Vec_Ptr_t * vLeaves, Vec_Ptr_t * vVisited )
{
+ Abc_Obj_t * pNode;
DdNode * bFunc0, * bFunc1, * bFunc;
int i;
// get the nodes in the cut without fanins in the DFS order
- Abc_NodeConeCollect( &pNode, 1, vLeaves, vVisited, 0 );
+ Abc_NodeConeCollect( &pRoot, 1, vLeaves, vVisited, 0 );
// set the elementary BDDs
Vec_PtrForEachEntry( vLeaves, pNode, i )
pNode->pCopy = (Abc_Obj_t *)pbVars[i];
// compute the BDDs for the collected nodes
Vec_PtrForEachEntry( vVisited, pNode, i )
{
+ assert( !Abc_ObjIsPi(pNode) );
bFunc0 = Cudd_NotCond( Abc_ObjFanin0(pNode)->pCopy, Abc_ObjFaninC0(pNode) );
bFunc1 = Cudd_NotCond( Abc_ObjFanin1(pNode)->pCopy, Abc_ObjFaninC1(pNode) );
bFunc = Cudd_bddAnd( dd, bFunc0, bFunc1 ); Cudd_Ref( bFunc );
@@ -585,7 +589,7 @@ Abc_ManCut_t * Abc_NtkManCutStart( int nNodeSizeMax, int nConeSizeMax, int nNode
p->vConeLeaves = Vec_PtrAlloc( 100 );
p->vVisited = Vec_PtrAlloc( 100 );
p->vLevels = Vec_VecAlloc( 100 );
- p->vNodesTfo = Vec_PtrAlloc( 100 );
+ p->vNodesTfo = Vec_PtrAlloc( 100 );
p->nNodeSizeMax = nNodeSizeMax;
p->nConeSizeMax = nConeSizeMax;
p->nNodeFanStop = nNodeFanStop;
@@ -641,6 +645,22 @@ Vec_Ptr_t * Abc_NtkManCutReadCutLarge( Abc_ManCut_t * p )
SeeAlso []
***********************************************************************/
+Vec_Ptr_t * Abc_NtkManCutReadCutSmall( Abc_ManCut_t * p )
+{
+ return p->vNodeLeaves;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Returns the leaves of the cone.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
Vec_Ptr_t * Abc_NtkManCutReadVisited( Abc_ManCut_t * p )
{
return p->vVisited;
@@ -692,7 +712,7 @@ Vec_Ptr_t * Abc_NodeCollectTfoCands( Abc_ManCut_t * p, Abc_Obj_t * pRoot, Vec_Pt
// mark MFFC
if ( pRoot )
- Abc_NodeMffcLabel( pRoot );
+ Abc_NodeMffcLabelAig( pRoot );
// go through the levels up
Vec_PtrClear( p->vNodesTfo );
diff --git a/src/base/abci/abcRefactor.c b/src/base/abci/abcRefactor.c
index 92d497fc..b925f1b9 100644
--- a/src/base/abci/abcRefactor.c
+++ b/src/base/abci/abcRefactor.c
@@ -43,6 +43,8 @@ struct Abc_ManRef_t_
int nNodesConsidered;
int nNodesRefactored;
int nNodesGained;
+ int nNodesBeg;
+ int nNodesEnd;
// runtime statistics
int timeCut;
int timeBdd;
@@ -58,10 +60,10 @@ struct Abc_ManRef_t_
static void Abc_NtkManRefPrintStats( Abc_ManRef_t * p );
static Abc_ManRef_t * Abc_NtkManRefStart( int nNodeSizeMax, int nConeSizeMax, bool fUseDcs, bool fVerbose );
static void Abc_NtkManRefStop( Abc_ManRef_t * p );
-static Dec_Graph_t * Abc_NodeRefactor( Abc_ManRef_t * p, Abc_Obj_t * pNode, Vec_Ptr_t * vFanins, bool fUseZeros, bool fUseDcs, bool fVerbose );
+static Dec_Graph_t * Abc_NodeRefactor( Abc_ManRef_t * p, Abc_Obj_t * pNode, Vec_Ptr_t * vFanins, bool fUpdateLevel, bool fUseZeros, bool fUseDcs, bool fVerbose );
////////////////////////////////////////////////////////////////////////
-/// FUNCTION DEFITIONS ///
+/// FUNCTION DEFINITIONS ///
////////////////////////////////////////////////////////////////////////
/**Function*************************************************************
@@ -80,8 +82,9 @@ static Dec_Graph_t * Abc_NodeRefactor( Abc_ManRef_t * p, Abc_Obj_t * pNode, Vec
SeeAlso []
***********************************************************************/
-int Abc_NtkRefactor( Abc_Ntk_t * pNtk, int nNodeSizeMax, int nConeSizeMax, bool fUseZeros, bool fUseDcs, bool fVerbose )
+int Abc_NtkRefactor( Abc_Ntk_t * pNtk, int nNodeSizeMax, int nConeSizeMax, bool fUpdateLevel, bool fUseZeros, bool fUseDcs, bool fVerbose )
{
+ extern void Dec_GraphUpdateNetwork( Abc_Obj_t * pRoot, Dec_Graph_t * pGraph, bool fUpdateLevel, int nGain );
ProgressBar * pProgress;
Abc_ManRef_t * pManRef;
Abc_ManCut_t * pManCut;
@@ -98,16 +101,22 @@ int Abc_NtkRefactor( Abc_Ntk_t * pNtk, int nNodeSizeMax, int nConeSizeMax, bool
pManCut = Abc_NtkManCutStart( nNodeSizeMax, nConeSizeMax, 2, 1000 );
pManRef = Abc_NtkManRefStart( nNodeSizeMax, nConeSizeMax, fUseDcs, fVerbose );
pManRef->vLeaves = Abc_NtkManCutReadCutLarge( pManCut );
- Abc_NtkStartReverseLevels( pNtk );
+ // compute the reverse levels if level update is requested
+ if ( fUpdateLevel )
+ Abc_NtkStartReverseLevels( pNtk, 0 );
// resynthesize each node once
+ pManRef->nNodesBeg = Abc_NtkNodeNum(pNtk);
nNodes = Abc_NtkObjNumMax(pNtk);
pProgress = Extra_ProgressBarStart( stdout, nNodes );
Abc_NtkForEachNode( pNtk, pNode, i )
{
Extra_ProgressBarUpdate( pProgress, i, NULL );
// skip the constant node
- if ( Abc_NodeIsConst(pNode) )
+// if ( Abc_NodeIsConst(pNode) )
+// continue;
+ // skip persistant nodes
+ if ( Abc_NodeIsPersistant(pNode) )
continue;
// skip the nodes with many fanouts
if ( Abc_ObjFanoutNum(pNode) > 1000 )
@@ -121,18 +130,23 @@ clk = clock();
pManRef->timeCut += clock() - clk;
// evaluate this cut
clk = clock();
- pFForm = Abc_NodeRefactor( pManRef, pNode, vFanins, fUseZeros, fUseDcs, fVerbose );
+ pFForm = Abc_NodeRefactor( pManRef, pNode, vFanins, fUpdateLevel, fUseZeros, fUseDcs, fVerbose );
pManRef->timeRes += clock() - clk;
if ( pFForm == NULL )
continue;
// acceptable replacement found, update the graph
clk = clock();
- Dec_GraphUpdateNetwork( pNode, pFForm, pManRef->nLastGain );
+ Dec_GraphUpdateNetwork( pNode, pFForm, fUpdateLevel, pManRef->nLastGain );
pManRef->timeNtk += clock() - clk;
Dec_GraphFree( pFForm );
+// {
+// extern int s_TotalChanges;
+// s_TotalChanges++;
+// }
}
Extra_ProgressBarStop( pProgress );
pManRef->timeTotal = clock() - clkStart;
+ pManRef->nNodesEnd = Abc_NtkNodeNum(pNtk);
// print statistics of the manager
if ( fVerbose )
@@ -140,7 +154,14 @@ pManRef->timeTotal = clock() - clkStart;
// delete the managers
Abc_NtkManCutStop( pManCut );
Abc_NtkManRefStop( pManRef );
- Abc_NtkStopReverseLevels( pNtk );
+ // put the nodes into the DFS order and reassign their IDs
+ Abc_NtkReassignIds( pNtk );
+// Abc_AigCheckFaninOrder( pNtk->pManFunc );
+ // fix the levels
+ if ( fUpdateLevel )
+ Abc_NtkStopReverseLevels( pNtk );
+ else
+ Abc_NtkLevel( pNtk );
// check
if ( !Abc_NtkCheck( pNtk ) )
{
@@ -161,14 +182,18 @@ pManRef->timeTotal = clock() - clkStart;
SeeAlso []
***********************************************************************/
-Dec_Graph_t * Abc_NodeRefactor( Abc_ManRef_t * p, Abc_Obj_t * pNode, Vec_Ptr_t * vFanins, bool fUseZeros, bool fUseDcs, bool fVerbose )
+Dec_Graph_t * Abc_NodeRefactor( Abc_ManRef_t * p, Abc_Obj_t * pNode, Vec_Ptr_t * vFanins, bool fUpdateLevel, bool fUseZeros, bool fUseDcs, bool fVerbose )
{
+ extern int Dec_GraphToNetworkCount( Abc_Obj_t * pRoot, Dec_Graph_t * pGraph, int NodeMax, int LevelMax );
int fVeryVerbose = 0;
Abc_Obj_t * pFanin;
Dec_Graph_t * pFForm;
DdNode * bNodeFunc;
int nNodesSaved, nNodesAdded, i, clk;
char * pSop;
+ int Required;
+
+ Required = fUpdateLevel? Abc_ObjRequiredLevel(pNode) : ABC_INFINITY;
p->nNodesConsidered++;
@@ -214,7 +239,7 @@ p->timeDcs += clock() - clk;
// get the SOP of the cut
clk = clock();
- pSop = Abc_ConvertBddToSop( NULL, p->dd, bNodeFunc, bNodeFunc, vFanins->nSize, p->vCube, -1 );
+ pSop = Abc_ConvertBddToSop( NULL, p->dd, bNodeFunc, bNodeFunc, vFanins->nSize, 0, p->vCube, -1 );
p->timeSop += clock() - clk;
// get the factored form
@@ -229,7 +254,7 @@ p->timeFact += clock() - clk;
pFanin->vFanouts.nSize++;
// label MFFC with current traversal ID
Abc_NtkIncrementTravId( pNode->pNtk );
- nNodesSaved = Abc_NodeMffcLabel( pNode );
+ nNodesSaved = Abc_NodeMffcLabelAig( pNode );
// unmark the fanin boundary and set the fanins as leaves in the form
Vec_PtrForEachEntry( vFanins, pFanin, i )
{
@@ -239,7 +264,7 @@ p->timeFact += clock() - clk;
// detect how many new nodes will be added (while taking into account reused nodes)
clk = clock();
- nNodesAdded = Dec_GraphToNetworkCount( pNode, pFForm, nNodesSaved, Abc_NodeReadRequiredLevel(pNode) );
+ nNodesAdded = Dec_GraphToNetworkCount( pNode, pFForm, nNodesSaved, Required );
p->timeEval += clock() - clk;
// quit if there is no improvement
if ( nNodesAdded == -1 || nNodesAdded == nNodesSaved && !fUseZeros )
@@ -336,7 +361,7 @@ void Abc_NtkManRefPrintStats( Abc_ManRef_t * p )
printf( "Refactoring statistics:\n" );
printf( "Nodes considered = %8d.\n", p->nNodesConsidered );
printf( "Nodes refactored = %8d.\n", p->nNodesRefactored );
- printf( "Calculated gain = %8d.\n", p->nNodesGained );
+ printf( "Gain = %8d. (%6.2f %%).\n", p->nNodesBeg-p->nNodesEnd, 100.0*(p->nNodesBeg-p->nNodesEnd)/p->nNodesBeg );
PRT( "Cuts ", p->timeCut );
PRT( "Resynthesis", p->timeRes );
PRT( " BDD ", p->timeBdd );
diff --git a/src/base/abci/abcRenode.c b/src/base/abci/abcRenode.c
index 165777f8..8e8e8719 100644
--- a/src/base/abci/abcRenode.c
+++ b/src/base/abci/abcRenode.c
@@ -6,7 +6,7 @@
PackageName [Network and node package.]
- Synopsis [Procedures which transform an AIG into the network of SOP logic nodes.]
+ Synopsis []
Author [Alan Mishchenko]
@@ -19,479 +19,172 @@
***********************************************************************/
#include "abc.h"
+#include "reo.h"
+#include "if.h"
+#include "kit.h"
////////////////////////////////////////////////////////////////////////
/// DECLARATIONS ///
////////////////////////////////////////////////////////////////////////
-static void Abc_NtkRenodeInt( Abc_Ntk_t * pNtk, Abc_Ntk_t * pNtkNew );
-static Abc_Obj_t * Abc_NtkRenode_rec( Abc_Ntk_t * pNtkNew, Abc_Obj_t * pNodeOld );
+static int Abc_NtkRenodeEvalAig( If_Cut_t * pCut );
+static int Abc_NtkRenodeEvalBdd( If_Cut_t * pCut );
+static int Abc_NtkRenodeEvalSop( If_Cut_t * pCut );
+static int Abc_NtkRenodeEvalCnf( If_Cut_t * pCut );
+static int Abc_NtkRenodeEvalMv( If_Cut_t * pCut );
-static DdNode * Abc_NtkRenodeDeriveBdd_rec( DdManager * dd, Abc_Obj_t * pNodeOld, Vec_Ptr_t * vFanins );
+static reo_man * s_pReo = NULL;
+static DdManager * s_pDd = NULL;
+static Vec_Int_t * s_vMemory = NULL;
+static Vec_Int_t * s_vMemory2 = NULL;
-static void Abc_NtkRenodeSetBounds( Abc_Ntk_t * pNtk, int nThresh, int nFaninMax );
-static void Abc_NtkRenodeSetBoundsCnf( Abc_Ntk_t * pNtk );
-static void Abc_NtkRenodeSetBoundsMulti( Abc_Ntk_t * pNtk, int nThresh );
-static void Abc_NtkRenodeSetBoundsSimple( Abc_Ntk_t * pNtk );
-static void Abc_NtkRenodeCone( Abc_Obj_t * pNode, Vec_Ptr_t * vCone );
+static int nDsdCounter = 0;
////////////////////////////////////////////////////////////////////////
-/// FUNCTION DEFITIONS ///
+/// FUNCTION DEFINITIONS ///
////////////////////////////////////////////////////////////////////////
/**Function*************************************************************
- Synopsis [Transforms the AIG into nodes.]
+ Synopsis [Performs renoding as technology mapping.]
- Description [Threhold is the max number of nodes duplicated at a node.]
+ Description []
SideEffects []
SeeAlso []
***********************************************************************/
-Abc_Ntk_t * Abc_NtkRenode( Abc_Ntk_t * pNtk, int nThresh, int nFaninMax, int fCnf, int fMulti, int fSimple )
+Abc_Ntk_t * Abc_NtkRenode( Abc_Ntk_t * pNtk, int nFaninMax, int nCubeMax, int nFlowIters, int nAreaIters, int fArea, int fUseBdds, int fUseSops, int fUseCnfs, int fUseMv, int fVerbose )
{
+ extern Abc_Ntk_t * Abc_NtkIf( Abc_Ntk_t * pNtk, If_Par_t * pPars );
+ If_Par_t Pars, * pPars = &Pars;
Abc_Ntk_t * pNtkNew;
- assert( Abc_NtkIsStrash(pNtk) );
- assert( nThresh >= 0 );
- assert( nFaninMax > 1 );
-
- // print a warning about choice nodes
if ( Abc_NtkGetChoiceNum( pNtk ) )
- printf( "Warning: The choice nodes in the AIG are removed by renoding.\n" );
-
- // define the boundary
- if ( fCnf )
- Abc_NtkRenodeSetBoundsCnf( pNtk );
- else if ( fMulti )
- Abc_NtkRenodeSetBoundsMulti( pNtk, nThresh );
- else if ( fSimple )
- Abc_NtkRenodeSetBoundsSimple( pNtk );
- else
- Abc_NtkRenodeSetBounds( pNtk, nThresh, nFaninMax );
-
- // perform renoding for this boundary
- pNtkNew = Abc_NtkStartFrom( pNtk, ABC_TYPE_LOGIC, ABC_FUNC_BDD );
- Abc_NtkRenodeInt( pNtk, pNtkNew );
- Abc_NtkFinalize( pNtk, pNtkNew );
-
- // make the network minimum base
- Abc_NtkMinimumBase( pNtkNew );
-
- // fix the problem with complemented and duplicated CO edges
- Abc_NtkLogicMakeSimpleCos( pNtkNew, 0 );
-
- // report the number of CNF objects
- if ( fCnf )
+ printf( "Performing renoding with choices.\n" );
+
+ nDsdCounter = 0;
+
+ // set defaults
+ memset( pPars, 0, sizeof(If_Par_t) );
+ // user-controlable paramters
+ pPars->nLutSize = nFaninMax;
+ pPars->nCutsMax = nCubeMax;
+ pPars->nFlowIters = nFlowIters;
+ pPars->nAreaIters = nAreaIters;
+ pPars->DelayTarget = -1;
+ pPars->fPreprocess = 1;
+ pPars->fArea = fArea;
+ pPars->fFancy = 0;
+ pPars->fExpRed = 0; //
+ pPars->fLatchPaths = 0;
+ pPars->fSeqMap = 0;
+ pPars->fVerbose = fVerbose;
+ // internal parameters
+ pPars->fTruth = 1;
+ pPars->fUsePerm = 1;
+ pPars->nLatches = 0;
+ pPars->pLutLib = NULL; // Abc_FrameReadLibLut();
+ pPars->pTimesArr = NULL;
+ pPars->pTimesArr = NULL;
+ pPars->fUseBdds = fUseBdds;
+ pPars->fUseSops = fUseSops;
+ pPars->fUseCnfs = fUseCnfs;
+ pPars->fUseMv = fUseMv;
+ if ( fUseBdds )
+ pPars->pFuncCost = Abc_NtkRenodeEvalBdd;
+ else if ( fUseSops )
+ pPars->pFuncCost = Abc_NtkRenodeEvalSop;
+ else if ( fUseCnfs )
{
-// int nClauses = Abc_NtkGetClauseNum(pNtkNew) + 2*Abc_NtkPoNum(pNtkNew) + 2*Abc_NtkLatchNum(pNtkNew);
-// printf( "CNF variables = %d. CNF clauses = %d.\n", Abc_NtkNodeNum(pNtkNew), nClauses );
+ pPars->fArea = 1;
+ pPars->pFuncCost = Abc_NtkRenodeEvalCnf;
}
-//printf( "Maximum fanin = %d.\n", Abc_NtkGetFaninMax(pNtkNew) );
+ else if ( fUseMv )
+ pPars->pFuncCost = Abc_NtkRenodeEvalMv;
+ else
+ pPars->pFuncCost = Abc_NtkRenodeEvalAig;
- // make sure everything is okay
- if ( !Abc_NtkCheck( pNtkNew ) )
+ // start the manager
+ if ( fUseBdds )
{
- printf( "Abc_NtkRenode: The network check has failed.\n" );
- Abc_NtkDelete( pNtkNew );
- return NULL;
+ assert( s_pReo == NULL );
+ s_pDd = Cudd_Init( nFaninMax, 0, CUDD_UNIQUE_SLOTS, CUDD_CACHE_SLOTS, 0 );
+ s_pReo = Extra_ReorderInit( nFaninMax, 100 );
+ pPars->pReoMan = s_pReo;
}
- return pNtkNew;
-}
-
-/**Function*************************************************************
-
- Synopsis [Transforms the AIG into nodes.]
-
- Description [Threhold is the max number of nodes duplicated at a node.]
-
- SideEffects []
-
- SeeAlso []
-
-***********************************************************************/
-void Abc_NtkRenodeInt( Abc_Ntk_t * pNtk, Abc_Ntk_t * pNtkNew )
-{
- ProgressBar * pProgress;
- Abc_Obj_t * pNode, * pConst1, * pNodeNew;
- int i;
-
- // set the constant node
- pConst1 = Abc_AigConst1(pNtk->pManFunc);
- if ( Abc_ObjFanoutNum(pConst1) > 0 )
+ else
{
- pNodeNew = Abc_NtkCreateNode( pNtkNew );
- pNodeNew->pData = Cudd_ReadOne( pNtkNew->pManFunc ); Cudd_Ref( pNodeNew->pData );
- pConst1->pCopy = pNodeNew;
+ assert( s_vMemory == NULL );
+ s_vMemory = Vec_IntAlloc( 1 << 16 );
+ s_vMemory2 = Vec_IntAlloc( 1 << 16 );
}
- // perform renoding for POs
- pProgress = Extra_ProgressBarStart( stdout, Abc_NtkCoNum(pNtk) );
- Abc_NtkForEachCo( pNtk, pNode, i )
- {
- Extra_ProgressBarUpdate( pProgress, i, NULL );
- if ( Abc_ObjIsCi(Abc_ObjFanin0(pNode)) )
- continue;
- Abc_NtkRenode_rec( pNtkNew, Abc_ObjFanin0(pNode) );
- }
- Extra_ProgressBarStop( pProgress );
+ // perform mapping/renoding
+ pNtkNew = Abc_NtkIf( pNtk, pPars );
- // clean the boundaries and data field in the old network
- Abc_NtkForEachObj( pNtk, pNode, i )
+ // start the manager
+ if ( fUseBdds )
{
- pNode->fMarkA = 0;
- pNode->pData = NULL;
+ Extra_StopManager( s_pDd );
+ Extra_ReorderQuit( s_pReo );
+ s_pReo = NULL;
+ s_pDd = NULL;
}
-}
-
-/**Function*************************************************************
-
- Synopsis [Find the best multi-input node rooted at the given node.]
-
- Description []
-
- SideEffects []
-
- SeeAlso []
-
-***********************************************************************/
-Abc_Obj_t * Abc_NtkRenode_rec( Abc_Ntk_t * pNtkNew, Abc_Obj_t * pNodeOld )
-{
- Vec_Ptr_t * vCone;
- Abc_Obj_t * pNodeNew;
- int i;
-
- assert( !Abc_ObjIsComplement(pNodeOld) );
- // return if the result if known
- if ( pNodeOld->pCopy )
- return pNodeOld->pCopy;
- assert( Abc_ObjIsNode(pNodeOld) );
- assert( !Abc_NodeIsConst(pNodeOld) );
- assert( pNodeOld->fMarkA );
-
- // collect the renoding cone
- vCone = Vec_PtrAlloc( 10 );
- Abc_NtkRenodeCone( pNodeOld, vCone );
-
- // create a new node
- pNodeNew = Abc_NtkCreateNode( pNtkNew );
- for ( i = 0; i < vCone->nSize; i++ )
- Abc_ObjAddFanin( pNodeNew, Abc_NtkRenode_rec(pNtkNew, vCone->pArray[i]) );
-
- // derive the function of this node
- pNodeNew->pData = Abc_NtkRenodeDeriveBdd( pNtkNew->pManFunc, pNodeOld, vCone );
- Cudd_Ref( pNodeNew->pData );
- Vec_PtrFree( vCone );
-
- // remember the node
- pNodeOld->pCopy = pNodeNew;
- return pNodeOld->pCopy;
-}
-
-
-/**Function*************************************************************
-
- Synopsis [Derives the local BDD of the node.]
-
- Description []
-
- SideEffects []
-
- SeeAlso []
-
-***********************************************************************/
-DdNode * Abc_NtkRenodeDeriveBdd( DdManager * dd, Abc_Obj_t * pNodeOld, Vec_Ptr_t * vFaninsOld )
-{
- Abc_Obj_t * pFaninOld;
- DdNode * bFunc;
- int i;
- assert( !Abc_NodeIsConst(pNodeOld) );
- assert( Abc_ObjIsNode(pNodeOld) );
- // set the elementary BDD variables for the input nodes
- for ( i = 0; i < vFaninsOld->nSize; i++ )
- {
- pFaninOld = vFaninsOld->pArray[i];
- pFaninOld->pData = Cudd_bddIthVar( dd, i ); Cudd_Ref( pFaninOld->pData );
- pFaninOld->fMarkC = 1;
- }
- // call the recursive BDD computation
- bFunc = Abc_NtkRenodeDeriveBdd_rec( dd, pNodeOld, vFaninsOld ); Cudd_Ref( bFunc );
- // dereference the intermediate nodes
- for ( i = 0; i < vFaninsOld->nSize; i++ )
+ else
{
- pFaninOld = vFaninsOld->pArray[i];
- Cudd_RecursiveDeref( dd, pFaninOld->pData );
- pFaninOld->fMarkC = 0;
+ Vec_IntFree( s_vMemory );
+ Vec_IntFree( s_vMemory2 );
+ s_vMemory = NULL;
+ s_vMemory2 = NULL;
}
- Cudd_Deref( bFunc );
- return bFunc;
-}
-/**Function*************************************************************
+// printf( "Decomposed %d functions.\n", nDsdCounter );
- Synopsis [Derives the local BDD of the node.]
-
- Description []
-
- SideEffects []
-
- SeeAlso []
-
-***********************************************************************/
-DdNode * Abc_NtkRenodeDeriveBdd_rec( DdManager * dd, Abc_Obj_t * pNode, Vec_Ptr_t * vFanins )
-{
- DdNode * bFunc, * bFunc0, * bFunc1;
- assert( !Abc_ObjIsComplement(pNode) );
- // if the result is available return
- if ( pNode->fMarkC )
- {
- assert( pNode->pData ); // network has a cycle
- return pNode->pData;
- }
- // mark the node as visited
- pNode->fMarkC = 1;
- Vec_PtrPush( vFanins, pNode );
- // compute the result for both branches
- bFunc0 = Abc_NtkRenodeDeriveBdd_rec( dd, Abc_ObjFanin(pNode,0), vFanins ); Cudd_Ref( bFunc0 );
- bFunc1 = Abc_NtkRenodeDeriveBdd_rec( dd, Abc_ObjFanin(pNode,1), vFanins ); Cudd_Ref( bFunc1 );
- bFunc0 = Cudd_NotCond( bFunc0, Abc_ObjFaninC0(pNode) );
- bFunc1 = Cudd_NotCond( bFunc1, Abc_ObjFaninC1(pNode) );
- // get the final result
- bFunc = Cudd_bddAnd( dd, bFunc0, bFunc1 ); Cudd_Ref( bFunc );
- Cudd_RecursiveDeref( dd, bFunc0 );
- Cudd_RecursiveDeref( dd, bFunc1 );
- // set the result
- pNode->pData = bFunc;
- assert( pNode->pData );
- return bFunc;
+ return pNtkNew;
}
-
-
/**Function*************************************************************
- Synopsis [Limits the cones to be no more than the given size.]
+ Synopsis [Computes the cost based on the factored form.]
- Description [Returns 1 if the last cone was limited. Returns 0 if no changes.]
+ Description []
SideEffects []
SeeAlso []
***********************************************************************/
-int Abc_NtkRenodeLimit_rec( Abc_Obj_t * pNode, Vec_Ptr_t * vCone, int nFaninMax, int fCanStop, int fFirst )
+int Abc_NtkRenodeEvalAig( If_Cut_t * pCut )
{
- int nNodes0, nNodes1;
- assert( !Abc_ObjIsComplement(pNode) );
- // check if the node should be added to the fanins
- if ( !fFirst && (pNode->fMarkA || !Abc_ObjIsNode(pNode)) )
- {
- Vec_PtrPushUnique( vCone, pNode );
- return 0;
- }
- // if we cannot stop in this branch, collect all nodes
- if ( !fCanStop )
- {
- Abc_NtkRenodeLimit_rec( Abc_ObjFanin(pNode,0), vCone, nFaninMax, 0, 0 );
- Abc_NtkRenodeLimit_rec( Abc_ObjFanin(pNode,1), vCone, nFaninMax, 0, 0 );
- return 0;
- }
- // if we can stop, try the left branch first, and return if we stopped
- assert( vCone->nSize == 0 );
- if ( Abc_NtkRenodeLimit_rec( Abc_ObjFanin(pNode,0), vCone, nFaninMax, 1, 0 ) )
- return 1;
- // save the number of nodes in the left branch and call for the right branch
- nNodes0 = vCone->nSize;
- assert( nNodes0 <= nFaninMax );
- Abc_NtkRenodeLimit_rec( Abc_ObjFanin(pNode,1), vCone, nFaninMax, 0, 0 );
- // check the number of nodes
- if ( vCone->nSize <= nFaninMax )
- return 0;
- // the number of nodes exceeds the limit
-
- // get the number of nodes in the right branch
- vCone->nSize = 0;
- Abc_NtkRenodeLimit_rec( Abc_ObjFanin(pNode,1), vCone, nFaninMax, 0, 0 );
- // if this number exceeds the limit, solve the problem for this branch
- if ( vCone->nSize > nFaninMax )
- {
- int RetValue;
- vCone->nSize = 0;
- RetValue = Abc_NtkRenodeLimit_rec( Abc_ObjFanin(pNode,1), vCone, nFaninMax, 1, 0 );
- assert( RetValue == 1 );
- return 1;
- }
-
- nNodes1 = vCone->nSize;
- assert( nNodes1 <= nFaninMax );
- if ( nNodes0 >= nNodes1 )
- { // the left branch is larger - cut it
- assert( Abc_ObjFanin(pNode,0)->fMarkA == 0 );
- Abc_ObjFanin(pNode,0)->fMarkA = 1;
- }
- else
- { // the right branch is larger - cut it
- assert( Abc_ObjFanin(pNode,1)->fMarkA == 0 );
- Abc_ObjFanin(pNode,1)->fMarkA = 1;
- }
- return 1;
-}
-
-/**Function*************************************************************
-
- Synopsis [Limits the cones to be no more than the given size.]
-
- Description [Returns 1 if the last cone was limited. Returns 0 if no changes.]
-
- SideEffects []
-
- SeeAlso []
-
-***********************************************************************/
-int Abc_NtkRenodeLimit( Abc_Obj_t * pNode, Vec_Ptr_t * vCone, int nFaninMax )
+ Kit_Graph_t * pGraph;
+ int i, nNodes;
+/*
+extern void Kit_DsdTest( unsigned * pTruth, int nVars );
+if ( If_CutLeaveNum(pCut) == 8 )
{
- vCone->nSize = 0;
- return Abc_NtkRenodeLimit_rec( pNode, vCone, nFaninMax, 1, 1 );
+ nDsdCounter++;
+ Kit_DsdTest( If_CutTruth(pCut), If_CutLeaveNum(pCut) );
}
-
-/**Function*************************************************************
-
- Synopsis [Sets the expansion boundary for multi-input nodes.]
-
- Description [The boundary includes the set of PIs and all nodes such that
- when expanding over the node we duplicate no more than nThresh nodes.]
-
- SideEffects []
-
- SeeAlso []
-
-***********************************************************************/
-void Abc_NtkRenodeSetBounds( Abc_Ntk_t * pNtk, int nThresh, int nFaninMax )
-{
- Vec_Ptr_t * vCone = pNtk->vPtrTemp;
- Abc_Obj_t * pNode;
- int i, nFanouts, nConeSize;
-
- // make sure the mark is not set
- Abc_NtkForEachObj( pNtk, pNode, i )
- assert( pNode->fMarkA == 0 );
-
- // mark the nodes where expansion stops using pNode->fMarkA
- Abc_NtkForEachNode( pNtk, pNode, i )
- {
- // skip PI/PO nodes
- if ( Abc_NodeIsConst(pNode) )
- continue;
- // mark the nodes with multiple fanouts
- nFanouts = Abc_ObjFanoutNum(pNode);
- nConeSize = Abc_NodeMffcSize(pNode);
- if ( (nFanouts - 1) * nConeSize > nThresh )
- pNode->fMarkA = 1;
- }
-
- // mark the PO drivers
- Abc_NtkForEachCo( pNtk, pNode, i )
- Abc_ObjFanin0(pNode)->fMarkA = 1;
-
- // make sure the fanin limit is met
- Abc_NtkForEachNode( pNtk, pNode, i )
- {
- // skip PI/PO nodes
- if ( Abc_NodeIsConst(pNode) )
- continue;
- if ( pNode->fMarkA == 0 )
- continue;
- // continue cutting branches ntil it meets the fanin limit
- while ( Abc_NtkRenodeLimit(pNode, vCone, nFaninMax) );
- assert( vCone->nSize <= nFaninMax );
- }
-/*
- // make sure the fanin limit is met
- Abc_NtkForEachNode( pNtk, pNode, i )
- {
- // skip PI/PO nodes
- if ( Abc_NodeIsConst(pNode) )
- continue;
- if ( pNode->fMarkA == 0 )
- continue;
- Abc_NtkRenodeCone( pNode, vCone );
- assert( vCone->nSize <= nFaninMax );
- }
*/
-}
-
-/**Function*************************************************************
-
- Synopsis [Sets the expansion boundary for conversion into CNF.]
-
- Description [The boundary includes the set of PIs, the roots of MUXes,
- the nodes with multiple fanouts and the nodes with complemented outputs.]
-
- SideEffects []
-
- SeeAlso []
-
-***********************************************************************/
-void Abc_NtkRenodeSetBoundsCnf( Abc_Ntk_t * pNtk )
-{
- Abc_Obj_t * pNode;
- int i, nMuxes;
-
- // make sure the mark is not set
- Abc_NtkForEachObj( pNtk, pNode, i )
- assert( pNode->fMarkA == 0 );
-
- // mark the nodes where expansion stops using pNode->fMarkA
- Abc_NtkForEachNode( pNtk, pNode, i )
+ pGraph = Kit_TruthToGraph( If_CutTruth(pCut), If_CutLeaveNum(pCut), s_vMemory );
+ if ( pGraph == NULL )
{
- // skip PI/PO nodes
- if ( Abc_NodeIsConst(pNode) )
- continue;
- // mark the nodes with multiple fanouts
- if ( Abc_ObjFanoutNum(pNode) > 1 )
- pNode->fMarkA = 1;
- // mark the nodes that are roots of MUXes
- if ( Abc_NodeIsMuxType( pNode ) )
- {
- pNode->fMarkA = 1;
- Abc_ObjFanin0( Abc_ObjFanin0(pNode) )->fMarkA = 1;
- Abc_ObjFanin0( Abc_ObjFanin1(pNode) )->fMarkA = 1;
- Abc_ObjFanin1( Abc_ObjFanin0(pNode) )->fMarkA = 1;
- Abc_ObjFanin1( Abc_ObjFanin1(pNode) )->fMarkA = 1;
- }
- else // mark the complemented edges
- {
- if ( Abc_ObjFaninC0(pNode) )
- Abc_ObjFanin0(pNode)->fMarkA = 1;
- if ( Abc_ObjFaninC1(pNode) )
- Abc_ObjFanin1(pNode)->fMarkA = 1;
- }
+ for ( i = 0; i < If_CutLeaveNum(pCut); i++ )
+ pCut->pPerm[i] = 100;
+ return IF_COST_MAX;
}
+ nNodes = Kit_GraphNodeNum( pGraph );
+ for ( i = 0; i < If_CutLeaveNum(pCut); i++ )
+ pCut->pPerm[i] = Kit_GraphLeafDepth_rec( pGraph, Kit_GraphNodeLast(pGraph), Kit_GraphNode(pGraph, i) );
+ Kit_GraphFree( pGraph );
+ return nNodes;
+}
- // mark the PO drivers
- Abc_NtkForEachCo( pNtk, pNode, i )
- Abc_ObjFanin0(pNode)->fMarkA = 1;
-
- // count the number of MUXes
- nMuxes = 0;
- Abc_NtkForEachNode( pNtk, pNode, i )
- {
- // skip PI/PO nodes
- if ( Abc_NodeIsConst(pNode) )
- continue;
- if ( Abc_NodeIsMuxType(pNode) &&
- Abc_ObjFanin0(pNode)->fMarkA == 0 &&
- Abc_ObjFanin1(pNode)->fMarkA == 0 )
- nMuxes++;
- }
- printf( "The number of MUXes detected = %d (%5.2f %% of logic).\n", nMuxes, 300.0*nMuxes/Abc_NtkNodeNum(pNtk) );
-}
-
/**Function*************************************************************
- Synopsis [Sets the expansion boundary for conversion into multi-input AND graph.]
+ Synopsis [Computes the cost based on the BDD size after reordering.]
Description []
@@ -500,44 +193,27 @@ void Abc_NtkRenodeSetBoundsCnf( Abc_Ntk_t * pNtk )
SeeAlso []
***********************************************************************/
-void Abc_NtkRenodeSetBoundsMulti( Abc_Ntk_t * pNtk, int nThresh )
+int Abc_NtkRenodeEvalBdd( If_Cut_t * pCut )
{
- Abc_Obj_t * pNode;
- int i, nFanouts, nConeSize;
-
- // make sure the mark is not set
- Abc_NtkForEachObj( pNtk, pNode, i )
- assert( pNode->fMarkA == 0 );
-
- // mark the nodes where expansion stops using pNode->fMarkA
- Abc_NtkForEachNode( pNtk, pNode, i )
- {
- // skip PI/PO nodes
- if ( Abc_NodeIsConst(pNode) )
- continue;
- // mark the nodes with multiple fanouts
-// if ( Abc_ObjFanoutNum(pNode) > 1 )
-// pNode->fMarkA = 1;
- // mark the nodes with multiple fanouts
- nFanouts = Abc_ObjFanoutNum(pNode);
- nConeSize = Abc_NodeMffcSizeStop(pNode);
- if ( (nFanouts - 1) * nConeSize > nThresh )
- pNode->fMarkA = 1;
- // mark the children if they are pointed by the complemented edges
- if ( Abc_ObjFaninC0(pNode) )
- Abc_ObjFanin0(pNode)->fMarkA = 1;
- if ( Abc_ObjFaninC1(pNode) )
- Abc_ObjFanin1(pNode)->fMarkA = 1;
- }
-
- // mark the PO drivers
- Abc_NtkForEachCo( pNtk, pNode, i )
- Abc_ObjFanin0(pNode)->fMarkA = 1;
+ int pOrder[IF_MAX_LUTSIZE];
+ DdNode * bFunc, * bFuncNew;
+ int i, k, nNodes;
+ for ( i = 0; i < If_CutLeaveNum(pCut); i++ )
+ pCut->pPerm[i] = pOrder[i] = -100;
+ bFunc = Kit_TruthToBdd( s_pDd, If_CutTruth(pCut), If_CutLeaveNum(pCut), 0 ); Cudd_Ref( bFunc );
+ bFuncNew = Extra_Reorder( s_pReo, s_pDd, bFunc, pOrder ); Cudd_Ref( bFuncNew );
+ for ( i = k = 0; i < If_CutLeaveNum(pCut); i++ )
+ if ( pOrder[i] >= 0 )
+ pCut->pPerm[pOrder[i]] = ++k; // double-check this!
+ nNodes = -1 + Cudd_DagSize( bFuncNew );
+ Cudd_RecursiveDeref( s_pDd, bFuncNew );
+ Cudd_RecursiveDeref( s_pDd, bFunc );
+ return nNodes;
}
/**Function*************************************************************
- Synopsis [Sets a simple boundary.]
+ Synopsis [Computes the cost based on ISOP.]
Description []
@@ -546,21 +222,21 @@ void Abc_NtkRenodeSetBoundsMulti( Abc_Ntk_t * pNtk, int nThresh )
SeeAlso []
***********************************************************************/
-void Abc_NtkRenodeSetBoundsSimple( Abc_Ntk_t * pNtk )
+int Abc_NtkRenodeEvalSop( If_Cut_t * pCut )
{
- Abc_Obj_t * pNode;
- int i;
- // make sure the mark is not set
- Abc_NtkForEachObj( pNtk, pNode, i )
- assert( pNode->fMarkA == 0 );
- // mark the nodes where expansion stops using pNode->fMarkA
- Abc_NtkForEachNode( pNtk, pNode, i )
- pNode->fMarkA = 1;
+ int i, RetValue;
+ for ( i = 0; i < If_CutLeaveNum(pCut); i++ )
+ pCut->pPerm[i] = 1;
+ RetValue = Kit_TruthIsop( If_CutTruth(pCut), If_CutLeaveNum(pCut), s_vMemory, 1 );
+ if ( RetValue == -1 )
+ return IF_COST_MAX;
+ assert( RetValue == 0 || RetValue == 1 );
+ return Vec_IntSize( s_vMemory );
}
/**Function*************************************************************
- Synopsis [Collects the fanins of a large node.]
+ Synopsis [Computes the cost based on two ISOPs.]
Description []
@@ -569,21 +245,32 @@ void Abc_NtkRenodeSetBoundsSimple( Abc_Ntk_t * pNtk )
SeeAlso []
***********************************************************************/
-void Abc_NtkRenodeCone_rec( Abc_Obj_t * pNode, Vec_Ptr_t * vCone )
+int Abc_NtkRenodeEvalCnf( If_Cut_t * pCut )
{
- assert( !Abc_ObjIsComplement(pNode) );
- if ( pNode->fMarkA || !Abc_ObjIsNode(pNode) )
- {
- Vec_PtrPushUnique( vCone, pNode );
- return;
- }
- Abc_NtkRenodeCone_rec( Abc_ObjFanin(pNode,0), vCone );
- Abc_NtkRenodeCone_rec( Abc_ObjFanin(pNode,1), vCone );
+ int i, RetValue, nClauses;
+ // set internal mapper parameters
+ for ( i = 0; i < If_CutLeaveNum(pCut); i++ )
+ pCut->pPerm[i] = 1;
+ // compute ISOP for the positive phase
+ RetValue = Kit_TruthIsop( If_CutTruth(pCut), If_CutLeaveNum(pCut), s_vMemory, 0 );
+ if ( RetValue == -1 )
+ return IF_COST_MAX;
+ assert( RetValue == 0 || RetValue == 1 );
+ nClauses = Vec_IntSize( s_vMemory );
+ // compute ISOP for the negative phase
+ Kit_TruthNot( If_CutTruth(pCut), If_CutTruth(pCut), If_CutLeaveNum(pCut) );
+ RetValue = Kit_TruthIsop( If_CutTruth(pCut), If_CutLeaveNum(pCut), s_vMemory, 0 );
+ Kit_TruthNot( If_CutTruth(pCut), If_CutTruth(pCut), If_CutLeaveNum(pCut) );
+ if ( RetValue == -1 )
+ return IF_COST_MAX;
+ assert( RetValue == 0 || RetValue == 1 );
+ nClauses += Vec_IntSize( s_vMemory );
+ return nClauses;
}
/**Function*************************************************************
- Synopsis [Collects the fanins of a large node.]
+ Synopsis [Computes the cost of MV-SOP of the cut function.]
Description []
@@ -592,13 +279,29 @@ void Abc_NtkRenodeCone_rec( Abc_Obj_t * pNode, Vec_Ptr_t * vCone )
SeeAlso []
***********************************************************************/
-void Abc_NtkRenodeCone( Abc_Obj_t * pNode, Vec_Ptr_t * vCone )
+int Abc_NtkRenodeEvalMv( If_Cut_t * pCut )
{
- assert( !Abc_ObjIsComplement(pNode) );
- assert( Abc_ObjIsNode(pNode) );
- vCone->nSize = 0;
- Abc_NtkRenodeCone_rec( Abc_ObjFanin(pNode,0), vCone );
- Abc_NtkRenodeCone_rec( Abc_ObjFanin(pNode,1), vCone );
+ int i, RetValue;
+ // set internal mapper parameters
+ for ( i = 0; i < If_CutLeaveNum(pCut); i++ )
+ pCut->pPerm[i] = 1;
+ // compute ISOP for the positive phase
+ RetValue = Kit_TruthIsop( If_CutTruth(pCut), If_CutLeaveNum(pCut), s_vMemory, 0 );
+ if ( RetValue == -1 )
+ return IF_COST_MAX;
+ assert( RetValue == 0 || RetValue == 1 );
+ // compute ISOP for the negative phase
+ Kit_TruthNot( If_CutTruth(pCut), If_CutTruth(pCut), If_CutLeaveNum(pCut) );
+ RetValue = Kit_TruthIsop( If_CutTruth(pCut), If_CutLeaveNum(pCut), s_vMemory2, 0 );
+ Kit_TruthNot( If_CutTruth(pCut), If_CutTruth(pCut), If_CutLeaveNum(pCut) );
+ if ( RetValue == -1 )
+ return IF_COST_MAX;
+ assert( RetValue == 0 || RetValue == 1 );
+ // return the cost of the cut
+ RetValue = Abc_NodeEvalMvCost( If_CutLeaveNum(pCut), s_vMemory, s_vMemory2 );
+ if ( RetValue >= IF_COST_MAX )
+ return IF_COST_MAX;
+ return RetValue;
}
////////////////////////////////////////////////////////////////////////
diff --git a/src/base/abci/abcReorder.c b/src/base/abci/abcReorder.c
new file mode 100644
index 00000000..182780cd
--- /dev/null
+++ b/src/base/abci/abcReorder.c
@@ -0,0 +1,102 @@
+/**CFile****************************************************************
+
+ FileName [abcReorder.c]
+
+ SystemName [ABC: Logic synthesis and verification system.]
+
+ PackageName [Network and node package.]
+
+ Synopsis [Reordering local BDDs of the nodes.]
+
+ Author [Alan Mishchenko]
+
+ Affiliation [UC Berkeley]
+
+ Date [Ver. 1.0. Started - June 20, 2005.]
+
+ Revision [$Id: abcReorder.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "abc.h"
+#include "reo.h"
+
+////////////////////////////////////////////////////////////////////////
+/// DECLARATIONS ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+/// FUNCTION DEFINITIONS ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+ Synopsis [Reorders BDD of the local function of the node.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Abc_NodeBddReorder( reo_man * p, Abc_Obj_t * pNode )
+{
+ Abc_Obj_t * pFanin;
+ DdNode * bFunc;
+ int * pOrder, i;
+ // create the temporary array for the variable order
+ pOrder = ALLOC( int, Abc_ObjFaninNum(pNode) );
+ for ( i = 0; i < Abc_ObjFaninNum(pNode); i++ )
+ pOrder[i] = -1;
+ // reorder the BDD
+ bFunc = Extra_Reorder( p, pNode->pNtk->pManFunc, pNode->pData, pOrder ); Cudd_Ref( bFunc );
+ Cudd_RecursiveDeref( pNode->pNtk->pManFunc, pNode->pData );
+ pNode->pData = bFunc;
+ // update the fanin order
+ Abc_ObjForEachFanin( pNode, pFanin, i )
+ pOrder[i] = pNode->vFanins.pArray[ pOrder[i] ];
+ Abc_ObjForEachFanin( pNode, pFanin, i )
+ pNode->vFanins.pArray[i] = pOrder[i];
+ free( pOrder );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Reorders BDDs of the local functions.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Abc_NtkBddReorder( Abc_Ntk_t * pNtk, int fVerbose )
+{
+ reo_man * p;
+ Abc_Obj_t * pNode;
+ int i;
+ Abc_NtkRemoveDupFanins( pNtk );
+ Abc_NtkMinimumBase( pNtk );
+ p = Extra_ReorderInit( Abc_NtkGetFaninMax(pNtk), 100 );
+ Abc_NtkForEachNode( pNtk, pNode, i )
+ {
+ if ( Abc_ObjFaninNum(pNode) < 3 )
+ continue;
+ if ( fVerbose )
+ fprintf( stdout, "%10s: ", Abc_ObjName(pNode) );
+ if ( fVerbose )
+ fprintf( stdout, "Before = %5d BDD nodes. ", Cudd_DagSize(pNode->pData) );
+ Abc_NodeBddReorder( p, pNode );
+ if ( fVerbose )
+ fprintf( stdout, "After = %5d BDD nodes.\n", Cudd_DagSize(pNode->pData) );
+ }
+ Extra_ReorderQuit( p );
+}
+
+////////////////////////////////////////////////////////////////////////
+/// END OF FILE ///
+////////////////////////////////////////////////////////////////////////
+
+
diff --git a/src/base/abci/abcRestruct.c b/src/base/abci/abcRestruct.c
new file mode 100644
index 00000000..aa9a2998
--- /dev/null
+++ b/src/base/abci/abcRestruct.c
@@ -0,0 +1,1497 @@
+/**CFile****************************************************************
+
+ FileName [abcRestruct.c]
+
+ SystemName [ABC: Logic synthesis and verification system.]
+
+ PackageName [Network and node package.]
+
+ Synopsis []
+
+ Author [Alan Mishchenko]
+
+ Affiliation [UC Berkeley]
+
+ Date [Ver. 1.0. Started - June 20, 2005.]
+
+ Revision [$Id: abcRestruct.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "abc.h"
+#include "dec.h"
+#include "dsd.h"
+#include "cut.h"
+
+////////////////////////////////////////////////////////////////////////
+/// DECLARATIONS ///
+////////////////////////////////////////////////////////////////////////
+
+#define RST_RANDOM_UNSIGNED ((((unsigned)rand()) << 24) ^ (((unsigned)rand()) << 12) ^ ((unsigned)rand()))
+
+typedef struct Abc_ManRst_t_ Abc_ManRst_t;
+struct Abc_ManRst_t_
+{
+ // the network
+ Abc_Ntk_t * pNtk; // the network for restructuring
+ // user specified parameters
+ int nCutMax; // the limit on the size of the supernode
+ int fUpdateLevel; // turns on watching the number of levels
+ int fUseZeros; // turns on zero-cost replacements
+ int fVerbose; // the verbosity flag
+ // internal data structures
+ DdManager * dd; // the BDD manager
+ Dsd_Manager_t * pManDsd; // the DSD manager
+ Vec_Ptr_t * vVisited; // temporary
+ Vec_Ptr_t * vLeaves; // temporary
+ Vec_Ptr_t * vDecs; // temporary
+ Vec_Ptr_t * vTemp; // temporary
+ Vec_Int_t * vSims; // temporary
+ Vec_Int_t * vRands; // temporary
+ Vec_Int_t * vOnes; // temporary
+ Vec_Int_t * vBinate; // temporary
+ Vec_Int_t * vTwos; // temporary
+ // node statistics
+ int nLastGain;
+ int nCutsConsidered;
+ int nCutsExplored;
+ int nNodesConsidered;
+ int nNodesRestructured;
+ int nNodesGained;
+ // runtime statistics
+ int timeCut;
+ int timeBdd;
+ int timeDsd;
+ int timeEval;
+ int timeRes;
+ int timeNtk;
+ int timeTotal;
+};
+
+static Dec_Graph_t * Abc_NodeResubstitute( Abc_ManRst_t * p, Abc_Obj_t * pNode, Cut_Cut_t * pCutList );
+
+static Dec_Graph_t * Abc_NodeRestructure( Abc_ManRst_t * p, Abc_Obj_t * pNode, Cut_Cut_t * pCutList );
+static Dec_Graph_t * Abc_NodeRestructureCut( Abc_ManRst_t * p, Abc_Obj_t * pNode, Cut_Cut_t * pCut );
+static Dec_Graph_t * Abc_NodeEvaluateDsd( Abc_ManRst_t * pManRst, Dsd_Node_t * pNodeDsd, Abc_Obj_t * pRoot, int Required, int nNodesSaved, int * pnNodesAdded );
+
+static Cut_Man_t * Abc_NtkStartCutManForRestruct( Abc_Ntk_t * pNtk, int nCutMax, int fDag );
+static Abc_ManRst_t * Abc_NtkManRstStart( int nCutMax, bool fUpdateLevel, bool fUseZeros, bool fVerbose );
+static void Abc_NtkManRstStop( Abc_ManRst_t * p );
+static void Abc_NtkManRstPrintStats( Abc_ManRst_t * p );
+
+////////////////////////////////////////////////////////////////////////
+/// FUNCTION DEFINITIONS ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+ Synopsis [Implements AIG restructuring.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Abc_NtkRestructure( Abc_Ntk_t * pNtk, int nCutMax, bool fUpdateLevel, bool fUseZeros, bool fVerbose )
+{
+ extern void Dec_GraphUpdateNetwork( Abc_Obj_t * pRoot, Dec_Graph_t * pGraph, bool fUpdateLevel, int nGain );
+ ProgressBar * pProgress;
+ Abc_ManRst_t * pManRst;
+ Cut_Man_t * pManCut;
+ Cut_Cut_t * pCutList;
+ Dec_Graph_t * pGraph;
+ Abc_Obj_t * pNode;
+ int clk, clkStart = clock();
+ int fMulti = 1;
+ int fResub = 0;
+ int i, nNodes;
+
+ assert( Abc_NtkIsStrash(pNtk) );
+ // cleanup the AIG
+ Abc_AigCleanup(pNtk->pManFunc);
+ Abc_NtkCleanCopy(pNtk);
+
+ // compute the reverse levels if level update is requested
+ if ( fUpdateLevel )
+ Abc_NtkStartReverseLevels( pNtk, 0 );
+
+ // start the restructuring manager
+ pManRst = Abc_NtkManRstStart( nCutMax, fUpdateLevel, fUseZeros, fVerbose );
+ pManRst->pNtk = pNtk;
+ // start the cut manager
+clk = clock();
+ pManCut = Abc_NtkStartCutManForRestruct( pNtk, nCutMax, fMulti );
+pManRst->timeCut += clock() - clk;
+// pNtk->pManCut = pManCut;
+
+ // resynthesize each node once
+ nNodes = Abc_NtkObjNumMax(pNtk);
+ pProgress = Extra_ProgressBarStart( stdout, nNodes );
+ Abc_NtkForEachNode( pNtk, pNode, i )
+ {
+ Extra_ProgressBarUpdate( pProgress, i, NULL );
+ // skip the constant node
+// if ( Abc_NodeIsConst(pNode) )
+// continue;
+ // skip persistant nodes
+ if ( Abc_NodeIsPersistant(pNode) )
+ continue;
+ // skip the node if it is inside the tree
+// if ( Abc_ObjFanoutNum(pNode) < 2 )
+// continue;
+ // skip the nodes with too many fanouts
+ if ( Abc_ObjFanoutNum(pNode) > 1000 )
+ continue;
+ // stop if all nodes have been tried once
+ if ( i >= nNodes )
+ break;
+ // get the cuts for the given node
+clk = clock();
+ pCutList = Abc_NodeGetCutsRecursive( pManCut, pNode, fMulti, 0 );
+pManRst->timeCut += clock() - clk;
+
+ // perform restructuring
+clk = clock();
+ if ( fResub )
+ pGraph = Abc_NodeResubstitute( pManRst, pNode, pCutList );
+ else
+ pGraph = Abc_NodeRestructure( pManRst, pNode, pCutList );
+pManRst->timeRes += clock() - clk;
+ if ( pGraph == NULL )
+ continue;
+
+ // acceptable replacement found, update the graph
+clk = clock();
+ Dec_GraphUpdateNetwork( pNode, pGraph, fUpdateLevel, pManRst->nLastGain );
+pManRst->timeNtk += clock() - clk;
+ Dec_GraphFree( pGraph );
+ }
+ Extra_ProgressBarStop( pProgress );
+pManRst->timeTotal = clock() - clkStart;
+
+ // print statistics of the manager
+// if ( fVerbose )
+ Abc_NtkManRstPrintStats( pManRst );
+ // delete the managers
+ Cut_ManStop( pManCut );
+ Abc_NtkManRstStop( pManRst );
+ // put the nodes into the DFS order and reassign their IDs
+ Abc_NtkReassignIds( pNtk );
+// Abc_AigCheckFaninOrder( pNtk->pManFunc );
+ // fix the levels
+ if ( fUpdateLevel )
+ Abc_NtkStopReverseLevels( pNtk );
+ else
+ Abc_NtkLevel( pNtk );
+ // check
+ if ( !Abc_NtkCheck( pNtk ) )
+ {
+ printf( "Abc_NtkRefactor: The network check has failed.\n" );
+ return 0;
+ }
+ return 1;
+}
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Abc_RestructNodeDivisors( Abc_ManRst_t * p, Abc_Obj_t * pRoot, int nNodesSaved )
+{
+ Abc_Obj_t * pNode, * pFanout;//, * pFanin;
+ int i, k;
+ // start with the leaves
+ Vec_PtrClear( p->vDecs );
+ Vec_PtrForEachEntry( p->vLeaves, pNode, i )
+ {
+ Vec_PtrPush( p->vDecs, pNode );
+ assert( pNode->fMarkC == 0 );
+ pNode->fMarkC = 1;
+ }
+ // explore the fanouts
+ Vec_PtrForEachEntry( p->vDecs, pNode, i )
+ {
+ // if the fanout has both fanins in the set, add it
+ Abc_ObjForEachFanout( pNode, pFanout, k )
+ {
+ if ( pFanout->fMarkC || Abc_ObjIsPo(pFanout) )
+ continue;
+ if ( Abc_ObjFanin0(pFanout)->fMarkC && Abc_ObjFanin1(pFanout)->fMarkC )
+ {
+ Vec_PtrPush( p->vDecs, pFanout );
+ pFanout->fMarkC = 1;
+ }
+ }
+ }
+ // unmark the nodes
+ Vec_PtrForEachEntry( p->vDecs, pNode, i )
+ pNode->fMarkC = 0;
+/*
+ // print the nodes
+ Vec_PtrForEachEntryStart( p->vDecs, pNode, i, Vec_PtrSize(p->vLeaves) )
+ {
+ printf( "%2d %s = ", i, Abc_NodeIsTravIdCurrent(pNode)? "*" : " " );
+ // find the first fanin
+ Vec_PtrForEachEntry( p->vDecs, pFanin, k )
+ if ( Abc_ObjFanin0(pNode) == pFanin )
+ break;
+ if ( k < Vec_PtrSize(p->vLeaves) )
+ printf( "%c", 'a' + k );
+ else
+ printf( "%d", k );
+ printf( "%s ", Abc_ObjFaninC0(pNode)? "\'" : "" );
+ // find the second fanin
+ Vec_PtrForEachEntry( p->vDecs, pFanin, k )
+ if ( Abc_ObjFanin1(pNode) == pFanin )
+ break;
+ if ( k < Vec_PtrSize(p->vLeaves) )
+ printf( "%c", 'a' + k );
+ else
+ printf( "%d", k );
+ printf( "%s ", Abc_ObjFaninC1(pNode)? "\'" : "" );
+ printf( "\n" );
+ }
+*/
+ printf( "%d\n", Vec_PtrSize(p->vDecs)-nNodesSaved-Vec_PtrSize(p->vLeaves) );
+}
+
+
+/**Function*************************************************************
+
+ Synopsis [Starts the cut manager for rewriting.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Dec_Graph_t * Abc_NodeRestructure( Abc_ManRst_t * p, Abc_Obj_t * pNode, Cut_Cut_t * pCutList )
+{
+ Dec_Graph_t * pGraph;
+ Cut_Cut_t * pCut;
+// int nCuts;
+ p->nNodesConsidered++;
+/*
+ // count the number of cuts with four inputs or more
+ nCuts = 0;
+ for ( pCut = pCutList; pCut; pCut = pCut->pNext )
+ nCuts += (int)(pCut->nLeaves > 3);
+ printf( "-----------------------------------\n" );
+ printf( "Node %6d : Factor-cuts = %5d.\n", pNode->Id, nCuts );
+*/
+ // go through the interesting cuts
+ for ( pCut = pCutList; pCut; pCut = pCut->pNext )
+ {
+ if ( pCut->nLeaves < 4 )
+ continue;
+ if ( pGraph = Abc_NodeRestructureCut( p, pNode, pCut ) )
+ return pGraph;
+ }
+ return NULL;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Starts the cut manager for rewriting.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Dec_Graph_t * Abc_NodeRestructureCut( Abc_ManRst_t * p, Abc_Obj_t * pRoot, Cut_Cut_t * pCut )
+{
+ Dec_Graph_t * pGraph;
+ Dsd_Node_t * pNodeDsd;
+ Abc_Obj_t * pLeaf;
+ DdNode * bFunc;
+ int nNodesSaved, nNodesAdded;
+ int Required, nMaxSize, clk, i;
+ int fVeryVerbose = 0;
+
+ p->nCutsConsidered++;
+
+ // get the required time for the node
+ Required = p->fUpdateLevel? Abc_ObjRequiredLevel(pRoot) : ABC_INFINITY;
+
+ // collect the leaves of the cut
+ Vec_PtrClear( p->vLeaves );
+ for ( i = 0; i < (int)pCut->nLeaves; i++ )
+ {
+ pLeaf = Abc_NtkObj(pRoot->pNtk, pCut->pLeaves[i]);
+ if ( pLeaf == NULL ) // the so-called "bad cut phenomenon" is due to removed nodes
+ return NULL;
+ Vec_PtrPush( p->vLeaves, pLeaf );
+ }
+
+ if ( pRoot->Id == 29 )
+ {
+ int x = 0;
+ }
+
+clk = clock();
+ // collect the internal nodes of the cut
+// Abc_NodeConeCollect( &pRoot, 1, p->vLeaves, p->vVisited, 0 );
+ // derive the BDD of the cut
+ bFunc = Abc_NodeConeBdd( p->dd, p->dd->vars, pRoot, p->vLeaves, p->vVisited ); Cudd_Ref( bFunc );
+p->timeBdd += clock() - clk;
+
+ // consider the special case, when the function is a constant
+ if ( Cudd_IsConstant(bFunc) )
+ {
+ p->nLastGain = Abc_NodeMffcSize( pRoot );
+ p->nNodesGained += p->nLastGain;
+ p->nNodesRestructured++;
+ Cudd_RecursiveDeref( p->dd, bFunc );
+ if ( Cudd_IsComplement(bFunc) )
+ return Dec_GraphCreateConst0();
+ return Dec_GraphCreateConst1();
+ }
+
+clk = clock();
+ // try disjoint support decomposition
+ pNodeDsd = Dsd_DecomposeOne( p->pManDsd, bFunc );
+p->timeDsd += clock() - clk;
+
+ // skip nodes with non-decomposable blocks
+ Dsd_TreeNodeGetInfoOne( pNodeDsd, NULL, &nMaxSize );
+ if ( nMaxSize > 3 )
+ {
+ Cudd_RecursiveDeref( p->dd, bFunc );
+ return NULL;
+ }
+
+
+/*
+ // skip nodes that cannot be improved
+ if ( Vec_PtrSize(p->vVisited) <= Dsd_TreeGetAigCost(pNodeDsd) )
+ {
+ Cudd_RecursiveDeref( p->dd, bFunc );
+ return NULL;
+ }
+*/
+
+ p->nCutsExplored++;
+
+ // mark the fanin boundary
+ // (can mark only essential fanins, belonging to bNodeFunc!)
+ Vec_PtrForEachEntry( p->vLeaves, pLeaf, i )
+ pLeaf->vFanouts.nSize++;
+ // label MFFC with current traversal ID
+ Abc_NtkIncrementTravId( pRoot->pNtk );
+ nNodesSaved = Abc_NodeMffcLabelAig( pRoot );
+ // unmark the fanin boundary and set the fanins as leaves in the form
+ Vec_PtrForEachEntry( p->vLeaves, pLeaf, i )
+ pLeaf->vFanouts.nSize--;
+/*
+ if ( nNodesSaved < 3 )
+ {
+ Cudd_RecursiveDeref( p->dd, bFunc );
+ return NULL;
+ }
+*/
+
+/*
+ printf( "%5d : Cut-size = %d. Old AIG = %2d. New AIG = %2d. Old MFFC = %2d.\n",
+ pRoot->Id, pCut->nLeaves, Vec_PtrSize(p->vVisited), Dsd_TreeGetAigCost(pNodeDsd),
+ nNodesSaved );
+ Dsd_NodePrint( stdout, pNodeDsd );
+
+ Abc_RestructNodeDivisors( p, pRoot );
+
+ if ( pRoot->Id == 433 )
+ {
+ int x = 0;
+ }
+*/
+// Abc_RestructNodeDivisors( p, pRoot, nNodesSaved );
+
+
+ // detect how many new nodes will be added (while taking into account reused nodes)
+clk = clock();
+ if ( nMaxSize > 3 )
+ pGraph = NULL;
+ else
+ pGraph = Abc_NodeEvaluateDsd( p, pNodeDsd, pRoot, Required, nNodesSaved, &nNodesAdded );
+// pGraph = NULL;
+p->timeEval += clock() - clk;
+
+ // quit if there is no improvement
+ if ( pGraph == NULL || nNodesAdded == -1 || nNodesAdded == nNodesSaved && !p->fUseZeros )
+ {
+ Cudd_RecursiveDeref( p->dd, bFunc );
+ if ( pGraph ) Dec_GraphFree( pGraph );
+ return NULL;
+ }
+
+/*
+ // print stats
+ printf( "%5d : Cut-size = %d. Old AIG = %2d. New AIG = %2d. Old MFFC = %2d. New MFFC = %2d. Gain = %d.\n",
+ pRoot->Id, pCut->nLeaves, Vec_PtrSize(p->vVisited), Dsd_TreeGetAigCost(pNodeDsd),
+ nNodesSaved, nNodesAdded, (nNodesAdded == -1)? 0 : nNodesSaved-nNodesAdded );
+// Dsd_NodePrint( stdout, pNodeDsd );
+// Dec_GraphPrint( stdout, pGraph, NULL, NULL );
+*/
+
+ // compute the total gain in the number of nodes
+ p->nLastGain = nNodesSaved - nNodesAdded;
+ p->nNodesGained += p->nLastGain;
+ p->nNodesRestructured++;
+
+ // report the progress
+ if ( fVeryVerbose )
+ {
+ printf( "Node %6s : ", Abc_ObjName(pRoot) );
+ printf( "Cone = %2d. ", p->vLeaves->nSize );
+ printf( "BDD = %2d. ", Cudd_DagSize(bFunc) );
+ printf( "FF = %2d. ", 1 + Dec_GraphNodeNum(pGraph) );
+ printf( "MFFC = %2d. ", nNodesSaved );
+ printf( "Add = %2d. ", nNodesAdded );
+ printf( "GAIN = %2d. ", p->nLastGain );
+ printf( "\n" );
+ }
+ Cudd_RecursiveDeref( p->dd, bFunc );
+ return pGraph;
+}
+
+
+/**Function*************************************************************
+
+ Synopsis [Moves closer to the end the node that is best for sharing.]
+
+ Description [If the flag is set, tries to find an EXOR, otherwise, tries
+ to find an OR.]
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Abc_NodeEdgeDsdPermute( Dec_Graph_t * pGraph, Abc_ManRst_t * pManRst, Vec_Int_t * vEdges, int fExor )
+{
+ Dec_Edge_t eNode1, eNode2, eNode3;
+ Abc_Obj_t * pNode1, * pNode2, * pNode3, * pTemp;
+ int LeftBound = 0, RightBound, i;
+ // get the right bound
+ RightBound = Vec_IntSize(vEdges) - 2;
+ assert( LeftBound <= RightBound );
+ if ( LeftBound == RightBound )
+ return;
+ // get the two last nodes
+ eNode1 = Dec_IntToEdge( Vec_IntEntry(vEdges, RightBound + 1) );
+ eNode2 = Dec_IntToEdge( Vec_IntEntry(vEdges, RightBound ) );
+ pNode1 = Dec_GraphNode( pGraph, eNode1.Node )->pFunc;
+ pNode2 = Dec_GraphNode( pGraph, eNode2.Node )->pFunc;
+ pNode1 = !pNode1? NULL : Abc_ObjNotCond( pNode1, eNode1.fCompl );
+ pNode2 = !pNode2? NULL : Abc_ObjNotCond( pNode2, eNode2.fCompl );
+ // quit if the last node does not exist
+ if ( pNode1 == NULL )
+ return;
+ // find the first node that can be shared
+ for ( i = RightBound; i >= LeftBound; i-- )
+ {
+ // get the third node
+ eNode3 = Dec_IntToEdge( Vec_IntEntry(vEdges, i) );
+ pNode3 = Dec_GraphNode( pGraph, eNode3.Node )->pFunc;
+ pNode3 = !pNode3? NULL : Abc_ObjNotCond( pNode3, eNode3.fCompl );
+ if ( pNode3 == NULL )
+ continue;
+ // check if the node exists
+ if ( fExor )
+ {
+ if ( pNode1 && pNode3 )
+ {
+ pTemp = Abc_AigXorLookup( pManRst->pNtk->pManFunc, pNode1, pNode3, NULL );
+ if ( !pTemp || Abc_NodeIsTravIdCurrent(Abc_ObjRegular(pTemp)) )
+ continue;
+
+ if ( pNode3 == pNode2 )
+ return;
+ Vec_IntWriteEntry( vEdges, i, Dec_EdgeToInt(eNode2) );
+ Vec_IntWriteEntry( vEdges, RightBound, Dec_EdgeToInt(eNode3) );
+ return;
+ }
+ }
+ else
+ {
+ if ( pNode1 && pNode3 )
+ {
+ pTemp = Abc_AigAndLookup( pManRst->pNtk->pManFunc, Abc_ObjNot(pNode1), Abc_ObjNot(pNode3) );
+ if ( !pTemp || Abc_NodeIsTravIdCurrent(Abc_ObjRegular(pTemp)) )
+ continue;
+
+ if ( eNode3.Node == eNode2.Node )
+ return;
+ Vec_IntWriteEntry( vEdges, i, Dec_EdgeToInt(eNode2) );
+ Vec_IntWriteEntry( vEdges, RightBound, Dec_EdgeToInt(eNode3) );
+ return;
+ }
+ }
+ }
+}
+
+/**Function*************************************************************
+
+ Synopsis [Adds the new edge in the given order.]
+
+ Description [Similar to Vec_IntPushOrder, except in decreasing order.]
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Abc_NodeEdgeDsdPushOrdered( Dec_Graph_t * pGraph, Vec_Int_t * vEdges, int Edge )
+{
+ int i, NodeOld, NodeNew;
+ vEdges->nSize++;
+ for ( i = vEdges->nSize-2; i >= 0; i-- )
+ {
+ NodeOld = Dec_IntToEdge(vEdges->pArray[i]).Node;
+ NodeNew = Dec_IntToEdge(Edge).Node;
+ // use <= because we are trying to push the new (non-existent) nodes as far as possible
+ if ( Dec_GraphNode(pGraph, NodeOld)->Level <= Dec_GraphNode(pGraph, NodeNew)->Level )
+ vEdges->pArray[i+1] = vEdges->pArray[i];
+ else
+ break;
+ }
+ vEdges->pArray[i+1] = Edge;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Evaluation one DSD.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Dec_Edge_t Abc_NodeEvaluateDsd_rec( Dec_Graph_t * pGraph, Abc_ManRst_t * pManRst, Dsd_Node_t * pNodeDsd, int Required, int nNodesSaved, int * pnNodesAdded )
+{
+ Dec_Edge_t eNode1, eNode2, eNode3, eResult, eQuit = { 0, 2006 };
+ Abc_Obj_t * pNode1, * pNode2, * pNode3, * pNode4, * pTemp;
+ Dsd_Node_t * pChildDsd;
+ Dsd_Type_t DecType;
+ Vec_Int_t * vEdges;
+ int Level1, Level2, Level3, Level4;
+ int i, Index, fCompl, Type;
+
+ // remove the complemented attribute
+ fCompl = Dsd_IsComplement( pNodeDsd );
+ pNodeDsd = Dsd_Regular( pNodeDsd );
+
+ // consider the trivial case
+ DecType = Dsd_NodeReadType( pNodeDsd );
+ if ( DecType == DSD_NODE_BUF )
+ {
+ Index = Dsd_NodeReadFunc(pNodeDsd)->index;
+ assert( Index < Dec_GraphLeaveNum(pGraph) );
+ eResult = Dec_EdgeCreate( Index, fCompl );
+ return eResult;
+ }
+ assert( DecType == DSD_NODE_OR || DecType == DSD_NODE_EXOR || DecType == DSD_NODE_PRIME );
+
+ // solve the problem for the children
+ vEdges = Vec_IntAlloc( Dsd_NodeReadDecsNum(pNodeDsd) );
+ Dsd_NodeForEachChild( pNodeDsd, i, pChildDsd )
+ {
+ eResult = Abc_NodeEvaluateDsd_rec( pGraph, pManRst, pChildDsd, Required, nNodesSaved, pnNodesAdded );
+ if ( eResult.Node == eQuit.Node ) // infeasible
+ {
+ Vec_IntFree( vEdges );
+ return eQuit;
+ }
+ // order the inputs only if this is OR or EXOR
+ if ( DecType == DSD_NODE_PRIME )
+ Vec_IntPush( vEdges, Dec_EdgeToInt(eResult) );
+ else
+ Abc_NodeEdgeDsdPushOrdered( pGraph, vEdges, Dec_EdgeToInt(eResult) );
+ }
+ // the edges are sorted by the level of their nodes in decreasing order
+
+
+ // consider special cases
+ if ( DecType == DSD_NODE_OR )
+ {
+ // try to balance the nodes by delay
+ assert( Vec_IntSize(vEdges) > 1 );
+ while ( Vec_IntSize(vEdges) > 1 )
+ {
+ // permute the last two entries
+ if ( Vec_IntSize(vEdges) > 2 )
+ Abc_NodeEdgeDsdPermute( pGraph, pManRst, vEdges, 0 );
+ // get the two last nodes
+ eNode1 = Dec_IntToEdge( Vec_IntPop(vEdges) );
+ eNode2 = Dec_IntToEdge( Vec_IntPop(vEdges) );
+ pNode1 = Dec_GraphNode( pGraph, eNode1.Node )->pFunc;
+ pNode2 = Dec_GraphNode( pGraph, eNode2.Node )->pFunc;
+ pNode1 = !pNode1? NULL : Abc_ObjNotCond( pNode1, eNode1.fCompl );
+ pNode2 = !pNode2? NULL : Abc_ObjNotCond( pNode2, eNode2.fCompl );
+ // check if the new node exists
+ pNode3 = NULL;
+ if ( pNode1 && pNode2 )
+ {
+ pNode3 = Abc_AigAndLookup( pManRst->pNtk->pManFunc, Abc_ObjNot(pNode1), Abc_ObjNot(pNode2) );
+ pNode3 = !pNode3? NULL : Abc_ObjNot(pNode3);
+ }
+ // create the new node
+ eNode3 = Dec_GraphAddNodeOr( pGraph, eNode1, eNode2 );
+ // set level
+ Level1 = Dec_GraphNode( pGraph, eNode1.Node )->Level;
+ Level2 = Dec_GraphNode( pGraph, eNode2.Node )->Level;
+ Dec_GraphNode( pGraph, eNode3.Node )->Level = 1 + ABC_MAX(Level1, Level2);
+ // get the new node if possible
+ if ( pNode3 )
+ {
+ Dec_GraphNode( pGraph, eNode3.Node )->pFunc = Abc_ObjNotCond(pNode3, eNode3.fCompl);
+ Level3 = Dec_GraphNode( pGraph, eNode3.Node )->Level;
+ assert( Required == ABC_INFINITY || Level3 == (int)Abc_ObjRegular(pNode3)->Level );
+ }
+ if ( !pNode3 || Abc_NodeIsTravIdCurrent(Abc_ObjRegular(pNode3)) )
+ {
+ (*pnNodesAdded)++;
+ if ( *pnNodesAdded > nNodesSaved )
+ {
+ Vec_IntFree( vEdges );
+ return eQuit;
+ }
+ }
+ // add the resulting node to the form
+ Abc_NodeEdgeDsdPushOrdered( pGraph, vEdges, Dec_EdgeToInt(eNode3) );
+ }
+ // get the last node
+ eResult = Dec_IntToEdge( Vec_IntPop(vEdges) );
+ Vec_IntFree( vEdges );
+ // complement the graph if the node was complemented
+ eResult.fCompl ^= fCompl;
+ return eResult;
+ }
+ if ( DecType == DSD_NODE_EXOR )
+ {
+ // try to balance the nodes by delay
+ assert( Vec_IntSize(vEdges) > 1 );
+ while ( Vec_IntSize(vEdges) > 1 )
+ {
+ // permute the last two entries
+ if ( Vec_IntSize(vEdges) > 2 )
+ Abc_NodeEdgeDsdPermute( pGraph, pManRst, vEdges, 1 );
+ // get the two last nodes
+ eNode1 = Dec_IntToEdge( Vec_IntPop(vEdges) );
+ eNode2 = Dec_IntToEdge( Vec_IntPop(vEdges) );
+ pNode1 = Dec_GraphNode( pGraph, eNode1.Node )->pFunc;
+ pNode2 = Dec_GraphNode( pGraph, eNode2.Node )->pFunc;
+ pNode1 = !pNode1? NULL : Abc_ObjNotCond( pNode1, eNode1.fCompl );
+ pNode2 = !pNode2? NULL : Abc_ObjNotCond( pNode2, eNode2.fCompl );
+ // check if the new node exists
+ Type = 0;
+ pNode3 = NULL;
+ if ( pNode1 && pNode2 )
+ pNode3 = Abc_AigXorLookup( pManRst->pNtk->pManFunc, pNode1, pNode2, &Type );
+ // create the new node
+ eNode3 = Dec_GraphAddNodeXor( pGraph, eNode1, eNode2, Type ); // should have the same structure as in AIG
+ // set level
+ Level1 = Dec_GraphNode( pGraph, eNode1.Node )->Level;
+ Level2 = Dec_GraphNode( pGraph, eNode2.Node )->Level;
+ Dec_GraphNode( pGraph, eNode3.Node )->Level = 2 + ABC_MAX(Level1, Level2);
+ // get the new node if possible
+ if ( pNode3 )
+ {
+ Dec_GraphNode( pGraph, eNode3.Node )->pFunc = Abc_ObjNotCond(pNode3, eNode3.fCompl);
+ Level3 = Dec_GraphNode( pGraph, eNode3.Node )->Level;
+ assert( Required == ABC_INFINITY || Level3 == (int)Abc_ObjRegular(pNode3)->Level );
+ }
+ if ( !pNode3 || Abc_NodeIsTravIdCurrent(Abc_ObjRegular(pNode3)) )
+ {
+ (*pnNodesAdded)++;
+ if ( !pNode1 || !pNode2 )
+ (*pnNodesAdded) += 2;
+ else if ( Type == 0 )
+ {
+ pTemp = Abc_AigAndLookup( pManRst->pNtk->pManFunc, pNode1, Abc_ObjNot(pNode2) );
+ if ( !pTemp || Abc_NodeIsTravIdCurrent(Abc_ObjRegular(pTemp)) )
+ (*pnNodesAdded)++;
+ pTemp = Abc_AigAndLookup( pManRst->pNtk->pManFunc, Abc_ObjNot(pNode1), pNode2 );
+ if ( !pTemp || Abc_NodeIsTravIdCurrent(Abc_ObjRegular(pTemp)) )
+ (*pnNodesAdded)++;
+ }
+ else
+ {
+ pTemp = Abc_AigAndLookup( pManRst->pNtk->pManFunc, Abc_ObjNot(pNode1), Abc_ObjNot(pNode2) );
+ if ( !pTemp || Abc_NodeIsTravIdCurrent(Abc_ObjRegular(pTemp)) )
+ (*pnNodesAdded)++;
+ pTemp = Abc_AigAndLookup( pManRst->pNtk->pManFunc, pNode1, pNode2 );
+ if ( !pTemp || Abc_NodeIsTravIdCurrent(Abc_ObjRegular(pTemp)) )
+ (*pnNodesAdded)++;
+ }
+ if ( *pnNodesAdded > nNodesSaved )
+ {
+ Vec_IntFree( vEdges );
+ return eQuit;
+ }
+ }
+ // add the resulting node to the form
+ Abc_NodeEdgeDsdPushOrdered( pGraph, vEdges, Dec_EdgeToInt(eNode3) );
+ }
+ // get the last node
+ eResult = Dec_IntToEdge( Vec_IntPop(vEdges) );
+ Vec_IntFree( vEdges );
+ // complement the graph if the node is complemented
+ eResult.fCompl ^= fCompl;
+ return eResult;
+ }
+ if ( DecType == DSD_NODE_PRIME )
+ {
+ DdNode * bLocal, * bVar, * bCofT, * bCofE;
+ bLocal = Dsd_TreeGetPrimeFunction( pManRst->dd, pNodeDsd ); Cudd_Ref( bLocal );
+//Extra_bddPrint( pManRst->dd, bLocal );
+
+ bVar = pManRst->dd->vars[0];
+ bCofE = Cudd_Cofactor( pManRst->dd, bLocal, Cudd_Not(bVar) ); Cudd_Ref( bCofE );
+ bCofT = Cudd_Cofactor( pManRst->dd, bLocal, bVar ); Cudd_Ref( bCofT );
+ if ( !Extra_bddIsVar(bCofE) || !Extra_bddIsVar(bCofT) )
+ {
+ Cudd_RecursiveDeref( pManRst->dd, bCofE );
+ Cudd_RecursiveDeref( pManRst->dd, bCofT );
+ bVar = pManRst->dd->vars[1];
+ bCofE = Cudd_Cofactor( pManRst->dd, bLocal, Cudd_Not(bVar) ); Cudd_Ref( bCofE );
+ bCofT = Cudd_Cofactor( pManRst->dd, bLocal, bVar ); Cudd_Ref( bCofT );
+ if ( !Extra_bddIsVar(bCofE) || !Extra_bddIsVar(bCofT) )
+ {
+ Cudd_RecursiveDeref( pManRst->dd, bCofE );
+ Cudd_RecursiveDeref( pManRst->dd, bCofT );
+ bVar = pManRst->dd->vars[2];
+ bCofE = Cudd_Cofactor( pManRst->dd, bLocal, Cudd_Not(bVar) ); Cudd_Ref( bCofE );
+ bCofT = Cudd_Cofactor( pManRst->dd, bLocal, bVar ); Cudd_Ref( bCofT );
+ if ( !Extra_bddIsVar(bCofE) || !Extra_bddIsVar(bCofT) )
+ {
+ Cudd_RecursiveDeref( pManRst->dd, bCofE );
+ Cudd_RecursiveDeref( pManRst->dd, bCofT );
+ Cudd_RecursiveDeref( pManRst->dd, bLocal );
+ Vec_IntFree( vEdges );
+ return eQuit;
+ }
+ }
+ }
+ Cudd_RecursiveDeref( pManRst->dd, bLocal );
+ // we found the control variable (bVar) and the var-cofactors (bCofT, bCofE)
+
+ // find the graph nodes
+ eNode1 = Dec_IntToEdge( Vec_IntEntry(vEdges, bVar->index) );
+ eNode2 = Dec_IntToEdge( Vec_IntEntry(vEdges, Cudd_Regular(bCofT)->index) );
+ eNode3 = Dec_IntToEdge( Vec_IntEntry(vEdges, Cudd_Regular(bCofE)->index) );
+ // add the complements to the graph nodes
+ eNode2.fCompl ^= Cudd_IsComplement(bCofT);
+ eNode3.fCompl ^= Cudd_IsComplement(bCofE);
+
+ // because the cofactors are vars, we can just as well deref them here
+ Cudd_RecursiveDeref( pManRst->dd, bCofE );
+ Cudd_RecursiveDeref( pManRst->dd, bCofT );
+
+ // find the ABC nodes
+ pNode1 = Dec_GraphNode( pGraph, eNode1.Node )->pFunc;
+ pNode2 = Dec_GraphNode( pGraph, eNode2.Node )->pFunc;
+ pNode3 = Dec_GraphNode( pGraph, eNode3.Node )->pFunc;
+ pNode1 = !pNode1? NULL : Abc_ObjNotCond( pNode1, eNode1.fCompl );
+ pNode2 = !pNode2? NULL : Abc_ObjNotCond( pNode2, eNode2.fCompl );
+ pNode3 = !pNode3? NULL : Abc_ObjNotCond( pNode3, eNode3.fCompl );
+
+ // check if the new node exists
+ Type = 0;
+ pNode4 = NULL;
+ if ( pNode1 && pNode2 && pNode3 )
+ pNode4 = Abc_AigMuxLookup( pManRst->pNtk->pManFunc, pNode1, pNode2, pNode3, &Type );
+
+ // create the new node
+ eResult = Dec_GraphAddNodeMux( pGraph, eNode1, eNode2, eNode3, Type ); // should have the same structure as AIG
+
+ // set level
+ Level1 = Dec_GraphNode( pGraph, eNode1.Node )->Level;
+ Level2 = Dec_GraphNode( pGraph, eNode2.Node )->Level;
+ Level3 = Dec_GraphNode( pGraph, eNode3.Node )->Level;
+ Dec_GraphNode( pGraph, eResult.Node )->Level = 2 + ABC_MAX( ABC_MAX(Level1, Level2), Level3 );
+ // get the new node if possible
+ if ( pNode4 )
+ {
+ Dec_GraphNode( pGraph, eResult.Node )->pFunc = Abc_ObjNotCond(pNode4, eResult.fCompl);
+ Level4 = Dec_GraphNode( pGraph, eResult.Node )->Level;
+ assert( Required == ABC_INFINITY || Level4 == (int)Abc_ObjRegular(pNode4)->Level );
+ }
+ if ( !pNode4 || Abc_NodeIsTravIdCurrent(Abc_ObjRegular(pNode4)) )
+ {
+ (*pnNodesAdded)++;
+ if ( Type == 0 )
+ {
+ if ( !pNode1 || !pNode2 )
+ (*pnNodesAdded)++;
+ else
+ {
+ pTemp = Abc_AigAndLookup( pManRst->pNtk->pManFunc, pNode1, pNode2 );
+ if ( !pTemp || Abc_NodeIsTravIdCurrent(Abc_ObjRegular(pTemp)) )
+ (*pnNodesAdded)++;
+ }
+ if ( !pNode1 || !pNode3 )
+ (*pnNodesAdded)++;
+ else
+ {
+ pTemp = Abc_AigAndLookup( pManRst->pNtk->pManFunc, Abc_ObjNot(pNode1), pNode3 );
+ if ( !pTemp || Abc_NodeIsTravIdCurrent(Abc_ObjRegular(pTemp)) )
+ (*pnNodesAdded)++;
+ }
+ }
+ else
+ {
+ if ( !pNode1 || !pNode2 )
+ (*pnNodesAdded)++;
+ else
+ {
+ pTemp = Abc_AigAndLookup( pManRst->pNtk->pManFunc, pNode1, Abc_ObjNot(pNode2) );
+ if ( !pTemp || Abc_NodeIsTravIdCurrent(Abc_ObjRegular(pTemp)) )
+ (*pnNodesAdded)++;
+ }
+ if ( !pNode1 || !pNode3 )
+ (*pnNodesAdded)++;
+ else
+ {
+ pTemp = Abc_AigAndLookup( pManRst->pNtk->pManFunc, Abc_ObjNot(pNode1), Abc_ObjNot(pNode3) );
+ if ( !pTemp || Abc_NodeIsTravIdCurrent(Abc_ObjRegular(pTemp)) )
+ (*pnNodesAdded)++;
+ }
+ }
+ if ( *pnNodesAdded > nNodesSaved )
+ {
+ Vec_IntFree( vEdges );
+ return eQuit;
+ }
+ }
+
+ Vec_IntFree( vEdges );
+ // complement the graph if the node was complemented
+ eResult.fCompl ^= fCompl;
+ return eResult;
+ }
+ Vec_IntFree( vEdges );
+ return eQuit;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Evaluation one DSD.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Dec_Graph_t * Abc_NodeEvaluateDsd( Abc_ManRst_t * pManRst, Dsd_Node_t * pNodeDsd, Abc_Obj_t * pRoot, int Required, int nNodesSaved, int * pnNodesAdded )
+{
+ Dec_Graph_t * pGraph;
+ Dec_Edge_t gEdge;
+ Abc_Obj_t * pLeaf;
+ Dec_Node_t * pNode;
+ int i;
+
+ // create the graph and set the leaves
+ pGraph = Dec_GraphCreate( Vec_PtrSize(pManRst->vLeaves) );
+ Dec_GraphForEachLeaf( pGraph, pNode, i )
+ {
+ pLeaf = Vec_PtrEntry( pManRst->vLeaves, i );
+ pNode->pFunc = pLeaf;
+ pNode->Level = pLeaf->Level;
+ }
+
+ // create the decomposition structure from the DSD
+ *pnNodesAdded = 0;
+ gEdge = Abc_NodeEvaluateDsd_rec( pGraph, pManRst, pNodeDsd, Required, nNodesSaved, pnNodesAdded );
+ if ( gEdge.Node > 1000 ) // infeasible
+ {
+ *pnNodesAdded = -1;
+ Dec_GraphFree( pGraph );
+ return NULL;
+ }
+
+ // quit if the root node is the same
+ pLeaf = Dec_GraphNode( pGraph, gEdge.Node )->pFunc;
+ if ( Abc_ObjRegular(pLeaf) == pRoot )
+ {
+ *pnNodesAdded = -1;
+ Dec_GraphFree( pGraph );
+ return NULL;
+ }
+
+ Dec_GraphSetRoot( pGraph, gEdge );
+ return pGraph;
+}
+
+
+
+/**Function*************************************************************
+
+ Synopsis [Starts the cut manager for rewriting.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Cut_Man_t * Abc_NtkStartCutManForRestruct( Abc_Ntk_t * pNtk, int nCutMax, int fDag )
+{
+ static Cut_Params_t Params, * pParams = &Params;
+ Cut_Man_t * pManCut;
+ Abc_Obj_t * pObj;
+ int i;
+ // start the cut manager
+ memset( pParams, 0, sizeof(Cut_Params_t) );
+ pParams->nVarsMax = nCutMax; // the max cut size ("k" of the k-feasible cuts)
+ pParams->nKeepMax = 250; // the max number of cuts kept at a node
+ pParams->fTruth = 0; // compute truth tables
+ pParams->fFilter = 1; // filter dominated cuts
+ pParams->fSeq = 0; // compute sequential cuts
+ pParams->fDrop = 0; // drop cuts on the fly
+ pParams->fDag = fDag; // compute DAG cuts
+ pParams->fTree = 0; // compute tree cuts
+ pParams->fVerbose = 0; // the verbosiness flag
+ pParams->nIdsMax = Abc_NtkObjNumMax( pNtk );
+ pManCut = Cut_ManStart( pParams );
+ if ( pParams->fDrop )
+ Cut_ManSetFanoutCounts( pManCut, Abc_NtkFanoutCounts(pNtk) );
+ // set cuts for PIs
+ Abc_NtkForEachCi( pNtk, pObj, i )
+ if ( Abc_ObjFanoutNum(pObj) > 0 )
+ Cut_NodeSetTriv( pManCut, pObj->Id );
+ return pManCut;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Starts the resynthesis manager.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Abc_ManRst_t * Abc_NtkManRstStart( int nCutMax, bool fUpdateLevel, bool fUseZeros, bool fVerbose )
+{
+ Abc_ManRst_t * p;
+ p = ALLOC( Abc_ManRst_t, 1 );
+ memset( p, 0, sizeof(Abc_ManRst_t) );
+ // set the parameters
+ p->nCutMax = nCutMax;
+ p->fUpdateLevel = fUpdateLevel;
+ p->fUseZeros = fUseZeros;
+ p->fVerbose = fVerbose;
+ // start the BDD manager
+ p->dd = Cudd_Init( p->nCutMax, 0, CUDD_UNIQUE_SLOTS, CUDD_CACHE_SLOTS, 0 );
+ Cudd_zddVarsFromBddVars( p->dd, 2 );
+ // start the DSD manager
+ p->pManDsd = Dsd_ManagerStart( p->dd, p->dd->size, 0 );
+ // other temp datastructures
+ p->vVisited = Vec_PtrAlloc( 100 );
+ p->vLeaves = Vec_PtrAlloc( 100 );
+ p->vDecs = Vec_PtrAlloc( 100 );
+ p->vTemp = Vec_PtrAlloc( 100 );
+ p->vSims = Vec_IntAlloc( 100 );
+ p->vOnes = Vec_IntAlloc( 100 );
+ p->vBinate = Vec_IntAlloc( 100 );
+ p->vTwos = Vec_IntAlloc( 100 );
+ p->vRands = Vec_IntAlloc( 20 );
+
+ {
+ int i;
+ for ( i = 0; i < 20; i++ )
+ Vec_IntPush( p->vRands, (int)RST_RANDOM_UNSIGNED );
+ }
+ return p;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Stops the resynthesis manager.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Abc_NtkManRstStop( Abc_ManRst_t * p )
+{
+ Dsd_ManagerStop( p->pManDsd );
+ Extra_StopManager( p->dd );
+ Vec_PtrFree( p->vDecs );
+ Vec_PtrFree( p->vLeaves );
+ Vec_PtrFree( p->vVisited );
+ Vec_PtrFree( p->vTemp );
+ Vec_IntFree( p->vSims );
+ Vec_IntFree( p->vOnes );
+ Vec_IntFree( p->vBinate );
+ Vec_IntFree( p->vTwos );
+ Vec_IntFree( p->vRands );
+ free( p );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Stops the resynthesis manager.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Abc_NtkManRstPrintStats( Abc_ManRst_t * p )
+{
+ printf( "Refactoring statistics:\n" );
+ printf( "Nodes considered = %8d.\n", p->nNodesConsidered );
+ printf( "Cuts considered = %8d.\n", p->nCutsConsidered );
+ printf( "Cuts explored = %8d.\n", p->nCutsExplored );
+ printf( "Nodes restructured = %8d.\n", p->nNodesRestructured );
+ printf( "Calculated gain = %8d.\n", p->nNodesGained );
+ PRT( "Cuts ", p->timeCut );
+ PRT( "Resynthesis", p->timeRes );
+ PRT( " BDD ", p->timeBdd );
+ PRT( " DSD ", p->timeDsd );
+ PRT( " Eval ", p->timeEval );
+ PRT( "AIG update ", p->timeNtk );
+ PRT( "TOTAL ", p->timeTotal );
+}
+
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Abc_Abc_NodeResubCollectDivs( Abc_ManRst_t * p, Abc_Obj_t * pRoot, Cut_Cut_t * pCut )
+{
+ Abc_Obj_t * pNode, * pFanout;
+ int i, k;
+ // collect the leaves of the cut
+ Vec_PtrClear( p->vDecs );
+ Abc_NtkIncrementTravId( pRoot->pNtk );
+ for ( i = 0; i < (int)pCut->nLeaves; i++ )
+ {
+ pNode = Abc_NtkObj(pRoot->pNtk, pCut->pLeaves[i]);
+ if ( pNode == NULL ) // the so-called "bad cut phenomenon" is due to removed nodes
+ return 0;
+ Vec_PtrPush( p->vDecs, pNode );
+ Abc_NodeSetTravIdCurrent( pNode );
+ }
+ // explore the fanouts
+ Vec_PtrForEachEntry( p->vDecs, pNode, i )
+ {
+ // if the fanout has both fanins in the set, add it
+ Abc_ObjForEachFanout( pNode, pFanout, k )
+ {
+ if ( Abc_NodeIsTravIdCurrent(pFanout) || Abc_ObjIsPo(pFanout) )
+ continue;
+ if ( Abc_NodeIsTravIdCurrent(Abc_ObjFanin0(pFanout)) && Abc_NodeIsTravIdCurrent(Abc_ObjFanin1(pFanout)) )
+ {
+ Vec_PtrPush( p->vDecs, pFanout );
+ Abc_NodeSetTravIdCurrent( pFanout );
+ }
+ }
+ }
+ return 1;
+}
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Abc_NodeResubMffc_rec( Abc_Obj_t * pNode )
+{
+ if ( Abc_NodeIsTravIdCurrent(pNode) )
+ return 0;
+ Abc_NodeSetTravIdCurrent( pNode );
+ return 1 + Abc_NodeResubMffc_rec( Abc_ObjFanin0(pNode) ) +
+ Abc_NodeResubMffc_rec( Abc_ObjFanin1(pNode) );
+}
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Abc_NodeResubMffc( Abc_ManRst_t * p, Vec_Ptr_t * vDecs, int nLeaves, Abc_Obj_t * pRoot )
+{
+ Abc_Obj_t * pObj;
+ int Counter, i, k;
+ // increment the traversal ID for the leaves
+ Abc_NtkIncrementTravId( pRoot->pNtk );
+ // label the leaves
+ Vec_PtrForEachEntryStop( vDecs, pObj, i, nLeaves )
+ Abc_NodeSetTravIdCurrent( pObj );
+ // make sure the node is in the cone and is no one of the leaves
+ assert( Abc_NodeIsTravIdPrevious(pRoot) );
+ Counter = Abc_NodeResubMffc_rec( pRoot );
+ // move the labeled nodes to the end
+ Vec_PtrClear( p->vTemp );
+ k = 0;
+ Vec_PtrForEachEntryStart( vDecs, pObj, i, nLeaves )
+ if ( Abc_NodeIsTravIdCurrent(pObj) )
+ Vec_PtrPush( p->vTemp, pObj );
+ else
+ Vec_PtrWriteEntry( vDecs, k++, pObj );
+ // add the labeled nodes
+ Vec_PtrForEachEntry( p->vTemp, pObj, i )
+ Vec_PtrWriteEntry( vDecs, k++, pObj );
+ assert( k == Vec_PtrSize(p->vDecs) );
+ assert( pRoot == Vec_PtrEntryLast(p->vDecs) );
+ return Counter;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Performs simulation.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Abc_NodeMffcSimulate( Vec_Ptr_t * vDecs, int nLeaves, Vec_Int_t * vRands, Vec_Int_t * vSims )
+{
+ Abc_Obj_t * pObj;
+ unsigned uData0, uData1, uData;
+ int i;
+ // initialize random simulation data
+ Vec_IntClear( vSims );
+ Vec_PtrForEachEntryStop( vDecs, pObj, i, nLeaves )
+ {
+ uData = (unsigned)Vec_IntEntry( vRands, i );
+ pObj->pData = (void *)uData;
+ Vec_IntPush( vSims, uData );
+ }
+ // simulate
+ Vec_PtrForEachEntryStart( vDecs, pObj, i, nLeaves )
+ {
+ uData0 = (unsigned)Abc_ObjFanin0(pObj)->pData;
+ uData1 = (unsigned)Abc_ObjFanin1(pObj)->pData;
+ uData = (Abc_ObjFaninC0(pObj)? ~uData0 : uData0) & (Abc_ObjFaninC1(pObj)? ~uData1 : uData1);
+ pObj->pData = (void *)uData;
+ Vec_IntPush( vSims, uData );
+ }
+}
+
+/**Function*************************************************************
+
+ Synopsis [Full equality check.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Abc_NodeCheckFull( Abc_ManRst_t * p, Dec_Graph_t * pGraph )
+{
+ return 1;
+}
+/**Function*************************************************************
+
+ Synopsis [Detect contants.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Dec_Graph_t * Abc_NodeMffcConstants( Abc_ManRst_t * p, Vec_Int_t * vSims )
+{
+ Dec_Graph_t * pGraph;
+ unsigned uRoot;
+ // get the root node
+ uRoot = (unsigned)Vec_IntEntryLast( vSims );
+ // get the graph if the node looks constant
+ if ( uRoot == 0 )
+ pGraph = Dec_GraphCreateConst0();
+ else if ( uRoot == ~(unsigned)0 )
+ pGraph = Dec_GraphCreateConst1();
+ // check the graph
+ if ( Abc_NodeCheckFull( p, pGraph ) )
+ return pGraph;
+ Dec_GraphFree( pGraph );
+ return NULL;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Detect single non-overlaps.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Dec_Graph_t * Abc_NodeMffcSingleVar( Abc_ManRst_t * p, Vec_Int_t * vSims, int nNodes, Vec_Int_t * vOnes )
+{
+ Dec_Graph_t * pGraph;
+ unsigned uRoot, uNode;
+ int i;
+
+ Vec_IntClear( vOnes );
+ Vec_IntClear( p->vBinate );
+ uRoot = (unsigned)Vec_IntEntryLast( vSims );
+ for ( i = 0; i < nNodes; i++ )
+ {
+ uNode = (unsigned)Vec_IntEntry( vSims, i );
+ if ( uRoot == uNode || uRoot == ~uNode )
+ {
+ pGraph = Dec_GraphCreate( 1 );
+ Dec_GraphNode( pGraph, 0 )->pFunc = Vec_PtrEntry( p->vDecs, i );
+ Dec_GraphSetRoot( pGraph, Dec_IntToEdge( (int)(uRoot == ~uNode) ) );
+ // check the graph
+ if ( Abc_NodeCheckFull( p, pGraph ) )
+ return pGraph;
+ Dec_GraphFree( pGraph );
+ }
+ if ( (uRoot & uNode) == 0 )
+ Vec_IntPush( vOnes, i << 1 );
+ else if ( (uRoot & ~uNode) == 0 )
+ Vec_IntPush( vOnes, (i << 1) + 1 );
+ else
+ Vec_IntPush( p->vBinate, i );
+ }
+ return NULL;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Detect single non-overlaps.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Dec_Graph_t * Abc_NodeMffcSingleNode( Abc_ManRst_t * p, Vec_Int_t * vSims, int nNodes, Vec_Int_t * vOnes )
+{
+ Dec_Graph_t * pGraph;
+ Dec_Edge_t eNode0, eNode1, eRoot;
+ unsigned uRoot;
+ int i, k;
+ uRoot = (unsigned)Vec_IntEntryLast( vSims );
+ for ( i = 0; i < vOnes->nSize; i++ )
+ for ( k = i+1; k < vOnes->nSize; k++ )
+ if ( ~uRoot == ((unsigned)vOnes->pArray[i] | (unsigned)vOnes->pArray[k]) )
+ {
+ eNode0 = Dec_IntToEdge( vOnes->pArray[i] ^ 1 );
+ eNode1 = Dec_IntToEdge( vOnes->pArray[k] ^ 1 );
+ pGraph = Dec_GraphCreate( 2 );
+ Dec_GraphNode( pGraph, 0 )->pFunc = Vec_PtrEntry( p->vDecs, eNode0.Node );
+ Dec_GraphNode( pGraph, 1 )->pFunc = Vec_PtrEntry( p->vDecs, eNode1.Node );
+ eRoot = Dec_GraphAddNodeAnd( pGraph, eNode0, eNode1 );
+ Dec_GraphSetRoot( pGraph, eRoot );
+ if ( Abc_NodeCheckFull( p, pGraph ) )
+ return pGraph;
+ Dec_GraphFree( pGraph );
+ }
+ return NULL;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Detect single non-overlaps.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Dec_Graph_t * Abc_NodeMffcDoubleNode( Abc_ManRst_t * p, Vec_Int_t * vSims, int nNodes, Vec_Int_t * vOnes )
+{
+// Dec_Graph_t * pGraph;
+// unsigned uRoot, uNode;
+// int i;
+
+
+ return NULL;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Evaluates resubstution of one cut.]
+
+ Description [Returns the graph to add if any.]
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Dec_Graph_t * Abc_NodeResubEval( Abc_ManRst_t * p, Abc_Obj_t * pRoot, Cut_Cut_t * pCut )
+{
+ Dec_Graph_t * pGraph;
+ int nNodesSaved;
+
+ // collect the nodes in the cut
+ if ( !Abc_Abc_NodeResubCollectDivs( p, pRoot, pCut ) )
+ return NULL;
+
+ // label MFFC and count its size
+ nNodesSaved = Abc_NodeResubMffc( p, p->vDecs, pCut->nLeaves, pRoot );
+ assert( nNodesSaved > 0 );
+
+ // simulate MFFC
+ Abc_NodeMffcSimulate( p->vDecs, pCut->nLeaves, p->vRands, p->vSims );
+
+ // check for constant output
+ pGraph = Abc_NodeMffcConstants( p, p->vSims );
+ if ( pGraph )
+ {
+ p->nNodesGained += nNodesSaved;
+ p->nNodesRestructured++;
+ return pGraph;
+ }
+
+ // check for one literal (fill up the ones array)
+ pGraph = Abc_NodeMffcSingleVar( p, p->vSims, Vec_IntSize(p->vSims) - nNodesSaved, p->vOnes );
+ if ( pGraph )
+ {
+ p->nNodesGained += nNodesSaved;
+ p->nNodesRestructured++;
+ return pGraph;
+ }
+ if ( nNodesSaved == 1 )
+ return NULL;
+
+ // look for one node
+ pGraph = Abc_NodeMffcSingleNode( p, p->vSims, Vec_IntSize(p->vSims) - nNodesSaved, p->vOnes );
+ if ( pGraph )
+ {
+ p->nNodesGained += nNodesSaved - 1;
+ p->nNodesRestructured++;
+ return pGraph;
+ }
+ if ( nNodesSaved == 2 )
+ return NULL;
+
+ // look for two nodes
+ pGraph = Abc_NodeMffcDoubleNode( p, p->vSims, Vec_IntSize(p->vSims) - nNodesSaved, p->vOnes );
+ if ( pGraph )
+ {
+ p->nNodesGained += nNodesSaved - 2;
+ p->nNodesRestructured++;
+ return pGraph;
+ }
+ if ( nNodesSaved == 3 )
+ return NULL;
+/*
+ // look for MUX/EXOR
+ pGraph = Abc_NodeMffcMuxNode( p, p->vSims, Vec_IntSize(p->vSims) - nNodesSaved );
+ if ( pGraph )
+ {
+ p->nNodesGained += nNodesSaved - 1;
+ p->nNodesRestructured++;
+ return pGraph;
+ }
+*/
+ return NULL;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Performs resubstution.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Dec_Graph_t * Abc_NodeResubstitute( Abc_ManRst_t * p, Abc_Obj_t * pNode, Cut_Cut_t * pCutList )
+{
+ Dec_Graph_t * pGraph, * pGraphBest = NULL;
+ Cut_Cut_t * pCut;
+ int nCuts;
+ p->nNodesConsidered++;
+
+ // count the number of cuts with four inputs or more
+ nCuts = 0;
+ for ( pCut = pCutList; pCut; pCut = pCut->pNext )
+ nCuts += (int)(pCut->nLeaves > 3);
+ printf( "-----------------------------------\n" );
+ printf( "Node %6d : Factor-cuts = %5d.\n", pNode->Id, nCuts );
+
+ // go through the interesting cuts
+ for ( pCut = pCutList; pCut; pCut = pCut->pNext )
+ {
+ if ( pCut->nLeaves < 4 )
+ continue;
+ pGraph = Abc_NodeResubEval( p, pNode, pCut );
+ if ( pGraph == NULL )
+ continue;
+ if ( !pGraphBest || Dec_GraphNodeNum(pGraph) < Dec_GraphNodeNum(pGraphBest) )
+ {
+ if ( pGraphBest )
+ Dec_GraphFree(pGraphBest);
+ pGraphBest = pGraph;
+ }
+ else
+ Dec_GraphFree(pGraph);
+ }
+ return pGraphBest;
+}
+
+////////////////////////////////////////////////////////////////////////
+/// END OF FILE ///
+////////////////////////////////////////////////////////////////////////
+
+
diff --git a/src/base/abci/abcResub.c b/src/base/abci/abcResub.c
new file mode 100644
index 00000000..a2b23c0c
--- /dev/null
+++ b/src/base/abci/abcResub.c
@@ -0,0 +1,1952 @@
+/**CFile****************************************************************
+
+ FileName [abcResub.c]
+
+ SystemName [ABC: Logic synthesis and verification system.]
+
+ PackageName [Network and node package.]
+
+ Synopsis [Resubstitution manager.]
+
+ Author [Alan Mishchenko]
+
+ Affiliation [UC Berkeley]
+
+ Date [Ver. 1.0. Started - June 20, 2005.]
+
+ Revision [$Id: abcResub.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "abc.h"
+#include "dec.h"
+
+////////////////////////////////////////////////////////////////////////
+/// DECLARATIONS ///
+////////////////////////////////////////////////////////////////////////
+
+#define ABC_RS_DIV1_MAX 150 // the max number of divisors to consider
+#define ABC_RS_DIV2_MAX 500 // the max number of pair-wise divisors to consider
+
+typedef struct Abc_ManRes_t_ Abc_ManRes_t;
+struct Abc_ManRes_t_
+{
+ // paramers
+ int nLeavesMax; // the max number of leaves in the cone
+ int nDivsMax; // the max number of divisors in the cone
+ // representation of the cone
+ Abc_Obj_t * pRoot; // the root of the cone
+ int nLeaves; // the number of leaves
+ int nDivs; // the number of all divisor (including leaves)
+ int nMffc; // the size of MFFC
+ int nLastGain; // the gain the number of nodes
+ Vec_Ptr_t * vDivs; // the divisors
+ // representation of the simulation info
+ int nBits; // the number of simulation bits
+ int nWords; // the number of unsigneds for siminfo
+ Vec_Ptr_t * vSims; // simulation info
+ unsigned * pInfo; // pointer to simulation info
+ // observability don't-cares
+ unsigned * pCareSet;
+ // internal divisor storage
+ Vec_Ptr_t * vDivs1UP; // the single-node unate divisors
+ Vec_Ptr_t * vDivs1UN; // the single-node unate divisors
+ Vec_Ptr_t * vDivs1B; // the single-node binate divisors
+ Vec_Ptr_t * vDivs2UP0; // the double-node unate divisors
+ Vec_Ptr_t * vDivs2UP1; // the double-node unate divisors
+ Vec_Ptr_t * vDivs2UN0; // the double-node unate divisors
+ Vec_Ptr_t * vDivs2UN1; // the double-node unate divisors
+ // other data
+ Vec_Ptr_t * vTemp; // temporary array of nodes
+ // runtime statistics
+ int timeCut;
+ int timeTruth;
+ int timeRes;
+ int timeDiv;
+ int timeMffc;
+ int timeSim;
+ int timeRes1;
+ int timeResD;
+ int timeRes2;
+ int timeRes3;
+ int timeNtk;
+ int timeTotal;
+ // improvement statistics
+ int nUsedNodeC;
+ int nUsedNode0;
+ int nUsedNode1Or;
+ int nUsedNode1And;
+ int nUsedNode2Or;
+ int nUsedNode2And;
+ int nUsedNode2OrAnd;
+ int nUsedNode2AndOr;
+ int nUsedNode3OrAnd;
+ int nUsedNode3AndOr;
+ int nUsedNodeTotal;
+ int nTotalDivs;
+ int nTotalLeaves;
+ int nTotalGain;
+ int nNodesBeg;
+ int nNodesEnd;
+};
+
+// external procedures
+static Abc_ManRes_t* Abc_ManResubStart( int nLeavesMax, int nDivsMax );
+static void Abc_ManResubStop( Abc_ManRes_t * p );
+static Dec_Graph_t * Abc_ManResubEval( Abc_ManRes_t * p, Abc_Obj_t * pRoot, Vec_Ptr_t * vLeaves, int nSteps, bool fUpdateLevel, int fVerbose );
+static void Abc_ManResubCleanup( Abc_ManRes_t * p );
+static void Abc_ManResubPrint( Abc_ManRes_t * p );
+
+// other procedures
+static int Abc_ManResubCollectDivs( Abc_ManRes_t * p, Abc_Obj_t * pRoot, Vec_Ptr_t * vLeaves, int Required );
+static void Abc_ManResubSimulate( Vec_Ptr_t * vDivs, int nLeaves, Vec_Ptr_t * vSims, int nLeavesMax, int nWords );
+static void Abc_ManResubPrintDivs( Abc_ManRes_t * p, Abc_Obj_t * pRoot, Vec_Ptr_t * vLeaves );
+
+static void Abc_ManResubDivsS( Abc_ManRes_t * p, int Required );
+static void Abc_ManResubDivsD( Abc_ManRes_t * p, int Required );
+static Dec_Graph_t * Abc_ManResubQuit( Abc_ManRes_t * p );
+static Dec_Graph_t * Abc_ManResubDivs0( Abc_ManRes_t * p );
+static Dec_Graph_t * Abc_ManResubDivs1( Abc_ManRes_t * p, int Required );
+static Dec_Graph_t * Abc_ManResubDivs12( Abc_ManRes_t * p, int Required );
+static Dec_Graph_t * Abc_ManResubDivs2( Abc_ManRes_t * p, int Required );
+static Dec_Graph_t * Abc_ManResubDivs3( Abc_ManRes_t * p, int Required );
+
+static Vec_Ptr_t * Abc_CutFactorLarge( Abc_Obj_t * pNode, int nLeavesMax );
+static int Abc_CutVolumeCheck( Abc_Obj_t * pNode, Vec_Ptr_t * vLeaves );
+
+// don't-care manager
+extern void * Abc_NtkDontCareAlloc( int nVarsMax, int nLevels, int fVerbose, int fVeryVerbose );
+extern void Abc_NtkDontCareClear( void * p );
+extern void Abc_NtkDontCareFree( void * p );
+extern int Abc_NtkDontCareCompute( void * p, Abc_Obj_t * pNode, Vec_Ptr_t * vLeaves, unsigned * puTruth );
+
+extern int s_ResubTime;
+
+////////////////////////////////////////////////////////////////////////
+/// FUNCTION DEFINITIONS ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+ Synopsis [Performs incremental resynthesis of the AIG.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Abc_NtkResubstitute( Abc_Ntk_t * pNtk, int nCutMax, int nStepsMax, int nLevelsOdc, bool fUpdateLevel, bool fVerbose, bool fVeryVerbose )
+{
+ extern void Dec_GraphUpdateNetwork( Abc_Obj_t * pRoot, Dec_Graph_t * pGraph, bool fUpdateLevel, int nGain );
+ ProgressBar * pProgress;
+ Abc_ManRes_t * pManRes;
+ Abc_ManCut_t * pManCut;
+ void * pManOdc = NULL;
+ Dec_Graph_t * pFForm;
+ Vec_Ptr_t * vLeaves;
+ Abc_Obj_t * pNode;
+ int clk, clkStart = clock();
+ int i, nNodes;
+
+ assert( Abc_NtkIsStrash(pNtk) );
+
+ // cleanup the AIG
+ Abc_AigCleanup(pNtk->pManFunc);
+ // start the managers
+ pManCut = Abc_NtkManCutStart( nCutMax, 100000, 100000, 100000 );
+ pManRes = Abc_ManResubStart( nCutMax, ABC_RS_DIV1_MAX );
+ if ( nLevelsOdc > 0 )
+ pManOdc = Abc_NtkDontCareAlloc( nCutMax, nLevelsOdc, fVerbose, fVeryVerbose );
+
+ // compute the reverse levels if level update is requested
+ if ( fUpdateLevel )
+ Abc_NtkStartReverseLevels( pNtk, 0 );
+
+ if ( Abc_NtkLatchNum(pNtk) )
+ Abc_NtkForEachLatch(pNtk, pNode, i)
+ pNode->pNext = pNode->pData;
+
+ // resynthesize each node once
+ pManRes->nNodesBeg = Abc_NtkNodeNum(pNtk);
+ nNodes = Abc_NtkObjNumMax(pNtk);
+ pProgress = Extra_ProgressBarStart( stdout, nNodes );
+ Abc_NtkForEachNode( pNtk, pNode, i )
+ {
+ Extra_ProgressBarUpdate( pProgress, i, NULL );
+ // skip the constant node
+// if ( Abc_NodeIsConst(pNode) )
+// continue;
+ // skip persistant nodes
+ if ( Abc_NodeIsPersistant(pNode) )
+ continue;
+ // skip the nodes with many fanouts
+ if ( Abc_ObjFanoutNum(pNode) > 1000 )
+ continue;
+ // stop if all nodes have been tried once
+ if ( i >= nNodes )
+ break;
+
+ // compute a reconvergence-driven cut
+clk = clock();
+ vLeaves = Abc_NodeFindCut( pManCut, pNode, 0 );
+// vLeaves = Abc_CutFactorLarge( pNode, nCutMax );
+pManRes->timeCut += clock() - clk;
+/*
+ if ( fVerbose && vLeaves )
+ printf( "Node %6d : Leaves = %3d. Volume = %3d.\n", pNode->Id, Vec_PtrSize(vLeaves), Abc_CutVolumeCheck(pNode, vLeaves) );
+ if ( vLeaves == NULL )
+ continue;
+*/
+ // get the don't-cares
+ if ( pManOdc )
+ {
+clk = clock();
+ Abc_NtkDontCareClear( pManOdc );
+ Abc_NtkDontCareCompute( pManOdc, pNode, vLeaves, pManRes->pCareSet );
+pManRes->timeTruth += clock() - clk;
+ }
+
+ // evaluate this cut
+clk = clock();
+ pFForm = Abc_ManResubEval( pManRes, pNode, vLeaves, nStepsMax, fUpdateLevel, fVerbose );
+// Vec_PtrFree( vLeaves );
+// Abc_ManResubCleanup( pManRes );
+pManRes->timeRes += clock() - clk;
+ if ( pFForm == NULL )
+ continue;
+ pManRes->nTotalGain += pManRes->nLastGain;
+/*
+ if ( pManRes->nLeaves == 4 && pManRes->nMffc == 2 && pManRes->nLastGain == 1 )
+ {
+ printf( "%6d : L = %2d. V = %2d. Mffc = %2d. Divs = %3d. Up = %3d. Un = %3d. B = %3d.\n",
+ pNode->Id, pManRes->nLeaves, Abc_CutVolumeCheck(pNode, vLeaves), pManRes->nMffc, pManRes->nDivs,
+ pManRes->vDivs1UP->nSize, pManRes->vDivs1UN->nSize, pManRes->vDivs1B->nSize );
+ Abc_ManResubPrintDivs( pManRes, pNode, vLeaves );
+ }
+*/
+ // acceptable replacement found, update the graph
+clk = clock();
+ Dec_GraphUpdateNetwork( pNode, pFForm, fUpdateLevel, pManRes->nLastGain );
+pManRes->timeNtk += clock() - clk;
+ Dec_GraphFree( pFForm );
+ }
+ Extra_ProgressBarStop( pProgress );
+pManRes->timeTotal = clock() - clkStart;
+ pManRes->nNodesEnd = Abc_NtkNodeNum(pNtk);
+
+ // print statistics
+ if ( fVerbose )
+ Abc_ManResubPrint( pManRes );
+
+ // delete the managers
+ Abc_ManResubStop( pManRes );
+ Abc_NtkManCutStop( pManCut );
+ if ( pManOdc ) Abc_NtkDontCareFree( pManOdc );
+
+ // clean the data field
+ Abc_NtkForEachObj( pNtk, pNode, i )
+ pNode->pData = NULL;
+
+ if ( Abc_NtkLatchNum(pNtk) )
+ Abc_NtkForEachLatch(pNtk, pNode, i)
+ pNode->pData = pNode->pNext, pNode->pNext = NULL;
+
+ // put the nodes into the DFS order and reassign their IDs
+ Abc_NtkReassignIds( pNtk );
+// Abc_AigCheckFaninOrder( pNtk->pManFunc );
+ // fix the levels
+ if ( fUpdateLevel )
+ Abc_NtkStopReverseLevels( pNtk );
+ else
+ Abc_NtkLevel( pNtk );
+ // check
+ if ( !Abc_NtkCheck( pNtk ) )
+ {
+ printf( "Abc_NtkRefactor: The network check has failed.\n" );
+ return 0;
+ }
+s_ResubTime = clock() - clkStart;
+ return 1;
+}
+
+
+
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Abc_ManRes_t * Abc_ManResubStart( int nLeavesMax, int nDivsMax )
+{
+ Abc_ManRes_t * p;
+ unsigned * pData;
+ int i, k;
+ assert( sizeof(unsigned) == 4 );
+ p = ALLOC( Abc_ManRes_t, 1 );
+ memset( p, 0, sizeof(Abc_ManRes_t) );
+ p->nLeavesMax = nLeavesMax;
+ p->nDivsMax = nDivsMax;
+ p->vDivs = Vec_PtrAlloc( p->nDivsMax );
+ // allocate simulation info
+ p->nBits = (1 << p->nLeavesMax);
+ p->nWords = (p->nBits <= 32)? 1 : (p->nBits / 32);
+ p->pInfo = ALLOC( unsigned, p->nWords * (p->nDivsMax + 1) );
+ memset( p->pInfo, 0, sizeof(unsigned) * p->nWords * p->nLeavesMax );
+ p->vSims = Vec_PtrAlloc( p->nDivsMax );
+ for ( i = 0; i < p->nDivsMax; i++ )
+ Vec_PtrPush( p->vSims, p->pInfo + i * p->nWords );
+ // assign the care set
+ p->pCareSet = p->pInfo + p->nDivsMax * p->nWords;
+ Abc_InfoFill( p->pCareSet, p->nWords );
+ // set elementary truth tables
+ for ( k = 0; k < p->nLeavesMax; k++ )
+ {
+ pData = p->vSims->pArray[k];
+ for ( i = 0; i < p->nBits; i++ )
+ if ( i & (1 << k) )
+ pData[i>>5] |= (1 << (i&31));
+ }
+ // create the remaining divisors
+ p->vDivs1UP = Vec_PtrAlloc( p->nDivsMax );
+ p->vDivs1UN = Vec_PtrAlloc( p->nDivsMax );
+ p->vDivs1B = Vec_PtrAlloc( p->nDivsMax );
+ p->vDivs2UP0 = Vec_PtrAlloc( p->nDivsMax );
+ p->vDivs2UP1 = Vec_PtrAlloc( p->nDivsMax );
+ p->vDivs2UN0 = Vec_PtrAlloc( p->nDivsMax );
+ p->vDivs2UN1 = Vec_PtrAlloc( p->nDivsMax );
+ p->vTemp = Vec_PtrAlloc( p->nDivsMax );
+ return p;
+}
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Abc_ManResubStop( Abc_ManRes_t * p )
+{
+ Vec_PtrFree( p->vDivs );
+ Vec_PtrFree( p->vSims );
+ Vec_PtrFree( p->vDivs1UP );
+ Vec_PtrFree( p->vDivs1UN );
+ Vec_PtrFree( p->vDivs1B );
+ Vec_PtrFree( p->vDivs2UP0 );
+ Vec_PtrFree( p->vDivs2UP1 );
+ Vec_PtrFree( p->vDivs2UN0 );
+ Vec_PtrFree( p->vDivs2UN1 );
+ Vec_PtrFree( p->vTemp );
+ free( p->pInfo );
+ free( p );
+}
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Abc_ManResubPrint( Abc_ManRes_t * p )
+{
+ printf( "Used constants = %6d. ", p->nUsedNodeC ); PRT( "Cuts ", p->timeCut );
+ printf( "Used replacements = %6d. ", p->nUsedNode0 ); PRT( "Resub ", p->timeRes );
+ printf( "Used single ORs = %6d. ", p->nUsedNode1Or ); PRT( " Div ", p->timeDiv );
+ printf( "Used single ANDs = %6d. ", p->nUsedNode1And ); PRT( " Mffc ", p->timeMffc );
+ printf( "Used double ORs = %6d. ", p->nUsedNode2Or ); PRT( " Sim ", p->timeSim );
+ printf( "Used double ANDs = %6d. ", p->nUsedNode2And ); PRT( " 1 ", p->timeRes1 );
+ printf( "Used OR-AND = %6d. ", p->nUsedNode2OrAnd ); PRT( " D ", p->timeResD );
+ printf( "Used AND-OR = %6d. ", p->nUsedNode2AndOr ); PRT( " 2 ", p->timeRes2 );
+ printf( "Used OR-2ANDs = %6d. ", p->nUsedNode3OrAnd ); PRT( "Truth ", p->timeTruth ); //PRT( " 3 ", p->timeRes3 );
+ printf( "Used AND-2ORs = %6d. ", p->nUsedNode3AndOr ); PRT( "AIG ", p->timeNtk );
+ printf( "TOTAL = %6d. ", p->nUsedNodeC +
+ p->nUsedNode0 +
+ p->nUsedNode1Or +
+ p->nUsedNode1And +
+ p->nUsedNode2Or +
+ p->nUsedNode2And +
+ p->nUsedNode2OrAnd +
+ p->nUsedNode2AndOr +
+ p->nUsedNode3OrAnd +
+ p->nUsedNode3AndOr
+ ); PRT( "TOTAL ", p->timeTotal );
+ printf( "Total leaves = %8d.\n", p->nTotalLeaves );
+ printf( "Total divisors = %8d.\n", p->nTotalDivs );
+// printf( "Total gain = %8d.\n", p->nTotalGain );
+ printf( "Gain = %8d. (%6.2f %%).\n", p->nNodesBeg-p->nNodesEnd, 100.0*(p->nNodesBeg-p->nNodesEnd)/p->nNodesBeg );
+}
+
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Abc_ManResubCollectDivs_rec( Abc_Obj_t * pNode, Vec_Ptr_t * vInternal )
+{
+ // skip visited nodes
+ if ( Abc_NodeIsTravIdCurrent(pNode) )
+ return;
+ Abc_NodeSetTravIdCurrent(pNode);
+ // collect the fanins
+ Abc_ManResubCollectDivs_rec( Abc_ObjFanin0(pNode), vInternal );
+ Abc_ManResubCollectDivs_rec( Abc_ObjFanin1(pNode), vInternal );
+ // collect the internal node
+ if ( pNode->fMarkA == 0 )
+ Vec_PtrPush( vInternal, pNode );
+}
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Abc_ManResubCollectDivs( Abc_ManRes_t * p, Abc_Obj_t * pRoot, Vec_Ptr_t * vLeaves, int Required )
+{
+ Abc_Obj_t * pNode, * pFanout;
+ int i, k, Limit, Counter;
+
+ Vec_PtrClear( p->vDivs1UP );
+ Vec_PtrClear( p->vDivs1UN );
+ Vec_PtrClear( p->vDivs1B );
+
+ // add the leaves of the cuts to the divisors
+ Vec_PtrClear( p->vDivs );
+ Abc_NtkIncrementTravId( pRoot->pNtk );
+ Vec_PtrForEachEntry( vLeaves, pNode, i )
+ {
+ Vec_PtrPush( p->vDivs, pNode );
+ Abc_NodeSetTravIdCurrent( pNode );
+ }
+
+ // mark nodes in the MFFC
+ Vec_PtrForEachEntry( p->vTemp, pNode, i )
+ pNode->fMarkA = 1;
+ // collect the cone (without MFFC)
+ Abc_ManResubCollectDivs_rec( pRoot, p->vDivs );
+ // unmark the current MFFC
+ Vec_PtrForEachEntry( p->vTemp, pNode, i )
+ pNode->fMarkA = 0;
+
+ // check if the number of divisors is not exceeded
+ if ( Vec_PtrSize(p->vDivs) - Vec_PtrSize(vLeaves) + Vec_PtrSize(p->vTemp) >= Vec_PtrSize(p->vSims) - p->nLeavesMax )
+ return 0;
+
+ // get the number of divisors to collect
+ Limit = Vec_PtrSize(p->vSims) - p->nLeavesMax - (Vec_PtrSize(p->vDivs) - Vec_PtrSize(vLeaves) + Vec_PtrSize(p->vTemp));
+
+ // explore the fanouts, which are not in the MFFC
+ Counter = 0;
+ Vec_PtrForEachEntry( p->vDivs, pNode, i )
+ {
+ if ( Abc_ObjFanoutNum(pNode) > 100 )
+ {
+// printf( "%d ", Abc_ObjFanoutNum(pNode) );
+ continue;
+ }
+ // if the fanout has both fanins in the set, add it
+ Abc_ObjForEachFanout( pNode, pFanout, k )
+ {
+ if ( Abc_NodeIsTravIdCurrent(pFanout) || Abc_ObjIsCo(pFanout) || (int)pFanout->Level > Required )
+ continue;
+ if ( Abc_NodeIsTravIdCurrent(Abc_ObjFanin0(pFanout)) && Abc_NodeIsTravIdCurrent(Abc_ObjFanin1(pFanout)) )
+ {
+ if ( Abc_ObjFanin0(pFanout) == pRoot || Abc_ObjFanin1(pFanout) == pRoot )
+ continue;
+ Vec_PtrPush( p->vDivs, pFanout );
+ Abc_NodeSetTravIdCurrent( pFanout );
+ // quit computing divisors if there is too many of them
+ if ( ++Counter == Limit )
+ goto Quits;
+ }
+ }
+ }
+
+Quits :
+ // get the number of divisors
+ p->nDivs = Vec_PtrSize(p->vDivs);
+
+ // add the nodes in the MFFC
+ Vec_PtrForEachEntry( p->vTemp, pNode, i )
+ Vec_PtrPush( p->vDivs, pNode );
+ assert( pRoot == Vec_PtrEntryLast(p->vDivs) );
+
+ assert( Vec_PtrSize(p->vDivs) - Vec_PtrSize(vLeaves) <= Vec_PtrSize(p->vSims) - p->nLeavesMax );
+ return 1;
+}
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Abc_ManResubPrintDivs( Abc_ManRes_t * p, Abc_Obj_t * pRoot, Vec_Ptr_t * vLeaves )
+{
+ Abc_Obj_t * pFanin, * pNode;
+ int i, k;
+ // print the nodes
+ Vec_PtrForEachEntry( p->vDivs, pNode, i )
+ {
+ if ( i < Vec_PtrSize(vLeaves) )
+ {
+ printf( "%6d : %c\n", pNode->Id, 'a'+i );
+ continue;
+ }
+ printf( "%6d : %2d = ", pNode->Id, i );
+ // find the first fanin
+ Vec_PtrForEachEntry( p->vDivs, pFanin, k )
+ if ( Abc_ObjFanin0(pNode) == pFanin )
+ break;
+ if ( k < Vec_PtrSize(vLeaves) )
+ printf( "%c", 'a' + k );
+ else
+ printf( "%d", k );
+ printf( "%s ", Abc_ObjFaninC0(pNode)? "\'" : "" );
+ // find the second fanin
+ Vec_PtrForEachEntry( p->vDivs, pFanin, k )
+ if ( Abc_ObjFanin1(pNode) == pFanin )
+ break;
+ if ( k < Vec_PtrSize(vLeaves) )
+ printf( "%c", 'a' + k );
+ else
+ printf( "%d", k );
+ printf( "%s ", Abc_ObjFaninC1(pNode)? "\'" : "" );
+ if ( pNode == pRoot )
+ printf( " root" );
+ printf( "\n" );
+ }
+ printf( "\n" );
+}
+
+
+/**Function*************************************************************
+
+ Synopsis [Performs simulation.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Abc_ManResubSimulate( Vec_Ptr_t * vDivs, int nLeaves, Vec_Ptr_t * vSims, int nLeavesMax, int nWords )
+{
+ Abc_Obj_t * pObj;
+ unsigned * puData0, * puData1, * puData;
+ int i, k;
+ assert( Vec_PtrSize(vDivs) - nLeaves <= Vec_PtrSize(vSims) - nLeavesMax );
+ // simulate
+ Vec_PtrForEachEntry( vDivs, pObj, i )
+ {
+ if ( i < nLeaves )
+ { // initialize the leaf
+ pObj->pData = Vec_PtrEntry( vSims, i );
+ continue;
+ }
+ // set storage for the node's simulation info
+ pObj->pData = Vec_PtrEntry( vSims, i - nLeaves + nLeavesMax );
+ // get pointer to the simulation info
+ puData = pObj->pData;
+ puData0 = Abc_ObjFanin0(pObj)->pData;
+ puData1 = Abc_ObjFanin1(pObj)->pData;
+ // simulate
+ if ( Abc_ObjFaninC0(pObj) && Abc_ObjFaninC1(pObj) )
+ for ( k = 0; k < nWords; k++ )
+ puData[k] = ~puData0[k] & ~puData1[k];
+ else if ( Abc_ObjFaninC0(pObj) )
+ for ( k = 0; k < nWords; k++ )
+ puData[k] = ~puData0[k] & puData1[k];
+ else if ( Abc_ObjFaninC1(pObj) )
+ for ( k = 0; k < nWords; k++ )
+ puData[k] = puData0[k] & ~puData1[k];
+ else
+ for ( k = 0; k < nWords; k++ )
+ puData[k] = puData0[k] & puData1[k];
+ }
+ // normalize
+ Vec_PtrForEachEntry( vDivs, pObj, i )
+ {
+ puData = pObj->pData;
+ pObj->fPhase = (puData[0] & 1);
+ if ( pObj->fPhase )
+ for ( k = 0; k < nWords; k++ )
+ puData[k] = ~puData[k];
+ }
+}
+
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Dec_Graph_t * Abc_ManResubQuit0( Abc_Obj_t * pRoot, Abc_Obj_t * pObj )
+{
+ Dec_Graph_t * pGraph;
+ Dec_Edge_t eRoot;
+ pGraph = Dec_GraphCreate( 1 );
+ Dec_GraphNode( pGraph, 0 )->pFunc = pObj;
+ eRoot = Dec_EdgeCreate( 0, pObj->fPhase );
+ Dec_GraphSetRoot( pGraph, eRoot );
+ if ( pRoot->fPhase )
+ Dec_GraphComplement( pGraph );
+ return pGraph;
+}
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Dec_Graph_t * Abc_ManResubQuit1( Abc_Obj_t * pRoot, Abc_Obj_t * pObj0, Abc_Obj_t * pObj1, int fOrGate )
+{
+ Dec_Graph_t * pGraph;
+ Dec_Edge_t eRoot, eNode0, eNode1;
+ assert( pObj0 != pObj1 );
+ assert( !Abc_ObjIsComplement(pObj0) );
+ assert( !Abc_ObjIsComplement(pObj1) );
+ pGraph = Dec_GraphCreate( 2 );
+ Dec_GraphNode( pGraph, 0 )->pFunc = pObj0;
+ Dec_GraphNode( pGraph, 1 )->pFunc = pObj1;
+ eNode0 = Dec_EdgeCreate( 0, pObj0->fPhase );
+ eNode1 = Dec_EdgeCreate( 1, pObj1->fPhase );
+ if ( fOrGate )
+ eRoot = Dec_GraphAddNodeOr( pGraph, eNode0, eNode1 );
+ else
+ eRoot = Dec_GraphAddNodeAnd( pGraph, eNode0, eNode1 );
+ Dec_GraphSetRoot( pGraph, eRoot );
+ if ( pRoot->fPhase )
+ Dec_GraphComplement( pGraph );
+ return pGraph;
+}
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Dec_Graph_t * Abc_ManResubQuit21( Abc_Obj_t * pRoot, Abc_Obj_t * pObj0, Abc_Obj_t * pObj1, Abc_Obj_t * pObj2, int fOrGate )
+{
+ Dec_Graph_t * pGraph;
+ Dec_Edge_t eRoot, eNode0, eNode1, eNode2;
+ assert( pObj0 != pObj1 );
+ assert( !Abc_ObjIsComplement(pObj0) );
+ assert( !Abc_ObjIsComplement(pObj1) );
+ assert( !Abc_ObjIsComplement(pObj2) );
+ pGraph = Dec_GraphCreate( 3 );
+ Dec_GraphNode( pGraph, 0 )->pFunc = pObj0;
+ Dec_GraphNode( pGraph, 1 )->pFunc = pObj1;
+ Dec_GraphNode( pGraph, 2 )->pFunc = pObj2;
+ eNode0 = Dec_EdgeCreate( 0, pObj0->fPhase );
+ eNode1 = Dec_EdgeCreate( 1, pObj1->fPhase );
+ eNode2 = Dec_EdgeCreate( 2, pObj2->fPhase );
+ if ( fOrGate )
+ {
+ eRoot = Dec_GraphAddNodeOr( pGraph, eNode0, eNode1 );
+ eRoot = Dec_GraphAddNodeOr( pGraph, eNode2, eRoot );
+ }
+ else
+ {
+ eRoot = Dec_GraphAddNodeAnd( pGraph, eNode0, eNode1 );
+ eRoot = Dec_GraphAddNodeAnd( pGraph, eNode2, eRoot );
+ }
+ Dec_GraphSetRoot( pGraph, eRoot );
+ if ( pRoot->fPhase )
+ Dec_GraphComplement( pGraph );
+ return pGraph;
+}
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Dec_Graph_t * Abc_ManResubQuit2( Abc_Obj_t * pRoot, Abc_Obj_t * pObj0, Abc_Obj_t * pObj1, Abc_Obj_t * pObj2, int fOrGate )
+{
+ Dec_Graph_t * pGraph;
+ Dec_Edge_t eRoot, ePrev, eNode0, eNode1, eNode2;
+ assert( pObj0 != pObj1 );
+ assert( pObj0 != pObj2 );
+ assert( pObj1 != pObj2 );
+ assert( !Abc_ObjIsComplement(pObj0) );
+ pGraph = Dec_GraphCreate( 3 );
+ Dec_GraphNode( pGraph, 0 )->pFunc = Abc_ObjRegular(pObj0);
+ Dec_GraphNode( pGraph, 1 )->pFunc = Abc_ObjRegular(pObj1);
+ Dec_GraphNode( pGraph, 2 )->pFunc = Abc_ObjRegular(pObj2);
+ eNode0 = Dec_EdgeCreate( 0, Abc_ObjRegular(pObj0)->fPhase );
+ if ( Abc_ObjIsComplement(pObj1) && Abc_ObjIsComplement(pObj2) )
+ {
+ eNode1 = Dec_EdgeCreate( 1, Abc_ObjRegular(pObj1)->fPhase );
+ eNode2 = Dec_EdgeCreate( 2, Abc_ObjRegular(pObj2)->fPhase );
+ ePrev = Dec_GraphAddNodeOr( pGraph, eNode1, eNode2 );
+ }
+ else
+ {
+ eNode1 = Dec_EdgeCreate( 1, Abc_ObjRegular(pObj1)->fPhase ^ Abc_ObjIsComplement(pObj1) );
+ eNode2 = Dec_EdgeCreate( 2, Abc_ObjRegular(pObj2)->fPhase ^ Abc_ObjIsComplement(pObj2) );
+ ePrev = Dec_GraphAddNodeAnd( pGraph, eNode1, eNode2 );
+ }
+ if ( fOrGate )
+ eRoot = Dec_GraphAddNodeOr( pGraph, eNode0, ePrev );
+ else
+ eRoot = Dec_GraphAddNodeAnd( pGraph, eNode0, ePrev );
+ Dec_GraphSetRoot( pGraph, eRoot );
+ if ( pRoot->fPhase )
+ Dec_GraphComplement( pGraph );
+ return pGraph;
+}
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Dec_Graph_t * Abc_ManResubQuit3( Abc_Obj_t * pRoot, Abc_Obj_t * pObj0, Abc_Obj_t * pObj1, Abc_Obj_t * pObj2, Abc_Obj_t * pObj3, int fOrGate )
+{
+ Dec_Graph_t * pGraph;
+ Dec_Edge_t eRoot, ePrev0, ePrev1, eNode0, eNode1, eNode2, eNode3;
+ assert( pObj0 != pObj1 );
+ assert( pObj2 != pObj3 );
+ pGraph = Dec_GraphCreate( 4 );
+ Dec_GraphNode( pGraph, 0 )->pFunc = Abc_ObjRegular(pObj0);
+ Dec_GraphNode( pGraph, 1 )->pFunc = Abc_ObjRegular(pObj1);
+ Dec_GraphNode( pGraph, 2 )->pFunc = Abc_ObjRegular(pObj2);
+ Dec_GraphNode( pGraph, 3 )->pFunc = Abc_ObjRegular(pObj3);
+ if ( Abc_ObjIsComplement(pObj0) && Abc_ObjIsComplement(pObj1) )
+ {
+ eNode0 = Dec_EdgeCreate( 0, Abc_ObjRegular(pObj0)->fPhase );
+ eNode1 = Dec_EdgeCreate( 1, Abc_ObjRegular(pObj1)->fPhase );
+ ePrev0 = Dec_GraphAddNodeOr( pGraph, eNode0, eNode1 );
+ if ( Abc_ObjIsComplement(pObj2) && Abc_ObjIsComplement(pObj3) )
+ {
+ eNode2 = Dec_EdgeCreate( 2, Abc_ObjRegular(pObj2)->fPhase );
+ eNode3 = Dec_EdgeCreate( 3, Abc_ObjRegular(pObj3)->fPhase );
+ ePrev1 = Dec_GraphAddNodeOr( pGraph, eNode2, eNode3 );
+ }
+ else
+ {
+ eNode2 = Dec_EdgeCreate( 2, Abc_ObjRegular(pObj2)->fPhase ^ Abc_ObjIsComplement(pObj2) );
+ eNode3 = Dec_EdgeCreate( 3, Abc_ObjRegular(pObj3)->fPhase ^ Abc_ObjIsComplement(pObj3) );
+ ePrev1 = Dec_GraphAddNodeAnd( pGraph, eNode2, eNode3 );
+ }
+ }
+ else
+ {
+ eNode0 = Dec_EdgeCreate( 0, Abc_ObjRegular(pObj0)->fPhase ^ Abc_ObjIsComplement(pObj0) );
+ eNode1 = Dec_EdgeCreate( 1, Abc_ObjRegular(pObj1)->fPhase ^ Abc_ObjIsComplement(pObj1) );
+ ePrev0 = Dec_GraphAddNodeAnd( pGraph, eNode0, eNode1 );
+ if ( Abc_ObjIsComplement(pObj2) && Abc_ObjIsComplement(pObj3) )
+ {
+ eNode2 = Dec_EdgeCreate( 2, Abc_ObjRegular(pObj2)->fPhase );
+ eNode3 = Dec_EdgeCreate( 3, Abc_ObjRegular(pObj3)->fPhase );
+ ePrev1 = Dec_GraphAddNodeOr( pGraph, eNode2, eNode3 );
+ }
+ else
+ {
+ eNode2 = Dec_EdgeCreate( 2, Abc_ObjRegular(pObj2)->fPhase ^ Abc_ObjIsComplement(pObj2) );
+ eNode3 = Dec_EdgeCreate( 3, Abc_ObjRegular(pObj3)->fPhase ^ Abc_ObjIsComplement(pObj3) );
+ ePrev1 = Dec_GraphAddNodeAnd( pGraph, eNode2, eNode3 );
+ }
+ }
+ if ( fOrGate )
+ eRoot = Dec_GraphAddNodeOr( pGraph, ePrev0, ePrev1 );
+ else
+ eRoot = Dec_GraphAddNodeAnd( pGraph, ePrev0, ePrev1 );
+ Dec_GraphSetRoot( pGraph, eRoot );
+ if ( pRoot->fPhase )
+ Dec_GraphComplement( pGraph );
+ return pGraph;
+}
+
+
+
+
+/**Function*************************************************************
+
+ Synopsis [Derives single-node unate/binate divisors.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Abc_ManResubDivsS( Abc_ManRes_t * p, int Required )
+{
+ Abc_Obj_t * pObj;
+ unsigned * puData, * puDataR;
+ int i, w;
+ Vec_PtrClear( p->vDivs1UP );
+ Vec_PtrClear( p->vDivs1UN );
+ Vec_PtrClear( p->vDivs1B );
+ puDataR = p->pRoot->pData;
+ Vec_PtrForEachEntryStop( p->vDivs, pObj, i, p->nDivs )
+ {
+ if ( (int)pObj->Level > Required - 1 )
+ continue;
+
+ puData = pObj->pData;
+ // check positive containment
+ for ( w = 0; w < p->nWords; w++ )
+// if ( puData[w] & ~puDataR[w] )
+ if ( puData[w] & ~puDataR[w] & p->pCareSet[w] ) // care set
+ break;
+ if ( w == p->nWords )
+ {
+ Vec_PtrPush( p->vDivs1UP, pObj );
+ continue;
+ }
+ // check negative containment
+ for ( w = 0; w < p->nWords; w++ )
+// if ( ~puData[w] & puDataR[w] )
+ if ( ~puData[w] & puDataR[w] & p->pCareSet[w] ) // care set
+ break;
+ if ( w == p->nWords )
+ {
+ Vec_PtrPush( p->vDivs1UN, pObj );
+ continue;
+ }
+ // add the node to binates
+ Vec_PtrPush( p->vDivs1B, pObj );
+ }
+}
+
+/**Function*************************************************************
+
+ Synopsis [Derives double-node unate/binate divisors.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Abc_ManResubDivsD( Abc_ManRes_t * p, int Required )
+{
+ Abc_Obj_t * pObj0, * pObj1;
+ unsigned * puData0, * puData1, * puDataR;
+ int i, k, w;
+ Vec_PtrClear( p->vDivs2UP0 );
+ Vec_PtrClear( p->vDivs2UP1 );
+ Vec_PtrClear( p->vDivs2UN0 );
+ Vec_PtrClear( p->vDivs2UN1 );
+ puDataR = p->pRoot->pData;
+ Vec_PtrForEachEntry( p->vDivs1B, pObj0, i )
+ {
+ if ( (int)pObj0->Level > Required - 2 )
+ continue;
+
+ puData0 = pObj0->pData;
+ Vec_PtrForEachEntryStart( p->vDivs1B, pObj1, k, i + 1 )
+ {
+ if ( (int)pObj1->Level > Required - 2 )
+ continue;
+
+ puData1 = pObj1->pData;
+
+ if ( Vec_PtrSize(p->vDivs2UP0) < ABC_RS_DIV2_MAX )
+ {
+ // get positive unate divisors
+ for ( w = 0; w < p->nWords; w++ )
+// if ( (puData0[w] & puData1[w]) & ~puDataR[w] )
+ if ( (puData0[w] & puData1[w]) & ~puDataR[w] & p->pCareSet[w] ) // care set
+ break;
+ if ( w == p->nWords )
+ {
+ Vec_PtrPush( p->vDivs2UP0, pObj0 );
+ Vec_PtrPush( p->vDivs2UP1, pObj1 );
+ }
+ for ( w = 0; w < p->nWords; w++ )
+// if ( (~puData0[w] & puData1[w]) & ~puDataR[w] )
+ if ( (~puData0[w] & puData1[w]) & ~puDataR[w] & p->pCareSet[w] ) // care set
+ break;
+ if ( w == p->nWords )
+ {
+ Vec_PtrPush( p->vDivs2UP0, Abc_ObjNot(pObj0) );
+ Vec_PtrPush( p->vDivs2UP1, pObj1 );
+ }
+ for ( w = 0; w < p->nWords; w++ )
+// if ( (puData0[w] & ~puData1[w]) & ~puDataR[w] )
+ if ( (puData0[w] & ~puData1[w]) & ~puDataR[w] & p->pCareSet[w] ) // care set
+ break;
+ if ( w == p->nWords )
+ {
+ Vec_PtrPush( p->vDivs2UP0, pObj0 );
+ Vec_PtrPush( p->vDivs2UP1, Abc_ObjNot(pObj1) );
+ }
+ for ( w = 0; w < p->nWords; w++ )
+// if ( (puData0[w] | puData1[w]) & ~puDataR[w] )
+ if ( (puData0[w] | puData1[w]) & ~puDataR[w] & p->pCareSet[w] ) // care set
+ break;
+ if ( w == p->nWords )
+ {
+ Vec_PtrPush( p->vDivs2UP0, Abc_ObjNot(pObj0) );
+ Vec_PtrPush( p->vDivs2UP1, Abc_ObjNot(pObj1) );
+ }
+ }
+
+ if ( Vec_PtrSize(p->vDivs2UN0) < ABC_RS_DIV2_MAX )
+ {
+ // get negative unate divisors
+ for ( w = 0; w < p->nWords; w++ )
+// if ( ~(puData0[w] & puData1[w]) & puDataR[w] )
+ if ( ~(puData0[w] & puData1[w]) & puDataR[w] & p->pCareSet[w] ) // care set
+ break;
+ if ( w == p->nWords )
+ {
+ Vec_PtrPush( p->vDivs2UN0, pObj0 );
+ Vec_PtrPush( p->vDivs2UN1, pObj1 );
+ }
+ for ( w = 0; w < p->nWords; w++ )
+// if ( ~(~puData0[w] & puData1[w]) & puDataR[w] )
+ if ( ~(~puData0[w] & puData1[w]) & puDataR[w] & p->pCareSet[w] ) // care set
+ break;
+ if ( w == p->nWords )
+ {
+ Vec_PtrPush( p->vDivs2UN0, Abc_ObjNot(pObj0) );
+ Vec_PtrPush( p->vDivs2UN1, pObj1 );
+ }
+ for ( w = 0; w < p->nWords; w++ )
+// if ( ~(puData0[w] & ~puData1[w]) & puDataR[w] )
+ if ( ~(puData0[w] & ~puData1[w]) & puDataR[w] & p->pCareSet[w] ) // care set
+ break;
+ if ( w == p->nWords )
+ {
+ Vec_PtrPush( p->vDivs2UN0, pObj0 );
+ Vec_PtrPush( p->vDivs2UN1, Abc_ObjNot(pObj1) );
+ }
+ for ( w = 0; w < p->nWords; w++ )
+// if ( ~(puData0[w] | puData1[w]) & puDataR[w] )
+ if ( ~(puData0[w] | puData1[w]) & puDataR[w] & p->pCareSet[w] ) // care set
+ break;
+ if ( w == p->nWords )
+ {
+ Vec_PtrPush( p->vDivs2UN0, Abc_ObjNot(pObj0) );
+ Vec_PtrPush( p->vDivs2UN1, Abc_ObjNot(pObj1) );
+ }
+ }
+ }
+ }
+// printf( "%d %d ", Vec_PtrSize(p->vDivs2UP0), Vec_PtrSize(p->vDivs2UN0) );
+}
+
+
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Dec_Graph_t * Abc_ManResubQuit( Abc_ManRes_t * p )
+{
+ Dec_Graph_t * pGraph;
+ unsigned * upData;
+ int w;
+ upData = p->pRoot->pData;
+ for ( w = 0; w < p->nWords; w++ )
+// if ( upData[w] )
+ if ( upData[w] & p->pCareSet[w] ) // care set
+ break;
+ if ( w != p->nWords )
+ return NULL;
+ // get constant node graph
+ if ( p->pRoot->fPhase )
+ pGraph = Dec_GraphCreateConst1();
+ else
+ pGraph = Dec_GraphCreateConst0();
+ return pGraph;
+}
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Dec_Graph_t * Abc_ManResubDivs0( Abc_ManRes_t * p )
+{
+ Abc_Obj_t * pObj;
+ unsigned * puData, * puDataR;
+ int i, w;
+ puDataR = p->pRoot->pData;
+ Vec_PtrForEachEntryStop( p->vDivs, pObj, i, p->nDivs )
+ {
+ puData = pObj->pData;
+ for ( w = 0; w < p->nWords; w++ )
+// if ( puData[w] != puDataR[w] )
+ if ( (puData[w] ^ puDataR[w]) & p->pCareSet[w] ) // care set
+ break;
+ if ( w == p->nWords )
+ return Abc_ManResubQuit0( p->pRoot, pObj );
+ }
+ return NULL;
+}
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Dec_Graph_t * Abc_ManResubDivs1( Abc_ManRes_t * p, int Required )
+{
+ Abc_Obj_t * pObj0, * pObj1;
+ unsigned * puData0, * puData1, * puDataR;
+ int i, k, w;
+ puDataR = p->pRoot->pData;
+ // check positive unate divisors
+ Vec_PtrForEachEntry( p->vDivs1UP, pObj0, i )
+ {
+ puData0 = pObj0->pData;
+ Vec_PtrForEachEntryStart( p->vDivs1UP, pObj1, k, i + 1 )
+ {
+ puData1 = pObj1->pData;
+ for ( w = 0; w < p->nWords; w++ )
+// if ( (puData0[w] | puData1[w]) != puDataR[w] )
+ if ( ((puData0[w] | puData1[w]) ^ puDataR[w]) & p->pCareSet[w] ) // care set
+ break;
+ if ( w == p->nWords )
+ {
+ p->nUsedNode1Or++;
+ return Abc_ManResubQuit1( p->pRoot, pObj0, pObj1, 1 );
+ }
+ }
+ }
+ // check negative unate divisors
+ Vec_PtrForEachEntry( p->vDivs1UN, pObj0, i )
+ {
+ puData0 = pObj0->pData;
+ Vec_PtrForEachEntryStart( p->vDivs1UN, pObj1, k, i + 1 )
+ {
+ puData1 = pObj1->pData;
+ for ( w = 0; w < p->nWords; w++ )
+// if ( (puData0[w] & puData1[w]) != puDataR[w] )
+ if ( ((puData0[w] & puData1[w]) ^ puDataR[w]) & p->pCareSet[w] ) // care set
+ break;
+ if ( w == p->nWords )
+ {
+ p->nUsedNode1And++;
+ return Abc_ManResubQuit1( p->pRoot, pObj0, pObj1, 0 );
+ }
+ }
+ }
+ return NULL;
+}
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Dec_Graph_t * Abc_ManResubDivs12( Abc_ManRes_t * p, int Required )
+{
+ Abc_Obj_t * pObj0, * pObj1, * pObj2, * pObjMax, * pObjMin0, * pObjMin1;
+ unsigned * puData0, * puData1, * puData2, * puDataR;
+ int i, k, j, w, LevelMax;
+ puDataR = p->pRoot->pData;
+ // check positive unate divisors
+ Vec_PtrForEachEntry( p->vDivs1UP, pObj0, i )
+ {
+ puData0 = pObj0->pData;
+ Vec_PtrForEachEntryStart( p->vDivs1UP, pObj1, k, i + 1 )
+ {
+ puData1 = pObj1->pData;
+ Vec_PtrForEachEntryStart( p->vDivs1UP, pObj2, j, k + 1 )
+ {
+ puData2 = pObj2->pData;
+ for ( w = 0; w < p->nWords; w++ )
+// if ( (puData0[w] | puData1[w] | puData2[w]) != puDataR[w] )
+ if ( ((puData0[w] | puData1[w] | puData2[w]) ^ puDataR[w]) & p->pCareSet[w] ) // care set
+ break;
+ if ( w == p->nWords )
+ {
+ LevelMax = ABC_MAX( pObj0->Level, ABC_MAX(pObj1->Level, pObj2->Level) );
+ assert( LevelMax <= Required - 1 );
+
+ pObjMax = NULL;
+ if ( (int)pObj0->Level == LevelMax )
+ pObjMax = pObj0, pObjMin0 = pObj1, pObjMin1 = pObj2;
+ if ( (int)pObj1->Level == LevelMax )
+ {
+ if ( pObjMax ) continue;
+ pObjMax = pObj1, pObjMin0 = pObj0, pObjMin1 = pObj2;
+ }
+ if ( (int)pObj2->Level == LevelMax )
+ {
+ if ( pObjMax ) continue;
+ pObjMax = pObj2, pObjMin0 = pObj0, pObjMin1 = pObj1;
+ }
+
+ p->nUsedNode2Or++;
+ return Abc_ManResubQuit21( p->pRoot, pObjMin0, pObjMin1, pObjMax, 1 );
+ }
+ }
+ }
+ }
+ // check negative unate divisors
+ Vec_PtrForEachEntry( p->vDivs1UN, pObj0, i )
+ {
+ puData0 = pObj0->pData;
+ Vec_PtrForEachEntryStart( p->vDivs1UN, pObj1, k, i + 1 )
+ {
+ puData1 = pObj1->pData;
+ Vec_PtrForEachEntryStart( p->vDivs1UN, pObj2, j, k + 1 )
+ {
+ puData2 = pObj2->pData;
+ for ( w = 0; w < p->nWords; w++ )
+// if ( (puData0[w] & puData1[w] & puData2[w]) != puDataR[w] )
+ if ( ((puData0[w] & puData1[w] & puData2[w]) ^ puDataR[w]) & p->pCareSet[w] ) // care set
+ break;
+ if ( w == p->nWords )
+ {
+ LevelMax = ABC_MAX( pObj0->Level, ABC_MAX(pObj1->Level, pObj2->Level) );
+ assert( LevelMax <= Required - 1 );
+
+ pObjMax = NULL;
+ if ( (int)pObj0->Level == LevelMax )
+ pObjMax = pObj0, pObjMin0 = pObj1, pObjMin1 = pObj2;
+ if ( (int)pObj1->Level == LevelMax )
+ {
+ if ( pObjMax ) continue;
+ pObjMax = pObj1, pObjMin0 = pObj0, pObjMin1 = pObj2;
+ }
+ if ( (int)pObj2->Level == LevelMax )
+ {
+ if ( pObjMax ) continue;
+ pObjMax = pObj2, pObjMin0 = pObj0, pObjMin1 = pObj1;
+ }
+
+ p->nUsedNode2And++;
+ return Abc_ManResubQuit21( p->pRoot, pObjMin0, pObjMin1, pObjMax, 0 );
+ }
+ }
+ }
+ }
+ return NULL;
+}
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Dec_Graph_t * Abc_ManResubDivs2( Abc_ManRes_t * p, int Required )
+{
+ Abc_Obj_t * pObj0, * pObj1, * pObj2;
+ unsigned * puData0, * puData1, * puData2, * puDataR;
+ int i, k, w;
+ puDataR = p->pRoot->pData;
+ // check positive unate divisors
+ Vec_PtrForEachEntry( p->vDivs1UP, pObj0, i )
+ {
+ puData0 = pObj0->pData;
+ Vec_PtrForEachEntry( p->vDivs2UP0, pObj1, k )
+ {
+ pObj2 = Vec_PtrEntry( p->vDivs2UP1, k );
+
+ puData1 = Abc_ObjRegular(pObj1)->pData;
+ puData2 = Abc_ObjRegular(pObj2)->pData;
+ if ( Abc_ObjIsComplement(pObj1) && Abc_ObjIsComplement(pObj2) )
+ {
+ for ( w = 0; w < p->nWords; w++ )
+// if ( (puData0[w] | (puData1[w] | puData2[w])) != puDataR[w] )
+ if ( ((puData0[w] | (puData1[w] | puData2[w])) ^ puDataR[w]) & p->pCareSet[w] ) // care set
+ break;
+ }
+ else if ( Abc_ObjIsComplement(pObj1) )
+ {
+ for ( w = 0; w < p->nWords; w++ )
+// if ( (puData0[w] | (~puData1[w] & puData2[w])) != puDataR[w] )
+ if ( ((puData0[w] | (~puData1[w] & puData2[w])) ^ puDataR[w]) & p->pCareSet[w] ) // care set
+ break;
+ }
+ else if ( Abc_ObjIsComplement(pObj2) )
+ {
+ for ( w = 0; w < p->nWords; w++ )
+// if ( (puData0[w] | (puData1[w] & ~puData2[w])) != puDataR[w] )
+ if ( ((puData0[w] | (puData1[w] & ~puData2[w])) ^ puDataR[w]) & p->pCareSet[w] ) // care set
+ break;
+ }
+ else
+ {
+ for ( w = 0; w < p->nWords; w++ )
+// if ( (puData0[w] | (puData1[w] & puData2[w])) != puDataR[w] )
+ if ( ((puData0[w] | (puData1[w] & puData2[w])) ^ puDataR[w]) & p->pCareSet[w] ) // care set
+ break;
+ }
+ if ( w == p->nWords )
+ {
+ p->nUsedNode2OrAnd++;
+ return Abc_ManResubQuit2( p->pRoot, pObj0, pObj1, pObj2, 1 );
+ }
+ }
+ }
+ // check negative unate divisors
+ Vec_PtrForEachEntry( p->vDivs1UN, pObj0, i )
+ {
+ puData0 = pObj0->pData;
+ Vec_PtrForEachEntry( p->vDivs2UN0, pObj1, k )
+ {
+ pObj2 = Vec_PtrEntry( p->vDivs2UN1, k );
+
+ puData1 = Abc_ObjRegular(pObj1)->pData;
+ puData2 = Abc_ObjRegular(pObj2)->pData;
+ if ( Abc_ObjIsComplement(pObj1) && Abc_ObjIsComplement(pObj2) )
+ {
+ for ( w = 0; w < p->nWords; w++ )
+// if ( (puData0[w] & (puData1[w] | puData2[w])) != puDataR[w] )
+ if ( ((puData0[w] & (puData1[w] | puData2[w])) ^ puDataR[w]) & p->pCareSet[w] ) // care set
+ break;
+ }
+ else if ( Abc_ObjIsComplement(pObj1) )
+ {
+ for ( w = 0; w < p->nWords; w++ )
+// if ( (puData0[w] & (~puData1[w] & puData2[w])) != puDataR[w] )
+ if ( ((puData0[w] & (~puData1[w] & puData2[w])) ^ puDataR[w]) & p->pCareSet[w] ) // care set
+ break;
+ }
+ else if ( Abc_ObjIsComplement(pObj2) )
+ {
+ for ( w = 0; w < p->nWords; w++ )
+// if ( (puData0[w] & (puData1[w] & ~puData2[w])) != puDataR[w] )
+ if ( ((puData0[w] & (puData1[w] & ~puData2[w])) ^ puDataR[w]) & p->pCareSet[w] ) // care set
+ break;
+ }
+ else
+ {
+ for ( w = 0; w < p->nWords; w++ )
+// if ( (puData0[w] & (puData1[w] & puData2[w])) != puDataR[w] )
+ if ( ((puData0[w] & (puData1[w] & puData2[w])) ^ puDataR[w]) & p->pCareSet[w] ) // care set
+ break;
+ }
+ if ( w == p->nWords )
+ {
+ p->nUsedNode2AndOr++;
+ return Abc_ManResubQuit2( p->pRoot, pObj0, pObj1, pObj2, 0 );
+ }
+ }
+ }
+ return NULL;
+}
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Dec_Graph_t * Abc_ManResubDivs3( Abc_ManRes_t * p, int Required )
+{
+ Abc_Obj_t * pObj0, * pObj1, * pObj2, * pObj3;
+ unsigned * puData0, * puData1, * puData2, * puData3, * puDataR;
+ int i, k, w, Flag;
+ puDataR = p->pRoot->pData;
+ // check positive unate divisors
+ Vec_PtrForEachEntry( p->vDivs2UP0, pObj0, i )
+ {
+ pObj1 = Vec_PtrEntry( p->vDivs2UP1, i );
+ puData0 = Abc_ObjRegular(pObj0)->pData;
+ puData1 = Abc_ObjRegular(pObj1)->pData;
+ Flag = (Abc_ObjIsComplement(pObj0) << 3) | (Abc_ObjIsComplement(pObj1) << 2);
+
+ Vec_PtrForEachEntryStart( p->vDivs2UP0, pObj2, k, i + 1 )
+ {
+ pObj3 = Vec_PtrEntry( p->vDivs2UP1, k );
+ puData2 = Abc_ObjRegular(pObj2)->pData;
+ puData3 = Abc_ObjRegular(pObj3)->pData;
+
+ Flag = (Flag & 12) | (Abc_ObjIsComplement(pObj2) << 1) | Abc_ObjIsComplement(pObj3);
+ assert( Flag < 16 );
+ switch( Flag )
+ {
+ case 0: // 0000
+ for ( w = 0; w < p->nWords; w++ )
+// if ( ((puData0[w] & puData1[w]) | (puData2[w] & puData3[w])) != puDataR[w] )
+ if ( (((puData0[w] & puData1[w]) | (puData2[w] & puData3[w])) ^ puDataR[w]) & p->pCareSet[w] ) // care set
+ break;
+ break;
+ case 1: // 0001
+ for ( w = 0; w < p->nWords; w++ )
+// if ( ((puData0[w] & puData1[w]) | (puData2[w] & ~puData3[w])) != puDataR[w] )
+ if ( (((puData0[w] & puData1[w]) | (puData2[w] & ~puData3[w])) ^ puDataR[w]) & p->pCareSet[w] ) // care set
+ break;
+ break;
+ case 2: // 0010
+ for ( w = 0; w < p->nWords; w++ )
+// if ( ((puData0[w] & puData1[w]) | (~puData2[w] & puData3[w])) != puDataR[w] )
+ if ( (((puData0[w] & puData1[w]) | (~puData2[w] & puData3[w])) ^ puDataR[w]) & p->pCareSet[w] ) // care set
+ break;
+ break;
+ case 3: // 0011
+ for ( w = 0; w < p->nWords; w++ )
+// if ( ((puData0[w] & puData1[w]) | (puData2[w] | puData3[w])) != puDataR[w] )
+ if ( (((puData0[w] & puData1[w]) | (puData2[w] | puData3[w])) ^ puDataR[w]) & p->pCareSet[w] ) // care set
+ break;
+ break;
+
+ case 4: // 0100
+ for ( w = 0; w < p->nWords; w++ )
+// if ( ((puData0[w] & ~puData1[w]) | (puData2[w] & puData3[w])) != puDataR[w] )
+ if ( (((puData0[w] & ~puData1[w]) | (puData2[w] & puData3[w])) ^ puDataR[w]) & p->pCareSet[w] ) // care set
+ break;
+ break;
+ case 5: // 0101
+ for ( w = 0; w < p->nWords; w++ )
+// if ( ((puData0[w] & ~puData1[w]) | (puData2[w] & ~puData3[w])) != puDataR[w] )
+ if ( (((puData0[w] & ~puData1[w]) | (puData2[w] & ~puData3[w])) ^ puDataR[w]) & p->pCareSet[w] ) // care set
+ break;
+ break;
+ case 6: // 0110
+ for ( w = 0; w < p->nWords; w++ )
+// if ( ((puData0[w] & ~puData1[w]) | (~puData2[w] & puData3[w])) != puDataR[w] )
+ if ( (((puData0[w] & ~puData1[w]) | (~puData2[w] & puData3[w])) ^ puDataR[w]) & p->pCareSet[w] ) // care set
+ break;
+ break;
+ case 7: // 0111
+ for ( w = 0; w < p->nWords; w++ )
+// if ( ((puData0[w] & ~puData1[w]) | (puData2[w] | puData3[w])) != puDataR[w] )
+ if ( (((puData0[w] & ~puData1[w]) | (puData2[w] | puData3[w])) ^ puDataR[w]) & p->pCareSet[w] ) // care set
+ break;
+ break;
+
+ case 8: // 1000
+ for ( w = 0; w < p->nWords; w++ )
+// if ( ((~puData0[w] & puData1[w]) | (puData2[w] & puData3[w])) != puDataR[w] )
+ if ( (((~puData0[w] & puData1[w]) | (puData2[w] & puData3[w])) ^ puDataR[w]) & p->pCareSet[w] ) // care set
+ break;
+ break;
+ case 9: // 1001
+ for ( w = 0; w < p->nWords; w++ )
+// if ( ((~puData0[w] & puData1[w]) | (puData2[w] & ~puData3[w])) != puDataR[w] )
+ if ( (((~puData0[w] & puData1[w]) | (puData2[w] & ~puData3[w])) ^ puDataR[w]) & p->pCareSet[w] ) // care set
+ break;
+ break;
+ case 10: // 1010
+ for ( w = 0; w < p->nWords; w++ )
+// if ( ((~puData0[w] & puData1[w]) | (~puData2[w] & puData3[w])) != puDataR[w] )
+ if ( (((~puData0[w] & puData1[w]) | (~puData2[w] & puData3[w])) ^ puDataR[w]) & p->pCareSet[w] ) // care set
+ break;
+ break;
+ case 11: // 1011
+ for ( w = 0; w < p->nWords; w++ )
+// if ( ((~puData0[w] & puData1[w]) | (puData2[w] | puData3[w])) != puDataR[w] )
+ if ( (((~puData0[w] & puData1[w]) | (puData2[w] | puData3[w])) ^ puDataR[w]) & p->pCareSet[w] ) // care set
+ break;
+ break;
+
+ case 12: // 1100
+ for ( w = 0; w < p->nWords; w++ )
+// if ( ((puData0[w] | puData1[w]) | (puData2[w] & puData3[w])) != puDataR[w] )
+ if ( (((puData0[w] | puData1[w]) | (puData2[w] & puData3[w])) ^ puDataR[w]) & p->pCareSet[w] ) // care set
+ break;
+ break;
+ case 13: // 1101
+ for ( w = 0; w < p->nWords; w++ )
+// if ( ((puData0[w] | puData1[w]) | (puData2[w] & ~puData3[w])) != puDataR[w] )
+ if ( (((puData0[w] | puData1[w]) | (puData2[w] & ~puData3[w])) ^ puDataR[w]) & p->pCareSet[w] )
+ break;
+ break;
+ case 14: // 1110
+ for ( w = 0; w < p->nWords; w++ )
+// if ( ((puData0[w] | puData1[w]) | (~puData2[w] & puData3[w])) != puDataR[w] )
+ if ( (((puData0[w] | puData1[w]) | (~puData2[w] & puData3[w])) ^ puDataR[w]) & p->pCareSet[w] )
+ break;
+ break;
+ case 15: // 1111
+ for ( w = 0; w < p->nWords; w++ )
+// if ( ((puData0[w] | puData1[w]) | (puData2[w] | puData3[w])) != puDataR[w] )
+ if ( (((puData0[w] | puData1[w]) | (puData2[w] | puData3[w])) ^ puDataR[w]) & p->pCareSet[w] )
+ break;
+ break;
+
+ }
+ if ( w == p->nWords )
+ {
+ p->nUsedNode3OrAnd++;
+ return Abc_ManResubQuit3( p->pRoot, pObj0, pObj1, pObj2, pObj3, 1 );
+ }
+ }
+ }
+/*
+ // check negative unate divisors
+ Vec_PtrForEachEntry( p->vDivs2UN0, pObj0, i )
+ {
+ pObj1 = Vec_PtrEntry( p->vDivs2UN1, i );
+ puData0 = Abc_ObjRegular(pObj0)->pData;
+ puData1 = Abc_ObjRegular(pObj1)->pData;
+ Flag = (Abc_ObjIsComplement(pObj0) << 3) | (Abc_ObjIsComplement(pObj1) << 2);
+
+ Vec_PtrForEachEntryStart( p->vDivs2UN0, pObj2, k, i + 1 )
+ {
+ pObj3 = Vec_PtrEntry( p->vDivs2UN1, k );
+ puData2 = Abc_ObjRegular(pObj2)->pData;
+ puData3 = Abc_ObjRegular(pObj3)->pData;
+
+ Flag = (Flag & 12) | (Abc_ObjIsComplement(pObj2) << 1) | Abc_ObjIsComplement(pObj3);
+ assert( Flag < 16 );
+ switch( Flag )
+ {
+ case 0: // 0000
+ for ( w = 0; w < p->nWords; w++ )
+ if ( ((puData0[w] & puData1[w]) & (puData2[w] & puData3[w])) != puDataR[w] )
+ break;
+ break;
+ case 1: // 0001
+ for ( w = 0; w < p->nWords; w++ )
+ if ( ((puData0[w] & puData1[w]) & (puData2[w] & ~puData3[w])) != puDataR[w] )
+ break;
+ break;
+ case 2: // 0010
+ for ( w = 0; w < p->nWords; w++ )
+ if ( ((puData0[w] & puData1[w]) & (~puData2[w] & puData3[w])) != puDataR[w] )
+ break;
+ break;
+ case 3: // 0011
+ for ( w = 0; w < p->nWords; w++ )
+ if ( ((puData0[w] & puData1[w]) & (puData2[w] | puData3[w])) != puDataR[w] )
+ break;
+ break;
+
+ case 4: // 0100
+ for ( w = 0; w < p->nWords; w++ )
+ if ( ((puData0[w] & ~puData1[w]) & (puData2[w] & puData3[w])) != puDataR[w] )
+ break;
+ break;
+ case 5: // 0101
+ for ( w = 0; w < p->nWords; w++ )
+ if ( ((puData0[w] & ~puData1[w]) & (puData2[w] & ~puData3[w])) != puDataR[w] )
+ break;
+ break;
+ case 6: // 0110
+ for ( w = 0; w < p->nWords; w++ )
+ if ( ((puData0[w] & ~puData1[w]) & (~puData2[w] & puData3[w])) != puDataR[w] )
+ break;
+ break;
+ case 7: // 0111
+ for ( w = 0; w < p->nWords; w++ )
+ if ( ((puData0[w] & ~puData1[w]) & (puData2[w] | puData3[w])) != puDataR[w] )
+ break;
+ break;
+
+ case 8: // 1000
+ for ( w = 0; w < p->nWords; w++ )
+ if ( ((~puData0[w] & puData1[w]) & (puData2[w] & puData3[w])) != puDataR[w] )
+ break;
+ break;
+ case 9: // 1001
+ for ( w = 0; w < p->nWords; w++ )
+ if ( ((~puData0[w] & puData1[w]) & (puData2[w] & ~puData3[w])) != puDataR[w] )
+ break;
+ break;
+ case 10: // 1010
+ for ( w = 0; w < p->nWords; w++ )
+ if ( ((~puData0[w] & puData1[w]) & (~puData2[w] & puData3[w])) != puDataR[w] )
+ break;
+ break;
+ case 11: // 1011
+ for ( w = 0; w < p->nWords; w++ )
+ if ( ((~puData0[w] & puData1[w]) & (puData2[w] | puData3[w])) != puDataR[w] )
+ break;
+ break;
+
+ case 12: // 1100
+ for ( w = 0; w < p->nWords; w++ )
+ if ( ((puData0[w] | puData1[w]) & (puData2[w] & puData3[w])) != puDataR[w] )
+ break;
+ break;
+ case 13: // 1101
+ for ( w = 0; w < p->nWords; w++ )
+ if ( ((puData0[w] | puData1[w]) & (puData2[w] & ~puData3[w])) != puDataR[w] )
+ break;
+ break;
+ case 14: // 1110
+ for ( w = 0; w < p->nWords; w++ )
+ if ( ((puData0[w] | puData1[w]) & (~puData2[w] & puData3[w])) != puDataR[w] )
+ break;
+ break;
+ case 15: // 1111
+ for ( w = 0; w < p->nWords; w++ )
+ if ( ((puData0[w] | puData1[w]) & (puData2[w] | puData3[w])) != puDataR[w] )
+ break;
+ break;
+
+ }
+ if ( w == p->nWords )
+ {
+ p->nUsedNode3AndOr++;
+ return Abc_ManResubQuit3( p->pRoot, pObj0, pObj1, pObj2, pObj3, 0 );
+ }
+ }
+ }
+*/
+ return NULL;
+}
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Abc_ManResubCleanup( Abc_ManRes_t * p )
+{
+ Abc_Obj_t * pObj;
+ int i;
+ Vec_PtrForEachEntry( p->vDivs, pObj, i )
+ pObj->pData = NULL;
+ Vec_PtrClear( p->vDivs );
+ p->pRoot = NULL;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Evaluates resubstution of one cut.]
+
+ Description [Returns the graph to add if any.]
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Dec_Graph_t * Abc_ManResubEval( Abc_ManRes_t * p, Abc_Obj_t * pRoot, Vec_Ptr_t * vLeaves, int nSteps, bool fUpdateLevel, bool fVerbose )
+{
+ extern int Abc_NodeMffsInside( Abc_Obj_t * pNode, Vec_Ptr_t * vLeaves, Vec_Ptr_t * vInside );
+ Dec_Graph_t * pGraph;
+ int Required;
+ int clk;
+
+ Required = fUpdateLevel? Abc_ObjRequiredLevel(pRoot) : ABC_INFINITY;
+
+ assert( nSteps >= 0 );
+ assert( nSteps <= 3 );
+ p->pRoot = pRoot;
+ p->nLeaves = Vec_PtrSize(vLeaves);
+ p->nLastGain = -1;
+
+ // collect the MFFC
+clk = clock();
+ p->nMffc = Abc_NodeMffsInside( pRoot, vLeaves, p->vTemp );
+p->timeMffc += clock() - clk;
+ assert( p->nMffc > 0 );
+
+ // collect the divisor nodes
+clk = clock();
+ if ( !Abc_ManResubCollectDivs( p, pRoot, vLeaves, Required ) )
+ return NULL;
+ p->timeDiv += clock() - clk;
+
+ p->nTotalDivs += p->nDivs;
+ p->nTotalLeaves += p->nLeaves;
+
+ // simulate the nodes
+clk = clock();
+ Abc_ManResubSimulate( p->vDivs, p->nLeaves, p->vSims, p->nLeavesMax, p->nWords );
+p->timeSim += clock() - clk;
+
+clk = clock();
+ // consider constants
+ if ( pGraph = Abc_ManResubQuit( p ) )
+ {
+ p->nUsedNodeC++;
+ p->nLastGain = p->nMffc;
+ return pGraph;
+ }
+
+ // consider equal nodes
+ if ( pGraph = Abc_ManResubDivs0( p ) )
+ {
+p->timeRes1 += clock() - clk;
+ p->nUsedNode0++;
+ p->nLastGain = p->nMffc;
+ return pGraph;
+ }
+ if ( nSteps == 0 || p->nMffc == 1 )
+ {
+p->timeRes1 += clock() - clk;
+ return NULL;
+ }
+
+ // get the one level divisors
+ Abc_ManResubDivsS( p, Required );
+
+ // consider one node
+ if ( pGraph = Abc_ManResubDivs1( p, Required ) )
+ {
+p->timeRes1 += clock() - clk;
+ p->nLastGain = p->nMffc - 1;
+ return pGraph;
+ }
+p->timeRes1 += clock() - clk;
+ if ( nSteps == 1 || p->nMffc == 2 )
+ return NULL;
+
+clk = clock();
+ // consider triples
+ if ( pGraph = Abc_ManResubDivs12( p, Required ) )
+ {
+p->timeRes2 += clock() - clk;
+ p->nLastGain = p->nMffc - 2;
+ return pGraph;
+ }
+p->timeRes2 += clock() - clk;
+
+ // get the two level divisors
+clk = clock();
+ Abc_ManResubDivsD( p, Required );
+p->timeResD += clock() - clk;
+
+ // consider two nodes
+clk = clock();
+ if ( pGraph = Abc_ManResubDivs2( p, Required ) )
+ {
+p->timeRes2 += clock() - clk;
+ p->nLastGain = p->nMffc - 2;
+ return pGraph;
+ }
+p->timeRes2 += clock() - clk;
+ if ( nSteps == 2 || p->nMffc == 3 )
+ return NULL;
+
+ // consider two nodes
+clk = clock();
+ if ( pGraph = Abc_ManResubDivs3( p, Required ) )
+ {
+p->timeRes3 += clock() - clk;
+ p->nLastGain = p->nMffc - 3;
+ return pGraph;
+ }
+p->timeRes3 += clock() - clk;
+ if ( nSteps == 3 || p->nLeavesMax == 4 )
+ return NULL;
+ return NULL;
+}
+
+
+
+
+/**Function*************************************************************
+
+ Synopsis [Computes the volume and checks if the cut is feasible.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Abc_CutVolumeCheck_rec( Abc_Obj_t * pObj )
+{
+ // quit if the node is visited (or if it is a leaf)
+ if ( Abc_NodeIsTravIdCurrent(pObj) )
+ return 0;
+ Abc_NodeSetTravIdCurrent(pObj);
+ // report the error
+ if ( Abc_ObjIsCi(pObj) )
+ printf( "Abc_CutVolumeCheck() ERROR: The set of nodes is not a cut!\n" );
+ // count the number of nodes in the leaves
+ return 1 + Abc_CutVolumeCheck_rec( Abc_ObjFanin0(pObj) ) +
+ Abc_CutVolumeCheck_rec( Abc_ObjFanin1(pObj) );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Computes the volume and checks if the cut is feasible.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Abc_CutVolumeCheck( Abc_Obj_t * pNode, Vec_Ptr_t * vLeaves )
+{
+ Abc_Obj_t * pObj;
+ int i;
+ // mark the leaves
+ Abc_NtkIncrementTravId( pNode->pNtk );
+ Vec_PtrForEachEntry( vLeaves, pObj, i )
+ Abc_NodeSetTravIdCurrent( pObj );
+ // traverse the nodes starting from the given one and count them
+ return Abc_CutVolumeCheck_rec( pNode );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Computes the factor cut of the node.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Abc_CutFactor_rec( Abc_Obj_t * pObj, Vec_Ptr_t * vLeaves )
+{
+ if ( pObj->fMarkA )
+ return;
+ if ( Abc_ObjIsCi(pObj) || (Abc_ObjFanoutNum(pObj) > 1 && !Abc_NodeIsMuxControlType(pObj)) )
+ {
+ Vec_PtrPush( vLeaves, pObj );
+ pObj->fMarkA = 1;
+ return;
+ }
+ Abc_CutFactor_rec( Abc_ObjFanin0(pObj), vLeaves );
+ Abc_CutFactor_rec( Abc_ObjFanin1(pObj), vLeaves );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Computes the factor cut of the node.]
+
+ Description [Factor-cut is the cut at a node in terms of factor-nodes.
+ Factor-nodes are roots of the node trees (MUXes/EXORs are counted as single nodes).
+ Factor-cut is unique for the given node.]
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Vec_Ptr_t * Abc_CutFactor( Abc_Obj_t * pNode )
+{
+ Vec_Ptr_t * vLeaves;
+ Abc_Obj_t * pObj;
+ int i;
+ assert( !Abc_ObjIsCi(pNode) );
+ vLeaves = Vec_PtrAlloc( 10 );
+ Abc_CutFactor_rec( Abc_ObjFanin0(pNode), vLeaves );
+ Abc_CutFactor_rec( Abc_ObjFanin1(pNode), vLeaves );
+ Vec_PtrForEachEntry( vLeaves, pObj, i )
+ pObj->fMarkA = 0;
+ return vLeaves;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Cut computation.]
+
+ Description [This cut computation works as follows:
+ It starts with the factor cut at the node. If the factor-cut is large, quit.
+ It supports the set of leaves of the cut under construction and labels all nodes
+ in the cut under construction, including the leaves.
+ It computes the factor-cuts of the leaves and checks if it is easible to add any of them.
+ If it is, it randomly chooses one feasible and continues.]
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Vec_Ptr_t * Abc_CutFactorLarge( Abc_Obj_t * pNode, int nLeavesMax )
+{
+ Vec_Ptr_t * vLeaves, * vFactors, * vFact, * vNext;
+ Vec_Int_t * vFeasible;
+ Abc_Obj_t * pLeaf, * pTemp;
+ int i, k, Counter, RandLeaf;
+ int BestCut, BestShare;
+ assert( Abc_ObjIsNode(pNode) );
+ // get one factor-cut
+ vLeaves = Abc_CutFactor( pNode );
+ if ( Vec_PtrSize(vLeaves) > nLeavesMax )
+ {
+ Vec_PtrFree(vLeaves);
+ return NULL;
+ }
+ if ( Vec_PtrSize(vLeaves) == nLeavesMax )
+ return vLeaves;
+ // initialize the factor cuts for the leaves
+ vFactors = Vec_PtrAlloc( nLeavesMax );
+ Abc_NtkIncrementTravId( pNode->pNtk );
+ Vec_PtrForEachEntry( vLeaves, pLeaf, i )
+ {
+ Abc_NodeSetTravIdCurrent( pLeaf );
+ if ( Abc_ObjIsCi(pLeaf) )
+ Vec_PtrPush( vFactors, NULL );
+ else
+ Vec_PtrPush( vFactors, Abc_CutFactor(pLeaf) );
+ }
+ // construct larger factor cuts
+ vFeasible = Vec_IntAlloc( nLeavesMax );
+ while ( 1 )
+ {
+ BestCut = -1;
+ // find the next feasible cut to add
+ Vec_IntClear( vFeasible );
+ Vec_PtrForEachEntry( vFactors, vFact, i )
+ {
+ if ( vFact == NULL )
+ continue;
+ // count the number of unmarked leaves of this factor cut
+ Counter = 0;
+ Vec_PtrForEachEntry( vFact, pTemp, k )
+ Counter += !Abc_NodeIsTravIdCurrent(pTemp);
+ // if the number of new leaves is smaller than the diff, it is feasible
+ if ( Counter <= nLeavesMax - Vec_PtrSize(vLeaves) + 1 )
+ {
+ Vec_IntPush( vFeasible, i );
+ if ( BestCut == -1 || BestShare < Vec_PtrSize(vFact) - Counter )
+ BestCut = i, BestShare = Vec_PtrSize(vFact) - Counter;
+ }
+ }
+ // quit if there is no feasible factor cuts
+ if ( Vec_IntSize(vFeasible) == 0 )
+ break;
+ // randomly choose one leaf and get its factor cut
+// RandLeaf = Vec_IntEntry( vFeasible, rand() % Vec_IntSize(vFeasible) );
+ // choose the cut that has most sharing with the other cuts
+ RandLeaf = BestCut;
+
+ pLeaf = Vec_PtrEntry( vLeaves, RandLeaf );
+ vNext = Vec_PtrEntry( vFactors, RandLeaf );
+ // unmark this leaf
+ Abc_NodeSetTravIdPrevious( pLeaf );
+ // remove this cut from the leaves and factor cuts
+ for ( i = RandLeaf; i < Vec_PtrSize(vLeaves)-1; i++ )
+ {
+ Vec_PtrWriteEntry( vLeaves, i, Vec_PtrEntry(vLeaves, i+1) );
+ Vec_PtrWriteEntry( vFactors, i, Vec_PtrEntry(vFactors,i+1) );
+ }
+ Vec_PtrShrink( vLeaves, Vec_PtrSize(vLeaves) -1 );
+ Vec_PtrShrink( vFactors, Vec_PtrSize(vFactors)-1 );
+ // add new leaves, compute their factor cuts
+ Vec_PtrForEachEntry( vNext, pLeaf, i )
+ {
+ if ( Abc_NodeIsTravIdCurrent(pLeaf) )
+ continue;
+ Abc_NodeSetTravIdCurrent( pLeaf );
+ Vec_PtrPush( vLeaves, pLeaf );
+ if ( Abc_ObjIsCi(pLeaf) )
+ Vec_PtrPush( vFactors, NULL );
+ else
+ Vec_PtrPush( vFactors, Abc_CutFactor(pLeaf) );
+ }
+ Vec_PtrFree( vNext );
+ assert( Vec_PtrSize(vLeaves) <= nLeavesMax );
+ if ( Vec_PtrSize(vLeaves) == nLeavesMax )
+ break;
+ }
+
+ // remove temporary storage
+ Vec_PtrForEachEntry( vFactors, vFact, i )
+ if ( vFact ) Vec_PtrFree( vFact );
+ Vec_PtrFree( vFactors );
+ Vec_IntFree( vFeasible );
+ return vLeaves;
+}
+
+////////////////////////////////////////////////////////////////////////
+/// END OF FILE ///
+////////////////////////////////////////////////////////////////////////
+
+
diff --git a/src/base/abci/abcRewrite.c b/src/base/abci/abcRewrite.c
index ea221296..3b50107b 100644
--- a/src/base/abci/abcRewrite.c
+++ b/src/base/abci/abcRewrite.c
@@ -32,11 +32,16 @@
/// DECLARATIONS ///
////////////////////////////////////////////////////////////////////////
-static Cut_Man_t * Abc_NtkStartCutManForRewrite( Abc_Ntk_t * pNtk, int fDrop );
+static Cut_Man_t * Abc_NtkStartCutManForRewrite( Abc_Ntk_t * pNtk );
static void Abc_NodePrintCuts( Abc_Obj_t * pNode );
+static void Abc_ManShowCutCone( Abc_Obj_t * pNode, Vec_Ptr_t * vLeaves );
+
+extern void Abc_PlaceBegin( Abc_Ntk_t * pNtk );
+extern void Abc_PlaceEnd( Abc_Ntk_t * pNtk );
+extern void Abc_PlaceUpdate( Vec_Ptr_t * vAddedCells, Vec_Ptr_t * vUpdatedNets );
////////////////////////////////////////////////////////////////////////
-/// FUNCTION DEFITIONS ///
+/// FUNCTION DEFINITIONS ///
////////////////////////////////////////////////////////////////////////
/**Function*************************************************************
@@ -50,31 +55,54 @@ static void Abc_NodePrintCuts( Abc_Obj_t * pNode );
SeeAlso []
***********************************************************************/
-int Abc_NtkRewrite( Abc_Ntk_t * pNtk, int fUseZeros, int fVerbose )
+int Abc_NtkRewrite( Abc_Ntk_t * pNtk, int fUpdateLevel, int fUseZeros, int fVerbose, int fVeryVerbose, int fPlaceEnable )
{
- int fDrop = 0;
+ extern void Dec_GraphUpdateNetwork( Abc_Obj_t * pRoot, Dec_Graph_t * pGraph, bool fUpdateLevel, int nGain );
ProgressBar * pProgress;
Cut_Man_t * pManCut;
Rwr_Man_t * pManRwr;
Abc_Obj_t * pNode;
- int i, nNodes, nGain;
+ Vec_Ptr_t * vAddedCells = NULL, * vUpdatedNets = NULL;
+ Dec_Graph_t * pGraph;
+ int i, nNodes, nGain, fCompl;
int clk, clkStart = clock();
assert( Abc_NtkIsStrash(pNtk) );
// cleanup the AIG
Abc_AigCleanup(pNtk->pManFunc);
+/*
+ {
+ Vec_Vec_t * vParts;
+ vParts = Abc_NtkPartitionSmart( pNtk, 50, 1 );
+ Vec_VecFree( vParts );
+ }
+*/
+
+ // start placement package
+// if ( fPlaceEnable )
+// {
+// Abc_PlaceBegin( pNtk );
+// vAddedCells = Abc_AigUpdateStart( pNtk->pManFunc, &vUpdatedNets );
+// }
+
// start the rewriting manager
pManRwr = Rwr_ManStart( 0 );
if ( pManRwr == NULL )
return 0;
- Abc_NtkStartReverseLevels( pNtk );
+ // compute the reverse levels if level update is requested
+ if ( fUpdateLevel )
+ Abc_NtkStartReverseLevels( pNtk, 0 );
// start the cut manager
clk = clock();
- pManCut = Abc_NtkStartCutManForRewrite( pNtk, fDrop );
+ pManCut = Abc_NtkStartCutManForRewrite( pNtk );
Rwr_ManAddTimeCuts( pManRwr, clock() - clk );
pNtk->pManCut = pManCut;
+ if ( fVeryVerbose )
+ Rwr_ScoresClean( pManRwr );
+
// resynthesize each node once
+ pManRwr->nNodesBeg = Abc_NtkNodeNum(pNtk);
nNodes = Abc_NtkObjNumMax(pNtk);
pProgress = Extra_ProgressBarStart( stdout, nNodes );
Abc_NtkForEachNode( pNtk, pNode, i )
@@ -83,34 +111,71 @@ Rwr_ManAddTimeCuts( pManRwr, clock() - clk );
// stop if all nodes have been tried once
if ( i >= nNodes )
break;
- // skip the constant node
- if ( Abc_NodeIsConst(pNode) )
+ // skip persistant nodes
+ if ( Abc_NodeIsPersistant(pNode) )
continue;
// skip the nodes with many fanouts
if ( Abc_ObjFanoutNum(pNode) > 1000 )
continue;
+
// for each cut, try to resynthesize it
- nGain = Rwr_NodeRewrite( pManRwr, pManCut, pNode, fUseZeros );
- if ( nGain > 0 || nGain == 0 && fUseZeros )
- {
- Dec_Graph_t * pGraph = Rwr_ManReadDecs(pManRwr);
- int fCompl = Rwr_ManReadCompl(pManRwr);
- // complement the FF if needed
- if ( fCompl ) Dec_GraphComplement( pGraph );
- Dec_GraphUpdateNetwork( pNode, pGraph, nGain );
- if ( fCompl ) Dec_GraphComplement( pGraph );
- }
+ nGain = Rwr_NodeRewrite( pManRwr, pManCut, pNode, fUpdateLevel, fUseZeros, fPlaceEnable );
+ if ( !(nGain > 0 || nGain == 0 && fUseZeros) )
+ continue;
+ // if we end up here, a rewriting step is accepted
+
+ // get hold of the new subgraph to be added to the AIG
+ pGraph = Rwr_ManReadDecs(pManRwr);
+ fCompl = Rwr_ManReadCompl(pManRwr);
+
+ // reset the array of the changed nodes
+ if ( fPlaceEnable )
+ Abc_AigUpdateReset( pNtk->pManFunc );
+
+ // complement the FF if needed
+ if ( fCompl ) Dec_GraphComplement( pGraph );
+clk = clock();
+ Dec_GraphUpdateNetwork( pNode, pGraph, fUpdateLevel, nGain );
+Rwr_ManAddTimeUpdate( pManRwr, clock() - clk );
+ if ( fCompl ) Dec_GraphComplement( pGraph );
+
+ // use the array of changed nodes to update placement
+// if ( fPlaceEnable )
+// Abc_PlaceUpdate( vAddedCells, vUpdatedNets );
}
Extra_ProgressBarStop( pProgress );
Rwr_ManAddTimeTotal( pManRwr, clock() - clkStart );
// print stats
+ pManRwr->nNodesEnd = Abc_NtkNodeNum(pNtk);
if ( fVerbose )
Rwr_ManPrintStats( pManRwr );
+// Rwr_ManPrintStatsFile( pManRwr );
+ if ( fVeryVerbose )
+ Rwr_ScoresReport( pManRwr );
// delete the managers
Rwr_ManStop( pManRwr );
Cut_ManStop( pManCut );
pNtk->pManCut = NULL;
- Abc_NtkStopReverseLevels( pNtk );
+
+ // start placement package
+// if ( fPlaceEnable )
+// {
+// Abc_PlaceEnd( pNtk );
+// Abc_AigUpdateStop( pNtk->pManFunc );
+// }
+
+ // put the nodes into the DFS order and reassign their IDs
+ {
+// int clk = clock();
+ Abc_NtkReassignIds( pNtk );
+// PRT( "time", clock() - clk );
+ }
+// Abc_AigCheckFaninOrder( pNtk->pManFunc );
+ // fix the levels
+ if ( fUpdateLevel )
+ Abc_NtkStopReverseLevels( pNtk );
+ else
+ Abc_NtkLevel( pNtk );
// check
if ( !Abc_NtkCheck( pNtk ) )
{
@@ -132,7 +197,7 @@ Rwr_ManAddTimeTotal( pManRwr, clock() - clkStart );
SeeAlso []
***********************************************************************/
-Cut_Man_t * Abc_NtkStartCutManForRewrite( Abc_Ntk_t * pNtk, int fDrop )
+Cut_Man_t * Abc_NtkStartCutManForRewrite( Abc_Ntk_t * pNtk )
{
static Cut_Params_t Params, * pParams = &Params;
Cut_Man_t * pManCut;
@@ -143,10 +208,9 @@ Cut_Man_t * Abc_NtkStartCutManForRewrite( Abc_Ntk_t * pNtk, int fDrop )
pParams->nVarsMax = 4; // the max cut size ("k" of the k-feasible cuts)
pParams->nKeepMax = 250; // the max number of cuts kept at a node
pParams->fTruth = 1; // compute truth tables
- pParams->fHash = 1; // hash cuts to detect unique
- pParams->fFilter = 0; // filter dominated cuts
+ pParams->fFilter = 1; // filter dominated cuts
pParams->fSeq = 0; // compute sequential cuts
- pParams->fDrop = fDrop; // drop cuts on the fly
+ pParams->fDrop = 0; // drop cuts on the fly
pParams->fVerbose = 0; // the verbosiness flag
pParams->nIdsMax = Abc_NtkObjNumMax( pNtk );
pManCut = Cut_ManStart( pParams );
@@ -172,19 +236,178 @@ Cut_Man_t * Abc_NtkStartCutManForRewrite( Abc_Ntk_t * pNtk, int fDrop )
***********************************************************************/
void Abc_NodePrintCuts( Abc_Obj_t * pNode )
{
+ Vec_Ptr_t * vCuts;
Cut_Cut_t * pCut;
- unsigned uTruth;
+ int k;
+
printf( "\nNode %s\n", Abc_ObjName(pNode) );
- for ( pCut = (Cut_Cut_t *)pNode->pCopy; pCut; pCut = pCut->pNext )
+ vCuts = (Vec_Ptr_t *)pNode->pCopy;
+ Vec_PtrForEachEntry( vCuts, pCut, k )
{
- uTruth = pCut->uTruth;
- Extra_PrintBinary( stdout, &uTruth, 16 );
+ Extra_PrintBinary( stdout, (unsigned *)&pCut->uSign, 16 );
printf( " " );
- Cut_CutPrint( pCut );
+ Cut_CutPrint( pCut, 0 );
printf( "\n" );
}
}
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Abc_ManRewritePrintDivs( Vec_Ptr_t * vDivs, int nLeaves )
+{
+ Abc_Obj_t * pFanin, * pNode, * pRoot;
+ int i, k;
+ pRoot = Vec_PtrEntryLast(vDivs);
+ // print the nodes
+ Vec_PtrForEachEntry( vDivs, pNode, i )
+ {
+ if ( i < nLeaves )
+ {
+ printf( "%6d : %c\n", pNode->Id, 'a'+i );
+ continue;
+ }
+ printf( "%6d : %2d = ", pNode->Id, i );
+ // find the first fanin
+ Vec_PtrForEachEntry( vDivs, pFanin, k )
+ if ( Abc_ObjFanin0(pNode) == pFanin )
+ break;
+ if ( k < nLeaves )
+ printf( "%c", 'a' + k );
+ else
+ printf( "%d", k );
+ printf( "%s ", Abc_ObjFaninC0(pNode)? "\'" : "" );
+ // find the second fanin
+ Vec_PtrForEachEntry( vDivs, pFanin, k )
+ if ( Abc_ObjFanin1(pNode) == pFanin )
+ break;
+ if ( k < nLeaves )
+ printf( "%c", 'a' + k );
+ else
+ printf( "%d", k );
+ printf( "%s ", Abc_ObjFaninC1(pNode)? "\'" : "" );
+ if ( pNode == pRoot )
+ printf( " root" );
+ printf( "\n" );
+ }
+ printf( "\n" );
+}
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Abc_ManShowCutCone_rec( Abc_Obj_t * pNode, Vec_Ptr_t * vDivs )
+{
+ if ( Abc_NodeIsTravIdCurrent(pNode) )
+ return;
+ Abc_NodeSetTravIdCurrent(pNode);
+ Abc_ManShowCutCone_rec( Abc_ObjFanin0(pNode), vDivs );
+ Abc_ManShowCutCone_rec( Abc_ObjFanin1(pNode), vDivs );
+ Vec_PtrPush( vDivs, pNode );
+}
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Abc_ManShowCutCone( Abc_Obj_t * pNode, Vec_Ptr_t * vLeaves )
+{
+ Abc_Ntk_t * pNtk = pNode->pNtk;
+ Abc_Obj_t * pObj;
+ Vec_Ptr_t * vDivs;
+ int i;
+ vDivs = Vec_PtrAlloc( 100 );
+ Abc_NtkIncrementTravId( pNtk );
+ Vec_PtrForEachEntry( vLeaves, pObj, i )
+ {
+ Abc_NodeSetTravIdCurrent( Abc_ObjRegular(pObj) );
+ Vec_PtrPush( vDivs, Abc_ObjRegular(pObj) );
+ }
+ Abc_ManShowCutCone_rec( pNode, vDivs );
+ Abc_ManRewritePrintDivs( vDivs, Vec_PtrSize(vLeaves) );
+ Vec_PtrFree( vDivs );
+}
+
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Abc_RwrExpWithCut_rec( Abc_Obj_t * pNode, Vec_Ptr_t * vLeaves, int fUseA )
+{
+ if ( Vec_PtrFind(vLeaves, pNode) >= 0 || Vec_PtrFind(vLeaves, Abc_ObjNot(pNode)) >= 0 )
+ {
+ if ( fUseA )
+ Abc_ObjRegular(pNode)->fMarkA = 1;
+ else
+ Abc_ObjRegular(pNode)->fMarkB = 1;
+ return;
+ }
+ assert( Abc_ObjIsNode(pNode) );
+ Abc_RwrExpWithCut_rec( Abc_ObjFanin0(pNode), vLeaves, fUseA );
+ Abc_RwrExpWithCut_rec( Abc_ObjFanin1(pNode), vLeaves, fUseA );
+}
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Abc_RwrExpWithCut( Abc_Obj_t * pNode, Vec_Ptr_t * vLeaves )
+{
+ Abc_Obj_t * pObj;
+ int i, CountA, CountB;
+ Abc_RwrExpWithCut_rec( Abc_ObjFanin0(pNode), vLeaves, 1 );
+ Abc_RwrExpWithCut_rec( Abc_ObjFanin1(pNode), vLeaves, 0 );
+ CountA = CountB = 0;
+ Vec_PtrForEachEntry( vLeaves, pObj, i )
+ {
+ CountA += Abc_ObjRegular(pObj)->fMarkA;
+ CountB += Abc_ObjRegular(pObj)->fMarkB;
+ Abc_ObjRegular(pObj)->fMarkA = 0;
+ Abc_ObjRegular(pObj)->fMarkB = 0;
+ }
+ printf( "(%d,%d:%d) ", CountA, CountB, CountA+CountB-Vec_PtrSize(vLeaves) );
+}
+
+
////////////////////////////////////////////////////////////////////////
/// END OF FILE ///
////////////////////////////////////////////////////////////////////////
diff --git a/src/base/abci/abcRr.c b/src/base/abci/abcRr.c
new file mode 100644
index 00000000..92adc718
--- /dev/null
+++ b/src/base/abci/abcRr.c
@@ -0,0 +1,999 @@
+/**CFile****************************************************************
+
+ FileName [abcRr.c]
+
+ SystemName [ABC: Logic synthesis and verification system.]
+
+ PackageName [Network and node package.]
+
+ Synopsis [Redundancy removal.]
+
+ Author [Alan Mishchenko]
+
+ Affiliation [UC Berkeley]
+
+ Date [Ver. 1.0. Started - June 20, 2005.]
+
+ Revision [$Id: abcRr.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "abc.h"
+#include "fraig.h"
+#include "sim.h"
+
+////////////////////////////////////////////////////////////////////////
+/// DECLARATIONS ///
+////////////////////////////////////////////////////////////////////////
+
+typedef struct Abc_RRMan_t_ Abc_RRMan_t;
+struct Abc_RRMan_t_
+{
+ // the parameters
+ Abc_Ntk_t * pNtk; // the network
+ int nFaninLevels; // the number of fanin levels
+ int nFanoutLevels; // the number of fanout levels
+ // the node/fanin/fanout
+ Abc_Obj_t * pNode; // the node
+ Abc_Obj_t * pFanin; // the fanin
+ Abc_Obj_t * pFanout; // the fanout
+ // the intermediate cones
+ Vec_Ptr_t * vFaninLeaves; // the leaves of the fanin cone
+ Vec_Ptr_t * vFanoutRoots; // the roots of the fanout cone
+ // the window
+ Vec_Ptr_t * vLeaves; // the leaves of the window
+ Vec_Ptr_t * vCone; // the internal nodes of the window
+ Vec_Ptr_t * vRoots; // the roots of the window
+ Abc_Ntk_t * pWnd; // the window derived for the edge
+ // the miter
+ Abc_Ntk_t * pMiter; // the miter derived from the window
+ Prove_Params_t * pParams; // the miter proving parameters
+ // statistical variables
+ int nNodesOld; // the old number of nodes
+ int nLevelsOld; // the old number of levels
+ int nEdgesTried; // the number of nodes tried
+ int nEdgesRemoved; // the number of nodes proved
+ int timeWindow; // the time to construct the window
+ int timeMiter; // the time to construct the miter
+ int timeProve; // the time to prove the miter
+ int timeUpdate; // the network update time
+ int timeTotal; // the total runtime
+};
+
+static Abc_RRMan_t * Abc_RRManStart();
+static void Abc_RRManStop( Abc_RRMan_t * p );
+static void Abc_RRManPrintStats( Abc_RRMan_t * p );
+static void Abc_RRManClean( Abc_RRMan_t * p );
+static int Abc_NtkRRProve( Abc_RRMan_t * p );
+static int Abc_NtkRRUpdate( Abc_Ntk_t * pNtk, Abc_Obj_t * pNode, Abc_Obj_t * pFanin, Abc_Obj_t * pFanout );
+static int Abc_NtkRRWindow( Abc_RRMan_t * p );
+
+static int Abc_NtkRRTfi_int( Vec_Ptr_t * vLeaves, int LevelLimit );
+static int Abc_NtkRRTfo_int( Vec_Ptr_t * vLeaves, Vec_Ptr_t * vRoots, int LevelLimit, Abc_Obj_t * pEdgeFanin, Abc_Obj_t * pEdgeFanout );
+static int Abc_NtkRRTfo_rec( Abc_Obj_t * pNode, Vec_Ptr_t * vRoots, int LevelLimit );
+static void Abc_NtkRRTfi_rec( Abc_Obj_t * pNode, Vec_Ptr_t * vLeaves, Vec_Ptr_t * vCone, int LevelLimit );
+static Abc_Ntk_t * Abc_NtkWindow( Abc_Ntk_t * pNtk, Vec_Ptr_t * vLeaves, Vec_Ptr_t * vCone, Vec_Ptr_t * vRoots );
+
+static void Abc_NtkRRSimulateStart( Abc_Ntk_t * pNtk );
+static void Abc_NtkRRSimulateStop( Abc_Ntk_t * pNtk );
+
+////////////////////////////////////////////////////////////////////////
+/// FUNCTION DEFINITIONS ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+ Synopsis [Removes stuck-at redundancies.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Abc_NtkRR( Abc_Ntk_t * pNtk, int nFaninLevels, int nFanoutLevels, int fUseFanouts, int fVerbose )
+{
+ ProgressBar * pProgress;
+ Abc_RRMan_t * p;
+ Abc_Obj_t * pNode, * pFanin, * pFanout;
+ int i, k, m, nNodes, RetValue, clk, clkTotal = clock();
+ // start the manager
+ p = Abc_RRManStart( nFaninLevels, nFanoutLevels );
+ p->pNtk = pNtk;
+ p->nFaninLevels = nFaninLevels;
+ p->nFanoutLevels = nFanoutLevels;
+ p->nNodesOld = Abc_NtkNodeNum(pNtk);
+ p->nLevelsOld = Abc_AigLevel(pNtk);
+ // remember latch values
+// Abc_NtkForEachLatch( pNtk, pNode, i )
+// pNode->pNext = pNode->pData;
+ // go through the nodes
+ Abc_NtkCleanCopy(pNtk);
+ nNodes = Abc_NtkObjNumMax(pNtk);
+ Abc_NtkRRSimulateStart(pNtk);
+ pProgress = Extra_ProgressBarStart( stdout, nNodes );
+ Abc_NtkForEachNode( pNtk, pNode, i )
+ {
+ Extra_ProgressBarUpdate( pProgress, i, NULL );
+ // stop if all nodes have been tried once
+ if ( i >= nNodes )
+ break;
+ // skip the constant node
+// if ( Abc_NodeIsConst(pNode) )
+// continue;
+ // skip persistant nodes
+ if ( Abc_NodeIsPersistant(pNode) )
+ continue;
+ // skip the nodes with many fanouts
+ if ( Abc_ObjFanoutNum(pNode) > 1000 )
+ continue;
+ // construct the window
+ if ( !fUseFanouts )
+ {
+ Abc_ObjForEachFanin( pNode, pFanin, k )
+ {
+ // skip the nodes with only one fanout (tree nodes)
+ if ( Abc_ObjFanoutNum(pFanin) == 1 )
+ continue;
+/*
+ if ( pFanin->Id == 228 && pNode->Id == 2649 )
+ {
+ int k = 0;
+ }
+*/
+ p->nEdgesTried++;
+ Abc_RRManClean( p );
+ p->pNode = pNode;
+ p->pFanin = pFanin;
+ p->pFanout = NULL;
+
+ clk = clock();
+ RetValue = Abc_NtkRRWindow( p );
+ p->timeWindow += clock() - clk;
+ if ( !RetValue )
+ continue;
+/*
+ if ( pFanin->Id == 228 && pNode->Id == 2649 )
+ {
+ Abc_NtkShowAig( p->pWnd, 0 );
+ }
+*/
+ clk = clock();
+ RetValue = Abc_NtkRRProve( p );
+ p->timeMiter += clock() - clk;
+ if ( !RetValue )
+ continue;
+//printf( "%d -> %d (%d)\n", pFanin->Id, pNode->Id, k );
+
+ clk = clock();
+ Abc_NtkRRUpdate( pNtk, p->pNode, p->pFanin, p->pFanout );
+ p->timeUpdate += clock() - clk;
+
+ p->nEdgesRemoved++;
+ break;
+ }
+ continue;
+ }
+ // use the fanouts
+ Abc_ObjForEachFanin( pNode, pFanin, k )
+ Abc_ObjForEachFanout( pNode, pFanout, m )
+ {
+ // skip the nodes with only one fanout (tree nodes)
+// if ( Abc_ObjFanoutNum(pFanin) == 1 && Abc_ObjFanoutNum(pNode) == 1 )
+// continue;
+
+ p->nEdgesTried++;
+ Abc_RRManClean( p );
+ p->pNode = pNode;
+ p->pFanin = pFanin;
+ p->pFanout = pFanout;
+
+ clk = clock();
+ RetValue = Abc_NtkRRWindow( p );
+ p->timeWindow += clock() - clk;
+ if ( !RetValue )
+ continue;
+
+ clk = clock();
+ RetValue = Abc_NtkRRProve( p );
+ p->timeMiter += clock() - clk;
+ if ( !RetValue )
+ continue;
+
+ clk = clock();
+ Abc_NtkRRUpdate( pNtk, p->pNode, p->pFanin, p->pFanout );
+ p->timeUpdate += clock() - clk;
+
+ p->nEdgesRemoved++;
+ break;
+ }
+ }
+ Abc_NtkRRSimulateStop(pNtk);
+ Extra_ProgressBarStop( pProgress );
+ p->timeTotal = clock() - clkTotal;
+ if ( fVerbose )
+ Abc_RRManPrintStats( p );
+ Abc_RRManStop( p );
+ // restore latch values
+// Abc_NtkForEachLatch( pNtk, pNode, i )
+// pNode->pData = pNode->pNext, pNode->pNext = NULL;
+ // put the nodes into the DFS order and reassign their IDs
+ Abc_NtkReassignIds( pNtk );
+ Abc_NtkLevel( pNtk );
+ // check
+ if ( !Abc_NtkCheck( pNtk ) )
+ {
+ printf( "Abc_NtkRR: The network check has failed.\n" );
+ return 0;
+ }
+ return 1;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Start the manager.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Abc_RRMan_t * Abc_RRManStart()
+{
+ Abc_RRMan_t * p;
+ p = ALLOC( Abc_RRMan_t, 1 );
+ memset( p, 0, sizeof(Abc_RRMan_t) );
+ p->vFaninLeaves = Vec_PtrAlloc( 100 ); // the leaves of the fanin cone
+ p->vFanoutRoots = Vec_PtrAlloc( 100 ); // the roots of the fanout cone
+ p->vLeaves = Vec_PtrAlloc( 100 ); // the leaves of the window
+ p->vCone = Vec_PtrAlloc( 100 ); // the internal nodes of the window
+ p->vRoots = Vec_PtrAlloc( 100 ); // the roots of the window
+ p->pParams = ALLOC( Prove_Params_t, 1 );
+ memset( p->pParams, 0, sizeof(Prove_Params_t) );
+ Prove_ParamsSetDefault( p->pParams );
+ return p;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Stop the manager.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Abc_RRManStop( Abc_RRMan_t * p )
+{
+ Abc_RRManClean( p );
+ Vec_PtrFree( p->vFaninLeaves );
+ Vec_PtrFree( p->vFanoutRoots );
+ Vec_PtrFree( p->vLeaves );
+ Vec_PtrFree( p->vCone );
+ Vec_PtrFree( p->vRoots );
+ free( p->pParams );
+ free( p );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Stop the manager.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Abc_RRManPrintStats( Abc_RRMan_t * p )
+{
+ double Ratio = 100.0*(p->nNodesOld - Abc_NtkNodeNum(p->pNtk))/p->nNodesOld;
+ printf( "Redundancy removal statistics:\n" );
+ printf( "Edges tried = %6d.\n", p->nEdgesTried );
+ printf( "Edges removed = %6d. (%5.2f %%)\n", p->nEdgesRemoved, 100.0*p->nEdgesRemoved/p->nEdgesTried );
+ printf( "Node gain = %6d. (%5.2f %%)\n", p->nNodesOld - Abc_NtkNodeNum(p->pNtk), Ratio );
+ printf( "Level gain = %6d.\n", p->nLevelsOld - Abc_AigLevel(p->pNtk) );
+ PRT( "Windowing ", p->timeWindow );
+ PRT( "Miter ", p->timeMiter );
+ PRT( " Construct ", p->timeMiter - p->timeProve );
+ PRT( " Prove ", p->timeProve );
+ PRT( "Update ", p->timeUpdate );
+ PRT( "TOTAL ", p->timeTotal );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Clean the manager.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Abc_RRManClean( Abc_RRMan_t * p )
+{
+ p->pNode = NULL;
+ p->pFanin = NULL;
+ p->pFanout = NULL;
+ Vec_PtrClear( p->vFaninLeaves );
+ Vec_PtrClear( p->vFanoutRoots );
+ Vec_PtrClear( p->vLeaves );
+ Vec_PtrClear( p->vCone );
+ Vec_PtrClear( p->vRoots );
+ if ( p->pWnd ) Abc_NtkDelete( p->pWnd );
+ if ( p->pMiter ) Abc_NtkDelete( p->pMiter );
+ p->pWnd = NULL;
+ p->pMiter = NULL;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Returns 1 if the miter is constant 0.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Abc_NtkRRProve( Abc_RRMan_t * p )
+{
+ Abc_Ntk_t * pWndCopy;
+ int RetValue, clk;
+// Abc_NtkShowAig( p->pWnd, 0 );
+ pWndCopy = Abc_NtkDup( p->pWnd );
+ Abc_NtkRRUpdate( pWndCopy, p->pNode->pCopy->pCopy, p->pFanin->pCopy->pCopy, p->pFanout? p->pFanout->pCopy->pCopy : NULL );
+ if ( !Abc_NtkIsDfsOrdered(pWndCopy) )
+ Abc_NtkReassignIds(pWndCopy);
+ p->pMiter = Abc_NtkMiter( p->pWnd, pWndCopy, 1, 0 );
+ Abc_NtkDelete( pWndCopy );
+clk = clock();
+ RetValue = Abc_NtkMiterProve( &p->pMiter, p->pParams );
+p->timeProve += clock() - clk;
+ if ( RetValue == 1 )
+ return 1;
+ return 0;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Updates the network after redundancy removal.]
+
+ Description [This procedure assumes that non-control value of the fanin
+ was proved redundant. It is okay to concentrate on non-control values
+ because the control values can be seen as redundancy of the fanout edge.]
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Abc_NtkRRUpdate( Abc_Ntk_t * pNtk, Abc_Obj_t * pNode, Abc_Obj_t * pFanin, Abc_Obj_t * pFanout )
+{
+ Abc_Obj_t * pNodeNew, * pFanoutNew;
+ assert( pFanout == NULL );
+ assert( !Abc_ObjIsComplement(pNode) );
+ assert( !Abc_ObjIsComplement(pFanin) );
+ assert( !Abc_ObjIsComplement(pFanout) );
+ // find the node after redundancy removal
+ if ( pFanin == Abc_ObjFanin0(pNode) )
+ pNodeNew = Abc_ObjChild1(pNode);
+ else if ( pFanin == Abc_ObjFanin1(pNode) )
+ pNodeNew = Abc_ObjChild0(pNode);
+ else assert( 0 );
+ // replace
+ if ( pFanout == NULL )
+ {
+ Abc_AigReplace( pNtk->pManFunc, pNode, pNodeNew, 1 );
+ return 1;
+ }
+ // find the fanout after redundancy removal
+ if ( pNode == Abc_ObjFanin0(pFanout) )
+ pFanoutNew = Abc_AigAnd( pNtk->pManFunc, Abc_ObjNotCond(pNodeNew,Abc_ObjFaninC0(pFanout)), Abc_ObjChild1(pFanout) );
+ else if ( pNode == Abc_ObjFanin1(pFanout) )
+ pFanoutNew = Abc_AigAnd( pNtk->pManFunc, Abc_ObjNotCond(pNodeNew,Abc_ObjFaninC1(pFanout)), Abc_ObjChild0(pFanout) );
+ else assert( 0 );
+ // replace
+ Abc_AigReplace( pNtk->pManFunc, pFanout, pFanoutNew, 1 );
+ return 1;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Constructs window for checking RR.]
+
+ Description [If the window (p->pWnd) with the given scope (p->nFaninLevels,
+ p->nFanoutLevels) cannot be constructed, returns 0. Otherwise, returns 1.
+ The levels are measured from the fanin node (pFanin) and the fanout node
+ (pEdgeFanout), respectively.]
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Abc_NtkRRWindow( Abc_RRMan_t * p )
+{
+ Abc_Obj_t * pObj, * pEdgeFanin, * pEdgeFanout;
+ int i, LevelMin, LevelMax, RetValue;
+
+ // get the edge
+ pEdgeFanout = p->pFanout? p->pFanout : p->pNode;
+ pEdgeFanin = p->pFanout? p->pNode : p->pFanin;
+ // get the minimum and maximum levels of the window
+ LevelMin = ABC_MAX( 0, ((int)p->pFanin->Level) - p->nFaninLevels );
+ LevelMax = (int)pEdgeFanout->Level + p->nFanoutLevels;
+
+ // start the TFI leaves with the fanin
+ Abc_NtkIncrementTravId( p->pNtk );
+ Abc_NodeSetTravIdCurrent( p->pFanin );
+ Vec_PtrPush( p->vFaninLeaves, p->pFanin );
+ // mark the TFI cone and collect the leaves down to the given level
+ while ( Abc_NtkRRTfi_int(p->vFaninLeaves, LevelMin) );
+
+ // mark the leaves with the new TravId
+ Abc_NtkIncrementTravId( p->pNtk );
+ Vec_PtrForEachEntry( p->vFaninLeaves, pObj, i )
+ Abc_NodeSetTravIdCurrent( pObj );
+ // traverse the TFO cone of the leaves (while skipping the edge)
+ // (a) mark the nodes in the cone using the current TravId
+ // (b) collect the nodes that have external fanouts into p->vFanoutRoots
+ while ( Abc_NtkRRTfo_int(p->vFaninLeaves, p->vFanoutRoots, LevelMax, pEdgeFanin, pEdgeFanout) );
+
+ // mark the fanout roots
+ Vec_PtrForEachEntry( p->vFanoutRoots, pObj, i )
+ pObj->fMarkA = 1;
+ // collect roots reachable from the fanout (p->vRoots)
+ RetValue = Abc_NtkRRTfo_rec( pEdgeFanout, p->vRoots, LevelMax + 1 );
+ // unmark the fanout roots
+ Vec_PtrForEachEntry( p->vFanoutRoots, pObj, i )
+ pObj->fMarkA = 0;
+
+ // return if the window is infeasible
+ if ( RetValue == 0 )
+ return 0;
+
+ // collect the DFS-ordered new cone (p->vCone) and new leaves (p->vLeaves)
+ // using the previous marks coming from the TFO cone
+ Abc_NtkIncrementTravId( p->pNtk );
+ Vec_PtrForEachEntry( p->vRoots, pObj, i )
+ Abc_NtkRRTfi_rec( pObj, p->vLeaves, p->vCone, LevelMin );
+
+ // create a new network
+ p->pWnd = Abc_NtkWindow( p->pNtk, p->vLeaves, p->vCone, p->vRoots );
+ return 1;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Marks the nodes in the TFI and collects their leaves.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Abc_NtkRRTfi_int( Vec_Ptr_t * vLeaves, int LevelLimit )
+{
+ Abc_Obj_t * pObj, * pNext;
+ int i, k, LevelMax, nSize;
+ assert( LevelLimit >= 0 );
+ // find the maximum level of leaves
+ LevelMax = 0;
+ Vec_PtrForEachEntry( vLeaves, pObj, i )
+ if ( LevelMax < (int)pObj->Level )
+ LevelMax = pObj->Level;
+ // if the nodes are all PIs, LevelMax == 0
+ if ( LevelMax <= LevelLimit )
+ return 0;
+ // expand the nodes with the minimum level
+ nSize = Vec_PtrSize(vLeaves);
+ Vec_PtrForEachEntryStop( vLeaves, pObj, i, nSize )
+ {
+ if ( LevelMax != (int)pObj->Level )
+ continue;
+ Abc_ObjForEachFanin( pObj, pNext, k )
+ {
+ if ( Abc_NodeIsTravIdCurrent(pNext) )
+ continue;
+ Abc_NodeSetTravIdCurrent( pNext );
+ Vec_PtrPush( vLeaves, pNext );
+ }
+ }
+ // remove old nodes (cannot remove a PI)
+ k = 0;
+ Vec_PtrForEachEntry( vLeaves, pObj, i )
+ {
+ if ( LevelMax == (int)pObj->Level )
+ continue;
+ Vec_PtrWriteEntry( vLeaves, k++, pObj );
+ }
+ Vec_PtrShrink( vLeaves, k );
+ if ( Vec_PtrSize(vLeaves) > 2000 )
+ return 0;
+ return 1;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Marks the nodes in the TFO and collects their roots.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Abc_NtkRRTfo_int( Vec_Ptr_t * vLeaves, Vec_Ptr_t * vRoots, int LevelLimit, Abc_Obj_t * pEdgeFanin, Abc_Obj_t * pEdgeFanout )
+{
+ Abc_Obj_t * pObj, * pNext;
+ int i, k, LevelMin, nSize, fObjIsRoot;
+ // find the minimum level of leaves
+ LevelMin = ABC_INFINITY;
+ Vec_PtrForEachEntry( vLeaves, pObj, i )
+ if ( LevelMin > (int)pObj->Level )
+ LevelMin = pObj->Level;
+ // if the minimum level exceed the limit, we are done
+ if ( LevelMin > LevelLimit )
+ return 0;
+ // expand the nodes with the minimum level
+ nSize = Vec_PtrSize(vLeaves);
+ Vec_PtrForEachEntryStop( vLeaves, pObj, i, nSize )
+ {
+ if ( LevelMin != (int)pObj->Level )
+ continue;
+ fObjIsRoot = 0;
+ Abc_ObjForEachFanout( pObj, pNext, k )
+ {
+ // check if the fanout is outside of the cone
+ if ( Abc_ObjIsCo(pNext) || pNext->Level > (unsigned)LevelLimit )
+ {
+ fObjIsRoot = 1;
+ continue;
+ }
+ // skip the edge under check
+ if ( pObj == pEdgeFanin && pNext == pEdgeFanout )
+ continue;
+ // skip the visited fanouts
+ if ( Abc_NodeIsTravIdCurrent(pNext) )
+ continue;
+ Abc_NodeSetTravIdCurrent( pNext );
+ Vec_PtrPush( vLeaves, pNext );
+ }
+ if ( fObjIsRoot )
+ Vec_PtrPush( vRoots, pObj );
+ }
+ // remove old nodes
+ k = 0;
+ Vec_PtrForEachEntry( vLeaves, pObj, i )
+ {
+ if ( LevelMin == (int)pObj->Level )
+ continue;
+ Vec_PtrWriteEntry( vLeaves, k++, pObj );
+ }
+ Vec_PtrShrink( vLeaves, k );
+ if ( Vec_PtrSize(vLeaves) > 2000 )
+ return 0;
+ return 1;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Collects the roots in the TFO of the node.]
+
+ Description [Note that this procedure can be improved by
+ marking and skipping the visited nodes.]
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Abc_NtkRRTfo_rec( Abc_Obj_t * pNode, Vec_Ptr_t * vRoots, int LevelLimit )
+{
+ Abc_Obj_t * pFanout;
+ int i;
+ // if we encountered a node outside of the TFO cone of the fanins, quit
+ if ( Abc_ObjIsCo(pNode) || pNode->Level > (unsigned)LevelLimit )
+ return 0;
+ // if we encountered a node on the boundary, add it to the roots
+ if ( pNode->fMarkA )
+ {
+ Vec_PtrPushUnique( vRoots, pNode );
+ return 1;
+ }
+ // mark the node with the current TravId (needed to have all internal nodes marked)
+ Abc_NodeSetTravIdCurrent( pNode );
+ // traverse the fanouts
+ Abc_ObjForEachFanout( pNode, pFanout, i )
+ if ( !Abc_NtkRRTfo_rec( pFanout, vRoots, LevelLimit ) )
+ return 0;
+ return 1;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Collects the leaves and cone of the roots.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Abc_NtkRRTfi_rec( Abc_Obj_t * pNode, Vec_Ptr_t * vLeaves, Vec_Ptr_t * vCone, int LevelLimit )
+{
+ Abc_Obj_t * pFanin;
+ int i;
+ // skip visited nodes
+ if ( Abc_NodeIsTravIdCurrent(pNode) )
+ return;
+ // add node to leaves if it is not in TFI cone of the leaves (marked before) or below the limit
+ if ( !Abc_NodeIsTravIdPrevious(pNode) || (int)pNode->Level <= LevelLimit )
+ {
+ Abc_NodeSetTravIdCurrent( pNode );
+ Vec_PtrPush( vLeaves, pNode );
+ return;
+ }
+ // mark the node as visited
+ Abc_NodeSetTravIdCurrent( pNode );
+ // call for the node's fanins
+ Abc_ObjForEachFanin( pNode, pFanin, i )
+ Abc_NtkRRTfi_rec( pFanin, vLeaves, vCone, LevelLimit );
+ // add the node to the cone in topological order
+ Vec_PtrPush( vCone, pNode );
+}
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Abc_Ntk_t * Abc_NtkWindow( Abc_Ntk_t * pNtk, Vec_Ptr_t * vLeaves, Vec_Ptr_t * vCone, Vec_Ptr_t * vRoots )
+{
+ Abc_Ntk_t * pNtkNew;
+ Abc_Obj_t * pObj;
+ int fCheck = 1;
+ int i;
+ assert( Abc_NtkIsStrash(pNtk) );
+ // start the network
+ pNtkNew = Abc_NtkAlloc( pNtk->ntkType, pNtk->ntkFunc, 1 );
+ // duplicate the name and the spec
+ pNtkNew->pName = Extra_UtilStrsav( "temp" );
+ // map the constant nodes
+ Abc_AigConst1(pNtk)->pCopy = Abc_AigConst1(pNtkNew);
+ // create and map the PIs
+ Vec_PtrForEachEntry( vLeaves, pObj, i )
+ pObj->pCopy = Abc_NtkCreatePi(pNtkNew);
+ // copy the AND gates
+ Vec_PtrForEachEntry( vCone, pObj, i )
+ pObj->pCopy = Abc_AigAnd( pNtkNew->pManFunc, Abc_ObjChild0Copy(pObj), Abc_ObjChild1Copy(pObj) );
+ // compare the number of nodes before and after
+ if ( Vec_PtrSize(vCone) != Abc_NtkNodeNum(pNtkNew) )
+ printf( "Warning: Structural hashing during windowing reduced %d nodes (this is a bug).\n",
+ Vec_PtrSize(vCone) - Abc_NtkNodeNum(pNtkNew) );
+ // create the POs
+ Vec_PtrForEachEntry( vRoots, pObj, i )
+ {
+ assert( !Abc_ObjIsComplement(pObj->pCopy) );
+ Abc_ObjAddFanin( Abc_NtkCreatePo(pNtkNew), pObj->pCopy );
+ }
+ // add the PI/PO names
+ Abc_NtkAddDummyPiNames( pNtkNew );
+ Abc_NtkAddDummyPoNames( pNtkNew );
+ Abc_NtkAddDummyAssertNames( pNtkNew );
+ // check
+ if ( fCheck && !Abc_NtkCheck( pNtkNew ) )
+ {
+ printf( "Abc_NtkWindow: The network check has failed.\n" );
+ return NULL;
+ }
+ return pNtkNew;
+}
+
+
+/**Function*************************************************************
+
+ Synopsis [Starts simulation to detect non-redundant edges.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Abc_NtkRRSimulateStart( Abc_Ntk_t * pNtk )
+{
+ Abc_Obj_t * pObj;
+ unsigned uData, uData0, uData1;
+ int i;
+ Abc_AigConst1(pNtk)->pData = (void *)~((unsigned)0);
+ Abc_NtkForEachCi( pNtk, pObj, i )
+ pObj->pData = (void *)SIM_RANDOM_UNSIGNED;
+ Abc_NtkForEachNode( pNtk, pObj, i )
+ {
+ if ( i == 0 ) continue;
+ uData0 = (unsigned)Abc_ObjFanin0(pObj)->pData;
+ uData1 = (unsigned)Abc_ObjFanin1(pObj)->pData;
+ uData = Abc_ObjFaninC0(pObj)? ~uData0 : uData0;
+ uData &= Abc_ObjFaninC1(pObj)? ~uData1 : uData1;
+ assert( pObj->pData == NULL );
+ pObj->pData = (void *)uData;
+ }
+}
+
+/**Function*************************************************************
+
+ Synopsis [Stops simulation to detect non-redundant edges.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Abc_NtkRRSimulateStop( Abc_Ntk_t * pNtk )
+{
+ Abc_Obj_t * pObj;
+ int i;
+ Abc_NtkForEachObj( pNtk, pObj, i )
+ pObj->pData = NULL;
+}
+
+
+
+
+
+
+
+static void Sim_TraverseNodes_rec( Abc_Obj_t * pRoot, Vec_Str_t * vTargets, Vec_Ptr_t * vNodes );
+static void Sim_CollectNodes_rec( Abc_Obj_t * pRoot, Vec_Ptr_t * vField );
+static void Sim_SimulateCollected( Vec_Str_t * vTargets, Vec_Ptr_t * vNodes, Vec_Ptr_t * vField );
+
+/**Function*************************************************************
+
+ Synopsis [Simulation to detect non-redundant edges.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Vec_Str_t * Abc_NtkRRSimulate( Abc_Ntk_t * pNtk )
+{
+ Vec_Ptr_t * vNodes, * vField;
+ Vec_Str_t * vTargets;
+ Abc_Obj_t * pObj;
+ unsigned uData, uData0, uData1;
+ int PrevCi, Phase, i, k;
+
+ // start the candidates
+ vTargets = Vec_StrStart( Abc_NtkObjNumMax(pNtk) + 1 );
+ Abc_NtkForEachNode( pNtk, pObj, i )
+ {
+ Phase = ((Abc_ObjFanoutNum(Abc_ObjFanin1(pObj)) > 1) << 1);
+ Phase |= (Abc_ObjFanoutNum(Abc_ObjFanin0(pObj)) > 1);
+ Vec_StrWriteEntry( vTargets, pObj->Id, (char)Phase );
+ }
+
+ // simulate patters and store them in copy
+ Abc_AigConst1(pNtk)->pCopy = (Abc_Obj_t *)~((unsigned)0);
+ Abc_NtkForEachCi( pNtk, pObj, i )
+ pObj->pCopy = (Abc_Obj_t *)SIM_RANDOM_UNSIGNED;
+ Abc_NtkForEachNode( pNtk, pObj, i )
+ {
+ if ( i == 0 ) continue;
+ uData0 = (unsigned)Abc_ObjFanin0(pObj)->pData;
+ uData1 = (unsigned)Abc_ObjFanin1(pObj)->pData;
+ uData = Abc_ObjFaninC0(pObj)? ~uData0 : uData0;
+ uData &= Abc_ObjFaninC1(pObj)? ~uData1 : uData1;
+ pObj->pCopy = (Abc_Obj_t *)uData;
+ }
+ // store the result in data
+ Abc_NtkForEachCo( pNtk, pObj, i )
+ {
+ uData0 = (unsigned)Abc_ObjFanin0(pObj)->pData;
+ if ( Abc_ObjFaninC0(pObj) )
+ pObj->pData = (void *)~uData0;
+ else
+ pObj->pData = (void *)uData0;
+ }
+
+ // refine the candidates
+ for ( PrevCi = 0; PrevCi < Abc_NtkCiNum(pNtk); PrevCi = i )
+ {
+ vNodes = Vec_PtrAlloc( 10 );
+ Abc_NtkIncrementTravId( pNtk );
+ for ( i = PrevCi; i < Abc_NtkCiNum(pNtk); i++ )
+ {
+ Sim_TraverseNodes_rec( Abc_NtkCi(pNtk, i), vTargets, vNodes );
+ if ( Vec_PtrSize(vNodes) > 128 )
+ break;
+ }
+ // collect the marked nodes in the topological order
+ vField = Vec_PtrAlloc( 10 );
+ Abc_NtkIncrementTravId( pNtk );
+ Abc_NtkForEachCo( pNtk, pObj, k )
+ Sim_CollectNodes_rec( pObj, vField );
+
+ // simulate these nodes
+ Sim_SimulateCollected( vTargets, vNodes, vField );
+ // prepare for the next loop
+ Vec_PtrFree( vNodes );
+ }
+
+ // clean
+ Abc_NtkForEachObj( pNtk, pObj, i )
+ pObj->pData = NULL;
+ return vTargets;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Collects nodes starting from the given node.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Sim_TraverseNodes_rec( Abc_Obj_t * pRoot, Vec_Str_t * vTargets, Vec_Ptr_t * vNodes )
+{
+ Abc_Obj_t * pFanout;
+ char Entry;
+ int k;
+ if ( Abc_NodeIsTravIdCurrent(pRoot) )
+ return;
+ Abc_NodeSetTravIdCurrent( pRoot );
+ // save the reached targets
+ Entry = Vec_StrEntry(vTargets, pRoot->Id);
+ if ( Entry & 1 )
+ Vec_PtrPush( vNodes, Abc_ObjNot(pRoot) );
+ if ( Entry & 2 )
+ Vec_PtrPush( vNodes, pRoot );
+ // explore the fanouts
+ Abc_ObjForEachFanout( pRoot, pFanout, k )
+ Sim_TraverseNodes_rec( pFanout, vTargets, vNodes );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Collects nodes starting from the given node.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Sim_CollectNodes_rec( Abc_Obj_t * pRoot, Vec_Ptr_t * vField )
+{
+ Abc_Obj_t * pFanin;
+ int i;
+ if ( Abc_NodeIsTravIdCurrent(pRoot) )
+ return;
+ if ( !Abc_NodeIsTravIdPrevious(pRoot) )
+ return;
+ Abc_NodeSetTravIdCurrent( pRoot );
+ Abc_ObjForEachFanin( pRoot, pFanin, i )
+ Sim_CollectNodes_rec( pFanin, vField );
+ if ( !Abc_ObjIsCo(pRoot) )
+ pRoot->pData = (void *)Vec_PtrSize(vField);
+ Vec_PtrPush( vField, pRoot );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Simulate the given nodes.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Sim_SimulateCollected( Vec_Str_t * vTargets, Vec_Ptr_t * vNodes, Vec_Ptr_t * vField )
+{
+ Abc_Obj_t * pObj, * pFanin0, * pFanin1, * pDisproved;
+ Vec_Ptr_t * vSims;
+ unsigned * pUnsigned, * pUnsignedF;
+ int i, k, Phase, fCompl;
+ // get simulation info
+ vSims = Sim_UtilInfoAlloc( Vec_PtrSize(vField), Vec_PtrSize(vNodes), 0 );
+ // simulate the nodes
+ Vec_PtrForEachEntry( vField, pObj, i )
+ {
+ if ( Abc_ObjIsCi(pObj) )
+ {
+ pUnsigned = Vec_PtrEntry( vSims, i );
+ for ( k = 0; k < Vec_PtrSize(vNodes); k++ )
+ pUnsigned[k] = (unsigned)pObj->pCopy;
+ continue;
+ }
+ if ( Abc_ObjIsCo(pObj) )
+ {
+ pUnsigned = Vec_PtrEntry( vSims, i );
+ pUnsignedF = Vec_PtrEntry( vSims, (int)Abc_ObjFanin0(pObj)->pData );
+ if ( Abc_ObjFaninC0(pObj) )
+ for ( k = 0; k < Vec_PtrSize(vNodes); k++ )
+ pUnsigned[k] = ~pUnsignedF[k];
+ else
+ for ( k = 0; k < Vec_PtrSize(vNodes); k++ )
+ pUnsigned[k] = pUnsignedF[k];
+ // update targets
+ for ( k = 0; k < Vec_PtrSize(vNodes); k++ )
+ {
+ if ( pUnsigned[k] == (unsigned)pObj->pData )
+ continue;
+ pDisproved = Vec_PtrEntry( vNodes, k );
+ fCompl = Abc_ObjIsComplement(pDisproved);
+ pDisproved = Abc_ObjRegular(pDisproved);
+ Phase = Vec_StrEntry( vTargets, pDisproved->Id );
+ if ( fCompl )
+ Phase = (Phase & 2);
+ else
+ Phase = (Phase & 1);
+ Vec_StrWriteEntry( vTargets, pDisproved->Id, (char)Phase );
+ }
+ continue;
+ }
+ // simulate the node
+ pFanin0 = Abc_ObjFanin0(pObj);
+ pFanin1 = Abc_ObjFanin1(pObj);
+ }
+}
+
+
+
+/*
+ {
+ unsigned uData;
+ if ( pFanin == Abc_ObjFanin0(pNode) )
+ {
+ uData = (unsigned)Abc_ObjFanin1(pNode)->pData;
+ uData = Abc_ObjFaninC1(pNode)? ~uData : uData;
+ }
+ else if ( pFanin == Abc_ObjFanin1(pNode) )
+ {
+ uData = (unsigned)Abc_ObjFanin0(pNode)->pData;
+ uData = Abc_ObjFaninC0(pNode)? ~uData : uData;
+ }
+ uData ^= (unsigned)pNode->pData;
+// Extra_PrintBinary( stdout, &uData, 32 ); printf( "\n" );
+ if ( Extra_WordCountOnes(uData) > 8 )
+ continue;
+ }
+*/
+
+////////////////////////////////////////////////////////////////////////
+/// END OF FILE ///
+////////////////////////////////////////////////////////////////////////
+
+
diff --git a/src/base/abci/abcSat.c b/src/base/abci/abcSat.c
index 4fb059e5..58614584 100644
--- a/src/base/abci/abcSat.c
+++ b/src/base/abci/abcSat.c
@@ -6,7 +6,7 @@
PackageName [Network and node package.]
- Synopsis [Procedures to solve the miter using the internal SAT solver.]
+ Synopsis [Procedures to solve the miter using the internal SAT sat_solver.]
Author [Alan Mishchenko]
@@ -19,79 +19,123 @@
***********************************************************************/
#include "abc.h"
+#include "satSolver.h"
////////////////////////////////////////////////////////////////////////
/// DECLARATIONS ///
////////////////////////////////////////////////////////////////////////
-static void Abc_NodeAddClauses( solver * pSat, char * pSop0, char * pSop1, Abc_Obj_t * pNode, Vec_Int_t * vVars );
-static void Abc_NodeAddClausesTop( solver * pSat, Abc_Obj_t * pNode, Vec_Int_t * vVars );
+static sat_solver * Abc_NtkMiterSatCreateLogic( Abc_Ntk_t * pNtk, int fAllPrimes );
+extern Vec_Int_t * Abc_NtkGetCiSatVarNums( Abc_Ntk_t * pNtk );
+static nMuxes;
////////////////////////////////////////////////////////////////////////
-/// FUNCTION DEFITIONS ///
+/// FUNCTION DEFINITIONS ///
////////////////////////////////////////////////////////////////////////
/**Function*************************************************************
- Synopsis [Attempts to solve the miter using an internal SAT solver.]
+ Synopsis [Attempts to solve the miter using an internal SAT sat_solver.]
- Description [Returns 1 if the miter is SAT.]
+ Description [Returns -1 if timed out; 0 if SAT; 1 if UNSAT.]
SideEffects []
SeeAlso []
***********************************************************************/
-bool Abc_NtkMiterSat( Abc_Ntk_t * pNtk, int fVerbose )
+int Abc_NtkMiterSat( Abc_Ntk_t * pNtk, sint64 nConfLimit, sint64 nInsLimit, int fVerbose, sint64 * pNumConfs, sint64 * pNumInspects )
{
- solver * pSat;
+ sat_solver * pSat;
lbool status;
- int clk;
+ int RetValue, clk;
+
+ if ( pNumConfs )
+ *pNumConfs = 0;
+ if ( pNumInspects )
+ *pNumInspects = 0;
- assert( Abc_NtkIsBddLogic(pNtk) );
assert( Abc_NtkLatchNum(pNtk) == 0 );
- if ( Abc_NtkPoNum(pNtk) > 1 )
- fprintf( stdout, "Warning: The miter has more than 1 output. SAT will try to prove all of them.\n" );
+// if ( Abc_NtkPoNum(pNtk) > 1 )
+// fprintf( stdout, "Warning: The miter has %d outputs. SAT will try to prove all of them.\n", Abc_NtkPoNum(pNtk) );
- // load clauses into the solver
+ // load clauses into the sat_solver
clk = clock();
- pSat = Abc_NtkMiterSatCreate( pNtk );
-// printf( "Created SAT problem with %d variable and %d clauses. ",
-// solver_nvars(pSat), solver_nclauses(pSat) );
+ pSat = Abc_NtkMiterSatCreate( pNtk, 0 );
+ if ( pSat == NULL )
+ return 1;
+//printf( "%d \n", pSat->clauses.size );
+//sat_solver_delete( pSat );
+//return 1;
+
+// printf( "Created SAT problem with %d variable and %d clauses. ", sat_solver_nvars(pSat), sat_solver_nclauses(pSat) );
// PRT( "Time", clock() - clk );
// simplify the problem
clk = clock();
- status = solver_simplify(pSat);
-// printf( "Simplified the problem to %d variables and %d clauses. ",
-// solver_nvars(pSat), solver_nclauses(pSat) );
+ status = sat_solver_simplify(pSat);
+// printf( "Simplified the problem to %d variables and %d clauses. ", sat_solver_nvars(pSat), sat_solver_nclauses(pSat) );
// PRT( "Time", clock() - clk );
- if ( status == l_False )
+ if ( status == 0 )
{
- solver_delete( pSat );
- printf( "The problem is UNSAT after simplification.\n" );
- return 0;
+ sat_solver_delete( pSat );
+// printf( "The problem is UNSATISFIABLE after simplification.\n" );
+ return 1;
}
// solve the miter
clk = clock();
if ( fVerbose )
pSat->verbosity = 1;
- status = solver_solve( pSat, NULL, NULL );
-// if ( fVerbose )
-// {
- printf( "The problem is %5s. ", (status == l_True)? "SAT" : "UNSAT" );
- PRT( "SAT solver time", clock() - clk );
-// }
- // free the solver
- solver_delete( pSat );
- return status == l_True;
+ status = sat_solver_solve( pSat, NULL, NULL, (sint64)nConfLimit, (sint64)nInsLimit, (sint64)0, (sint64)0 );
+ if ( status == l_Undef )
+ {
+// printf( "The problem timed out.\n" );
+ RetValue = -1;
+ }
+ else if ( status == l_True )
+ {
+// printf( "The problem is SATISFIABLE.\n" );
+ RetValue = 0;
+ }
+ else if ( status == l_False )
+ {
+// printf( "The problem is UNSATISFIABLE.\n" );
+ RetValue = 1;
+ }
+ else
+ assert( 0 );
+// PRT( "SAT sat_solver time", clock() - clk );
+// printf( "The number of conflicts = %d.\n", (int)pSat->sat_solver_stats.conflicts );
+
+ // if the problem is SAT, get the counterexample
+ if ( status == l_True )
+ {
+// Vec_Int_t * vCiIds = Abc_NtkGetCiIds( pNtk );
+ Vec_Int_t * vCiIds = Abc_NtkGetCiSatVarNums( pNtk );
+ pNtk->pModel = Sat_SolverGetModel( pSat, vCiIds->pArray, vCiIds->nSize );
+ Vec_IntFree( vCiIds );
+ }
+ // free the sat_solver
+ if ( fVerbose )
+ Sat_SolverPrintStats( stdout, pSat );
+
+ if ( pNumConfs )
+ *pNumConfs = (int)pSat->stats.conflicts;
+ if ( pNumInspects )
+ *pNumInspects = (int)pSat->stats.inspects;
+
+sat_solver_store_write( pSat, "trace.cnf" );
+sat_solver_store_free( pSat );
+
+ sat_solver_delete( pSat );
+ return RetValue;
}
/**Function*************************************************************
- Synopsis [Sets up the SAT solver.]
+ Synopsis [Returns the array of CI IDs.]
Description []
@@ -100,43 +144,505 @@ bool Abc_NtkMiterSat( Abc_Ntk_t * pNtk, int fVerbose )
SeeAlso []
***********************************************************************/
-solver * Abc_NtkMiterSatCreate( Abc_Ntk_t * pNtk )
+Vec_Int_t * Abc_NtkGetCiSatVarNums( Abc_Ntk_t * pNtk )
+{
+ Vec_Int_t * vCiIds;
+ Abc_Obj_t * pObj;
+ int i;
+ vCiIds = Vec_IntAlloc( Abc_NtkCiNum(pNtk) );
+ Abc_NtkForEachCi( pNtk, pObj, i )
+ Vec_IntPush( vCiIds, (int)pObj->pCopy );
+ return vCiIds;
+}
+
+
+
+/**Function*************************************************************
+
+ Synopsis [Adds trivial clause.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Abc_NtkClauseTriv( sat_solver * pSat, Abc_Obj_t * pNode, Vec_Int_t * vVars )
+{
+//printf( "Adding triv %d. %d\n", Abc_ObjRegular(pNode)->Id, (int)pSat->sat_solver_stats.clauses );
+ vVars->nSize = 0;
+ Vec_IntPush( vVars, toLitCond( (int)Abc_ObjRegular(pNode)->pCopy, Abc_ObjIsComplement(pNode) ) );
+// Vec_IntPush( vVars, toLitCond( (int)Abc_ObjRegular(pNode)->Id, Abc_ObjIsComplement(pNode) ) );
+ return sat_solver_addclause( pSat, vVars->pArray, vVars->pArray + vVars->nSize );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Adds trivial clause.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Abc_NtkClauseTop( sat_solver * pSat, Vec_Ptr_t * vNodes, Vec_Int_t * vVars )
{
- solver * pSat;
- Extra_MmFlex_t * pMmFlex;
Abc_Obj_t * pNode;
- Vec_Str_t * vCube;
- Vec_Int_t * vVars;
- char * pSop0, * pSop1;
int i;
+//printf( "Adding triv %d. %d\n", Abc_ObjRegular(pNode)->Id, (int)pSat->sat_solver_stats.clauses );
+ vVars->nSize = 0;
+ Vec_PtrForEachEntry( vNodes, pNode, i )
+ Vec_IntPush( vVars, toLitCond( (int)Abc_ObjRegular(pNode)->pCopy, Abc_ObjIsComplement(pNode) ) );
+// Vec_IntPush( vVars, toLitCond( (int)Abc_ObjRegular(pNode)->Id, Abc_ObjIsComplement(pNode) ) );
+ return sat_solver_addclause( pSat, vVars->pArray, vVars->pArray + vVars->nSize );
+}
+
+/**Function*************************************************************
- assert( Abc_NtkIsBddLogic(pNtk) );
+ Synopsis [Adds trivial clause.]
- // start the data structures
- pSat = solver_new();
- pMmFlex = Extra_MmFlexStart();
- vCube = Vec_StrAlloc( 100 );
- vVars = Vec_IntAlloc( 100 );
+ Description []
+
+ SideEffects []
- // add clauses for each internal nodes
- Abc_NtkForEachNode( pNtk, pNode, i )
+ SeeAlso []
+
+***********************************************************************/
+int Abc_NtkClauseAnd( sat_solver * pSat, Abc_Obj_t * pNode, Vec_Ptr_t * vSuper, Vec_Int_t * vVars )
+{
+ int fComp1, Var, Var1, i;
+//printf( "Adding AND %d. (%d) %d\n", pNode->Id, vSuper->nSize+1, (int)pSat->sat_solver_stats.clauses );
+
+ assert( !Abc_ObjIsComplement( pNode ) );
+ assert( Abc_ObjIsNode( pNode ) );
+
+// nVars = sat_solver_nvars(pSat);
+ Var = (int)pNode->pCopy;
+// Var = pNode->Id;
+
+// assert( Var < nVars );
+ for ( i = 0; i < vSuper->nSize; i++ )
{
- // derive SOPs for both phases of the node
- Abc_NodeBddToCnf( pNode, pMmFlex, vCube, &pSop0, &pSop1 );
- // add the clauses to the solver
- Abc_NodeAddClauses( pSat, pSop0, pSop1, pNode, vVars );
+ // get the predecessor nodes
+ // get the complemented attributes of the nodes
+ fComp1 = Abc_ObjIsComplement(vSuper->pArray[i]);
+ // determine the variable numbers
+ Var1 = (int)Abc_ObjRegular(vSuper->pArray[i])->pCopy;
+// Var1 = (int)Abc_ObjRegular(vSuper->pArray[i])->Id;
+
+ // check that the variables are in the SAT manager
+// assert( Var1 < nVars );
+
+ // suppose the AND-gate is A * B = C
+ // add !A => !C or A + !C
+ // fprintf( pFile, "%d %d 0%c", Var1, -Var, 10 );
+ vVars->nSize = 0;
+ Vec_IntPush( vVars, toLitCond(Var1, fComp1) );
+ Vec_IntPush( vVars, toLitCond(Var, 1 ) );
+ if ( !sat_solver_addclause( pSat, vVars->pArray, vVars->pArray + vVars->nSize ) )
+ return 0;
}
- // add clauses for each PO
- Abc_NtkForEachPo( pNtk, pNode, i )
- Abc_NodeAddClausesTop( pSat, pNode, vVars );
+ // add A & B => C or !A + !B + C
+// fprintf( pFile, "%d %d %d 0%c", -Var1, -Var2, Var, 10 );
+ vVars->nSize = 0;
+ for ( i = 0; i < vSuper->nSize; i++ )
+ {
+ // get the predecessor nodes
+ // get the complemented attributes of the nodes
+ fComp1 = Abc_ObjIsComplement(vSuper->pArray[i]);
+ // determine the variable numbers
+ Var1 = (int)Abc_ObjRegular(vSuper->pArray[i])->pCopy;
+// Var1 = (int)Abc_ObjRegular(vSuper->pArray[i])->Id;
+ // add this variable to the array
+ Vec_IntPush( vVars, toLitCond(Var1, !fComp1) );
+ }
+ Vec_IntPush( vVars, toLitCond(Var, 0) );
+ return sat_solver_addclause( pSat, vVars->pArray, vVars->pArray + vVars->nSize );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Adds trivial clause.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Abc_NtkClauseMux( sat_solver * pSat, Abc_Obj_t * pNode, Abc_Obj_t * pNodeC, Abc_Obj_t * pNodeT, Abc_Obj_t * pNodeE, Vec_Int_t * vVars )
+{
+ int VarF, VarI, VarT, VarE, fCompT, fCompE;
+//printf( "Adding mux %d. %d\n", pNode->Id, (int)pSat->sat_solver_stats.clauses );
+
+ assert( !Abc_ObjIsComplement( pNode ) );
+ assert( Abc_NodeIsMuxType( pNode ) );
+ // get the variable numbers
+ VarF = (int)pNode->pCopy;
+ VarI = (int)pNodeC->pCopy;
+ VarT = (int)Abc_ObjRegular(pNodeT)->pCopy;
+ VarE = (int)Abc_ObjRegular(pNodeE)->pCopy;
+// VarF = (int)pNode->Id;
+// VarI = (int)pNodeC->Id;
+// VarT = (int)Abc_ObjRegular(pNodeT)->Id;
+// VarE = (int)Abc_ObjRegular(pNodeE)->Id;
+
+ // get the complementation flags
+ fCompT = Abc_ObjIsComplement(pNodeT);
+ fCompE = Abc_ObjIsComplement(pNodeE);
+
+ // f = ITE(i, t, e)
+ // i' + t' + f
+ // i' + t + f'
+ // i + e' + f
+ // i + e + f'
+ // create four clauses
+ vVars->nSize = 0;
+ Vec_IntPush( vVars, toLitCond(VarI, 1) );
+ Vec_IntPush( vVars, toLitCond(VarT, 1^fCompT) );
+ Vec_IntPush( vVars, toLitCond(VarF, 0) );
+ if ( !sat_solver_addclause( pSat, vVars->pArray, vVars->pArray + vVars->nSize ) )
+ return 0;
+ vVars->nSize = 0;
+ Vec_IntPush( vVars, toLitCond(VarI, 1) );
+ Vec_IntPush( vVars, toLitCond(VarT, 0^fCompT) );
+ Vec_IntPush( vVars, toLitCond(VarF, 1) );
+ if ( !sat_solver_addclause( pSat, vVars->pArray, vVars->pArray + vVars->nSize ) )
+ return 0;
+ vVars->nSize = 0;
+ Vec_IntPush( vVars, toLitCond(VarI, 0) );
+ Vec_IntPush( vVars, toLitCond(VarE, 1^fCompE) );
+ Vec_IntPush( vVars, toLitCond(VarF, 0) );
+ if ( !sat_solver_addclause( pSat, vVars->pArray, vVars->pArray + vVars->nSize ) )
+ return 0;
+ vVars->nSize = 0;
+ Vec_IntPush( vVars, toLitCond(VarI, 0) );
+ Vec_IntPush( vVars, toLitCond(VarE, 0^fCompE) );
+ Vec_IntPush( vVars, toLitCond(VarF, 1) );
+ if ( !sat_solver_addclause( pSat, vVars->pArray, vVars->pArray + vVars->nSize ) )
+ return 0;
+
+ if ( VarT == VarE )
+ {
+// assert( fCompT == !fCompE );
+ return 1;
+ }
+
+ // two additional clauses
+ // t' & e' -> f' t + e + f'
+ // t & e -> f t' + e' + f
+ vVars->nSize = 0;
+ Vec_IntPush( vVars, toLitCond(VarT, 0^fCompT) );
+ Vec_IntPush( vVars, toLitCond(VarE, 0^fCompE) );
+ Vec_IntPush( vVars, toLitCond(VarF, 1) );
+ if ( !sat_solver_addclause( pSat, vVars->pArray, vVars->pArray + vVars->nSize ) )
+ return 0;
+ vVars->nSize = 0;
+ Vec_IntPush( vVars, toLitCond(VarT, 1^fCompT) );
+ Vec_IntPush( vVars, toLitCond(VarE, 1^fCompE) );
+ Vec_IntPush( vVars, toLitCond(VarF, 0) );
+ return sat_solver_addclause( pSat, vVars->pArray, vVars->pArray + vVars->nSize );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Returns the array of nodes to be combined into one multi-input AND-gate.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Abc_NtkCollectSupergate_rec( Abc_Obj_t * pNode, Vec_Ptr_t * vSuper, int fFirst, int fStopAtMux )
+{
+ int RetValue1, RetValue2, i;
+ // check if the node is visited
+ if ( Abc_ObjRegular(pNode)->fMarkB )
+ {
+ // check if the node occurs in the same polarity
+ for ( i = 0; i < vSuper->nSize; i++ )
+ if ( vSuper->pArray[i] == pNode )
+ return 1;
+ // check if the node is present in the opposite polarity
+ for ( i = 0; i < vSuper->nSize; i++ )
+ if ( vSuper->pArray[i] == Abc_ObjNot(pNode) )
+ return -1;
+ assert( 0 );
+ return 0;
+ }
+ // if the new node is complemented or a PI, another gate begins
+ if ( !fFirst )
+ if ( Abc_ObjIsComplement(pNode) || !Abc_ObjIsNode(pNode) || Abc_ObjFanoutNum(pNode) > 1 || fStopAtMux && Abc_NodeIsMuxType(pNode) )
+ {
+ Vec_PtrPush( vSuper, pNode );
+ Abc_ObjRegular(pNode)->fMarkB = 1;
+ return 0;
+ }
+ assert( !Abc_ObjIsComplement(pNode) );
+ assert( Abc_ObjIsNode(pNode) );
+ // go through the branches
+ RetValue1 = Abc_NtkCollectSupergate_rec( Abc_ObjChild0(pNode), vSuper, 0, fStopAtMux );
+ RetValue2 = Abc_NtkCollectSupergate_rec( Abc_ObjChild1(pNode), vSuper, 0, fStopAtMux );
+ if ( RetValue1 == -1 || RetValue2 == -1 )
+ return -1;
+ // return 1 if at least one branch has a duplicate
+ return RetValue1 || RetValue2;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Returns the array of nodes to be combined into one multi-input AND-gate.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Abc_NtkCollectSupergate( Abc_Obj_t * pNode, int fStopAtMux, Vec_Ptr_t * vNodes )
+{
+ int RetValue, i;
+ assert( !Abc_ObjIsComplement(pNode) );
+ // collect the nodes in the implication supergate
+ Vec_PtrClear( vNodes );
+ RetValue = Abc_NtkCollectSupergate_rec( pNode, vNodes, 1, fStopAtMux );
+ assert( vNodes->nSize > 1 );
+ // unmark the visited nodes
+ for ( i = 0; i < vNodes->nSize; i++ )
+ Abc_ObjRegular((Abc_Obj_t *)vNodes->pArray[i])->fMarkB = 0;
+ // if we found the node and its complement in the same implication supergate,
+ // return empty set of nodes (meaning that we should use constant-0 node)
+ if ( RetValue == -1 )
+ vNodes->nSize = 0;
+}
+
+
+/**Function*************************************************************
+
+ Synopsis [Computes the factor of the node.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Abc_NtkNodeFactor( Abc_Obj_t * pObj, int nLevelMax )
+{
+// nLevelMax = ((nLevelMax)/2)*3;
+ assert( (int)pObj->Level <= nLevelMax );
+// return (int)(100000000.0 * pow(0.999, nLevelMax - pObj->Level));
+ return (int)(100000000.0 * (1 + 0.01 * pObj->Level));
+// return (int)(100000000.0 / ((nLevelMax)/2)*3 - pObj->Level);
+}
+
+/**Function*************************************************************
+
+ Synopsis [Sets up the SAT sat_solver.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Abc_NtkMiterSatCreateInt( sat_solver * pSat, Abc_Ntk_t * pNtk )
+{
+ Abc_Obj_t * pNode, * pFanin, * pNodeC, * pNodeT, * pNodeE;
+ Vec_Ptr_t * vNodes, * vSuper;
+ Vec_Int_t * vVars;
+ int i, k, fUseMuxes = 1;
+ int clk1 = clock();
+// int fOrderCiVarsFirst = 0;
+ int nLevelsMax = Abc_AigLevel(pNtk);
+ int RetValue = 0;
+
+ assert( Abc_NtkIsStrash(pNtk) );
+
+ // clean the CI node pointers
+ Abc_NtkForEachCi( pNtk, pNode, i )
+ pNode->pCopy = NULL;
+
+ // start the data structures
+ vNodes = Vec_PtrAlloc( 1000 ); // the nodes corresponding to vars in the sat_solver
+ vSuper = Vec_PtrAlloc( 100 ); // the nodes belonging to the given implication supergate
+ vVars = Vec_IntAlloc( 100 ); // the temporary array for variables in the clause
+
+ // add the clause for the constant node
+ pNode = Abc_AigConst1(pNtk);
+ pNode->fMarkA = 1;
+ pNode->pCopy = (Abc_Obj_t *)vNodes->nSize;
+ Vec_PtrPush( vNodes, pNode );
+ Abc_NtkClauseTriv( pSat, pNode, vVars );
+/*
+ // add the PI variables first
+ Abc_NtkForEachCi( pNtk, pNode, i )
+ {
+ pNode->fMarkA = 1;
+ pNode->pCopy = (Abc_Obj_t *)vNodes->nSize;
+ Vec_PtrPush( vNodes, pNode );
+ }
+*/
+ // collect the nodes that need clauses and top-level assignments
+ Vec_PtrClear( vSuper );
+ Abc_NtkForEachCo( pNtk, pNode, i )
+ {
+ // get the fanin
+ pFanin = Abc_ObjFanin0(pNode);
+ // create the node's variable
+ if ( pFanin->fMarkA == 0 )
+ {
+ pFanin->fMarkA = 1;
+ pFanin->pCopy = (Abc_Obj_t *)vNodes->nSize;
+ Vec_PtrPush( vNodes, pFanin );
+ }
+ // add the trivial clause
+ Vec_PtrPush( vSuper, Abc_ObjChild0(pNode) );
+ }
+ if ( !Abc_NtkClauseTop( pSat, vSuper, vVars ) )
+ goto Quits;
+
+
+ // add the clauses
+ Vec_PtrForEachEntry( vNodes, pNode, i )
+ {
+ assert( !Abc_ObjIsComplement(pNode) );
+ if ( !Abc_AigNodeIsAnd(pNode) )
+ continue;
+//printf( "%d ", pNode->Id );
+
+ // add the clauses
+ if ( fUseMuxes && Abc_NodeIsMuxType(pNode) )
+ {
+ nMuxes++;
+
+ pNodeC = Abc_NodeRecognizeMux( pNode, &pNodeT, &pNodeE );
+ Vec_PtrClear( vSuper );
+ Vec_PtrPush( vSuper, pNodeC );
+ Vec_PtrPush( vSuper, pNodeT );
+ Vec_PtrPush( vSuper, pNodeE );
+ // add the fanin nodes to explore
+ Vec_PtrForEachEntry( vSuper, pFanin, k )
+ {
+ pFanin = Abc_ObjRegular(pFanin);
+ if ( pFanin->fMarkA == 0 )
+ {
+ pFanin->fMarkA = 1;
+ pFanin->pCopy = (Abc_Obj_t *)vNodes->nSize;
+ Vec_PtrPush( vNodes, pFanin );
+ }
+ }
+ // add the clauses
+ if ( !Abc_NtkClauseMux( pSat, pNode, pNodeC, pNodeT, pNodeE, vVars ) )
+ goto Quits;
+ }
+ else
+ {
+ // get the supergate
+ Abc_NtkCollectSupergate( pNode, fUseMuxes, vSuper );
+ // add the fanin nodes to explore
+ Vec_PtrForEachEntry( vSuper, pFanin, k )
+ {
+ pFanin = Abc_ObjRegular(pFanin);
+ if ( pFanin->fMarkA == 0 )
+ {
+ pFanin->fMarkA = 1;
+ pFanin->pCopy = (Abc_Obj_t *)vNodes->nSize;
+ Vec_PtrPush( vNodes, pFanin );
+ }
+ }
+ // add the clauses
+ if ( vSuper->nSize == 0 )
+ {
+ if ( !Abc_NtkClauseTriv( pSat, Abc_ObjNot(pNode), vVars ) )
+// if ( !Abc_NtkClauseTriv( pSat, pNode, vVars ) )
+ goto Quits;
+ }
+ else
+ {
+ if ( !Abc_NtkClauseAnd( pSat, pNode, vSuper, vVars ) )
+ goto Quits;
+ }
+ }
+ }
+/*
+ // set preferred variables
+ if ( fOrderCiVarsFirst )
+ {
+ int * pPrefVars = ALLOC( int, Abc_NtkCiNum(pNtk) );
+ int nVars = 0;
+ Abc_NtkForEachCi( pNtk, pNode, i )
+ {
+ if ( pNode->fMarkA == 0 )
+ continue;
+ pPrefVars[nVars++] = (int)pNode->pCopy;
+ }
+ nVars = ABC_MIN( nVars, 10 );
+ ASat_SolverSetPrefVars( pSat, pPrefVars, nVars );
+ }
+*/
+ RetValue = 1;
+Quits :
// delete
- Vec_StrFree( vCube );
Vec_IntFree( vVars );
- Extra_MmFlexStop( pMmFlex, 0 );
+ Vec_PtrFree( vNodes );
+ Vec_PtrFree( vSuper );
+ return RetValue;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Sets up the SAT sat_solver.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void * Abc_NtkMiterSatCreate( Abc_Ntk_t * pNtk, int fAllPrimes )
+{
+ sat_solver * pSat;
+ Abc_Obj_t * pNode;
+ int RetValue, i, clk = clock();
+
+ assert( Abc_NtkIsStrash(pNtk) || Abc_NtkIsBddLogic(pNtk) );
+ if ( Abc_NtkIsBddLogic(pNtk) )
+ return Abc_NtkMiterSatCreateLogic(pNtk, fAllPrimes);
+
+ nMuxes = 0;
+ pSat = sat_solver_new();
+//sat_solver_store_alloc( pSat );
+ RetValue = Abc_NtkMiterSatCreateInt( pSat, pNtk );
+sat_solver_store_mark_roots( pSat );
+
+ Abc_NtkForEachObj( pNtk, pNode, i )
+ pNode->fMarkA = 0;
+// ASat_SolverWriteDimacs( pSat, "temp_sat.cnf", NULL, NULL, 1 );
+ if ( RetValue == 0 )
+ {
+ sat_solver_delete(pSat);
+ return NULL;
+ }
+// printf( "Ands = %6d. Muxes = %6d (%5.2f %%). ", Abc_NtkNodeNum(pNtk), nMuxes, 300.0*nMuxes/Abc_NtkNodeNum(pNtk) );
+// PRT( "Creating sat_solver", clock() - clk );
return pSat;
}
+
+
+
/**Function*************************************************************
Synopsis [Adds clauses for the internal node.]
@@ -148,14 +654,33 @@ solver * Abc_NtkMiterSatCreate( Abc_Ntk_t * pNtk )
SeeAlso []
***********************************************************************/
-void Abc_NodeAddClauses( solver * pSat, char * pSop0, char * pSop1, Abc_Obj_t * pNode, Vec_Int_t * vVars )
+int Abc_NodeAddClauses( sat_solver * pSat, char * pSop0, char * pSop1, Abc_Obj_t * pNode, Vec_Int_t * vVars )
{
Abc_Obj_t * pFanin;
int i, c, nFanins;
+ int RetValue;
char * pCube;
nFanins = Abc_ObjFaninNum( pNode );
assert( nFanins == Abc_SopGetVarNum( pSop0 ) );
+
+// if ( nFanins == 0 )
+ if ( Cudd_Regular(pNode->pData) == Cudd_ReadOne(pNode->pNtk->pManFunc) )
+ {
+ vVars->nSize = 0;
+// if ( Abc_SopIsConst1(pSop1) )
+ if ( !Cudd_IsComplement(pNode->pData) )
+ Vec_IntPush( vVars, toLit(pNode->Id) );
+ else
+ Vec_IntPush( vVars, lit_neg(toLit(pNode->Id)) );
+ RetValue = sat_solver_addclause( pSat, vVars->pArray, vVars->pArray + vVars->nSize );
+ if ( !RetValue )
+ {
+ printf( "The CNF is trivially UNSAT.\n" );
+ return 0;
+ }
+ return 1;
+ }
// add clauses for the negative phase
for ( c = 0; ; c++ )
@@ -171,10 +696,15 @@ void Abc_NodeAddClauses( solver * pSat, char * pSop0, char * pSop1, Abc_Obj_t *
if ( pCube[i] == '0' )
Vec_IntPush( vVars, toLit(pFanin->Id) );
else if ( pCube[i] == '1' )
- Vec_IntPush( vVars, neg(toLit(pFanin->Id)) );
+ Vec_IntPush( vVars, lit_neg(toLit(pFanin->Id)) );
+ }
+ Vec_IntPush( vVars, lit_neg(toLit(pNode->Id)) );
+ RetValue = sat_solver_addclause( pSat, vVars->pArray, vVars->pArray + vVars->nSize );
+ if ( !RetValue )
+ {
+ printf( "The CNF is trivially UNSAT.\n" );
+ return 0;
}
- Vec_IntPush( vVars, neg(toLit(pNode->Id)) );
- solver_addclause( pSat, vVars->pArray, vVars->pArray + vVars->nSize );
}
// add clauses for the positive phase
@@ -191,11 +721,17 @@ void Abc_NodeAddClauses( solver * pSat, char * pSop0, char * pSop1, Abc_Obj_t *
if ( pCube[i] == '0' )
Vec_IntPush( vVars, toLit(pFanin->Id) );
else if ( pCube[i] == '1' )
- Vec_IntPush( vVars, neg(toLit(pFanin->Id)) );
+ Vec_IntPush( vVars, lit_neg(toLit(pFanin->Id)) );
}
Vec_IntPush( vVars, toLit(pNode->Id) );
- solver_addclause( pSat, vVars->pArray, vVars->pArray + vVars->nSize );
+ RetValue = sat_solver_addclause( pSat, vVars->pArray, vVars->pArray + vVars->nSize );
+ if ( !RetValue )
+ {
+ printf( "The CNF is trivially UNSAT.\n" );
+ return 0;
+ }
}
+ return 1;
}
/**Function*************************************************************
@@ -209,9 +745,10 @@ void Abc_NodeAddClauses( solver * pSat, char * pSop0, char * pSop1, Abc_Obj_t *
SeeAlso []
***********************************************************************/
-void Abc_NodeAddClausesTop( solver * pSat, Abc_Obj_t * pNode, Vec_Int_t * vVars )
+int Abc_NodeAddClausesTop( sat_solver * pSat, Abc_Obj_t * pNode, Vec_Int_t * vVars )
{
Abc_Obj_t * pFanin;
+ int RetValue;
pFanin = Abc_ObjFanin0(pNode);
if ( Abc_ObjFaninC0(pNode) )
@@ -219,31 +756,126 @@ void Abc_NodeAddClausesTop( solver * pSat, Abc_Obj_t * pNode, Vec_Int_t * vVars
vVars->nSize = 0;
Vec_IntPush( vVars, toLit(pFanin->Id) );
Vec_IntPush( vVars, toLit(pNode->Id) );
- solver_addclause( pSat, vVars->pArray, vVars->pArray + vVars->nSize );
+ RetValue = sat_solver_addclause( pSat, vVars->pArray, vVars->pArray + vVars->nSize );
+ if ( !RetValue )
+ {
+ printf( "The CNF is trivially UNSAT.\n" );
+ return 0;
+ }
vVars->nSize = 0;
- Vec_IntPush( vVars, neg(toLit(pFanin->Id)) );
- Vec_IntPush( vVars, neg(toLit(pNode->Id)) );
- solver_addclause( pSat, vVars->pArray, vVars->pArray + vVars->nSize );
+ Vec_IntPush( vVars, lit_neg(toLit(pFanin->Id)) );
+ Vec_IntPush( vVars, lit_neg(toLit(pNode->Id)) );
+ RetValue = sat_solver_addclause( pSat, vVars->pArray, vVars->pArray + vVars->nSize );
+ if ( !RetValue )
+ {
+ printf( "The CNF is trivially UNSAT.\n" );
+ return 0;
+ }
}
else
{
vVars->nSize = 0;
- Vec_IntPush( vVars, neg(toLit(pFanin->Id)) );
+ Vec_IntPush( vVars, lit_neg(toLit(pFanin->Id)) );
Vec_IntPush( vVars, toLit(pNode->Id) );
- solver_addclause( pSat, vVars->pArray, vVars->pArray + vVars->nSize );
+ RetValue = sat_solver_addclause( pSat, vVars->pArray, vVars->pArray + vVars->nSize );
+ if ( !RetValue )
+ {
+ printf( "The CNF is trivially UNSAT.\n" );
+ return 0;
+ }
vVars->nSize = 0;
Vec_IntPush( vVars, toLit(pFanin->Id) );
- Vec_IntPush( vVars, neg(toLit(pNode->Id)) );
- solver_addclause( pSat, vVars->pArray, vVars->pArray + vVars->nSize );
+ Vec_IntPush( vVars, lit_neg(toLit(pNode->Id)) );
+ RetValue = sat_solver_addclause( pSat, vVars->pArray, vVars->pArray + vVars->nSize );
+ if ( !RetValue )
+ {
+ printf( "The CNF is trivially UNSAT.\n" );
+ return 0;
+ }
}
vVars->nSize = 0;
Vec_IntPush( vVars, toLit(pNode->Id) );
- solver_addclause( pSat, vVars->pArray, vVars->pArray + vVars->nSize );
+ RetValue = sat_solver_addclause( pSat, vVars->pArray, vVars->pArray + vVars->nSize );
+ if ( !RetValue )
+ {
+ printf( "The CNF is trivially UNSAT.\n" );
+ return 0;
+ }
+ return 1;
}
+/**Function*************************************************************
+
+ Synopsis [Sets up the SAT sat_solver.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+sat_solver * Abc_NtkMiterSatCreateLogic( Abc_Ntk_t * pNtk, int fAllPrimes )
+{
+ sat_solver * pSat;
+ Extra_MmFlex_t * pMmFlex;
+ Abc_Obj_t * pNode;
+ Vec_Str_t * vCube;
+ Vec_Int_t * vVars;
+ char * pSop0, * pSop1;
+ int i;
+
+ assert( Abc_NtkIsBddLogic(pNtk) );
+
+ // transfer the IDs to the copy field
+ Abc_NtkForEachPi( pNtk, pNode, i )
+ pNode->pCopy = (void *)pNode->Id;
+
+ // start the data structures
+ pSat = sat_solver_new();
+sat_solver_store_alloc( pSat );
+ pMmFlex = Extra_MmFlexStart();
+ vCube = Vec_StrAlloc( 100 );
+ vVars = Vec_IntAlloc( 100 );
+
+ // add clauses for each internal nodes
+ Abc_NtkForEachNode( pNtk, pNode, i )
+ {
+ // derive SOPs for both phases of the node
+ Abc_NodeBddToCnf( pNode, pMmFlex, vCube, fAllPrimes, &pSop0, &pSop1 );
+ // add the clauses to the sat_solver
+ if ( !Abc_NodeAddClauses( pSat, pSop0, pSop1, pNode, vVars ) )
+ {
+ sat_solver_delete( pSat );
+ pSat = NULL;
+ goto finish;
+ }
+ }
+ // add clauses for each PO
+ Abc_NtkForEachPo( pNtk, pNode, i )
+ {
+ if ( !Abc_NodeAddClausesTop( pSat, pNode, vVars ) )
+ {
+ sat_solver_delete( pSat );
+ pSat = NULL;
+ goto finish;
+ }
+ }
+sat_solver_store_mark_roots( pSat );
+
+finish:
+ // delete
+ Vec_StrFree( vCube );
+ Vec_IntFree( vVars );
+ Extra_MmFlexStop( pMmFlex );
+ return pSat;
+}
+
+
+
////////////////////////////////////////////////////////////////////////
/// END OF FILE ///
diff --git a/src/base/abci/abcStrash.c b/src/base/abci/abcStrash.c
index de87a1e9..c77f8dea 100644
--- a/src/base/abci/abcStrash.c
+++ b/src/base/abci/abcStrash.c
@@ -1,6 +1,6 @@
/**CFile****************************************************************
- FileName [aigStrash.c]
+ FileName [abcStrash.c]
SystemName [ABC: Logic synthesis and verification system.]
@@ -14,7 +14,7 @@
Date [Ver. 1.0. Started - June 20, 2005.]
- Revision [$Id: aigStrash.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
+ Revision [$Id: abcStrash.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
***********************************************************************/
@@ -26,52 +26,170 @@
/// DECLARATIONS ///
////////////////////////////////////////////////////////////////////////
-// static functions
-static void Abc_NtkStrashPerform( Abc_Ntk_t * pNtk, Abc_Ntk_t * pNtkAig, bool fAllNodes );
-static Abc_Obj_t * Abc_NodeStrashSop( Abc_Aig_t * pMan, Abc_Obj_t * pNode, char * pSop );
-static Abc_Obj_t * Abc_NodeStrashFactor( Abc_Aig_t * pMan, Abc_Obj_t * pNode, char * pSop );
-
-extern char * Mio_GateReadSop( void * pGate );
+static void Abc_NtkStrashPerform( Abc_Ntk_t * pNtk, Abc_Ntk_t * pNtkNew, int fAllNodes, int fRecord );
////////////////////////////////////////////////////////////////////////
-/// FUNCTION DEFITIONS ///
+/// FUNCTION DEFINITIONS ///
////////////////////////////////////////////////////////////////////////
/**Function*************************************************************
- Synopsis [Creates the strashed AIG network.]
+ Synopsis [Reapplies structural hashing to the AIG.]
- Description [Converts the logic network or the AIG into a
- structurally hashed AIG.]
+ Description [Because of the structural hashing, this procedure should not
+ change the number of nodes. It is useful to detect the bugs in the original AIG.]
SideEffects []
SeeAlso []
***********************************************************************/
-Abc_Ntk_t * Abc_NtkStrash( Abc_Ntk_t * pNtk, bool fAllNodes, bool fCleanup )
+Abc_Ntk_t * Abc_NtkRestrash( Abc_Ntk_t * pNtk, bool fCleanup )
{
+ extern int timeRetime;
Abc_Ntk_t * pNtkAig;
- int nNodes;
+ Abc_Obj_t * pObj;
+ int i, nNodes;//, RetValue;
+ assert( Abc_NtkIsStrash(pNtk) );
+//timeRetime = clock();
+ // print warning about choice nodes
+ if ( Abc_NtkGetChoiceNum( pNtk ) )
+ printf( "Warning: The choice nodes in the original AIG are removed by strashing.\n" );
+ // start the new network (constants and CIs of the old network will point to the their counterparts in the new network)
+ pNtkAig = Abc_NtkStartFrom( pNtk, ABC_NTK_STRASH, ABC_FUNC_AIG );
+ // restrash the nodes (assuming a topological order of the old network)
+ Abc_NtkForEachNode( pNtk, pObj, i )
+ pObj->pCopy = Abc_AigAnd( pNtkAig->pManFunc, Abc_ObjChild0Copy(pObj), Abc_ObjChild1Copy(pObj) );
+ // finalize the network
+ Abc_NtkFinalize( pNtk, pNtkAig );
+ // print warning about self-feed latches
+// if ( Abc_NtkCountSelfFeedLatches(pNtkAig) )
+// printf( "Warning: The network has %d self-feeding latches.\n", Abc_NtkCountSelfFeedLatches(pNtkAig) );
+ // perform cleanup if requested
+ if ( fCleanup && (nNodes = Abc_AigCleanup(pNtkAig->pManFunc)) )
+ printf( "Abc_NtkRestrash(): AIG cleanup removed %d nodes (this is a bug).\n", nNodes );
+ // duplicate EXDC
+ if ( pNtk->pExdc )
+ pNtkAig->pExdc = Abc_NtkDup( pNtk->pExdc );
+ // make sure everything is okay
+ if ( !Abc_NtkCheck( pNtkAig ) )
+ {
+ printf( "Abc_NtkStrash: The network check has failed.\n" );
+ Abc_NtkDelete( pNtkAig );
+ return NULL;
+ }
+//timeRetime = clock() - timeRetime;
+// if ( RetValue = Abc_NtkRemoveSelfFeedLatches(pNtkAig) )
+// printf( "Modified %d self-feeding latches. The result may not verify.\n", RetValue );
+ return pNtkAig;
+
+}
+
+/**Function*************************************************************
+
+ Synopsis [Reapplies structural hashing to the AIG.]
- assert( !Abc_NtkIsNetlist(pNtk) );
- if ( Abc_NtkIsBddLogic(pNtk) )
- Abc_NtkBddToSop(pNtk);
+ Description [Because of the structural hashing, this procedure should not
+ change the number of nodes. It is useful to detect the bugs in the original AIG.]
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Abc_Ntk_t * Abc_NtkRestrashZero( Abc_Ntk_t * pNtk, bool fCleanup )
+{
+ extern int timeRetime;
+ Abc_Ntk_t * pNtkAig;
+ Abc_Obj_t * pObj;
+ int i, nNodes;//, RetValue;
+ assert( Abc_NtkIsStrash(pNtk) );
+//timeRetime = clock();
// print warning about choice nodes
if ( Abc_NtkGetChoiceNum( pNtk ) )
- printf( "Warning: The choice nodes in the initial AIG are removed by strashing.\n" );
+ printf( "Warning: The choice nodes in the original AIG are removed by strashing.\n" );
+ // start the new network (constants and CIs of the old network will point to the their counterparts in the new network)
+ pNtkAig = Abc_NtkStartFrom( pNtk, ABC_NTK_STRASH, ABC_FUNC_AIG );
+ // complement the 1-values registers
+ Abc_NtkForEachLatch( pNtk, pObj, i )
+ if ( Abc_LatchIsInit1(pObj) )
+ Abc_ObjFanout0(pObj)->pCopy = Abc_ObjNot(Abc_ObjFanout0(pObj)->pCopy);
+ // restrash the nodes (assuming a topological order of the old network)
+ Abc_NtkForEachNode( pNtk, pObj, i )
+ pObj->pCopy = Abc_AigAnd( pNtkAig->pManFunc, Abc_ObjChild0Copy(pObj), Abc_ObjChild1Copy(pObj) );
+ // finalize the network
+ Abc_NtkFinalize( pNtk, pNtkAig );
+ // complement the 1-valued registers
+ Abc_NtkForEachLatch( pNtkAig, pObj, i )
+ if ( Abc_LatchIsInit1(pObj) )
+ Abc_ObjXorFaninC( Abc_ObjFanin0(pObj), 0 );
+ // set all constant-0 values
+ Abc_NtkForEachLatch( pNtkAig, pObj, i )
+ Abc_LatchSetInit0( pObj );
+
+ // print warning about self-feed latches
+// if ( Abc_NtkCountSelfFeedLatches(pNtkAig) )
+// printf( "Warning: The network has %d self-feeding latches.\n", Abc_NtkCountSelfFeedLatches(pNtkAig) );
+ // perform cleanup if requested
+ if ( fCleanup && (nNodes = Abc_AigCleanup(pNtkAig->pManFunc)) )
+ printf( "Abc_NtkRestrash(): AIG cleanup removed %d nodes (this is a bug).\n", nNodes );
+ // duplicate EXDC
+ if ( pNtk->pExdc )
+ pNtkAig->pExdc = Abc_NtkDup( pNtk->pExdc );
+ // make sure everything is okay
+ if ( !Abc_NtkCheck( pNtkAig ) )
+ {
+ printf( "Abc_NtkStrash: The network check has failed.\n" );
+ Abc_NtkDelete( pNtkAig );
+ return NULL;
+ }
+//timeRetime = clock() - timeRetime;
+// if ( RetValue = Abc_NtkRemoveSelfFeedLatches(pNtkAig) )
+// printf( "Modified %d self-feeding latches. The result may not verify.\n", RetValue );
+ return pNtkAig;
+
+}
+
+/**Function*************************************************************
+
+ Synopsis [Transforms logic network into structurally hashed AIG.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Abc_Ntk_t * Abc_NtkStrash( Abc_Ntk_t * pNtk, int fAllNodes, int fCleanup, int fRecord )
+{
+ Abc_Ntk_t * pNtkAig;
+ int nNodes;
+ assert( Abc_NtkIsLogic(pNtk) || Abc_NtkIsStrash(pNtk) );
+ // consider the special case when the network is already structurally hashed
+ if ( Abc_NtkIsStrash(pNtk) )
+ return Abc_NtkRestrash( pNtk, fCleanup );
+ // convert the node representation in the logic network to the AIG form
+ if ( !Abc_NtkToAig(pNtk) )
+ {
+ printf( "Converting to AIGs has failed.\n" );
+ return NULL;
+ }
// perform strashing
- pNtkAig = Abc_NtkStartFrom( pNtk, ABC_TYPE_STRASH, ABC_FUNC_AIG );
- Abc_NtkStrashPerform( pNtk, pNtkAig, fAllNodes );
+// Abc_NtkCleanCopy( pNtk );
+ pNtkAig = Abc_NtkStartFrom( pNtk, ABC_NTK_STRASH, ABC_FUNC_AIG );
+ Abc_NtkStrashPerform( pNtk, pNtkAig, fAllNodes, fRecord );
Abc_NtkFinalize( pNtk, pNtkAig );
// print warning about self-feed latches
- if ( Abc_NtkCountSelfFeedLatches(pNtkAig) )
- printf( "The network has %d self-feeding latches.\n", Abc_NtkCountSelfFeedLatches(pNtkAig) );
- if ( fCleanup && (nNodes = Abc_AigCleanup(pNtkAig->pManFunc)) )
- printf( "Cleanup has removed %d nodes.\n", nNodes );
+// if ( Abc_NtkCountSelfFeedLatches(pNtkAig) )
+// printf( "Warning: The network has %d self-feeding latches.\n", Abc_NtkCountSelfFeedLatches(pNtkAig) );
+ // perform cleanup if requested
+ nNodes = fCleanup? Abc_AigCleanup(pNtkAig->pManFunc) : 0;
+// if ( nNodes )
+// printf( "Warning: AIG cleanup removed %d nodes (this is not a bug).\n", nNodes );
// duplicate EXDC
if ( pNtk->pExdc )
- pNtkAig->pExdc = Abc_NtkStrash( pNtk->pExdc, 0, 1 );
+ pNtkAig->pExdc = Abc_NtkDup( pNtk->pExdc );
// make sure everything is okay
if ( !Abc_NtkCheck( pNtkAig ) )
{
@@ -87,34 +205,85 @@ Abc_Ntk_t * Abc_NtkStrash( Abc_Ntk_t * pNtk, bool fAllNodes, bool fCleanup )
Synopsis [Appends the second network to the first.]
Description [Modifies the first network by adding the logic of the second.
- Performs structural hashing while appending the networks. Does not add
- the COs of the second. Does not change the second network. Returns 0
- if the appending failed, 1 otherise.]
+ Performs structural hashing while appending the networks. Does not change
+ the second network. Returns 0 if the appending failed, 1 otherise.]
SideEffects []
SeeAlso []
***********************************************************************/
-int Abc_NtkAppend( Abc_Ntk_t * pNtk1, Abc_Ntk_t * pNtk2 )
+int Abc_NtkAppend( Abc_Ntk_t * pNtk1, Abc_Ntk_t * pNtk2, int fAddPos )
{
Abc_Obj_t * pObj;
- int i;
+ char * pName;
+ int i, nNewCis;
// the first network should be an AIG
assert( Abc_NtkIsStrash(pNtk1) );
assert( Abc_NtkIsLogic(pNtk2) || Abc_NtkIsStrash(pNtk2) );
- if ( Abc_NtkIsBddLogic(pNtk2) )
- Abc_NtkBddToSop(pNtk2);
+ if ( Abc_NtkIsLogic(pNtk2) && !Abc_NtkToAig(pNtk2) )
+ {
+ printf( "Converting to AIGs has failed.\n" );
+ return 0;
+ }
// check that the networks have the same PIs
// reorder PIs of pNtk2 according to pNtk1
- if ( !Abc_NtkCompareSignals( pNtk1, pNtk2, 1 ) )
- return 0;
+ if ( !Abc_NtkCompareSignals( pNtk1, pNtk2, 1, 1 ) )
+ printf( "Abc_NtkAppend(): The union of the network PIs is computed (warning).\n" );
// perform strashing
+ nNewCis = 0;
Abc_NtkCleanCopy( pNtk2 );
+ if ( Abc_NtkIsStrash(pNtk2) )
+ Abc_AigConst1(pNtk2)->pCopy = Abc_AigConst1(pNtk1);
Abc_NtkForEachCi( pNtk2, pObj, i )
- pObj->pCopy = Abc_NtkCi(pNtk1, i);
+ {
+ pName = Abc_ObjName(pObj);
+ pObj->pCopy = Abc_NtkFindCi(pNtk1, Abc_ObjName(pObj));
+ if ( pObj->pCopy == NULL )
+ {
+ pObj->pCopy = Abc_NtkDupObj(pNtk1, pObj, 1);
+ nNewCis++;
+ }
+ }
+ if ( nNewCis )
+ printf( "Warning: Procedure Abc_NtkAppend() added %d new CIs.\n", nNewCis );
// add pNtk2 to pNtk1 while strashing
- Abc_NtkStrashPerform( pNtk2, pNtk1, 1 );
+ if ( Abc_NtkIsLogic(pNtk2) )
+ Abc_NtkStrashPerform( pNtk2, pNtk1, 1, 0 );
+ else
+ Abc_NtkForEachNode( pNtk2, pObj, i )
+ pObj->pCopy = Abc_AigAnd( pNtk1->pManFunc, Abc_ObjChild0Copy(pObj), Abc_ObjChild1Copy(pObj) );
+ // add the COs of the second network
+ if ( fAddPos )
+ {
+ Abc_NtkForEachPo( pNtk2, pObj, i )
+ {
+ Abc_NtkDupObj( pNtk1, pObj, 0 );
+ Abc_ObjAddFanin( pObj->pCopy, Abc_ObjChild0Copy(pObj) );
+ Abc_ObjAssignName( pObj->pCopy, Abc_ObjName(pObj->pCopy), NULL );
+ }
+ }
+ else
+ {
+ Abc_Obj_t * pObjOld, * pDriverOld, * pDriverNew;
+ int fCompl, iNodeId;
+ // OR the choices
+ Abc_NtkForEachCo( pNtk2, pObj, i )
+ {
+ iNodeId = Nm_ManFindIdByNameTwoTypes( pNtk1->pManName, Abc_ObjName(pObj), ABC_OBJ_PO, ABC_OBJ_BI );
+ assert( iNodeId >= 0 );
+ pObjOld = Abc_NtkObj( pNtk1, iNodeId );
+ // derive the new driver
+ pDriverOld = Abc_ObjChild0( pObjOld );
+ pDriverNew = Abc_ObjChild0Copy( pObj );
+ pDriverNew = Abc_AigOr( pNtk1->pManFunc, pDriverOld, pDriverNew );
+ if ( Abc_ObjRegular(pDriverOld) == Abc_ObjRegular(pDriverNew) )
+ continue;
+ // replace the old driver by the new driver
+ fCompl = Abc_ObjRegular(pDriverOld)->fPhase ^ Abc_ObjRegular(pDriverNew)->fPhase;
+ Abc_ObjPatchFanin( pObjOld, Abc_ObjRegular(pDriverOld), Abc_ObjNotCond(Abc_ObjRegular(pDriverNew), fCompl) );
+ }
+ }
// make sure that everything is okay
if ( !Abc_NtkCheck( pNtk1 ) )
{
@@ -124,7 +293,6 @@ int Abc_NtkAppend( Abc_Ntk_t * pNtk1, Abc_Ntk_t * pNtk2 )
return 1;
}
-
/**Function*************************************************************
Synopsis [Prepares the network for strashing.]
@@ -136,38 +304,31 @@ int Abc_NtkAppend( Abc_Ntk_t * pNtk1, Abc_Ntk_t * pNtk2 )
SeeAlso []
***********************************************************************/
-void Abc_NtkStrashPerform( Abc_Ntk_t * pNtk, Abc_Ntk_t * pNtkNew, bool fAllNodes )
+void Abc_NtkStrashPerform( Abc_Ntk_t * pNtkOld, Abc_Ntk_t * pNtkNew, int fAllNodes, int fRecord )
{
ProgressBar * pProgress;
- Abc_Aig_t * pMan = pNtkNew->pManFunc;
Vec_Ptr_t * vNodes;
- Abc_Obj_t * pNode, * pNodeNew, * pObj;
- int i;
-
- // perform strashing
- vNodes = Abc_NtkDfs( pNtk, fAllNodes );
+ Abc_Obj_t * pNodeOld;
+ int i, clk = clock();
+ assert( Abc_NtkIsLogic(pNtkOld) );
+ assert( Abc_NtkIsStrash(pNtkNew) );
+// vNodes = Abc_NtkDfs( pNtkOld, fAllNodes );
+ vNodes = Abc_NtkDfsIter( pNtkOld, fAllNodes );
+//printf( "Nodes = %d. ", Vec_PtrSize(vNodes) );
+//PRT( "Time", clock() - clk );
pProgress = Extra_ProgressBarStart( stdout, vNodes->nSize );
- Vec_PtrForEachEntry( vNodes, pNode, i )
+ Vec_PtrForEachEntry( vNodes, pNodeOld, i )
{
Extra_ProgressBarUpdate( pProgress, i, NULL );
- // get the node
- assert( Abc_ObjIsNode(pNode) );
- // strash the node
- pNodeNew = Abc_NodeStrash( pMan, pNode );
- // get the old object
- pObj = Abc_ObjFanout0Ntk( pNode );
- // make sure the node is not yet strashed
- assert( pObj->pCopy == NULL );
- // mark the old object with the new AIG node
- pObj->pCopy = pNodeNew;
+ pNodeOld->pCopy = Abc_NodeStrash( pNtkNew, pNodeOld, fRecord );
}
- Vec_PtrFree( vNodes );
Extra_ProgressBarStop( pProgress );
+ Vec_PtrFree( vNodes );
}
/**Function*************************************************************
- Synopsis [Strashes one logic node.]
+ Synopsis [Transfers the AIG from one manager into another.]
Description []
@@ -176,40 +337,76 @@ void Abc_NtkStrashPerform( Abc_Ntk_t * pNtk, Abc_Ntk_t * pNtkNew, bool fAllNodes
SeeAlso []
***********************************************************************/
-Abc_Obj_t * Abc_NodeStrash( Abc_Aig_t * pMan, Abc_Obj_t * pNode )
+void Abc_NodeStrash_rec( Abc_Aig_t * pMan, Hop_Obj_t * pObj )
{
- int fUseFactor = 1;
- char * pSop;
+ assert( !Hop_IsComplement(pObj) );
+ if ( !Hop_ObjIsNode(pObj) || Hop_ObjIsMarkA(pObj) )
+ return;
+ Abc_NodeStrash_rec( pMan, Hop_ObjFanin0(pObj) );
+ Abc_NodeStrash_rec( pMan, Hop_ObjFanin1(pObj) );
+ pObj->pData = Abc_AigAnd( pMan, (Abc_Obj_t *)Hop_ObjChild0Copy(pObj), (Abc_Obj_t *)Hop_ObjChild1Copy(pObj) );
+ assert( !Hop_ObjIsMarkA(pObj) ); // loop detection
+ Hop_ObjSetMarkA( pObj );
+}
+
+/**Function*************************************************************
- assert( Abc_ObjIsNode(pNode) );
+ Synopsis [Strashes one logic node.]
- // consider the case when the graph is an AIG
- if ( Abc_NtkIsStrash(pNode->pNtk) )
+ Description [Assume the network is in the AIG form]
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Abc_Obj_t * Abc_NodeStrash( Abc_Ntk_t * pNtkNew, Abc_Obj_t * pNodeOld, int fRecord )
+{
+ Hop_Man_t * pMan;
+ Hop_Obj_t * pRoot;
+ Abc_Obj_t * pFanin;
+ int i;
+ assert( Abc_ObjIsNode(pNodeOld) );
+ assert( Abc_NtkHasAig(pNodeOld->pNtk) && !Abc_NtkIsStrash(pNodeOld->pNtk) );
+ // get the local AIG manager and the local root node
+ pMan = pNodeOld->pNtk->pManFunc;
+ pRoot = pNodeOld->pData;
+ // check the constant case
+ if ( Abc_NodeIsConst(pNodeOld) || Hop_Regular(pRoot) == Hop_ManConst1(pMan) )
+ return Abc_ObjNotCond( Abc_AigConst1(pNtkNew), Hop_IsComplement(pRoot) );
+ // perform special case-strashing using the record of AIG subgraphs
+ if ( fRecord && Abc_NtkRecIsRunning() && Abc_ObjFaninNum(pNodeOld) > 2 && Abc_ObjFaninNum(pNodeOld) <= Abc_NtkRecVarNum() )
{
- if ( Abc_NodeIsConst(pNode) )
- return Abc_AigConst1(pMan);
- return Abc_AigAnd( pMan, Abc_ObjChild0Copy(pNode), Abc_ObjChild1Copy(pNode) );
+ extern Vec_Int_t * Abc_NtkRecMemory();
+ extern int Abc_NtkRecStrashNode( Abc_Ntk_t * pNtkNew, Abc_Obj_t * pObj, unsigned * pTruth, int nVars );
+ int nVars = Abc_NtkRecVarNum();
+ Vec_Int_t * vMemory = Abc_NtkRecMemory();
+ unsigned * pTruth = Abc_ConvertAigToTruth( pMan, Hop_Regular(pRoot), nVars, vMemory, 0 );
+ assert( Extra_TruthSupportSize(pTruth, nVars) == Abc_ObjFaninNum(pNodeOld) ); // should be swept
+ if ( Hop_IsComplement(pRoot) )
+ Extra_TruthNot( pTruth, pTruth, nVars );
+ if ( Abc_NtkRecStrashNode( pNtkNew, pNodeOld, pTruth, nVars ) )
+ return pNodeOld->pCopy;
}
+ // set elementary variables
+ Abc_ObjForEachFanin( pNodeOld, pFanin, i )
+ Hop_IthVar(pMan, i)->pData = pFanin->pCopy;
+ // strash the AIG of this node
+ Abc_NodeStrash_rec( pNtkNew->pManFunc, Hop_Regular(pRoot) );
+ Hop_ConeUnmark_rec( Hop_Regular(pRoot) );
+ // return the final node
+ return Abc_ObjNotCond( Hop_Regular(pRoot)->pData, Hop_IsComplement(pRoot) );
+}
+
+
+
- // get the SOP of the node
- if ( Abc_NtkHasMapping(pNode->pNtk) )
- pSop = Mio_GateReadSop(pNode->pData);
- else
- pSop = pNode->pData;
- // consider the constant node
- if ( Abc_NodeIsConst(pNode) )
- return Abc_ObjNotCond( Abc_AigConst1(pMan), Abc_SopIsConst0(pSop) );
- // decide when to use factoring
- if ( fUseFactor && Abc_ObjFaninNum(pNode) > 2 && Abc_SopGetCubeNum(pSop) > 1 )
- return Abc_NodeStrashFactor( pMan, pNode, pSop );
- return Abc_NodeStrashSop( pMan, pNode, pSop );
-}
/**Function*************************************************************
- Synopsis [Strashes one logic node using its SOP.]
+ Synopsis [Copies the topmost levels of the network.]
Description []
@@ -218,41 +415,21 @@ Abc_Obj_t * Abc_NodeStrash( Abc_Aig_t * pMan, Abc_Obj_t * pNode )
SeeAlso []
***********************************************************************/
-Abc_Obj_t * Abc_NodeStrashSop( Abc_Aig_t * pMan, Abc_Obj_t * pNode, char * pSop )
+Abc_Obj_t * Abc_NtkTopmost_rec( Abc_Ntk_t * pNtkNew, Abc_Obj_t * pNode, int LevelCut )
{
- Abc_Obj_t * pFanin, * pAnd, * pSum;
- Abc_Obj_t * pConst1 = Abc_AigConst1(pMan);
- char * pCube;
- int i, nFanins;
-
- // get the number of node's fanins
- nFanins = Abc_ObjFaninNum( pNode );
- assert( nFanins == Abc_SopGetVarNum(pSop) );
- // go through the cubes of the node's SOP
- pSum = Abc_ObjNot(pConst1);
- Abc_SopForEachCube( pSop, nFanins, pCube )
- {
- // create the AND of literals
- pAnd = pConst1;
- Abc_ObjForEachFanin( pNode, pFanin, i ) // pFanin can be a net
- {
- if ( pCube[i] == '1' )
- pAnd = Abc_AigAnd( pMan, pAnd, pFanin->pCopy );
- else if ( pCube[i] == '0' )
- pAnd = Abc_AigAnd( pMan, pAnd, Abc_ObjNot(pFanin->pCopy) );
- }
- // add to the sum of cubes
- pSum = Abc_AigOr( pMan, pSum, pAnd );
- }
- // decide whether to complement the result
- if ( Abc_SopIsComplement(pSop) )
- pSum = Abc_ObjNot(pSum);
- return pSum;
+ assert( !Abc_ObjIsComplement(pNode) );
+ if ( pNode->pCopy )
+ return pNode->pCopy;
+ if ( pNode->Level <= (unsigned)LevelCut )
+ return pNode->pCopy = Abc_NtkCreatePi( pNtkNew );
+ Abc_NtkTopmost_rec( pNtkNew, Abc_ObjFanin0(pNode), LevelCut );
+ Abc_NtkTopmost_rec( pNtkNew, Abc_ObjFanin1(pNode), LevelCut );
+ return pNode->pCopy = Abc_AigAnd( pNtkNew->pManFunc, Abc_ObjChild0Copy(pNode), Abc_ObjChild1Copy(pNode) );
}
/**Function*************************************************************
- Synopsis [Strashes one logic node using its SOP.]
+ Synopsis [Copies the topmost levels of the network.]
Description []
@@ -261,23 +438,39 @@ Abc_Obj_t * Abc_NodeStrashSop( Abc_Aig_t * pMan, Abc_Obj_t * pNode, char * pSop
SeeAlso []
***********************************************************************/
-Abc_Obj_t * Abc_NodeStrashFactor( Abc_Aig_t * pMan, Abc_Obj_t * pRoot, char * pSop )
+Abc_Ntk_t * Abc_NtkTopmost( Abc_Ntk_t * pNtk, int nLevels )
{
- Dec_Graph_t * pFForm;
- Dec_Node_t * pNode;
- Abc_Obj_t * pAnd;
- int i;
- // perform factoring
- pFForm = Dec_Factor( pSop );
- // collect the fanins
- Dec_GraphForEachLeaf( pFForm, pNode, i )
- pNode->pFunc = Abc_ObjFanin(pRoot,i)->pCopy;
- // perform strashing
- pAnd = Dec_GraphToNetwork( pMan, pFForm );
- Dec_GraphFree( pFForm );
- return pAnd;
+ Abc_Ntk_t * pNtkNew;
+ Abc_Obj_t * pObjNew, * pPoNew;
+ int LevelCut;
+ assert( Abc_NtkIsStrash(pNtk) );
+ assert( Abc_NtkCoNum(pNtk) == 1 );
+ // get the cutoff level
+ LevelCut = ABC_MAX( 0, Abc_AigLevel(pNtk) - nLevels );
+ // start the network
+ pNtkNew = Abc_NtkAlloc( ABC_NTK_STRASH, ABC_FUNC_AIG, 1 );
+ pNtkNew->pName = Extra_UtilStrsav(pNtk->pName);
+ Abc_AigConst1(pNtk)->pCopy = Abc_AigConst1(pNtkNew);
+ // create PIs below the cut and nodes above the cut
+ Abc_NtkCleanCopy( pNtk );
+ pObjNew = Abc_NtkTopmost_rec( pNtkNew, Abc_ObjFanin0(Abc_NtkPo(pNtk, 0)), LevelCut );
+ pObjNew = Abc_ObjNotCond( pObjNew, Abc_ObjFaninC0(Abc_NtkPo(pNtk, 0)) );
+ // add the PO node and name
+ pPoNew = Abc_NtkCreatePo(pNtkNew);
+ Abc_ObjAddFanin( pPoNew, pObjNew );
+ Abc_NtkAddDummyPiNames( pNtkNew );
+ Abc_ObjAssignName( pPoNew, Abc_ObjName(Abc_NtkPo(pNtk, 0)), NULL );
+ // make sure everything is okay
+ if ( !Abc_NtkCheck( pNtkNew ) )
+ {
+ printf( "Abc_NtkTopmost: The network check has failed.\n" );
+ Abc_NtkDelete( pNtkNew );
+ return NULL;
+ }
+ return pNtkNew;
}
+
////////////////////////////////////////////////////////////////////////
/// END OF FILE ///
////////////////////////////////////////////////////////////////////////
diff --git a/src/base/abci/abcSweep.c b/src/base/abci/abcSweep.c
index 7000ecad..1ae8745b 100644
--- a/src/base/abci/abcSweep.c
+++ b/src/base/abci/abcSweep.c
@@ -25,20 +25,20 @@
/// DECLARATIONS ///
////////////////////////////////////////////////////////////////////////
-extern Fraig_Man_t * Abc_NtkToFraig( Abc_Ntk_t * pNtk, Fraig_Params_t * pParams, int fAllNodes );
-
-static stmm_table * Abc_NtkFraigEquiv( Fraig_Man_t * p, Abc_Ntk_t * pNtk, int fUseInv, bool fVerbose );
+static void Abc_NtkFraigSweepUsingExdc( Fraig_Man_t * pMan, Abc_Ntk_t * pNtk );
+static stmm_table * Abc_NtkFraigEquiv( Abc_Ntk_t * pNtk, int fUseInv, int fVerbose, int fVeryVerbose );
static void Abc_NtkFraigTransform( Abc_Ntk_t * pNtk, stmm_table * tEquiv, int fUseInv, bool fVerbose );
-static void Abc_NtkFraigMergeClassMapped( Abc_Ntk_t * pNtk, Abc_Obj_t * pChain, int fVerbose, int fUseInv );
-static void Abc_NtkFraigMergeClass( Abc_Ntk_t * pNtk, Abc_Obj_t * pChain, int fVerbose, int fUseInv );
+static void Abc_NtkFraigMergeClassMapped( Abc_Ntk_t * pNtk, Abc_Obj_t * pChain, int fUseInv, int fVerbose );
+static void Abc_NtkFraigMergeClass( Abc_Ntk_t * pNtk, Abc_Obj_t * pChain, int fUseInv, int fVerbose );
static int Abc_NodeDroppingCost( Abc_Obj_t * pNode );
+static int Abc_NtkReduceNodes( Abc_Ntk_t * pNtk, Vec_Ptr_t * vNodes );
static void Abc_NodeSweep( Abc_Obj_t * pNode, int fVerbose );
static void Abc_NodeConstantInput( Abc_Obj_t * pNode, Abc_Obj_t * pFanin, bool fConst0 );
static void Abc_NodeComplementInput( Abc_Obj_t * pNode, Abc_Obj_t * pFanin );
////////////////////////////////////////////////////////////////////////
-/// FUNCTION DEFITIONS ///
+/// FUNCTION DEFINITIONS ///
////////////////////////////////////////////////////////////////////////
/**Function*************************************************************
@@ -54,22 +54,57 @@ static void Abc_NodeComplementInput( Abc_Obj_t * pNode, Abc_Obj_t * pF
SeeAlso []
***********************************************************************/
-bool Abc_NtkFraigSweep( Abc_Ntk_t * pNtk, int fUseInv, int fVerbose )
+bool Abc_NtkFraigSweep( Abc_Ntk_t * pNtk, int fUseInv, int fExdc, int fVerbose, int fVeryVerbose )
{
Fraig_Params_t Params;
Abc_Ntk_t * pNtkAig;
Fraig_Man_t * pMan;
stmm_table * tEquiv;
+ Abc_Obj_t * pObj;
+ int i, fUseTrick;
assert( !Abc_NtkIsStrash(pNtk) );
+ // save gate assignments
+ fUseTrick = 0;
+ if ( Abc_NtkIsMappedLogic(pNtk) )
+ {
+ fUseTrick = 1;
+ Abc_NtkForEachNode( pNtk, pObj, i )
+ pObj->pNext = pObj->pData;
+ }
// derive the AIG
- pNtkAig = Abc_NtkStrash( pNtk, 0, 1 );
+ pNtkAig = Abc_NtkStrash( pNtk, 0, 1, 0 );
+ // reconstruct gate assignments
+ if ( fUseTrick )
+ {
+ extern void * Abc_FrameReadLibGen();
+ Hop_ManStop( pNtk->pManFunc );
+ pNtk->pManFunc = Abc_FrameReadLibGen();
+ pNtk->ntkFunc = ABC_FUNC_MAP;
+ Abc_NtkForEachNode( pNtk, pObj, i )
+ pObj->pData = pObj->pNext, pObj->pNext = NULL;
+ }
+
// perform fraiging of the AIG
Fraig_ParamsSetDefault( &Params );
- pMan = Abc_NtkToFraig( pNtkAig, &Params, 0 );
+ pMan = Abc_NtkToFraig( pNtkAig, &Params, 0, 0 );
+ // cannot use EXDC with FRAIG because it can create classes of equivalent FRAIG nodes
+ // with representative nodes that do not correspond to the nodes with the current network
+
+ // update FRAIG using EXDC
+ if ( fExdc )
+ {
+ if ( pNtk->pExdc == NULL )
+ printf( "Warning: Networks has no EXDC.\n" );
+ else
+ Abc_NtkFraigSweepUsingExdc( pMan, pNtk );
+ }
+ // assign levels to the nodes of the network
+ Abc_NtkLevel( pNtk );
+
// collect the classes of equivalent nets
- tEquiv = Abc_NtkFraigEquiv( pMan, pNtk, fUseInv, fVerbose );
+ tEquiv = Abc_NtkFraigEquiv( pNtk, fUseInv, fVerbose, fVeryVerbose );
// transform the network into the equivalent one
Abc_NtkFraigTransform( pNtk, tEquiv, fUseInv, fVerbose );
@@ -80,7 +115,11 @@ bool Abc_NtkFraigSweep( Abc_Ntk_t * pNtk, int fUseInv, int fVerbose )
Abc_NtkDelete( pNtkAig );
// cleanup the dangling nodes
- Abc_NtkCleanup( pNtk, fVerbose );
+ if ( Abc_NtkHasMapping(pNtk) )
+ Abc_NtkCleanup( pNtk, fVerbose );
+ else
+ Abc_NtkSweep( pNtk, fVerbose );
+
// check
if ( !Abc_NtkCheck( pNtk ) )
{
@@ -92,6 +131,47 @@ bool Abc_NtkFraigSweep( Abc_Ntk_t * pNtk, int fUseInv, int fVerbose )
/**Function*************************************************************
+ Synopsis [Sweep the network using EXDC.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Abc_NtkFraigSweepUsingExdc( Fraig_Man_t * pMan, Abc_Ntk_t * pNtk )
+{
+ Fraig_Node_t * gNodeExdc, * gNode, * gNodeRes;
+ Abc_Obj_t * pNode, * pNodeAig;
+ int i;
+ extern Fraig_Node_t * Abc_NtkToFraigExdc( Fraig_Man_t * pMan, Abc_Ntk_t * pNtk, Abc_Ntk_t * pNtkExdc );
+
+ assert( pNtk->pExdc );
+ // derive FRAIG node representing don't-cares in the EXDC network
+ gNodeExdc = Abc_NtkToFraigExdc( pMan, pNtk, pNtk->pExdc );
+ // update the node pointers
+ Abc_NtkForEachNode( pNtk, pNode, i )
+ {
+ // skip the constant input nodes
+ if ( Abc_ObjFaninNum(pNode) == 0 )
+ continue;
+ // get the strashed node
+ pNodeAig = pNode->pCopy;
+ // skip the dangling nodes
+ if ( pNodeAig == NULL )
+ continue;
+ // get the FRAIG node
+ gNode = Fraig_NotCond( Abc_ObjRegular(pNodeAig)->pCopy, Abc_ObjIsComplement(pNodeAig) );
+ // perform ANDing with EXDC
+ gNodeRes = Fraig_NodeAnd( pMan, gNode, Fraig_Not(gNodeExdc) );
+ // write the node back
+ Abc_ObjRegular(pNodeAig)->pCopy = (Abc_Obj_t *)Fraig_NotCond( gNodeRes, Abc_ObjIsComplement(pNodeAig) );
+ }
+}
+
+/**Function*************************************************************
+
Synopsis [Collects equivalence classses of node in the network.]
Description []
@@ -101,7 +181,7 @@ bool Abc_NtkFraigSweep( Abc_Ntk_t * pNtk, int fUseInv, int fVerbose )
SeeAlso []
***********************************************************************/
-stmm_table * Abc_NtkFraigEquiv( Fraig_Man_t * p, Abc_Ntk_t * pNtk, int fUseInv, bool fVerbose )
+stmm_table * Abc_NtkFraigEquiv( Abc_Ntk_t * pNtk, int fUseInv, int fVerbose, int fVeryVerbose )
{
Abc_Obj_t * pList, * pNode, * pNodeAig;
Fraig_Node_t * gNode;
@@ -115,16 +195,16 @@ stmm_table * Abc_NtkFraigEquiv( Fraig_Man_t * p, Abc_Ntk_t * pNtk, int fUseInv,
tStrash2Net = stmm_init_table(stmm_ptrcmp,stmm_ptrhash);
Abc_NtkForEachNode( pNtk, pNode, c )
{
+ // skip the constant input nodes
+ if ( Abc_ObjFaninNum(pNode) == 0 )
+ continue;
// get the strashed node
pNodeAig = pNode->pCopy;
// skip the dangling nodes
if ( pNodeAig == NULL )
continue;
- // skip the constant input nodes
- if ( Abc_ObjFaninNum(pNode) == 0 )
- continue;
- // skip the nodes that fanout into POs
- if ( Abc_NodeHasUniqueCoFanout(pNode) )
+ // skip the nodes that fanout into COs
+ if ( Abc_NodeFindCoFanout(pNode) )
continue;
// get the FRAIG node
gNode = Fraig_NotCond( Abc_ObjRegular(pNodeAig)->pCopy, Abc_ObjIsComplement(pNodeAig) );
@@ -151,22 +231,22 @@ stmm_table * Abc_NtkFraigEquiv( Fraig_Man_t * p, Abc_Ntk_t * pNtk, int fUseInv,
// count nodes in the non-trival classes
for ( pNode = pList; pNode; pNode = pNode->pNext )
Counter++;
-/*
- if ( fVerbose )
+
+ if ( fVeryVerbose )
{
printf( "Class %2d : {", c );
for ( pNode = pList; pNode; pNode = pNode->pNext )
{
pNode->pCopy = NULL;
printf( " %s", Abc_ObjName(pNode) );
- if ( pNode->fPhase ) printf( "(*)" );
+ printf( "(%c)", pNode->fPhase? '-' : '+' );
+ printf( "(%d)", pNode->Level );
}
printf( " }\n" );
c++;
}
-*/
}
- if ( fVerbose )
+ if ( fVerbose || fVeryVerbose )
{
printf( "Sweeping stats for network \"%s\":\n", pNtk->pName );
printf( "Internal nodes = %d. Different functions (up to compl) = %d.\n", Abc_NtkNodeNum(pNtk), stmm_count(tStrash2Net) );
@@ -194,8 +274,6 @@ void Abc_NtkFraigTransform( Abc_Ntk_t * pNtk, stmm_table * tEquiv, int fUseInv,
Abc_Obj_t * pList;
if ( stmm_count(tEquiv) == 0 )
return;
- // assign levels to the nodes of the network
- Abc_NtkGetLevelNum( pNtk );
// merge nodes in the classes
if ( Abc_NtkHasMapping( pNtk ) )
{
@@ -257,8 +335,8 @@ void Abc_NtkFraigMergeClassMapped( Abc_Ntk_t * pNtk, Abc_Obj_t * pChain, int fUs
{
Arrival1 = Abc_NodeReadArrival(pNodeMin)->Worst;
Arrival2 = Abc_NodeReadArrival(pNode )->Worst;
- assert( Abc_ObjIsCi(pNodeMin) || Arrival1 > 0 );
- assert( Abc_ObjIsCi(pNode) || Arrival2 > 0 );
+// assert( Abc_ObjIsCi(pNodeMin) || Arrival1 > 0 );
+// assert( Abc_ObjIsCi(pNode) || Arrival2 > 0 );
if ( Arrival1 > Arrival2 ||
Arrival1 == Arrival2 && pNodeMin->Level > pNode->Level ||
Arrival1 == Arrival2 && pNodeMin->Level == pNode->Level &&
@@ -277,8 +355,8 @@ void Abc_NtkFraigMergeClassMapped( Abc_Ntk_t * pNtk, Abc_Obj_t * pChain, int fUs
{
Arrival1 = Abc_NodeReadArrival(pNodeMin)->Worst;
Arrival2 = Abc_NodeReadArrival(pNode )->Worst;
- assert( Abc_ObjIsCi(pNodeMin) || Arrival1 > 0 );
- assert( Abc_ObjIsCi(pNode) || Arrival2 > 0 );
+// assert( Abc_ObjIsCi(pNodeMin) || Arrival1 > 0 );
+// assert( Abc_ObjIsCi(pNode) || Arrival2 > 0 );
if ( Arrival1 > Arrival2 ||
Arrival1 == Arrival2 && pNodeMin->Level > pNode->Level ||
Arrival1 == Arrival2 && pNodeMin->Level == pNode->Level &&
@@ -352,7 +430,7 @@ void Abc_NtkFraigMergeClass( Abc_Ntk_t * pNtk, Abc_Obj_t * pChain, int fUseInv,
return;
// add the invertor
- pNodeMinInv = Abc_NodeCreateInv( pNtk, pNodeMin );
+ pNodeMinInv = Abc_NtkCreateNodeInv( pNtk, pNodeMin );
// move the fanouts of the inverted nodes
for ( pNode = pListInv; pNode; pNode = pNode->pNext )
@@ -394,19 +472,36 @@ int Abc_NodeDroppingCost( Abc_Obj_t * pNode )
int Abc_NtkCleanup( Abc_Ntk_t * pNtk, int fVerbose )
{
Vec_Ptr_t * vNodes;
+ int Counter;
+ assert( Abc_NtkIsLogic(pNtk) );
+ // mark the nodes reachable from the POs
+ vNodes = Abc_NtkDfs( pNtk, 0 );
+ Counter = Abc_NtkReduceNodes( pNtk, vNodes );
+ if ( fVerbose )
+ printf( "Cleanup removed %d dangling nodes.\n", Counter );
+ Vec_PtrFree( vNodes );
+ return Counter;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Preserves the nodes collected in the array.]
+
+ Description [Returns the number of nodes removed.]
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Abc_NtkReduceNodes( Abc_Ntk_t * pNtk, Vec_Ptr_t * vNodes )
+{
Abc_Obj_t * pNode;
int i, Counter;
+ assert( Abc_NtkIsLogic(pNtk) );
// mark the nodes reachable from the POs
- vNodes = Abc_NtkDfs( pNtk, 0 );
- for ( i = 0; i < vNodes->nSize; i++ )
- {
- pNode = vNodes->pArray[i];
+ Vec_PtrForEachEntry( vNodes, pNode, i )
pNode->fMarkA = 1;
- }
- Vec_PtrFree( vNodes );
- // if it is an AIG, also mark the constant 1 node
- if ( Abc_NtkIsStrash(pNtk) )
- Abc_AigConst1(pNtk->pManFunc)->fMarkA = 1;
// remove the non-marked nodes
Counter = 0;
Abc_NtkForEachNode( pNtk, pNode, i )
@@ -416,16 +511,11 @@ int Abc_NtkCleanup( Abc_Ntk_t * pNtk, int fVerbose )
Counter++;
}
// unmark the remaining nodes
- Abc_NtkForEachNode( pNtk, pNode, i )
+ Vec_PtrForEachEntry( vNodes, pNode, i )
pNode->fMarkA = 0;
- if ( fVerbose )
- printf( "Cleanup removed %d dangling nodes.\n", Counter );
// check
if ( !Abc_NtkCheck( pNtk ) )
- {
printf( "Abc_NtkCleanup: The network check has failed.\n" );
- return -1;
- }
return Counter;
}
@@ -445,85 +535,40 @@ int Abc_NtkCleanup( Abc_Ntk_t * pNtk, int fVerbose )
***********************************************************************/
int Abc_NtkSweep( Abc_Ntk_t * pNtk, int fVerbose )
{
- Abc_Obj_t * pNode;
- int i, fConvert, nSwept, nSweptNew;
- assert( Abc_NtkIsSopLogic(pNtk) || Abc_NtkIsBddLogic(pNtk) );
- // convert to the BDD representation
- fConvert = 0;
- if ( Abc_NtkIsSopLogic(pNtk) )
- Abc_NtkSopToBdd(pNtk), fConvert = 1;
- // perform cleanup to get rid of dangling nodes
- nSwept = Abc_NtkCleanup( pNtk, 0 );
- // make the network minimum base
- Abc_NtkRemoveDupFanins(pNtk);
- Abc_NtkMinimumBase(pNtk);
- do
- {
- // sweep constants and single-input nodes
- Abc_NtkForEachNode( pNtk, pNode, i )
- if ( Abc_ObjFaninNum(pNode) < 2 )
- Abc_NodeSweep( pNode, fVerbose );
- // make the network minimum base
- Abc_NtkRemoveDupFanins(pNtk);
- Abc_NtkMinimumBase(pNtk);
- // perform final clean up (in case new danglies are created)
- nSweptNew = Abc_NtkCleanup( pNtk, 0 );
- nSwept += nSweptNew;
- }
- while ( nSweptNew );
- // conver back to BDD
- if ( fConvert )
- Abc_NtkBddToSop(pNtk);
- // report
- if ( fVerbose )
- printf( "Sweep removed %d nodes.\n", nSwept );
- // check
- if ( !Abc_NtkCheck( pNtk ) )
+ Vec_Ptr_t * vNodes;
+ Abc_Obj_t * pNode, * pFanout, * pDriver;
+ int i, nNodesOld;
+ assert( Abc_NtkIsLogic(pNtk) );
+ // convert network to BDD representation
+ if ( !Abc_NtkToBdd(pNtk) )
{
- printf( "Abc_NtkSweep: The network check has failed.\n" );
- return -1;
+ fprintf( stdout, "Converting to BDD has failed.\n" );
+ return 1;
}
- return nSwept;
-}
-
-/**Function*************************************************************
-
- Synopsis [Tranditional sweep of the network.]
-
- Description [Propagates constant and single-input node, removes dangling nodes.]
-
- SideEffects []
-
- SeeAlso []
-
-***********************************************************************/
-void Abc_NodeSweep( Abc_Obj_t * pNode, int fVerbose )
-{
- Vec_Ptr_t * vFanout = pNode->pNtk->vPtrTemp;
- Abc_Obj_t * pFanout, * pDriver;
- int i;
- assert( Abc_ObjFaninNum(pNode) < 2 );
- assert( Abc_ObjFanoutNum(pNode) > 0 );
- // iterate through the fanouts
- Abc_NodeCollectFanouts( pNode, vFanout );
- Vec_PtrForEachEntry( vFanout, pFanout, i )
+ // perform cleanup
+ nNodesOld = Abc_NtkNodeNum(pNtk);
+ Abc_NtkCleanup( pNtk, 0 );
+ // prepare nodes for sweeping
+ Abc_NtkRemoveDupFanins(pNtk);
+ Abc_NtkMinimumBase(pNtk);
+ // collect sweepable nodes
+ vNodes = Vec_PtrAlloc( 100 );
+ Abc_NtkForEachNode( pNtk, pNode, i )
+ if ( Abc_ObjFaninNum(pNode) < 2 )
+ Vec_PtrPush( vNodes, pNode );
+ // sweep the nodes
+ while ( Vec_PtrSize(vNodes) > 0 )
{
- if ( Abc_ObjIsCo(pFanout) )
- {
- if ( Abc_ObjFaninNum(pNode) == 1 )
- {
- pDriver = Abc_ObjFanin0(pNode);
- if ( Abc_ObjIsCi(pDriver) || Abc_ObjFanoutNum(pDriver) > 1 || Abc_ObjFanoutNum(pNode) > 1 )
- continue;
- // the driver is a node and its only fanout is this node
- if ( Abc_NodeIsInv(pNode) )
- pDriver->pData = Cudd_Not(pDriver->pData);
- // replace the fanin of the fanout
- Abc_ObjPatchFanin( pFanout, pNode, pDriver );
- }
+ // get any sweepable node
+ pNode = Vec_PtrPop(vNodes);
+ if ( !Abc_ObjIsNode(pNode) )
continue;
- }
- // the fanout is a regular node
+ // get any non-CO fanout of this node
+ pFanout = Abc_NodeFindNonCoFanout(pNode);
+ if ( pFanout == NULL )
+ continue;
+ assert( Abc_ObjIsNode(pFanout) );
+ // transform the function of the fanout
if ( Abc_ObjFaninNum(pNode) == 0 )
Abc_NodeConstantInput( pFanout, pNode, Abc_NodeIsConst0(pNode) );
else
@@ -534,9 +579,44 @@ void Abc_NodeSweep( Abc_Obj_t * pNode, int fVerbose )
Abc_NodeComplementInput( pFanout, pNode );
Abc_ObjPatchFanin( pFanout, pNode, pDriver );
}
+ Abc_NodeRemoveDupFanins( pFanout );
+ Abc_NodeMinimumBase( pFanout );
+ // check if the fanout should be added
+ if ( Abc_ObjFaninNum(pFanout) < 2 )
+ Vec_PtrPush( vNodes, pFanout );
+ // check if the node has other fanouts
+ if ( Abc_ObjFanoutNum(pNode) > 0 )
+ Vec_PtrPush( vNodes, pNode );
+ else
+ Abc_NtkDeleteObj_rec( pNode, 1 );
+ }
+ Vec_PtrFree( vNodes );
+ // sweep a node into its CO fanout if all of this is true:
+ // (a) this node is a single-input node
+ // (b) the driver of the node has only one fanout (this node)
+ // (c) the driver is a node
+ Abc_NtkForEachCo( pNtk, pFanout, i )
+ {
+ pNode = Abc_ObjFanin0(pFanout);
+ if ( Abc_ObjFaninNum(pNode) != 1 )
+ continue;
+ pDriver = Abc_ObjFanin0(pNode);
+ if ( !(Abc_ObjFanoutNum(pDriver) == 1 && Abc_ObjIsNode(pDriver)) )
+ continue;
+ // trasform this CO
+ if ( Abc_NodeIsInv(pNode) )
+ pDriver->pData = Cudd_Not(pDriver->pData);
+ Abc_ObjPatchFanin( pFanout, pNode, pDriver );
}
+ // perform cleanup
+ Abc_NtkCleanup( pNtk, 0 );
+ // report
+ if ( fVerbose )
+ printf( "Sweep removed %d nodes.\n", nNodesOld - Abc_NtkNodeNum(pNtk) );
+ return nNodesOld - Abc_NtkNodeNum(pNtk);
}
+
/**Function*************************************************************
Synopsis [Replaces the local function by its cofactor.]
@@ -554,7 +634,7 @@ void Abc_NodeConstantInput( Abc_Obj_t * pNode, Abc_Obj_t * pFanin, bool fConst0
DdNode * bVar, * bTemp;
int iFanin;
assert( Abc_NtkIsBddLogic(pNode->pNtk) );
- if ( (iFanin = Vec_FanFindEntry( &pNode->vFanins, pFanin->Id )) == -1 )
+ if ( (iFanin = Vec_IntFind( &pNode->vFanins, pFanin->Id )) == -1 )
{
printf( "Node %s should be among", Abc_ObjName(pFanin) );
printf( " the fanins of node %s...\n", Abc_ObjName(pNode) );
@@ -582,7 +662,7 @@ void Abc_NodeComplementInput( Abc_Obj_t * pNode, Abc_Obj_t * pFanin )
DdNode * bVar, * bCof0, * bCof1;
int iFanin;
assert( Abc_NtkIsBddLogic(pNode->pNtk) );
- if ( (iFanin = Vec_FanFindEntry( &pNode->vFanins, pFanin->Id )) == -1 )
+ if ( (iFanin = Vec_IntFind( &pNode->vFanins, pFanin->Id )) == -1 )
{
printf( "Node %s should be among", Abc_ObjName(pFanin) );
printf( " the fanins of node %s...\n", Abc_ObjName(pNode) );
@@ -597,6 +677,270 @@ void Abc_NodeComplementInput( Abc_Obj_t * pNode, Abc_Obj_t * pFanin )
Cudd_RecursiveDeref( dd, bCof1 );
}
+
+
+/**Function*************************************************************
+
+ Synopsis [Removes all objects whose trav ID is not current.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Abc_NodeRemoveNonCurrentObjects( Abc_Ntk_t * pNtk )
+{
+ Abc_Obj_t * pObj;
+ int Counter, i;
+ int fVerbose = 0;
+
+ // report on the nodes to be deleted
+ if ( fVerbose )
+ {
+ printf( "These nodes will be deleted: \n" );
+ Abc_NtkForEachObj( pNtk, pObj, i )
+ if ( !Abc_NodeIsTravIdCurrent( pObj ) )
+ {
+ printf( " " );
+ Abc_ObjPrint( stdout, pObj );
+ }
+ }
+
+ // delete the nodes
+ Counter = 0;
+ Abc_NtkForEachObj( pNtk, pObj, i )
+ if ( !Abc_NodeIsTravIdCurrent( pObj ) )
+ {
+ Abc_NtkDeleteObj( pObj );
+ Counter++;
+ }
+ return Counter;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Check if the fanin of this latch is a constant.]
+
+ Description [Returns 0/1 if constant; -1 if not a constant.]
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Abc_NtkSetTravId_rec( Abc_Obj_t * pObj )
+{
+ Abc_NodeSetTravIdCurrent(pObj);
+ if ( Abc_ObjFaninNum(pObj) == 0 )
+ return;
+ assert( Abc_ObjFaninNum(pObj) == 1 );
+ Abc_NtkSetTravId_rec( Abc_ObjFanin0(pObj) );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Check if the fanin of this latch is a constant.]
+
+ Description [Returns 0/1 if constant; -1 if not a constant.]
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Abc_NtkCheckConstant_rec( Abc_Obj_t * pObj )
+{
+ if ( Abc_ObjFaninNum(pObj) == 0 )
+ {
+ if ( !Abc_ObjIsNode(pObj) )
+ return -1;
+ if ( Abc_NodeIsConst0(pObj) )
+ return 0;
+ if ( Abc_NodeIsConst1(pObj) )
+ return 1;
+ assert( 0 );
+ return -1;
+ }
+ if ( Abc_ObjIsLatch(pObj) || Abc_ObjFaninNum(pObj) > 1 )
+ return -1;
+ if ( !Abc_ObjIsNode(pObj) || Abc_NodeIsBuf(pObj) )
+ return Abc_NtkCheckConstant_rec( Abc_ObjFanin0(pObj) );
+ if ( Abc_NodeIsInv(pObj) )
+ {
+ int RetValue = Abc_NtkCheckConstant_rec( Abc_ObjFanin0(pObj) );
+ if ( RetValue == 0 )
+ return 1;
+ if ( RetValue == 1 )
+ return 0;
+ return RetValue;
+ }
+ assert( 0 );
+ return -1;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Removes redundant latches.]
+
+ Description [The redundant latches are of two types:
+ - Latches fed by a constant which matches the init value of the latch.
+ - Latches fed by a constant which does not match the init value of the latch
+ can be all replaced by one latch.]
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Abc_NtkLatchSweep( Abc_Ntk_t * pNtk )
+{
+ Abc_Obj_t * pFanin, * pLatch, * pLatchPivot = NULL;
+ int Counter, RetValue, i;
+ Counter = 0;
+ // go through the latches
+ Abc_NtkForEachLatch( pNtk, pLatch, i )
+ {
+ // check if the latch has constant input
+ RetValue = Abc_NtkCheckConstant_rec( Abc_ObjFanin0(pLatch) );
+ if ( RetValue == -1 )
+ continue;
+ // found a latch with constant fanin
+ if ( (RetValue == 1 && Abc_LatchIsInit0(pLatch)) ||
+ (RetValue == 0 && Abc_LatchIsInit1(pLatch)) )
+ {
+ // fanin constant differs from the latch init value
+ if ( pLatchPivot == NULL )
+ {
+ pLatchPivot = pLatch;
+ continue;
+ }
+ if ( Abc_LatchInit(pLatch) != Abc_LatchInit(pLatchPivot) ) // add inverter
+ pFanin = Abc_NtkCreateNodeInv( pNtk, Abc_ObjFanout0(pLatchPivot) );
+ else
+ pFanin = Abc_ObjFanout0(pLatchPivot);
+ }
+ else
+ pFanin = Abc_ObjFanin0(Abc_ObjFanin0(pLatch));
+ // replace latch
+ Abc_ObjTransferFanout( Abc_ObjFanout0(pLatch), pFanin );
+ // delete the extra nodes
+ Abc_NtkDeleteObj_rec( Abc_ObjFanout0(pLatch), 0 );
+ Counter++;
+ }
+ return Counter;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Replaces autonumnous logic by free inputs.]
+
+ Description [Assumes that non-autonomous logic is marked with
+ the current ID.]
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Abc_NtkReplaceAutonomousLogic( Abc_Ntk_t * pNtk )
+{
+ Abc_Obj_t * pNode, * pFanin;
+ Vec_Ptr_t * vNodes;
+ int i, k, Counter;
+ // collect the nodes that feed into the reachable logic
+ vNodes = Vec_PtrAlloc( 100 );
+ Abc_NtkForEachObj( pNtk, pNode, i )
+ {
+ // skip non-visited fanins
+ if ( !Abc_NodeIsTravIdCurrent(pNode) )
+ continue;
+ // look for non-visited fanins
+ Abc_ObjForEachFanin( pNode, pFanin, k )
+ {
+ // skip visited fanins
+ if ( Abc_NodeIsTravIdCurrent(pFanin) )
+ continue;
+ // skip constants and latches fed by constants
+ if ( Abc_NtkCheckConstant_rec(pFanin) != -1 ||
+ (Abc_ObjIsBo(pFanin) && Abc_NtkCheckConstant_rec(Abc_ObjFanin0(Abc_ObjFanin0(pFanin))) != -1) )
+ {
+ Abc_NtkSetTravId_rec( pFanin );
+ continue;
+ }
+ assert( !Abc_ObjIsLatch(pFanin) );
+ Vec_PtrPush( vNodes, pFanin );
+ }
+ }
+ Vec_PtrUniqify( vNodes, Abc_ObjPointerCompare );
+ // replace these nodes by the PIs
+ Vec_PtrForEachEntry( vNodes, pNode, i )
+ {
+ pFanin = Abc_NtkCreatePi(pNtk);
+ Abc_ObjAssignName( pFanin, Abc_ObjName(pFanin), NULL );
+ Abc_NodeSetTravIdCurrent( pFanin );
+ Abc_ObjTransferFanout( pNode, pFanin );
+ }
+ Counter = Vec_PtrSize(vNodes);
+ Vec_PtrFree( vNodes );
+ return Counter;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Sequential cleanup.]
+
+ Description [Performs three tasks:
+ - Removes logic that does not feed into POs.
+ - Removes latches driven by constant values equal to the initial state.
+ - Replaces the autonomous components by additional PI variables.]
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Abc_NtkCleanupSeq( Abc_Ntk_t * pNtk, int fLatchSweep, int fAutoSweep, int fVerbose )
+{
+ Vec_Ptr_t * vNodes;
+ int Counter;
+ assert( Abc_NtkIsLogic(pNtk) );
+ // mark the nodes reachable from the POs
+ vNodes = Abc_NtkDfsSeq( pNtk );
+ Vec_PtrFree( vNodes );
+ // remove the non-marked nodes
+ Counter = Abc_NodeRemoveNonCurrentObjects( pNtk );
+ if ( fVerbose )
+ printf( "Cleanup removed %4d dangling objects.\n", Counter );
+ // check if some of the latches can be removed
+ if ( fLatchSweep )
+ {
+ Counter = Abc_NtkLatchSweep( pNtk );
+ if ( fVerbose )
+ printf( "Cleanup removed %4d redundant latches.\n", Counter );
+ }
+ // detect the autonomous components
+ if ( fAutoSweep )
+ {
+ vNodes = Abc_NtkDfsSeqReverse( pNtk );
+ Vec_PtrFree( vNodes );
+ // replace them by PIs
+ Counter = Abc_NtkReplaceAutonomousLogic( pNtk );
+ if ( fVerbose )
+ printf( "Cleanup added %4d additional PIs.\n", Counter );
+ // remove the non-marked nodes
+ Counter = Abc_NodeRemoveNonCurrentObjects( pNtk );
+ if ( fVerbose )
+ printf( "Cleanup removed %4d autonomous objects.\n", Counter );
+ }
+ // check
+ if ( !Abc_NtkCheck( pNtk ) )
+ printf( "Abc_NtkCleanupSeq: The network check has failed.\n" );
+ return 1;
+}
+
+
////////////////////////////////////////////////////////////////////////
/// END OF FILE ///
////////////////////////////////////////////////////////////////////////
diff --git a/src/base/abci/abcSymm.c b/src/base/abci/abcSymm.c
index f1e427c0..0f76065c 100644
--- a/src/base/abci/abcSymm.c
+++ b/src/base/abci/abcSymm.c
@@ -24,13 +24,13 @@
/// DECLARATIONS ///
////////////////////////////////////////////////////////////////////////
-static void Abc_NtkSymmetriesUsingBdds( Abc_Ntk_t * pNtk, int fNaive, int fVerbose );
+static void Abc_NtkSymmetriesUsingBdds( Abc_Ntk_t * pNtk, int fNaive, int fReorder, int fVerbose );
static void Abc_NtkSymmetriesUsingSandS( Abc_Ntk_t * pNtk, int fVerbose );
static void Ntk_NetworkSymmsBdd( DdManager * dd, Abc_Ntk_t * pNtk, int fNaive, int fVerbose );
static void Ntk_NetworkSymmsPrint( Abc_Ntk_t * pNtk, Extra_SymmInfo_t * pSymms );
////////////////////////////////////////////////////////////////////////
-/// FUNCTION DEFITIONS ///
+/// FUNCTION DEFINITIONS ///
////////////////////////////////////////////////////////////////////////
/**Function*************************************************************
@@ -44,10 +44,10 @@ static void Ntk_NetworkSymmsPrint( Abc_Ntk_t * pNtk, Extra_SymmInfo_t * pSymms )
SeeAlso []
***********************************************************************/
-void Abc_NtkSymmetries( Abc_Ntk_t * pNtk, int fUseBdds, int fNaive, int fVerbose )
+void Abc_NtkSymmetries( Abc_Ntk_t * pNtk, int fUseBdds, int fNaive, int fReorder, int fVerbose )
{
- if ( fUseBdds )
- Abc_NtkSymmetriesUsingBdds( pNtk, fNaive, fVerbose );
+ if ( fUseBdds || fNaive )
+ Abc_NtkSymmetriesUsingBdds( pNtk, fNaive, fReorder, fVerbose );
else
Abc_NtkSymmetriesUsingSandS( pNtk, fVerbose );
}
@@ -81,15 +81,19 @@ void Abc_NtkSymmetriesUsingSandS( Abc_Ntk_t * pNtk, int fVerbose )
SeeAlso []
***********************************************************************/
-void Abc_NtkSymmetriesUsingBdds( Abc_Ntk_t * pNtk, int fNaive, int fVerbose )
+void Abc_NtkSymmetriesUsingBdds( Abc_Ntk_t * pNtk, int fNaive, int fReorder, int fVerbose )
{
DdManager * dd;
int clk, clkBdd, clkSym;
+ int fGarbCollect = 1;
// compute the global functions
clk = clock();
- dd = Abc_NtkGlobalBdds( pNtk, 0 );
+ dd = Abc_NtkBuildGlobalBdds( pNtk, 10000000, 1, fReorder, fVerbose );
+ printf( "Shared BDD size = %d nodes.\n", Abc_NtkSizeOfGlobalBdds(pNtk) );
Cudd_AutodynDisable( dd );
+ if ( !fGarbCollect )
+ Cudd_DisableGarbageCollection( dd );
Cudd_zddVarsFromBddVars( dd, 2 );
clkBdd = clock() - clk;
// create the collapsed network
@@ -97,10 +101,10 @@ clk = clock();
Ntk_NetworkSymmsBdd( dd, pNtk, fNaive, fVerbose );
clkSym = clock() - clk;
// undo the global functions
- Abc_NtkFreeGlobalBdds( pNtk );
- Extra_StopManager( dd );
- pNtk->pManGlob = NULL;
-
+ Abc_NtkFreeGlobalBdds( pNtk, 1 );
+printf( "Statistics of BDD-based symmetry detection:\n" );
+printf( "Algorithm = %s. Reordering = %s. Garbage collection = %s.\n",
+ fNaive? "naive" : "fast", fReorder? "yes" : "no", fGarbCollect? "yes" : "no" );
PRT( "Constructing BDDs", clkBdd );
PRT( "Computing symms ", clkSym );
PRT( "TOTAL ", clkBdd + clkSym );
@@ -129,7 +133,8 @@ void Ntk_NetworkSymmsBdd( DdManager * dd, Abc_Ntk_t * pNtk, int fNaive, int fVer
// compute symmetry info for each PO
Abc_NtkForEachCo( pNtk, pNode, i )
{
- bFunc = pNtk->vFuncsGlob->pArray[i];
+// bFunc = pNtk->vFuncsGlob->pArray[i];
+ bFunc = Abc_ObjGlobalBdd( pNode );
nSupps += Cudd_SupportSize( dd, bFunc );
if ( Cudd_IsConstant(bFunc) )
continue;
diff --git a/src/base/abci/abcTiming.c b/src/base/abci/abcTiming.c
index b8524bd5..967e4617 100644
--- a/src/base/abci/abcTiming.c
+++ b/src/base/abci/abcTiming.c
@@ -37,16 +37,16 @@ struct Abc_ManTime_t_
// static functions
static Abc_ManTime_t * Abc_ManTimeStart();
static void Abc_ManTimeExpand( Abc_ManTime_t * p, int nSize, int fProgressive );
-static void Abc_NtkTimePrepare( Abc_Ntk_t * pNtk );
+void Abc_NtkTimePrepare( Abc_Ntk_t * pNtk );
-static void Abc_NodeDelayTraceArrival( Abc_Obj_t * pNode );
+void Abc_NodeDelayTraceArrival( Abc_Obj_t * pNode );
// accessing the arrival and required times of a node
static inline Abc_Time_t * Abc_NodeArrival( Abc_Obj_t * pNode ) { return pNode->pNtk->pManTime->vArrs->pArray[pNode->Id]; }
static inline Abc_Time_t * Abc_NodeRequired( Abc_Obj_t * pNode ) { return pNode->pNtk->pManTime->vReqs->pArray[pNode->Id]; }
////////////////////////////////////////////////////////////////////////
-/// FUNCTION DEFITIONS ///
+/// FUNCTION DEFINITIONS ///
////////////////////////////////////////////////////////////////////////
/**Function*************************************************************
@@ -254,9 +254,9 @@ void Abc_NtkTimeInitialize( Abc_Ntk_t * pNtk )
continue;
*pTime = pNtk->pManTime->tReqDef;
}
- // set the 0 arrival times for latches and constant nodes
+ // set the 0 arrival times for latch outputs and constant nodes
ppTimes = (Abc_Time_t **)pNtk->pManTime->vArrs->pArray;
- Abc_NtkForEachLatch( pNtk, pObj, i )
+ Abc_NtkForEachLatchOutput( pNtk, pObj, i )
{
pTime = ppTimes[pObj->Id];
pTime->Fall = pTime->Rise = pTime->Worst = 0.0;
@@ -470,9 +470,9 @@ void Abc_NtkSetNodeLevelsArrival( Abc_Ntk_t * pNtkOld )
int i;
if ( pNtkOld->pManTime == NULL )
return;
- if ( Mio_LibraryReadNand2(Abc_FrameReadLibGen(Abc_FrameGetGlobalFrame())) == NULL )
+ if ( Mio_LibraryReadNand2(Abc_FrameReadLibGen()) == NULL )
return;
- tAndDelay = Mio_LibraryReadDelayNand2Max(Abc_FrameReadLibGen(Abc_FrameGetGlobalFrame()));
+ tAndDelay = Mio_LibraryReadDelayNand2Max(Abc_FrameReadLibGen());
Abc_NtkForEachPi( pNtkOld, pNodeOld, i )
{
pNodeNew = pNodeOld->pCopy;
@@ -595,13 +595,12 @@ void Abc_NodeDelayTraceArrival( Abc_Obj_t * pNode )
// start the arrival time of the node
pTimeOut = Abc_NodeArrival(pNode);
- pTimeOut->Rise = pTimeOut->Fall = 0;
+ pTimeOut->Rise = pTimeOut->Fall = -ABC_INFINITY;
// go through the pins of the gate
pPin = Mio_GateReadPins(pNode->pData);
Abc_ObjForEachFanin( pNode, pFanin, i )
{
pTimeIn = Abc_NodeArrival(pFanin);
- assert( pTimeIn->Worst != -ABC_INFINITY );
// get the interesting parameters of this pin
PinPhase = Mio_PinReadPhase(pPin);
tDelayBlockRise = (float)Mio_PinReadDelayBlockRise( pPin );
@@ -631,38 +630,133 @@ void Abc_NodeDelayTraceArrival( Abc_Obj_t * pNode )
/**Function*************************************************************
- Synopsis [Prepares the AIG for the comptuation of required levels.]
+ Synopsis [Computes the level of the node using its fanin levels.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Abc_ObjLevelNew( Abc_Obj_t * pObj )
+{
+ Abc_Obj_t * pFanin;
+ int i, Level = 0;
+ Abc_ObjForEachFanin( pObj, pFanin, i )
+ Level = ABC_MAX( Level, Abc_ObjLevel(pFanin) );
+ return Level + 1;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Computes the reverse level of the node using its fanout levels.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Abc_ObjReverseLevelNew( Abc_Obj_t * pObj )
+{
+ Abc_Obj_t * pFanout;
+ int i, LevelCur, Level = 0;
+ Abc_ObjForEachFanout( pObj, pFanout, i )
+ {
+ LevelCur = Abc_ObjReverseLevel( pFanout );
+ Level = ABC_MAX( Level, LevelCur );
+ }
+ return Level + 1;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Returns required level of the node.]
+
+ Description [Converts the reverse levels of the node into its required
+ level as follows: ReqLevel(Node) = MaxLevels(Ntk) + 1 - LevelR(Node).]
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Abc_ObjRequiredLevel( Abc_Obj_t * pObj )
+{
+ Abc_Ntk_t * pNtk = pObj->pNtk;
+ assert( pNtk->vLevelsR );
+ return pNtk->LevelMax + 1 - Abc_ObjReverseLevel(pObj);
+}
+
+/**Function*************************************************************
+
+ Synopsis [Returns the reverse level of the node.]
+
+ Description [The reverse level is the level of the node in reverse
+ topological order, starting from the COs.]
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Abc_ObjReverseLevel( Abc_Obj_t * pObj )
+{
+ Abc_Ntk_t * pNtk = pObj->pNtk;
+ assert( pNtk->vLevelsR );
+ Vec_IntFillExtra( pNtk->vLevelsR, pObj->Id + 1, 0 );
+ return Vec_IntEntry(pNtk->vLevelsR, pObj->Id);
+}
+
+/**Function*************************************************************
+
+ Synopsis [Sets the reverse level of the node.]
+
+ Description [The reverse level is the level of the node in reverse
+ topological order, starting from the COs.]
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Abc_ObjSetReverseLevel( Abc_Obj_t * pObj, int LevelR )
+{
+ Abc_Ntk_t * pNtk = pObj->pNtk;
+ assert( pNtk->vLevelsR );
+ Vec_IntFillExtra( pNtk->vLevelsR, pObj->Id + 1, 0 );
+ Vec_IntWriteEntry( pNtk->vLevelsR, pObj->Id, LevelR );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Prepares for the computation of required levels.]
Description [This procedure should be called before the required times
are used. It starts internal data structures, which records the level
- from the COs of the AIG nodes in reverse topologogical order.]
+ from the COs of the network nodes in reverse topologogical order.]
SideEffects []
SeeAlso []
***********************************************************************/
-void Abc_NtkStartReverseLevels( Abc_Ntk_t * pNtk )
+void Abc_NtkStartReverseLevels( Abc_Ntk_t * pNtk, int nMaxLevelIncrease )
{
Vec_Ptr_t * vNodes;
- Abc_Obj_t * pObj, * pFanout;
- int i, k, nLevelsCur;
- assert( Abc_NtkIsStrash(pNtk) );
+ Abc_Obj_t * pObj;
+ int i;
// remember the maximum number of direct levels
- pNtk->LevelMax = Abc_AigGetLevelNum(pNtk);
+ pNtk->LevelMax = Abc_NtkLevel(pNtk) + nMaxLevelIncrease;
// start the reverse levels
pNtk->vLevelsR = Vec_IntAlloc( 0 );
- Vec_IntFill( pNtk->vLevelsR, Abc_NtkObjNumMax(pNtk), 0 );
+ Vec_IntFill( pNtk->vLevelsR, 1 + Abc_NtkObjNumMax(pNtk), 0 );
// compute levels in reverse topological order
vNodes = Abc_NtkDfsReverse( pNtk );
Vec_PtrForEachEntry( vNodes, pObj, i )
- {
- nLevelsCur = 0;
- Abc_ObjForEachFanout( pObj, pFanout, k )
- if ( nLevelsCur < Vec_IntEntry(pNtk->vLevelsR, pFanout->Id) )
- nLevelsCur = Vec_IntEntry(pNtk->vLevelsR, pFanout->Id);
- Vec_IntWriteEntry( pNtk->vLevelsR, pObj->Id, nLevelsCur + 1 );
- }
+ Abc_ObjSetReverseLevel( pObj, Abc_ObjReverseLevelNew(pObj) );
Vec_PtrFree( vNodes );
}
@@ -688,64 +782,120 @@ void Abc_NtkStopReverseLevels( Abc_Ntk_t * pNtk )
/**Function*************************************************************
- Synopsis [Sets the reverse level of the node.]
+ Synopsis [Incrementally updates level of the nodes.]
- Description [The reverse level is the level of the node in reverse
- topological order, starting from the COs.]
+ Description []
SideEffects []
SeeAlso []
***********************************************************************/
-void Abc_NodeSetReverseLevel( Abc_Obj_t * pObj, int LevelR )
+void Abc_NtkUpdateLevel( Abc_Obj_t * pObjNew, Vec_Vec_t * vLevels )
{
- Abc_Ntk_t * pNtk = pObj->pNtk;
- assert( Abc_NtkIsStrash(pNtk) );
- assert( pNtk->vLevelsR );
- Vec_IntFillExtra( pNtk->vLevelsR, pObj->Id + 1, 0 );
- Vec_IntWriteEntry( pNtk->vLevelsR, pObj->Id, LevelR );
+ Abc_Obj_t * pFanout, * pTemp;
+ int LevelOld, Lev, k, m;
+ // check if level has changed
+ LevelOld = Abc_ObjLevel(pObjNew);
+ if ( LevelOld == Abc_ObjLevelNew(pObjNew) )
+ return;
+ // start the data structure for level update
+ // we cannot fail to visit a node when using this structure because the
+ // nodes are stored by their _old_ levels, which are assumed to be correct
+ Vec_VecClear( vLevels );
+ Vec_VecPush( vLevels, LevelOld, pObjNew );
+ pObjNew->fMarkA = 1;
+ // recursively update level
+ Vec_VecForEachEntryStart( vLevels, pTemp, Lev, k, LevelOld )
+ {
+ pTemp->fMarkA = 0;
+ assert( Abc_ObjLevel(pTemp) == Lev );
+ Abc_ObjSetLevel( pTemp, Abc_ObjLevelNew(pTemp) );
+ // if the level did not change, no need to check the fanout levels
+ if ( Abc_ObjLevel(pTemp) == Lev )
+ continue;
+ // schedule fanout for level update
+ Abc_ObjForEachFanout( pTemp, pFanout, m )
+ {
+ if ( !Abc_ObjIsCo(pFanout) && !pFanout->fMarkA )
+ {
+ assert( Abc_ObjLevel(pFanout) >= Lev );
+ Vec_VecPush( vLevels, Abc_ObjLevel(pFanout), pFanout );
+ pFanout->fMarkA = 1;
+ }
+ }
+ }
}
/**Function*************************************************************
- Synopsis [Returns the reverse level of the node.]
+ Synopsis [Incrementally updates level of the nodes.]
- Description [The reverse level is the level of the node in reverse
- topological order, starting from the COs.]
+ Description []
SideEffects []
SeeAlso []
***********************************************************************/
-int Abc_NodeReadReverseLevel( Abc_Obj_t * pObj )
+void Abc_NtkUpdateReverseLevel( Abc_Obj_t * pObjNew, Vec_Vec_t * vLevels )
{
- Abc_Ntk_t * pNtk = pObj->pNtk;
- assert( Abc_NtkIsStrash(pNtk) );
- assert( pNtk->vLevelsR );
- Vec_IntFillExtra( pNtk->vLevelsR, pObj->Id + 1, 0 );
- return Vec_IntEntry(pNtk->vLevelsR, pObj->Id);
+ Abc_Obj_t * pFanin, * pTemp;
+ int LevelOld, LevFanin, Lev, k, m;
+ // check if level has changed
+ LevelOld = Abc_ObjReverseLevel(pObjNew);
+ if ( LevelOld == Abc_ObjReverseLevelNew(pObjNew) )
+ return;
+ // start the data structure for level update
+ // we cannot fail to visit a node when using this structure because the
+ // nodes are stored by their _old_ levels, which are assumed to be correct
+ Vec_VecClear( vLevels );
+ Vec_VecPush( vLevels, LevelOld, pObjNew );
+ pObjNew->fMarkA = 1;
+ // recursively update level
+ Vec_VecForEachEntryStart( vLevels, pTemp, Lev, k, LevelOld )
+ {
+ pTemp->fMarkA = 0;
+ LevelOld = Abc_ObjReverseLevel(pTemp);
+ assert( LevelOld == Lev );
+ Abc_ObjSetReverseLevel( pTemp, Abc_ObjReverseLevelNew(pTemp) );
+ // if the level did not change, no need to check the fanout levels
+ if ( Abc_ObjReverseLevel(pTemp) == Lev )
+ continue;
+ // schedule fanins for level update
+ Abc_ObjForEachFanin( pTemp, pFanin, m )
+ {
+ if ( !Abc_ObjIsCi(pFanin) && !pFanin->fMarkA )
+ {
+ LevFanin = Abc_ObjReverseLevel( pFanin );
+ assert( LevFanin >= Lev );
+ Vec_VecPush( vLevels, LevFanin, pFanin );
+ pFanin->fMarkA = 1;
+ }
+ }
+ }
}
/**Function*************************************************************
- Synopsis [Returns required level of the node.]
+ Synopsis [Replaces the node and incrementally updates levels.]
- Description [Converts the reverse levels of the node into its required
- level as follows: ReqLevel(Node) = MaxLevels(Ntk) + 1 - LevelR(Node).]
+ Description []
SideEffects []
SeeAlso []
***********************************************************************/
-int Abc_NodeReadRequiredLevel( Abc_Obj_t * pObj )
+void Abc_NtkUpdate( Abc_Obj_t * pObj, Abc_Obj_t * pObjNew, Vec_Vec_t * vLevels )
{
- Abc_Ntk_t * pNtk = pObj->pNtk;
- assert( Abc_NtkIsStrash(pNtk) );
- assert( pNtk->vLevelsR );
- return pNtk->LevelMax + 1 - Vec_IntEntry(pNtk->vLevelsR, pObj->Id);
+ // replace the old node by the new node
+ pObjNew->Level = pObj->Level;
+ Abc_ObjReplace( pObj, pObjNew );
+ // update the level of the node
+ Abc_NtkUpdateLevel( pObjNew, vLevels );
+ Abc_ObjSetReverseLevel( pObjNew, 0 );
+ Abc_NtkUpdateReverseLevel( pObjNew, vLevels );
}
////////////////////////////////////////////////////////////////////////
diff --git a/src/base/abci/abcUnate.c b/src/base/abci/abcUnate.c
new file mode 100644
index 00000000..20804d19
--- /dev/null
+++ b/src/base/abci/abcUnate.c
@@ -0,0 +1,155 @@
+/**CFile****************************************************************
+
+ FileName [abcUnate.c]
+
+ SystemName [ABC: Logic synthesis and verification system.]
+
+ PackageName [Network and node package.]
+
+ Synopsis []
+
+ Author [Alan Mishchenko]
+
+ Affiliation [UC Berkeley]
+
+ Date [Ver. 1.0. Started - June 20, 2005.]
+
+ Revision [$Id: abcUnate.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "abc.h"
+
+////////////////////////////////////////////////////////////////////////
+/// DECLARATIONS ///
+////////////////////////////////////////////////////////////////////////
+
+static void Abc_NtkPrintUnateBdd( Abc_Ntk_t * pNtk, int fUseNaive, int fVerbose );
+static void Abc_NtkPrintUnateSat( Abc_Ntk_t * pNtk, int fVerbose );
+
+////////////////////////////////////////////////////////////////////////
+/// FUNCTION DEFINITIONS ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+ Synopsis [Detects unate variables of the multi-output function.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Abc_NtkPrintUnate( Abc_Ntk_t * pNtk, int fUseBdds, int fUseNaive, int fVerbose )
+{
+ if ( fUseBdds || fUseNaive )
+ Abc_NtkPrintUnateBdd( pNtk, fUseNaive, fVerbose );
+ else
+ Abc_NtkPrintUnateSat( pNtk, fVerbose );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Detects unate variables using BDDs.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Abc_NtkPrintUnateBdd( Abc_Ntk_t * pNtk, int fUseNaive, int fVerbose )
+{
+ Abc_Obj_t * pNode;
+ Extra_UnateInfo_t * p;
+ DdManager * dd; // the BDD manager used to hold shared BDDs
+// DdNode ** pbGlobal; // temporary storage for global BDDs
+ int TotalSupps = 0;
+ int TotalUnate = 0;
+ int i, clk = clock();
+ int clkBdd, clkUnate;
+
+ // compute the global BDDs
+ dd = Abc_NtkBuildGlobalBdds(pNtk, 10000000, 1, 1, fVerbose);
+ if ( dd == NULL )
+ return;
+clkBdd = clock() - clk;
+
+ // get information about the network
+// dd = pNtk->pManGlob;
+// dd = Abc_NtkGlobalBddMan( pNtk );
+// pbGlobal = (DdNode **)Vec_PtrArray( pNtk->vFuncsGlob );
+
+ // print the size of the BDDs
+ printf( "Shared BDD size = %6d nodes.\n", Cudd_ReadKeys(dd) - Cudd_ReadDead(dd) );
+
+ // perform naive BDD-based computation
+ if ( fUseNaive )
+ {
+ Abc_NtkForEachCo( pNtk, pNode, i )
+ {
+// p = Extra_UnateComputeSlow( dd, pbGlobal[i] );
+ p = Extra_UnateComputeSlow( dd, Abc_ObjGlobalBdd(pNode) );
+ if ( fVerbose )
+ Extra_UnateInfoPrint( p );
+ TotalSupps += p->nVars;
+ TotalUnate += p->nUnate;
+ Extra_UnateInfoDissolve( p );
+ }
+ }
+ // perform smart BDD-based computation
+ else
+ {
+ // create ZDD variables in the manager
+ Cudd_zddVarsFromBddVars( dd, 2 );
+ Abc_NtkForEachCo( pNtk, pNode, i )
+ {
+// p = Extra_UnateComputeFast( dd, pbGlobal[i] );
+ p = Extra_UnateComputeFast( dd, Abc_ObjGlobalBdd(pNode) );
+ if ( fVerbose )
+ Extra_UnateInfoPrint( p );
+ TotalSupps += p->nVars;
+ TotalUnate += p->nUnate;
+ Extra_UnateInfoDissolve( p );
+ }
+ }
+clkUnate = clock() - clk - clkBdd;
+
+ // print stats
+ printf( "Ins/Outs = %4d/%4d. Total supp = %5d. Total unate = %5d.\n",
+ Abc_NtkCiNum(pNtk), Abc_NtkCoNum(pNtk), TotalSupps, TotalUnate );
+ PRT( "Glob BDDs", clkBdd );
+ PRT( "Unateness", clkUnate );
+ PRT( "Total ", clock() - clk );
+
+ // deref the PO functions
+// Abc_NtkFreeGlobalBdds( pNtk );
+ // stop the global BDD manager
+// Extra_StopManager( pNtk->pManGlob );
+// pNtk->pManGlob = NULL;
+ Abc_NtkFreeGlobalBdds( pNtk, 1 );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Detects unate variables using SAT.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Abc_NtkPrintUnateSat( Abc_Ntk_t * pNtk, int fVerbose )
+{
+}
+
+////////////////////////////////////////////////////////////////////////
+/// END OF FILE ///
+////////////////////////////////////////////////////////////////////////
+
+
diff --git a/src/base/abci/abcUnreach.c b/src/base/abci/abcUnreach.c
index abc02cc3..ea0a4cd2 100644
--- a/src/base/abci/abcUnreach.c
+++ b/src/base/abci/abcUnreach.c
@@ -30,7 +30,7 @@ static DdNode * Abc_NtkComputeUnreachable( DdManager * dd, Abc_Ntk_t * pNtk,
static Abc_Ntk_t * Abc_NtkConstructExdc ( DdManager * dd, Abc_Ntk_t * pNtk, DdNode * bUnreach );
////////////////////////////////////////////////////////////////////////
-/// FUNCTION DEFITIONS ///
+/// FUNCTION DEFINITIONS ///
////////////////////////////////////////////////////////////////////////
/**Function*************************************************************
@@ -58,11 +58,11 @@ int Abc_NtkExtractSequentialDcs( Abc_Ntk_t * pNtk, bool fVerbose )
}
// compute the global BDDs of the latches
- dd = Abc_NtkGlobalBdds( pNtk, 1 );
+ dd = Abc_NtkBuildGlobalBdds( pNtk, 10000000, 1, 1, fVerbose );
if ( dd == NULL )
return 0;
if ( fVerbose )
- printf( "The shared BDD size is %d nodes.\n", Cudd_ReadKeys(dd) - Cudd_ReadDead(dd) );
+ printf( "Shared BDD size = %6d nodes.\n", Cudd_ReadKeys(dd) - Cudd_ReadDead(dd) );
// create the transition relation (dereferenced global BDDs)
bRelation = Abc_NtkTransitionRelation( dd, pNtk, fVerbose ); Cudd_Ref( bRelation );
@@ -87,13 +87,15 @@ int Abc_NtkExtractSequentialDcs( Abc_Ntk_t * pNtk, bool fVerbose )
// allocate ZDD variables
Cudd_zddVarsFromBddVars( dd, 2 );
// create the EXDC network representing the unreachable states
+ if ( pNtk->pExdc )
+ Abc_NtkDelete( pNtk->pExdc );
pNtk->pExdc = Abc_NtkConstructExdc( dd, pNtk, bUnreach );
Cudd_RecursiveDeref( dd, bUnreach );
Extra_StopManager( dd );
- pNtk->pManGlob = NULL;
+// pNtk->pManGlob = NULL;
// make sure that everything is okay
- if ( !Abc_NtkCheck( pNtk->pExdc ) )
+ if ( pNtk->pExdc && !Abc_NtkCheck( pNtk->pExdc ) )
{
printf( "Abc_NtkExtractSequentialDcs: The network check has failed.\n" );
Abc_NtkDelete( pNtk->pExdc );
@@ -135,13 +137,15 @@ DdNode * Abc_NtkTransitionRelation( DdManager * dd, Abc_Ntk_t * pNtk, int fVerbo
Abc_NtkForEachLatch( pNtk, pNode, i )
{
bVar = Cudd_bddIthVar( dd, Abc_NtkCiNum(pNtk) + i );
- bProd = Cudd_bddXnor( dd, bVar, pNtk->vFuncsGlob->pArray[i] ); Cudd_Ref( bProd );
+// bProd = Cudd_bddXnor( dd, bVar, pNtk->vFuncsGlob->pArray[i] ); Cudd_Ref( bProd );
+ bProd = Cudd_bddXnor( dd, bVar, Abc_ObjGlobalBdd(Abc_ObjFanin0(pNode)) ); Cudd_Ref( bProd );
bRel = Cudd_bddAnd( dd, bTemp = bRel, bProd ); Cudd_Ref( bRel );
Cudd_RecursiveDeref( dd, bTemp );
Cudd_RecursiveDeref( dd, bProd );
}
// free the global BDDs
- Abc_NtkFreeGlobalBdds( pNtk );
+// Abc_NtkFreeGlobalBdds( pNtk );
+ Abc_NtkFreeGlobalBdds( pNtk, 0 );
// quantify the PI variables
bInputs = Extra_bddComputeRangeCube( dd, 0, Abc_NtkPiNum(pNtk) ); Cudd_Ref( bInputs );
@@ -217,7 +221,7 @@ DdNode * Abc_NtkComputeUnreachable( DdManager * dd, Abc_Ntk_t * pNtk, DdNode * b
{
DdNode * bRelation, * bReached, * bCubeCs;
DdNode * bCurrent, * bNext, * bTemp;
- int nIters;
+ int nIters, nMints;
// perform reachability analisys
bCurrent = bInitial; Cudd_Ref( bCurrent );
@@ -254,9 +258,9 @@ DdNode * Abc_NtkComputeUnreachable( DdManager * dd, Abc_Ntk_t * pNtk, DdNode * b
// report the stats
if ( fVerbose )
{
- fprintf( stdout, "Reachability analysis completed in %d iterations.\n", nIters );
- fprintf( stdout, "The number of minterms in the reachable state set = %d.\n",
- (int)Cudd_CountMinterm(dd, bReached, Abc_NtkLatchNum(pNtk) ) );
+ nMints = (int)Cudd_CountMinterm(dd, bReached, Abc_NtkLatchNum(pNtk) );
+ fprintf( stdout, "Reachability analysis completed in %d iterations.\n", nIters );
+ fprintf( stdout, "The number of minterms in the reachable state set = %d. (%6.2f %%)\n", nMints, 100.0*nMints/(1<<Abc_NtkLatchNum(pNtk)) );
}
//PRB( dd, bReached );
Cudd_Deref( bReached );
@@ -282,15 +286,19 @@ Abc_Ntk_t * Abc_NtkConstructExdc( DdManager * dd, Abc_Ntk_t * pNtk, DdNode * bUn
int i;
// start the new network
- pNtkNew = Abc_NtkAlloc( ABC_TYPE_LOGIC, ABC_FUNC_BDD );
+ pNtkNew = Abc_NtkAlloc( ABC_NTK_LOGIC, ABC_FUNC_BDD, 1 );
+ pNtkNew->pName = Extra_UtilStrsav( "exdc" );
+ pNtkNew->pSpec = NULL;
+
// create PIs corresponding to LOs
- Abc_NtkForEachLatch( pNtk, pNode, i )
- pNode->pCopy = Abc_NtkCreatePi(pNtkNew);
+ Abc_NtkForEachLatchOutput( pNtk, pNode, i )
+ Abc_ObjAssignName( pNode->pCopy = Abc_NtkCreatePi(pNtkNew), Abc_ObjName(pNode), NULL );
+ // cannot ADD POs here because pLatch->pCopy point to the PIs
// create a new node
pNodeNew = Abc_NtkCreateNode(pNtkNew);
// add the fanins corresponding to latch outputs
- Abc_NtkForEachLatch( pNtk, pNode, i )
+ Abc_NtkForEachLatchOutput( pNtk, pNode, i )
Abc_ObjAddFanin( pNodeNew, pNode->pCopy );
// create the logic function
@@ -304,28 +312,34 @@ Abc_Ntk_t * Abc_NtkConstructExdc( DdManager * dd, Abc_Ntk_t * pNtk, DdNode * bUn
free( pPermute );
Abc_NodeMinimumBase( pNodeNew );
- // make the new node drive all the COs
- Abc_NtkForEachCo( pNtk, pNode, i )
- Abc_ObjAddFanin( Abc_NtkCreatePo(pNtkNew), pNodeNew );
+ // for each CO, create PO (skip POs equal to CIs because of name conflict)
+ Abc_NtkForEachPo( pNtk, pNode, i )
+ if ( !Abc_ObjIsCi(Abc_ObjFanin0(pNode)) )
+ Abc_ObjAssignName( pNode->pCopy = Abc_NtkCreatePo(pNtkNew), Abc_ObjName(pNode), NULL );
+ Abc_NtkForEachLatchInput( pNtk, pNode, i )
+ Abc_ObjAssignName( pNode->pCopy = Abc_NtkCreatePo(pNtkNew), Abc_ObjName(pNode), NULL );
- // store the PI names of the EXDC network
- Abc_NtkForEachLatch( pNtk, pNode, i )
- Abc_NtkLogicStoreName( Abc_NtkPi(pNtkNew,i), Abc_ObjName(pNode) );
- // store the PO names of the EXDC network
+ // link to the POs of the network
Abc_NtkForEachPo( pNtk, pNode, i )
- Abc_NtkLogicStoreName( Abc_NtkPo(pNtkNew,i), Abc_ObjName(pNode) );
- Abc_NtkForEachLatch( pNtk, pNode, i )
- Abc_NtkLogicStoreName( Abc_NtkCo(pNtkNew,Abc_NtkPoNum(pNtk) + i), Abc_ObjNameSuffix(pNode, "_in") );
+ if ( !Abc_ObjIsCi(Abc_ObjFanin0(pNode)) )
+ Abc_ObjAddFanin( pNode->pCopy, pNodeNew );
+ Abc_NtkForEachLatchInput( pNtk, pNode, i )
+ Abc_ObjAddFanin( pNode->pCopy, pNodeNew );
- // make the network minimum base
- Abc_NtkMinimumBase( pNtkNew );
+ // remove the extra nodes
+ Abc_AigCleanup( pNtkNew->pManFunc );
// fix the problem with complemented and duplicated CO edges
Abc_NtkLogicMakeSimpleCos( pNtkNew, 0 );
// transform the network to the SOP representation
- Abc_NtkBddToSop( pNtkNew );
+ if ( !Abc_NtkBddToSop( pNtkNew, 0 ) )
+ {
+ printf( "Abc_NtkConstructExdc(): Converting to SOPs has failed.\n" );
+ return NULL;
+ }
return pNtkNew;
+// return NULL;
}
////////////////////////////////////////////////////////////////////////
diff --git a/src/base/abci/abcVerify.c b/src/base/abci/abcVerify.c
index 55d6cf7d..9c9bbcfd 100644
--- a/src/base/abci/abcVerify.c
+++ b/src/base/abci/abcVerify.c
@@ -20,13 +20,17 @@
#include "abc.h"
#include "fraig.h"
+#include "sim.h"
////////////////////////////////////////////////////////////////////////
/// DECLARATIONS ///
////////////////////////////////////////////////////////////////////////
+static void Abc_NtkVerifyReportError( Abc_Ntk_t * pNtk1, Abc_Ntk_t * pNtk2, int * pModel );
+extern void Abc_NtkVerifyReportErrorSeq( Abc_Ntk_t * pNtk1, Abc_Ntk_t * pNtk2, int * pModel, int nFrames );
+
////////////////////////////////////////////////////////////////////////
-/// FUNCTION DEFITIONS ///
+/// FUNCTION DEFINITIONS ///
////////////////////////////////////////////////////////////////////////
/**Function*************************************************************
@@ -40,27 +44,32 @@
SeeAlso []
***********************************************************************/
-void Abc_NtkCecSat( Abc_Ntk_t * pNtk1, Abc_Ntk_t * pNtk2 )
+void Abc_NtkCecSat( Abc_Ntk_t * pNtk1, Abc_Ntk_t * pNtk2, int nConfLimit, int nInsLimit )
{
+ extern Abc_Ntk_t * Abc_NtkMulti( Abc_Ntk_t * pNtk, int nThresh, int nFaninMax, int fCnf, int fMulti, int fSimple, int fFactor );
Abc_Ntk_t * pMiter;
Abc_Ntk_t * pCnf;
int RetValue;
// get the miter of the two networks
- pMiter = Abc_NtkMiter( pNtk1, pNtk2, 1 );
+ pMiter = Abc_NtkMiter( pNtk1, pNtk2, 1, 0 );
if ( pMiter == NULL )
{
printf( "Miter computation has failed.\n" );
return;
}
RetValue = Abc_NtkMiterIsConstant( pMiter );
- if ( RetValue == 1 )
+ if ( RetValue == 0 )
{
- Abc_NtkDelete( pMiter );
printf( "Networks are NOT EQUIVALENT after structural hashing.\n" );
+ // report the error
+ pMiter->pModel = Abc_NtkVerifyGetCleanModel( pMiter, 1 );
+ Abc_NtkVerifyReportError( pNtk1, pNtk2, pMiter->pModel );
+ FREE( pMiter->pModel );
+ Abc_NtkDelete( pMiter );
return;
}
- if ( RetValue == 0 )
+ if ( RetValue == 1 )
{
Abc_NtkDelete( pMiter );
printf( "Networks are equivalent after structural hashing.\n" );
@@ -68,7 +77,7 @@ void Abc_NtkCecSat( Abc_Ntk_t * pNtk1, Abc_Ntk_t * pNtk2 )
}
// convert the miter into a CNF
- pCnf = Abc_NtkRenode( pMiter, 0, 100, 1, 0, 0 );
+ pCnf = Abc_NtkMulti( pMiter, 0, 100, 1, 0, 0, 0 );
Abc_NtkDelete( pMiter );
if ( pCnf == NULL )
{
@@ -77,10 +86,16 @@ void Abc_NtkCecSat( Abc_Ntk_t * pNtk1, Abc_Ntk_t * pNtk2 )
}
// solve the CNF using the SAT solver
- if ( Abc_NtkMiterSat( pCnf, 0 ) )
+ RetValue = Abc_NtkMiterSat( pCnf, (sint64)nConfLimit, (sint64)nInsLimit, 0, NULL, NULL );
+ if ( RetValue == -1 )
+ printf( "Networks are undecided (SAT solver timed out).\n" );
+ else if ( RetValue == 0 )
printf( "Networks are NOT EQUIVALENT after SAT.\n" );
else
printf( "Networks are equivalent after SAT.\n" );
+ if ( pCnf->pModel )
+ Abc_NtkVerifyReportError( pNtk1, pNtk2, pCnf->pModel );
+ FREE( pCnf->pModel );
Abc_NtkDelete( pCnf );
}
@@ -96,52 +111,329 @@ void Abc_NtkCecSat( Abc_Ntk_t * pNtk1, Abc_Ntk_t * pNtk2 )
SeeAlso []
***********************************************************************/
-void Abc_NtkCecFraig( Abc_Ntk_t * pNtk1, Abc_Ntk_t * pNtk2, int fVerbose )
+void Abc_NtkCecFraig( Abc_Ntk_t * pNtk1, Abc_Ntk_t * pNtk2, int nSeconds, int fVerbose )
{
- Fraig_Params_t Params;
+ Prove_Params_t Params, * pParams = &Params;
+// Fraig_Params_t Params;
+// Fraig_Man_t * pMan;
Abc_Ntk_t * pMiter;
- Abc_Ntk_t * pFraig;
int RetValue;
// get the miter of the two networks
- pMiter = Abc_NtkMiter( pNtk1, pNtk2, 1 );
+ pMiter = Abc_NtkMiter( pNtk1, pNtk2, 1, 0 );
if ( pMiter == NULL )
{
printf( "Miter computation has failed.\n" );
return;
}
RetValue = Abc_NtkMiterIsConstant( pMiter );
+ if ( RetValue == 0 )
+ {
+ printf( "Networks are NOT EQUIVALENT after structural hashing.\n" );
+ // report the error
+ pMiter->pModel = Abc_NtkVerifyGetCleanModel( pMiter, 1 );
+ Abc_NtkVerifyReportError( pNtk1, pNtk2, pMiter->pModel );
+ FREE( pMiter->pModel );
+ Abc_NtkDelete( pMiter );
+ return;
+ }
if ( RetValue == 1 )
{
+ printf( "Networks are equivalent after structural hashing.\n" );
Abc_NtkDelete( pMiter );
- printf( "Networks are NOT EQUIVALENT after structural hashing.\n" );
return;
}
+/*
+ // convert the miter into a FRAIG
+ Fraig_ParamsSetDefault( &Params );
+ Params.fVerbose = fVerbose;
+ Params.nSeconds = nSeconds;
+// Params.fFuncRed = 0;
+// Params.nPatsRand = 0;
+// Params.nPatsDyna = 0;
+ pMan = Abc_NtkToFraig( pMiter, &Params, 0, 0 );
+ Fraig_ManProveMiter( pMan );
+
+ // analyze the result
+ RetValue = Fraig_ManCheckMiter( pMan );
+ // report the result
+ if ( RetValue == -1 )
+ printf( "Networks are undecided (SAT solver timed out on the final miter).\n" );
+ else if ( RetValue == 1 )
+ printf( "Networks are equivalent after fraiging.\n" );
+ else if ( RetValue == 0 )
+ {
+ printf( "Networks are NOT EQUIVALENT after fraiging.\n" );
+ Abc_NtkVerifyReportError( pNtk1, pNtk2, Fraig_ManReadModel(pMan) );
+ }
+ else assert( 0 );
+ // delete the fraig manager
+ Fraig_ManFree( pMan );
+ // delete the miter
+ Abc_NtkDelete( pMiter );
+*/
+ // solve the CNF using the SAT solver
+ Prove_ParamsSetDefault( pParams );
+ pParams->nItersMax = 5;
+// RetValue = Abc_NtkMiterProve( &pMiter, pParams );
+// pParams->fVerbose = 1;
+ RetValue = Abc_NtkIvyProve( &pMiter, pParams );
+ if ( RetValue == -1 )
+ printf( "Networks are undecided (resource limits is reached).\n" );
+ else if ( RetValue == 0 )
+ {
+ int * pSimInfo = Abc_NtkVerifySimulatePattern( pMiter, pMiter->pModel );
+ if ( pSimInfo[0] != 1 )
+ printf( "ERROR in Abc_NtkMiterProve(): Generated counter-example is invalid.\n" );
+ else
+ printf( "Networks are NOT EQUIVALENT.\n" );
+ free( pSimInfo );
+ }
+ else
+ printf( "Networks are equivalent.\n" );
+ if ( pMiter->pModel )
+ Abc_NtkVerifyReportError( pNtk1, pNtk2, pMiter->pModel );
+ Abc_NtkDelete( pMiter );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Verifies sequential equivalence by fraiging followed by SAT.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Abc_NtkCecFraigPart( Abc_Ntk_t * pNtk1, Abc_Ntk_t * pNtk2, int nSeconds, int nPartSize, int fVerbose )
+{
+ extern int Cmd_CommandExecute( void * pAbc, char * sCommand );
+ extern void * Abc_FrameGetGlobalFrame();
+
+ Prove_Params_t Params, * pParams = &Params;
+ Abc_Ntk_t * pMiter, * pMiterPart;
+ Abc_Obj_t * pObj;
+ int i, RetValue, Status, nOutputs;
+
+ // solve the CNF using the SAT solver
+ Prove_ParamsSetDefault( pParams );
+ pParams->nItersMax = 5;
+ // pParams->fVerbose = 1;
+
+ assert( nPartSize > 0 );
+
+ // get the miter of the two networks
+ pMiter = Abc_NtkMiter( pNtk1, pNtk2, 1, nPartSize );
+ if ( pMiter == NULL )
+ {
+ printf( "Miter computation has failed.\n" );
+ return;
+ }
+ RetValue = Abc_NtkMiterIsConstant( pMiter );
if ( RetValue == 0 )
{
+ printf( "Networks are NOT EQUIVALENT after structural hashing.\n" );
+ // report the error
+ pMiter->pModel = Abc_NtkVerifyGetCleanModel( pMiter, 1 );
+ Abc_NtkVerifyReportError( pNtk1, pNtk2, pMiter->pModel );
+ FREE( pMiter->pModel );
Abc_NtkDelete( pMiter );
+ return;
+ }
+ if ( RetValue == 1 )
+ {
printf( "Networks are equivalent after structural hashing.\n" );
+ Abc_NtkDelete( pMiter );
return;
}
- // convert the miter into a FRAIG
- Fraig_ParamsSetDefault( &Params );
- Params.fVerbose = fVerbose;
- pFraig = Abc_NtkFraig( pMiter, &Params, 0 );
+ Cmd_CommandExecute( Abc_FrameGetGlobalFrame(), "unset progressbar" );
+
+ // solve the problem iteratively for each output of the miter
+ Status = 1;
+ nOutputs = 0;
+ Abc_NtkForEachPo( pMiter, pObj, i )
+ {
+ if ( Abc_ObjFanin0(pObj) == Abc_AigConst1(pMiter) )
+ {
+ if ( Abc_ObjFaninC0(pObj) ) // complemented -> const 0
+ RetValue = 1;
+ else
+ RetValue = 0;
+ pMiterPart = NULL;
+ }
+ else
+ {
+ // get the cone of this output
+ pMiterPart = Abc_NtkCreateCone( pMiter, Abc_ObjFanin0(pObj), Abc_ObjName(pObj), 0 );
+ if ( Abc_ObjFaninC0(pObj) )
+ Abc_ObjXorFaninC( Abc_NtkPo(pMiterPart,0), 0 );
+ // solve the cone
+ // RetValue = Abc_NtkMiterProve( &pMiterPart, pParams );
+ RetValue = Abc_NtkIvyProve( &pMiterPart, pParams );
+ }
+
+ if ( RetValue == -1 )
+ {
+ printf( "Networks are undecided (resource limits is reached).\r" );
+ Status = -1;
+ }
+ else if ( RetValue == 0 )
+ {
+ int * pSimInfo = Abc_NtkVerifySimulatePattern( pMiterPart, pMiterPart->pModel );
+ if ( pSimInfo[0] != 1 )
+ printf( "ERROR in Abc_NtkMiterProve(): Generated counter-example is invalid.\n" );
+ else
+ printf( "Networks are NOT EQUIVALENT. \n" );
+ free( pSimInfo );
+ Status = 0;
+ break;
+ }
+ else
+ {
+ printf( "Finished part %5d (out of %5d)\r", i+1, Abc_NtkPoNum(pMiter) );
+ nOutputs += nPartSize;
+ }
+// if ( pMiter->pModel )
+// Abc_NtkVerifyReportError( pNtk1, pNtk2, pMiter->pModel );
+ if ( pMiterPart )
+ Abc_NtkDelete( pMiterPart );
+ }
+
+ Cmd_CommandExecute( Abc_FrameGetGlobalFrame(), "set progressbar" );
+
+ if ( Status == 1 )
+ printf( "Networks are equivalent. \n" );
+ else if ( Status == -1 )
+ printf( "Timed out after verifying %d outputs (out of %d).\n", nOutputs, Abc_NtkCoNum(pNtk1) );
Abc_NtkDelete( pMiter );
- if ( pFraig == NULL )
+}
+
+/**Function*************************************************************
+
+ Synopsis [Verifies sequential equivalence by fraiging followed by SAT.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Abc_NtkCecFraigPartAuto( Abc_Ntk_t * pNtk1, Abc_Ntk_t * pNtk2, int nSeconds, int fVerbose )
+{
+ extern int Abc_NtkCombinePos( Abc_Ntk_t * pNtk, int fAnd );
+ extern Vec_Ptr_t * Abc_NtkPartitionSmart( Abc_Ntk_t * pNtk, int nPartSizeLimit, int fVerbose );
+ extern void Abc_NtkConvertCos( Abc_Ntk_t * pNtk, Vec_Int_t * vOuts, Vec_Ptr_t * vOnePtr );
+ extern int Cmd_CommandExecute( void * pAbc, char * sCommand );
+ extern void * Abc_FrameGetGlobalFrame();
+
+ Vec_Ptr_t * vParts, * vOnePtr;
+ Vec_Int_t * vOne;
+ Prove_Params_t Params, * pParams = &Params;
+ Abc_Ntk_t * pMiter, * pMiterPart;
+ int i, RetValue, Status, nOutputs;
+
+ // solve the CNF using the SAT solver
+ Prove_ParamsSetDefault( pParams );
+ pParams->nItersMax = 5;
+ // pParams->fVerbose = 1;
+
+ // get the miter of the two networks
+ pMiter = Abc_NtkMiter( pNtk1, pNtk2, 1, 1 );
+ if ( pMiter == NULL )
{
- printf( "Fraiging has failed.\n" );
+ printf( "Miter computation has failed.\n" );
return;
}
- RetValue = Abc_NtkMiterIsConstant( pFraig );
- Abc_NtkDelete( pFraig );
+ RetValue = Abc_NtkMiterIsConstant( pMiter );
if ( RetValue == 0 )
{
- printf( "Networks are equivalent after fraiging.\n" );
+ printf( "Networks are NOT EQUIVALENT after structural hashing.\n" );
+ // report the error
+ pMiter->pModel = Abc_NtkVerifyGetCleanModel( pMiter, 1 );
+ Abc_NtkVerifyReportError( pNtk1, pNtk2, pMiter->pModel );
+ FREE( pMiter->pModel );
+ Abc_NtkDelete( pMiter );
return;
}
- printf( "Networks are NOT EQUIVALENT after fraiging.\n" );
+ if ( RetValue == 1 )
+ {
+ printf( "Networks are equivalent after structural hashing.\n" );
+ Abc_NtkDelete( pMiter );
+ return;
+ }
+
+ Cmd_CommandExecute( Abc_FrameGetGlobalFrame(), "unset progressbar" );
+
+ // partition the outputs
+ vParts = Abc_NtkPartitionSmart( pMiter, 300, 0 );
+
+ // fraig each partition
+ Status = 1;
+ nOutputs = 0;
+ vOnePtr = Vec_PtrAlloc( 1000 );
+ Vec_PtrForEachEntry( vParts, vOne, i )
+ {
+ // get this part of the miter
+ Abc_NtkConvertCos( pMiter, vOne, vOnePtr );
+ pMiterPart = Abc_NtkCreateConeArray( pMiter, vOnePtr, 0 );
+ Abc_NtkCombinePos( pMiterPart, 0 );
+ // check the miter for being constant
+ RetValue = Abc_NtkMiterIsConstant( pMiterPart );
+ if ( RetValue == 0 )
+ {
+ printf( "Networks are NOT EQUIVALENT after partitioning.\n" );
+ Abc_NtkDelete( pMiterPart );
+ break;
+ }
+ if ( RetValue == 1 )
+ {
+ Abc_NtkDelete( pMiterPart );
+ continue;
+ }
+ printf( "Verifying part %4d (out of %4d) PI = %5d. PO = %5d. And = %6d. Lev = %4d.\r",
+ i+1, Vec_PtrSize(vParts), Abc_NtkPiNum(pMiterPart), Abc_NtkPoNum(pMiterPart),
+ Abc_NtkNodeNum(pMiterPart), Abc_AigLevel(pMiterPart) );
+ // solve the problem
+ RetValue = Abc_NtkIvyProve( &pMiterPart, pParams );
+ if ( RetValue == -1 )
+ {
+ printf( "Networks are undecided (resource limits is reached).\r" );
+ Status = -1;
+ }
+ else if ( RetValue == 0 )
+ {
+ int * pSimInfo = Abc_NtkVerifySimulatePattern( pMiterPart, pMiterPart->pModel );
+ if ( pSimInfo[0] != 1 )
+ printf( "ERROR in Abc_NtkMiterProve(): Generated counter-example is invalid.\n" );
+ else
+ printf( "Networks are NOT EQUIVALENT. \n" );
+ free( pSimInfo );
+ Status = 0;
+ Abc_NtkDelete( pMiterPart );
+ break;
+ }
+ else
+ {
+// printf( "Finished part %5d (out of %5d)\r", i+1, Vec_PtrSize(vParts) );
+ nOutputs += Vec_IntSize(vOne);
+ }
+ Abc_NtkDelete( pMiterPart );
+ }
+ printf( " \r" );
+ Vec_VecFree( (Vec_Vec_t *)vParts );
+ Vec_PtrFree( vOnePtr );
+
+ Cmd_CommandExecute( Abc_FrameGetGlobalFrame(), "set progressbar" );
+
+ if ( Status == 1 )
+ printf( "Networks are equivalent. \n" );
+ else if ( Status == -1 )
+ printf( "Timed out after verifying %d outputs (out of %d).\n", nOutputs, Abc_NtkCoNum(pNtk1) );
+ Abc_NtkDelete( pMiter );
}
/**Function*************************************************************
@@ -155,28 +447,29 @@ void Abc_NtkCecFraig( Abc_Ntk_t * pNtk1, Abc_Ntk_t * pNtk2, int fVerbose )
SeeAlso []
***********************************************************************/
-void Abc_NtkSecSat( Abc_Ntk_t * pNtk1, Abc_Ntk_t * pNtk2, int nFrames )
+void Abc_NtkSecSat( Abc_Ntk_t * pNtk1, Abc_Ntk_t * pNtk2, int nConfLimit, int nInsLimit, int nFrames )
{
+ extern Abc_Ntk_t * Abc_NtkMulti( Abc_Ntk_t * pNtk, int nThresh, int nFaninMax, int fCnf, int fMulti, int fSimple, int fFactor );
Abc_Ntk_t * pMiter;
Abc_Ntk_t * pFrames;
Abc_Ntk_t * pCnf;
int RetValue;
// get the miter of the two networks
- pMiter = Abc_NtkMiter( pNtk1, pNtk2, 0 );
+ pMiter = Abc_NtkMiter( pNtk1, pNtk2, 0, 0 );
if ( pMiter == NULL )
{
printf( "Miter computation has failed.\n" );
return;
}
RetValue = Abc_NtkMiterIsConstant( pMiter );
- if ( RetValue == 1 )
+ if ( RetValue == 0 )
{
Abc_NtkDelete( pMiter );
printf( "Networks are NOT EQUIVALENT after structural hashing.\n" );
return;
}
- if ( RetValue == 0 )
+ if ( RetValue == 1 )
{
Abc_NtkDelete( pMiter );
printf( "Networks are equivalent after structural hashing.\n" );
@@ -192,13 +485,13 @@ void Abc_NtkSecSat( Abc_Ntk_t * pNtk1, Abc_Ntk_t * pNtk2, int nFrames )
return;
}
RetValue = Abc_NtkMiterIsConstant( pFrames );
- if ( RetValue == 1 )
+ if ( RetValue == 0 )
{
Abc_NtkDelete( pFrames );
printf( "Networks are NOT EQUIVALENT after framing.\n" );
return;
}
- if ( RetValue == 0 )
+ if ( RetValue == 1 )
{
Abc_NtkDelete( pFrames );
printf( "Networks are equivalent after framing.\n" );
@@ -206,7 +499,7 @@ void Abc_NtkSecSat( Abc_Ntk_t * pNtk1, Abc_Ntk_t * pNtk2, int nFrames )
}
// convert the miter into a CNF
- pCnf = Abc_NtkRenode( pFrames, 0, 100, 1, 0, 0 );
+ pCnf = Abc_NtkMulti( pFrames, 0, 100, 1, 0, 0, 0 );
Abc_NtkDelete( pFrames );
if ( pCnf == NULL )
{
@@ -215,7 +508,10 @@ void Abc_NtkSecSat( Abc_Ntk_t * pNtk1, Abc_Ntk_t * pNtk2, int nFrames )
}
// solve the CNF using the SAT solver
- if ( Abc_NtkMiterSat( pCnf, 0 ) )
+ RetValue = Abc_NtkMiterSat( pCnf, (sint64)nConfLimit, (sint64)nInsLimit, 0, NULL, NULL );
+ if ( RetValue == -1 )
+ printf( "Networks are undecided (SAT solver timed out).\n" );
+ else if ( RetValue == 0 )
printf( "Networks are NOT EQUIVALENT after SAT.\n" );
else
printf( "Networks are equivalent after SAT.\n" );
@@ -233,33 +529,37 @@ void Abc_NtkSecSat( Abc_Ntk_t * pNtk1, Abc_Ntk_t * pNtk2, int nFrames )
SeeAlso []
***********************************************************************/
-void Abc_NtkSecFraig( Abc_Ntk_t * pNtk1, Abc_Ntk_t * pNtk2, int nFrames )
+int Abc_NtkSecFraig( Abc_Ntk_t * pNtk1, Abc_Ntk_t * pNtk2, int nSeconds, int nFrames, int fVerbose )
{
Fraig_Params_t Params;
+ Fraig_Man_t * pMan;
Abc_Ntk_t * pMiter;
- Abc_Ntk_t * pFraig;
Abc_Ntk_t * pFrames;
int RetValue;
// get the miter of the two networks
- pMiter = Abc_NtkMiter( pNtk1, pNtk2, 0 );
+ pMiter = Abc_NtkMiter( pNtk1, pNtk2, 0, 0 );
if ( pMiter == NULL )
{
printf( "Miter computation has failed.\n" );
- return;
+ return 0;
}
RetValue = Abc_NtkMiterIsConstant( pMiter );
- if ( RetValue == 1 )
+ if ( RetValue == 0 )
{
- Abc_NtkDelete( pMiter );
printf( "Networks are NOT EQUIVALENT after structural hashing.\n" );
- return;
+ // report the error
+ pMiter->pModel = Abc_NtkVerifyGetCleanModel( pMiter, nFrames );
+ Abc_NtkVerifyReportErrorSeq( pNtk1, pNtk2, pMiter->pModel, nFrames );
+ FREE( pMiter->pModel );
+ Abc_NtkDelete( pMiter );
+ return 0;
}
- if ( RetValue == 0 )
+ if ( RetValue == 1 )
{
Abc_NtkDelete( pMiter );
printf( "Networks are equivalent after structural hashing.\n" );
- return;
+ return 1;
}
// create the timeframes
@@ -268,39 +568,446 @@ void Abc_NtkSecFraig( Abc_Ntk_t * pNtk1, Abc_Ntk_t * pNtk2, int nFrames )
if ( pFrames == NULL )
{
printf( "Frames computation has failed.\n" );
- return;
+ return 0;
}
RetValue = Abc_NtkMiterIsConstant( pFrames );
- if ( RetValue == 1 )
+ if ( RetValue == 0 )
{
- Abc_NtkDelete( pFrames );
printf( "Networks are NOT EQUIVALENT after framing.\n" );
- return;
+ // report the error
+ pFrames->pModel = Abc_NtkVerifyGetCleanModel( pFrames, 1 );
+// Abc_NtkVerifyReportErrorSeq( pNtk1, pNtk2, pFrames->pModel, nFrames );
+ FREE( pFrames->pModel );
+ Abc_NtkDelete( pFrames );
+ return 0;
}
- if ( RetValue == 0 )
+ if ( RetValue == 1 )
{
Abc_NtkDelete( pFrames );
printf( "Networks are equivalent after framing.\n" );
- return;
+ return 1;
}
// convert the miter into a FRAIG
Fraig_ParamsSetDefault( &Params );
- pFraig = Abc_NtkFraig( pFrames, &Params, 0 );
+ Params.fVerbose = fVerbose;
+ Params.nSeconds = nSeconds;
+// Params.fFuncRed = 0;
+// Params.nPatsRand = 0;
+// Params.nPatsDyna = 0;
+ pMan = Abc_NtkToFraig( pFrames, &Params, 0, 0 );
+ Fraig_ManProveMiter( pMan );
+
+ // analyze the result
+ RetValue = Fraig_ManCheckMiter( pMan );
+ // report the result
+ if ( RetValue == -1 )
+ printf( "Networks are undecided (SAT solver timed out on the final miter).\n" );
+ else if ( RetValue == 1 )
+ printf( "Networks are equivalent after fraiging.\n" );
+ else if ( RetValue == 0 )
+ {
+ printf( "Networks are NOT EQUIVALENT after fraiging.\n" );
+// Abc_NtkVerifyReportErrorSeq( pNtk1, pNtk2, Fraig_ManReadModel(pMan), nFrames );
+ }
+ else assert( 0 );
+ // delete the fraig manager
+ Fraig_ManFree( pMan );
+ // delete the miter
Abc_NtkDelete( pFrames );
- if ( pFraig == NULL )
+ return RetValue == 1;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Returns a dummy pattern full of zeros.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int * Abc_NtkVerifyGetCleanModel( Abc_Ntk_t * pNtk, int nFrames )
+{
+ int * pModel = ALLOC( int, Abc_NtkCiNum(pNtk) * nFrames );
+ memset( pModel, 0, sizeof(int) * Abc_NtkCiNum(pNtk) * nFrames );
+ return pModel;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Returns the PO values under the given input pattern.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int * Abc_NtkVerifySimulatePattern( Abc_Ntk_t * pNtk, int * pModel )
+{
+ Abc_Obj_t * pNode;
+ int * pValues, Value0, Value1, i;
+ int fStrashed = 0;
+ if ( !Abc_NtkIsStrash(pNtk) )
{
- printf( "Fraiging has failed.\n" );
- return;
+ pNtk = Abc_NtkStrash(pNtk, 0, 0, 0);
+ fStrashed = 1;
}
- RetValue = Abc_NtkMiterIsConstant( pFraig );
- Abc_NtkDelete( pFraig );
- if ( RetValue == 0 )
+/*
+ printf( "Counter example: " );
+ Abc_NtkForEachCi( pNtk, pNode, i )
+ printf( " %d", pModel[i] );
+ printf( "\n" );
+*/
+ // increment the trav ID
+ Abc_NtkIncrementTravId( pNtk );
+ // set the CI values
+ Abc_AigConst1(pNtk)->pCopy = (void *)1;
+ Abc_NtkForEachCi( pNtk, pNode, i )
+ pNode->pCopy = (void *)pModel[i];
+ // simulate in the topological order
+ Abc_NtkForEachNode( pNtk, pNode, i )
{
- printf( "Networks are equivalent after fraiging.\n" );
+ Value0 = ((int)Abc_ObjFanin0(pNode)->pCopy) ^ Abc_ObjFaninC0(pNode);
+ Value1 = ((int)Abc_ObjFanin1(pNode)->pCopy) ^ Abc_ObjFaninC1(pNode);
+ pNode->pCopy = (void *)(Value0 & Value1);
+ }
+ // fill the output values
+ pValues = ALLOC( int, Abc_NtkCoNum(pNtk) );
+ Abc_NtkForEachCo( pNtk, pNode, i )
+ pValues[i] = ((int)Abc_ObjFanin0(pNode)->pCopy) ^ Abc_ObjFaninC0(pNode);
+ if ( fStrashed )
+ Abc_NtkDelete( pNtk );
+ return pValues;
+}
+
+
+/**Function*************************************************************
+
+ Synopsis [Reports mismatch between the two networks.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Abc_NtkVerifyReportError( Abc_Ntk_t * pNtk1, Abc_Ntk_t * pNtk2, int * pModel )
+{
+ Vec_Ptr_t * vNodes;
+ Abc_Obj_t * pNode;
+ int * pValues1, * pValues2;
+ int nErrors, nPrinted, i, iNode = -1;
+
+ assert( Abc_NtkCiNum(pNtk1) == Abc_NtkCiNum(pNtk2) );
+ assert( Abc_NtkCoNum(pNtk1) == Abc_NtkCoNum(pNtk2) );
+ // get the CO values under this model
+ pValues1 = Abc_NtkVerifySimulatePattern( pNtk1, pModel );
+ pValues2 = Abc_NtkVerifySimulatePattern( pNtk2, pModel );
+ // count the mismatches
+ nErrors = 0;
+ for ( i = 0; i < Abc_NtkCoNum(pNtk1); i++ )
+ nErrors += (int)( pValues1[i] != pValues2[i] );
+ printf( "Verification failed for at least %d outputs: ", nErrors );
+ // print the first 3 outputs
+ nPrinted = 0;
+ for ( i = 0; i < Abc_NtkCoNum(pNtk1); i++ )
+ if ( pValues1[i] != pValues2[i] )
+ {
+ if ( iNode == -1 )
+ iNode = i;
+ printf( " %s", Abc_ObjName(Abc_NtkCo(pNtk1,i)) );
+ if ( ++nPrinted == 3 )
+ break;
+ }
+ if ( nPrinted != nErrors )
+ printf( " ..." );
+ printf( "\n" );
+ // report mismatch for the first output
+ if ( iNode >= 0 )
+ {
+ printf( "Output %s: Value in Network1 = %d. Value in Network2 = %d.\n",
+ Abc_ObjName(Abc_NtkCo(pNtk1,iNode)), pValues1[iNode], pValues2[iNode] );
+ printf( "Input pattern: " );
+ // collect PIs in the cone
+ pNode = Abc_NtkCo(pNtk1,iNode);
+ vNodes = Abc_NtkNodeSupport( pNtk1, &pNode, 1 );
+ // set the PI numbers
+ Abc_NtkForEachCi( pNtk1, pNode, i )
+ pNode->pCopy = (void*)i;
+ // print the model
+ pNode = Vec_PtrEntry( vNodes, 0 );
+ if ( Abc_ObjIsCi(pNode) )
+ {
+ Vec_PtrForEachEntry( vNodes, pNode, i )
+ {
+ assert( Abc_ObjIsCi(pNode) );
+ printf( " %s=%d", Abc_ObjName(pNode), pModel[(int)pNode->pCopy] );
+ }
+ }
+ printf( "\n" );
+ Vec_PtrFree( vNodes );
+ }
+ free( pValues1 );
+ free( pValues2 );
+}
+
+
+/**Function*************************************************************
+
+ Synopsis [Computes the COs in the support of the PO in the given frame.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Abc_NtkGetSeqPoSupp( Abc_Ntk_t * pNtk, int iFrame, int iNumPo )
+{
+ Abc_Ntk_t * pFrames;
+ Abc_Obj_t * pObj, * pNodePo;
+ Vec_Ptr_t * vSupp;
+ int i, k;
+ // get the timeframes of the network
+ pFrames = Abc_NtkFrames( pNtk, iFrame + 1, 0 );
+//Abc_NtkShowAig( pFrames );
+
+ // get the PO of the timeframes
+ pNodePo = Abc_NtkPo( pFrames, iFrame * Abc_NtkPoNum(pNtk) + iNumPo );
+ // set the support
+ vSupp = Abc_NtkNodeSupport( pFrames, &pNodePo, 1 );
+ // mark the support of the frames
+ Abc_NtkForEachCi( pFrames, pObj, i )
+ pObj->pCopy = NULL;
+ Vec_PtrForEachEntry( vSupp, pObj, i )
+ pObj->pCopy = (void *)1;
+ // mark the support of the network if the support of the timeframes is marked
+ Abc_NtkForEachCi( pNtk, pObj, i )
+ pObj->pCopy = NULL;
+ Abc_NtkForEachLatch( pNtk, pObj, i )
+ if ( Abc_NtkBox(pFrames, i)->pCopy )
+ pObj->pCopy = (void *)1;
+ Abc_NtkForEachPi( pNtk, pObj, i )
+ for ( k = 0; k <= iFrame; k++ )
+ if ( Abc_NtkPi(pFrames, k*Abc_NtkPiNum(pNtk) + i)->pCopy )
+ pObj->pCopy = (void *)1;
+ // free stuff
+ Vec_PtrFree( vSupp );
+ Abc_NtkDelete( pFrames );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Reports mismatch between the two sequential networks.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Abc_NtkVerifyReportErrorSeq( Abc_Ntk_t * pNtk1, Abc_Ntk_t * pNtk2, int * pModel, int nFrames )
+{
+ Vec_Ptr_t * vInfo1, * vInfo2;
+ Abc_Obj_t * pObj, * pObjError, * pObj1, * pObj2;
+ int ValueError1, ValueError2;
+ unsigned * pPats1, * pPats2;
+ int i, o, k, nErrors, iFrameError, iNodePo, nPrinted;
+ int fRemove1 = 0, fRemove2 = 0;
+
+ if ( !Abc_NtkIsStrash(pNtk1) )
+ fRemove1 = 1, pNtk1 = Abc_NtkStrash( pNtk1, 0, 0, 0 );
+ if ( !Abc_NtkIsStrash(pNtk2) )
+ fRemove2 = 1, pNtk2 = Abc_NtkStrash( pNtk2, 0, 0, 0 );
+
+ // simulate sequential circuits
+ vInfo1 = Sim_SimulateSeqModel( pNtk1, nFrames, pModel );
+ vInfo2 = Sim_SimulateSeqModel( pNtk2, nFrames, pModel );
+
+ // look for a discrepancy in the PO values
+ nErrors = 0;
+ pObjError = NULL;
+ for ( i = 0; i < nFrames; i++ )
+ {
+ if ( pObjError )
+ break;
+ Abc_NtkForEachPo( pNtk1, pObj1, o )
+ {
+ pObj2 = Abc_NtkPo( pNtk2, o );
+ pPats1 = Sim_SimInfoGet(vInfo1, pObj1);
+ pPats2 = Sim_SimInfoGet(vInfo2, pObj2);
+ if ( pPats1[i] == pPats2[i] )
+ continue;
+ nErrors++;
+ if ( pObjError == NULL )
+ {
+ pObjError = pObj1;
+ iFrameError = i;
+ iNodePo = o;
+ ValueError1 = (pPats1[i] > 0);
+ ValueError2 = (pPats2[i] > 0);
+ }
+ }
+ }
+
+ if ( pObjError == NULL )
+ {
+ printf( "No output mismatches detected.\n" );
+ Sim_UtilInfoFree( vInfo1 );
+ Sim_UtilInfoFree( vInfo2 );
+ if ( fRemove1 ) Abc_NtkDelete( pNtk1 );
+ if ( fRemove2 ) Abc_NtkDelete( pNtk2 );
return;
}
- printf( "Networks are NOT EQUIVALENT after fraiging.\n" );
+
+ printf( "Verification failed for at least %d output%s of frame %d: ", nErrors, (nErrors>1? "s":""), iFrameError+1 );
+ // print the first 3 outputs
+ nPrinted = 0;
+ Abc_NtkForEachPo( pNtk1, pObj1, o )
+ {
+ pObj2 = Abc_NtkPo( pNtk2, o );
+ pPats1 = Sim_SimInfoGet(vInfo1, pObj1);
+ pPats2 = Sim_SimInfoGet(vInfo2, pObj2);
+ if ( pPats1[iFrameError] == pPats2[iFrameError] )
+ continue;
+ printf( " %s", Abc_ObjName(pObj1) );
+ if ( ++nPrinted == 3 )
+ break;
+ }
+ if ( nPrinted != nErrors )
+ printf( " ..." );
+ printf( "\n" );
+
+ // mark CIs of the networks in the cone of influence of this output
+ Abc_NtkGetSeqPoSupp( pNtk1, iFrameError, iNodePo );
+ Abc_NtkGetSeqPoSupp( pNtk2, iFrameError, iNodePo );
+
+ // report mismatch for the first output
+ printf( "Output %s: Value in Network1 = %d. Value in Network2 = %d.\n",
+ Abc_ObjName(pObjError), ValueError1, ValueError2 );
+
+ printf( "The cone of influence of output %s in Network1:\n", Abc_ObjName(pObjError) );
+ printf( "PIs: " );
+ Abc_NtkForEachPi( pNtk1, pObj, i )
+ if ( pObj->pCopy )
+ printf( "%s ", Abc_ObjName(pObj) );
+ printf( "\n" );
+ printf( "Latches: " );
+ Abc_NtkForEachLatch( pNtk1, pObj, i )
+ if ( pObj->pCopy )
+ printf( "%s ", Abc_ObjName(pObj) );
+ printf( "\n" );
+
+ printf( "The cone of influence of output %s in Network2:\n", Abc_ObjName(pObjError) );
+ printf( "PIs: " );
+ Abc_NtkForEachPi( pNtk2, pObj, i )
+ if ( pObj->pCopy )
+ printf( "%s ", Abc_ObjName(pObj) );
+ printf( "\n" );
+ printf( "Latches: " );
+ Abc_NtkForEachLatch( pNtk2, pObj, i )
+ if ( pObj->pCopy )
+ printf( "%s ", Abc_ObjName(pObj) );
+ printf( "\n" );
+
+ // print the patterns
+ for ( i = 0; i <= iFrameError; i++ )
+ {
+ printf( "Frame %d: ", i+1 );
+
+ printf( "PI(1):" );
+ Abc_NtkForEachPi( pNtk1, pObj, k )
+ if ( pObj->pCopy )
+ printf( "%d", Sim_SimInfoGet(vInfo1, pObj)[i] > 0 );
+ printf( " " );
+ printf( "L(1):" );
+ Abc_NtkForEachLatch( pNtk1, pObj, k )
+ if ( pObj->pCopy )
+ printf( "%d", Sim_SimInfoGet(vInfo1, pObj)[i] > 0 );
+ printf( " " );
+ printf( "%s(1):", Abc_ObjName(pObjError) );
+ printf( "%d", Sim_SimInfoGet(vInfo1, pObjError)[i] > 0 );
+
+ printf( " " );
+
+ printf( "PI(2):" );
+ Abc_NtkForEachPi( pNtk2, pObj, k )
+ if ( pObj->pCopy )
+ printf( "%d", Sim_SimInfoGet(vInfo2, pObj)[i] > 0 );
+ printf( " " );
+ printf( "L(2):" );
+ Abc_NtkForEachLatch( pNtk2, pObj, k )
+ if ( pObj->pCopy )
+ printf( "%d", Sim_SimInfoGet(vInfo2, pObj)[i] > 0 );
+ printf( " " );
+ printf( "%s(2):", Abc_ObjName(pObjError) );
+ printf( "%d", Sim_SimInfoGet(vInfo2, pObjError)[i] > 0 );
+
+ printf( "\n" );
+ }
+ Abc_NtkForEachCi( pNtk1, pObj, i )
+ pObj->pCopy = NULL;
+ Abc_NtkForEachCi( pNtk2, pObj, i )
+ pObj->pCopy = NULL;
+
+ Sim_UtilInfoFree( vInfo1 );
+ Sim_UtilInfoFree( vInfo2 );
+ if ( fRemove1 ) Abc_NtkDelete( pNtk1 );
+ if ( fRemove2 ) Abc_NtkDelete( pNtk2 );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Simulates buggy miter emailed by Mike.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Abc_NtkSimulteBuggyMiter( Abc_Ntk_t * pNtk )
+{
+ Abc_Obj_t * pObj;
+ int i;
+ int * pModel1, * pModel2, * pResult1, * pResult2;
+ char * vPiValues1 = "01001011100000000011010110101000000";
+ char * vPiValues2 = "11001101011101011111110100100010001";
+
+ assert( strlen(vPiValues1) == (unsigned)Abc_NtkPiNum(pNtk) );
+ assert( 1 == Abc_NtkPoNum(pNtk) );
+
+ pModel1 = ALLOC( int, Abc_NtkCiNum(pNtk) );
+ Abc_NtkForEachPi( pNtk, pObj, i )
+ pModel1[i] = vPiValues1[i] - '0';
+ Abc_NtkForEachLatch( pNtk, pObj, i )
+ pModel1[Abc_NtkPiNum(pNtk)+i] = ((int)pObj->pData) - 1;
+
+ pResult1 = Abc_NtkVerifySimulatePattern( pNtk, pModel1 );
+ printf( "Value = %d\n", pResult1[0] );
+
+ pModel2 = ALLOC( int, Abc_NtkCiNum(pNtk) );
+ Abc_NtkForEachPi( pNtk, pObj, i )
+ pModel2[i] = vPiValues2[i] - '0';
+ Abc_NtkForEachLatch( pNtk, pObj, i )
+ pModel2[Abc_NtkPiNum(pNtk)+i] = pResult1[Abc_NtkPoNum(pNtk)+i];
+
+ pResult2 = Abc_NtkVerifySimulatePattern( pNtk, pModel2 );
+ printf( "Value = %d\n", pResult2[0] );
+
+ free( pModel1 );
+ free( pModel2 );
+ free( pResult1 );
+ free( pResult2 );
}
diff --git a/src/base/abci/abcXsim.c b/src/base/abci/abcXsim.c
new file mode 100644
index 00000000..e5656170
--- /dev/null
+++ b/src/base/abci/abcXsim.c
@@ -0,0 +1,224 @@
+/**CFile****************************************************************
+
+ FileName [abcXsim.c]
+
+ SystemName [ABC: Logic synthesis and verification system.]
+
+ PackageName [Network and node package.]
+
+ Synopsis [Using X-valued simulation.]
+
+ Author [Alan Mishchenko]
+
+ Affiliation [UC Berkeley]
+
+ Date [Ver. 1.0. Started - June 20, 2005.]
+
+ Revision [$Id: abcXsim.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "abc.h"
+
+////////////////////////////////////////////////////////////////////////
+/// DECLARATIONS ///
+////////////////////////////////////////////////////////////////////////
+
+#define XVS0 ABC_INIT_ZERO
+#define XVS1 ABC_INIT_ONE
+#define XVSX ABC_INIT_DC
+
+static inline void Abc_ObjSetXsim( Abc_Obj_t * pObj, int Value ) { pObj->pCopy = (void *)Value; }
+static inline int Abc_ObjGetXsim( Abc_Obj_t * pObj ) { return (int)pObj->pCopy; }
+static inline int Abc_XsimInv( int Value )
+{
+ if ( Value == XVS0 )
+ return XVS1;
+ if ( Value == XVS1 )
+ return XVS0;
+ assert( Value == XVSX );
+ return XVSX;
+}
+static inline int Abc_XsimAnd( int Value0, int Value1 )
+{
+ if ( Value0 == XVS0 || Value1 == XVS0 )
+ return XVS0;
+ if ( Value0 == XVSX || Value1 == XVSX )
+ return XVSX;
+ assert( Value0 == XVS1 && Value1 == XVS1 );
+ return XVS1;
+}
+static inline int Abc_XsimRand2()
+{
+ return (rand() & 1) ? XVS1 : XVS0;
+}
+static inline int Abc_XsimRand3()
+{
+ int RetValue;
+ do {
+ RetValue = rand() & 3;
+ } while ( RetValue == 0 );
+ return RetValue;
+}
+static inline int Abc_ObjGetXsimFanin0( Abc_Obj_t * pObj )
+{
+ int RetValue;
+ RetValue = Abc_ObjGetXsim(Abc_ObjFanin0(pObj));
+ return Abc_ObjFaninC0(pObj)? Abc_XsimInv(RetValue) : RetValue;
+}
+static inline int Abc_ObjGetXsimFanin1( Abc_Obj_t * pObj )
+{
+ int RetValue;
+ RetValue = Abc_ObjGetXsim(Abc_ObjFanin1(pObj));
+ return Abc_ObjFaninC1(pObj)? Abc_XsimInv(RetValue) : RetValue;
+}
+static inline void Abc_XsimPrint( FILE * pFile, int Value )
+{
+ if ( Value == XVS0 )
+ {
+ fprintf( pFile, "0" );
+ return;
+ }
+ if ( Value == XVS1 )
+ {
+ fprintf( pFile, "1" );
+ return;
+ }
+ assert( Value == XVSX );
+ fprintf( pFile, "x" );
+}
+
+////////////////////////////////////////////////////////////////////////
+/// FUNCTION DEFINITIONS ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+ Synopsis [Performs X-valued simulation of the sequential network.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Abc_NtkXValueSimulate( Abc_Ntk_t * pNtk, int nFrames, int fXInputs, int fXState, int fVerbose )
+{
+ Abc_Obj_t * pObj;
+ int i, f;
+ assert( Abc_NtkIsStrash(pNtk) );
+ srand( 0x12341234 );
+ // start simulation
+ Abc_ObjSetXsim( Abc_AigConst1(pNtk), XVS1 );
+ if ( fXInputs )
+ {
+ Abc_NtkForEachPi( pNtk, pObj, i )
+ Abc_ObjSetXsim( pObj, XVSX );
+ }
+ else
+ {
+ Abc_NtkForEachPi( pNtk, pObj, i )
+ Abc_ObjSetXsim( pObj, Abc_XsimRand2() );
+ }
+ if ( fXState )
+ {
+ Abc_NtkForEachLatch( pNtk, pObj, i )
+ Abc_ObjSetXsim( Abc_ObjFanout0(pObj), XVSX );
+ }
+ else
+ {
+ Abc_NtkForEachLatch( pNtk, pObj, i )
+ Abc_ObjSetXsim( Abc_ObjFanout0(pObj), Abc_LatchInit(pObj) );
+ }
+ // simulate and print the result
+ fprintf( stdout, "Frame : Inputs : Latches : Outputs\n" );
+ for ( f = 0; f < nFrames; f++ )
+ {
+ Abc_AigForEachAnd( pNtk, pObj, i )
+ Abc_ObjSetXsim( pObj, Abc_XsimAnd(Abc_ObjGetXsimFanin0(pObj), Abc_ObjGetXsimFanin1(pObj)) );
+ Abc_NtkForEachCo( pNtk, pObj, i )
+ Abc_ObjSetXsim( pObj, Abc_ObjGetXsimFanin0(pObj) );
+ // print out
+ fprintf( stdout, "%2d : ", f );
+ Abc_NtkForEachPi( pNtk, pObj, i )
+ Abc_XsimPrint( stdout, Abc_ObjGetXsim(pObj) );
+ fprintf( stdout, " : " );
+ Abc_NtkForEachLatch( pNtk, pObj, i )
+ {
+// if ( Abc_ObjGetXsim(Abc_ObjFanout0(pObj)) != XVSX )
+// printf( " %s=", Abc_ObjName(pObj) );
+ Abc_XsimPrint( stdout, Abc_ObjGetXsim(Abc_ObjFanout0(pObj)) );
+ }
+ fprintf( stdout, " : " );
+ Abc_NtkForEachPo( pNtk, pObj, i )
+ Abc_XsimPrint( stdout, Abc_ObjGetXsim(pObj) );
+ if ( Abc_NtkAssertNum(pNtk) )
+ {
+ fprintf( stdout, " : " );
+ Abc_NtkForEachAssert( pNtk, pObj, i )
+ Abc_XsimPrint( stdout, Abc_ObjGetXsim(pObj) );
+ }
+ fprintf( stdout, "\n" );
+ // assign input values
+ if ( fXInputs )
+ {
+ Abc_NtkForEachPi( pNtk, pObj, i )
+ Abc_ObjSetXsim( pObj, XVSX );
+ }
+ else
+ {
+ Abc_NtkForEachPi( pNtk, pObj, i )
+ Abc_ObjSetXsim( pObj, Abc_XsimRand2() );
+ }
+ // transfer the latch values
+ Abc_NtkForEachLatch( pNtk, pObj, i )
+ Abc_ObjSetXsim( Abc_ObjFanout0(pObj), Abc_ObjGetXsim(Abc_ObjFanin0(pObj)) );
+ }
+}
+
+/**Function*************************************************************
+
+ Synopsis [Cycles the circuit to create a new initial state.]
+
+ Description [Simulates the circuit with random input for the given
+ number of timeframes to get a better initial state.]
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Abc_NtkCycleInitState( Abc_Ntk_t * pNtk, int nFrames, int fVerbose )
+{
+ Abc_Obj_t * pObj;
+ int i, f;
+ assert( Abc_NtkIsStrash(pNtk) );
+ srand( 0x12341234 );
+ // initialize the values
+ Abc_ObjSetXsim( Abc_AigConst1(pNtk), XVS1 );
+ Abc_NtkForEachLatch( pNtk, pObj, i )
+// Abc_ObjSetXsim( Abc_ObjFanout0(pObj), Abc_LatchIsInit1(pObj)? XVS1 : XVS0 );
+ Abc_ObjSetXsim( Abc_ObjFanout0(pObj), Abc_LatchInit(pObj) );
+ // simulate for the given number of timeframes
+ for ( f = 0; f < nFrames; f++ )
+ {
+ Abc_NtkForEachPi( pNtk, pObj, i )
+ Abc_ObjSetXsim( pObj, Abc_XsimRand2() );
+ Abc_AigForEachAnd( pNtk, pObj, i )
+ Abc_ObjSetXsim( pObj, Abc_XsimAnd(Abc_ObjGetXsimFanin0(pObj), Abc_ObjGetXsimFanin1(pObj)) );
+ Abc_NtkForEachCo( pNtk, pObj, i )
+ Abc_ObjSetXsim( pObj, Abc_ObjGetXsimFanin0(pObj) );
+ Abc_NtkForEachLatch( pNtk, pObj, i )
+ Abc_ObjSetXsim( Abc_ObjFanout0(pObj), Abc_ObjGetXsim(Abc_ObjFanin0(pObj)) );
+ }
+ // set the final values
+ Abc_NtkForEachLatch( pNtk, pObj, i )
+ pObj->pData = (void *)Abc_ObjGetXsim(Abc_ObjFanout0(pObj));
+}
+
+///////////////////////////////////////////////////////////////////////
+/// END OF FILE ///
+////////////////////////////////////////////////////////////////////////
+
+
diff --git a/src/base/abci/abc_.c b/src/base/abci/abc_.c
index bef3836f..75ec88c3 100644
--- a/src/base/abci/abc_.c
+++ b/src/base/abci/abc_.c
@@ -23,9 +23,9 @@
////////////////////////////////////////////////////////////////////////
/// DECLARATIONS ///
////////////////////////////////////////////////////////////////////////
-
+
////////////////////////////////////////////////////////////////////////
-/// FUNCTION DEFITIONS ///
+/// FUNCTION DEFINITIONS ///
////////////////////////////////////////////////////////////////////////
/**Function*************************************************************
@@ -40,6 +40,7 @@
***********************************************************************/
+
////////////////////////////////////////////////////////////////////////
/// END OF FILE ///
////////////////////////////////////////////////////////////////////////
diff --git a/src/base/abci/abc_new.h b/src/base/abci/abc_new.h
new file mode 100644
index 00000000..3460bb38
--- /dev/null
+++ b/src/base/abci/abc_new.h
@@ -0,0 +1,23 @@
+struct Abc_Obj_t_ // 6 words
+{
+ Abc_Obj_t * pCopy; // the copy of this object
+ Abc_Ntk_t * pNtk; // the host network
+ int Id; // the object ID
+ int TravId; // the traversal ID
+ int nRefs; // the number of fanouts
+ unsigned Type : 4; // the object type
+ unsigned fMarkA : 1; // the multipurpose mark
+ unsigned fMarkB : 1; // the multipurpose mark
+ unsigned fPhase : 1; // the flag to mark the phase of equivalent node
+ unsigned fPersist: 1; // marks the persistant AIG node
+ unsigned nFanins : 24; // the level of the node
+ Abc_Obj_t * Fanins[0]; // the array of fanins
+};
+
+struct Abc_Pin_t_ // 4 words
+{
+ Abc_Pin_t * pNext;
+ Abc_Pin_t * pPrev;
+ Abc_Obj_t * pFanin;
+ Abc_Obj_t * pFanout;
+};
diff --git a/src/base/abci/module.make b/src/base/abci/module.make
index d7c0add2..4558119e 100644
--- a/src/base/abci/module.make
+++ b/src/base/abci/module.make
@@ -1,24 +1,54 @@
SRC += src/base/abci/abc.c \
src/base/abci/abcAttach.c \
+ src/base/abci/abcAuto.c \
src/base/abci/abcBalance.c \
- src/base/abci/abcCollapse.c \
+ src/base/abci/abcBmc.c \
+ src/base/abci/abcCas.c \
+ src/base/abci/abcClpBdd.c \
+ src/base/abci/abcClpSop.c \
src/base/abci/abcCut.c \
+ src/base/abci/abcDar.c \
+ src/base/abci/abcDebug.c \
+ src/base/abci/abcDress.c \
src/base/abci/abcDsd.c \
+ src/base/abci/abcEspresso.c \
+ src/base/abci/abcExtract.c \
src/base/abci/abcFpga.c \
+ src/base/abci/abcFpgaFast.c \
src/base/abci/abcFraig.c \
src/base/abci/abcFxu.c \
+ src/base/abci/abcGen.c \
+ src/base/abci/abcHaig.c \
+ src/base/abci/abcIf.c \
+ src/base/abci/abcIvy.c \
+ src/base/abci/abcLut.c \
src/base/abci/abcMap.c \
+ src/base/abci/abcMini.c \
src/base/abci/abcMiter.c \
+ src/base/abci/abcMulti.c \
src/base/abci/abcNtbdd.c \
+ src/base/abci/abcOdc.c \
+ src/base/abci/abcOrder.c \
+ src/base/abci/abcPart.c \
src/base/abci/abcPrint.c \
+ src/base/abci/abcProve.c \
+ src/base/abci/abcQbf.c \
+ src/base/abci/abcQuant.c \
+ src/base/abci/abcRec.c \
src/base/abci/abcReconv.c \
src/base/abci/abcRefactor.c \
src/base/abci/abcRenode.c \
+ src/base/abci/abcReorder.c \
+ src/base/abci/abcRestruct.c \
+ src/base/abci/abcResub.c \
src/base/abci/abcRewrite.c \
+ src/base/abci/abcRr.c \
src/base/abci/abcSat.c \
src/base/abci/abcStrash.c \
src/base/abci/abcSweep.c \
src/base/abci/abcSymm.c \
src/base/abci/abcTiming.c \
+ src/base/abci/abcUnate.c \
src/base/abci/abcUnreach.c \
- src/base/abci/abcVerify.c
+ src/base/abci/abcVerify.c \
+ src/base/abci/abcXsim.c
diff --git a/src/base/abcs/abcRetime.c b/src/base/abcs/abcRetime.c
deleted file mode 100644
index 13b8a926..00000000
--- a/src/base/abcs/abcRetime.c
+++ /dev/null
@@ -1,203 +0,0 @@
-/**CFile****************************************************************
-
- FileName [abcSeqRetime.c]
-
- SystemName [ABC: Logic synthesis and verification system.]
-
- PackageName [Network and node package.]
-
- Synopsis [Peforms retiming for optimal clock cycle.]
-
- Author [Alan Mishchenko]
-
- Affiliation [UC Berkeley]
-
- Date [Ver. 1.0. Started - June 20, 2005.]
-
- Revision [$Id: abcSeqRetime.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
-
-***********************************************************************/
-
-#include "abc.h"
-
-////////////////////////////////////////////////////////////////////////
-/// DECLARATIONS ///
-////////////////////////////////////////////////////////////////////////
-
-// storing arrival times in the nodes
-static inline int Abc_NodeReadLValue( Abc_Obj_t * pNode ) { return Vec_IntEntry( (pNode)->pNtk->pData, (pNode)->Id ); }
-static inline void Abc_NodeSetLValue( Abc_Obj_t * pNode, int Value ) { Vec_IntWriteEntry( (pNode)->pNtk->pData, (pNode)->Id, (Value) ); }
-
-// the internal procedures
-static int Abc_NtkRetimeSearch_rec( Abc_Ntk_t * pNtk, int FiMin, int FiMax );
-static int Abc_NtkRetimeForPeriod( Abc_Ntk_t * pNtk, int Fi );
-static int Abc_NodeUpdateLValue( Abc_Obj_t * pObj, int Fi );
-
-// node status after updating its arrival time
-enum { ABC_UPDATE_FAIL, ABC_UPDATE_NO, ABC_UPDATE_YES };
-
-////////////////////////////////////////////////////////////////////////
-/// FUNCTION DEFITIONS ///
-////////////////////////////////////////////////////////////////////////
-
-/**Function*************************************************************
-
- Synopsis [Retimes AIG for optimal delay.]
-
- Description []
-
- SideEffects []
-
- SeeAlso []
-
-***********************************************************************/
-void Abc_NtkSeqRetimeDelay( Abc_Ntk_t * pNtk )
-{
- int FiMax, FiBest;
- assert( Abc_NtkIsSeq( pNtk ) );
-
- // start storage for sequential arrival times
- assert( pNtk->pData == NULL );
- pNtk->pData = Vec_IntAlloc( 0 );
-
- // get the maximum possible clock
- FiMax = Abc_NtkNodeNum(pNtk);
-
- // make sure this clock period is feasible
- assert( Abc_NtkRetimeForPeriod( pNtk, FiMax ) );
-
- // search for the optimal clock period between 0 and nLevelMax
- FiBest = Abc_NtkRetimeSearch_rec( pNtk, 0, FiMax );
- // print the result
- printf( "The best clock period is %3d.\n", FiBest );
-
- // free storage
- Vec_IntFree( pNtk->pData );
- pNtk->pData = NULL;
-}
-
-/**Function*************************************************************
-
- Synopsis [Performs binary search for the optimal clock period.]
-
- Description [Assumes that FiMin is infeasible while FiMax is feasible.]
-
- SideEffects []
-
- SeeAlso []
-
-***********************************************************************/
-int Abc_NtkRetimeSearch_rec( Abc_Ntk_t * pNtk, int FiMin, int FiMax )
-{
- int Median;
-
- assert( FiMin < FiMax );
- if ( FiMin + 1 == FiMax )
- return FiMax;
-
- Median = FiMin + (FiMax - FiMin)/2;
-
- if ( Abc_NtkRetimeForPeriod( pNtk, Median ) )
- return Abc_NtkRetimeSearch_rec( pNtk, FiMin, Median ); // Median is feasible
- else
- return Abc_NtkRetimeSearch_rec( pNtk, Median, FiMax ); // Median is infeasible
-}
-
-/**Function*************************************************************
-
- Synopsis [Returns 1 if retiming with this clock period is feasible.]
-
- Description []
-
- SideEffects []
-
- SeeAlso []
-
-***********************************************************************/
-int Abc_NtkRetimeForPeriod( Abc_Ntk_t * pNtk, int Fi )
-{
- Vec_Ptr_t * vFrontier;
- Abc_Obj_t * pObj, * pFanout;
- int RetValue, i, k;
-
- // set l-values of all nodes to be minus infinity
- Vec_IntFill( pNtk->pData, Abc_NtkObjNumMax(pNtk), -ABC_INFINITY );
-
- // start the frontier by including PI fanouts
- vFrontier = Vec_PtrAlloc( 100 );
- Abc_NtkForEachPi( pNtk, pObj, i )
- {
- Abc_NodeSetLValue( pObj, 0 );
- Abc_ObjForEachFanout( pObj, pFanout, k )
- if ( pFanout->fMarkA == 0 )
- {
- Vec_PtrPush( vFrontier, pFanout );
- pFanout->fMarkA = 1;
- }
- }
-
- // iterate until convergence
- Vec_PtrForEachEntry( vFrontier, pObj, i )
- {
- RetValue = Abc_NodeUpdateLValue( pObj, Fi );
- if ( RetValue == ABC_UPDATE_FAIL )
- break;
- // unmark the node as processed
- pObj->fMarkA = 0;
- if ( RetValue == ABC_UPDATE_NO )
- continue;
- assert( RetValue == ABC_UPDATE_YES );
- // arrival times have changed - add fanouts to the frontier
- Abc_ObjForEachFanout( pObj, pFanout, k )
- if ( pFanout->fMarkA == 0 )
- {
- Vec_PtrPush( vFrontier, pFanout );
- pFanout->fMarkA = 1;
- }
- }
- // clean the nodes
- Vec_PtrForEachEntryStart( vFrontier, pObj, k, i )
- pObj->fMarkA = 0;
-
- // report the results
- if ( RetValue == ABC_UPDATE_FAIL )
- printf( "Period = %3d. Updated nodes = %6d. Infeasible\n", Fi, vFrontier->nSize );
- else
- printf( "Period = %3d. Updated nodes = %6d. Feasible\n", Fi, vFrontier->nSize );
- Vec_PtrFree( vFrontier );
- return RetValue != ABC_UPDATE_FAIL;
-}
-
-/**Function*************************************************************
-
- Synopsis [Computes the l-value of the node.]
-
- Description []
-
- SideEffects []
-
- SeeAlso []
-
-***********************************************************************/
-int Abc_NodeUpdateLValue( Abc_Obj_t * pObj, int Fi )
-{
- int lValueNew, lValue0, lValue1;
- assert( !Abc_ObjIsPi(pObj) );
- lValue0 = Abc_NodeReadLValue(Abc_ObjFanin0(pObj)) - Fi * Abc_ObjFaninL0(pObj);
- if ( Abc_ObjFaninNum(pObj) == 2 )
- lValue1 = Abc_NodeReadLValue(Abc_ObjFanin1(pObj)) - Fi * Abc_ObjFaninL1(pObj);
- else
- lValue1 = -ABC_INFINITY;
- lValueNew = 1 + ABC_MAX( lValue0, lValue1 );
- if ( Abc_ObjIsPo(pObj) && lValueNew > Fi )
- return ABC_UPDATE_FAIL;
- if ( lValueNew == Abc_NodeReadLValue(pObj) )
- return ABC_UPDATE_NO;
- Abc_NodeSetLValue( pObj, lValueNew );
- return ABC_UPDATE_YES;
-}
-
-////////////////////////////////////////////////////////////////////////
-/// END OF FILE ///
-////////////////////////////////////////////////////////////////////////
-
diff --git a/src/base/abcs/abcSeq.c b/src/base/abcs/abcSeq.c
deleted file mode 100644
index a41edac1..00000000
--- a/src/base/abcs/abcSeq.c
+++ /dev/null
@@ -1,642 +0,0 @@
-/**CFile****************************************************************
-
- FileName [abcSeq.c]
-
- SystemName [ABC: Logic synthesis and verification system.]
-
- PackageName [Network and node package.]
-
- Synopsis []
-
- Author [Alan Mishchenko]
-
- Affiliation [UC Berkeley]
-
- Date [Ver. 1.0. Started - June 20, 2005.]
-
- Revision [$Id: abcSeq.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
-
-***********************************************************************/
-
-#include "abc.h"
-
-/*
- A sequential network is an AIG whose edges have number-of-latches attributes,
- in addition to the complemented attibutes.
-
- The sets of PIs/POs remain the same as in logic network.
- Constant 1 node can only be used as a fanin of a PO node and the reset node.
- The reset node produces sequence (01111...). It is used to create the
- initialization logic of all latches.
- The latches do not have explicit initial state but they are implicitly
- reset by the reset node.
-
-*/
-
-////////////////////////////////////////////////////////////////////////
-/// DECLARATIONS ///
-////////////////////////////////////////////////////////////////////////
-
-static Vec_Int_t * Abc_NtkSeqCountLatches( Abc_Ntk_t * pNtk );
-static void Abc_NodeSeqCountLatches( Abc_Obj_t * pObj, Vec_Int_t * vNumbers );
-
-static void Abc_NtkSeqCreateLatches( Abc_Ntk_t * pNtk, Abc_Ntk_t * pNtkNew );
-static void Abc_NodeSeqCreateLatches( Abc_Obj_t * pObj, int nLatches );
-
-////////////////////////////////////////////////////////////////////////
-/// FUNCTION DEFITIONS ///
-////////////////////////////////////////////////////////////////////////
-
-/**Function*************************************************************
-
- Synopsis [Converts a normal AIG into a sequential AIG.]
-
- Description []
-
- SideEffects []
-
- SeeAlso []
-
-***********************************************************************/
-Abc_Ntk_t * Abc_NtkAigToSeq( Abc_Ntk_t * pNtk )
-{
- Abc_Ntk_t * pNtkNew;
- Abc_Aig_t * pManNew;
- Vec_Ptr_t * vNodes;
- Abc_Obj_t * pObj, * pConst, * pFanout, * pFaninNew, * pLatch;
- int i, k, fChange, Counter;
-
- assert( Abc_NtkIsStrash(pNtk) );
- // start the network
- pNtkNew = Abc_NtkStartFrom( pNtk, ABC_TYPE_SEQ, ABC_FUNC_AIG );
- pManNew = pNtkNew->pManFunc;
-
- // set mapping of the constant nodes
- Abc_AigConst1(pNtk->pManFunc)->pCopy = Abc_AigConst1( pManNew );
- Abc_AigReset(pNtk->pManFunc)->pCopy = Abc_AigReset( pManNew );
-
- // get rid of initial states
- Abc_NtkForEachLatch( pNtk, pObj, i )
- {
- pObj->pNext = pObj->pCopy;
- if ( Abc_LatchIsInit0(pObj) )
- pObj->pCopy = Abc_AigAnd( pManNew, pObj->pCopy, Abc_AigReset(pManNew) );
- else if ( Abc_LatchIsInit1(pObj) )
- pObj->pCopy = Abc_AigOr( pManNew, pObj->pCopy, Abc_ObjNot( Abc_AigReset(pManNew) ) );
- }
-
- // copy internal nodes
- vNodes = Abc_AigDfs( pNtk, 1, 0 );
- Vec_PtrForEachEntry( vNodes, pObj, i )
- if ( Abc_ObjFaninNum(pObj) == 2 )
- pObj->pCopy = Abc_AigAnd( pManNew, Abc_ObjChild0Copy(pObj), Abc_ObjChild1Copy(pObj) );
- Vec_PtrFree( vNodes );
-
- // relink the CO nodes
- Abc_NtkForEachPo( pNtk, pObj, i )
- Abc_ObjAddFanin( pObj->pCopy, Abc_ObjChild0Copy(pObj) );
- Abc_NtkForEachLatch( pNtk, pObj, i )
- Abc_ObjAddFanin( pObj->pNext, Abc_ObjChild0Copy(pObj) );
-
- // propagate constant input latches in the new network
- Counter = 0;
- fChange = 1;
- while ( fChange )
- {
- fChange = 0;
- Abc_NtkForEachLatch( pNtkNew, pLatch, i )
- {
- if ( Abc_ObjFanoutNum(pLatch) == 0 )
- continue;
- pFaninNew = Abc_ObjFanin0(pLatch);
- if ( Abc_ObjIsCi(pFaninNew) || !Abc_NodeIsConst(pFaninNew) )
- continue;
- pConst = Abc_ObjNotCond( Abc_AigConst1(pManNew), Abc_ObjFaninC0(pLatch) );
- Abc_AigReplace( pManNew, pLatch, pConst );
- fChange = 1;
- Counter++;
- }
- }
- if ( Counter )
- fprintf( stdout, "Latch sweeping removed %d latches (out of %d).\n", Counter, Abc_NtkLatchNum(pNtk) );
-
- // redirect fanouts of each latch to the latch fanins
- vNodes = Vec_PtrAlloc( 100 );
- Abc_NtkForEachLatch( pNtkNew, pLatch, i )
- {
-//printf( "Latch %s. Fanouts = %d.\n", Abc_ObjName(pLatch), Abc_ObjFanoutNum(pLatch) );
-
- Abc_NodeCollectFanouts( pLatch, vNodes );
- Vec_PtrForEachEntry( vNodes, pFanout, k )
- {
- if ( Abc_ObjFaninId0(pFanout) == Abc_ObjFaninId1(pFanout))
- printf( " ******* Identical fanins!!! ******* \n" );
-
- if ( Abc_ObjFaninId0(pFanout) == (int)pLatch->Id )
- {
-// pFaninNew = Abc_ObjNotCond( Abc_ObjChild0(pLatch), Abc_ObjFaninC0(pFanout) );
- pFaninNew = Abc_ObjChild0(pLatch);
- Abc_ObjPatchFanin( pFanout, pLatch, pFaninNew );
- Abc_ObjAddFaninL0( pFanout, 1 );
- }
- else if ( Abc_ObjFaninId1(pFanout) == (int)pLatch->Id )
- {
-// pFaninNew = Abc_ObjNotCond( Abc_ObjChild0(pLatch), Abc_ObjFaninC1(pFanout) );
- pFaninNew = Abc_ObjChild0(pLatch);
- Abc_ObjPatchFanin( pFanout, pLatch, pFaninNew );
- Abc_ObjAddFaninL1( pFanout, 1 );
- }
- else
- assert( 0 );
- }
- assert( Abc_ObjFanoutNum(pLatch) == 0 );
- Abc_NtkDeleteObj( pLatch );
- }
- Vec_PtrFree( vNodes );
- // get rid of latches altogether
-// Abc_NtkForEachLatch( pNtkNew, pObj, i )
-// Abc_NtkDeleteObj( pObj );
- assert( pNtkNew->nLatches == 0 );
- Vec_PtrClear( pNtkNew->vLats );
- Vec_PtrShrink( pNtkNew->vCis, pNtk->nPis );
- Vec_PtrShrink( pNtkNew->vCos, pNtk->nPos );
-
-/*
-/////////////////////////////////////////////
-Abc_NtkForEachNode( pNtkNew, pObj, i )
- if ( !Abc_NodeIsConst(pObj) )
- if ( Abc_ObjFaninL0(pObj) + Abc_ObjFaninL1(pObj) > 20 )
- printf( "(%d,%d) ", Abc_ObjFaninL0(pObj), Abc_ObjFaninL1(pObj) );
-Abc_NtkForEachCo( pNtkNew, pObj, i )
- printf( "(%d) ", Abc_ObjFaninL0(pObj) );
-/////////////////////////////////////////////
-printf( "\n" );
-*/
-
- if ( pNtk->pExdc )
- fprintf( stdout, "Warning: EXDC is dropped when converting to sequential AIG.\n" );
- if ( !Abc_NtkCheck( pNtkNew ) )
- fprintf( stdout, "Abc_NtkAigToSeq(): Network check has failed.\n" );
- return pNtkNew;
-}
-
-/**Function*************************************************************
-
- Synopsis [Converts a sequential AIG into a logic SOP network.]
-
- Description []
-
- SideEffects []
-
- SeeAlso []
-
-***********************************************************************/
-Abc_Ntk_t * Abc_NtkSeqToLogicSop( Abc_Ntk_t * pNtk )
-{
- Abc_Ntk_t * pNtkNew;
- Abc_Obj_t * pObj, * pFanin, * pFaninNew;
- int i, k, c;
- assert( Abc_NtkIsSeq(pNtk) );
- // start the network
- pNtkNew = Abc_NtkStartFrom( pNtk, ABC_TYPE_LOGIC, ABC_FUNC_SOP );
- // create the constant and reset nodes
- Abc_NtkDupConst1( pNtk, pNtkNew );
- Abc_NtkDupReset( pNtk, pNtkNew );
- // duplicate the nodes, create node functions and latches
- Abc_NtkForEachNode( pNtk, pObj, i )
- {
- if ( Abc_NodeIsConst(pObj) )
- continue;
- Abc_NtkDupObj(pNtkNew, pObj);
- pObj->pCopy->pData = Abc_SopCreateAnd2( pNtkNew->pManFunc, Abc_ObjFaninC0(pObj), Abc_ObjFaninC1(pObj) );
- }
- // create latches for the new nodes
- Abc_NtkSeqCreateLatches( pNtk, pNtkNew );
- // connect the objects
- Abc_NtkForEachObj( pNtk, pObj, i )
- Abc_ObjForEachFanin( pObj, pFanin, k )
- {
- // find the fanin
- pFaninNew = pFanin->pCopy;
- for ( c = 0; c < Abc_ObjFaninL(pObj, k); c++ )
- pFaninNew = pFaninNew->pCopy;
- Abc_ObjAddFanin( pObj->pCopy, pFaninNew );
- }
- // set the complemented attributed of CO edges (to be fixed by making simple COs)
- Abc_NtkForEachPo( pNtk, pObj, i )
- if ( Abc_ObjFaninC0(pObj) )
- Abc_ObjSetFaninC( pObj->pCopy, 0 );
- // fix the problem with complemented and duplicated CO edges
- Abc_NtkLogicMakeSimpleCos( pNtkNew, 0 );
- // duplicate the EXDC network
- if ( pNtk->pExdc )
- fprintf( stdout, "Warning: EXDC network is not copied.\n" );
- if ( !Abc_NtkCheck( pNtkNew ) )
- fprintf( stdout, "Abc_NtkSeqToLogic(): Network check has failed.\n" );
- return pNtkNew;
-}
-
-
-
-
-/**Function*************************************************************
-
- Synopsis [Finds max number of latches on the fanout edges of each node.]
-
- Description []
-
- SideEffects []
-
- SeeAlso []
-
-***********************************************************************/
-Vec_Int_t * Abc_NtkSeqCountLatches( Abc_Ntk_t * pNtk )
-{
- Vec_Int_t * vNumbers;
- Abc_Obj_t * pObj;
- int i;
- assert( Abc_NtkIsSeq( pNtk ) );
- // start the array of counters
- vNumbers = Vec_IntAlloc( 0 );
- Vec_IntFill( vNumbers, Abc_NtkObjNumMax(pNtk), 0 );
- // count for each edge
- Abc_NtkForEachObj( pNtk, pObj, i )
- Abc_NodeSeqCountLatches( pObj, vNumbers );
- return vNumbers;
-}
-
-/**Function*************************************************************
-
- Synopsis [Countes the latch numbers due to the fanins edges of the given node.]
-
- Description []
-
- SideEffects []
-
- SeeAlso []
-
-***********************************************************************/
-void Abc_NodeSeqCountLatches( Abc_Obj_t * pObj, Vec_Int_t * vNumbers )
-{
- Abc_Obj_t * pFanin;
- int k, nLatches;
- // go through each fanin edge
- Abc_ObjForEachFanin( pObj, pFanin, k )
- {
- nLatches = Abc_ObjFaninL( pObj, k );
- if ( nLatches == 0 )
- continue;
- if ( Vec_IntEntry( vNumbers, pFanin->Id ) < nLatches )
- Vec_IntWriteEntry( vNumbers, pFanin->Id, nLatches );
- }
-}
-
-
-
-/**Function*************************************************************
-
- Synopsis [Creates latches.]
-
- Description []
-
- SideEffects []
-
- SeeAlso []
-
-***********************************************************************/
-void Abc_NtkSeqCreateLatches( Abc_Ntk_t * pNtk, Abc_Ntk_t * pNtkNew )
-{
- Vec_Int_t * vNumbers;
- Abc_Obj_t * pObj;
- int i;
- assert( Abc_NtkIsSeq( pNtk ) );
- // create latches for each new object according to the counters
- vNumbers = Abc_NtkSeqCountLatches( pNtk );
- Abc_NtkForEachObj( pNtk, pObj, i )
- {
- if ( pObj->pCopy == NULL )
- continue;
- Abc_NodeSeqCreateLatches( pObj->pCopy, Vec_IntEntry(vNumbers, (int)pObj->Id) );
- }
- Vec_IntFree( vNumbers );
- // add latch to the PI/PO lists, create latch names
- Abc_NtkFinalizeLatches( pNtkNew );
-}
-
-/**Function*************************************************************
-
- Synopsis [Creates the given number of latches for this object.]
-
- Description [The latches are attached to the node and to each other
- through the pCopy field.]
-
- SideEffects []
-
- SeeAlso []
-
-***********************************************************************/
-void Abc_NodeSeqCreateLatches( Abc_Obj_t * pObj, int nLatches )
-{
- Abc_Ntk_t * pNtk = pObj->pNtk;
- Abc_Obj_t * pLatch, * pFanin;
- int i;
- pFanin = pObj;
- for ( i = 0, pFanin = pObj; i < nLatches; pFanin = pLatch, i++ )
- {
- pLatch = Abc_NtkCreateLatch( pNtk );
- Abc_LatchSetInitDc(pLatch);
- Abc_ObjAddFanin( pLatch, pFanin );
- pFanin->pCopy = pLatch;
- }
-}
-
-/**Function*************************************************************
-
- Synopsis [Counters the number of latches in the sequential AIG.]
-
- Description []
-
- SideEffects []
-
- SeeAlso []
-
-***********************************************************************/
-int Abc_NtkSeqLatchNum( Abc_Ntk_t * pNtk )
-{
- Vec_Int_t * vNumbers;
- Abc_Obj_t * pObj;
- int i, Counter;
- assert( Abc_NtkIsSeq( pNtk ) );
- // create latches for each new object according to the counters
- Counter = 0;
- vNumbers = Abc_NtkSeqCountLatches( pNtk );
- Abc_NtkForEachPi( pNtk, pObj, i )
- {
- assert( Abc_ObjFanoutLMax(pObj) == Vec_IntEntry(vNumbers, (int)pObj->Id) );
- Counter += Vec_IntEntry(vNumbers, (int)pObj->Id);
- }
- Abc_NtkForEachNode( pNtk, pObj, i )
- {
- if ( Abc_NodeIsConst(pObj) )
- continue;
- assert( Abc_ObjFanoutLMax(pObj) == Vec_IntEntry(vNumbers, (int)pObj->Id) );
- Counter += Vec_IntEntry(vNumbers, (int)pObj->Id);
- }
- Vec_IntFree( vNumbers );
- if ( Abc_ObjFanoutNum( Abc_AigReset(pNtk->pManFunc) ) > 0 )
- Counter++;
- return Counter;
-}
-
-
-
-
-
-
-/**Function*************************************************************
-
- Synopsis [Performs forward retiming of the sequential AIG.]
-
- Description []
-
- SideEffects []
-
- SeeAlso []
-
-***********************************************************************/
-void Abc_NtkSeqRetimeForward( Abc_Ntk_t * pNtk )
-{
- Vec_Ptr_t * vNodes;
- Abc_Obj_t * pNode, * pFanout;
- int i, k, nLatches;
- assert( Abc_NtkIsSeq( pNtk ) );
- // assume that all nodes can be retimed
- vNodes = Vec_PtrAlloc( 100 );
- Abc_NtkForEachNode( pNtk, pNode, i )
- {
- if ( Abc_NodeIsConst(pNode) )
- continue;
- Vec_PtrPush( vNodes, pNode );
- pNode->fMarkA = 1;
- }
- // process the nodes
- Vec_PtrForEachEntry( vNodes, pNode, i )
- {
-// printf( "(%d,%d) ", Abc_ObjFaninL0(pNode), Abc_ObjFaninL0(pNode) );
- // get the number of latches to retime
- nLatches = Abc_ObjFaninLMin(pNode);
- if ( nLatches == 0 )
- continue;
- assert( nLatches > 0 );
- // subtract these latches on the fanin side
- Abc_ObjAddFaninL0( pNode, -nLatches );
- Abc_ObjAddFaninL1( pNode, -nLatches );
- // add these latches on the fanout size
- Abc_ObjForEachFanout( pNode, pFanout, k )
- {
- Abc_ObjAddFanoutL( pNode, pFanout, nLatches );
- if ( pFanout->fMarkA == 0 )
- { // schedule the node for updating
- Vec_PtrPush( vNodes, pFanout );
- pFanout->fMarkA = 1;
- }
- }
- // unmark the node as processed
- pNode->fMarkA = 0;
- }
- Vec_PtrFree( vNodes );
- // clean the marks
- Abc_NtkForEachNode( pNtk, pNode, i )
- {
- pNode->fMarkA = 0;
- if ( Abc_NodeIsConst(pNode) )
- continue;
- assert( Abc_ObjFaninLMin(pNode) == 0 );
- }
-}
-
-/**Function*************************************************************
-
- Synopsis [Performs forward retiming of the sequential AIG.]
-
- Description []
-
- SideEffects []
-
- SeeAlso []
-
-***********************************************************************/
-void Abc_NtkSeqRetimeBackward( Abc_Ntk_t * pNtk )
-{
- Vec_Ptr_t * vNodes;
- Abc_Obj_t * pNode, * pFanin, * pFanout;
- int i, k, nLatches;
- assert( Abc_NtkIsSeq( pNtk ) );
- // assume that all nodes can be retimed
- vNodes = Vec_PtrAlloc( 100 );
- Abc_NtkForEachNode( pNtk, pNode, i )
- {
- if ( Abc_NodeIsConst(pNode) )
- continue;
- Vec_PtrPush( vNodes, pNode );
- pNode->fMarkA = 1;
- }
- // process the nodes
- Vec_PtrForEachEntry( vNodes, pNode, i )
- {
- // get the number of latches to retime
- nLatches = Abc_ObjFanoutLMin(pNode);
- if ( nLatches == 0 )
- continue;
- assert( nLatches > 0 );
- // subtract these latches on the fanout side
- Abc_ObjForEachFanout( pNode, pFanout, k )
- Abc_ObjAddFanoutL( pNode, pFanout, -nLatches );
- // add these latches on the fanin size
- Abc_ObjForEachFanin( pNode, pFanin, k )
- {
- Abc_ObjAddFaninL( pNode, k, nLatches );
- if ( Abc_ObjIsPi(pFanin) || Abc_NodeIsConst(pFanin) )
- continue;
- if ( pFanin->fMarkA == 0 )
- { // schedule the node for updating
- Vec_PtrPush( vNodes, pFanin );
- pFanin->fMarkA = 1;
- }
- }
- // unmark the node as processed
- pNode->fMarkA = 0;
- }
- Vec_PtrFree( vNodes );
- // clean the marks
- Abc_NtkForEachNode( pNtk, pNode, i )
- {
- pNode->fMarkA = 0;
- if ( Abc_NodeIsConst(pNode) )
- continue;
-// assert( Abc_ObjFanoutLMin(pNode) == 0 );
- }
-}
-
-
-
-
-/**Function*************************************************************
-
- Synopsis [Returns the latch number of the fanout.]
-
- Description []
-
- SideEffects []
-
- SeeAlso []
-
-***********************************************************************/
-int Abc_ObjFanoutL( Abc_Obj_t * pObj, Abc_Obj_t * pFanout )
-{
- assert( Abc_NtkIsSeq(pObj->pNtk) );
- if ( Abc_ObjFaninId0(pFanout) == (int)pObj->Id )
- return Abc_ObjFaninL0(pFanout);
- else if ( Abc_ObjFaninId1(pFanout) == (int)pObj->Id )
- return Abc_ObjFaninL1(pFanout);
- else
- assert( 0 );
- return 0;
-}
-
-/**Function*************************************************************
-
- Synopsis [Sets the latch number of the fanout.]
-
- Description []
-
- SideEffects []
-
- SeeAlso []
-
-***********************************************************************/
-void Abc_ObjSetFanoutL( Abc_Obj_t * pObj, Abc_Obj_t * pFanout, int nLats )
-{
- assert( Abc_NtkIsSeq(pObj->pNtk) );
- if ( Abc_ObjFaninId0(pFanout) == (int)pObj->Id )
- Abc_ObjSetFaninL0(pFanout, nLats);
- else if ( Abc_ObjFaninId1(pFanout) == (int)pObj->Id )
- Abc_ObjSetFaninL1(pFanout, nLats);
- else
- assert( 0 );
-}
-
-/**Function*************************************************************
-
- Synopsis [Adds to the latch number of the fanout.]
-
- Description []
-
- SideEffects []
-
- SeeAlso []
-
-***********************************************************************/
-void Abc_ObjAddFanoutL( Abc_Obj_t * pObj, Abc_Obj_t * pFanout, int nLats )
-{
- assert( Abc_NtkIsSeq(pObj->pNtk) );
- if ( Abc_ObjFaninId0(pFanout) == (int)pObj->Id )
- Abc_ObjAddFaninL0(pFanout, nLats);
- else if ( Abc_ObjFaninId1(pFanout) == (int)pObj->Id )
- Abc_ObjAddFaninL1(pFanout, nLats);
- else
- assert( 0 );
-}
-
-/**Function*************************************************************
-
- Synopsis [Returns the latch number of the fanout.]
-
- Description []
-
- SideEffects []
-
- SeeAlso []
-
-***********************************************************************/
-int Abc_ObjFanoutLMax( Abc_Obj_t * pObj )
-{
- Abc_Obj_t * pFanout;
- int i, nLatch, nLatchRes;
- nLatchRes = 0;
- Abc_ObjForEachFanout( pObj, pFanout, i )
- if ( nLatchRes < (nLatch = Abc_ObjFanoutL(pObj, pFanout)) )
- nLatchRes = nLatch;
- assert( nLatchRes >= 0 );
- return nLatchRes;
-}
-
-/**Function*************************************************************
-
- Synopsis [Returns the latch number of the fanout.]
-
- Description []
-
- SideEffects []
-
- SeeAlso []
-
-***********************************************************************/
-int Abc_ObjFanoutLMin( Abc_Obj_t * pObj )
-{
- Abc_Obj_t * pFanout;
- int i, nLatch, nLatchRes;
- nLatchRes = ABC_INFINITY;
- Abc_ObjForEachFanout( pObj, pFanout, i )
- if ( nLatchRes > (nLatch = Abc_ObjFanoutL(pObj, pFanout)) )
- nLatchRes = nLatch;
- assert( nLatchRes < ABC_INFINITY );
- return nLatchRes;
-}
-
-
-////////////////////////////////////////////////////////////////////////
-/// END OF FILE ///
-////////////////////////////////////////////////////////////////////////
-
-
diff --git a/src/base/abcs/module.make b/src/base/abcs/module.make
deleted file mode 100644
index ad084bb8..00000000
--- a/src/base/abcs/module.make
+++ /dev/null
@@ -1,2 +0,0 @@
-SRC += src/base/abcs/abcRetime.c \
- src/base/abcs/abcSeq.c
diff --git a/src/base/cmd/cmd.c b/src/base/cmd/cmd.c
index 9195554a..2dc03d5c 100644
--- a/src/base/cmd/cmd.c
+++ b/src/base/cmd/cmd.c
@@ -18,6 +18,10 @@
***********************************************************************/
+#ifdef WIN32
+#include <process.h>
+#endif
+
#include "mainInt.h"
#include "cmdInt.h"
#include "abc.h"
@@ -45,9 +49,10 @@ static int CmdCommandLs ( Abc_Frame_t * pAbc, int argc, char ** argv
#endif
static int CmdCommandSis ( Abc_Frame_t * pAbc, int argc, char ** argv );
static int CmdCommandMvsis ( Abc_Frame_t * pAbc, int argc, char ** argv );
+static int CmdCommandCapo ( Abc_Frame_t * pAbc, int argc, char ** argv );
////////////////////////////////////////////////////////////////////////
-/// FUNCTION DEFITIONS ///
+/// FUNCTION DEFINITIONS ///
////////////////////////////////////////////////////////////////////////
/**Function********************************************************************
@@ -85,6 +90,7 @@ void Cmd_Init( Abc_Frame_t * pAbc )
Cmd_CommandAdd( pAbc, "Various", "sis", CmdCommandSis, 1);
Cmd_CommandAdd( pAbc, "Various", "mvsis", CmdCommandMvsis, 1);
+ Cmd_CommandAdd( pAbc, "Various", "capo", CmdCommandCapo, 0);
}
/**Function********************************************************************
@@ -142,8 +148,8 @@ int CmdCommandTime( Abc_Frame_t * pAbc, int argc, char **argv )
{
int c;
- util_getopt_reset();
- while ( ( c = util_getopt( argc, argv, "h" ) ) != EOF )
+ Extra_UtilGetoptReset();
+ while ( ( c = Extra_UtilGetopt( argc, argv, "h" ) ) != EOF )
{
switch ( c )
{
@@ -154,7 +160,7 @@ int CmdCommandTime( Abc_Frame_t * pAbc, int argc, char **argv )
}
}
- if ( argc != util_optind )
+ if ( argc != globalUtilOptind )
{
goto usage;
}
@@ -162,6 +168,14 @@ int CmdCommandTime( Abc_Frame_t * pAbc, int argc, char **argv )
pAbc->TimeTotal += pAbc->TimeCommand;
fprintf( pAbc->Out, "elapse: %3.2f seconds, total: %3.2f seconds\n",
(float)pAbc->TimeCommand / CLOCKS_PER_SEC, (float)pAbc->TimeTotal / CLOCKS_PER_SEC );
+/*
+ {
+ FILE * pTable;
+ pTable = fopen( "runtimes.txt", "a+" );
+ fprintf( pTable, "%4.2f\n", (float)pAbc->TimeCommand / CLOCKS_PER_SEC );
+ fclose( pTable );
+ }
+*/
pAbc->TimeCommand = 0;
return 0;
@@ -188,8 +202,8 @@ int CmdCommandEcho( Abc_Frame_t * pAbc, int argc, char **argv )
int c;
int n = 1;
- util_getopt_reset();
- while ( ( c = util_getopt( argc, argv, "hn" ) ) != EOF )
+ Extra_UtilGetoptReset();
+ while ( ( c = Extra_UtilGetopt( argc, argv, "hn" ) ) != EOF )
{
switch ( c )
{
@@ -204,7 +218,7 @@ int CmdCommandEcho( Abc_Frame_t * pAbc, int argc, char **argv )
}
}
- for ( i = util_optind; i < argc; i++ )
+ for ( i = globalUtilOptind; i < argc; i++ )
fprintf( pAbc->Out, "%s ", argv[i] );
if ( n )
fprintf( pAbc->Out, "\n" );
@@ -234,8 +248,8 @@ int CmdCommandQuit( Abc_Frame_t * pAbc, int argc, char **argv )
{
int c;
- util_getopt_reset();
- while ( ( c = util_getopt( argc, argv, "hs" ) ) != EOF )
+ Extra_UtilGetoptReset();
+ while ( ( c = Extra_UtilGetopt( argc, argv, "hs" ) ) != EOF )
{
switch ( c )
{
@@ -250,7 +264,7 @@ int CmdCommandQuit( Abc_Frame_t * pAbc, int argc, char **argv )
}
}
- if ( argc != util_optind )
+ if ( argc != globalUtilOptind )
goto usage;
return -1;
@@ -294,8 +308,8 @@ int CmdCommandHistory( Abc_Frame_t * pAbc, int argc, char **argv )
int i, c, num, size;
num = 20;
- util_getopt_reset();
- while ( ( c = util_getopt( argc, argv, "h" ) ) != EOF )
+ Extra_UtilGetoptReset();
+ while ( ( c = Extra_UtilGetopt( argc, argv, "h" ) ) != EOF )
{
switch ( c )
{
@@ -309,8 +323,8 @@ int CmdCommandHistory( Abc_Frame_t * pAbc, int argc, char **argv )
goto usage;
// get the number of commands to print
- if ( argc == util_optind + 1 )
- num = atoi(argv[util_optind]);
+ if ( argc == globalUtilOptind + 1 )
+ num = atoi(argv[globalUtilOptind]);
// print the commands
size = pAbc->aHistory->nSize;
num = ( num < size ) ? num : size;
@@ -342,8 +356,8 @@ int CmdCommandAlias( Abc_Frame_t * pAbc, int argc, char **argv )
char *key, *value;
int c;
- util_getopt_reset();
- while ( ( c = util_getopt( argc, argv, "h" ) ) != EOF )
+ Extra_UtilGetoptReset();
+ while ( ( c = Extra_UtilGetopt( argc, argv, "h" ) ) != EOF )
{
switch ( c )
{
@@ -399,8 +413,8 @@ int CmdCommandUnalias( Abc_Frame_t * pAbc, int argc, char **argv )
char *key, *value;
int c;
- util_getopt_reset();
- while ( ( c = util_getopt( argc, argv, "h" ) ) != EOF )
+ Extra_UtilGetoptReset();
+ while ( ( c = Extra_UtilGetopt( argc, argv, "h" ) ) != EOF )
{
switch ( c )
{
@@ -450,8 +464,8 @@ int CmdCommandHelp( Abc_Frame_t * pAbc, int argc, char **argv )
int c;
fPrintAll = 0;
- util_getopt_reset();
- while ( ( c = util_getopt( argc, argv, "ah" ) ) != EOF )
+ Extra_UtilGetoptReset();
+ while ( ( c = Extra_UtilGetopt( argc, argv, "ah" ) ) != EOF )
{
switch ( c )
{
@@ -468,7 +482,7 @@ int CmdCommandHelp( Abc_Frame_t * pAbc, int argc, char **argv )
}
}
- if ( argc != util_optind )
+ if ( argc != globalUtilOptind )
goto usage;
CmdCommandPrint( pAbc, fPrintAll );
@@ -503,38 +517,37 @@ int CmdCommandSource( Abc_Frame_t * pAbc, int argc, char **argv )
interactive = silent = prompt = echo = 0;
- util_getopt_reset();
- while ( ( c = util_getopt( argc, argv, "hipsx" ) ) != EOF )
+ Extra_UtilGetoptReset();
+ while ( ( c = Extra_UtilGetopt( argc, argv, "ipsxh" ) ) != EOF )
{
switch ( c )
{
- case 'h':
- goto usage;
- break;
case 'i': /* a hack to distinguish EOF from stdin */
interactive = 1;
break;
case 'p':
- prompt = 1;
+ prompt ^= 1;
break;
case 's':
- silent = 1;
+ silent ^= 1;
break;
case 'x':
echo ^= 1;
break;
+ case 'h':
+ goto usage;
default:
goto usage;
}
}
/* added to avoid core-dumping when no script file is specified */
- if ( argc == util_optind )
+ if ( argc == globalUtilOptind )
{
goto usage;
}
- lp_file_index = util_optind;
+ lp_file_index = globalUtilOptind;
lp_count = 0;
/*
@@ -568,7 +581,7 @@ int CmdCommandSource( Abc_Frame_t * pAbc, int argc, char **argv )
}
else
{
- prompt_string = NIL( char );
+ prompt_string = NULL;
}
/* clear errors -- e.g., EOF reached from stdin */
@@ -602,7 +615,7 @@ int CmdCommandSource( Abc_Frame_t * pAbc, int argc, char **argv )
fprintf( pAbc->Out, "abc - > %s", line );
}
command = CmdHistorySubstitution( pAbc, line, &did_subst );
- if ( command == NIL( char ) )
+ if ( command == NULL )
{
status = 1;
break;
@@ -620,8 +633,8 @@ int CmdCommandSource( Abc_Frame_t * pAbc, int argc, char **argv )
}
if ( interactive && *line != '\0' )
{
- Cmd_HistoryAddCommand( pAbc, util_strsav(line) );
- if ( pAbc->Hst != NIL( FILE ) )
+ Cmd_HistoryAddCommand( pAbc, Extra_UtilStrsav(line) );
+ if ( pAbc->Hst != NULL )
{
fprintf( pAbc->Hst, "%s\n", line );
( void ) fflush( pAbc->Hst );
@@ -650,11 +663,11 @@ int CmdCommandSource( Abc_Frame_t * pAbc, int argc, char **argv )
return status;
usage:
- fprintf( pAbc->Err, "usage: source [-h] [-p] [-s] [-x] file_name\n" );
+ fprintf( pAbc->Err, "usage: source [-psxh] <file_name>\n" );
+ fprintf( pAbc->Err, "\t-p supply prompt before reading each line [default = %s]\n", prompt? "yes": "no" );
+ fprintf( pAbc->Err, "\t-s silently ignore nonexistant file [default = %s]\n", silent? "yes": "no" );
+ fprintf( pAbc->Err, "\t-x echo each line as it is executed [default = %s]\n", echo? "yes": "no" );
fprintf( pAbc->Err, "\t-h print the command usage\n" );
- fprintf( pAbc->Err, "\t-p supply prompt before reading each line\n" );
- fprintf( pAbc->Err, "\t-s silently ignore nonexistant file\n" );
- fprintf( pAbc->Err, "\t-x echo each line as it is executed\n" );
return 1;
}
@@ -674,8 +687,8 @@ int CmdCommandSetVariable( Abc_Frame_t * pAbc, int argc, char **argv )
char *flag_value, *key, *value;
int c;
- util_getopt_reset();
- while ( ( c = util_getopt( argc, argv, "h" ) ) != EOF )
+ Extra_UtilGetoptReset();
+ while ( ( c = Extra_UtilGetopt( argc, argv, "h" ) ) != EOF )
{
switch ( c )
{
@@ -703,9 +716,9 @@ int CmdCommandSetVariable( Abc_Frame_t * pAbc, int argc, char **argv )
FREE( value );
}
- flag_value = argc == 2 ? util_strsav( "" ) : util_strsav( argv[2] );
-// flag_value = argc == 2 ? NULL : util_strsav(argv[2]);
- st_insert( pAbc->tFlags, util_strsav(argv[1]), flag_value );
+ flag_value = argc == 2 ? Extra_UtilStrsav( "" ) : Extra_UtilStrsav( argv[2] );
+// flag_value = argc == 2 ? NULL : Extra_UtilStrsav(argv[2]);
+ st_insert( pAbc->tFlags, Extra_UtilStrsav(argv[1]), flag_value );
if ( strcmp( argv[1], "abcout" ) == 0 )
{
@@ -713,7 +726,7 @@ int CmdCommandSetVariable( Abc_Frame_t * pAbc, int argc, char **argv )
fclose( pAbc->Out );
if ( strcmp( flag_value, "" ) == 0 )
flag_value = "-";
- pAbc->Out = CmdFileOpen( pAbc, flag_value, "w", NIL( char * ), 0 );
+ pAbc->Out = CmdFileOpen( pAbc, flag_value, "w", NULL, 0 );
if ( pAbc->Out == NULL )
pAbc->Out = stdout;
#if HAVE_SETVBUF
@@ -726,7 +739,7 @@ int CmdCommandSetVariable( Abc_Frame_t * pAbc, int argc, char **argv )
fclose( pAbc->Err );
if ( strcmp( flag_value, "" ) == 0 )
flag_value = "-";
- pAbc->Err = CmdFileOpen( pAbc, flag_value, "w", NIL( char * ), 0 );
+ pAbc->Err = CmdFileOpen( pAbc, flag_value, "w", NULL, 0 );
if ( pAbc->Err == NULL )
pAbc->Err = stderr;
#if HAVE_SETVBUF
@@ -735,15 +748,15 @@ int CmdCommandSetVariable( Abc_Frame_t * pAbc, int argc, char **argv )
}
if ( strcmp( argv[1], "history" ) == 0 )
{
- if ( pAbc->Hst != NIL( FILE ) )
+ if ( pAbc->Hst != NULL )
fclose( pAbc->Hst );
if ( strcmp( flag_value, "" ) == 0 )
- pAbc->Hst = NIL( FILE );
+ pAbc->Hst = NULL;
else
{
- pAbc->Hst = CmdFileOpen( pAbc, flag_value, "w", NIL( char * ), 0 );
+ pAbc->Hst = CmdFileOpen( pAbc, flag_value, "w", NULL, 0 );
if ( pAbc->Hst == NULL )
- pAbc->Hst = NIL( FILE );
+ pAbc->Hst = NULL;
}
}
return 0;
@@ -774,8 +787,8 @@ int CmdCommandUnsetVariable( Abc_Frame_t * pAbc, int argc, char **argv )
char *key, *value;
int c;
- util_getopt_reset();
- while ( ( c = util_getopt( argc, argv, "h" ) ) != EOF )
+ Extra_UtilGetoptReset();
+ while ( ( c = Extra_UtilGetopt( argc, argv, "h" ) ) != EOF )
{
switch ( c )
{
@@ -867,8 +880,8 @@ int CmdCommandRecall( Abc_Frame_t * pAbc, int argc, char **argv )
}
- util_getopt_reset();
- while ( ( c = util_getopt( argc, argv, "h" ) ) != EOF )
+ Extra_UtilGetoptReset();
+ while ( ( c = Extra_UtilGetopt( argc, argv, "h" ) ) != EOF )
{
switch ( c )
{
@@ -979,8 +992,8 @@ int CmdCommandEmpty( Abc_Frame_t * pAbc, int argc, char **argv )
return 0;
}
- util_getopt_reset();
- while ( ( c = util_getopt( argc, argv, "h" ) ) != EOF )
+ Extra_UtilGetoptReset();
+ while ( ( c = Extra_UtilGetopt( argc, argv, "h" ) ) != EOF )
{
switch ( c )
{
@@ -1021,7 +1034,7 @@ int CmdCommandUndo( Abc_Frame_t * pAbc, int argc, char **argv )
Abc_Ntk_t * pNtkTemp;
int id, c;
- while ( ( c = util_getopt( argc, argv, "h" ) ) != EOF )
+ while ( ( c = Extra_UtilGetopt( argc, argv, "h" ) ) != EOF )
{
switch ( c )
{
@@ -1032,12 +1045,12 @@ int CmdCommandUndo( Abc_Frame_t * pAbc, int argc, char **argv )
goto usage;
}
}
- if (util_optind <= argc) {
+ if (globalUtilOptind <= argc) {
pNtkTemp = pAbc->pNtk;
pAbc->pNtk = pAbc->pNtkSaved;
pAbc->pNtkSaved = pNtkTemp;
}
- id = atoi(argv[util_optind]);
+ id = atoi(argv[globalUtilOptind]);
pNtkTemp = Cmd_HistoryGetSnapshot(pAbc, id);
if (!pNtkTemp)
fprintf( pAbc->Err, "Snapshot %d does not exist\n", id);
@@ -1095,8 +1108,8 @@ int CmdCommandLs( Abc_Frame_t * pAbc, int argc, char **argv )
int fPrintedNewLine;
char c;
- util_getopt_reset();
- while ( (c = util_getopt(argc, argv, "lb") ) != EOF )
+ Extra_UtilGetoptReset();
+ while ( (c = Extra_UtilGetopt(argc, argv, "lb") ) != EOF )
{
switch (c)
{
@@ -1204,7 +1217,7 @@ int CmdCommandSis( Abc_Frame_t * pAbc, int argc, char **argv )
char * pSisName;
int i;
- pNtk = Abc_FrameReadNet(pAbc);
+ pNtk = Abc_FrameReadNtk(pAbc);
pOut = Abc_FrameReadOut(pAbc);
pErr = Abc_FrameReadErr(pAbc);
@@ -1245,8 +1258,21 @@ int CmdCommandSis( Abc_Frame_t * pAbc, int argc, char **argv )
}
fclose( pFile );
+ if ( Abc_NtkIsMappedLogic(pNtk) )
+ {
+ Abc_NtkMapToSop(pNtk);
+ printf( "The current network is unmapped before calling SIS.\n" );
+ }
+
// write out the current network
- pNetlist = Abc_NtkLogicToNetlist(pNtk);
+ if ( Abc_NtkIsLogic(pNtk) )
+ Abc_NtkToSop(pNtk, 0);
+ pNetlist = Abc_NtkToNetlist(pNtk);
+ if ( pNetlist == NULL )
+ {
+ fprintf( pErr, "Cannot produce the intermediate network.\n" );
+ goto usage;
+ }
Io_WriteBlif( pNetlist, "_sis_in.blif", 1 );
Abc_NtkDelete( pNetlist );
@@ -1283,12 +1309,12 @@ int CmdCommandSis( Abc_Frame_t * pAbc, int argc, char **argv )
fclose( pFile );
// set the new network
- pNtkNew = Io_Read( "_sis_out.blif", 1 );
+ pNtkNew = Io_Read( "_sis_out.blif", IO_FILE_BLIF, 1 );
// set the original spec of the new network
if ( pNtk->pSpec )
{
FREE( pNtkNew->pSpec );
- pNtkNew->pSpec = util_strsav( pNtk->pSpec );
+ pNtkNew->pSpec = Extra_UtilStrsav( pNtk->pSpec );
}
// replace the current network
Abc_FrameReplaceCurrentNetwork( pAbc, pNtkNew );
@@ -1334,7 +1360,7 @@ int CmdCommandMvsis( Abc_Frame_t * pAbc, int argc, char **argv )
char * pMvsisName;
int i;
- pNtk = Abc_FrameReadNet(pAbc);
+ pNtk = Abc_FrameReadNtk(pAbc);
pOut = Abc_FrameReadOut(pAbc);
pErr = Abc_FrameReadErr(pAbc);
@@ -1375,9 +1401,21 @@ int CmdCommandMvsis( Abc_Frame_t * pAbc, int argc, char **argv )
}
fclose( pFile );
+ if ( Abc_NtkIsMappedLogic(pNtk) )
+ {
+ Abc_NtkMapToSop(pNtk);
+ printf( "The current network is unmapped before calling MVSIS.\n" );
+ }
// write out the current network
- pNetlist = Abc_NtkLogicToNetlist(pNtk);
+ if ( Abc_NtkIsLogic(pNtk) )
+ Abc_NtkToSop(pNtk, 0);
+ pNetlist = Abc_NtkToNetlist(pNtk);
+ if ( pNetlist == NULL )
+ {
+ fprintf( pErr, "Cannot produce the intermediate network.\n" );
+ goto usage;
+ }
Io_WriteBlif( pNetlist, "_mvsis_in.blif", 1 );
Abc_NtkDelete( pNetlist );
@@ -1414,12 +1452,12 @@ int CmdCommandMvsis( Abc_Frame_t * pAbc, int argc, char **argv )
fclose( pFile );
// set the new network
- pNtkNew = Io_Read( "_mvsis_out.blif", 1 );
+ pNtkNew = Io_Read( "_mvsis_out.blif", IO_FILE_BLIF, 1 );
// set the original spec of the new network
if ( pNtk->pSpec )
{
FREE( pNtkNew->pSpec );
- pNtkNew->pSpec = util_strsav( pNtk->pSpec );
+ pNtkNew->pSpec = Extra_UtilStrsav( pNtk->pSpec );
}
// replace the current network
Abc_FrameReplaceCurrentNetwork( pAbc, pNtkNew );
@@ -1443,6 +1481,192 @@ usage:
}
+/**Function********************************************************************
+
+ Synopsis [Calls Capo internally.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+******************************************************************************/
+int CmdCommandCapo( Abc_Frame_t * pAbc, int argc, char **argv )
+{
+ FILE * pFile;
+ FILE * pOut, * pErr;
+ Abc_Ntk_t * pNtk, * pNetlist;
+ char Command[1000], Buffer[100];
+ char * pProgNameCapoWin = "capo.exe";
+ char * pProgNameCapoUnix = "capo";
+ char * pProgNameGnuplotWin = "wgnuplot.exe";
+ char * pProgNameGnuplotUnix = "gnuplot";
+ char * pProgNameCapo;
+ char * pProgNameGnuplot;
+ char * pPlotFileName;
+ int i;
+
+ pNtk = Abc_FrameReadNtk(pAbc);
+ pOut = Abc_FrameReadOut(pAbc);
+ pErr = Abc_FrameReadErr(pAbc);
+
+ if ( pNtk == NULL )
+ {
+ fprintf( pErr, "Empty network.\n" );
+ goto usage;
+ }
+
+ if ( strcmp( argv[0], "capo" ) != 0 )
+ {
+ fprintf( pErr, "Wrong command: \"%s\".\n", argv[0] );
+ goto usage;
+ }
+
+ if ( argc > 1 )
+ {
+ if ( strcmp( argv[1], "-h" ) == 0 )
+ goto usage;
+ if ( strcmp( argv[1], "-?" ) == 0 )
+ goto usage;
+ }
+
+ // get the names from the resource file
+ if ( Cmd_FlagReadByName(pAbc, "capowin") )
+ pProgNameCapoWin = Cmd_FlagReadByName(pAbc, "capowin");
+ if ( Cmd_FlagReadByName(pAbc, "capounix") )
+ pProgNameCapoUnix = Cmd_FlagReadByName(pAbc, "capounix");
+
+ // check if capo is available
+ if ( (pFile = fopen( pProgNameCapoWin, "r" )) )
+ pProgNameCapo = pProgNameCapoWin;
+ else if ( (pFile = fopen( pProgNameCapoUnix, "r" )) )
+ pProgNameCapo = pProgNameCapoUnix;
+ else if ( pFile == NULL )
+ {
+ fprintf( pErr, "Cannot find \"%s\" or \"%s\" in the current directory.\n", pProgNameCapoWin, pProgNameCapoUnix );
+ goto usage;
+ }
+ fclose( pFile );
+
+ if ( Abc_NtkIsMappedLogic(pNtk) )
+ {
+ Abc_NtkMapToSop(pNtk);
+ printf( "The current network is unmapped before calling Capo.\n" );
+ }
+
+ // write out the current network
+ if ( Abc_NtkIsLogic(pNtk) )
+ Abc_NtkToSop(pNtk, 0);
+ pNetlist = Abc_NtkToNetlist(pNtk);
+ if ( pNetlist == NULL )
+ {
+ fprintf( pErr, "Cannot produce the intermediate network.\n" );
+ goto usage;
+ }
+ Io_WriteBlif( pNetlist, "_capo_in.blif", 1 );
+ Abc_NtkDelete( pNetlist );
+
+ // create the file for Capo
+ sprintf( Command, "%s -f _capo_in.blif -log out.txt ", pProgNameCapo );
+ pPlotFileName = NULL;
+ for ( i = 1; i < argc; i++ )
+ {
+ sprintf( Buffer, " %s", argv[i] );
+ strcat( Command, Buffer );
+ if ( !strcmp( argv[i], "-plot" ) )
+ pPlotFileName = argv[i+1];
+ }
+
+ // call Capo
+ if ( system( Command ) )
+ {
+ fprintf( pErr, "The following command has returned non-zero exit status:\n" );
+ fprintf( pErr, "\"%s\"\n", Command );
+ unlink( "_capo_in.blif" );
+ goto usage;
+ }
+ // remove temporary networks
+ unlink( "_capo_in.blif" );
+ if ( pPlotFileName == NULL )
+ return 0;
+
+ // get the file name
+ sprintf( Buffer, "%s.plt", pPlotFileName );
+ pPlotFileName = Buffer;
+
+ // read in the Capo plotting output
+ if ( (pFile = fopen( pPlotFileName, "r" )) == NULL )
+ {
+ fprintf( pErr, "Cannot open the plot file \"%s\".\n\n", pPlotFileName );
+ goto usage;
+ }
+ fclose( pFile );
+
+ // get the names from the plotting software
+ if ( Cmd_FlagReadByName(pAbc, "gnuplotwin") )
+ pProgNameGnuplotWin = Cmd_FlagReadByName(pAbc, "gnuplotwin");
+ if ( Cmd_FlagReadByName(pAbc, "gnuplotunix") )
+ pProgNameGnuplotUnix = Cmd_FlagReadByName(pAbc, "gnuplotunix");
+
+ // check if Gnuplot is available
+ if ( (pFile = fopen( pProgNameGnuplotWin, "r" )) )
+ pProgNameGnuplot = pProgNameGnuplotWin;
+ else if ( (pFile = fopen( pProgNameGnuplotUnix, "r" )) )
+ pProgNameGnuplot = pProgNameGnuplotUnix;
+ else if ( pFile == NULL )
+ {
+ fprintf( pErr, "Cannot find \"%s\" or \"%s\" in the current directory.\n", pProgNameGnuplotWin, pProgNameGnuplotUnix );
+ goto usage;
+ }
+ fclose( pFile );
+
+ // spawn the viewer
+#ifdef WIN32
+ if ( _spawnl( _P_NOWAIT, pProgNameGnuplot, pProgNameGnuplot, pPlotFileName, NULL ) == -1 )
+ {
+ fprintf( stdout, "Cannot find \"%s\".\n", pProgNameGnuplot );
+ goto usage;
+ }
+#else
+ {
+ sprintf( Command, "%s %s ", pProgNameGnuplot, pPlotFileName );
+ if ( system( Command ) == -1 )
+ {
+ fprintf( stdout, "Cannot execute \"%s\".\n", Command );
+ goto usage;
+ }
+ }
+#endif
+
+ // remove temporary networks
+// unlink( pPlotFileName );
+ return 0;
+
+usage:
+ fprintf( pErr, "\n" );
+ fprintf( pErr, "Usage: capo [-h] <com>\n");
+ fprintf( pErr, " peforms placement of the current network using Capo\n" );
+ fprintf( pErr, " a Capo binary should be present in the same directory\n" );
+ fprintf( pErr, " (if plotting, the Gnuplot binary should also be present)\n" );
+ fprintf( pErr, " -h : print the command usage\n" );
+ fprintf( pErr, " <com> : a Capo command\n" );
+ fprintf( pErr, " Example 1: capo\n" );
+ fprintf( pErr, " (performs placement with default options)\n" );
+ fprintf( pErr, " Example 2: capo -AR <aspec_ratio> -WS <whitespace_percentage> -save\n" );
+ fprintf( pErr, " (specifies the aspect ratio [default = 1.0] and\n" );
+ fprintf( pErr, " the whitespace percentage [0%%; 100%%) [default = 15%%])\n" );
+ fprintf( pErr, " Example 3: capo -plot <base_fileName>\n" );
+ fprintf( pErr, " (produces <base_fileName.plt> and visualize it using Gnuplot)\n" );
+ fprintf( pErr, " Example 4: capo -help\n" );
+ fprintf( pErr, " (prints the default usage message of the Capo binary)\n" );
+ fprintf( pErr, " Please refer to the Capo webpage for additional information:\n" );
+ fprintf( pErr, " http://vlsicad.eecs.umich.edu/BK/PDtools/\n" );
+ return 1; // error exit
+}
+
+
+
////////////////////////////////////////////////////////////////////////
/// END OF FILE ///
////////////////////////////////////////////////////////////////////////
diff --git a/src/base/cmd/cmd.h b/src/base/cmd/cmd.h
index 6389afae..030b77e8 100644
--- a/src/base/cmd/cmd.h
+++ b/src/base/cmd/cmd.h
@@ -21,6 +21,10 @@
#ifndef __CMD_H__
#define __CMD_H__
+#ifdef __cplusplus
+extern "C" {
+#endif
+
////////////////////////////////////////////////////////////////////////
/// INCLUDES ///
////////////////////////////////////////////////////////////////////////
@@ -37,11 +41,11 @@ typedef struct MvCommand Abc_Command; // one command
typedef struct MvAlias Abc_Alias; // one alias
////////////////////////////////////////////////////////////////////////
-/// MACRO DEFITIONS ///
+/// MACRO DEFINITIONS ///
////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////
-/// FUNCTION DEFITIONS ///
+/// FUNCTION DEFINITIONS ///
////////////////////////////////////////////////////////////////////////
/*=== cmd.c ===========================================================*/
@@ -57,9 +61,13 @@ extern void Cmd_FlagUpdateValue( Abc_Frame_t * pAbc, char * key, char * v
/*=== cmdHist.c ========================================================*/
extern void Cmd_HistoryAddCommand( Abc_Frame_t * pAbc, char * command );
+#ifdef __cplusplus
+}
+#endif
+
+#endif
+
////////////////////////////////////////////////////////////////////////
/// END OF FILE ///
////////////////////////////////////////////////////////////////////////
-#endif
-
diff --git a/src/base/cmd/cmdAlias.c b/src/base/cmd/cmdAlias.c
index 59a8b87e..0ec3feea 100644
--- a/src/base/cmd/cmdAlias.c
+++ b/src/base/cmd/cmdAlias.c
@@ -25,7 +25,7 @@
////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////
-/// FUNCTION DEFITIONS ///
+/// FUNCTION DEFINITIONS ///
////////////////////////////////////////////////////////////////////////
/**Function*************************************************************
@@ -45,11 +45,11 @@ void CmdCommandAliasAdd( Abc_Frame_t * pAbc, char * sName, int argc, char ** arg
int fStatus, i;
pAlias = ALLOC(Abc_Alias, 1);
- pAlias->sName = util_strsav(sName);
+ pAlias->sName = Extra_UtilStrsav(sName);
pAlias->argc = argc;
pAlias->argv = ALLOC(char *, pAlias->argc);
for(i = 0; i < argc; i++)
- pAlias->argv[i] = util_strsav(argv[i]);
+ pAlias->argv[i] = Extra_UtilStrsav(argv[i]);
fStatus = st_insert( pAbc->tAliases, pAlias->sName, (char *) pAlias );
assert(!fStatus);
}
diff --git a/src/base/cmd/cmdApi.c b/src/base/cmd/cmdApi.c
index 8dd67637..7167e22b 100644
--- a/src/base/cmd/cmdApi.c
+++ b/src/base/cmd/cmdApi.c
@@ -27,7 +27,7 @@
////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////
-/// FUNCTION DEFITIONS ///
+/// FUNCTION DEFINITIONS ///
////////////////////////////////////////////////////////////////////////
/**Function*************************************************************
@@ -57,8 +57,8 @@ void Cmd_CommandAdd( Abc_Frame_t * pAbc, char * sGroup, char * sName, void * pFu
// create the new command
pCommand = ALLOC( Abc_Command, 1 );
- pCommand->sName = util_strsav( sName );
- pCommand->sGroup = util_strsav( sGroup );
+ pCommand->sName = Extra_UtilStrsav( sName );
+ pCommand->sGroup = Extra_UtilStrsav( sGroup );
pCommand->pFunc = pFunc;
pCommand->fChange = fChanges;
fStatus = st_insert( pAbc->tCommands, sName, (char *)pCommand );
diff --git a/src/base/cmd/cmdFlag.c b/src/base/cmd/cmdFlag.c
index 63a0389d..993f2a49 100644
--- a/src/base/cmd/cmdFlag.c
+++ b/src/base/cmd/cmdFlag.c
@@ -25,7 +25,7 @@
////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////
-/// FUNCTION DEFITIONS ///
+/// FUNCTION DEFINITIONS ///
////////////////////////////////////////////////////////////////////////
@@ -35,8 +35,7 @@
Description [The command parser maintains a table of named values. These
are manipulated using the 'set' and 'unset' commands. The value of the
- named flag is returned, or NIL(char) is returned if the flag has not been
- set.]
+ named flag is returned, or NULL is returned if the flag has not been set.]
SideEffects []
@@ -65,9 +64,9 @@ void Cmd_FlagUpdateValue( Abc_Frame_t * pAbc, char * key, char * value )
if ( !key )
return;
if ( value )
- newValue = util_strsav(value);
+ newValue = Extra_UtilStrsav(value);
else
- newValue = util_strsav("");
+ newValue = Extra_UtilStrsav("");
// newValue = NULL;
if ( st_delete(pAbc->tFlags, &key, &oldValue) )
FREE(oldValue);
diff --git a/src/base/cmd/cmdHist.c b/src/base/cmd/cmdHist.c
index 5b46ea00..fae9382d 100644
--- a/src/base/cmd/cmdHist.c
+++ b/src/base/cmd/cmdHist.c
@@ -27,7 +27,7 @@
////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////
-/// FUNCTION DEFITIONS ///
+/// FUNCTION DEFINITIONS ///
////////////////////////////////////////////////////////////////////////
/**Function*************************************************************
@@ -43,11 +43,11 @@
***********************************************************************/
void Cmd_HistoryAddCommand( Abc_Frame_t * p, char * command )
{
- char Buffer[500];
+ static char Buffer[MAX_STR];
strcpy( Buffer, command );
if ( command[strlen(command)-1] != '\n' )
strcat( Buffer, "\n" );
- Vec_PtrPush( p->aHistory, util_strsav(Buffer) );
+ Vec_PtrPush( p->aHistory, Extra_UtilStrsav(Buffer) );
}
////////////////////////////////////////////////////////////////////////
diff --git a/src/base/cmd/cmdInt.h b/src/base/cmd/cmdInt.h
index d110b634..c082bd94 100644
--- a/src/base/cmd/cmdInt.h
+++ b/src/base/cmd/cmdInt.h
@@ -52,11 +52,11 @@ struct MvAlias
};
////////////////////////////////////////////////////////////////////////
-/// MACRO DEFITIONS ///
+/// MACRO DEFINITIONS ///
////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////
-/// FUNCTION DEFITIONS ///
+/// FUNCTION DEFINITIONS ///
////////////////////////////////////////////////////////////////////////
/*=== cmdAlias.c =============-========================================*/
diff --git a/src/base/cmd/cmdUtils.c b/src/base/cmd/cmdUtils.c
index 71396d3e..47e54bb3 100644
--- a/src/base/cmd/cmdUtils.c
+++ b/src/base/cmd/cmdUtils.c
@@ -30,7 +30,7 @@
static int CmdCommandPrintCompare( Abc_Command ** ppC1, Abc_Command ** ppC2 );
////////////////////////////////////////////////////////////////////////
-/// FUNCTION DEFITIONS ///
+/// FUNCTION DEFINITIONS ///
////////////////////////////////////////////////////////////////////////
/**Function*************************************************************
@@ -121,10 +121,10 @@ int CmdCommandDispatch( Abc_Frame_t * pAbc, int argc, char **argv )
}
// execute the command
- clk = util_cpu_time();
+ clk = Extra_CpuTime();
pFunc = (int (*)(Abc_Frame_t *, int, char **))pCommand->pFunc;
fError = (*pFunc)( pAbc, argc, argv );
- pAbc->TimeCommand += (util_cpu_time() - clk);
+ pAbc->TimeCommand += (Extra_CpuTime() - clk);
// automatic execution of arbitrary command after each command
// usually this is a passive command ...
@@ -245,7 +245,7 @@ int CmdApplyAlias( Abc_Frame_t * pAbc, int *argcp, char ***argvp, int *loop )
argc = *argcp;
argv = *argvp;
stopit = 0;
- for ( ; *loop < 20; ( *loop )++ )
+ for ( ; *loop < 200; ( *loop )++ )
{
if ( argc == 0 )
return 0;
@@ -270,7 +270,7 @@ int CmdApplyAlias( Abc_Frame_t * pAbc, int *argcp, char ***argvp, int *loop )
}
for ( i = 1; i <= added; i++ )
{
- argv[i] = NIL( char );
+ argv[i] = NULL;
}
argc += added;
}
@@ -278,7 +278,7 @@ int CmdApplyAlias( Abc_Frame_t * pAbc, int *argcp, char ***argvp, int *loop )
for ( i = 0, offset = 0; i < alias->argc; i++, offset++ )
{
arg = CmdHistorySubstitution( pAbc, alias->argv[i], &did_subst );
- if ( arg == NIL( char ) )
+ if ( arg == NULL )
{
*argcp = argc;
*argvp = argv;
@@ -383,11 +383,11 @@ FILE * CmdFileOpen( Abc_Frame_t * pAbc, char *sFileName, char *sMode, char **pFi
if (strcmp(sFileName, "-") == 0) {
if (strcmp(sMode, "w") == 0) {
- sRealName = util_strsav( "stdout" );
+ sRealName = Extra_UtilStrsav( "stdout" );
pFile = stdout;
}
else {
- sRealName = util_strsav( "stdin" );
+ sRealName = Extra_UtilStrsav( "stdin" );
pFile = stdin;
}
}
@@ -403,24 +403,24 @@ FILE * CmdFileOpen( Abc_Frame_t * pAbc, char *sFileName, char *sMode, char **pFi
sPathAll = NULL;
}
else if ( sPathUsr == NULL ) {
- sPathAll = util_strsav( sPathLib );
+ sPathAll = Extra_UtilStrsav( sPathLib );
}
else if ( sPathLib == NULL ) {
- sPathAll = util_strsav( sPathUsr );
+ sPathAll = Extra_UtilStrsav( sPathUsr );
}
else {
sPathAll = ALLOC( char, strlen(sPathLib)+strlen(sPathUsr)+5 );
sprintf( sPathAll, "%s:%s",sPathUsr, sPathLib );
}
- if ( sPathAll != NIL(char) ) {
- sRealName = util_file_search(sFileName, sPathAll, "r");
+ if ( sPathAll != NULL ) {
+ sRealName = Extra_UtilFileSearch(sFileName, sPathAll, "r");
FREE( sPathAll );
}
}
- if (sRealName == NIL(char)) {
- sRealName = util_tilde_expand(sFileName);
+ if (sRealName == NULL) {
+ sRealName = Extra_UtilTildeExpand(sFileName);
}
- if ((pFile = fopen(sRealName, sMode)) == NIL(FILE)) {
+ if ((pFile = fopen(sRealName, sMode)) == NULL) {
if (! silent) {
perror(sRealName);
}
diff --git a/src/base/io/io.c b/src/base/io/io.c
index 89703214..fe88a285 100644
--- a/src/base/io/io.c
+++ b/src/base/io/io.c
@@ -26,23 +26,43 @@
////////////////////////////////////////////////////////////////////////
static int IoCommandRead ( Abc_Frame_t * pAbc, int argc, char **argv );
+static int IoCommandReadAiger ( Abc_Frame_t * pAbc, int argc, char **argv );
+static int IoCommandReadBaf ( Abc_Frame_t * pAbc, int argc, char **argv );
static int IoCommandReadBlif ( Abc_Frame_t * pAbc, int argc, char **argv );
+static int IoCommandReadBlifMv ( Abc_Frame_t * pAbc, int argc, char **argv );
static int IoCommandReadBench ( Abc_Frame_t * pAbc, int argc, char **argv );
+static int IoCommandReadDsd ( Abc_Frame_t * pAbc, int argc, char **argv );
static int IoCommandReadEdif ( Abc_Frame_t * pAbc, int argc, char **argv );
static int IoCommandReadEqn ( Abc_Frame_t * pAbc, int argc, char **argv );
-static int IoCommandReadVerilog ( Abc_Frame_t * pAbc, int argc, char **argv );
+static int IoCommandReadInit ( Abc_Frame_t * pAbc, int argc, char **argv );
static int IoCommandReadPla ( Abc_Frame_t * pAbc, int argc, char **argv );
+static int IoCommandReadTruth ( Abc_Frame_t * pAbc, int argc, char **argv );
+static int IoCommandReadVerilog ( Abc_Frame_t * pAbc, int argc, char **argv );
+static int IoCommandReadVer ( Abc_Frame_t * pAbc, int argc, char **argv );
+static int IoCommandReadVerLib ( Abc_Frame_t * pAbc, int argc, char **argv );
+static int IoCommandWrite ( Abc_Frame_t * pAbc, int argc, char **argv );
+static int IoCommandWriteHie ( Abc_Frame_t * pAbc, int argc, char **argv );
+static int IoCommandWriteAiger ( Abc_Frame_t * pAbc, int argc, char **argv );
+static int IoCommandWriteBaf ( Abc_Frame_t * pAbc, int argc, char **argv );
static int IoCommandWriteBlif ( Abc_Frame_t * pAbc, int argc, char **argv );
+static int IoCommandWriteBlifMv ( Abc_Frame_t * pAbc, int argc, char **argv );
static int IoCommandWriteBench ( Abc_Frame_t * pAbc, int argc, char **argv );
+static int IoCommandWriteCellNet( Abc_Frame_t * pAbc, int argc, char **argv );
static int IoCommandWriteCnf ( Abc_Frame_t * pAbc, int argc, char **argv );
+static int IoCommandWriteCounter( Abc_Frame_t * pAbc, int argc, char **argv );
static int IoCommandWriteDot ( Abc_Frame_t * pAbc, int argc, char **argv );
static int IoCommandWriteEqn ( Abc_Frame_t * pAbc, int argc, char **argv );
static int IoCommandWriteGml ( Abc_Frame_t * pAbc, int argc, char **argv );
+static int IoCommandWriteList ( Abc_Frame_t * pAbc, int argc, char **argv );
static int IoCommandWritePla ( Abc_Frame_t * pAbc, int argc, char **argv );
+static int IoCommandWriteVerilog( Abc_Frame_t * pAbc, int argc, char **argv );
+static int IoCommandWriteVerLib ( Abc_Frame_t * pAbc, int argc, char **argv );
+
+extern int glo_fMapped;
////////////////////////////////////////////////////////////////////////
-/// FUNCTION DEFITIONS ///
+/// FUNCTION DEFINITIONS ///
////////////////////////////////////////////////////////////////////////
/**Function*************************************************************
@@ -59,20 +79,38 @@ static int IoCommandWritePla ( Abc_Frame_t * pAbc, int argc, char **argv );
void Io_Init( Abc_Frame_t * pAbc )
{
Cmd_CommandAdd( pAbc, "I/O", "read", IoCommandRead, 1 );
+ Cmd_CommandAdd( pAbc, "I/O", "read_aiger", IoCommandReadAiger, 1 );
+ Cmd_CommandAdd( pAbc, "I/O", "read_baf", IoCommandReadBaf, 1 );
Cmd_CommandAdd( pAbc, "I/O", "read_blif", IoCommandReadBlif, 1 );
+ Cmd_CommandAdd( pAbc, "I/O", "read_blif_mv", IoCommandReadBlifMv, 1 );
Cmd_CommandAdd( pAbc, "I/O", "read_bench", IoCommandReadBench, 1 );
- Cmd_CommandAdd( pAbc, "I/O", "read_edif", IoCommandReadEdif, 1 );
+ Cmd_CommandAdd( pAbc, "I/O", "read_dsd", IoCommandReadDsd, 1 );
+// Cmd_CommandAdd( pAbc, "I/O", "read_edif", IoCommandReadEdif, 1 );
Cmd_CommandAdd( pAbc, "I/O", "read_eqn", IoCommandReadEqn, 1 );
- Cmd_CommandAdd( pAbc, "I/O", "read_verilog", IoCommandReadVerilog, 1 );
+ Cmd_CommandAdd( pAbc, "I/O", "read_init", IoCommandReadInit, 1 );
Cmd_CommandAdd( pAbc, "I/O", "read_pla", IoCommandReadPla, 1 );
+ Cmd_CommandAdd( pAbc, "I/O", "read_truth", IoCommandReadTruth, 1 );
+ Cmd_CommandAdd( pAbc, "I/O", "read_verilog", IoCommandReadVerilog, 1 );
+// Cmd_CommandAdd( pAbc, "I/O", "read_ver", IoCommandReadVer, 1 );
+// Cmd_CommandAdd( pAbc, "I/O", "read_verlib", IoCommandReadVerLib, 0 );
+ Cmd_CommandAdd( pAbc, "I/O", "write", IoCommandWrite, 0 );
+ Cmd_CommandAdd( pAbc, "I/O", "write_hie", IoCommandWriteHie, 0 );
+ Cmd_CommandAdd( pAbc, "I/O", "write_aiger", IoCommandWriteAiger, 0 );
+ Cmd_CommandAdd( pAbc, "I/O", "write_baf", IoCommandWriteBaf, 0 );
Cmd_CommandAdd( pAbc, "I/O", "write_blif", IoCommandWriteBlif, 0 );
+ Cmd_CommandAdd( pAbc, "I/O", "write_blif_mv", IoCommandWriteBlifMv, 0 );
Cmd_CommandAdd( pAbc, "I/O", "write_bench", IoCommandWriteBench, 0 );
+ Cmd_CommandAdd( pAbc, "I/O", "write_cellnet", IoCommandWriteCellNet, 0 );
+ Cmd_CommandAdd( pAbc, "I/O", "write_counter", IoCommandWriteCounter, 0 );
Cmd_CommandAdd( pAbc, "I/O", "write_cnf", IoCommandWriteCnf, 0 );
Cmd_CommandAdd( pAbc, "I/O", "write_dot", IoCommandWriteDot, 0 );
Cmd_CommandAdd( pAbc, "I/O", "write_eqn", IoCommandWriteEqn, 0 );
Cmd_CommandAdd( pAbc, "I/O", "write_gml", IoCommandWriteGml, 0 );
+// Cmd_CommandAdd( pAbc, "I/O", "write_list", IoCommandWriteList, 0 );
Cmd_CommandAdd( pAbc, "I/O", "write_pla", IoCommandWritePla, 0 );
+ Cmd_CommandAdd( pAbc, "I/O", "write_verilog", IoCommandWriteVerilog, 0 );
+// Cmd_CommandAdd( pAbc, "I/O", "write_verlib", IoCommandWriteVerLib, 0 );
}
/**Function*************************************************************
@@ -104,17 +142,20 @@ void Io_End()
int IoCommandRead( Abc_Frame_t * pAbc, int argc, char ** argv )
{
Abc_Ntk_t * pNtk;
- char * FileName;
- FILE * pFile;
+ char * pFileName;
int fCheck;
int c;
fCheck = 1;
- util_getopt_reset();
- while ( ( c = util_getopt( argc, argv, "ch" ) ) != EOF )
+ glo_fMapped = 0;
+ Extra_UtilGetoptReset();
+ while ( ( c = Extra_UtilGetopt( argc, argv, "mch" ) ) != EOF )
{
switch ( c )
{
+ case 'm':
+ glo_fMapped ^= 1;
+ break;
case 'c':
fCheck ^= 1;
break;
@@ -124,38 +165,132 @@ int IoCommandRead( Abc_Frame_t * pAbc, int argc, char ** argv )
goto usage;
}
}
+ if ( argc != globalUtilOptind + 1 )
+ goto usage;
+ // get the input file name
+ pFileName = argv[globalUtilOptind];
+ // read the file using the corresponding file reader
+ pNtk = Io_Read( pFileName, Io_ReadFileType(pFileName), fCheck );
+ if ( pNtk == NULL )
+ return 1;
+ // replace the current network
+ Abc_FrameReplaceCurrentNetwork( pAbc, pNtk );
+ return 0;
- if ( argc != util_optind + 1 )
+usage:
+ fprintf( pAbc->Err, "usage: read [-mch] <file>\n" );
+ fprintf( pAbc->Err, "\t replaces the current network by the network read from <file>\n" );
+ fprintf( pAbc->Err, "\t by calling the parser that matches the extension of <file>\n" );
+ fprintf( pAbc->Err, "\t (to read a hierarchical design, use \"read_hie\")\n" );
+ fprintf( pAbc->Err, "\t-m : toggle reading mapped Verilog [default = %s]\n", glo_fMapped? "yes":"no" );
+ fprintf( pAbc->Err, "\t-c : toggle network check after reading [default = %s]\n", fCheck? "yes":"no" );
+ fprintf( pAbc->Err, "\t-h : prints the command summary\n" );
+ fprintf( pAbc->Err, "\tfile : the name of a file to read\n" );
+ return 1;
+}
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int IoCommandReadAiger( Abc_Frame_t * pAbc, int argc, char ** argv )
+{
+ Abc_Ntk_t * pNtk;
+ char * pFileName;
+ int fCheck;
+ int c;
+
+ fCheck = 1;
+ Extra_UtilGetoptReset();
+ while ( ( c = Extra_UtilGetopt( argc, argv, "ch" ) ) != EOF )
{
- goto usage;
+ switch ( c )
+ {
+ case 'c':
+ fCheck ^= 1;
+ break;
+ case 'h':
+ goto usage;
+ default:
+ goto usage;
+ }
}
-
+ if ( argc != globalUtilOptind + 1 )
+ goto usage;
// get the input file name
- FileName = argv[util_optind];
- if ( (pFile = fopen( FileName, "r" )) == NULL )
- {
- fprintf( pAbc->Err, "Cannot open input file \"%s\". ", FileName );
- if ( FileName = Extra_FileGetSimilarName( FileName, ".mv", ".blif", ".pla", ".eqn", ".bench" ) )
- fprintf( pAbc->Err, "Did you mean \"%s\"?", FileName );
- fprintf( pAbc->Err, "\n" );
+ pFileName = argv[globalUtilOptind];
+ // read the file using the corresponding file reader
+ pNtk = Io_Read( pFileName, IO_FILE_AIGER, fCheck );
+ if ( pNtk == NULL )
return 1;
+ // replace the current network
+ Abc_FrameReplaceCurrentNetwork( pAbc, pNtk );
+ return 0;
+
+usage:
+ fprintf( pAbc->Err, "usage: read_aiger [-ch] <file>\n" );
+ fprintf( pAbc->Err, "\t read the network in the AIGER format (http://fmv.jku.at/aiger)\n" );
+ fprintf( pAbc->Err, "\t-c : toggle network check after reading [default = %s]\n", fCheck? "yes":"no" );
+ fprintf( pAbc->Err, "\t-h : prints the command summary\n" );
+ fprintf( pAbc->Err, "\tfile : the name of a file to read\n" );
+ return 1;
+}
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int IoCommandReadBaf( Abc_Frame_t * pAbc, int argc, char ** argv )
+{
+ Abc_Ntk_t * pNtk;
+ char * pFileName;
+ int fCheck;
+ int c;
+
+ fCheck = 1;
+ Extra_UtilGetoptReset();
+ while ( ( c = Extra_UtilGetopt( argc, argv, "ch" ) ) != EOF )
+ {
+ switch ( c )
+ {
+ case 'c':
+ fCheck ^= 1;
+ break;
+ case 'h':
+ goto usage;
+ default:
+ goto usage;
+ }
}
- fclose( pFile );
-
- // set the new network
- pNtk = Io_Read( FileName, fCheck );
+ if ( argc != globalUtilOptind + 1 )
+ goto usage;
+ // get the input file name
+ pFileName = argv[globalUtilOptind];
+ // read the file using the corresponding file reader
+ pNtk = Io_Read( pFileName, IO_FILE_BAF, fCheck );
if ( pNtk == NULL )
- {
- fprintf( pAbc->Err, "Reading network from file has failed.\n" );
return 1;
- }
// replace the current network
Abc_FrameReplaceCurrentNetwork( pAbc, pNtk );
return 0;
usage:
- fprintf( pAbc->Err, "usage: read [-ch] <file>\n" );
- fprintf( pAbc->Err, "\t read the network from file in Verilog/BLIF/BENCH format\n" );
+ fprintf( pAbc->Err, "usage: read_baf [-ch] <file>\n" );
+ fprintf( pAbc->Err, "\t read the network in Binary Aig Format (BAF)\n" );
fprintf( pAbc->Err, "\t-c : toggle network check after reading [default = %s]\n", fCheck? "yes":"no" );
fprintf( pAbc->Err, "\t-h : prints the command summary\n" );
fprintf( pAbc->Err, "\tfile : the name of a file to read\n" );
@@ -175,18 +310,23 @@ usage:
***********************************************************************/
int IoCommandReadBlif( Abc_Frame_t * pAbc, int argc, char ** argv )
{
- Abc_Ntk_t * pNtk, * pTemp;
- char * FileName;
- FILE * pFile;
+ Abc_Ntk_t * pNtk;
+ char * pFileName;
+ int fReadAsAig;
int fCheck;
int c;
+ extern Abc_Ntk_t * Io_ReadBlifAsAig( char * pFileName, int fCheck );
fCheck = 1;
- util_getopt_reset();
- while ( ( c = util_getopt( argc, argv, "ch" ) ) != EOF )
+ fReadAsAig = 0;
+ Extra_UtilGetoptReset();
+ while ( ( c = Extra_UtilGetopt( argc, argv, "ach" ) ) != EOF )
{
switch ( c )
{
+ case 'a':
+ fReadAsAig ^= 1;
+ break;
case 'c':
fCheck ^= 1;
break;
@@ -196,47 +336,34 @@ int IoCommandReadBlif( Abc_Frame_t * pAbc, int argc, char ** argv )
goto usage;
}
}
-
- if ( argc != util_optind + 1 )
- {
+ if ( argc != globalUtilOptind + 1 )
goto usage;
- }
-
// get the input file name
- FileName = argv[util_optind];
- if ( (pFile = fopen( FileName, "r" )) == NULL )
+ pFileName = argv[globalUtilOptind];
+ // read the file using the corresponding file reader
+ if ( fReadAsAig )
+ pNtk = Io_ReadBlifAsAig( pFileName, fCheck );
+ else
+// pNtk = Io_Read( pFileName, IO_FILE_BLIF, fCheck );
{
- fprintf( pAbc->Err, "Cannot open input file \"%s\". ", FileName );
- if ( FileName = Extra_FileGetSimilarName( FileName, ".mv", ".blif", ".pla", ".eqn", ".bench" ) )
- fprintf( pAbc->Err, "Did you mean \"%s\"?", FileName );
- fprintf( pAbc->Err, "\n" );
- return 1;
- }
- fclose( pFile );
-
- // set the new network
- pNtk = Io_ReadBlif( FileName, fCheck );
- if ( pNtk == NULL )
- {
- fprintf( pAbc->Err, "Reading network from BLIF file has failed.\n" );
- return 1;
+ Abc_Ntk_t * pTemp;
+ pNtk = Io_ReadBlif( pFileName, fCheck );
+ if ( pNtk == NULL )
+ return 1;
+ pNtk = Abc_NtkToLogic( pTemp = pNtk );
+ Abc_NtkDelete( pTemp );
}
- pNtk = Abc_NtkNetlistToLogic( pTemp = pNtk );
- Abc_NtkDelete( pTemp );
if ( pNtk == NULL )
- {
- fprintf( pAbc->Err, "Converting to logic network after reading has failed.\n" );
return 1;
- }
-
// replace the current network
Abc_FrameReplaceCurrentNetwork( pAbc, pNtk );
return 0;
usage:
- fprintf( pAbc->Err, "usage: read_blif [-ch] <file>\n" );
+ fprintf( pAbc->Err, "usage: read_blif [-ach] <file>\n" );
fprintf( pAbc->Err, "\t read the network in binary BLIF format\n" );
+ fprintf( pAbc->Err, "\t-a : toggle creating AIG while reading the file [default = %s]\n", fReadAsAig? "yes":"no" );
fprintf( pAbc->Err, "\t-c : toggle network check after reading [default = %s]\n", fCheck? "yes":"no" );
fprintf( pAbc->Err, "\t-h : prints the command summary\n" );
fprintf( pAbc->Err, "\tfile : the name of a file to read\n" );
@@ -254,17 +381,16 @@ usage:
SeeAlso []
***********************************************************************/
-int IoCommandReadBench( Abc_Frame_t * pAbc, int argc, char ** argv )
+int IoCommandReadBlifMv( Abc_Frame_t * pAbc, int argc, char ** argv )
{
- Abc_Ntk_t * pNtk, * pTemp;
- char * FileName;
- FILE * pFile;
+ Abc_Ntk_t * pNtk;
+ char * pFileName;
int fCheck;
int c;
fCheck = 1;
- util_getopt_reset();
- while ( ( c = util_getopt( argc, argv, "ch" ) ) != EOF )
+ Extra_UtilGetoptReset();
+ while ( ( c = Extra_UtilGetopt( argc, argv, "ch" ) ) != EOF )
{
switch ( c )
{
@@ -277,39 +403,68 @@ int IoCommandReadBench( Abc_Frame_t * pAbc, int argc, char ** argv )
goto usage;
}
}
-
- if ( argc != util_optind + 1 )
- {
+ if ( argc != globalUtilOptind + 1 )
goto usage;
- }
-
// get the input file name
- FileName = argv[util_optind];
- if ( (pFile = fopen( FileName, "r" )) == NULL )
- {
- fprintf( pAbc->Err, "Cannot open input file \"%s\". ", FileName );
- if ( FileName = Extra_FileGetSimilarName( FileName, ".mv", ".blif", ".pla", ".eqn", ".bench" ) )
- fprintf( pAbc->Err, "Did you mean \"%s\"?", FileName );
- fprintf( pAbc->Err, "\n" );
+ pFileName = argv[globalUtilOptind];
+ // read the file using the corresponding file reader
+ pNtk = Io_Read( pFileName, IO_FILE_BLIFMV, fCheck );
+ if ( pNtk == NULL )
return 1;
- }
- fclose( pFile );
+ // replace the current network
+ Abc_FrameReplaceCurrentNetwork( pAbc, pNtk );
+ return 0;
- // set the new network
- pNtk = Io_ReadBench( FileName, fCheck );
- if ( pNtk == NULL )
+usage:
+ fprintf( pAbc->Err, "usage: read_blif_mv [-ch] <file>\n" );
+ fprintf( pAbc->Err, "\t read the network in BLIF-MV format\n" );
+ fprintf( pAbc->Err, "\t-c : toggle network check after reading [default = %s]\n", fCheck? "yes":"no" );
+ fprintf( pAbc->Err, "\t-h : prints the command summary\n" );
+ fprintf( pAbc->Err, "\tfile : the name of a file to read\n" );
+ return 1;
+}
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int IoCommandReadBench( Abc_Frame_t * pAbc, int argc, char ** argv )
+{
+ Abc_Ntk_t * pNtk;
+ char * pFileName;
+ int fCheck;
+ int c;
+
+ fCheck = 1;
+ Extra_UtilGetoptReset();
+ while ( ( c = Extra_UtilGetopt( argc, argv, "ch" ) ) != EOF )
{
- fprintf( pAbc->Err, "Reading network from BENCH file has failed.\n" );
- return 1;
+ switch ( c )
+ {
+ case 'c':
+ fCheck ^= 1;
+ break;
+ case 'h':
+ goto usage;
+ default:
+ goto usage;
+ }
}
-
- pNtk = Abc_NtkNetlistToLogic( pTemp = pNtk );
- Abc_NtkDelete( pTemp );
+ if ( argc != globalUtilOptind + 1 )
+ goto usage;
+ // get the input file name
+ pFileName = argv[globalUtilOptind];
+ // read the file using the corresponding file reader
+ pNtk = Io_Read( pFileName, IO_FILE_BENCH, fCheck );
if ( pNtk == NULL )
- {
- fprintf( pAbc->Err, "Converting to logic network after reading has failed.\n" );
return 1;
- }
// replace the current network
Abc_FrameReplaceCurrentNetwork( pAbc, pNtk );
return 0;
@@ -334,17 +489,17 @@ usage:
SeeAlso []
***********************************************************************/
-int IoCommandReadEdif( Abc_Frame_t * pAbc, int argc, char ** argv )
+int IoCommandReadDsd( Abc_Frame_t * pAbc, int argc, char ** argv )
{
- Abc_Ntk_t * pNtk, * pTemp;
- char * FileName;
- FILE * pFile;
+ Abc_Ntk_t * pNtk;
+ char * pString;
int fCheck;
int c;
+ extern Abc_Ntk_t * Io_ReadDsd( char * pFormula );
fCheck = 1;
- util_getopt_reset();
- while ( ( c = util_getopt( argc, argv, "ch" ) ) != EOF )
+ Extra_UtilGetoptReset();
+ while ( ( c = Extra_UtilGetopt( argc, argv, "ch" ) ) != EOF )
{
switch ( c )
{
@@ -357,47 +512,195 @@ int IoCommandReadEdif( Abc_Frame_t * pAbc, int argc, char ** argv )
goto usage;
}
}
+ if ( argc != globalUtilOptind + 1 )
+ goto usage;
+ // get the input file name
+ pString = argv[globalUtilOptind];
+ // read the file using the corresponding file reader
+ pNtk = Io_ReadDsd( pString );
+ if ( pNtk == NULL )
+ return 1;
+ // replace the current network
+ Abc_FrameReplaceCurrentNetwork( pAbc, pNtk );
+ return 0;
- if ( argc != util_optind + 1 )
+usage:
+ fprintf( pAbc->Err, "usage: read_dsd [-h] <formula>\n" );
+ fprintf( pAbc->Err, "\t parses a formula representing DSD of a function\n" );
+ fprintf( pAbc->Err, "\t-h : prints the command summary\n" );
+ fprintf( pAbc->Err, "\tformula : the formula representing disjoint-support decomposition (DSD)\n" );
+ fprintf( pAbc->Err, "\t Example of a formula: !(a*(b+CA(!d,e*f,c))*79B3(g,h,i,k))\n" );
+ fprintf( pAbc->Err, "\t where \'!\' is an INV, \'*\' is an AND, \'+\' is an XOR, \n" );
+ fprintf( pAbc->Err, "\t CA and 79B3 are hexadecimal representations of truth tables\n" );
+ fprintf( pAbc->Err, "\t (in this case CA=11001010 is truth table of MUX(Data0,Data1,Ctrl))\n" );
+ fprintf( pAbc->Err, "\t The lower chars (a,b,c,etc) are reserved for elementary variables.\n" );
+ fprintf( pAbc->Err, "\t The upper chars (A,B,C,etc) are reserved for hexadecimal digits.\n" );
+ fprintf( pAbc->Err, "\t No spaces are allowed in formulas. In parantheses, LSB goes first.\n" );
+ return 1;
+}
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int IoCommandReadEdif( Abc_Frame_t * pAbc, int argc, char ** argv )
+{
+ Abc_Ntk_t * pNtk;
+ char * pFileName;
+ int fCheck;
+ int c;
+
+ fCheck = 1;
+ Extra_UtilGetoptReset();
+ while ( ( c = Extra_UtilGetopt( argc, argv, "ch" ) ) != EOF )
{
- goto usage;
+ switch ( c )
+ {
+ case 'c':
+ fCheck ^= 1;
+ break;
+ case 'h':
+ goto usage;
+ default:
+ goto usage;
+ }
}
-
+ if ( argc != globalUtilOptind + 1 )
+ goto usage;
// get the input file name
- FileName = argv[util_optind];
- if ( (pFile = fopen( FileName, "r" )) == NULL )
- {
- fprintf( pAbc->Err, "Cannot open input file \"%s\". ", FileName );
- if ( FileName = Extra_FileGetSimilarName( FileName, ".mv", ".blif", ".pla", ".eqn", ".bench" ) )
- fprintf( pAbc->Err, "Did you mean \"%s\"?", FileName );
- fprintf( pAbc->Err, "\n" );
+ pFileName = argv[globalUtilOptind];
+ // read the file using the corresponding file reader
+ pNtk = Io_Read( pFileName, IO_FILE_EDIF, fCheck );
+ if ( pNtk == NULL )
return 1;
- }
- fclose( pFile );
+ // replace the current network
+ Abc_FrameReplaceCurrentNetwork( pAbc, pNtk );
+ return 0;
- // set the new network
- pNtk = Io_ReadEdif( FileName, fCheck );
- if ( pNtk == NULL )
+usage:
+ fprintf( pAbc->Err, "usage: read_edif [-ch] <file>\n" );
+ fprintf( pAbc->Err, "\t read the network in EDIF (works only for ISCAS benchmarks)\n" );
+ fprintf( pAbc->Err, "\t-c : toggle network check after reading [default = %s]\n", fCheck? "yes":"no" );
+ fprintf( pAbc->Err, "\t-h : prints the command summary\n" );
+ fprintf( pAbc->Err, "\tfile : the name of a file to read\n" );
+ return 1;
+}
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int IoCommandReadEqn( Abc_Frame_t * pAbc, int argc, char ** argv )
+{
+ Abc_Ntk_t * pNtk;
+ char * pFileName;
+ int fCheck;
+ int c;
+
+ fCheck = 1;
+ Extra_UtilGetoptReset();
+ while ( ( c = Extra_UtilGetopt( argc, argv, "ch" ) ) != EOF )
{
- fprintf( pAbc->Err, "Reading network from EDIF file has failed.\n" );
+ switch ( c )
+ {
+ case 'c':
+ fCheck ^= 1;
+ break;
+ case 'h':
+ goto usage;
+ default:
+ goto usage;
+ }
+ }
+ if ( argc != globalUtilOptind + 1 )
+ goto usage;
+ // get the input file name
+ pFileName = argv[globalUtilOptind];
+ // read the file using the corresponding file reader
+ pNtk = Io_Read( pFileName, IO_FILE_EQN, fCheck );
+ if ( pNtk == NULL )
return 1;
+ // replace the current network
+ Abc_FrameReplaceCurrentNetwork( pAbc, pNtk );
+ return 0;
+
+usage:
+ fprintf( pAbc->Err, "usage: read_eqn [-ch] <file>\n" );
+ fprintf( pAbc->Err, "\t read the network in equation format\n" );
+ fprintf( pAbc->Err, "\t-c : toggle network check after reading [default = %s]\n", fCheck? "yes":"no" );
+ fprintf( pAbc->Err, "\t-h : prints the command summary\n" );
+ fprintf( pAbc->Err, "\tfile : the name of a file to read\n" );
+ return 1;
+}
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int IoCommandReadInit( Abc_Frame_t * pAbc, int argc, char ** argv )
+{
+ FILE * pOut, * pErr;
+ Abc_Ntk_t * pNtk;
+ char * pFileName;
+ int c;
+ extern void Io_ReadBenchInit( Abc_Ntk_t * pNtk, char * pFileName );
+
+ pNtk = Abc_FrameReadNtk(pAbc);
+ pOut = Abc_FrameReadOut(pAbc);
+ pErr = Abc_FrameReadErr(pAbc);
+
+ Extra_UtilGetoptReset();
+ while ( ( c = Extra_UtilGetopt( argc, argv, "h" ) ) != EOF )
+ {
+ switch ( c )
+ {
+ case 'h':
+ goto usage;
+ default:
+ goto usage;
+ }
}
+ if ( argc != globalUtilOptind + 1 )
+ goto usage;
- pNtk = Abc_NtkNetlistToLogic( pTemp = pNtk );
- Abc_NtkDelete( pTemp );
if ( pNtk == NULL )
{
- fprintf( pAbc->Err, "Converting to logic network after reading has failed.\n" );
+ fprintf( pErr, "Empty network.\n" );
return 1;
}
+ // get the input file name
+ pFileName = argv[globalUtilOptind];
+ // read the file using the corresponding file reader
+ pNtk = Abc_NtkDup( pNtk );
+ Io_ReadBenchInit( pNtk, pFileName );
// replace the current network
Abc_FrameReplaceCurrentNetwork( pAbc, pNtk );
return 0;
usage:
- fprintf( pAbc->Err, "usage: read_edif [-ch] <file>\n" );
- fprintf( pAbc->Err, "\t read the network in EDIF (works only for ISCAS benchmarks)\n" );
- fprintf( pAbc->Err, "\t-c : toggle network check after reading [default = %s]\n", fCheck? "yes":"no" );
+ fprintf( pAbc->Err, "usage: read_init [-h] <file>\n" );
+ fprintf( pAbc->Err, "\t reads initial state of the network in BENCH format\n" );
fprintf( pAbc->Err, "\t-h : prints the command summary\n" );
fprintf( pAbc->Err, "\tfile : the name of a file to read\n" );
return 1;
@@ -414,17 +717,16 @@ usage:
SeeAlso []
***********************************************************************/
-int IoCommandReadEqn( Abc_Frame_t * pAbc, int argc, char ** argv )
+int IoCommandReadPla( Abc_Frame_t * pAbc, int argc, char ** argv )
{
- Abc_Ntk_t * pNtk, * pTemp;
- char * FileName;
- FILE * pFile;
+ Abc_Ntk_t * pNtk;
+ char * pFileName;
int fCheck;
int c;
fCheck = 1;
- util_getopt_reset();
- while ( ( c = util_getopt( argc, argv, "ch" ) ) != EOF )
+ Extra_UtilGetoptReset();
+ while ( ( c = Extra_UtilGetopt( argc, argv, "ch" ) ) != EOF )
{
switch ( c )
{
@@ -437,46 +739,150 @@ int IoCommandReadEqn( Abc_Frame_t * pAbc, int argc, char ** argv )
goto usage;
}
}
+ if ( argc != globalUtilOptind + 1 )
+ goto usage;
+ // get the input file name
+ pFileName = argv[globalUtilOptind];
+ // read the file using the corresponding file reader
+ pNtk = Io_Read( pFileName, IO_FILE_PLA, fCheck );
+ if ( pNtk == NULL )
+ return 1;
+ // replace the current network
+ Abc_FrameReplaceCurrentNetwork( pAbc, pNtk );
+ return 0;
- if ( argc != util_optind + 1 )
+usage:
+ fprintf( pAbc->Err, "usage: read_pla [-ch] <file>\n" );
+ fprintf( pAbc->Err, "\t read the network in PLA\n" );
+ fprintf( pAbc->Err, "\t-c : toggle network check after reading [default = %s]\n", fCheck? "yes":"no" );
+ fprintf( pAbc->Err, "\t-h : prints the command summary\n" );
+ fprintf( pAbc->Err, "\tfile : the name of a file to read\n" );
+ return 1;
+}
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int IoCommandReadTruth( Abc_Frame_t * pAbc, int argc, char ** argv )
+{
+ Abc_Ntk_t * pNtk;
+ char * pSopCover;
+ int fHex;
+ int c;
+
+ fHex = 1;
+ Extra_UtilGetoptReset();
+ while ( ( c = Extra_UtilGetopt( argc, argv, "xh" ) ) != EOF )
+ {
+ switch ( c )
+ {
+ case 'x':
+ fHex ^= 1;
+ break;
+ case 'h':
+ goto usage;
+ default:
+ goto usage;
+ }
+ }
+
+ if ( argc != globalUtilOptind + 1 )
{
goto usage;
}
- // get the input file name
- FileName = argv[util_optind];
- if ( (pFile = fopen( FileName, "r" )) == NULL )
+ // convert truth table to SOP
+ if ( fHex )
+ pSopCover = Abc_SopFromTruthHex(argv[globalUtilOptind]);
+ else
+ pSopCover = Abc_SopFromTruthBin(argv[globalUtilOptind]);
+ if ( pSopCover == NULL )
{
- fprintf( pAbc->Err, "Cannot open input file \"%s\". ", FileName );
- if ( FileName = Extra_FileGetSimilarName( FileName, ".mv", ".blif", ".pla", ".eqn", ".bench" ) )
- fprintf( pAbc->Err, "Did you mean \"%s\"?", FileName );
- fprintf( pAbc->Err, "\n" );
+ fprintf( pAbc->Err, "Reading truth table has failed.\n" );
return 1;
}
- fclose( pFile );
- // set the new network
- pNtk = Io_ReadEqn( FileName, fCheck );
+ pNtk = Abc_NtkCreateWithNode( pSopCover );
+ free( pSopCover );
if ( pNtk == NULL )
{
- fprintf( pAbc->Err, "Reading network from the equation file has failed.\n" );
+ fprintf( pAbc->Err, "Deriving the network has failed.\n" );
return 1;
}
+ // replace the current network
+ Abc_FrameReplaceCurrentNetwork( pAbc, pNtk );
+ return 0;
- pNtk = Abc_NtkNetlistToLogic( pTemp = pNtk );
- Abc_NtkDelete( pTemp );
- if ( pNtk == NULL )
+usage:
+ fprintf( pAbc->Err, "usage: read_truth [-xh] <truth>\n" );
+ fprintf( pAbc->Err, "\t creates network with node having given truth table\n" );
+ fprintf( pAbc->Err, "\t-x : toggles between bin and hex representation [default = %s]\n", fHex? "hex":"bin" );
+ fprintf( pAbc->Err, "\t-h : prints the command summary\n" );
+ fprintf( pAbc->Err, "\ttruth : truth table with most signficant bit first (e.g. 1000 for AND(a,b))\n" );
+ return 1;
+}
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int IoCommandReadVerilog( Abc_Frame_t * pAbc, int argc, char ** argv )
+{
+ Abc_Ntk_t * pNtk;
+ char * pFileName;
+ int fCheck;
+ int c;
+
+ fCheck = 1;
+ glo_fMapped = 0;
+ Extra_UtilGetoptReset();
+ while ( ( c = Extra_UtilGetopt( argc, argv, "mch" ) ) != EOF )
{
- fprintf( pAbc->Err, "Converting to logic network after reading has failed.\n" );
- return 1;
+ switch ( c )
+ {
+ case 'm':
+ glo_fMapped ^= 1;
+ break;
+ case 'c':
+ fCheck ^= 1;
+ break;
+ case 'h':
+ goto usage;
+ default:
+ goto usage;
+ }
}
+ if ( argc != globalUtilOptind + 1 )
+ goto usage;
+ // get the input file name
+ pFileName = argv[globalUtilOptind];
+ // read the file using the corresponding file reader
+ pNtk = Io_Read( pFileName, IO_FILE_VERILOG, fCheck );
+ if ( pNtk == NULL )
+ return 1;
// replace the current network
Abc_FrameReplaceCurrentNetwork( pAbc, pNtk );
return 0;
usage:
- fprintf( pAbc->Err, "usage: read_eqn [-ch] <file>\n" );
- fprintf( pAbc->Err, "\t read the network in equation format\n" );
+ fprintf( pAbc->Err, "usage: read_verilog [-mch] <file>\n" );
+ fprintf( pAbc->Err, "\t read the network in Verilog (IWLS 2002/2005 subset)\n" );
+ fprintf( pAbc->Err, "\t-m : toggle reading mapped Verilog [default = %s]\n", glo_fMapped? "yes":"no" );
fprintf( pAbc->Err, "\t-c : toggle network check after reading [default = %s]\n", fCheck? "yes":"no" );
fprintf( pAbc->Err, "\t-h : prints the command summary\n" );
fprintf( pAbc->Err, "\tfile : the name of a file to read\n" );
@@ -494,17 +900,23 @@ usage:
SeeAlso []
***********************************************************************/
-int IoCommandReadVerilog( Abc_Frame_t * pAbc, int argc, char ** argv )
+int IoCommandReadVer( Abc_Frame_t * pAbc, int argc, char ** argv )
{
- Abc_Ntk_t * pNtk, * pTemp;
- char * FileName;
+ Abc_Ntk_t * pNtk, * pNtkNew;
+ Abc_Lib_t * pDesign;
+ char * pFileName;
FILE * pFile;
int fCheck;
int c;
+ extern Abc_Ntk_t * Abc_LibDeriveAig( Abc_Ntk_t * pNtk, Abc_Lib_t * pLib );
+ extern Abc_Lib_t * Ver_ParseFile( char * pFileName, Abc_Lib_t * pGateLib, int fCheck, int fUseMemMan );
+
+ printf( "Stand-alone structural Verilog reader is available as command \"read_verilog\".\n" );
+ return 0;
fCheck = 1;
- util_getopt_reset();
- while ( ( c = util_getopt( argc, argv, "ch" ) ) != EOF )
+ Extra_UtilGetoptReset();
+ while ( ( c = Extra_UtilGetopt( argc, argv, "ch" ) ) != EOF )
{
switch ( c )
{
@@ -518,45 +930,55 @@ int IoCommandReadVerilog( Abc_Frame_t * pAbc, int argc, char ** argv )
}
}
- if ( argc != util_optind + 1 )
+ if ( argc != globalUtilOptind + 1 )
{
goto usage;
}
// get the input file name
- FileName = argv[util_optind];
- if ( (pFile = fopen( FileName, "r" )) == NULL )
+ pFileName = argv[globalUtilOptind];
+ if ( (pFile = fopen( pFileName, "r" )) == NULL )
{
- fprintf( pAbc->Err, "Cannot open input file \"%s\". ", FileName );
- if ( FileName = Extra_FileGetSimilarName( FileName, ".mv", ".blif", ".pla", ".eqn", ".bench" ) )
- fprintf( pAbc->Err, "Did you mean \"%s\"?", FileName );
+ fprintf( pAbc->Err, "Cannot open input file \"%s\". ", pFileName );
+ if ( pFileName = Extra_FileGetSimilarName( pFileName, ".blif", ".bench", ".pla", ".baf", ".aig" ) )
+ fprintf( pAbc->Err, "Did you mean \"%s\"?", pFileName );
fprintf( pAbc->Err, "\n" );
return 1;
}
fclose( pFile );
// set the new network
- pNtk = Io_ReadVerilog( FileName, fCheck );
- if ( pNtk == NULL )
+ pDesign = Ver_ParseFile( pFileName, Abc_FrameReadLibVer(), fCheck, 1 );
+ if ( pDesign == NULL )
{
fprintf( pAbc->Err, "Reading network from the verilog file has failed.\n" );
return 1;
}
- pNtk = Abc_NtkNetlistToLogic( pTemp = pNtk );
- Abc_NtkDelete( pTemp );
+ // derive root design
+ pNtk = Abc_LibDeriveRoot( pDesign );
+ Abc_LibFree( pDesign, NULL );
if ( pNtk == NULL )
{
- fprintf( pAbc->Err, "Converting to logic network after reading has failed.\n" );
+ fprintf( pAbc->Err, "Deriving root module has failed.\n" );
+ return 1;
+ }
+
+ // derive the AIG network from this design
+ pNtkNew = Abc_LibDeriveAig( pNtk, Abc_FrameReadLibVer() );
+ Abc_NtkDelete( pNtk );
+ if ( pNtkNew == NULL )
+ {
+ fprintf( pAbc->Err, "Converting root module to AIG has failed.\n" );
return 1;
}
// replace the current network
- Abc_FrameReplaceCurrentNetwork( pAbc, pNtk );
+ Abc_FrameReplaceCurrentNetwork( pAbc, pNtkNew );
return 0;
usage:
- fprintf( pAbc->Err, "usage: read_verilog [-ch] <file>\n" );
- fprintf( pAbc->Err, "\t read the network in Verilog (IWLS 2005 subset)\n" );
+ fprintf( pAbc->Err, "usage: read_ver [-ch] <file>\n" );
+ fprintf( pAbc->Err, "\t read a network in structural verilog (using current library)\n" );
fprintf( pAbc->Err, "\t-c : toggle network check after reading [default = %s]\n", fCheck? "yes":"no" );
fprintf( pAbc->Err, "\t-h : prints the command summary\n" );
fprintf( pAbc->Err, "\tfile : the name of a file to read\n" );
@@ -574,17 +996,18 @@ usage:
SeeAlso []
***********************************************************************/
-int IoCommandReadPla( Abc_Frame_t * pAbc, int argc, char ** argv )
+int IoCommandReadVerLib( Abc_Frame_t * pAbc, int argc, char ** argv )
{
- Abc_Ntk_t * pNtk, * pTemp;
- char * FileName;
+ Abc_Lib_t * pLibrary;
+ char * pFileName;
FILE * pFile;
int fCheck;
int c;
+ extern Abc_Lib_t * Ver_ParseFile( char * pFileName, Abc_Lib_t * pGateLib, int fCheck, int fUseMemMan );
fCheck = 1;
- util_getopt_reset();
- while ( ( c = util_getopt( argc, argv, "ch" ) ) != EOF )
+ Extra_UtilGetoptReset();
+ while ( ( c = Extra_UtilGetopt( argc, argv, "ch" ) ) != EOF )
{
switch ( c )
{
@@ -598,45 +1021,41 @@ int IoCommandReadPla( Abc_Frame_t * pAbc, int argc, char ** argv )
}
}
- if ( argc != util_optind + 1 )
+ if ( argc != globalUtilOptind + 1 )
{
goto usage;
}
// get the input file name
- FileName = argv[util_optind];
- if ( (pFile = fopen( FileName, "r" )) == NULL )
+ pFileName = argv[globalUtilOptind];
+ if ( (pFile = fopen( pFileName, "r" )) == NULL )
{
- fprintf( pAbc->Err, "Cannot open input file \"%s\". ", FileName );
- if ( FileName = Extra_FileGetSimilarName( FileName, ".mv", ".blif", ".pla", ".eqn", ".bench" ) )
- fprintf( pAbc->Err, "Did you mean \"%s\"?", FileName );
+ fprintf( pAbc->Err, "Cannot open input file \"%s\". ", pFileName );
+ if ( pFileName = Extra_FileGetSimilarName( pFileName, ".blif", ".bench", ".pla", ".baf", ".aig" ) )
+ fprintf( pAbc->Err, "Did you mean \"%s\"?", pFileName );
fprintf( pAbc->Err, "\n" );
return 1;
}
fclose( pFile );
// set the new network
- pNtk = Io_ReadPla( FileName, fCheck );
- if ( pNtk == NULL )
+ pLibrary = Ver_ParseFile( pFileName, NULL, fCheck, 0 );
+ if ( pLibrary == NULL )
{
- fprintf( pAbc->Err, "Reading network from PLA file has failed.\n" );
+ fprintf( pAbc->Err, "Reading library from the verilog file has failed.\n" );
return 1;
}
-
- pNtk = Abc_NtkNetlistToLogic( pTemp = pNtk );
- Abc_NtkDelete( pTemp );
- if ( pNtk == NULL )
- {
- fprintf( pAbc->Err, "Converting to logic network after reading has failed.\n" );
- return 1;
- }
- // replace the current network
- Abc_FrameReplaceCurrentNetwork( pAbc, pNtk );
+ printf( "The library contains %d gates.\n", st_count(pLibrary->tModules) );
+ // free old library
+ if ( Abc_FrameReadLibVer() )
+ Abc_LibFree( Abc_FrameReadLibVer(), NULL );
+ // read new library
+ Abc_FrameSetLibVer( pLibrary );
return 0;
usage:
- fprintf( pAbc->Err, "usage: read_pla [-ch] <file>\n" );
- fprintf( pAbc->Err, "\t read the network in PLA\n" );
+ fprintf( pAbc->Err, "usage: read_verlib [-ch] <file>\n" );
+ fprintf( pAbc->Err, "\t read a gate library in structural verilog\n" );
fprintf( pAbc->Err, "\t-c : toggle network check after reading [default = %s]\n", fCheck? "yes":"no" );
fprintf( pAbc->Err, "\t-h : prints the command summary\n" );
fprintf( pAbc->Err, "\tfile : the name of a file to read\n" );
@@ -655,57 +1074,87 @@ usage:
SeeAlso []
***********************************************************************/
-int IoCommandWriteBlif( Abc_Frame_t * pAbc, int argc, char **argv )
+int IoCommandWrite( Abc_Frame_t * pAbc, int argc, char **argv )
{
- Abc_Ntk_t * pNtk;
- char * FileName;
- int fWriteLatches;
+ char * pFileName;
int c;
- fWriteLatches = 1;
- util_getopt_reset();
- while ( ( c = util_getopt( argc, argv, "lh" ) ) != EOF )
+ Extra_UtilGetoptReset();
+ while ( ( c = Extra_UtilGetopt( argc, argv, "h" ) ) != EOF )
{
switch ( c )
{
- case 'l':
- fWriteLatches ^= 1;
- break;
case 'h':
goto usage;
default:
goto usage;
}
}
+ if ( argc != globalUtilOptind + 1 )
+ goto usage;
+ // get the output file name
+ pFileName = argv[globalUtilOptind];
+ // call the corresponding file writer
+ Io_Write( pAbc->pNtkCur, pFileName, Io_ReadFileType(pFileName) );
+ return 0;
- pNtk = pAbc->pNtkCur;
- if ( pNtk == NULL )
- {
- fprintf( pAbc->Out, "Empty network.\n" );
- return 0;
- }
+usage:
+ fprintf( pAbc->Err, "usage: write [-h] <file>\n" );
+ fprintf( pAbc->Err, "\t writes the current network into <file> by calling\n" );
+ fprintf( pAbc->Err, "\t the writer that matches the extension of <file>\n" );
+ fprintf( pAbc->Err, "\t-h : print the help massage\n" );
+ fprintf( pAbc->Err, "\tfile : the name of the file to write\n" );
+ return 1;
+}
- if ( argc != util_optind + 1 )
- {
- goto usage;
- }
- FileName = argv[util_optind];
+/**Function*************************************************************
- // check the network type
- if ( !Abc_NtkIsLogic(pNtk) && !Abc_NtkIsStrash(pNtk) && !Abc_NtkIsSeq(pNtk) )
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int IoCommandWriteHie( Abc_Frame_t * pAbc, int argc, char **argv )
+{
+ char * pBaseName, * pFileName;
+ int c;
+
+ glo_fMapped = 0;
+ Extra_UtilGetoptReset();
+ while ( ( c = Extra_UtilGetopt( argc, argv, "mh" ) ) != EOF )
{
- fprintf( pAbc->Out, "Currently can only write logic networks, AIGs, and seq AIGs.\n" );
- return 0;
+ switch ( c )
+ {
+ case 'm':
+ glo_fMapped ^= 1;
+ break;
+ case 'h':
+ goto usage;
+ default:
+ goto usage;
+ }
}
- Io_WriteBlifLogic( pNtk, FileName, fWriteLatches );
-// Io_WriteBlif( pNtk, FileName, fWriteLatches );
+ if ( argc != globalUtilOptind + 2 )
+ goto usage;
+ // get the output file name
+ pBaseName = argv[globalUtilOptind];
+ pFileName = argv[globalUtilOptind+1];
+ // call the corresponding file writer
+// Io_Write( pAbc->pNtkCur, pFileName, Io_ReadFileType(pFileName) );
+ Io_WriteHie( pAbc->pNtkCur, pBaseName, pFileName );
return 0;
usage:
- fprintf( pAbc->Err, "usage: write_blif [-lh] <file>\n" );
- fprintf( pAbc->Err, "\t write the network into a BLIF file\n" );
- fprintf( pAbc->Err, "\t-l : toggle writing latches [default = %s]\n", fWriteLatches? "yes":"no" );
+ fprintf( pAbc->Err, "usage: write_hie [-h] <orig> <file>\n" );
+ fprintf( pAbc->Err, "\t writes the current network into <file> by calling\n" );
+ fprintf( pAbc->Err, "\t the hierarchical writer that matches the extension of <file>\n" );
+ fprintf( pAbc->Err, "\t-m : toggle reading mapped Verilog for <orig> [default = %s]\n", glo_fMapped? "yes":"no" );
fprintf( pAbc->Err, "\t-h : print the help massage\n" );
+ fprintf( pAbc->Err, "\torig : the name of the original file with the hierarchical design\n" );
fprintf( pAbc->Err, "\tfile : the name of the file to write\n" );
return 1;
}
@@ -721,21 +1170,25 @@ usage:
SeeAlso []
***********************************************************************/
-int IoCommandWriteBench( Abc_Frame_t * pAbc, int argc, char **argv )
+int IoCommandWriteAiger( Abc_Frame_t * pAbc, int argc, char **argv )
{
- Abc_Ntk_t * pNtk, * pNtkTemp;
- char * FileName;
- int fWriteLatches;
+ char * pFileName;
+ int fWriteSymbols;
+ int fCompact;
int c;
- fWriteLatches = 1;
- util_getopt_reset();
- while ( ( c = util_getopt( argc, argv, "lh" ) ) != EOF )
+ fCompact = 1;
+ fWriteSymbols = 0;
+ Extra_UtilGetoptReset();
+ while ( ( c = Extra_UtilGetopt( argc, argv, "sch" ) ) != EOF )
{
switch ( c )
{
- case 'l':
- fWriteLatches ^= 1;
+ case 's':
+ fWriteSymbols ^= 1;
+ break;
+ case 'c':
+ fCompact ^= 1;
break;
case 'h':
goto usage;
@@ -743,44 +1196,213 @@ int IoCommandWriteBench( Abc_Frame_t * pAbc, int argc, char **argv )
goto usage;
}
}
-
- pNtk = pAbc->pNtkCur;
- if ( pNtk == NULL )
+ if ( argc != globalUtilOptind + 1 )
+ goto usage;
+ // get the output file name
+ pFileName = argv[globalUtilOptind];
+ // call the corresponding file writer
+ if ( !Abc_NtkIsStrash(pAbc->pNtkCur) )
{
- fprintf( pAbc->Out, "Empty network.\n" );
- return 0;
+ fprintf( stdout, "Writing this format is only possible for structurally hashed AIGs.\n" );
+ return 1;
}
+ Io_WriteAiger( pAbc->pNtkCur, pFileName, fWriteSymbols, fCompact );
+ return 0;
+
+usage:
+ fprintf( pAbc->Err, "usage: write_aiger [-sch] <file>\n" );
+ fprintf( pAbc->Err, "\t write the network in the AIGER format (http://fmv.jku.at/aiger)\n" );
+ fprintf( pAbc->Err, "\t-s : toggle saving I/O names [default = %s]\n", fWriteSymbols? "yes" : "no" );
+ fprintf( pAbc->Err, "\t-c : toggle writing more compactly [default = %s]\n", fCompact? "yes" : "no" );
+ fprintf( pAbc->Err, "\t-h : print the help massage\n" );
+ fprintf( pAbc->Err, "\tfile : the name of the file to write (extension .aig)\n" );
+ return 1;
+}
- if ( argc != util_optind + 1 )
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int IoCommandWriteBaf( Abc_Frame_t * pAbc, int argc, char **argv )
+{
+ char * pFileName;
+ int c;
+
+ Extra_UtilGetoptReset();
+ while ( ( c = Extra_UtilGetopt( argc, argv, "h" ) ) != EOF )
{
+ switch ( c )
+ {
+ case 'h':
+ goto usage;
+ default:
+ goto usage;
+ }
+ }
+ if ( argc != globalUtilOptind + 1 )
goto usage;
+ // get the output file name
+ pFileName = argv[globalUtilOptind];
+ // call the corresponding file writer
+ Io_Write( pAbc->pNtkCur, pFileName, IO_FILE_BAF );
+ return 0;
+
+usage:
+ fprintf( pAbc->Err, "usage: write_baf [-h] <file>\n" );
+ fprintf( pAbc->Err, "\t write the network into a BLIF file\n" );
+ fprintf( pAbc->Err, "\t-h : print the help massage\n" );
+ fprintf( pAbc->Err, "\tfile : the name of the file to write (extension .baf)\n" );
+ return 1;
+}
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int IoCommandWriteBlif( Abc_Frame_t * pAbc, int argc, char **argv )
+{
+ char * pFileName;
+ int c;
+
+ Extra_UtilGetoptReset();
+ while ( ( c = Extra_UtilGetopt( argc, argv, "h" ) ) != EOF )
+ {
+ switch ( c )
+ {
+ case 'h':
+ goto usage;
+ default:
+ goto usage;
+ }
}
- // get the input file name
- FileName = argv[util_optind];
+ if ( argc != globalUtilOptind + 1 )
+ goto usage;
+ // get the output file name
+ pFileName = argv[globalUtilOptind];
+ // call the corresponding file writer
+ Io_Write( pAbc->pNtkCur, pFileName, IO_FILE_BLIF );
+ return 0;
+
+usage:
+ fprintf( pAbc->Err, "usage: write_blif [-h] <file>\n" );
+ fprintf( pAbc->Err, "\t write the network into a BLIF file\n" );
+ fprintf( pAbc->Err, "\t-h : print the help massage\n" );
+ fprintf( pAbc->Err, "\tfile : the name of the file to write (extension .blif)\n" );
+ return 1;
+}
+
+/**Function*************************************************************
+
+ Synopsis []
- if ( !Abc_NtkIsStrash(pNtk) )
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int IoCommandWriteBlifMv( Abc_Frame_t * pAbc, int argc, char **argv )
+{
+ char * pFileName;
+ int c;
+
+ Extra_UtilGetoptReset();
+ while ( ( c = Extra_UtilGetopt( argc, argv, "h" ) ) != EOF )
{
- fprintf( pAbc->Out, "The network should be an AIG.\n" );
- return 0;
+ switch ( c )
+ {
+ case 'h':
+ goto usage;
+ default:
+ goto usage;
+ }
}
+ if ( argc != globalUtilOptind + 1 )
+ goto usage;
+ // get the output file name
+ pFileName = argv[globalUtilOptind];
+ // call the corresponding file writer
+ Io_Write( pAbc->pNtkCur, pFileName, IO_FILE_BLIFMV );
+ return 0;
- // derive the netlist
- pNtkTemp = Abc_NtkLogicToNetlistBench(pNtk);
- if ( pNtkTemp == NULL )
+usage:
+ fprintf( pAbc->Err, "usage: write_blif_mv [-h] <file>\n" );
+ fprintf( pAbc->Err, "\t write the network into a BLIF-MV file\n" );
+ fprintf( pAbc->Err, "\t-h : print the help massage\n" );
+ fprintf( pAbc->Err, "\tfile : the name of the file to write (extension .mv)\n" );
+ return 1;
+}
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int IoCommandWriteBench( Abc_Frame_t * pAbc, int argc, char **argv )
+{
+ char * pFileName;
+ int fUseLuts;
+ int c;
+
+ fUseLuts = 1;
+ Extra_UtilGetoptReset();
+ while ( ( c = Extra_UtilGetopt( argc, argv, "lh" ) ) != EOF )
{
- fprintf( pAbc->Out, "Writing BENCH has failed.\n" );
- return 0;
+ switch ( c )
+ {
+ case 'l':
+ fUseLuts ^= 1;
+ break;
+ case 'h':
+ goto usage;
+ default:
+ goto usage;
+ }
+ }
+ if ( argc != globalUtilOptind + 1 )
+ goto usage;
+ // get the output file name
+ pFileName = argv[globalUtilOptind];
+ // call the corresponding file writer
+ if ( !fUseLuts )
+ Io_Write( pAbc->pNtkCur, pFileName, IO_FILE_BENCH );
+ else
+ {
+ Abc_Ntk_t * pNtkTemp;
+ pNtkTemp = Abc_NtkToNetlist( pAbc->pNtkCur );
+ Abc_NtkToAig( pNtkTemp );
+ Io_WriteBenchLut( pNtkTemp, pFileName );
+ Abc_NtkDelete( pNtkTemp );
}
- Io_WriteBench( pNtkTemp, FileName );
- Abc_NtkDelete( pNtkTemp );
return 0;
usage:
- fprintf( pAbc->Err, "usage: write_bench [-h] <file>\n" );
+ fprintf( pAbc->Err, "usage: write_bench [-lh] <file>\n" );
fprintf( pAbc->Err, "\t write the network in BENCH format\n" );
-// fprintf( pAbc->Err, "\t-l : toggle writing latches [default = %s]\n", fWriteLatches? "yes":"no" );
+ fprintf( pAbc->Err, "\t-l : toggle using LUTs in the output [default = %s]\n", fUseLuts? "yes" : "no" );
fprintf( pAbc->Err, "\t-h : print the help massage\n" );
- fprintf( pAbc->Err, "\tfile : the name of the file to write\n" );
+ fprintf( pAbc->Err, "\tfile : the name of the file to write (extension .bench)\n" );
return 1;
}
@@ -795,13 +1417,15 @@ usage:
SeeAlso []
***********************************************************************/
-int IoCommandWriteCnf( Abc_Frame_t * pAbc, int argc, char **argv )
+int IoCommandWriteCellNet( Abc_Frame_t * pAbc, int argc, char **argv )
{
- char * FileName;
+ Abc_Ntk_t * pNtk;
+ char * pFileName;
int c;
+ extern void Io_WriteCellNet( Abc_Ntk_t * pNtk, char * pFileName );
- util_getopt_reset();
- while ( ( c = util_getopt( argc, argv, "h" ) ) != EOF )
+ Extra_UtilGetoptReset();
+ while ( ( c = Extra_UtilGetopt( argc, argv, "h" ) ) != EOF )
{
switch ( c )
{
@@ -811,31 +1435,95 @@ int IoCommandWriteCnf( Abc_Frame_t * pAbc, int argc, char **argv )
goto usage;
}
}
-
- if ( pAbc->pNtkCur == NULL )
+ if ( argc != globalUtilOptind + 1 )
+ goto usage;
+ pNtk = pAbc->pNtkCur;
+ if ( pNtk == NULL )
{
fprintf( pAbc->Out, "Empty network.\n" );
return 0;
}
-
- if ( argc != util_optind + 1 )
+ // get the output file name
+ pFileName = argv[globalUtilOptind];
+ // call the corresponding file writer
+ if ( !Abc_NtkIsLogic(pNtk) )
{
- goto usage;
+ fprintf( pAbc->Out, "The network should be a logic network (if it an AIG, use command \"logic\")\n" );
+ return 0;
}
+ Io_WriteCellNet( pNtk, pFileName );
+ return 0;
- // get the input file name
- FileName = argv[util_optind];
- // write the file
- if ( !Io_WriteCnf( pAbc->pNtkCur, FileName ) )
+usage:
+ fprintf( pAbc->Err, "usage: write_cellnet [-h] <file>\n" );
+ fprintf( pAbc->Err, "\t write the network is the cellnet format\n" );
+ fprintf( pAbc->Err, "\t-h : print the help massage\n" );
+ fprintf( pAbc->Err, "\tfile : the name of the file to write\n" );
+ return 1;
+}
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int IoCommandWriteCnf( Abc_Frame_t * pAbc, int argc, char **argv )
+{
+ char * pFileName;
+ int c;
+ int fAllPrimes;
+ int fNewAlgo;
+ extern Abc_Ntk_t * Abc_NtkDarToCnf( Abc_Ntk_t * pNtk, char * pFileName );
+
+ fNewAlgo = 1;
+ fAllPrimes = 0;
+ Extra_UtilGetoptReset();
+ while ( ( c = Extra_UtilGetopt( argc, argv, "nph" ) ) != EOF )
{
- printf( "Writing CNF has failed.\n" );
- return 1;
+ switch ( c )
+ {
+ case 'n':
+ fNewAlgo ^= 1;
+ break;
+ case 'p':
+ fAllPrimes ^= 1;
+ break;
+ case 'h':
+ goto usage;
+ default:
+ goto usage;
+ }
}
+ if ( argc != globalUtilOptind + 1 )
+ goto usage;
+ // get the output file name
+ pFileName = argv[globalUtilOptind];
+ // check if the feature will be used
+ if ( Abc_NtkIsStrash(pAbc->pNtkCur) && fAllPrimes )
+ {
+ fAllPrimes = 0;
+ printf( "Warning: Selected option to write all primes has no effect when deriving CNF from AIG.\n" );
+ }
+ // call the corresponding file writer
+ if ( fNewAlgo )
+ Abc_NtkDarToCnf( pAbc->pNtkCur, pFileName );
+ else if ( fAllPrimes )
+ Io_WriteCnf( pAbc->pNtkCur, pFileName, 1 );
+ else
+ Io_Write( pAbc->pNtkCur, pFileName, IO_FILE_CNF );
return 0;
usage:
- fprintf( pAbc->Err, "usage: write_cnf [-h] <file>\n" );
+ fprintf( pAbc->Err, "usage: write_cnf [-nph] <file>\n" );
fprintf( pAbc->Err, "\t write the miter cone into a CNF file\n" );
+ fprintf( pAbc->Err, "\t-n : toggle using new algorithm [default = %s]\n", fNewAlgo? "yes" : "no" );
+ fprintf( pAbc->Err, "\t-p : toggle using all primes to enhance implicativity [default = %s]\n", fAllPrimes? "yes" : "no" );
fprintf( pAbc->Err, "\t-h : print the help massage\n" );
fprintf( pAbc->Err, "\tfile : the name of the file to write\n" );
return 1;
@@ -854,12 +1542,11 @@ usage:
***********************************************************************/
int IoCommandWriteDot( Abc_Frame_t * pAbc, int argc, char **argv )
{
- char * FileName;
- Vec_Ptr_t * vNodes;
+ char * pFileName;
int c;
- util_getopt_reset();
- while ( ( c = util_getopt( argc, argv, "h" ) ) != EOF )
+ Extra_UtilGetoptReset();
+ while ( ( c = Extra_UtilGetopt( argc, argv, "h" ) ) != EOF )
{
switch ( c )
{
@@ -869,40 +1556,24 @@ int IoCommandWriteDot( Abc_Frame_t * pAbc, int argc, char **argv )
goto usage;
}
}
-
- if ( pAbc->pNtkCur == NULL )
- {
- fprintf( pAbc->Out, "Empty network.\n" );
- return 0;
- }
-
- if ( !Abc_NtkIsStrash(pAbc->pNtkCur) )
- {
- fprintf( stdout, "IoCommandWriteDot(): Currently can only process logic networks with BDDs.\n" );
- return 0;
- }
-
- if ( argc != util_optind + 1 )
- {
+ if ( argc != globalUtilOptind + 1 )
goto usage;
- }
-
- // get the input file name
- FileName = argv[util_optind];
- // write the file
- vNodes = Abc_NtkCollectObjects( pAbc->pNtkCur );
- Io_WriteDot( pAbc->pNtkCur, vNodes, NULL, FileName );
- Vec_PtrFree( vNodes );
+ // get the output file name
+ pFileName = argv[globalUtilOptind];
+ // call the corresponding file writer
+ Io_Write( pAbc->pNtkCur, pFileName, IO_FILE_DOT );
return 0;
usage:
fprintf( pAbc->Err, "usage: write_dot [-h] <file>\n" );
- fprintf( pAbc->Err, "\t write the AIG into a DOT file\n" );
+ fprintf( pAbc->Err, "\t write the current network into a DOT file\n" );
fprintf( pAbc->Err, "\t-h : print the help massage\n" );
fprintf( pAbc->Err, "\tfile : the name of the file to write\n" );
return 1;
}
+#include "fra.h"
+
/**Function*************************************************************
Synopsis []
@@ -914,17 +1585,22 @@ usage:
SeeAlso []
***********************************************************************/
-int IoCommandWriteEqn( Abc_Frame_t * pAbc, int argc, char **argv )
+int IoCommandWriteCounter( Abc_Frame_t * pAbc, int argc, char **argv )
{
- Abc_Ntk_t * pNtk, * pNtkTemp;
- char * FileName;
+ Abc_Ntk_t * pNtk;
+ char * pFileName;
int c;
+ int fNames;
- util_getopt_reset();
- while ( ( c = util_getopt( argc, argv, "h" ) ) != EOF )
+ fNames = 0;
+ Extra_UtilGetoptReset();
+ while ( ( c = Extra_UtilGetopt( argc, argv, "nh" ) ) != EOF )
{
switch ( c )
{
+ case 'n':
+ fNames ^= 1;
+ break;
case 'h':
goto usage;
default:
@@ -939,32 +1615,128 @@ int IoCommandWriteEqn( Abc_Frame_t * pAbc, int argc, char **argv )
return 0;
}
- if ( argc != util_optind + 1 )
+ if ( argc != globalUtilOptind + 1 )
{
goto usage;
}
+ // get the input file name
+ pFileName = argv[globalUtilOptind];
- if ( !Abc_NtkIsLogic(pNtk) && !Abc_NtkIsStrash(pNtk) )
+ if ( pNtk->pModel == NULL && pNtk->pSeqModel == NULL )
{
- fprintf( stdout, "IoCommandWriteGml(): Currently can only process logic networks with BDDs.\n" );
+ fprintf( pAbc->Out, "Counter-example is not available.\n" );
return 0;
}
- // get the input file name
- FileName = argv[util_optind];
- // write the file
- // get rid of complemented covers if present
- if ( Abc_NtkIsSopLogic(pNtk) )
- Abc_NtkLogicMakeDirectSops(pNtk);
- // derive the netlist
- pNtkTemp = Abc_NtkLogicToNetlist(pNtk);
- if ( pNtkTemp == NULL )
+ // write the counter-example into the file
+ if ( pNtk->pModel )
{
- fprintf( pAbc->Out, "Writing BENCH has failed.\n" );
- return 0;
+ Abc_Obj_t * pObj;
+ FILE * pFile = fopen( pFileName, "w" );
+ int i;
+ if ( pFile == NULL )
+ {
+ fprintf( stdout, "IoCommandWriteCounter(): Cannot open the output file \"%s\".\n", pFileName );
+ return 1;
+ }
+ if ( fNames )
+ {
+ Abc_NtkForEachPi( pNtk, pObj, i )
+ fprintf( pFile, "%s=%c ", Abc_ObjName(pObj), '0'+(pNtk->pModel[i]==1) );
+ }
+ else
+ {
+ Abc_NtkForEachPi( pNtk, pObj, i )
+ fprintf( pFile, "%c", '0'+(pNtk->pModel[i]==1) );
+ }
+ fprintf( pFile, "\n" );
+ fclose( pFile );
+ }
+ else
+ {
+ Fra_Cex_t * pCex = pNtk->pSeqModel;
+ Abc_Obj_t * pObj;
+ FILE * pFile;
+ int i, f;
+ Abc_NtkForEachLatch( pNtk, pObj, i )
+ if ( !Abc_LatchIsInit0(pObj) )
+ {
+ fprintf( stdout, "IoCommandWriteCounter(): The init-state should be all-0 for counter-example to work.\n" );
+ fprintf( stdout, "Run commands \"undc\" and \"zero\" and then rerun the equivalence check.\n" );
+ return 1;
+ }
+
+ pFile = fopen( pFileName, "w" );
+ if ( pFile == NULL )
+ {
+ fprintf( stdout, "IoCommandWriteCounter(): Cannot open the output file \"%s\".\n", pFileName );
+ return 1;
+ }
+ if ( fNames )
+ {
+ Abc_NtkForEachLatch( pNtk, pObj, i )
+ fprintf( pFile, "%s@0=%c ", Abc_ObjName(Abc_ObjFanout0(pObj)), '0'+!Abc_LatchIsInit0(pObj) );
+ for ( f = 0; f <= pCex->iFrame; f++ )
+ Abc_NtkForEachPi( pNtk, pObj, i )
+ fprintf( pFile, "%s@%d=%c ", Abc_ObjName(pObj), f, '0'+Abc_InfoHasBit(pCex->pData, pCex->nRegs+pCex->nPis*f + i) );
+ }
+ else
+ {
+ Abc_NtkForEachLatch( pNtk, pObj, i )
+ fprintf( pFile, "%c", '0'+!Abc_LatchIsInit0(pObj) );
+ for ( i = pCex->nRegs; i < pCex->nBits; i++ )
+ fprintf( pFile, "%c", '0'+Abc_InfoHasBit(pCex->pData, i) );
+ }
+ fprintf( pFile, "\n" );
+ fclose( pFile );
}
- Io_WriteEqn( pNtkTemp, FileName );
- Abc_NtkDelete( pNtkTemp );
+
+ return 0;
+
+usage:
+ fprintf( pAbc->Err, "usage: write_counter [-nh] <file>\n" );
+ fprintf( pAbc->Err, "\t saves counter-example derived by \"sat\", \"iprove\", or \"dprove\"\n" );
+ fprintf( pAbc->Err, "\t the file contains values for each PI in the natural order\n" );
+ fprintf( pAbc->Err, "\t-n : write input names into the file [default = %s]\n", fNames? "yes": "no" );
+ fprintf( pAbc->Err, "\t-h : print the help massage\n" );
+ fprintf( pAbc->Err, "\tfile : the name of the file to write\n" );
+ return 1;
+}
+
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int IoCommandWriteEqn( Abc_Frame_t * pAbc, int argc, char **argv )
+{
+ char * pFileName;
+ int c;
+
+ Extra_UtilGetoptReset();
+ while ( ( c = Extra_UtilGetopt( argc, argv, "h" ) ) != EOF )
+ {
+ switch ( c )
+ {
+ case 'h':
+ goto usage;
+ default:
+ goto usage;
+ }
+ }
+ if ( argc != globalUtilOptind + 1 )
+ goto usage;
+ // get the output file name
+ pFileName = argv[globalUtilOptind];
+ // call the corresponding file writer
+ Io_Write( pAbc->pNtkCur, pFileName, IO_FILE_EQN );
return 0;
usage:
@@ -988,11 +1760,11 @@ usage:
***********************************************************************/
int IoCommandWriteGml( Abc_Frame_t * pAbc, int argc, char **argv )
{
- char * FileName;
+ char * pFileName;
int c;
- util_getopt_reset();
- while ( ( c = util_getopt( argc, argv, "h" ) ) != EOF )
+ Extra_UtilGetoptReset();
+ while ( ( c = Extra_UtilGetopt( argc, argv, "h" ) ) != EOF )
{
switch ( c )
{
@@ -1002,33 +1774,81 @@ int IoCommandWriteGml( Abc_Frame_t * pAbc, int argc, char **argv )
goto usage;
}
}
+ if ( argc != globalUtilOptind + 1 )
+ goto usage;
+ // get the output file name
+ pFileName = argv[globalUtilOptind];
+ // call the corresponding file writer
+ Io_Write( pAbc->pNtkCur, pFileName, IO_FILE_GML );
+ return 0;
+
+usage:
+ fprintf( pAbc->Err, "usage: write_gml [-h] <file>\n" );
+ fprintf( pAbc->Err, "\t write network using graph representation formal GML\n" );
+ fprintf( pAbc->Err, "\t-h : print the help massage\n" );
+ fprintf( pAbc->Err, "\tfile : the name of the file to write\n" );
+ return 1;
+}
+
+/**Function*************************************************************
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int IoCommandWriteList( Abc_Frame_t * pAbc, int argc, char **argv )
+{
+ char * pFileName;
+ int fUseHost;
+ int c;
+
+ printf( "This command currently does not work.\n" );
+ return 0;
+
+ fUseHost = 1;
+ Extra_UtilGetoptReset();
+ while ( ( c = Extra_UtilGetopt( argc, argv, "nh" ) ) != EOF )
+ {
+ switch ( c )
+ {
+ case 'n':
+ fUseHost ^= 1;
+ break;
+ case 'h':
+ goto usage;
+ default:
+ goto usage;
+ }
+ }
+ if ( argc != globalUtilOptind + 1 )
+ goto usage;
if ( pAbc->pNtkCur == NULL )
{
fprintf( pAbc->Out, "Empty network.\n" );
return 0;
}
-
- if ( !Abc_NtkIsLogic(pAbc->pNtkCur) && !Abc_NtkIsStrash(pAbc->pNtkCur) )
+/*
+ if ( !Abc_NtkIsSeq(pAbc->pNtkCur) )
{
- fprintf( stdout, "IoCommandWriteGml(): Currently can only process logic networks with BDDs.\n" );
+ fprintf( stdout, "IoCommandWriteList(): Can write adjacency list for sequential AIGs only.\n" );
return 0;
}
-
- if ( argc != util_optind + 1 )
- {
- goto usage;
- }
-
+*/
// get the input file name
- FileName = argv[util_optind];
+ pFileName = argv[globalUtilOptind];
// write the file
- Io_WriteGml( pAbc->pNtkCur, FileName );
+ Io_WriteList( pAbc->pNtkCur, pFileName, fUseHost );
return 0;
usage:
- fprintf( pAbc->Err, "usage: write_gml [-h] <file>\n" );
+ fprintf( pAbc->Err, "usage: write_list [-nh] <file>\n" );
fprintf( pAbc->Err, "\t write network using graph representation formal GML\n" );
+ fprintf( pAbc->Err, "\t-n : toggle writing host node [default = %s]\n", fUseHost? "yes":"no" );
fprintf( pAbc->Err, "\t-h : print the help massage\n" );
fprintf( pAbc->Err, "\tfile : the name of the file to write\n" );
return 1;
@@ -1047,12 +1867,11 @@ usage:
***********************************************************************/
int IoCommandWritePla( Abc_Frame_t * pAbc, int argc, char **argv )
{
- Abc_Ntk_t * pNtk, * pNtkTemp;
- char * FileName;
+ char * pFileName;
int c;
- util_getopt_reset();
- while ( ( c = util_getopt( argc, argv, "h" ) ) != EOF )
+ Extra_UtilGetoptReset();
+ while ( ( c = Extra_UtilGetopt( argc, argv, "h" ) ) != EOF )
{
switch ( c )
{
@@ -1062,47 +1881,111 @@ int IoCommandWritePla( Abc_Frame_t * pAbc, int argc, char **argv )
goto usage;
}
}
+ if ( argc != globalUtilOptind + 1 )
+ goto usage;
+ // get the output file name
+ pFileName = argv[globalUtilOptind];
+ // call the corresponding file writer
+ Io_Write( pAbc->pNtkCur, pFileName, IO_FILE_PLA );
+ return 0;
- pNtk = pAbc->pNtkCur;
- if ( pNtk == NULL )
- {
- fprintf( pAbc->Out, "Empty network.\n" );
- return 0;
- }
+usage:
+ fprintf( pAbc->Err, "usage: write_pla [-h] <file>\n" );
+ fprintf( pAbc->Err, "\t write the collapsed network into a PLA file\n" );
+ fprintf( pAbc->Err, "\t-h : print the help massage\n" );
+ fprintf( pAbc->Err, "\tfile : the name of the file to write\n" );
+ return 1;
+}
- if ( Abc_NtkGetLevelNum(pNtk) > 1 )
- {
- fprintf( pAbc->Out, "PLA writing is available for collapsed networks.\n" );
- return 0;
- }
+/**Function*************************************************************
+
+ Synopsis []
- if ( Abc_NtkLatchNum(pNtk) > 0 )
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int IoCommandWriteVerilog( Abc_Frame_t * pAbc, int argc, char **argv )
+{
+ char * pFileName;
+ int c;
+
+ Extra_UtilGetoptReset();
+ while ( ( c = Extra_UtilGetopt( argc, argv, "h" ) ) != EOF )
{
- fprintf( pAbc->Out, "Latches are writed at PI/PO pairs in the PLA file.\n" );
- return 0;
+ switch ( c )
+ {
+ case 'h':
+ goto usage;
+ default:
+ goto usage;
+ }
}
+ if ( argc != globalUtilOptind + 1 )
+ goto usage;
+ // get the output file name
+ pFileName = argv[globalUtilOptind];
+ // call the corresponding file writer
+ Io_Write( pAbc->pNtkCur, pFileName, IO_FILE_VERILOG );
+ return 0;
+
+usage:
+ fprintf( pAbc->Err, "usage: write_verilog [-h] <file>\n" );
+ fprintf( pAbc->Err, "\t write the current network in Verilog format\n" );
+ fprintf( pAbc->Err, "\t-h : print the help massage\n" );
+ fprintf( pAbc->Err, "\tfile : the name of the file to write\n" );
+ return 1;
+}
- if ( argc != util_optind + 1 )
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int IoCommandWriteVerLib( Abc_Frame_t * pAbc, int argc, char **argv )
+{
+ Abc_Lib_t * pLibrary;
+ char * pFileName;
+ int c;
+ extern void Io_WriteVerilogLibrary( Abc_Lib_t * pLibrary, char * pFileName );
+
+ Extra_UtilGetoptReset();
+ while ( ( c = Extra_UtilGetopt( argc, argv, "h" ) ) != EOF )
{
- goto usage;
+ switch ( c )
+ {
+ case 'h':
+ goto usage;
+ default:
+ goto usage;
+ }
}
+ if ( argc != globalUtilOptind + 1 )
+ goto usage;
// get the input file name
- FileName = argv[util_optind];
-
+ pFileName = argv[globalUtilOptind];
// derive the netlist
- pNtkTemp = Abc_NtkLogicToNetlist(pNtk);
- if ( pNtkTemp == NULL )
+ pLibrary = Abc_FrameReadLibVer();
+ if ( pLibrary == NULL )
{
- fprintf( pAbc->Out, "Writing PLA has failed.\n" );
+ fprintf( pAbc->Out, "Verilog library is not specified.\n" );
return 0;
}
- Io_WritePla( pNtkTemp, FileName );
- Abc_NtkDelete( pNtkTemp );
+// Io_WriteVerilogLibrary( pLibrary, pFileName );
return 0;
usage:
- fprintf( pAbc->Err, "usage: write_pla [-h] <file>\n" );
- fprintf( pAbc->Err, "\t write the collapsed network into a PLA file\n" );
+ fprintf( pAbc->Err, "usage: write_verlib [-h] <file>\n" );
+ fprintf( pAbc->Err, "\t write the current verilog library\n" );
fprintf( pAbc->Err, "\t-h : print the help massage\n" );
fprintf( pAbc->Err, "\tfile : the name of the file to write\n" );
return 1;
diff --git a/src/base/io/io.h b/src/base/io/io.h
index 6bf3a85c..126de332 100644
--- a/src/base/io/io.h
+++ b/src/base/io/io.h
@@ -21,6 +21,10 @@
#ifndef __IO_H__
#define __IO_H__
+#ifdef __cplusplus
+extern "C" {
+#endif
+
////////////////////////////////////////////////////////////////////////
/// INCLUDES ///
////////////////////////////////////////////////////////////////////////
@@ -35,8 +39,27 @@
/// BASIC TYPES ///
////////////////////////////////////////////////////////////////////////
+// network functionality
+typedef enum {
+ IO_FILE_NONE = 0,
+ IO_FILE_AIGER,
+ IO_FILE_BAF,
+ IO_FILE_BLIF,
+ IO_FILE_BLIFMV,
+ IO_FILE_BENCH,
+ IO_FILE_CNF,
+ IO_FILE_DOT,
+ IO_FILE_EDIF,
+ IO_FILE_EQN,
+ IO_FILE_GML,
+ IO_FILE_LIST,
+ IO_FILE_PLA,
+ IO_FILE_VERILOG,
+ IO_FILE_UNKNOWN
+} Io_FileType_t;
+
////////////////////////////////////////////////////////////////////////
-/// MACRO DEFITIONS ///
+/// MACRO DEFINITIONS ///
////////////////////////////////////////////////////////////////////////
#define IO_WRITE_LINE_LENGTH 78 // the output line length
@@ -45,48 +68,79 @@
/// FUNCTION DECLARATIONS ///
////////////////////////////////////////////////////////////////////////
-/*=== abcRead.c ==========================================================*/
-extern Abc_Ntk_t * Io_Read( char * pFileName, int fCheck );
-/*=== abcReadBlif.c ==========================================================*/
+/*=== abcReadAiger.c ==========================================================*/
+extern Abc_Ntk_t * Io_ReadAiger( char * pFileName, int fCheck );
+/*=== abcReadBaf.c ============================================================*/
+extern Abc_Ntk_t * Io_ReadBaf( char * pFileName, int fCheck );
+/*=== abcReadBlif.c ===========================================================*/
extern Abc_Ntk_t * Io_ReadBlif( char * pFileName, int fCheck );
+/*=== abcReadBlifMv.c =========================================================*/
+extern Abc_Ntk_t * Io_ReadBlifMv( char * pFileName, int fBlifMv, int fCheck );
/*=== abcReadBench.c ==========================================================*/
extern Abc_Ntk_t * Io_ReadBench( char * pFileName, int fCheck );
-/*=== abcReadEdif.c ==========================================================*/
+/*=== abcReadEdif.c ===========================================================*/
extern Abc_Ntk_t * Io_ReadEdif( char * pFileName, int fCheck );
-/*=== abcReadEqn.c ==========================================================*/
+/*=== abcReadEqn.c ============================================================*/
extern Abc_Ntk_t * Io_ReadEqn( char * pFileName, int fCheck );
-/*=== abcReadVerilog.c ==========================================================*/
-extern Abc_Ntk_t * Io_ReadVerilog( char * pFileName, int fCheck );
-/*=== abcReadPla.c ==========================================================*/
+/*=== abcReadPla.c ============================================================*/
extern Abc_Ntk_t * Io_ReadPla( char * pFileName, int fCheck );
-/*=== abcUtil.c ==========================================================*/
-extern Abc_Obj_t * Io_ReadCreatePi( Abc_Ntk_t * pNtk, char * pName );
-extern Abc_Obj_t * Io_ReadCreatePo( Abc_Ntk_t * pNtk, char * pName );
-extern Abc_Obj_t * Io_ReadCreateLatch( Abc_Ntk_t * pNtk, char * pNetLI, char * pNetLO );
-extern Abc_Obj_t * Io_ReadCreateNode( Abc_Ntk_t * pNtk, char * pNameOut, char * pNamesIn[], int nInputs );
-extern Abc_Obj_t * Io_ReadCreateConst( Abc_Ntk_t * pNtk, char * pName, bool fConst1 );
-extern Abc_Obj_t * Io_ReadCreateInv( Abc_Ntk_t * pNtk, char * pNameIn, char * pNameOut );
-extern Abc_Obj_t * Io_ReadCreateBuf( Abc_Ntk_t * pNtk, char * pNameIn, char * pNameOut );
+/*=== abcReadVerilog.c ========================================================*/
+extern Abc_Ntk_t * Io_ReadVerilog( char * pFileName, int fCheck );
+/*=== abcWriteAiger.c =========================================================*/
+extern void Io_WriteAiger( Abc_Ntk_t * pNtk, char * pFileName, int fWriteSymbols, int fCompact );
+/*=== abcWriteBaf.c ===========================================================*/
+extern void Io_WriteBaf( Abc_Ntk_t * pNtk, char * pFileName );
/*=== abcWriteBlif.c ==========================================================*/
-extern void Io_WriteBlif( Abc_Ntk_t * pNtk, char * pFileName, int fWriteLatches );
extern void Io_WriteBlifLogic( Abc_Ntk_t * pNtk, char * pFileName, int fWriteLatches );
+extern void Io_WriteBlif( Abc_Ntk_t * pNtk, char * pFileName, int fWriteLatches );
extern void Io_WriteTimingInfo( FILE * pFile, Abc_Ntk_t * pNtk );
-/*=== abcWriteBench.c ==========================================================*/
+/*=== abcWriteBlifMv.c ==========================================================*/
+extern void Io_WriteBlifMv( Abc_Ntk_t * pNtk, char * FileName );
+/*=== abcWriteBench.c =========================================================*/
extern int Io_WriteBench( Abc_Ntk_t * pNtk, char * FileName );
-/*=== abcWriteCnf.c ==========================================================*/
-extern int Io_WriteCnf( Abc_Ntk_t * pNtk, char * FileName );
-/*=== abcWriteDot.c ==========================================================*/
-extern void Io_WriteDot( Abc_Ntk_t * pNtk, Vec_Ptr_t * vNodes, Vec_Ptr_t * vNodesShow, char * pFileName );
-/*=== abcWriteEqn.c ==========================================================*/
+extern int Io_WriteBenchLut( Abc_Ntk_t * pNtk, char * FileName );
+/*=== abcWriteCnf.c ===========================================================*/
+extern int Io_WriteCnf( Abc_Ntk_t * pNtk, char * FileName, int fAllPrimes );
+/*=== abcWriteDot.c ===========================================================*/
+extern void Io_WriteDot( Abc_Ntk_t * pNtk, char * FileName );
+extern void Io_WriteDotNtk( Abc_Ntk_t * pNtk, Vec_Ptr_t * vNodes, Vec_Ptr_t * vNodesShow, char * pFileName, int fGateNames, int fUseReverse );
+extern void Io_WriteDotSeq( Abc_Ntk_t * pNtk, Vec_Ptr_t * vNodes, Vec_Ptr_t * vNodesShow, char * pFileName, int fGateNames, int fUseReverse );
+/*=== abcWriteEqn.c ===========================================================*/
extern void Io_WriteEqn( Abc_Ntk_t * pNtk, char * pFileName );
-/*=== abcWriteGml.c ==========================================================*/
+/*=== abcWriteGml.c ===========================================================*/
extern void Io_WriteGml( Abc_Ntk_t * pNtk, char * pFileName );
-/*=== abcWritePla.c ==========================================================*/
+/*=== abcWriteList.c ==========================================================*/
+extern void Io_WriteList( Abc_Ntk_t * pNtk, char * pFileName, int fUseHost );
+/*=== abcWritePla.c ===========================================================*/
extern int Io_WritePla( Abc_Ntk_t * pNtk, char * FileName );
+/*=== abcWriteVerilog.c =======================================================*/
+extern void Io_WriteVerilog( Abc_Ntk_t * pNtk, char * FileName );
+/*=== abcUtil.c ===============================================================*/
+extern Io_FileType_t Io_ReadFileType( char * pFileName );
+extern Abc_Ntk_t * Io_ReadNetlist( char * pFileName, Io_FileType_t FileType, int fCheck );
+extern Abc_Ntk_t * Io_Read( char * pFileName, Io_FileType_t FileType, int fCheck );
+extern void Io_Write( Abc_Ntk_t * pNtk, char * pFileName, Io_FileType_t FileType );
+extern void Io_WriteHie( Abc_Ntk_t * pNtk, char * pBaseName, char * pFileName );
+extern Abc_Obj_t * Io_ReadCreatePi( Abc_Ntk_t * pNtk, char * pName );
+extern Abc_Obj_t * Io_ReadCreatePo( Abc_Ntk_t * pNtk, char * pName );
+extern Abc_Obj_t * Io_ReadCreateAssert( Abc_Ntk_t * pNtk, char * pName );
+extern Abc_Obj_t * Io_ReadCreateLatch( Abc_Ntk_t * pNtk, char * pNetLI, char * pNetLO );
+extern Abc_Obj_t * Io_ReadCreateResetLatch( Abc_Ntk_t * pNtk, int fBlifMv );
+extern Abc_Obj_t * Io_ReadCreateResetMux( Abc_Ntk_t * pNtk, char * pResetLO, char * pDataLI, int fBlifMv );
+extern Abc_Obj_t * Io_ReadCreateNode( Abc_Ntk_t * pNtk, char * pNameOut, char * pNamesIn[], int nInputs );
+extern Abc_Obj_t * Io_ReadCreateConst( Abc_Ntk_t * pNtk, char * pName, bool fConst1 );
+extern Abc_Obj_t * Io_ReadCreateInv( Abc_Ntk_t * pNtk, char * pNameIn, char * pNameOut );
+extern Abc_Obj_t * Io_ReadCreateBuf( Abc_Ntk_t * pNtk, char * pNameIn, char * pNameOut );
+extern FILE * Io_FileOpen( const char * FileName, const char * PathVar, const char * Mode, int fVerbose );
+
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
////////////////////////////////////////////////////////////////////////
/// END OF FILE ///
////////////////////////////////////////////////////////////////////////
-#endif
-
diff --git a/src/base/io/ioInt.h b/src/base/io/ioInt.h
index 736884c4..3daf3c75 100644
--- a/src/base/io/ioInt.h
+++ b/src/base/io/ioInt.h
@@ -34,16 +34,16 @@
////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////
-/// MACRO DEFITIONS ///
+/// MACRO DEFINITIONS ///
////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////
/// FUNCTION DECLARATIONS ///
////////////////////////////////////////////////////////////////////////
+#endif
+
////////////////////////////////////////////////////////////////////////
/// END OF FILE ///
////////////////////////////////////////////////////////////////////////
-#endif
-
diff --git a/src/base/io/ioRead.c b/src/base/io/ioRead.c
deleted file mode 100644
index acf4deda..00000000
--- a/src/base/io/ioRead.c
+++ /dev/null
@@ -1,81 +0,0 @@
-/**CFile****************************************************************
-
- FileName [ioRead.c]
-
- SystemName [ABC: Logic synthesis and verification system.]
-
- PackageName [Command processing package.]
-
- Synopsis [Procedure to read network from file.]
-
- Author [Alan Mishchenko]
-
- Affiliation [UC Berkeley]
-
- Date [Ver. 1.0. Started - June 20, 2005.]
-
- Revision [$Id: ioRead.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
-
-***********************************************************************/
-
-#include "io.h"
-
-////////////////////////////////////////////////////////////////////////
-/// DECLARATIONS ///
-////////////////////////////////////////////////////////////////////////
-
-////////////////////////////////////////////////////////////////////////
-/// FUNCTION DEFITIONS ///
-////////////////////////////////////////////////////////////////////////
-
-/**Function*************************************************************
-
- Synopsis [Read the network from a file.]
-
- Description []
-
- SideEffects []
-
- SeeAlso []
-
-***********************************************************************/
-Abc_Ntk_t * Io_Read( char * pFileName, int fCheck )
-{
- Abc_Ntk_t * pNtk, * pTemp;
- // set the new network
- if ( Extra_FileNameCheckExtension( pFileName, "blif" ) )
- pNtk = Io_ReadBlif( pFileName, fCheck );
- else if ( Extra_FileNameCheckExtension( pFileName, "v" ) )
- pNtk = Io_ReadVerilog( pFileName, fCheck );
- else if ( Extra_FileNameCheckExtension( pFileName, "bench" ) )
- pNtk = Io_ReadBench( pFileName, fCheck );
- else if ( Extra_FileNameCheckExtension( pFileName, "edf" ) )
- pNtk = Io_ReadEdif( pFileName, fCheck );
- else if ( Extra_FileNameCheckExtension( pFileName, "pla" ) )
- pNtk = Io_ReadPla( pFileName, fCheck );
- else if ( Extra_FileNameCheckExtension( pFileName, "eqn" ) )
- pNtk = Io_ReadEqn( pFileName, fCheck );
- else
- {
- fprintf( stderr, "Unknown file format\n" );
- return NULL;
- }
- if ( pNtk == NULL )
- return NULL;
-
- pNtk = Abc_NtkNetlistToLogic( pTemp = pNtk );
- Abc_NtkDelete( pTemp );
- if ( pNtk == NULL )
- {
- fprintf( stdout, "Converting to logic network after reading has failed.\n" );
- return NULL;
- }
- return pNtk;
-}
-
-////////////////////////////////////////////////////////////////////////
-/// END OF FILE ///
-////////////////////////////////////////////////////////////////////////
-
-
-
diff --git a/src/base/io/ioReadAiger.c b/src/base/io/ioReadAiger.c
new file mode 100644
index 00000000..4820bced
--- /dev/null
+++ b/src/base/io/ioReadAiger.c
@@ -0,0 +1,366 @@
+/**CFile****************************************************************
+
+ FileName [ioReadAiger.c]
+
+ SystemName [ABC: Logic synthesis and verification system.]
+
+ PackageName [Command processing package.]
+
+ Synopsis [Procedures to read binary AIGER format developed by
+ Armin Biere, Johannes Kepler University (http://fmv.jku.at/)]
+
+ Author [Alan Mishchenko]
+
+ Affiliation [UC Berkeley]
+
+ Date [Ver. 1.0. Started - December 16, 2006.]
+
+ Revision [$Id: ioReadAiger.c,v 1.00 2006/12/16 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "io.h"
+
+////////////////////////////////////////////////////////////////////////
+/// DECLARATIONS ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+/// FUNCTION DEFINITIONS ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+ Synopsis [Extracts one unsigned AIG edge from the input buffer.]
+
+ Description [This procedure is a slightly modified version of Armin Biere's
+ procedure "unsigned decode (FILE * file)". ]
+
+ SideEffects [Updates the current reading position.]
+
+ SeeAlso []
+
+***********************************************************************/
+unsigned Io_ReadAigerDecode( char ** ppPos )
+{
+ unsigned x = 0, i = 0;
+ unsigned char ch;
+
+// while ((ch = getnoneofch (file)) & 0x80)
+ while ((ch = *(*ppPos)++) & 0x80)
+ x |= (ch & 0x7f) << (7 * i++);
+
+ return x | (ch << (7 * i));
+}
+
+/**Function*************************************************************
+
+ Synopsis [Decodes the encoded array of literals.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Vec_Int_t * Io_WriteDecodeLiterals( char ** ppPos, int nEntries )
+{
+ Vec_Int_t * vLits;
+ int Lit, LitPrev, Diff, i;
+ vLits = Vec_IntAlloc( nEntries );
+ LitPrev = Io_ReadAigerDecode( ppPos );
+ Vec_IntPush( vLits, LitPrev );
+ for ( i = 1; i < nEntries; i++ )
+ {
+// Diff = Lit - LitPrev;
+// Diff = (Lit < LitPrev)? -Diff : Diff;
+// Diff = ((2 * Diff) << 1) | (int)(Lit < LitPrev);
+ Diff = Io_ReadAigerDecode( ppPos );
+ Diff = (Diff & 1)? -(Diff >> 1) : Diff >> 1;
+ Lit = Diff + LitPrev;
+ Vec_IntPush( vLits, Lit );
+ LitPrev = Lit;
+ }
+ return vLits;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Reads the AIG in the binary AIGER format.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Abc_Ntk_t * Io_ReadAiger( char * pFileName, int fCheck )
+{
+ ProgressBar * pProgress;
+ FILE * pFile;
+ Vec_Ptr_t * vNodes, * vTerms;
+ Vec_Int_t * vLits = NULL;
+ Abc_Obj_t * pObj, * pNode0, * pNode1;
+ Abc_Ntk_t * pNtkNew;
+ int nTotal, nInputs, nOutputs, nLatches, nAnds, nFileSize, iTerm, nDigits, i;
+ char * pContents, * pDrivers, * pSymbols, * pCur, * pName, * pType;
+ unsigned uLit0, uLit1, uLit;
+
+ // read the file into the buffer
+ nFileSize = Extra_FileSize( pFileName );
+ pFile = fopen( pFileName, "rb" );
+ pContents = ALLOC( char, nFileSize );
+ fread( pContents, nFileSize, 1, pFile );
+ fclose( pFile );
+
+ // check if the input file format is correct
+ if ( strncmp(pContents, "aig", 3) != 0 || (pContents[3] != ' ' && pContents[3] != '2') )
+ {
+ fprintf( stdout, "Wrong input file format.\n" );
+ return NULL;
+ }
+
+ // allocate the empty AIG
+ pNtkNew = Abc_NtkAlloc( ABC_NTK_STRASH, ABC_FUNC_AIG, 1 );
+ pName = Extra_FileNameGeneric( pFileName );
+ pNtkNew->pName = Extra_UtilStrsav( pName );
+ pNtkNew->pSpec = Extra_UtilStrsav( pFileName );
+ free( pName );
+
+
+ // read the file type
+ pCur = pContents; while ( *pCur++ != ' ' );
+ // read the number of objects
+ nTotal = atoi( pCur ); while ( *pCur++ != ' ' );
+ // read the number of inputs
+ nInputs = atoi( pCur ); while ( *pCur++ != ' ' );
+ // read the number of latches
+ nLatches = atoi( pCur ); while ( *pCur++ != ' ' );
+ // read the number of outputs
+ nOutputs = atoi( pCur ); while ( *pCur++ != ' ' );
+ // read the number of nodes
+ nAnds = atoi( pCur ); while ( *pCur++ != '\n' );
+ // check the parameters
+ if ( nTotal != nInputs + nLatches + nAnds )
+ {
+ fprintf( stdout, "The paramters are wrong.\n" );
+ return NULL;
+ }
+
+ // prepare the array of nodes
+ vNodes = Vec_PtrAlloc( 1 + nInputs + nLatches + nAnds );
+ Vec_PtrPush( vNodes, Abc_ObjNot( Abc_AigConst1(pNtkNew) ) );
+
+ // create the PIs
+ for ( i = 0; i < nInputs; i++ )
+ {
+ pObj = Abc_NtkCreatePi(pNtkNew);
+ Vec_PtrPush( vNodes, pObj );
+ }
+ // create the POs
+ for ( i = 0; i < nOutputs; i++ )
+ {
+ pObj = Abc_NtkCreatePo(pNtkNew);
+ }
+ // create the latches
+ nDigits = Extra_Base10Log( nLatches );
+ for ( i = 0; i < nLatches; i++ )
+ {
+ pObj = Abc_NtkCreateLatch(pNtkNew);
+ Abc_LatchSetInit0( pObj );
+ pNode0 = Abc_NtkCreateBi(pNtkNew);
+ pNode1 = Abc_NtkCreateBo(pNtkNew);
+ Abc_ObjAddFanin( pObj, pNode0 );
+ Abc_ObjAddFanin( pNode1, pObj );
+ Vec_PtrPush( vNodes, pNode1 );
+ // assign names to latch and its input
+// Abc_ObjAssignName( pObj, Abc_ObjNameDummy("_L", i, nDigits), NULL );
+// printf( "Creating latch %s with input %d and output %d.\n", Abc_ObjName(pObj), pNode0->Id, pNode1->Id );
+ }
+
+
+ if ( pContents[3] == ' ' ) // standard AIGER
+ {
+ // remember the beginning of latch/PO literals
+ pDrivers = pCur;
+ // scroll to the beginning of the binary data
+ for ( i = 0; i < nLatches + nOutputs; )
+ if ( *pCur++ == '\n' )
+ i++;
+ }
+ else // modified AIGER
+ {
+ vLits = Io_WriteDecodeLiterals( &pCur, nLatches + nOutputs );
+ }
+
+ // create the AND gates
+ pProgress = Extra_ProgressBarStart( stdout, nAnds );
+ for ( i = 0; i < nAnds; i++ )
+ {
+ Extra_ProgressBarUpdate( pProgress, i, NULL );
+ uLit = ((i + 1 + nInputs + nLatches) << 1);
+ uLit1 = uLit - Io_ReadAigerDecode( &pCur );
+ uLit0 = uLit1 - Io_ReadAigerDecode( &pCur );
+// assert( uLit1 > uLit0 );
+ pNode0 = Abc_ObjNotCond( Vec_PtrEntry(vNodes, uLit0 >> 1), uLit0 & 1 );
+ pNode1 = Abc_ObjNotCond( Vec_PtrEntry(vNodes, uLit1 >> 1), uLit1 & 1 );
+ assert( Vec_PtrSize(vNodes) == i + 1 + nInputs + nLatches );
+ Vec_PtrPush( vNodes, Abc_AigAnd(pNtkNew->pManFunc, pNode0, pNode1) );
+ }
+ Extra_ProgressBarStop( pProgress );
+
+ // remember the place where symbols begin
+ pSymbols = pCur;
+
+ // read the latch driver literals
+ pCur = pDrivers;
+ if ( pContents[3] == ' ' ) // standard AIGER
+ {
+ Abc_NtkForEachLatchInput( pNtkNew, pObj, i )
+ {
+ uLit0 = atoi( pCur ); while ( *pCur++ != '\n' );
+ pNode0 = Abc_ObjNotCond( Vec_PtrEntry(vNodes, uLit0 >> 1), (uLit0 & 1) );//^ (uLit0 < 2) );
+ Abc_ObjAddFanin( pObj, pNode0 );
+ }
+ // read the PO driver literals
+ Abc_NtkForEachPo( pNtkNew, pObj, i )
+ {
+ uLit0 = atoi( pCur ); while ( *pCur++ != '\n' );
+ pNode0 = Abc_ObjNotCond( Vec_PtrEntry(vNodes, uLit0 >> 1), (uLit0 & 1) );//^ (uLit0 < 2) );
+ Abc_ObjAddFanin( pObj, pNode0 );
+ }
+ }
+ else
+ {
+ // read the latch driver literals
+ Abc_NtkForEachLatchInput( pNtkNew, pObj, i )
+ {
+ uLit0 = Vec_IntEntry( vLits, i );
+ pNode0 = Abc_ObjNotCond( Vec_PtrEntry(vNodes, uLit0 >> 1), (uLit0 & 1) );
+ Abc_ObjAddFanin( pObj, pNode0 );
+ }
+ // read the PO driver literals
+ Abc_NtkForEachPo( pNtkNew, pObj, i )
+ {
+ uLit0 = Vec_IntEntry( vLits, i+Abc_NtkLatchNum(pNtkNew) );
+ pNode0 = Abc_ObjNotCond( Vec_PtrEntry(vNodes, uLit0 >> 1), (uLit0 & 1) );
+ Abc_ObjAddFanin( pObj, pNode0 );
+ }
+ Vec_IntFree( vLits );
+ }
+
+ // read the names if present
+ pCur = pSymbols;
+ if ( *pCur != 'c' )
+ {
+ int Counter = 0;
+ while ( pCur < pContents + nFileSize && *pCur != 'c' )
+ {
+ // get the terminal type
+ pType = pCur;
+ if ( *pCur == 'i' )
+ vTerms = pNtkNew->vPis;
+ else if ( *pCur == 'l' )
+ vTerms = pNtkNew->vBoxes;
+ else if ( *pCur == 'o' )
+ vTerms = pNtkNew->vPos;
+ else
+ {
+ fprintf( stdout, "Wrong terminal type.\n" );
+ return NULL;
+ }
+ // get the terminal number
+ iTerm = atoi( ++pCur ); while ( *pCur++ != ' ' );
+ // get the node
+ if ( iTerm >= Vec_PtrSize(vTerms) )
+ {
+ fprintf( stdout, "The number of terminal is out of bound.\n" );
+ return NULL;
+ }
+ pObj = Vec_PtrEntry( vTerms, iTerm );
+ if ( *pType == 'l' )
+ pObj = Abc_ObjFanout0(pObj);
+ // assign the name
+ pName = pCur; while ( *pCur++ != '\n' );
+ // assign this name
+ *(pCur-1) = 0;
+ Abc_ObjAssignName( pObj, pName, NULL );
+ if ( *pType == 'l' )
+ {
+ Abc_ObjAssignName( Abc_ObjFanin0(pObj), Abc_ObjName(pObj), "L" );
+ Abc_ObjAssignName( Abc_ObjFanin0(Abc_ObjFanin0(pObj)), Abc_ObjName(pObj), "_in" );
+ }
+ // mark the node as named
+ pObj->pCopy = (Abc_Obj_t *)Abc_ObjName(pObj);
+ }
+
+ // assign the remaining names
+ Abc_NtkForEachPi( pNtkNew, pObj, i )
+ {
+ if ( pObj->pCopy ) continue;
+ Abc_ObjAssignName( pObj, Abc_ObjName(pObj), NULL );
+ Counter++;
+ }
+ Abc_NtkForEachLatchOutput( pNtkNew, pObj, i )
+ {
+ if ( pObj->pCopy ) continue;
+ Abc_ObjAssignName( pObj, Abc_ObjName(pObj), NULL );
+ Abc_ObjAssignName( Abc_ObjFanin0(pObj), Abc_ObjName(pObj), "L" );
+ Abc_ObjAssignName( Abc_ObjFanin0(Abc_ObjFanin0(pObj)), Abc_ObjName(pObj), "_in" );
+ Counter++;
+ }
+ Abc_NtkForEachPo( pNtkNew, pObj, i )
+ {
+ if ( pObj->pCopy ) continue;
+ Abc_ObjAssignName( pObj, Abc_ObjName(pObj), NULL );
+ Counter++;
+ }
+// if ( Counter )
+// printf( "Io_ReadAiger(): Added %d default names for nameless I/O/register objects.\n", Counter );
+ }
+ else
+ {
+// printf( "Io_ReadAiger(): I/O/register names are not given. Generating short names.\n" );
+ Abc_NtkShortNames( pNtkNew );
+ }
+
+ // read the name of the model if given
+ if ( *pCur == 'c' )
+ {
+ if ( !strncmp( pCur + 2, ".model", 6 ) )
+ {
+ char * pTemp;
+ for ( pTemp = pCur + 9; *pTemp && *pTemp != '\n'; pTemp++ );
+ *pTemp = 0;
+ free( pNtkNew->pName );
+ pNtkNew->pName = Extra_UtilStrsav( pCur + 9 );
+ }
+ }
+
+
+ // skipping the comments
+ free( pContents );
+ Vec_PtrFree( vNodes );
+
+ // remove the extra nodes
+ Abc_AigCleanup( pNtkNew->pManFunc );
+
+ // check the result
+ if ( fCheck && !Abc_NtkCheckRead( pNtkNew ) )
+ {
+ printf( "Io_ReadAiger: The network check has failed.\n" );
+ Abc_NtkDelete( pNtkNew );
+ return NULL;
+ }
+ return pNtkNew;
+}
+
+
+
+////////////////////////////////////////////////////////////////////////
+/// END OF FILE ///
+////////////////////////////////////////////////////////////////////////
+
+
diff --git a/src/base/io/ioReadBaf.c b/src/base/io/ioReadBaf.c
new file mode 100644
index 00000000..8dce54af
--- /dev/null
+++ b/src/base/io/ioReadBaf.c
@@ -0,0 +1,171 @@
+/**CFile****************************************************************
+
+ FileName [ioReadBaf.c]
+
+ SystemName [ABC: Logic synthesis and verification system.]
+
+ PackageName [Command processing package.]
+
+ Synopsis [Procedures to read AIG in the binary format.]
+
+ Author [Alan Mishchenko]
+
+ Affiliation [UC Berkeley]
+
+ Date [Ver. 1.0. Started - June 20, 2005.]
+
+ Revision [$Id: ioReadBaf.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "io.h"
+
+////////////////////////////////////////////////////////////////////////
+/// DECLARATIONS ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+/// FUNCTION DEFINITIONS ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+ Synopsis [Reads the AIG in the binary format.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Abc_Ntk_t * Io_ReadBaf( char * pFileName, int fCheck )
+{
+ ProgressBar * pProgress;
+ FILE * pFile;
+ Vec_Ptr_t * vNodes;
+ Abc_Obj_t * pObj, * pNode0, * pNode1;
+ Abc_Ntk_t * pNtkNew;
+ int nInputs, nOutputs, nLatches, nAnds, nFileSize, Num, i;
+ char * pContents, * pName, * pCur;
+ unsigned * pBufferNode;
+
+ // read the file into the buffer
+ nFileSize = Extra_FileSize( pFileName );
+ pFile = fopen( pFileName, "rb" );
+ pContents = ALLOC( char, nFileSize );
+ fread( pContents, nFileSize, 1, pFile );
+ fclose( pFile );
+
+ // skip the comments (comment lines begin with '#' and end with '\n')
+ for ( pCur = pContents; *pCur == '#'; )
+ while ( *pCur++ != '\n' );
+
+ // read the name
+ pName = pCur; while ( *pCur++ );
+ // read the number of inputs
+ nInputs = atoi( pCur ); while ( *pCur++ );
+ // read the number of outputs
+ nOutputs = atoi( pCur ); while ( *pCur++ );
+ // read the number of latches
+ nLatches = atoi( pCur ); while ( *pCur++ );
+ // read the number of nodes
+ nAnds = atoi( pCur ); while ( *pCur++ );
+
+ // allocate the empty AIG
+ pNtkNew = Abc_NtkAlloc( ABC_NTK_STRASH, ABC_FUNC_AIG, 1 );
+ pNtkNew->pName = Extra_UtilStrsav( pName );
+ pNtkNew->pSpec = Extra_UtilStrsav( pFileName );
+
+ // prepare the array of nodes
+ vNodes = Vec_PtrAlloc( 1 + nInputs + nLatches + nAnds );
+ Vec_PtrPush( vNodes, Abc_AigConst1(pNtkNew) );
+
+ // create the PIs
+ for ( i = 0; i < nInputs; i++ )
+ {
+ pObj = Abc_NtkCreatePi(pNtkNew);
+ Abc_ObjAssignName( pObj, pCur, NULL ); while ( *pCur++ );
+ Vec_PtrPush( vNodes, pObj );
+ }
+ // create the POs
+ for ( i = 0; i < nOutputs; i++ )
+ {
+ pObj = Abc_NtkCreatePo(pNtkNew);
+ Abc_ObjAssignName( pObj, pCur, NULL ); while ( *pCur++ );
+ }
+ // create the latches
+ for ( i = 0; i < nLatches; i++ )
+ {
+ pObj = Abc_NtkCreateLatch(pNtkNew);
+ Abc_ObjAssignName( pObj, pCur, NULL ); while ( *pCur++ );
+
+ pNode0 = Abc_NtkCreateBi(pNtkNew);
+ Abc_ObjAssignName( pNode0, pCur, NULL ); while ( *pCur++ );
+
+ pNode1 = Abc_NtkCreateBo(pNtkNew);
+ Abc_ObjAssignName( pNode1, pCur, NULL ); while ( *pCur++ );
+ Vec_PtrPush( vNodes, pNode1 );
+
+ Abc_ObjAddFanin( pObj, pNode0 );
+ Abc_ObjAddFanin( pNode1, pObj );
+ }
+
+ // get the pointer to the beginning of the node array
+ pBufferNode = (int *)(pContents + (nFileSize - (2 * nAnds + nOutputs + nLatches) * sizeof(int)) );
+ // make sure we are at the place where the nodes begin
+ if ( pBufferNode != (int *)pCur )
+ {
+ free( pContents );
+ Vec_PtrFree( vNodes );
+ Abc_NtkDelete( pNtkNew );
+ printf( "Warning: Internal reader error.\n" );
+ return NULL;
+ }
+
+ // create the AND gates
+ pProgress = Extra_ProgressBarStart( stdout, nAnds );
+ for ( i = 0; i < nAnds; i++ )
+ {
+ Extra_ProgressBarUpdate( pProgress, i, NULL );
+ pNode0 = Abc_ObjNotCond( Vec_PtrEntry(vNodes, pBufferNode[2*i+0] >> 1), pBufferNode[2*i+0] & 1 );
+ pNode1 = Abc_ObjNotCond( Vec_PtrEntry(vNodes, pBufferNode[2*i+1] >> 1), pBufferNode[2*i+1] & 1 );
+ Vec_PtrPush( vNodes, Abc_AigAnd(pNtkNew->pManFunc, pNode0, pNode1) );
+ }
+ Extra_ProgressBarStop( pProgress );
+
+ // read the POs
+ Abc_NtkForEachCo( pNtkNew, pObj, i )
+ {
+ Num = pBufferNode[2*nAnds+i];
+ if ( Abc_ObjFanoutNum(pObj) > 0 && Abc_ObjIsLatch(Abc_ObjFanout0(pObj)) )
+ {
+ Abc_ObjSetData( Abc_ObjFanout0(pObj), (void *)(Num & 3) );
+ Num >>= 2;
+ }
+ pNode0 = Abc_ObjNotCond( Vec_PtrEntry(vNodes, Num >> 1), Num & 1 );
+ Abc_ObjAddFanin( pObj, pNode0 );
+ }
+ free( pContents );
+ Vec_PtrFree( vNodes );
+
+ // remove the extra nodes
+// Abc_AigCleanup( pNtkNew->pManFunc );
+
+ // check the result
+ if ( fCheck && !Abc_NtkCheckRead( pNtkNew ) )
+ {
+ printf( "Io_ReadBaf: The network check has failed.\n" );
+ Abc_NtkDelete( pNtkNew );
+ return NULL;
+ }
+ return pNtkNew;
+
+}
+
+
+////////////////////////////////////////////////////////////////////////
+/// END OF FILE ///
+////////////////////////////////////////////////////////////////////////
+
+
diff --git a/src/base/io/ioReadBench.c b/src/base/io/ioReadBench.c
index 393b2216..007147bc 100644
--- a/src/base/io/ioReadBench.c
+++ b/src/base/io/ioReadBench.c
@@ -27,7 +27,7 @@
static Abc_Ntk_t * Io_ReadBenchNetwork( Extra_FileReader_t * p );
////////////////////////////////////////////////////////////////////////
-/// FUNCTION DEFITIONS ///
+/// FUNCTION DEFINITIONS ///
////////////////////////////////////////////////////////////////////////
/**Function*************************************************************
@@ -47,7 +47,7 @@ Abc_Ntk_t * Io_ReadBench( char * pFileName, int fCheck )
Abc_Ntk_t * pNtk;
// start the file
- p = Extra_FileReaderAlloc( pFileName, "#", "\n", " \t\r,()=" );
+ p = Extra_FileReaderAlloc( pFileName, "#", "\n\r", " \t,()=" );
if ( p == NULL )
return NULL;
@@ -66,6 +66,7 @@ Abc_Ntk_t * Io_ReadBench( char * pFileName, int fCheck )
}
return pNtk;
}
+
/**Function*************************************************************
Synopsis []
@@ -82,10 +83,11 @@ Abc_Ntk_t * Io_ReadBenchNetwork( Extra_FileReader_t * p )
ProgressBar * pProgress;
Vec_Ptr_t * vTokens;
Abc_Ntk_t * pNtk;
- Abc_Obj_t * pNet, * pNode;
+ Abc_Obj_t * pNode, * pNet;
Vec_Str_t * vString;
- char * pType, ** ppNames;
- int iLine, nNames;
+ unsigned uTruth[8];
+ char * pType, ** ppNames, * pString;
+ int iLine, nNames, nDigits, fLutsPresent = 0;
// allocate the empty network
pNtk = Abc_NtkStartRead( Extra_FileReaderGetFileName(p) );
@@ -100,6 +102,7 @@ Abc_Ntk_t * Io_ReadBenchNetwork( Extra_FileReader_t * p )
if ( vTokens->nSize == 1 )
{
printf( "%s: Wrong input file format.\n", Extra_FileReaderGetFileName(p) );
+ Vec_StrFree( vString );
Abc_NtkDelete( pNtk );
return NULL;
}
@@ -113,8 +116,90 @@ Abc_Ntk_t * Io_ReadBenchNetwork( Extra_FileReader_t * p )
{
// get the node name and the node type
pType = vTokens->pArray[1];
- if ( strcmp(pType, "DFF") == 0 )
- Io_ReadCreateLatch( pNtk, vTokens->pArray[2], vTokens->pArray[0] );
+ if ( strncmp(pType, "DFF", 3) == 0 ) // works for both DFF and DFFRSE
+ {
+ pNode = Io_ReadCreateLatch( pNtk, vTokens->pArray[2], vTokens->pArray[0] );
+// Abc_LatchSetInit0( pNode );
+ if ( pType[3] == '0' )
+ Abc_LatchSetInit0( pNode );
+ else if ( pType[3] == '1' )
+ Abc_LatchSetInit1( pNode );
+ else
+ Abc_LatchSetInitDc( pNode );
+ }
+ else if ( strcmp(pType, "LUT") == 0 )
+ {
+ fLutsPresent = 1;
+ ppNames = (char **)vTokens->pArray + 3;
+ nNames = vTokens->nSize - 3;
+ // check the number of inputs
+ if ( nNames > 8 )
+ {
+ printf( "%s: Currently cannot read truth tables with more than 8 inputs (%d).\n", Extra_FileReaderGetFileName(p), nNames );
+ Vec_StrFree( vString );
+ Abc_NtkDelete( pNtk );
+ return NULL;
+ }
+ // get the hex string
+ pString = vTokens->pArray[2];
+ if ( strncmp( pString, "0x", 2 ) )
+ {
+ printf( "%s: The LUT signature (%s) does not look like a hexadecimal beginning with \"0x\".\n", Extra_FileReaderGetFileName(p), pString );
+ Vec_StrFree( vString );
+ Abc_NtkDelete( pNtk );
+ return NULL;
+ }
+ pString += 2;
+ // pad the string with zero's if needed
+ nDigits = (1 << nNames) / 4;
+ if ( nDigits == 0 )
+ nDigits = 1;
+ if ( strlen(pString) < (unsigned)nDigits )
+ {
+ Vec_StrFill( vString, nDigits - strlen(pString), '0' );
+ Vec_StrPrintStr( vString, pString );
+ Vec_StrPush( vString, 0 );
+ pString = Vec_StrArray( vString );
+ }
+ // read the hex number from the string
+ if ( !Extra_ReadHexadecimal( uTruth, pString, nNames ) )
+ {
+ printf( "%s: Reading hexadecimal number (%s) has failed.\n", Extra_FileReaderGetFileName(p), pString );
+ Vec_StrFree( vString );
+ Abc_NtkDelete( pNtk );
+ return NULL;
+ }
+ // check if the node is a constant node
+ if ( Extra_TruthIsConst0(uTruth, nNames) )
+ {
+ pNode = Io_ReadCreateNode( pNtk, vTokens->pArray[0], ppNames, 0 );
+ Abc_ObjSetData( pNode, Abc_SopRegister( pNtk->pManFunc, " 0\n" ) );
+ }
+ else if ( Extra_TruthIsConst1(uTruth, nNames) )
+ {
+ pNode = Io_ReadCreateNode( pNtk, vTokens->pArray[0], ppNames, 0 );
+ Abc_ObjSetData( pNode, Abc_SopRegister( pNtk->pManFunc, " 1\n" ) );
+ }
+ else
+ {
+ // create the node
+ pNode = Io_ReadCreateNode( pNtk, vTokens->pArray[0], ppNames, nNames );
+ assert( nNames > 0 );
+ if ( nNames > 1 )
+ Abc_ObjSetData( pNode, Abc_SopCreateFromTruth(pNtk->pManFunc, nNames, uTruth) );
+ else if ( pString[0] == '2' )
+ Abc_ObjSetData( pNode, Abc_SopCreateBuf(pNtk->pManFunc) );
+ else if ( pString[0] == '1' )
+ Abc_ObjSetData( pNode, Abc_SopCreateInv(pNtk->pManFunc) );
+ else
+ {
+ printf( "%s: Reading truth table (%s) of single-input node has failed.\n", Extra_FileReaderGetFileName(p), pString );
+ Vec_StrFree( vString );
+ Abc_NtkDelete( pNtk );
+ return NULL;
+ }
+ }
+ }
else
{
// create a new node and add it to the network
@@ -123,7 +208,7 @@ Abc_Ntk_t * Io_ReadBenchNetwork( Extra_FileReader_t * p )
pNode = Io_ReadCreateNode( pNtk, vTokens->pArray[0], ppNames, nNames );
// assign the cover
if ( strcmp(pType, "AND") == 0 )
- Abc_ObjSetData( pNode, Abc_SopCreateAnd(pNtk->pManFunc, nNames) );
+ Abc_ObjSetData( pNode, Abc_SopCreateAnd(pNtk->pManFunc, nNames, NULL) );
else if ( strcmp(pType, "OR") == 0 )
Abc_ObjSetData( pNode, Abc_SopCreateOr(pNtk->pManFunc, nNames, NULL) );
else if ( strcmp(pType, "NAND") == 0 )
@@ -132,15 +217,22 @@ Abc_Ntk_t * Io_ReadBenchNetwork( Extra_FileReader_t * p )
Abc_ObjSetData( pNode, Abc_SopCreateNor(pNtk->pManFunc, nNames) );
else if ( strcmp(pType, "XOR") == 0 )
Abc_ObjSetData( pNode, Abc_SopCreateXor(pNtk->pManFunc, nNames) );
- else if ( strcmp(pType, "NXOR") == 0 )
+ else if ( strcmp(pType, "NXOR") == 0 || strcmp(pType, "XNOR") == 0 )
Abc_ObjSetData( pNode, Abc_SopCreateNxor(pNtk->pManFunc, nNames) );
else if ( strncmp(pType, "BUF", 3) == 0 )
Abc_ObjSetData( pNode, Abc_SopCreateBuf(pNtk->pManFunc) );
else if ( strcmp(pType, "NOT") == 0 )
Abc_ObjSetData( pNode, Abc_SopCreateInv(pNtk->pManFunc) );
- else
+ else if ( strncmp(pType, "MUX", 3) == 0 )
+ Abc_ObjSetData( pNode, Abc_SopRegister(pNtk->pManFunc, "1-0 1\n-11 1\n") );
+ else if ( strncmp(pType, "gnd", 3) == 0 )
+ Abc_ObjSetData( pNode, Abc_SopRegister( pNtk->pManFunc, " 0\n" ) );
+ else if ( strncmp(pType, "vdd", 3) == 0 )
+ Abc_ObjSetData( pNode, Abc_SopRegister( pNtk->pManFunc, " 1\n" ) );
+ else
{
- printf( "Cannot determine gate type \"%s\" in line %d.\n", pType, Extra_FileReaderGetLineNumber(p, 0) );
+ printf( "Io_ReadBenchNetwork(): Cannot determine gate type \"%s\" in line %d.\n", pType, Extra_FileReaderGetLineNumber(p, 0) );
+ Vec_StrFree( vString );
Abc_NtkDelete( pNtk );
return NULL;
}
@@ -150,17 +242,116 @@ Abc_Ntk_t * Io_ReadBenchNetwork( Extra_FileReader_t * p )
Extra_ProgressBarStop( pProgress );
Vec_StrFree( vString );
- // check if constant have been added
- if ( pNet = Abc_NtkFindNet( pNtk, "vdd" ) )
- Io_ReadCreateConst( pNtk, "vdd", 1 );
- if ( pNet = Abc_NtkFindNet( pNtk, "gnd" ) )
- Io_ReadCreateConst( pNtk, "gnd", 0 );
+ // check if constant 0 is present
+ if ( (pNet = Abc_NtkFindNet( pNtk, "gnd" )) )
+ {
+ if ( Abc_ObjFaninNum(pNet) == 0 )
+ Io_ReadCreateConst( pNtk, "gnd", 0 );
+ }
+ if ( (pNet = Abc_NtkFindNet( pNtk, "1" )) )
+ {
+ if ( Abc_ObjFaninNum(pNet) == 0 )
+ {
+ printf( "Io_ReadBenchNetwork(): Adding constant 0 fanin to non-driven net \"1\".\n" );
+ Io_ReadCreateConst( pNtk, "1", 0 );
+ }
+ }
+ // check if constant 1 is present
+ if ( (pNet = Abc_NtkFindNet( pNtk, "vdd" )) )
+ {
+ if ( Abc_ObjFaninNum(pNet) == 0 )
+ Io_ReadCreateConst( pNtk, "vdd", 1 );
+ }
+ if ( (pNet = Abc_NtkFindNet( pNtk, "2" )) )
+ {
+ if ( Abc_ObjFaninNum(pNet) == 0 )
+ {
+ printf( "Io_ReadBenchNetwork(): Adding constant 1 fanin to non-driven net \"2\".\n" );
+ Io_ReadCreateConst( pNtk, "2", 1 );
+ }
+ }
Abc_NtkFinalizeRead( pNtk );
+
+ // if LUTs are present, collapse the truth tables into cubes
+ if ( fLutsPresent )
+ {
+ if ( !Abc_NtkToBdd(pNtk) )
+ {
+ printf( "Io_ReadBenchNetwork(): Converting to BDD has failed.\n" );
+ Abc_NtkDelete( pNtk );
+ return NULL;
+ }
+ if ( !Abc_NtkToSop(pNtk, 0) )
+ {
+ printf( "Io_ReadBenchNetwork(): Converting to SOP has failed.\n" );
+ Abc_NtkDelete( pNtk );
+ return NULL;
+ }
+ }
return pNtk;
}
+/**Function*************************************************************
+
+ Synopsis [Reads initial state in BENCH format.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Io_ReadBenchInit( Abc_Ntk_t * pNtk, char * pFileName )
+{
+ char pBuffer[1000];
+ FILE * pFile;
+ char * pToken;
+ Abc_Obj_t * pObj;
+ int Num;
+ pFile = fopen( pFileName, "r" );
+ if ( pFile == NULL )
+ {
+ printf( "Io_ReadBenchInit(): Failed to open file \"%s\".\n", pFileName );
+ return;
+ }
+ while ( fgets( pBuffer, 999, pFile ) )
+ {
+ pToken = strtok( pBuffer, " \n\t\r" );
+ // find the latch output
+ Num = Nm_ManFindIdByName( pNtk->pManName, pToken, ABC_OBJ_BO );
+ if ( Num < 0 )
+ {
+ printf( "Io_ReadBenchInit(): Cannot find register with output %s.\n", pToken );
+ continue;
+ }
+ pObj = Abc_ObjFanin0( Abc_NtkObj( pNtk, Num ) );
+ if ( !Abc_ObjIsLatch(pObj) )
+ {
+ printf( "Io_ReadBenchInit(): The signal is not a register output %s.\n", pToken );
+ continue;
+ }
+ // assign the new init state
+ pToken = strtok( NULL, " \n\t\r" );
+ if ( pToken[0] == '0' )
+ Abc_LatchSetInit0( pObj );
+ else if ( pToken[0] == '1' )
+ Abc_LatchSetInit1( pObj );
+ else if ( pToken[0] == '2' )
+ Abc_LatchSetInitDc( pObj );
+ else
+ {
+ printf( "Io_ReadBenchInit(): The signal %s has unknown initial value (%s).\n",
+ Abc_ObjName(Abc_ObjFanout0(pObj)), pToken );
+ continue;
+ }
+ }
+ fclose( pFile );
+}
+
+
////////////////////////////////////////////////////////////////////////
/// END OF FILE ///
////////////////////////////////////////////////////////////////////////
diff --git a/src/base/io/ioReadBlif.c b/src/base/io/ioReadBlif.c
index 946de42b..d0750178 100644
--- a/src/base/io/ioReadBlif.c
+++ b/src/base/io/ioReadBlif.c
@@ -33,42 +33,47 @@ struct Io_ReadBlif_t_
char * pFileName; // the name of the file
Extra_FileReader_t * pReader; // the input file reader
// current processing info
- Abc_Ntk_t * pNtk; // the primary network
- Abc_Ntk_t * pNtkExdc; // the exdc network
- int fParsingExdc; // this flag is on, when we are parsing EXDC network
+ Abc_Ntk_t * pNtkMaster; // the primary network
+ Abc_Ntk_t * pNtkCur; // the primary network
int LineCur; // the line currently parsed
// temporary storage for tokens
+ Vec_Ptr_t * vTokens; // the current tokens
Vec_Ptr_t * vNewTokens; // the temporary storage for the tokens
Vec_Str_t * vCubes; // the temporary storage for the tokens
// the error message
FILE * Output; // the output stream
char sError[1000]; // the error string generated during parsing
+ int fError; // set to 1 when error occurs
};
static Io_ReadBlif_t * Io_ReadBlifFile( char * pFileName );
static void Io_ReadBlifFree( Io_ReadBlif_t * p );
static void Io_ReadBlifPrintErrorMessage( Io_ReadBlif_t * p );
static Vec_Ptr_t * Io_ReadBlifGetTokens( Io_ReadBlif_t * p );
-static Abc_Ntk_t * Io_ReadBlifNetwork( Io_ReadBlif_t * p );
static char * Io_ReadBlifCleanName( char * pName );
+static Abc_Ntk_t * Io_ReadBlifNetwork( Io_ReadBlif_t * p );
+static Abc_Ntk_t * Io_ReadBlifNetworkOne( Io_ReadBlif_t * p );
static int Io_ReadBlifNetworkInputs( Io_ReadBlif_t * p, Vec_Ptr_t * vTokens );
static int Io_ReadBlifNetworkOutputs( Io_ReadBlif_t * p, Vec_Ptr_t * vTokens );
+static int Io_ReadBlifNetworkAsserts( Io_ReadBlif_t * p, Vec_Ptr_t * vTokens );
static int Io_ReadBlifNetworkLatch( Io_ReadBlif_t * p, Vec_Ptr_t * vTokens );
static int Io_ReadBlifNetworkNames( Io_ReadBlif_t * p, Vec_Ptr_t ** pvTokens );
static int Io_ReadBlifNetworkGate( Io_ReadBlif_t * p, Vec_Ptr_t * vTokens );
+static int Io_ReadBlifNetworkSubcircuit( Io_ReadBlif_t * p, Vec_Ptr_t * vTokens );
static int Io_ReadBlifNetworkInputArrival( Io_ReadBlif_t * p, Vec_Ptr_t * vTokens );
static int Io_ReadBlifNetworkDefaultInputArrival( Io_ReadBlif_t * p, Vec_Ptr_t * vTokens );
+static int Io_ReadBlifNetworkConnectBoxes( Io_ReadBlif_t * p, Abc_Ntk_t * pNtkMaster );
////////////////////////////////////////////////////////////////////////
-/// FUNCTION DEFITIONS ///
+/// FUNCTION DEFINITIONS ///
////////////////////////////////////////////////////////////////////////
/**Function*************************************************************
- Synopsis [Reads the network from a BLIF file.]
+ Synopsis [Reads the (hierarchical) network from the BLIF file.]
- Description [Works only for flat (non-hierarchical) BLIF.]
+ Description []
SideEffects []
@@ -78,34 +83,22 @@ static int Io_ReadBlifNetworkDefaultInputArrival( Io_ReadBlif_t * p, Vec_Ptr_t *
Abc_Ntk_t * Io_ReadBlif( char * pFileName, int fCheck )
{
Io_ReadBlif_t * p;
- Abc_Ntk_t * pNtk, * pNtkExdc;
+ Abc_Ntk_t * pNtk;
// start the file
p = Io_ReadBlifFile( pFileName );
if ( p == NULL )
return NULL;
- // read the network
+ // read the hierarchical network
pNtk = Io_ReadBlifNetwork( p );
if ( pNtk == NULL )
{
Io_ReadBlifFree( p );
return NULL;
}
+ pNtk->pSpec = Extra_UtilStrsav( pFileName );
Abc_NtkTimeInitialize( pNtk );
-
- // read the EXDC network
- if ( p->fParsingExdc )
- {
- pNtkExdc = Io_ReadBlifNetwork( p );
- if ( pNtkExdc == NULL )
- {
- Abc_NtkDelete( pNtk );
- Io_ReadBlifFree( p );
- return NULL;
- }
- pNtk->pExdc = pNtkExdc;
- }
Io_ReadBlifFree( p );
// make sure that everything is okay with the network structure
@@ -120,7 +113,7 @@ Abc_Ntk_t * Io_ReadBlif( char * pFileName, int fCheck )
/**Function*************************************************************
- Synopsis [Starts the reading data structure.]
+ Synopsis [Iteratively reads several networks in the hierarchical design.]
Description []
@@ -129,140 +122,80 @@ Abc_Ntk_t * Io_ReadBlif( char * pFileName, int fCheck )
SeeAlso []
***********************************************************************/
-Io_ReadBlif_t * Io_ReadBlifFile( char * pFileName )
-{
- Extra_FileReader_t * pReader;
- Io_ReadBlif_t * p;
-
- // start the reader
- pReader = Extra_FileReaderAlloc( pFileName, "#", "\n", " \t\r" );
- if ( pReader == NULL )
- return NULL;
-
- // start the reading data structure
- p = ALLOC( Io_ReadBlif_t, 1 );
- memset( p, 0, sizeof(Io_ReadBlif_t) );
- p->pFileName = pFileName;
- p->pReader = pReader;
- p->Output = stdout;
- p->vNewTokens = Vec_PtrAlloc( 100 );
- p->vCubes = Vec_StrAlloc( 100 );
- return p;
-}
-
-/**Function*************************************************************
-
- Synopsis [Frees the data structure.]
-
- Description []
-
- SideEffects []
-
- SeeAlso []
-
-***********************************************************************/
-void Io_ReadBlifFree( Io_ReadBlif_t * p )
-{
- Extra_FileReaderFree( p->pReader );
- Vec_PtrFree( p->vNewTokens );
- Vec_StrFree( p->vCubes );
- free( p );
-}
-
-/**Function*************************************************************
-
- Synopsis [Prints the error message including the file name and line number.]
-
- Description []
-
- SideEffects []
-
- SeeAlso []
-
-***********************************************************************/
-void Io_ReadBlifPrintErrorMessage( Io_ReadBlif_t * p )
-{
- if ( p->LineCur == 0 ) // the line number is not given
- fprintf( p->Output, "%s: %s\n", p->pFileName, p->sError );
- else // print the error message with the line number
- fprintf( p->Output, "%s (line %d): %s\n", p->pFileName, p->LineCur, p->sError );
-}
-
-/**Function*************************************************************
-
- Synopsis [Gets the tokens taking into account the line breaks.]
-
- Description []
-
- SideEffects []
-
- SeeAlso []
-
-***********************************************************************/
-Vec_Ptr_t * Io_ReadBlifGetTokens( Io_ReadBlif_t * p )
+Abc_Ntk_t * Io_ReadBlifNetwork( Io_ReadBlif_t * p )
{
- Vec_Ptr_t * vTokens;
- char * pLastToken;
- int i;
+ Abc_Ntk_t * pNtk, * pNtkMaster;
- // get rid of the old tokens
- if ( p->vNewTokens->nSize > 0 )
+ // read the name of the master network
+ p->vTokens = Io_ReadBlifGetTokens(p);
+ if ( p->vTokens == NULL || strcmp( p->vTokens->pArray[0], ".model" ) )
{
- for ( i = 0; i < p->vNewTokens->nSize; i++ )
- free( p->vNewTokens->pArray[i] );
- p->vNewTokens->nSize = 0;
+ p->LineCur = 0;
+ sprintf( p->sError, "Wrong input file format." );
+ Io_ReadBlifPrintErrorMessage( p );
+ return NULL;
}
- // get the new tokens
- vTokens = Extra_FileReaderGetTokens(p->pReader);
- if ( vTokens == NULL )
- return vTokens;
-
- // check if there is a transfer to another line
- pLastToken = vTokens->pArray[vTokens->nSize - 1];
- if ( pLastToken[ strlen(pLastToken)-1 ] != '\\' )
- return vTokens;
-
- // remove the slash
- pLastToken[ strlen(pLastToken)-1 ] = 0;
- if ( pLastToken[0] == 0 )
- vTokens->nSize--;
- // load them into the new array
- for ( i = 0; i < vTokens->nSize; i++ )
- Vec_PtrPush( p->vNewTokens, util_strsav(vTokens->pArray[i]) );
-
- // load as long as there is the line break
- while ( 1 )
+ // read networks (with EXDC)
+ pNtkMaster = NULL;
+ while ( p->vTokens )
{
- // get the new tokens
- vTokens = Extra_FileReaderGetTokens(p->pReader);
- if ( vTokens->nSize == 0 )
- return p->vNewTokens;
- // check if there is a transfer to another line
- pLastToken = vTokens->pArray[vTokens->nSize - 1];
- if ( pLastToken[ strlen(pLastToken)-1 ] == '\\' )
+ // read the network and its EXDC if present
+ pNtk = Io_ReadBlifNetworkOne( p );
+ if ( pNtk == NULL )
+ break;
+ if ( p->vTokens && strcmp(p->vTokens->pArray[0], ".exdc") == 0 )
{
- // remove the slash
- pLastToken[ strlen(pLastToken)-1 ] = 0;
- if ( pLastToken[0] == 0 )
- vTokens->nSize--;
- // load them into the new array
- for ( i = 0; i < vTokens->nSize; i++ )
- Vec_PtrPush( p->vNewTokens, util_strsav(vTokens->pArray[i]) );
+ pNtk->pExdc = Io_ReadBlifNetworkOne( p );
+ Abc_NtkFinalizeRead( pNtk->pExdc );
+ if ( pNtk->pExdc == NULL )
+ break;
+ }
+ // add this network as part of the hierarchy
+ if ( pNtkMaster == NULL ) // no master network so far
+ {
+ p->pNtkMaster = pNtkMaster = pNtk;
continue;
}
- // otherwise, load them and break
- for ( i = 0; i < vTokens->nSize; i++ )
- Vec_PtrPush( p->vNewTokens, util_strsav(vTokens->pArray[i]) );
- break;
+/*
+ // make sure hierarchy does not have the network with this name
+ if ( pNtkMaster->tName2Model && stmm_is_member( pNtkMaster->tName2Model, pNtk->pName ) )
+ {
+ p->LineCur = 0;
+ sprintf( p->sError, "Model %s is multiply defined in the file.", pNtk->pName );
+ Io_ReadBlifPrintErrorMessage( p );
+ Abc_NtkDelete( pNtk );
+ Abc_NtkDelete( pNtkMaster );
+ pNtkMaster = NULL;
+ return NULL;
+ }
+ // add the network to the hierarchy
+ if ( pNtkMaster->tName2Model == NULL )
+ pNtkMaster->tName2Model = stmm_init_table(strcmp, stmm_strhash);
+ stmm_insert( pNtkMaster->tName2Model, pNtk->pName, (char *)pNtk );
+*/
}
- return p->vNewTokens;
+/*
+ // if there is a hierarchy, connect the boxes
+ if ( pNtkMaster && pNtkMaster->tName2Model )
+ {
+ if ( Io_ReadBlifNetworkConnectBoxes( p, pNtkMaster ) )
+ {
+ Abc_NtkDelete( pNtkMaster );
+ return NULL;
+ }
+ }
+ else
+*/
+ if ( !p->fError )
+ Abc_NtkFinalizeRead( pNtkMaster );
+ // return the master network
+ return pNtkMaster;
}
-
/**Function*************************************************************
- Synopsis [Reads the BLIF file.]
+ Synopsis [Reads one (main or exdc) network from the BLIF file.]
Description []
@@ -271,74 +204,89 @@ Vec_Ptr_t * Io_ReadBlifGetTokens( Io_ReadBlif_t * p )
SeeAlso []
***********************************************************************/
-Abc_Ntk_t * Io_ReadBlifNetwork( Io_ReadBlif_t * p )
+Abc_Ntk_t * Io_ReadBlifNetworkOne( Io_ReadBlif_t * p )
{
ProgressBar * pProgress;
- Vec_Ptr_t * vTokens;
- char * pModelName, * pDirective;
+ Abc_Ntk_t * pNtk;
+ char * pDirective;
int iLine, fTokensReady, fStatus;
+ // make sure the tokens are present
+ assert( p->vTokens != NULL );
+
+ // create the new network
+ p->pNtkCur = pNtk = Abc_NtkAlloc( ABC_NTK_NETLIST, ABC_FUNC_SOP, 1 );
// read the model name
- if ( !p->fParsingExdc )
+ if ( strcmp( p->vTokens->pArray[0], ".model" ) == 0 )
+ pNtk->pName = Extra_UtilStrsav( p->vTokens->pArray[1] );
+ else if ( strcmp( p->vTokens->pArray[0], ".exdc" ) != 0 )
{
- // read the model name
- vTokens = Io_ReadBlifGetTokens(p);
- if ( vTokens == NULL || strcmp( vTokens->pArray[0], ".model" ) )
- {
- p->LineCur = 0;
- sprintf( p->sError, "Wrong input file format." );
- Io_ReadBlifPrintErrorMessage( p );
- return NULL;
- }
- pModelName = vTokens->pArray[1];
- // allocate the empty network
- p->pNtk = Abc_NtkAlloc( ABC_TYPE_NETLIST, ABC_FUNC_SOP );
- p->pNtk->pName = util_strsav( pModelName );
- p->pNtk->pSpec = util_strsav( p->pFileName );
+ printf( "%s: File parsing skipped after line %d (\"%s\").\n", p->pFileName,
+ Extra_FileReaderGetLineNumber(p->pReader, 0), p->vTokens->pArray[0] );
+ Abc_NtkDelete(pNtk);
+ p->pNtkCur = NULL;
+ return NULL;
}
- else
- p->pNtk = Abc_NtkAlloc( ABC_TYPE_NETLIST, ABC_FUNC_SOP );
// read the inputs/outputs
+ if ( p->pNtkMaster == NULL )
pProgress = Extra_ProgressBarStart( stdout, Extra_FileReaderGetFileSize(p->pReader) );
fTokensReady = fStatus = 0;
- for ( iLine = 0; fTokensReady || (vTokens = Io_ReadBlifGetTokens(p)); iLine++ )
+ for ( iLine = 0; fTokensReady || (p->vTokens = Io_ReadBlifGetTokens(p)); iLine++ )
{
- if ( iLine % 1000 == 0 )
+ if ( p->pNtkMaster == NULL && iLine % 1000 == 0 )
Extra_ProgressBarUpdate( pProgress, Extra_FileReaderGetCurPosition(p->pReader), NULL );
// consider different line types
fTokensReady = 0;
- pDirective = vTokens->pArray[0];
+ pDirective = p->vTokens->pArray[0];
if ( !strcmp( pDirective, ".names" ) )
- { fStatus = Io_ReadBlifNetworkNames( p, &vTokens ); fTokensReady = 1; }
+ { fStatus = Io_ReadBlifNetworkNames( p, &p->vTokens ); fTokensReady = 1; }
else if ( !strcmp( pDirective, ".gate" ) )
- fStatus = Io_ReadBlifNetworkGate( p, vTokens );
+ fStatus = Io_ReadBlifNetworkGate( p, p->vTokens );
else if ( !strcmp( pDirective, ".latch" ) )
- fStatus = Io_ReadBlifNetworkLatch( p, vTokens );
+ fStatus = Io_ReadBlifNetworkLatch( p, p->vTokens );
else if ( !strcmp( pDirective, ".inputs" ) )
- fStatus = Io_ReadBlifNetworkInputs( p, vTokens );
+ fStatus = Io_ReadBlifNetworkInputs( p, p->vTokens );
else if ( !strcmp( pDirective, ".outputs" ) )
- fStatus = Io_ReadBlifNetworkOutputs( p, vTokens );
+ fStatus = Io_ReadBlifNetworkOutputs( p, p->vTokens );
+ else if ( !strcmp( pDirective, ".asserts" ) )
+ fStatus = Io_ReadBlifNetworkAsserts( p, p->vTokens );
else if ( !strcmp( pDirective, ".input_arrival" ) )
- fStatus = Io_ReadBlifNetworkInputArrival( p, vTokens );
+ fStatus = Io_ReadBlifNetworkInputArrival( p, p->vTokens );
else if ( !strcmp( pDirective, ".default_input_arrival" ) )
- fStatus = Io_ReadBlifNetworkDefaultInputArrival( p, vTokens );
+ fStatus = Io_ReadBlifNetworkDefaultInputArrival( p, p->vTokens );
+// else if ( !strcmp( pDirective, ".subckt" ) )
+// fStatus = Io_ReadBlifNetworkSubcircuit( p, p->vTokens );
else if ( !strcmp( pDirective, ".exdc" ) )
- { p->fParsingExdc = 1; break; }
+ break;
else if ( !strcmp( pDirective, ".end" ) )
+ {
+ p->vTokens = Io_ReadBlifGetTokens(p);
break;
+ }
+ else if ( !strcmp( pDirective, ".blackbox" ) )
+ {
+ pNtk->ntkType = ABC_NTK_NETLIST;
+ pNtk->ntkFunc = ABC_FUNC_BLACKBOX;
+ Extra_MmFlexStop( pNtk->pManFunc );
+ pNtk->pManFunc = NULL;
+ }
else
printf( "%s (line %d): Skipping directive \"%s\".\n", p->pFileName,
Extra_FileReaderGetLineNumber(p->pReader, 0), pDirective );
- if ( vTokens == NULL ) // some files do not have ".end" in the end
+ if ( p->vTokens == NULL ) // some files do not have ".end" in the end
break;
if ( fStatus == 1 )
+ {
+ Extra_ProgressBarStop( pProgress );
+ Abc_NtkDelete( pNtk );
return NULL;
+ }
}
+ if ( p->pNtkMaster == NULL )
Extra_ProgressBarStop( pProgress );
- Abc_NtkFinalizeRead( p->pNtk );
- return p->pNtk;
+ return pNtk;
}
/**Function*************************************************************
@@ -356,7 +304,7 @@ int Io_ReadBlifNetworkInputs( Io_ReadBlif_t * p, Vec_Ptr_t * vTokens )
{
int i;
for ( i = 1; i < vTokens->nSize; i++ )
- Io_ReadCreatePi( p->pNtk, vTokens->pArray[i] );
+ Io_ReadCreatePi( p->pNtkCur, vTokens->pArray[i] );
return 0;
}
@@ -375,7 +323,7 @@ int Io_ReadBlifNetworkOutputs( Io_ReadBlif_t * p, Vec_Ptr_t * vTokens )
{
int i;
for ( i = 1; i < vTokens->nSize; i++ )
- Io_ReadCreatePo( p->pNtk, vTokens->pArray[i] );
+ Io_ReadCreatePo( p->pNtkCur, vTokens->pArray[i] );
return 0;
}
@@ -390,12 +338,30 @@ int Io_ReadBlifNetworkOutputs( Io_ReadBlif_t * p, Vec_Ptr_t * vTokens )
SeeAlso []
***********************************************************************/
-int Io_ReadBlifNetworkLatch( Io_ReadBlif_t * p, Vec_Ptr_t * vTokens )
+int Io_ReadBlifNetworkAsserts( Io_ReadBlif_t * p, Vec_Ptr_t * vTokens )
{
- Abc_Ntk_t * pNtk = p->pNtk;
+ int i;
+ for ( i = 1; i < vTokens->nSize; i++ )
+ Io_ReadCreateAssert( p->pNtkCur, vTokens->pArray[i] );
+ return 0;
+}
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Io_ReadBlifNetworkLatch( Io_ReadBlif_t * p, Vec_Ptr_t * vTokens )
+{
+ Abc_Ntk_t * pNtk = p->pNtkCur;
Abc_Obj_t * pLatch;
int ResetValue;
-
if ( vTokens->nSize < 3 )
{
p->LineCur = Extra_FileReaderGetLineNumber(p->pReader, 0);
@@ -407,10 +373,10 @@ int Io_ReadBlifNetworkLatch( Io_ReadBlif_t * p, Vec_Ptr_t * vTokens )
pLatch = Io_ReadCreateLatch( pNtk, vTokens->pArray[1], vTokens->pArray[2] );
// get the latch reset value
if ( vTokens->nSize == 3 )
- ResetValue = 2;
+ Abc_LatchSetInitDc( pLatch );
else
{
- ResetValue = atoi(vTokens->pArray[3]);
+ ResetValue = atoi(vTokens->pArray[vTokens->nSize-1]);
if ( ResetValue != 0 && ResetValue != 1 && ResetValue != 2 )
{
p->LineCur = Extra_FileReaderGetLineNumber(p->pReader, 0);
@@ -418,8 +384,13 @@ int Io_ReadBlifNetworkLatch( Io_ReadBlif_t * p, Vec_Ptr_t * vTokens )
Io_ReadBlifPrintErrorMessage( p );
return 1;
}
+ if ( ResetValue == 0 )
+ Abc_LatchSetInit0( pLatch );
+ else if ( ResetValue == 1 )
+ Abc_LatchSetInit1( pLatch );
+ else if ( ResetValue == 2 )
+ Abc_LatchSetInitDc( pLatch );
}
- Abc_ObjSetData( pLatch, (void *)ResetValue );
return 0;
}
@@ -437,7 +408,7 @@ int Io_ReadBlifNetworkLatch( Io_ReadBlif_t * p, Vec_Ptr_t * vTokens )
int Io_ReadBlifNetworkNames( Io_ReadBlif_t * p, Vec_Ptr_t ** pvTokens )
{
Vec_Ptr_t * vTokens = *pvTokens;
- Abc_Ntk_t * pNtk = p->pNtk;
+ Abc_Ntk_t * pNtk = p->pNtkCur;
Abc_Obj_t * pNode;
char * pToken, Char, ** ppNames;
int nFanins, nNames;
@@ -500,7 +471,7 @@ int Io_ReadBlifNetworkNames( Io_ReadBlif_t * p, Vec_Ptr_t ** pvTokens )
Vec_StrAppend( p->vCubes, vTokens->pArray[0] );
// check the char
Char = ((char *)vTokens->pArray[1])[0];
- if ( Char != '0' && Char != '1' )
+ if ( Char != '0' && Char != '1' && Char != 'x' && Char != 'n' )
{
p->LineCur = Extra_FileReaderGetLineNumber(p->pReader, 0);
sprintf( p->sError, "The output character in the constant cube is wrong." );
@@ -525,6 +496,16 @@ int Io_ReadBlifNetworkNames( Io_ReadBlif_t * p, Vec_Ptr_t ** pvTokens )
// set the pointer to the functionality of the node
Abc_ObjSetData( pNode, Abc_SopRegister(pNtk->pManFunc, p->vCubes->pArray) );
+ // check the size
+ if ( Abc_ObjFaninNum(pNode) != Abc_SopGetVarNum(Abc_ObjData(pNode)) )
+ {
+ p->LineCur = Extra_FileReaderGetLineNumber(p->pReader, 0);
+ sprintf( p->sError, "The number of fanins (%d) of node %s is different from SOP size (%d).",
+ Abc_ObjFaninNum(pNode), Abc_ObjName(Abc_ObjFanout(pNode,0)), Abc_SopGetVarNum(Abc_ObjData(pNode)) );
+ Io_ReadBlifPrintErrorMessage( p );
+ return 1;
+ }
+
// return the last array of tokens
*pvTokens = vTokens;
return 0;
@@ -550,7 +531,7 @@ int Io_ReadBlifNetworkGate( Io_ReadBlif_t * p, Vec_Ptr_t * vTokens )
int i, nNames;
// check that the library is available
- pGenlib = Abc_FrameReadLibGen(Abc_FrameGetGlobalFrame());
+ pGenlib = Abc_FrameReadLibGen();
if ( pGenlib == NULL )
{
p->LineCur = Extra_FileReaderGetLineNumber(p->pReader, 0);
@@ -579,12 +560,12 @@ int Io_ReadBlifNetworkGate( Io_ReadBlif_t * p, Vec_Ptr_t * vTokens )
}
// if this is the first line with gate, update the network type
- if ( Abc_NtkNodeNum(p->pNtk) == 0 )
+ if ( Abc_NtkNodeNum(p->pNtkCur) == 0 )
{
- assert( p->pNtk->ntkFunc == ABC_FUNC_SOP );
- p->pNtk->ntkFunc = ABC_FUNC_MAP;
- Extra_MmFlexStop( p->pNtk->pManFunc, 0 );
- p->pNtk->pManFunc = pGenlib;
+ assert( p->pNtkCur->ntkFunc == ABC_FUNC_SOP );
+ p->pNtkCur->ntkFunc = ABC_FUNC_MAP;
+ Extra_MmFlexStop( p->pNtkCur->pManFunc );
+ p->pNtkCur->pManFunc = pGenlib;
}
// remove the formal parameter names
@@ -603,13 +584,54 @@ int Io_ReadBlifNetworkGate( Io_ReadBlif_t * p, Vec_Ptr_t * vTokens )
// create the node
ppNames = (char **)vTokens->pArray + 2;
nNames = vTokens->nSize - 3;
- pNode = Io_ReadCreateNode( p->pNtk, ppNames[nNames], ppNames, nNames );
+ pNode = Io_ReadCreateNode( p->pNtkCur, ppNames[nNames], ppNames, nNames );
// set the pointer to the functionality of the node
Abc_ObjSetData( pNode, pGate );
return 0;
}
+/**Function*************************************************************
+
+ Synopsis [Creates a multi-input multi-output box in the hierarchical design.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Io_ReadBlifNetworkSubcircuit( Io_ReadBlif_t * p, Vec_Ptr_t * vTokens )
+{
+ Abc_Obj_t * pBox;
+ Vec_Ptr_t * vNames;
+ char * pName;
+ int i;
+
+ // create a new node and add it to the network
+ if ( vTokens->nSize < 3 )
+ {
+ p->LineCur = Extra_FileReaderGetLineNumber(p->pReader, 0);
+ sprintf( p->sError, "The .subcircuit line has less than three tokens." );
+ Io_ReadBlifPrintErrorMessage( p );
+ return 1;
+ }
+
+ // store the names of formal/actual inputs/outputs of the box
+ vNames = Vec_PtrAlloc( 10 );
+ Vec_PtrForEachEntryStart( vTokens, pName, i, 1 )
+// Vec_PtrPush( vNames, Abc_NtkRegisterName(p->pNtkCur, pName) );
+ Vec_PtrPush( vNames, Extra_UtilStrsav(pName) ); // memory leak!!!
+
+ // create a new box and add it to the network
+ pBox = Abc_NtkCreateBlackbox( p->pNtkCur );
+ // set the pointer to the node names
+ Abc_ObjSetData( pBox, vNames );
+ // remember the line of the file
+ pBox->pCopy = (void *)Extra_FileReaderGetLineNumber(p->pReader, 0);
+ return 0;
+}
/**Function*************************************************************
@@ -658,7 +680,7 @@ int Io_ReadBlifNetworkInputArrival( Io_ReadBlif_t * p, Vec_Ptr_t * vTokens )
Io_ReadBlifPrintErrorMessage( p );
return 1;
}
- pNet = Abc_NtkFindNet( p->pNtk, vTokens->pArray[1] );
+ pNet = Abc_NtkFindNet( p->pNtkCur, vTokens->pArray[1] );
if ( pNet == NULL )
{
p->LineCur = Extra_FileReaderGetLineNumber(p->pReader, 0);
@@ -676,7 +698,7 @@ int Io_ReadBlifNetworkInputArrival( Io_ReadBlif_t * p, Vec_Ptr_t * vTokens )
return 1;
}
// set the arrival time
- Abc_NtkTimeSetArrival( p->pNtk, pNet->Id, (float)TimeRise, (float)TimeFall );
+ Abc_NtkTimeSetArrival( p->pNtkCur, Abc_ObjFanin0(pNet)->Id, (float)TimeRise, (float)TimeFall );
return 0;
}
@@ -715,10 +737,366 @@ int Io_ReadBlifNetworkDefaultInputArrival( Io_ReadBlif_t * p, Vec_Ptr_t * vToken
return 1;
}
// set the arrival time
- Abc_NtkTimeSetDefaultArrival( p->pNtk, (float)TimeRise, (float)TimeFall );
+ Abc_NtkTimeSetDefaultArrival( p->pNtkCur, (float)TimeRise, (float)TimeFall );
+ return 0;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Prints the error message including the file name and line number.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Io_ReadBlifPrintErrorMessage( Io_ReadBlif_t * p )
+{
+ p->fError = 1;
+ if ( p->LineCur == 0 ) // the line number is not given
+ fprintf( p->Output, "%s: %s\n", p->pFileName, p->sError );
+ else // print the error message with the line number
+ fprintf( p->Output, "%s (line %d): %s\n", p->pFileName, p->LineCur, p->sError );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Gets the tokens taking into account the line breaks.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Vec_Ptr_t * Io_ReadBlifGetTokens( Io_ReadBlif_t * p )
+{
+ Vec_Ptr_t * vTokens;
+ char * pLastToken;
+ int i;
+
+ // get rid of the old tokens
+ if ( p->vNewTokens->nSize > 0 )
+ {
+ for ( i = 0; i < p->vNewTokens->nSize; i++ )
+ free( p->vNewTokens->pArray[i] );
+ p->vNewTokens->nSize = 0;
+ }
+
+ // get the new tokens
+ vTokens = Extra_FileReaderGetTokens(p->pReader);
+ if ( vTokens == NULL )
+ return vTokens;
+
+ // check if there is a transfer to another line
+ pLastToken = vTokens->pArray[vTokens->nSize - 1];
+ if ( pLastToken[ strlen(pLastToken)-1 ] != '\\' )
+ return vTokens;
+
+ // remove the slash
+ pLastToken[ strlen(pLastToken)-1 ] = 0;
+ if ( pLastToken[0] == 0 )
+ vTokens->nSize--;
+ // load them into the new array
+ for ( i = 0; i < vTokens->nSize; i++ )
+ Vec_PtrPush( p->vNewTokens, Extra_UtilStrsav(vTokens->pArray[i]) );
+
+ // load as long as there is the line break
+ while ( 1 )
+ {
+ // get the new tokens
+ vTokens = Extra_FileReaderGetTokens(p->pReader);
+ if ( vTokens->nSize == 0 )
+ return p->vNewTokens;
+ // check if there is a transfer to another line
+ pLastToken = vTokens->pArray[vTokens->nSize - 1];
+ if ( pLastToken[ strlen(pLastToken)-1 ] == '\\' )
+ {
+ // remove the slash
+ pLastToken[ strlen(pLastToken)-1 ] = 0;
+ if ( pLastToken[0] == 0 )
+ vTokens->nSize--;
+ // load them into the new array
+ for ( i = 0; i < vTokens->nSize; i++ )
+ Vec_PtrPush( p->vNewTokens, Extra_UtilStrsav(vTokens->pArray[i]) );
+ continue;
+ }
+ // otherwise, load them and break
+ for ( i = 0; i < vTokens->nSize; i++ )
+ Vec_PtrPush( p->vNewTokens, Extra_UtilStrsav(vTokens->pArray[i]) );
+ break;
+ }
+ return p->vNewTokens;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Starts the reading data structure.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Io_ReadBlif_t * Io_ReadBlifFile( char * pFileName )
+{
+ Extra_FileReader_t * pReader;
+ Io_ReadBlif_t * p;
+
+ // start the reader
+ pReader = Extra_FileReaderAlloc( pFileName, "#", "\n\r", " \t" );
+
+ if ( pReader == NULL )
+ return NULL;
+
+ // start the reading data structure
+ p = ALLOC( Io_ReadBlif_t, 1 );
+ memset( p, 0, sizeof(Io_ReadBlif_t) );
+ p->pFileName = pFileName;
+ p->pReader = pReader;
+ p->Output = stdout;
+ p->vNewTokens = Vec_PtrAlloc( 100 );
+ p->vCubes = Vec_StrAlloc( 100 );
+ return p;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Frees the data structure.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Io_ReadBlifFree( Io_ReadBlif_t * p )
+{
+ Extra_FileReaderFree( p->pReader );
+ Vec_PtrFree( p->vNewTokens );
+ Vec_StrFree( p->vCubes );
+ free( p );
+}
+
+
+/**Function*************************************************************
+
+ Synopsis [Connect one box.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Io_ReadBlifNetworkConnectBoxesOneBox( Io_ReadBlif_t * p, Abc_Obj_t * pBox, stmm_table * tName2Model )
+{
+ Vec_Ptr_t * pNames;
+ Abc_Ntk_t * pNtkModel;
+ Abc_Obj_t * pObj, * pNet;
+ char * pName, * pActual;
+ int i, Length, Start;
+
+ // get the model for this box
+ pNames = pBox->pData;
+ if ( !stmm_lookup( tName2Model, Vec_PtrEntry(pNames, 0), (char **)&pNtkModel ) )
+ {
+ p->LineCur = (int)pBox->pCopy;
+ sprintf( p->sError, "Cannot find the model for subcircuit %s.", Vec_PtrEntry(pNames, 0) );
+ Io_ReadBlifPrintErrorMessage( p );
+ return 1;
+ }
+
+ // create the fanins of the box
+ Abc_NtkForEachPi( pNtkModel, pObj, i )
+ pObj->pCopy = NULL;
+ if ( Abc_NtkPiNum(pNtkModel) == 0 )
+ Start = 1;
+ else
+ {
+ Vec_PtrForEachEntryStart( pNames, pName, i, 1 )
+ {
+ pActual = Io_ReadBlifCleanName(pName);
+ if ( pActual == NULL )
+ {
+ p->LineCur = (int)pBox->pCopy;
+ sprintf( p->sError, "Cannot parse formal/actual name pair \"%s\".", pName );
+ Io_ReadBlifPrintErrorMessage( p );
+ return 1;
+ }
+ Length = pActual - pName - 1;
+ pName[Length] = 0;
+ // find the PI net with this name
+ pObj = Abc_NtkFindNet( pNtkModel, pName );
+ if ( pObj == NULL )
+ {
+ p->LineCur = (int)pBox->pCopy;
+ sprintf( p->sError, "Cannot find formal input \"%s\" as an PI of model \"%s\".", pName, Vec_PtrEntry(pNames, 0) );
+ Io_ReadBlifPrintErrorMessage( p );
+ return 1;
+ }
+ // get the PI
+ pObj = Abc_ObjFanin0(pObj);
+ // quit if this is not a PI net
+ if ( !Abc_ObjIsPi(pObj) )
+ {
+ pName[Length] = '=';
+ Start = i;
+ break;
+ }
+ // remember the actual name in the net
+ if ( pObj->pCopy != NULL )
+ {
+ p->LineCur = (int)pBox->pCopy;
+ sprintf( p->sError, "Formal input \"%s\" is used more than once.", pName );
+ Io_ReadBlifPrintErrorMessage( p );
+ return 1;
+ }
+ pObj->pCopy = (void *)pActual;
+ // quit if we processed all PIs
+ if ( i == Abc_NtkPiNum(pNtkModel) )
+ {
+ Start = i+1;
+ break;
+ }
+ }
+ }
+ // create the fanins of the box
+ Abc_NtkForEachPi( pNtkModel, pObj, i )
+ {
+ pActual = (void *)pObj->pCopy;
+ if ( pActual == NULL )
+ {
+ p->LineCur = (int)pBox->pCopy;
+ sprintf( p->sError, "Formal input \"%s\" of model %s is not driven.", pName, Vec_PtrEntry(pNames, 0) );
+ Io_ReadBlifPrintErrorMessage( p );
+ return 1;
+ }
+ pNet = Abc_NtkFindOrCreateNet( pBox->pNtk, pActual );
+ Abc_ObjAddFanin( pBox, pNet );
+ }
+ Abc_NtkForEachPi( pNtkModel, pObj, i )
+ pObj->pCopy = NULL;
+
+ // create the fanouts of the box
+ Abc_NtkForEachPo( pNtkModel, pObj, i )
+ pObj->pCopy = NULL;
+ Vec_PtrForEachEntryStart( pNames, pName, i, Start )
+ {
+ pActual = Io_ReadBlifCleanName(pName);
+ if ( pActual == NULL )
+ {
+ p->LineCur = (int)pBox->pCopy;
+ sprintf( p->sError, "Cannot parse formal/actual name pair \"%s\".", pName );
+ Io_ReadBlifPrintErrorMessage( p );
+ return 1;
+ }
+ Length = pActual - pName - 1;
+ pName[Length] = 0;
+ // find the PO net with this name
+ pObj = Abc_NtkFindNet( pNtkModel, pName );
+ if ( pObj == NULL )
+ {
+ p->LineCur = (int)pBox->pCopy;
+ sprintf( p->sError, "Cannot find formal output \"%s\" as an PO of model \"%s\".", pName, Vec_PtrEntry(pNames, 0) );
+ Io_ReadBlifPrintErrorMessage( p );
+ return 1;
+ }
+ // get the PO
+ pObj = Abc_ObjFanout0(pObj);
+ if ( pObj->pCopy != NULL )
+ {
+ p->LineCur = (int)pBox->pCopy;
+ sprintf( p->sError, "Formal output \"%s\" is used more than once.", pName );
+ Io_ReadBlifPrintErrorMessage( p );
+ return 1;
+ }
+ pObj->pCopy = (void *)pActual;
+ }
+ // create the fanouts of the box
+ Abc_NtkForEachPo( pNtkModel, pObj, i )
+ {
+ pActual = (void *)pObj->pCopy;
+ if ( pActual == NULL )
+ {
+ p->LineCur = (int)pBox->pCopy;
+ sprintf( p->sError, "Formal output \"%s\" of model %s is not driven.", pName, Vec_PtrEntry(pNames, 0) );
+ Io_ReadBlifPrintErrorMessage( p );
+ return 1;
+ }
+ pNet = Abc_NtkFindOrCreateNet( pBox->pNtk, pActual );
+ Abc_ObjAddFanin( pNet, pBox );
+ }
+ Abc_NtkForEachPo( pNtkModel, pObj, i )
+ pObj->pCopy = NULL;
+
+ // remove the array of names, assign the pointer to the model
+ Vec_PtrForEachEntry( pBox->pData, pName, i )
+ free( pName );
+ Vec_PtrFree( pBox->pData );
+ pBox->pData = pNtkModel;
+ return 0;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Connect the boxes in the hierarchy of networks.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Io_ReadBlifNetworkConnectBoxesOne( Io_ReadBlif_t * p, Abc_Ntk_t * pNtk, stmm_table * tName2Model )
+{
+ Abc_Obj_t * pBox;
+ int i;
+ // go through the boxes
+ Abc_NtkForEachBlackbox( pNtk, pBox, i )
+ if ( Io_ReadBlifNetworkConnectBoxesOneBox( p, pBox, tName2Model ) )
+ return 1;
+ Abc_NtkFinalizeRead( pNtk );
+ return 0;
+}
+
+#if 0
+
+/**Function*************************************************************
+
+ Synopsis [Connect the boxes in the hierarchy of networks.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Io_ReadBlifNetworkConnectBoxes( Io_ReadBlif_t * p, Abc_Ntk_t * pNtkMaster )
+{
+ stmm_generator * gen;
+ Abc_Ntk_t * pNtk;
+ char * pName;
+ // connect the master network
+ if ( Io_ReadBlifNetworkConnectBoxesOne( p, pNtkMaster, pNtkMaster->tName2Model ) )
+ return 1;
+ // connect other networks
+ stmm_foreach_item( pNtkMaster->tName2Model, gen, &pName, (char **)&pNtk )
+ if ( Io_ReadBlifNetworkConnectBoxesOne( p, pNtk, pNtkMaster->tName2Model ) )
+ return 1;
return 0;
}
+#endif
////////////////////////////////////////////////////////////////////////
/// END OF FILE ///
diff --git a/src/base/io/ioReadBlifAig.c b/src/base/io/ioReadBlifAig.c
new file mode 100644
index 00000000..c448bab6
--- /dev/null
+++ b/src/base/io/ioReadBlifAig.c
@@ -0,0 +1,1013 @@
+/**CFile****************************************************************
+
+ FileName [ioReadBlifAig.c]
+
+ SystemName [ABC: Logic synthesis and verification system.]
+
+ PackageName [Command processing package.]
+
+ Synopsis [Procedures to read BLIF file into AIG.]
+
+ Author [Alan Mishchenko]
+
+ Affiliation [UC Berkeley]
+
+ Date [Ver. 1.0. Started - December 23, 2006.]
+
+ Revision [$Id: ioReadBlifAig.c,v 1.00 2006/12/23 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "abc.h"
+#include "extra.h"
+#include "vecPtr.h"
+
+////////////////////////////////////////////////////////////////////////
+/// DECLARATIONS ///
+////////////////////////////////////////////////////////////////////////
+
+// latch initial values
+typedef enum {
+ IO_BLIF_INIT_NONE = 0, // 0: unknown
+ IO_BLIF_INIT_ZERO, // 1: zero
+ IO_BLIF_INIT_ONE, // 2: one
+ IO_BLIF_INIT_DC // 3: don't-care
+} Io_BlifInit_t;
+
+typedef struct Io_BlifObj_t_ Io_BlifObj_t; // parsing object
+struct Io_BlifObj_t_
+{
+ unsigned fPi : 1; // the object is a primary input
+ unsigned fPo : 1; // the object is a primary output
+ unsigned fLi : 1; // the object is a latch input
+ unsigned fLo : 1; // the object is a latch output
+ unsigned fDef : 1; // the object is defined as a table (node, PO, LI)
+ unsigned fLoop : 1; // flag for loop detection
+ unsigned Init : 2; // the latch initial state
+ unsigned Offset : 24; // temporary number
+ char * pName; // the name of this object
+ void * pEquiv; // the AIG node representing this line
+ Io_BlifObj_t * pNext; // the next obj in the hash table
+};
+
+typedef struct Io_BlifMan_t_ Io_BlifMan_t; // parsing manager
+struct Io_BlifMan_t_
+{
+ // general info about file
+ char * pFileName; // the name of the file
+ char * pBuffer; // the begining of the file buffer
+ Vec_Ptr_t * vLines; // the line beginnings
+ // temporary objects
+ Io_BlifObj_t * pObjects; // the storage for objects
+ int nObjects; // the number of objects allocated
+ int iObjNext; // the next free object
+ // file lines
+ char * pModel; // .model line
+ Vec_Ptr_t * vInputs; // .inputs lines
+ Vec_Ptr_t * vOutputs; // .outputs lines
+ Vec_Ptr_t * vLatches; // .latches lines
+ Vec_Ptr_t * vNames; // .names lines
+ // network objects
+ Vec_Ptr_t * vPis; // the PI structures
+ Vec_Ptr_t * vPos; // the PO structures
+ Vec_Ptr_t * vLis; // the LI structures
+ Vec_Ptr_t * vLos; // the LO structures
+ // mapping of names into objects
+ Io_BlifObj_t ** pTable; // the hash table
+ int nTableSize; // the hash table size
+ // current processing info
+ Abc_Ntk_t * pAig; // the network under construction
+ Vec_Ptr_t * vTokens; // the current tokens
+ char sError[512]; // the error string generated during parsing
+ // statistics
+ int nTablesRead; // the number of processed tables
+ int nTablesLeft; // the number of dangling tables
+};
+
+// static functions
+static Io_BlifMan_t * Io_BlifAlloc();
+static void Io_BlifFree( Io_BlifMan_t * p );
+static char * Io_BlifLoadFile( char * pFileName );
+static void Io_BlifReadPreparse( Io_BlifMan_t * p );
+static Abc_Ntk_t * Io_BlifParse( Io_BlifMan_t * p );
+static int Io_BlifParseModel( Io_BlifMan_t * p, char * pLine );
+static int Io_BlifParseInputs( Io_BlifMan_t * p, char * pLine );
+static int Io_BlifParseOutputs( Io_BlifMan_t * p, char * pLine );
+static int Io_BlifParseLatch( Io_BlifMan_t * p, char * pLine );
+static int Io_BlifParseNames( Io_BlifMan_t * p, char * pLine );
+static int Io_BlifParseConstruct( Io_BlifMan_t * p );
+static int Io_BlifCharIsSpace( char s ) { return s == ' ' || s == '\t' || s == '\r' || s == '\n'; }
+
+////////////////////////////////////////////////////////////////////////
+/// FUNCTION DEFINITIONS ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+ Synopsis [Reads the network from the BLIF file as an AIG.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Abc_Ntk_t * Io_ReadBlifAsAig( char * pFileName, int fCheck )
+{
+ FILE * pFile;
+ Io_BlifMan_t * p;
+ Abc_Ntk_t * pAig;
+
+ // check that the file is available
+ pFile = fopen( pFileName, "rb" );
+ if ( pFile == NULL )
+ {
+ printf( "Io_Blif(): The file is unavailable (absent or open).\n" );
+ return 0;
+ }
+ fclose( pFile );
+
+ // start the file reader
+ p = Io_BlifAlloc();
+ p->pFileName = pFileName;
+ p->pBuffer = Io_BlifLoadFile( pFileName );
+ if ( p->pBuffer == NULL )
+ {
+ Io_BlifFree( p );
+ return NULL;
+ }
+ // prepare the file for parsing
+ Io_BlifReadPreparse( p );
+ // construct the network
+ pAig = Io_BlifParse( p );
+ if ( p->sError[0] )
+ fprintf( stdout, "%s\n", p->sError );
+ if ( pAig == NULL )
+ return NULL;
+ Io_BlifFree( p );
+
+ // make sure that everything is okay with the network structure
+ if ( fCheck && !Abc_NtkCheckRead( pAig ) )
+ {
+ printf( "Io_Blif: The network check has failed.\n" );
+ Abc_NtkDelete( pAig );
+ return NULL;
+ }
+ return pAig;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Allocates the BLIF parsing structure.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+static Io_BlifMan_t * Io_BlifAlloc()
+{
+ Io_BlifMan_t * p;
+ p = ALLOC( Io_BlifMan_t, 1 );
+ memset( p, 0, sizeof(Io_BlifMan_t) );
+ p->vLines = Vec_PtrAlloc( 512 );
+ p->vInputs = Vec_PtrAlloc( 512 );
+ p->vOutputs = Vec_PtrAlloc( 512 );
+ p->vLatches = Vec_PtrAlloc( 512 );
+ p->vNames = Vec_PtrAlloc( 512 );
+ p->vTokens = Vec_PtrAlloc( 512 );
+ p->vPis = Vec_PtrAlloc( 512 );
+ p->vPos = Vec_PtrAlloc( 512 );
+ p->vLis = Vec_PtrAlloc( 512 );
+ p->vLos = Vec_PtrAlloc( 512 );
+ return p;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Frees the BLIF parsing structure.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+static void Io_BlifFree( Io_BlifMan_t * p )
+{
+ if ( p->pAig )
+ Abc_NtkDelete( p->pAig );
+ if ( p->pBuffer ) free( p->pBuffer );
+ if ( p->pObjects ) free( p->pObjects );
+ if ( p->pTable ) free( p->pTable );
+ Vec_PtrFree( p->vLines );
+ Vec_PtrFree( p->vInputs );
+ Vec_PtrFree( p->vOutputs );
+ Vec_PtrFree( p->vLatches );
+ Vec_PtrFree( p->vNames );
+ Vec_PtrFree( p->vTokens );
+ Vec_PtrFree( p->vPis );
+ Vec_PtrFree( p->vPos );
+ Vec_PtrFree( p->vLis );
+ Vec_PtrFree( p->vLos );
+ free( p );
+}
+
+
+/**Function*************************************************************
+
+ Synopsis [Hashing for character strings.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+static unsigned Io_BlifHashString( char * pName, int TableSize )
+{
+ static int s_Primes[10] = {
+ 1291, 1699, 2357, 4177, 5147,
+ 5647, 6343, 7103, 7873, 8147
+ };
+ unsigned i, Key = 0;
+ for ( i = 0; pName[i] != '\0'; i++ )
+ Key ^= s_Primes[i%10]*pName[i]*pName[i];
+ return Key % TableSize;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Checks if the given name exists in the table.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+static Io_BlifObj_t ** Io_BlifHashLookup( Io_BlifMan_t * p, char * pName )
+{
+ Io_BlifObj_t ** ppEntry;
+ for ( ppEntry = p->pTable + Io_BlifHashString(pName, p->nTableSize); *ppEntry; ppEntry = &(*ppEntry)->pNext )
+ if ( !strcmp((*ppEntry)->pName, pName) )
+ return ppEntry;
+ return ppEntry;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Finds or add the given name to the table.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+static Io_BlifObj_t * Io_BlifHashFindOrAdd( Io_BlifMan_t * p, char * pName )
+{
+ Io_BlifObj_t ** ppEntry;
+ ppEntry = Io_BlifHashLookup( p, pName );
+ if ( *ppEntry == NULL )
+ {
+ assert( p->iObjNext < p->nObjects );
+ *ppEntry = p->pObjects + p->iObjNext++;
+ (*ppEntry)->pName = pName;
+ }
+ return *ppEntry;
+}
+
+
+/**Function*************************************************************
+
+ Synopsis [Collects the already split tokens.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+static void Io_BlifCollectTokens( Vec_Ptr_t * vTokens, char * pInput, char * pOutput )
+{
+ char * pCur;
+ Vec_PtrClear( vTokens );
+ for ( pCur = pInput; pCur < pOutput; pCur++ )
+ {
+ if ( *pCur == 0 )
+ continue;
+ Vec_PtrPush( vTokens, pCur );
+ while ( *++pCur );
+ }
+}
+
+/**Function*************************************************************
+
+ Synopsis [Splits the line into tokens.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+static void Io_BlifSplitIntoTokens( Vec_Ptr_t * vTokens, char * pLine, char Stop )
+{
+ char * pCur;
+ // clear spaces
+ for ( pCur = pLine; *pCur != Stop; pCur++ )
+ if ( Io_BlifCharIsSpace(*pCur) )
+ *pCur = 0;
+ // collect tokens
+ Io_BlifCollectTokens( vTokens, pLine, pCur );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Returns the 1-based number of the line in which the token occurs.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+static int Io_BlifGetLine( Io_BlifMan_t * p, char * pToken )
+{
+ char * pLine;
+ int i;
+ Vec_PtrForEachEntry( p->vLines, pLine, i )
+ if ( pToken < pLine )
+ return i;
+ return -1;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Conservatively estimates the number of primary inputs.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+static int Io_BlifEstimatePiNum( Io_BlifMan_t * p )
+{
+ char * pCur;
+ int i, fSpaces;
+ int Counter = 0;
+ Vec_PtrForEachEntry( p->vInputs, pCur, i )
+ for ( fSpaces = 0; *pCur; pCur++ )
+ {
+ if ( Io_BlifCharIsSpace(*pCur) )
+ {
+ if ( !fSpaces )
+ Counter++;
+ fSpaces = 1;
+ }
+ else
+ fSpaces = 0;
+ }
+ return Counter;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Conservatively estimates the number of AIG nodes.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+static int Io_BlifEstimateAndNum( Io_BlifMan_t * p )
+{
+ Io_BlifObj_t * pObj;
+ char * pCur;
+ int i, CounterOne, Counter = 0;
+ for ( i = 0; i < p->iObjNext; i++ )
+ {
+ pObj = p->pObjects + i;
+ if ( !pObj->fDef )
+ continue;
+ CounterOne = 0;
+ for ( pCur = pObj->pName + strlen(pObj->pName); *pCur != '.'; pCur++ )
+ if ( *pCur == '0' || *pCur == '1' )
+ CounterOne++;
+ if ( CounterOne )
+ Counter += CounterOne - 1;
+ }
+ return Counter;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Reads the file into a character buffer.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+static char * Io_BlifLoadFile( char * pFileName )
+{
+ FILE * pFile;
+ int nFileSize;
+ char * pContents;
+ pFile = fopen( pFileName, "rb" );
+ if ( pFile == NULL )
+ {
+ printf( "Io_BlifLoadFile(): The file is unavailable (absent or open).\n" );
+ return NULL;
+ }
+ fseek( pFile, 0, SEEK_END );
+ nFileSize = ftell( pFile );
+ if ( nFileSize == 0 )
+ {
+ printf( "Io_BlifLoadFile(): The file is empty.\n" );
+ return NULL;
+ }
+ pContents = ALLOC( char, nFileSize + 10 );
+ rewind( pFile );
+ fread( pContents, nFileSize, 1, pFile );
+ fclose( pFile );
+ // finish off the file with the spare .end line
+ // some benchmarks suddenly break off without this line
+ strcpy( pContents + nFileSize, "\n.end\n" );
+ return pContents;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Prepares the parsing.]
+
+ Description [Performs several preliminary operations:
+ - Cuts the file buffer into separate lines.
+ - Removes comments and line extenders.
+ - Sorts lines by directives.
+ - Estimates the number of objects.
+ - Allocates room for the objects.
+ - Allocates room for the hash table.]
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+static void Io_BlifReadPreparse( Io_BlifMan_t * p )
+{
+ char * pCur, * pPrev;
+ int i, fComment = 0;
+ // parse the buffer into lines and remove comments
+ Vec_PtrPush( p->vLines, p->pBuffer );
+ for ( pCur = p->pBuffer; *pCur; pCur++ )
+ {
+ if ( *pCur == '\n' )
+ {
+ *pCur = 0;
+ fComment = 0;
+ Vec_PtrPush( p->vLines, pCur + 1 );
+ }
+ else if ( *pCur == '#' )
+ fComment = 1;
+ // remove comments
+ if ( fComment )
+ *pCur = 0;
+ }
+
+ // unfold the line extensions and sort lines by directive
+ Vec_PtrForEachEntry( p->vLines, pCur, i )
+ {
+ if ( *pCur == 0 )
+ continue;
+ // find previous non-space character
+ for ( pPrev = pCur - 2; pPrev >= p->pBuffer; pPrev-- )
+ if ( !Io_BlifCharIsSpace(*pPrev) )
+ break;
+ // if it is the line extender, overwrite it with spaces
+ if ( *pPrev == '\\' )
+ {
+ for ( ; *pPrev; pPrev++ )
+ *pPrev = ' ';
+ *pPrev = ' ';
+ continue;
+ }
+ // skip spaces at the beginning of the line
+ while ( Io_BlifCharIsSpace(*pCur++) );
+ // parse directives
+ if ( *(pCur-1) != '.' )
+ continue;
+ if ( !strncmp(pCur, "names", 5) )
+ Vec_PtrPush( p->vNames, pCur );
+ else if ( !strncmp(pCur, "latch", 5) )
+ Vec_PtrPush( p->vLatches, pCur );
+ else if ( !strncmp(pCur, "inputs", 6) )
+ Vec_PtrPush( p->vInputs, pCur );
+ else if ( !strncmp(pCur, "outputs", 7) )
+ Vec_PtrPush( p->vOutputs, pCur );
+ else if ( !strncmp(pCur, "model", 5) )
+ p->pModel = pCur;
+ else if ( !strncmp(pCur, "end", 3) || !strncmp(pCur, "exdc", 4) )
+ break;
+ else
+ {
+ pCur--;
+ if ( pCur[strlen(pCur)-1] == '\r' )
+ pCur[strlen(pCur)-1] = 0;
+ fprintf( stdout, "Line %d: Skipping line \"%s\".\n", Io_BlifGetLine(p, pCur), pCur );
+ }
+ }
+
+ // count the number of objects
+ p->nObjects = Io_BlifEstimatePiNum(p) + Vec_PtrSize(p->vLatches) + Vec_PtrSize(p->vNames) + 512;
+
+ // allocate memory for objects
+ p->pObjects = ALLOC( Io_BlifObj_t, p->nObjects );
+ memset( p->pObjects, 0, p->nObjects * sizeof(Io_BlifObj_t) );
+
+ // allocate memory for the hash table
+ p->nTableSize = p->nObjects/2 + 1;
+ p->pTable = ALLOC( Io_BlifObj_t *, p->nTableSize );
+ memset( p->pTable, 0, p->nTableSize * sizeof(Io_BlifObj_t *) );
+}
+
+
+/**Function*************************************************************
+
+ Synopsis [Reads the AIG in the binary AIGER format.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+static Abc_Ntk_t * Io_BlifParse( Io_BlifMan_t * p )
+{
+ Abc_Ntk_t * pAig;
+ char * pLine;
+ int i;
+ // parse the model
+ if ( !Io_BlifParseModel( p, p->pModel ) )
+ return NULL;
+ // parse the inputs
+ Vec_PtrForEachEntry( p->vInputs, pLine, i )
+ if ( !Io_BlifParseInputs( p, pLine ) )
+ return NULL;
+ // parse the outputs
+ Vec_PtrForEachEntry( p->vOutputs, pLine, i )
+ if ( !Io_BlifParseOutputs( p, pLine ) )
+ return NULL;
+ // parse the latches
+ Vec_PtrForEachEntry( p->vLatches, pLine, i )
+ if ( !Io_BlifParseLatch( p, pLine ) )
+ return NULL;
+ // parse the nodes
+ Vec_PtrForEachEntry( p->vNames, pLine, i )
+ if ( !Io_BlifParseNames( p, pLine ) )
+ return NULL;
+ // reconstruct the network from the parsed data
+ if ( !Io_BlifParseConstruct( p ) )
+ return NULL;
+ // return the network
+ pAig = p->pAig;
+ p->pAig = NULL;
+ return pAig;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Parses the model line.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+static int Io_BlifParseModel( Io_BlifMan_t * p, char * pLine )
+{
+ char * pToken;
+ Io_BlifSplitIntoTokens( p->vTokens, pLine, '\0' );
+ pToken = Vec_PtrEntry( p->vTokens, 0 );
+ assert( !strcmp(pToken, "model") );
+ if ( Vec_PtrSize(p->vTokens) != 2 )
+ {
+ sprintf( p->sError, "Line %d: Model line has %d entries while it should have 2.", Io_BlifGetLine(p, pToken), Vec_PtrSize(p->vTokens) );
+ return 0;
+ }
+ p->pModel = Vec_PtrEntry( p->vTokens, 1 );
+ return 1;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Parses the inputs line.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+static int Io_BlifParseInputs( Io_BlifMan_t * p, char * pLine )
+{
+ Io_BlifObj_t * pObj;
+ char * pToken;
+ int i;
+ Io_BlifSplitIntoTokens( p->vTokens, pLine, '\0' );
+ pToken = Vec_PtrEntry(p->vTokens, 0);
+ assert( !strcmp(pToken, "inputs") );
+ Vec_PtrForEachEntryStart( p->vTokens, pToken, i, 1 )
+ {
+ pObj = Io_BlifHashFindOrAdd( p, pToken );
+ if ( pObj->fPi )
+ {
+ sprintf( p->sError, "Line %d: Primary input (%s) is defined more than once.", Io_BlifGetLine(p, pToken), pToken );
+ return 0;
+ }
+ pObj->fPi = 1;
+ Vec_PtrPush( p->vPis, pObj );
+ }
+ return 1;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Parses the outputs line.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+static int Io_BlifParseOutputs( Io_BlifMan_t * p, char * pLine )
+{
+ Io_BlifObj_t * pObj;
+ char * pToken;
+ int i;
+ Io_BlifSplitIntoTokens( p->vTokens, pLine, '\0' );
+ pToken = Vec_PtrEntry(p->vTokens, 0);
+ assert( !strcmp(pToken, "outputs") );
+ Vec_PtrForEachEntryStart( p->vTokens, pToken, i, 1 )
+ {
+ pObj = Io_BlifHashFindOrAdd( p, pToken );
+ if ( pObj->fPo )
+ fprintf( stdout, "Line %d: Primary output (%s) is defined more than once (warning only).\n", Io_BlifGetLine(p, pToken), pToken );
+ pObj->fPo = 1;
+ Vec_PtrPush( p->vPos, pObj );
+ }
+ return 1;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Parses the latches line.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+static int Io_BlifParseLatch( Io_BlifMan_t * p, char * pLine )
+{
+ Io_BlifObj_t * pObj;
+ char * pToken;
+ int Init;
+ Io_BlifSplitIntoTokens( p->vTokens, pLine, '\0' );
+ pToken = Vec_PtrEntry(p->vTokens,0);
+ assert( !strcmp(pToken, "latch") );
+ if ( Vec_PtrSize(p->vTokens) < 3 )
+ {
+ sprintf( p->sError, "Line %d: Latch does not have input name and output name.", Io_BlifGetLine(p, pToken) );
+ return 0;
+ }
+ // get initial value
+ if ( Vec_PtrSize(p->vTokens) > 3 )
+ Init = atoi( Vec_PtrEntry(p->vTokens,3) );
+ else
+ Init = 2;
+ if ( Init < 0 || Init > 2 )
+ {
+ sprintf( p->sError, "Line %d: Initial state of the latch is incorrect (%s).", Io_BlifGetLine(p, pToken), Vec_PtrEntry(p->vTokens,3) );
+ return 0;
+ }
+ if ( Init == 0 )
+ Init = IO_BLIF_INIT_ZERO;
+ else if ( Init == 1 )
+ Init = IO_BLIF_INIT_ONE;
+ else // if ( Init == 2 )
+ Init = IO_BLIF_INIT_DC;
+ // get latch input
+ pObj = Io_BlifHashFindOrAdd( p, Vec_PtrEntry(p->vTokens,1) );
+ pObj->fLi = 1;
+ Vec_PtrPush( p->vLis, pObj );
+ pObj->Init = Init;
+ // get latch output
+ pObj = Io_BlifHashFindOrAdd( p, Vec_PtrEntry(p->vTokens,2) );
+ if ( pObj->fPi )
+ {
+ sprintf( p->sError, "Line %d: Primary input (%s) is also defined latch output.", Io_BlifGetLine(p, pToken), Vec_PtrEntry(p->vTokens,2) );
+ return 0;
+ }
+ if ( pObj->fLo )
+ {
+ sprintf( p->sError, "Line %d: Latch output (%s) is defined as the output of another latch.", Io_BlifGetLine(p, pToken), Vec_PtrEntry(p->vTokens,2) );
+ return 0;
+ }
+ pObj->fLo = 1;
+ Vec_PtrPush( p->vLos, pObj );
+ pObj->Init = Init;
+ return 1;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Parses the nodes line.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+static int Io_BlifParseNames( Io_BlifMan_t * p, char * pLine )
+{
+ Io_BlifObj_t * pObj;
+ char * pName;
+ Io_BlifSplitIntoTokens( p->vTokens, pLine, '\0' );
+ assert( !strcmp(Vec_PtrEntry(p->vTokens,0), "names") );
+ pName = Vec_PtrEntryLast( p->vTokens );
+ pObj = Io_BlifHashFindOrAdd( p, pName );
+ if ( pObj->fPi )
+ {
+ sprintf( p->sError, "Line %d: Primary input (%s) has a table.", Io_BlifGetLine(p, pName), pName );
+ return 0;
+ }
+ if ( pObj->fLo )
+ {
+ sprintf( p->sError, "Line %d: Latch output (%s) has a table.", Io_BlifGetLine(p, pName), pName );
+ return 0;
+ }
+ if ( pObj->fDef )
+ {
+ sprintf( p->sError, "Line %d: Signal (%s) is defined more than once.", Io_BlifGetLine(p, pName), pName );
+ return 0;
+ }
+ pObj->fDef = 1;
+ // remember offset to the first fanin name
+ pObj->pName = pName;
+ pObj->Offset = pObj->pName - (char *)Vec_PtrEntry(p->vTokens,1);
+ return 1;
+}
+
+
+/**Function*************************************************************
+
+ Synopsis [Constructs the AIG from the file parsing info.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+static Abc_Obj_t * Io_BlifParseTable( Io_BlifMan_t * p, char * pTable, Vec_Ptr_t * vFanins )
+{
+ char * pProduct, * pOutput;
+ Abc_Obj_t * pRes, * pCube;
+ int i, k, Polarity = -1;
+
+ p->nTablesRead++;
+ // get the tokens
+ Io_BlifSplitIntoTokens( p->vTokens, pTable, '.' );
+ if ( Vec_PtrSize(p->vTokens) == 0 )
+ return Abc_ObjNot( Abc_AigConst1(p->pAig) );
+ if ( Vec_PtrSize(p->vTokens) == 1 )
+ {
+ pOutput = Vec_PtrEntry( p->vTokens, 0 );
+ if ( ((pOutput[0] - '0') & 0x8E) || pOutput[1] )
+ {
+ sprintf( p->sError, "Line %d: Constant table has wrong output value (%s).", Io_BlifGetLine(p, pOutput), pOutput );
+ return NULL;
+ }
+ return Abc_ObjNotCond( Abc_AigConst1(p->pAig), pOutput[0] == '0' );
+ }
+ pProduct = Vec_PtrEntry( p->vTokens, 0 );
+ if ( Vec_PtrSize(p->vTokens) % 2 == 1 )
+ {
+ sprintf( p->sError, "Line %d: Table has odd number of tokens (%d).", Io_BlifGetLine(p, pProduct), Vec_PtrSize(p->vTokens) );
+ return NULL;
+ }
+ // parse the table
+ pRes = Abc_ObjNot( Abc_AigConst1(p->pAig) );
+ for ( i = 0; i < Vec_PtrSize(p->vTokens)/2; i++ )
+ {
+ pProduct = Vec_PtrEntry( p->vTokens, 2*i + 0 );
+ pOutput = Vec_PtrEntry( p->vTokens, 2*i + 1 );
+ if ( strlen(pProduct) != (unsigned)Vec_PtrSize(vFanins) )
+ {
+ sprintf( p->sError, "Line %d: Cube (%s) has size different from the fanin count (%d).", Io_BlifGetLine(p, pProduct), pProduct, Vec_PtrSize(vFanins) );
+ return NULL;
+ }
+ if ( ((pOutput[0] - '0') & 0x8E) || pOutput[1] )
+ {
+ sprintf( p->sError, "Line %d: Output value (%s) is incorrect.", Io_BlifGetLine(p, pProduct), pOutput );
+ return NULL;
+ }
+ if ( Polarity == -1 )
+ Polarity = pOutput[0] - '0';
+ else if ( Polarity != pOutput[0] - '0' )
+ {
+ sprintf( p->sError, "Line %d: Output value (%s) differs from the value in the first line of the table (%d).", Io_BlifGetLine(p, pProduct), pOutput, Polarity );
+ return NULL;
+ }
+ // parse one product product
+ pCube = Abc_AigConst1(p->pAig);
+ for ( k = 0; pProduct[k]; k++ )
+ {
+ if ( pProduct[k] == '0' )
+ pCube = Abc_AigAnd( p->pAig->pManFunc, pCube, Abc_ObjNot(Vec_PtrEntry(vFanins,k)) );
+ else if ( pProduct[k] == '1' )
+ pCube = Abc_AigAnd( p->pAig->pManFunc, pCube, Vec_PtrEntry(vFanins,k) );
+ else if ( pProduct[k] != '-' )
+ {
+ sprintf( p->sError, "Line %d: Product term (%s) contains character (%c).", Io_BlifGetLine(p, pProduct), pProduct, pProduct[k] );
+ return NULL;
+ }
+ }
+ pRes = Abc_AigOr( p->pAig->pManFunc, pRes, pCube );
+ }
+ pRes = Abc_ObjNotCond( pRes, Polarity == 0 );
+ return pRes;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Constructs the AIG from the file parsing info.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+static Abc_Obj_t * Io_BlifParseConstruct_rec( Io_BlifMan_t * p, char * pName )
+{
+ Vec_Ptr_t * vFanins;
+ Abc_Obj_t * pFaninAbc;
+ Io_BlifObj_t * pObjIo;
+ char * pNameFanin;
+ int i;
+ // get the IO object with this name
+ pObjIo = *Io_BlifHashLookup( p, pName );
+ if ( pObjIo == NULL )
+ {
+ sprintf( p->sError, "Line %d: Signal (%s) is not defined as a table.", Io_BlifGetLine(p, pName), pName );
+ return NULL;
+ }
+ // loop detection
+ if ( pObjIo->fLoop )
+ {
+ sprintf( p->sError, "Line %d: Signal (%s) appears twice on a combinational path.", Io_BlifGetLine(p, pName), pName );
+ return NULL;
+ }
+ // check if the AIG is already constructed
+ if ( pObjIo->pEquiv )
+ return pObjIo->pEquiv;
+ // mark this node on the path
+ pObjIo->fLoop = 1;
+ // construct the AIGs for the fanins
+ vFanins = Vec_PtrAlloc( 8 );
+ Io_BlifCollectTokens( vFanins, pObjIo->pName - pObjIo->Offset, pObjIo->pName );
+ Vec_PtrForEachEntry( vFanins, pNameFanin, i )
+ {
+ pFaninAbc = Io_BlifParseConstruct_rec( p, pNameFanin );
+ if ( pFaninAbc == NULL )
+ {
+ Vec_PtrFree( vFanins );
+ return NULL;
+ }
+ Vec_PtrWriteEntry( vFanins, i, pFaninAbc );
+ }
+ // construct the node
+ pObjIo->pEquiv = Io_BlifParseTable( p, pObjIo->pName + strlen(pObjIo->pName), vFanins );
+ Vec_PtrFree( vFanins );
+ // unmark this node on the path
+ pObjIo->fLoop = 0;
+ // remember the new node
+ return pObjIo->pEquiv;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Constructs the AIG from the file parsing info.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+static int Io_BlifParseConstruct( Io_BlifMan_t * p )
+{
+ Abc_Ntk_t * pAig;
+ Io_BlifObj_t * pObjIo, * pObjIoInput;
+ Abc_Obj_t * pObj, * pLatch;
+ int i;
+ // allocate the empty AIG
+ pAig = p->pAig = Abc_NtkAlloc( ABC_NTK_STRASH, ABC_FUNC_AIG, 1 );
+ pAig->pName = Extra_UtilStrsav( p->pModel );
+ pAig->pSpec = Extra_UtilStrsav( p->pFileName );
+ // create PIs
+ Vec_PtrForEachEntry( p->vPis, pObjIo, i )
+ {
+ pObj = Abc_NtkCreatePi( pAig );
+ Abc_ObjAssignName( pObj, pObjIo->pName, NULL );
+ pObjIo->pEquiv = pObj;
+ }
+ // create POs
+ Vec_PtrForEachEntry( p->vPos, pObjIo, i )
+ {
+ pObj = Abc_NtkCreatePo( pAig );
+ Abc_ObjAssignName( pObj, pObjIo->pName, NULL );
+ }
+ // create latches
+ Vec_PtrForEachEntry( p->vLos, pObjIo, i )
+ {
+ // add the latch input terminal
+ pObj = Abc_NtkCreateBi( pAig );
+ pObjIoInput = Vec_PtrEntry( p->vLis, i );
+ Abc_ObjAssignName( pObj, pObjIoInput->pName, NULL );
+
+ // add the latch box
+ pLatch = Abc_NtkCreateLatch( pAig );
+ pLatch->pData = (void *)pObjIo->Init;
+ Abc_ObjAssignName( pLatch, pObjIo->pName, "L" );
+ Abc_ObjAddFanin( pLatch, pObj );
+
+ // add the latch output terminal
+ pObj = Abc_NtkCreateBo( pAig );
+ Abc_ObjAssignName( pObj, pObjIo->pName, NULL );
+ Abc_ObjAddFanin( pObj, pLatch );
+ // set the value of the latch output
+// pObjIo->pEquiv = Abc_ObjNotCond( pObj, pObjIo->Init );
+ pObjIo->pEquiv = pObj;
+ }
+ // traverse the nodes from the POs
+ Vec_PtrForEachEntry( p->vPos, pObjIo, i )
+ {
+ pObj = Io_BlifParseConstruct_rec( p, pObjIo->pName );
+ if ( pObj == NULL )
+ return 0;
+ Abc_ObjAddFanin( Abc_NtkPo(p->pAig, i), pObj );
+ }
+ // traverse the nodes from the latch inputs
+ Vec_PtrForEachEntry( p->vLis, pObjIo, i )
+ {
+ pObj = Io_BlifParseConstruct_rec( p, pObjIo->pName );
+ if ( pObj == NULL )
+ return 0;
+// pObj = Abc_ObjNotCond( pObj, pObjIo->Init );
+ Abc_ObjAddFanin( Abc_ObjFanin0(Abc_NtkBox(p->pAig, i)), pObj );
+ }
+ p->nTablesLeft = Vec_PtrSize(p->vNames) - p->nTablesRead;
+ if ( p->nTablesLeft )
+ printf( "The number of dangling tables = %d.\n", p->nTablesLeft );
+ printf( "AND nodes = %6d. Estimate = %6d.\n", Abc_NtkNodeNum(p->pAig), Io_BlifEstimateAndNum(p) );
+ return 1;
+}
+
+////////////////////////////////////////////////////////////////////////
+/// END OF FILE ///
+////////////////////////////////////////////////////////////////////////
+
+
diff --git a/src/base/io/ioReadBlifMv.c b/src/base/io/ioReadBlifMv.c
new file mode 100644
index 00000000..97f2fbf3
--- /dev/null
+++ b/src/base/io/ioReadBlifMv.c
@@ -0,0 +1,1702 @@
+/**CFile****************************************************************
+
+ FileName [ioReadBlifMv.c]
+
+ SystemName [ABC: Logic synthesis and verification system.]
+
+ PackageName [Command processing package.]
+
+ Synopsis [Procedures to read BLIF-MV file.]
+
+ Author [Alan Mishchenko]
+
+ Affiliation [UC Berkeley]
+
+ Date [Ver. 1.0. Started - January 8, 2007.]
+
+ Revision [$Id: ioReadBlifMv.c,v 1.00 2007/01/08 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "abc.h"
+#include "extra.h"
+#include "vecPtr.h"
+#include "io.h"
+
+////////////////////////////////////////////////////////////////////////
+/// DECLARATIONS ///
+////////////////////////////////////////////////////////////////////////
+
+#define IO_BLIFMV_MAXVALUES 256
+
+typedef struct Io_MvVar_t_ Io_MvVar_t; // parsing var
+typedef struct Io_MvMod_t_ Io_MvMod_t; // parsing model
+typedef struct Io_MvMan_t_ Io_MvMan_t; // parsing manager
+
+struct Io_MvVar_t_
+{
+ int nValues; // the number of values
+ char ** pNames; // the value names
+};
+
+struct Io_MvMod_t_
+{
+ // file lines
+ char * pName; // .model line
+ Vec_Ptr_t * vInputs; // .inputs lines
+ Vec_Ptr_t * vOutputs; // .outputs lines
+ Vec_Ptr_t * vLatches; // .latch lines
+ Vec_Ptr_t * vResets; // .reset lines
+ Vec_Ptr_t * vNames; // .names lines
+ Vec_Ptr_t * vSubckts; // .subckt lines
+ Vec_Ptr_t * vMvs; // .mv lines
+ int fBlackBox; // indicates blackbox model
+ // the resulting network
+ Abc_Ntk_t * pNtk;
+ Abc_Obj_t * pResetLatch;
+ // the parent manager
+ Io_MvMan_t * pMan;
+};
+
+struct Io_MvMan_t_
+{
+ // general info about file
+ int fBlifMv; // the file is BLIF-MV
+ int fUseReset; // the reset circuitry is added
+ char * pFileName; // the name of the file
+ char * pBuffer; // the contents of the file
+ Vec_Ptr_t * vLines; // the line beginnings
+ // the results of reading
+ Abc_Lib_t * pDesign; // the design under construction
+ int nNDnodes; // the counter of ND nodes
+ // intermediate storage for models
+ Vec_Ptr_t * vModels; // vector of models
+ Io_MvMod_t * pLatest; // the current model
+ // current processing info
+ Vec_Ptr_t * vTokens; // the current tokens
+ Vec_Ptr_t * vTokens2; // the current tokens
+ Vec_Str_t * vFunc; // the local function
+ // error reporting
+ char sError[512]; // the error string generated during parsing
+ // statistics
+ int nTablesRead; // the number of processed tables
+ int nTablesLeft; // the number of dangling tables
+};
+
+// static functions
+static Io_MvMan_t * Io_MvAlloc();
+static void Io_MvFree( Io_MvMan_t * p );
+static Io_MvMod_t * Io_MvModAlloc();
+static void Io_MvModFree( Io_MvMod_t * p );
+static char * Io_MvLoadFile( char * pFileName );
+static void Io_MvReadPreparse( Io_MvMan_t * p );
+static void Io_MvReadInterfaces( Io_MvMan_t * p );
+static Abc_Lib_t * Io_MvParse( Io_MvMan_t * p );
+static int Io_MvParseLineModel( Io_MvMod_t * p, char * pLine );
+static int Io_MvParseLineInputs( Io_MvMod_t * p, char * pLine );
+static int Io_MvParseLineOutputs( Io_MvMod_t * p, char * pLine );
+static int Io_MvParseLineLatch( Io_MvMod_t * p, char * pLine );
+static int Io_MvParseLineSubckt( Io_MvMod_t * p, char * pLine );
+static int Io_MvParseLineMv( Io_MvMod_t * p, char * pLine );
+static int Io_MvParseLineNamesMv( Io_MvMod_t * p, char * pLine, int fReset );
+static int Io_MvParseLineNamesBlif( Io_MvMod_t * p, char * pLine );
+static int Io_MvParseLineGateBlif( Io_MvMod_t * p, Vec_Ptr_t * vTokens );
+static Io_MvVar_t * Abc_NtkMvVarDup( Abc_Ntk_t * pNtk, Io_MvVar_t * pVar );
+
+static int Io_MvCharIsSpace( char s ) { return s == ' ' || s == '\t' || s == '\r' || s == '\n'; }
+static int Io_MvCharIsMvSymb( char s ) { return s == '(' || s == ')' || s == '{' || s == '}' || s == '-' || s == ',' || s == '!'; }
+
+extern void Abc_NtkStartMvVars( Abc_Ntk_t * pNtk );
+
+////////////////////////////////////////////////////////////////////////
+/// FUNCTION DEFINITIONS ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+ Synopsis [Reads the network from the BLIF or BLIF-MV file.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Abc_Ntk_t * Io_ReadBlifMv( char * pFileName, int fBlifMv, int fCheck )
+{
+ FILE * pFile;
+ Io_MvMan_t * p;
+ Abc_Ntk_t * pNtk;
+ Abc_Lib_t * pDesign;
+ char * pDesignName;
+ int RetValue, i;
+
+ // check that the file is available
+ pFile = fopen( pFileName, "rb" );
+ if ( pFile == NULL )
+ {
+ printf( "Io_ReadBlifMv(): The file is unavailable (absent or open).\n" );
+ return 0;
+ }
+ fclose( pFile );
+
+ // start the file reader
+ p = Io_MvAlloc();
+ p->fBlifMv = fBlifMv;
+ p->fUseReset = 0;
+ p->pFileName = pFileName;
+ p->pBuffer = Io_MvLoadFile( pFileName );
+ if ( p->pBuffer == NULL )
+ {
+ Io_MvFree( p );
+ return NULL;
+ }
+ // set the design name
+ pDesignName = Extra_FileNameGeneric( pFileName );
+ p->pDesign = Abc_LibCreate( pDesignName );
+ free( pDesignName );
+ // free the HOP manager
+ Hop_ManStop( p->pDesign->pManFunc );
+ p->pDesign->pManFunc = NULL;
+ // prepare the file for parsing
+ Io_MvReadPreparse( p );
+ // parse interfaces of each network
+ Io_MvReadInterfaces( p );
+ // construct the network
+ pDesign = Io_MvParse( p );
+ if ( p->sError[0] )
+ fprintf( stdout, "%s\n", p->sError );
+ Io_MvFree( p );
+ if ( pDesign == NULL )
+ return NULL;
+// pDesign should be linked to all models of the design
+
+ // make sure that everything is okay with the network structure
+ if ( fCheck )
+ {
+ Vec_PtrForEachEntry( pDesign->vModules, pNtk, i )
+ {
+ if ( !Abc_NtkCheckRead( pNtk ) )
+ {
+ printf( "Io_ReadBlifMv: The network check has failed for network %s.\n", pNtk->pName );
+ Abc_LibFree( pDesign, NULL );
+ return NULL;
+ }
+ }
+ }
+
+//Abc_LibPrint( pDesign );
+
+ // detect top-level model
+ RetValue = Abc_LibFindTopLevelModels( pDesign );
+ pNtk = Vec_PtrEntry( pDesign->vTops, 0 );
+ if ( RetValue > 1 )
+ printf( "Warning: The design has %d root-level modules. The first one (%s) will be used.\n",
+ Vec_PtrSize(pDesign->vTops), pNtk->pName );
+
+ // extract the master network
+ pNtk->pDesign = pDesign;
+ pDesign->pManFunc = NULL;
+
+ // verify the design for cyclic dependence
+ assert( Vec_PtrSize(pDesign->vModules) > 0 );
+ if ( Vec_PtrSize(pDesign->vModules) == 1 )
+ {
+// printf( "Warning: The design is not hierarchical.\n" );
+ Abc_LibFree( pDesign, pNtk );
+ pNtk->pDesign = NULL;
+ pNtk->pSpec = Extra_UtilStrsav( pFileName );
+ }
+ else
+ Abc_NtkIsAcyclicHierarchy( pNtk );
+
+//Io_WriteBlifMv( pNtk, "_temp_.mv" );
+ if ( pNtk->pSpec == NULL )
+ pNtk->pSpec = Extra_UtilStrsav( pFileName );
+ return pNtk;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Allocates the BLIF parsing structure.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+static Io_MvMan_t * Io_MvAlloc()
+{
+ Io_MvMan_t * p;
+ p = ALLOC( Io_MvMan_t, 1 );
+ memset( p, 0, sizeof(Io_MvMan_t) );
+ p->vLines = Vec_PtrAlloc( 512 );
+ p->vModels = Vec_PtrAlloc( 512 );
+ p->vTokens = Vec_PtrAlloc( 512 );
+ p->vTokens2 = Vec_PtrAlloc( 512 );
+ p->vFunc = Vec_StrAlloc( 512 );
+ return p;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Frees the BLIF parsing structure.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+static void Io_MvFree( Io_MvMan_t * p )
+{
+ Io_MvMod_t * pMod;
+ int i;
+ if ( p->pDesign )
+ Abc_LibFree( p->pDesign, NULL );
+ if ( p->pBuffer )
+ free( p->pBuffer );
+ if ( p->vLines )
+ Vec_PtrFree( p->vLines );
+ if ( p->vModels )
+ {
+ Vec_PtrForEachEntry( p->vModels, pMod, i )
+ Io_MvModFree( pMod );
+ Vec_PtrFree( p->vModels );
+ }
+ Vec_PtrFree( p->vTokens );
+ Vec_PtrFree( p->vTokens2 );
+ Vec_StrFree( p->vFunc );
+ free( p );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Allocates the BLIF parsing structure for one model.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+static Io_MvMod_t * Io_MvModAlloc()
+{
+ Io_MvMod_t * p;
+ p = ALLOC( Io_MvMod_t, 1 );
+ memset( p, 0, sizeof(Io_MvMod_t) );
+ p->vInputs = Vec_PtrAlloc( 512 );
+ p->vOutputs = Vec_PtrAlloc( 512 );
+ p->vLatches = Vec_PtrAlloc( 512 );
+ p->vResets = Vec_PtrAlloc( 512 );
+ p->vNames = Vec_PtrAlloc( 512 );
+ p->vSubckts = Vec_PtrAlloc( 512 );
+ p->vMvs = Vec_PtrAlloc( 512 );
+ return p;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Allocates the BLIF parsing structure for one model.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+static void Io_MvModFree( Io_MvMod_t * p )
+{
+// if ( p->pNtk )
+// Abc_NtkDelete( p->pNtk );
+ Vec_PtrFree( p->vInputs );
+ Vec_PtrFree( p->vOutputs );
+ Vec_PtrFree( p->vLatches );
+ Vec_PtrFree( p->vResets );
+ Vec_PtrFree( p->vNames );
+ Vec_PtrFree( p->vSubckts );
+ Vec_PtrFree( p->vMvs );
+ free( p );
+}
+
+
+
+/**Function*************************************************************
+
+ Synopsis [Counts the number of given chars.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+static int Io_MvCountChars( char * pLine, char Char )
+{
+ char * pCur;
+ int Counter = 0;
+ for ( pCur = pLine; *pCur; pCur++ )
+ if ( *pCur == Char )
+ Counter++;
+ return Counter;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Returns the place where the arrow is hiding.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+static char * Io_MvFindArrow( char * pLine )
+{
+ char * pCur;
+ for ( pCur = pLine; *(pCur+1); pCur++ )
+ if ( *pCur == '-' && *(pCur+1) == '>' )
+ {
+ *pCur = ' ';
+ *(pCur+1) = ' ';
+ return pCur;
+ }
+ return NULL;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Collects the already split tokens.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+static void Io_MvCollectTokens( Vec_Ptr_t * vTokens, char * pInput, char * pOutput )
+{
+ char * pCur;
+ Vec_PtrClear( vTokens );
+ for ( pCur = pInput; pCur < pOutput; pCur++ )
+ {
+ if ( *pCur == 0 )
+ continue;
+ Vec_PtrPush( vTokens, pCur );
+ while ( *++pCur );
+ }
+}
+
+/**Function*************************************************************
+
+ Synopsis [Splits the line into tokens.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+static void Io_MvSplitIntoTokens( Vec_Ptr_t * vTokens, char * pLine, char Stop )
+{
+ char * pCur;
+ // clear spaces
+ for ( pCur = pLine; *pCur != Stop; pCur++ )
+ if ( Io_MvCharIsSpace(*pCur) )
+ *pCur = 0;
+ // collect tokens
+ Io_MvCollectTokens( vTokens, pLine, pCur );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Splits the line into tokens when .default may be present.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+static void Io_MvSplitIntoTokensMv( Vec_Ptr_t * vTokens, char * pLine )
+{
+ char * pCur;
+ // clear spaces
+ for ( pCur = pLine; *pCur != '.' || *(pCur+1) == 'd'; pCur++ )
+ if ( Io_MvCharIsSpace(*pCur) )
+ *pCur = 0;
+ // collect tokens
+ Io_MvCollectTokens( vTokens, pLine, pCur );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Splits the line into tokens.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+static void Io_MvSplitIntoTokensAndClear( Vec_Ptr_t * vTokens, char * pLine, char Stop, char Char )
+{
+ char * pCur;
+ // clear spaces
+ for ( pCur = pLine; *pCur != Stop; pCur++ )
+ if ( Io_MvCharIsSpace(*pCur) || *pCur == Char )
+ *pCur = 0;
+ // collect tokens
+ Io_MvCollectTokens( vTokens, pLine, pCur );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Returns the 1-based number of the line in which the token occurs.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+static int Io_MvGetLine( Io_MvMan_t * p, char * pToken )
+{
+ char * pLine;
+ int i;
+ Vec_PtrForEachEntry( p->vLines, pLine, i )
+ if ( pToken < pLine )
+ return i;
+ return -1;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Reads the file into a character buffer.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+static char * Io_MvLoadFile( char * pFileName )
+{
+ FILE * pFile;
+ int nFileSize;
+ char * pContents;
+ pFile = fopen( pFileName, "rb" );
+ if ( pFile == NULL )
+ {
+ printf( "Io_MvLoadFile(): The file is unavailable (absent or open).\n" );
+ return NULL;
+ }
+ fseek( pFile, 0, SEEK_END );
+ nFileSize = ftell( pFile );
+ if ( nFileSize == 0 )
+ {
+ printf( "Io_MvLoadFile(): The file is empty.\n" );
+ return NULL;
+ }
+ pContents = ALLOC( char, nFileSize + 10 );
+ rewind( pFile );
+ fread( pContents, nFileSize, 1, pFile );
+ fclose( pFile );
+ // finish off the file with the spare .end line
+ // some benchmarks suddenly break off without this line
+ strcpy( pContents + nFileSize, "\n.end\n" );
+ return pContents;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Prepares the parsing.]
+
+ Description [Performs several preliminary operations:
+ - Cuts the file buffer into separate lines.
+ - Removes comments and line extenders.
+ - Sorts lines by directives.
+ - Estimates the number of objects.
+ - Allocates room for the objects.
+ - Allocates room for the hash table.]
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+static void Io_MvReadPreparse( Io_MvMan_t * p )
+{
+ char * pCur, * pPrev;
+ int i, fComment = 0;
+ // parse the buffer into lines and remove comments
+ Vec_PtrPush( p->vLines, p->pBuffer );
+ for ( pCur = p->pBuffer; *pCur; pCur++ )
+ {
+ if ( *pCur == '\n' )
+ {
+ *pCur = 0;
+// if ( *(pCur-1) == '\r' )
+// *(pCur-1) = 0;
+ fComment = 0;
+ Vec_PtrPush( p->vLines, pCur + 1 );
+ }
+ else if ( *pCur == '#' )
+ fComment = 1;
+ // remove comments
+ if ( fComment )
+ *pCur = 0;
+ }
+
+ // unfold the line extensions and sort lines by directive
+ Vec_PtrForEachEntry( p->vLines, pCur, i )
+ {
+ if ( *pCur == 0 )
+ continue;
+ // find previous non-space character
+ for ( pPrev = pCur - 2; pPrev >= p->pBuffer; pPrev-- )
+ if ( !Io_MvCharIsSpace(*pPrev) )
+ break;
+ // if it is the line extender, overwrite it with spaces
+ if ( *pPrev == '\\' )
+ {
+ for ( ; *pPrev; pPrev++ )
+ *pPrev = ' ';
+ *pPrev = ' ';
+ continue;
+ }
+ // skip spaces at the beginning of the line
+ while ( Io_MvCharIsSpace(*pCur++) );
+ // parse directives
+ if ( *(pCur-1) != '.' )
+ continue;
+ if ( !strncmp(pCur, "names", 5) || !strncmp(pCur, "table", 5) || !strncmp(pCur, "gate", 4) )
+ Vec_PtrPush( p->pLatest->vNames, pCur );
+ else if ( p->fBlifMv && (!strncmp(pCur, "def ", 4) || !strncmp(pCur, "default ", 8)) )
+ continue;
+ else if ( !strncmp(pCur, "latch", 5) )
+ Vec_PtrPush( p->pLatest->vLatches, pCur );
+ else if ( !strncmp(pCur, "r ", 2) || !strncmp(pCur, "reset ", 6) )
+ Vec_PtrPush( p->pLatest->vResets, pCur );
+ else if ( !strncmp(pCur, "inputs", 6) )
+ Vec_PtrPush( p->pLatest->vInputs, pCur );
+ else if ( !strncmp(pCur, "outputs", 7) )
+ Vec_PtrPush( p->pLatest->vOutputs, pCur );
+ else if ( !strncmp(pCur, "subckt", 6) )
+ Vec_PtrPush( p->pLatest->vSubckts, pCur );
+ else if ( p->fBlifMv && !strncmp(pCur, "mv", 2) )
+ Vec_PtrPush( p->pLatest->vMvs, pCur );
+ else if ( !strncmp(pCur, "blackbox", 8) )
+ p->pLatest->fBlackBox = 1;
+ else if ( !strncmp(pCur, "model", 5) )
+ {
+ p->pLatest = Io_MvModAlloc();
+ p->pLatest->pName = pCur;
+ p->pLatest->pMan = p;
+ }
+ else if ( !strncmp(pCur, "end", 3) )
+ {
+ if ( p->pLatest )
+ Vec_PtrPush( p->vModels, p->pLatest );
+ p->pLatest = NULL;
+ }
+ else if ( !strncmp(pCur, "exdc", 4) )
+ {
+ fprintf( stdout, "Line %d: Skipping EXDC network.\n", Io_MvGetLine(p, pCur) );
+ break;
+ }
+ else if ( !strncmp(pCur, "delay", 5) )
+ {}
+ else if ( !strncmp(pCur, "input_arrival", 13) )
+ {}
+ else if ( !strncmp(pCur, "output_required", 15) )
+ {}
+ else
+ {
+ pCur--;
+ if ( pCur[strlen(pCur)-1] == '\r' )
+ pCur[strlen(pCur)-1] = 0;
+ fprintf( stdout, "Line %d: Skipping line \"%s\".\n", Io_MvGetLine(p, pCur), pCur );
+ }
+ }
+}
+
+/**Function*************************************************************
+
+ Synopsis [Parses interfaces of the models.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+static void Io_MvReadInterfaces( Io_MvMan_t * p )
+{
+ Io_MvMod_t * pMod;
+ char * pLine;
+ int i, k;
+ // iterate through the models
+ Vec_PtrForEachEntry( p->vModels, pMod, i )
+ {
+ // parse the model
+ if ( !Io_MvParseLineModel( pMod, pMod->pName ) )
+ return;
+ // add model to the design
+ if ( !Abc_LibAddModel( p->pDesign, pMod->pNtk ) )
+ {
+ sprintf( p->sError, "Line %d: Model %s is defined twice.", Io_MvGetLine(p, pMod->pName), pMod->pName );
+ return;
+ }
+ // parse the inputs
+ Vec_PtrForEachEntry( pMod->vInputs, pLine, k )
+ if ( !Io_MvParseLineInputs( pMod, pLine ) )
+ return;
+ // parse the outputs
+ Vec_PtrForEachEntry( pMod->vOutputs, pLine, k )
+ if ( !Io_MvParseLineOutputs( pMod, pLine ) )
+ return;
+ }
+}
+
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+static Abc_Lib_t * Io_MvParse( Io_MvMan_t * p )
+{
+ Abc_Lib_t * pDesign;
+ Io_MvMod_t * pMod;
+ char * pLine;
+ int i, k;
+ // iterate through the models
+ Vec_PtrForEachEntry( p->vModels, pMod, i )
+ {
+ // check if there any MV lines
+ if ( Vec_PtrSize(pMod->vMvs) > 0 )
+ Abc_NtkStartMvVars( pMod->pNtk );
+ // parse the mv lines
+ Vec_PtrForEachEntry( pMod->vMvs, pLine, k )
+ if ( !Io_MvParseLineMv( pMod, pLine ) )
+ return NULL;
+ // if reset lines are used there should be the same number of them as latches
+ if ( Vec_PtrSize(pMod->vResets) > 0 )
+ {
+ if ( Vec_PtrSize(pMod->vLatches) != Vec_PtrSize(pMod->vResets) )
+ {
+ sprintf( p->sError, "Line %d: Model %s has different number of latches (%d) and reset nodes (%d).",
+ Io_MvGetLine(p, pMod->pName), Abc_NtkName(pMod->pNtk), Vec_PtrSize(pMod->vLatches), Vec_PtrSize(pMod->vResets) );
+ return NULL;
+ }
+ // create binary latch with 1-data and 0-init
+ if ( p->fUseReset )
+ pMod->pResetLatch = Io_ReadCreateResetLatch( pMod->pNtk, p->fBlifMv );
+ }
+ // parse the latches
+ Vec_PtrForEachEntry( pMod->vLatches, pLine, k )
+ if ( !Io_MvParseLineLatch( pMod, pLine ) )
+ return NULL;
+ // parse the reset lines
+ if ( p->fUseReset )
+ Vec_PtrForEachEntry( pMod->vResets, pLine, k )
+ if ( !Io_MvParseLineNamesMv( pMod, pLine, 1 ) )
+ return NULL;
+ // parse the nodes
+ if ( p->fBlifMv )
+ {
+ Vec_PtrForEachEntry( pMod->vNames, pLine, k )
+ if ( !Io_MvParseLineNamesMv( pMod, pLine, 0 ) )
+ return NULL;
+ }
+ else
+ {
+ Vec_PtrForEachEntry( pMod->vNames, pLine, k )
+ if ( !Io_MvParseLineNamesBlif( pMod, pLine ) )
+ return NULL;
+ }
+ // parse the subcircuits
+ Vec_PtrForEachEntry( pMod->vSubckts, pLine, k )
+ if ( !Io_MvParseLineSubckt( pMod, pLine ) )
+ return NULL;
+ // finalize the network
+ Abc_NtkFinalizeRead( pMod->pNtk );
+ }
+ if ( p->nNDnodes )
+// printf( "Warning: The parser added %d PIs to replace non-deterministic nodes.\n", p->nNDnodes );
+ printf( "Warning: The parser added %d constant 0 nodes to replace non-deterministic nodes.\n", p->nNDnodes );
+ // return the network
+ pDesign = p->pDesign;
+ p->pDesign = NULL;
+ return pDesign;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Parses the model line.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+static int Io_MvParseLineModel( Io_MvMod_t * p, char * pLine )
+{
+ Vec_Ptr_t * vTokens = p->pMan->vTokens;
+ char * pToken;
+ Io_MvSplitIntoTokens( vTokens, pLine, '\0' );
+ pToken = Vec_PtrEntry( vTokens, 0 );
+ assert( !strcmp(pToken, "model") );
+ if ( Vec_PtrSize(vTokens) != 2 )
+ {
+ sprintf( p->pMan->sError, "Line %d: Model line has %d entries while it should have 2.", Io_MvGetLine(p->pMan, pToken), Vec_PtrSize(vTokens) );
+ return 0;
+ }
+ if ( p->fBlackBox )
+ p->pNtk = Abc_NtkAlloc( ABC_NTK_NETLIST, ABC_FUNC_BLACKBOX, 1 );
+ else if ( p->pMan->fBlifMv )
+ p->pNtk = Abc_NtkAlloc( ABC_NTK_NETLIST, ABC_FUNC_BLIFMV, 1 );
+ else
+ p->pNtk = Abc_NtkAlloc( ABC_NTK_NETLIST, ABC_FUNC_SOP, 1 );
+ p->pNtk->pName = Extra_UtilStrsav( Vec_PtrEntry(vTokens, 1) );
+ return 1;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Parses the inputs line.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+static int Io_MvParseLineInputs( Io_MvMod_t * p, char * pLine )
+{
+ Vec_Ptr_t * vTokens = p->pMan->vTokens;
+ char * pToken;
+ int i;
+ Io_MvSplitIntoTokens( vTokens, pLine, '\0' );
+ pToken = Vec_PtrEntry(vTokens, 0);
+ assert( !strcmp(pToken, "inputs") );
+ Vec_PtrForEachEntryStart( vTokens, pToken, i, 1 )
+ Io_ReadCreatePi( p->pNtk, pToken );
+ return 1;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Parses the outputs line.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+static int Io_MvParseLineOutputs( Io_MvMod_t * p, char * pLine )
+{
+ Vec_Ptr_t * vTokens = p->pMan->vTokens;
+ char * pToken;
+ int i;
+ Io_MvSplitIntoTokens( vTokens, pLine, '\0' );
+ pToken = Vec_PtrEntry(vTokens, 0);
+ assert( !strcmp(pToken, "outputs") );
+ Vec_PtrForEachEntryStart( vTokens, pToken, i, 1 )
+ Io_ReadCreatePo( p->pNtk, pToken );
+ return 1;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Parses the latches line.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+static int Io_MvParseLineLatch( Io_MvMod_t * p, char * pLine )
+{
+ Vec_Ptr_t * vTokens = p->pMan->vTokens;
+ Abc_Obj_t * pObj, * pNet;
+ char * pToken;
+ int Init;
+ Io_MvSplitIntoTokens( vTokens, pLine, '\0' );
+ pToken = Vec_PtrEntry(vTokens,0);
+ assert( !strcmp(pToken, "latch") );
+ if ( Vec_PtrSize(vTokens) < 3 )
+ {
+ sprintf( p->pMan->sError, "Line %d: Latch does not have input name and output name.", Io_MvGetLine(p->pMan, pToken) );
+ return 0;
+ }
+ // create latch
+ if ( p->pResetLatch == NULL )
+ {
+ pObj = Io_ReadCreateLatch( p->pNtk, Vec_PtrEntry(vTokens,1), Vec_PtrEntry(vTokens,2) );
+ // get initial value
+ if ( p->pMan->fBlifMv )
+ Abc_LatchSetInit0( pObj );
+ else
+ {
+ if ( Vec_PtrSize(vTokens) > 3 )
+ Init = atoi( Vec_PtrEntryLast(vTokens) );
+ else
+ Init = 2;
+ if ( Init < 0 || Init > 2 )
+ {
+ sprintf( p->pMan->sError, "Line %d: Initial state of the latch is incorrect \"%s\".", Io_MvGetLine(p->pMan, pToken), Vec_PtrEntry(vTokens,3) );
+ return 0;
+ }
+ if ( Init == 0 )
+ Abc_LatchSetInit0( pObj );
+ else if ( Init == 1 )
+ Abc_LatchSetInit1( pObj );
+ else // if ( Init == 2 )
+ Abc_LatchSetInitDc( pObj );
+ }
+ }
+ else
+ {
+ // get the net corresponding to the output of the latch
+ pNet = Abc_NtkFindOrCreateNet( p->pNtk, Vec_PtrEntry(vTokens,2) );
+ // get the net corresponding to the latch output (feeding into reset MUX)
+ pNet = Abc_NtkFindOrCreateNet( p->pNtk, Abc_ObjNameSuffix(pNet, "_out") );
+ // create latch
+ pObj = Io_ReadCreateLatch( p->pNtk, Vec_PtrEntry(vTokens,1), Abc_ObjName(pNet) );
+ Abc_LatchSetInit0( pObj );
+ }
+ return 1;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Parses the subckt line.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+static int Io_MvParseLineSubckt( Io_MvMod_t * p, char * pLine )
+{
+ Vec_Ptr_t * vTokens = p->pMan->vTokens;
+ Abc_Ntk_t * pModel;
+ Abc_Obj_t * pBox, * pNet, * pTerm;
+ char * pToken, * pName, ** ppNames;
+ int nEquals, i, k;
+
+ // split the line into tokens
+ nEquals = Io_MvCountChars( pLine, '=' );
+ Io_MvSplitIntoTokensAndClear( vTokens, pLine, '\0', '=' );
+ pToken = Vec_PtrEntry(vTokens,0);
+ assert( !strcmp(pToken, "subckt") );
+
+ // get the model for this box
+ pName = Vec_PtrEntry(vTokens,1);
+ pModel = Abc_LibFindModelByName( p->pMan->pDesign, pName );
+ if ( pModel == NULL )
+ {
+ sprintf( p->pMan->sError, "Line %d: Cannot find the model for subcircuit %s.", Io_MvGetLine(p->pMan, pToken), pName );
+ return 0;
+ }
+
+ // check if the number of tokens is correct
+ if ( nEquals != Abc_NtkPiNum(pModel) + Abc_NtkPoNum(pModel) )
+ {
+ sprintf( p->pMan->sError, "Line %d: The number of ports (%d) in .subckt differs from the sum of PIs and POs of the model (%d).",
+ Io_MvGetLine(p->pMan, pToken), nEquals, Abc_NtkPiNum(pModel) + Abc_NtkPoNum(pModel) );
+ return 0;
+ }
+
+ // get the names
+ ppNames = (char **)Vec_PtrArray(vTokens) + 2 + p->pMan->fBlifMv;
+
+ // create the box with these terminals
+ if ( Abc_NtkHasBlackbox(pModel) )
+ pBox = Abc_NtkCreateBlackbox( p->pNtk );
+ else
+ pBox = Abc_NtkCreateWhitebox( p->pNtk );
+ pBox->pData = pModel;
+ if ( p->pMan->fBlifMv )
+ Abc_ObjAssignName( pBox, Vec_PtrEntry(vTokens,2), NULL );
+ Abc_NtkForEachPi( pModel, pTerm, i )
+ {
+ // find this terminal among the formal inputs of the subcircuit
+ pName = Abc_ObjName(Abc_ObjFanout0(pTerm));
+ for ( k = 0; k < nEquals; k++ )
+ if ( !strcmp( ppNames[2*k], pName ) )
+ break;
+ if ( k == nEquals )
+ {
+ sprintf( p->pMan->sError, "Line %d: Cannot find PI \"%s\" of the model \"%s\" as a formal input of the subcircuit.",
+ Io_MvGetLine(p->pMan, pToken), pName, Abc_NtkName(pModel) );
+ return 0;
+ }
+ // create the BI with the actual name
+ pNet = Abc_NtkFindOrCreateNet( p->pNtk, ppNames[2*k+1] );
+ pTerm = Abc_NtkCreateBi( p->pNtk );
+ Abc_ObjAddFanin( pBox, pTerm );
+ Abc_ObjAddFanin( pTerm, pNet );
+ }
+ Abc_NtkForEachPo( pModel, pTerm, i )
+ {
+ // find this terminal among the formal outputs of the subcircuit
+ pName = Abc_ObjName(Abc_ObjFanin0(pTerm));
+ for ( k = 0; k < nEquals; k++ )
+ if ( !strcmp( ppNames[2*k], pName ) )
+ break;
+ if ( k == nEquals )
+ {
+ sprintf( p->pMan->sError, "Line %d: Cannot find PO \"%s\" of the modell \"%s\" as a formal output of the subcircuit.",
+ Io_MvGetLine(p->pMan, pToken), pName, Abc_NtkName(pModel) );
+ return 0;
+ }
+ // create the BI with the actual name
+ pNet = Abc_NtkFindOrCreateNet( p->pNtk, ppNames[2*k+1] );
+ pTerm = Abc_NtkCreateBo( p->pNtk );
+ Abc_ObjAddFanin( pNet, pTerm );
+ Abc_ObjAddFanin( pTerm, pBox );
+ }
+ return 1;
+}
+
+
+/**Function*************************************************************
+
+ Synopsis [Parses the mv line.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+static int Io_MvParseLineMv( Io_MvMod_t * p, char * pLine )
+{
+ Vec_Ptr_t * vTokens = p->pMan->vTokens;
+ Abc_Obj_t * pObj;
+ Io_MvVar_t * pVar;
+ Extra_MmFlex_t * pFlex;
+ char * pName;
+ int nCommas, nValues, i, k;
+ // count commas and get the tokens
+ nCommas = Io_MvCountChars( pLine, ',' );
+ Io_MvSplitIntoTokensAndClear( vTokens, pLine, '\0', ',' );
+ pName = Vec_PtrEntry(vTokens,0);
+ assert( !strcmp(pName, "mv") );
+ // get the number of values
+ if ( Vec_PtrSize(vTokens) <= nCommas + 2 )
+ {
+ sprintf( p->pMan->sError, "Line %d: The number of values in not specified in .mv line.", Io_MvGetLine(p->pMan, pName), pName );
+ return 0;
+ }
+ nValues = atoi( Vec_PtrEntry(vTokens,nCommas+2) );
+ if ( nValues < 2 || nValues > IO_BLIFMV_MAXVALUES )
+ {
+ sprintf( p->pMan->sError, "Line %d: The number of values (%d) is incorrect (should be >= 2 and <= %d).",
+ Io_MvGetLine(p->pMan, pName), nValues, IO_BLIFMV_MAXVALUES );
+ return 0;
+ }
+ // if there is no symbolic values, quit
+ if ( nValues == 2 && Vec_PtrSize(vTokens) == nCommas + 3 )
+ return 1;
+ if ( Vec_PtrSize(vTokens) > nCommas + 3 && Vec_PtrSize(vTokens) - (nCommas + 3) != nValues )
+ {
+ sprintf( p->pMan->sError, "Line %d: Wrong number (%d) of symbolic value names (should be %d).",
+ Io_MvGetLine(p->pMan, pName), Vec_PtrSize(vTokens) - (nCommas + 3), nValues );
+ return 0;
+ }
+ // go through variables
+ pFlex = Abc_NtkMvVarMan( p->pNtk );
+ for ( i = 0; i <= nCommas; i++ )
+ {
+ pName = Vec_PtrEntry( vTokens, i+1 );
+ pObj = Abc_NtkFindOrCreateNet( p->pNtk, pName );
+ // allocate variable
+ pVar = (Io_MvVar_t *)Extra_MmFlexEntryFetch( pFlex, sizeof(Io_MvVar_t) );
+ pVar->nValues = nValues;
+ pVar->pNames = NULL;
+ // create names
+ if ( Vec_PtrSize(vTokens) > nCommas + 3 )
+ {
+ pVar->pNames = (char **)Extra_MmFlexEntryFetch( pFlex, sizeof(char *) * nValues );
+ Vec_PtrForEachEntryStart( vTokens, pName, k, nCommas + 3 )
+ {
+ pVar->pNames[k-(nCommas + 3)] = (char *)Extra_MmFlexEntryFetch( pFlex, strlen(pName) + 1 );
+ strcpy( pVar->pNames[k-(nCommas + 3)], pName );
+ }
+ }
+ // save the variable
+ Abc_ObjSetMvVar( pObj, pVar );
+ }
+ // make sure the names are unique
+ if ( pVar->pNames )
+ {
+ for ( i = 0; i < nValues; i++ )
+ for ( k = i+1; k < nValues; k++ )
+ if ( !strcmp(pVar->pNames[i], pVar->pNames[k]) )
+ {
+ pName = Vec_PtrEntry(vTokens,0);
+ sprintf( p->pMan->sError, "Line %d: Symbolic value name \"%s\" is repeated in .mv line.",
+ Io_MvGetLine(p->pMan, pName), pVar->pNames[i] );
+ return 0;
+ }
+ }
+ return 1;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Writes the values into the BLIF-MV representation for the node.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+static int Io_MvWriteValues( Abc_Obj_t * pNode, Vec_Str_t * vFunc )
+{
+ char Buffer[10];
+ Abc_Obj_t * pFanin;
+ int i;
+ // add the fanin number of values
+ Abc_ObjForEachFanin( pNode, pFanin, i )
+ {
+ sprintf( Buffer, "%d", Abc_ObjMvVarNum(pFanin) );
+ Vec_StrAppend( vFunc, Buffer );
+ Vec_StrPush( vFunc, ' ' );
+ }
+ // add the node number of values
+ sprintf( Buffer, "%d", Abc_ObjMvVarNum(Abc_ObjFanout0(pNode)) );
+ Vec_StrAppend( vFunc, Buffer );
+ Vec_StrPush( vFunc, '\n' );
+ return 1;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Translated one literal.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+static int Io_MvParseLiteralMv( Io_MvMod_t * p, Abc_Obj_t * pNode, char * pToken, Vec_Str_t * vFunc, int iLit )
+{
+ char Buffer[10];
+ Io_MvVar_t * pVar;
+ Abc_Obj_t * pFanin, * pNet;
+ char * pCur, * pNext;
+ int i;
+ // consider the equality literal
+ if ( pToken[0] == '=' )
+ {
+ // find the fanins
+ Abc_ObjForEachFanin( pNode, pFanin, i )
+ if ( !strcmp( Abc_ObjName(pFanin), pToken + 1 ) )
+ break;
+ if ( i == Abc_ObjFaninNum(pNode) )
+ {
+ sprintf( p->pMan->sError, "Line %d: Node name in the table \"%s\" cannot be found on .names line.",
+ Io_MvGetLine(p->pMan, pToken), pToken + 1 );
+ return 0;
+ }
+ Vec_StrPush( vFunc, '=' );
+ sprintf( Buffer, "%d", i );
+ Vec_StrAppend( vFunc, Buffer );
+ Vec_StrPush( vFunc, (char)((iLit == -1)? '\n' : ' ') );
+ return 1;
+ }
+ // consider regular literal
+ assert( iLit < Abc_ObjFaninNum(pNode) );
+ pNet = iLit >= 0 ? Abc_ObjFanin(pNode, iLit) : Abc_ObjFanout0(pNode);
+ pVar = Abc_ObjMvVar( pNet );
+ // if the var is absent or has no symbolic values quit
+ if ( pVar == NULL || pVar->pNames == NULL )
+ {
+ Vec_StrAppend( vFunc, pToken );
+ Vec_StrPush( vFunc, (char)((iLit == -1)? '\n' : ' ') );
+ return 1;
+ }
+ // parse the literal using symbolic values
+ for ( pCur = pToken; *pCur; pCur++ )
+ {
+ if ( Io_MvCharIsMvSymb(*pCur) )
+ {
+ Vec_StrPush( vFunc, *pCur );
+ continue;
+ }
+ // find the next MvSymb char
+ for ( pNext = pCur+1; *pNext; pNext++ )
+ if ( Io_MvCharIsMvSymb(*pNext) )
+ break;
+ // look for the value name
+ for ( i = 0; i < pVar->nValues; i++ )
+ if ( !strncmp( pVar->pNames[i], pCur, pNext-pCur ) )
+ break;
+ if ( i == pVar->nValues )
+ {
+ *pNext = 0;
+ sprintf( p->pMan->sError, "Line %d: Cannot find value name \"%s\" among the value names of variable \"%s\".",
+ Io_MvGetLine(p->pMan, pToken), pCur, Abc_ObjName(pNet) );
+ return 0;
+ }
+ // value name is found
+ sprintf( Buffer, "%d", i );
+ Vec_StrAppend( vFunc, Buffer );
+ // update the pointer
+ pCur = pNext - 1;
+ }
+ Vec_StrPush( vFunc, (char)((iLit == -1)? '\n' : ' ') );
+ return 1;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Constructs the MV-SOP cover from the file parsing info.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+static char * Io_MvParseTableMv( Io_MvMod_t * p, Abc_Obj_t * pNode, Vec_Ptr_t * vTokens2, int nInputs, int nOutputs, int iOut )
+{
+ Vec_Str_t * vFunc = p->pMan->vFunc;
+ char * pFirst, * pToken;
+ int iStart, i;
+ // prepare the place for the cover
+ Vec_StrClear( vFunc );
+ // write the number of values
+// Io_MvWriteValues( pNode, vFunc );
+ // get the first token
+ pFirst = Vec_PtrEntry( vTokens2, 0 );
+ if ( pFirst[0] == '.' )
+ {
+ // write the default literal
+ Vec_StrPush( vFunc, 'd' );
+ pToken = Vec_PtrEntry(vTokens2, 1 + iOut);
+ if ( !Io_MvParseLiteralMv( p, pNode, pToken, vFunc, -1 ) )
+ return NULL;
+ iStart = 1 + nOutputs;
+ }
+ else
+ iStart = 0;
+ // write the remaining literals
+ while ( iStart < Vec_PtrSize(vTokens2) )
+ {
+ // input literals
+ for ( i = 0; i < nInputs; i++ )
+ {
+ pToken = Vec_PtrEntry( vTokens2, iStart + i );
+ if ( !Io_MvParseLiteralMv( p, pNode, pToken, vFunc, i ) )
+ return NULL;
+ }
+ // output literal
+ pToken = Vec_PtrEntry( vTokens2, iStart + nInputs + iOut );
+ if ( !Io_MvParseLiteralMv( p, pNode, pToken, vFunc, -1 ) )
+ return NULL;
+ // update the counter
+ iStart += nInputs + nOutputs;
+ }
+ Vec_StrPush( vFunc, '\0' );
+ return Vec_StrArray( vFunc );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Adds reset circuitry corresponding to latch with pName.]
+
+ Description [Returns the reset node's net.]
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+static Abc_Obj_t * Io_MvParseAddResetCircuit( Io_MvMod_t * p, char * pName )
+{
+ char Buffer[50];
+ Abc_Obj_t * pNode, * pData0Net, * pData1Net, * pResetLONet, * pOutNet;
+ Io_MvVar_t * pVar;
+ // make sure the reset latch exists
+ assert( p->pResetLatch != NULL );
+ // get the reset net
+ pResetLONet = Abc_ObjFanout0(Abc_ObjFanout0(p->pResetLatch));
+ // get the output net
+ pOutNet = Abc_NtkFindOrCreateNet( p->pNtk, pName );
+ // get the data nets
+ pData0Net = Abc_NtkFindOrCreateNet( p->pNtk, Abc_ObjNameSuffix(pOutNet, "_reset") );
+ pData1Net = Abc_NtkFindOrCreateNet( p->pNtk, Abc_ObjNameSuffix(pOutNet, "_out") );
+ // duplicate MV variables
+ if ( Abc_NtkMvVar(p->pNtk) )
+ {
+ pVar = Abc_ObjMvVar( pOutNet );
+ Abc_ObjSetMvVar( pData0Net, Abc_NtkMvVarDup(p->pNtk, pVar) );
+ Abc_ObjSetMvVar( pData1Net, Abc_NtkMvVarDup(p->pNtk, pVar) );
+ }
+ // create the node
+ pNode = Abc_NtkCreateNode( p->pNtk );
+ // create the output net
+ Abc_ObjAddFanin( pOutNet, pNode );
+ // create the function
+ if ( p->pMan->fBlifMv )
+ {
+// Vec_Att_t * p = Abc_NtkMvVar( pNtk );
+ int nValues = Abc_ObjMvVarNum(pOutNet);
+// sprintf( Buffer, "2 %d %d %d\n1 - - =1\n0 - - =2\n", nValues, nValues, nValues );
+ sprintf( Buffer, "1 - - =1\n0 - - =2\n" );
+ pNode->pData = Abc_SopRegister( p->pNtk->pManFunc, Buffer );
+ }
+ else
+ pNode->pData = Abc_SopCreateMux( p->pNtk->pManFunc );
+ // add nets
+ Abc_ObjAddFanin( pNode, pResetLONet );
+ Abc_ObjAddFanin( pNode, pData1Net );
+ Abc_ObjAddFanin( pNode, pData0Net );
+ return pData0Net;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Parses the nodes line.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+static int Io_MvParseLineNamesMvOne( Io_MvMod_t * p, Vec_Ptr_t * vTokens, Vec_Ptr_t * vTokens2, int nInputs, int nOutputs, int iOut, int fReset )
+{
+ Abc_Obj_t * pNet, * pNode;
+ char * pName;
+ // get the output name
+ pName = Vec_PtrEntry( vTokens, Vec_PtrSize(vTokens) - nOutputs + iOut );
+ // create the node
+ if ( fReset )
+ {
+ pNet = Abc_NtkFindNet( p->pNtk, pName );
+ if ( pNet == NULL )
+ {
+ sprintf( p->pMan->sError, "Line %d: Latch with output signal \"%s\" does not exist.", Io_MvGetLine(p->pMan, pName), pName );
+ return 0;
+ }
+/*
+ if ( !Abc_ObjIsBo(Abc_ObjFanin0(pNet)) )
+ {
+ sprintf( p->pMan->sError, "Line %d: Reset line \"%s\" defines signal that is not a latch output.", Io_MvGetLine(p->pMan, pName), pName );
+ return 0;
+ }
+*/
+ // construct the reset circuit and get the reset net feeding into it
+ pNet = Io_MvParseAddResetCircuit( p, pName );
+ // create fanins
+ pNode = Io_ReadCreateNode( p->pNtk, Abc_ObjName(pNet), (char **)(vTokens->pArray + 1), nInputs );
+ assert( nInputs == Vec_PtrSize(vTokens) - 2 );
+ }
+ else
+ {
+ pNet = Abc_NtkFindOrCreateNet( p->pNtk, pName );
+ if ( Abc_ObjFaninNum(pNet) > 0 )
+ {
+ sprintf( p->pMan->sError, "Line %d: Signal \"%s\" is defined more than once.", Io_MvGetLine(p->pMan, pName), pName );
+ return 0;
+ }
+ pNode = Io_ReadCreateNode( p->pNtk, pName, (char **)(vTokens->pArray + 1), nInputs );
+ }
+ // create the cover
+ pNode->pData = Io_MvParseTableMv( p, pNode, vTokens2, nInputs, nOutputs, iOut );
+ if ( pNode->pData == NULL )
+ return 0;
+ pNode->pData = Abc_SopRegister( p->pNtk->pManFunc, pNode->pData );
+//printf( "Finished parsing node \"%s\" with table:\n%s\n", pName, pNode->pData );
+ return 1;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Parses the nodes line.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+static int Io_MvParseLineNamesMv( Io_MvMod_t * p, char * pLine, int fReset )
+{
+ Vec_Ptr_t * vTokens = p->pMan->vTokens;
+ Vec_Ptr_t * vTokens2 = p->pMan->vTokens2;
+ Abc_Obj_t * pNet;
+ char * pName, * pFirst, * pArrow;
+ int nInputs, nOutputs, nLiterals, nLines, i;
+ assert( p->pMan->fBlifMv );
+ // get the arrow if it is present
+ pArrow = Io_MvFindArrow( pLine );
+ if ( !p->pMan->fBlifMv && pArrow )
+ {
+ sprintf( p->pMan->sError, "Line %d: Multi-output node symbol (->) in binary BLIF file.", Io_MvGetLine(p->pMan, pLine) );
+ return 0;
+ }
+ // split names line into tokens
+ Io_MvSplitIntoTokens( vTokens, pLine, '\0' );
+ if ( fReset )
+ assert( !strcmp(Vec_PtrEntry(vTokens,0), "r") || !strcmp(Vec_PtrEntry(vTokens,0), "reset") );
+ else
+ assert( !strcmp(Vec_PtrEntry(vTokens,0), "names") || !strcmp(Vec_PtrEntry(vTokens,0), "table") );
+ // find the number of inputs and outputs
+ nInputs = Vec_PtrSize(vTokens) - 2;
+ nOutputs = 1;
+ if ( pArrow != NULL )
+ {
+ for ( i = Vec_PtrSize(vTokens) - 2; i >= 1; i-- )
+ if ( pArrow < (char*)Vec_PtrEntry(vTokens,i) )
+ {
+ nInputs--;
+ nOutputs++;
+ }
+ }
+ // split table into tokens
+ pName = Vec_PtrEntryLast( vTokens );
+ Io_MvSplitIntoTokensMv( vTokens2, pName + strlen(pName) );
+ pFirst = Vec_PtrEntry( vTokens2, 0 );
+ if ( pFirst[0] == '.' )
+ {
+ assert( pFirst[1] == 'd' );
+ nLiterals = Vec_PtrSize(vTokens2) - 1 - nOutputs;
+ }
+ else
+ nLiterals = Vec_PtrSize(vTokens2);
+ // check the number of lines
+ if ( nLiterals % (nInputs + nOutputs) != 0 )
+ {
+ sprintf( p->pMan->sError, "Line %d: Wrong number of literals in the table of node \"%s\". (Spaces inside literals are not allowed.)", Io_MvGetLine(p->pMan, pFirst), pName );
+ return 0;
+ }
+ // check for the ND table
+ nLines = nLiterals / (nInputs + nOutputs);
+ if ( nInputs == 0 && nLines > 1 )
+ {
+ // add the outputs to the PIs
+ for ( i = 0; i < nOutputs; i++ )
+ {
+ pName = Vec_PtrEntry( vTokens, Vec_PtrSize(vTokens) - nOutputs + i );
+ // get the net corresponding to this node
+ pNet = Abc_NtkFindOrCreateNet(p->pNtk, pName);
+ if ( fReset )
+ {
+ assert( p->pResetLatch != NULL );
+ // construct the reset circuit and get the reset net feeding into it
+ pNet = Io_MvParseAddResetCircuit( p, pName );
+ }
+ // add the new PI node
+// Abc_ObjAddFanin( pNet, Abc_NtkCreatePi(p->pNtk) );
+// fprintf( stdout, "Io_ReadBlifMv(): Adding PI for internal non-deterministic node \"%s\".\n", pName );
+ p->pMan->nNDnodes++;
+ Abc_ObjAddFanin( pNet, Abc_NtkCreateNodeConst0(p->pNtk) );
+ }
+ return 1;
+ }
+ // iterate through the outputs
+ for ( i = 0; i < nOutputs; i++ )
+ {
+ if ( !Io_MvParseLineNamesMvOne( p, vTokens, vTokens2, nInputs, nOutputs, i, fReset ) )
+ return 0;
+ }
+ return 1;
+}
+
+
+/**Function*************************************************************
+
+ Synopsis [Constructs the SOP cover from the file parsing info.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+static char * Io_MvParseTableBlif( Io_MvMod_t * p, char * pTable, int nFanins )
+{
+ Vec_Ptr_t * vTokens = p->pMan->vTokens;
+ Vec_Str_t * vFunc = p->pMan->vFunc;
+ char * pProduct, * pOutput;
+ int i, Polarity = -1;
+
+ p->pMan->nTablesRead++;
+ // get the tokens
+ Io_MvSplitIntoTokens( vTokens, pTable, '.' );
+ if ( Vec_PtrSize(vTokens) == 0 )
+ return Abc_SopCreateConst0( p->pNtk->pManFunc );
+ if ( Vec_PtrSize(vTokens) == 1 )
+ {
+ pOutput = Vec_PtrEntry( vTokens, 0 );
+ if ( ((pOutput[0] - '0') & 0x8E) || pOutput[1] )
+ {
+ sprintf( p->pMan->sError, "Line %d: Constant table has wrong output value \"%s\".", Io_MvGetLine(p->pMan, pOutput), pOutput );
+ return NULL;
+ }
+ return pOutput[0] == '0' ? Abc_SopCreateConst0(p->pNtk->pManFunc) : Abc_SopCreateConst1(p->pNtk->pManFunc);
+ }
+ pProduct = Vec_PtrEntry( vTokens, 0 );
+ if ( Vec_PtrSize(vTokens) % 2 == 1 )
+ {
+ sprintf( p->pMan->sError, "Line %d: Table has odd number of tokens (%d).", Io_MvGetLine(p->pMan, pProduct), Vec_PtrSize(vTokens) );
+ return NULL;
+ }
+ // parse the table
+ Vec_StrClear( vFunc );
+ for ( i = 0; i < Vec_PtrSize(vTokens)/2; i++ )
+ {
+ pProduct = Vec_PtrEntry( vTokens, 2*i + 0 );
+ pOutput = Vec_PtrEntry( vTokens, 2*i + 1 );
+ if ( strlen(pProduct) != (unsigned)nFanins )
+ {
+ sprintf( p->pMan->sError, "Line %d: Cube \"%s\" has size different from the fanin count (%d).", Io_MvGetLine(p->pMan, pProduct), pProduct, nFanins );
+ return NULL;
+ }
+ if ( ((pOutput[0] - '0') & 0x8E) || pOutput[1] )
+ {
+ sprintf( p->pMan->sError, "Line %d: Output value \"%s\" is incorrect.", Io_MvGetLine(p->pMan, pProduct), pOutput );
+ return NULL;
+ }
+ if ( Polarity == -1 )
+ Polarity = pOutput[0] - '0';
+ else if ( Polarity != pOutput[0] - '0' )
+ {
+ sprintf( p->pMan->sError, "Line %d: Output value \"%s\" differs from the value in the first line of the table (%d).", Io_MvGetLine(p->pMan, pProduct), pOutput, Polarity );
+ return NULL;
+ }
+ // parse one product
+ Vec_StrAppend( vFunc, pProduct );
+ Vec_StrPush( vFunc, ' ' );
+ Vec_StrPush( vFunc, pOutput[0] );
+ Vec_StrPush( vFunc, '\n' );
+ }
+ Vec_StrPush( vFunc, '\0' );
+ return Vec_StrArray( vFunc );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Parses the nodes line.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+static int Io_MvParseLineNamesBlif( Io_MvMod_t * p, char * pLine )
+{
+ Vec_Ptr_t * vTokens = p->pMan->vTokens;
+ Abc_Obj_t * pNet, * pNode;
+ char * pName;
+ assert( !p->pMan->fBlifMv );
+ Io_MvSplitIntoTokens( vTokens, pLine, '\0' );
+ // parse the mapped node
+ if ( !strcmp(Vec_PtrEntry(vTokens,0), "gate") )
+ return Io_MvParseLineGateBlif( p, vTokens );
+ // parse the regular name line
+ assert( !strcmp(Vec_PtrEntry(vTokens,0), "names") );
+ pName = Vec_PtrEntryLast( vTokens );
+ pNet = Abc_NtkFindOrCreateNet( p->pNtk, pName );
+ if ( Abc_ObjFaninNum(pNet) > 0 )
+ {
+ sprintf( p->pMan->sError, "Line %d: Signal \"%s\" is defined more than once.", Io_MvGetLine(p->pMan, pName), pName );
+ return 0;
+ }
+ // create fanins
+ pNode = Io_ReadCreateNode( p->pNtk, pName, (char **)(vTokens->pArray + 1), Vec_PtrSize(vTokens) - 2 );
+ // parse the table of this node
+ pNode->pData = Io_MvParseTableBlif( p, pName + strlen(pName), Abc_ObjFaninNum(pNode) );
+ if ( pNode->pData == NULL )
+ return 0;
+ pNode->pData = Abc_SopRegister( p->pNtk->pManFunc, pNode->pData );
+ return 1;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Duplicate the MV variable.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Io_MvVar_t * Abc_NtkMvVarDup( Abc_Ntk_t * pNtk, Io_MvVar_t * pVar )
+{
+ Extra_MmFlex_t * pFlex;
+ Io_MvVar_t * pVarDup;
+ int i;
+ if ( pVar == NULL )
+ return NULL;
+ pFlex = Abc_NtkMvVarMan( pNtk );
+ assert( pFlex != NULL );
+ pVarDup = (Io_MvVar_t *)Extra_MmFlexEntryFetch( pFlex, sizeof(Io_MvVar_t) );
+ pVarDup->nValues = pVar->nValues;
+ pVarDup->pNames = NULL;
+ if ( pVar->pNames == NULL )
+ return pVarDup;
+ pVarDup->pNames = (char **)Extra_MmFlexEntryFetch( pFlex, sizeof(char *) * pVar->nValues );
+ for ( i = 0; i < pVar->nValues; i++ )
+ {
+ pVarDup->pNames[i] = (char *)Extra_MmFlexEntryFetch( pFlex, strlen(pVar->pNames[i]) + 1 );
+ strcpy( pVarDup->pNames[i], pVar->pNames[i] );
+ }
+ return pVarDup;
+}
+
+
+#include "mio.h"
+#include "main.h"
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+static char * Io_ReadBlifCleanName( char * pName )
+{
+ int i, Length;
+ Length = strlen(pName);
+ for ( i = 0; i < Length; i++ )
+ if ( pName[i] == '=' )
+ return pName + i + 1;
+ return NULL;
+}
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+static int Io_MvParseLineGateBlif( Io_MvMod_t * p, Vec_Ptr_t * vTokens )
+{
+ Mio_Library_t * pGenlib;
+ Mio_Gate_t * pGate;
+ Abc_Obj_t * pNode;
+ char ** ppNames, * pName;
+ int i, nNames;
+
+ pName = vTokens->pArray[0];
+
+ // check that the library is available
+ pGenlib = Abc_FrameReadLibGen();
+ if ( pGenlib == NULL )
+ {
+ sprintf( p->pMan->sError, "Line %d: The current library is not available.", Io_MvGetLine(p->pMan, pName) );
+ return 0;
+ }
+
+ // create a new node and add it to the network
+ if ( vTokens->nSize < 2 )
+ {
+ sprintf( p->pMan->sError, "Line %d: The .gate line has less than two tokens.", Io_MvGetLine(p->pMan, pName) );
+ return 0;
+ }
+
+ // get the gate
+ pGate = Mio_LibraryReadGateByName( pGenlib, vTokens->pArray[1] );
+ if ( pGate == NULL )
+ {
+ sprintf( p->pMan->sError, "Line %d: Cannot find gate \"%s\" in the library.", Io_MvGetLine(p->pMan, pName), vTokens->pArray[1] );
+ return 0;
+ }
+
+ // if this is the first line with gate, update the network type
+ if ( Abc_NtkNodeNum(p->pNtk) == 0 )
+ {
+ assert( p->pNtk->ntkFunc == ABC_FUNC_SOP );
+ p->pNtk->ntkFunc = ABC_FUNC_MAP;
+ Extra_MmFlexStop( p->pNtk->pManFunc );
+ p->pNtk->pManFunc = pGenlib;
+ }
+
+ // remove the formal parameter names
+ for ( i = 2; i < vTokens->nSize; i++ )
+ {
+ vTokens->pArray[i] = Io_ReadBlifCleanName( vTokens->pArray[i] );
+ if ( vTokens->pArray[i] == NULL )
+ {
+ sprintf( p->pMan->sError, "Line %d: Invalid gate input assignment.", Io_MvGetLine(p->pMan, pName) );
+ return 0;
+ }
+ }
+
+ // create the node
+ ppNames = (char **)vTokens->pArray + 2;
+ nNames = vTokens->nSize - 3;
+ pNode = Io_ReadCreateNode( p->pNtk, ppNames[nNames], ppNames, nNames );
+
+ // set the pointer to the functionality of the node
+ Abc_ObjSetData( pNode, pGate );
+ return 1;
+}
+
+////////////////////////////////////////////////////////////////////////
+/// END OF FILE ///
+////////////////////////////////////////////////////////////////////////
+
+
diff --git a/src/base/io/ioReadDsd.c b/src/base/io/ioReadDsd.c
new file mode 100644
index 00000000..1ab726e5
--- /dev/null
+++ b/src/base/io/ioReadDsd.c
@@ -0,0 +1,308 @@
+/**CFile****************************************************************
+
+ FileName [ioReadDsd.c]
+
+ SystemName [ABC: Logic synthesis and verification system.]
+
+ PackageName [Command processing package.]
+
+ Synopsis [Procedure to read network from file.]
+
+ Author [Alan Mishchenko]
+
+ Affiliation [UC Berkeley]
+
+ Date [Ver. 1.0. Started - June 20, 2005.]
+
+ Revision [$Id: ioReadDsd.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "io.h"
+
+////////////////////////////////////////////////////////////////////////
+/// DECLARATIONS ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+/// FUNCTION DEFINITIONS ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+ Synopsis [Finds the end of the part.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+char * Io_ReadDsdFindEnd( char * pCur )
+{
+ char * pEnd;
+ int nParts = 0;
+ assert( *pCur == '(' );
+ for ( pEnd = pCur; *pEnd; pEnd++ )
+ {
+ if ( *pEnd == '(' )
+ nParts++;
+ else if ( *pEnd == ')' )
+ nParts--;
+ if ( nParts == 0 )
+ return pEnd;
+ }
+ return NULL;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Splits the formula into parts.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Io_ReadDsdStrSplit( char * pCur, char * pParts[], int * pTypeXor )
+{
+ int fAnd = 0, fXor = 0, fPri = 0, nParts = 0;
+ assert( *pCur );
+ // process the parts
+ while ( 1 )
+ {
+ // save the current part
+ pParts[nParts++] = pCur;
+ // skip the complement
+ if ( *pCur == '!' )
+ pCur++;
+ // skip var
+ if ( *pCur >= 'a' && *pCur <= 'z' )
+ pCur++;
+ else
+ {
+ // skip hex truth table
+ while ( (*pCur >= '0' && *pCur <= '9') || (*pCur >= 'A' && *pCur <= 'F') )
+ pCur++;
+ // process parantheses
+ if ( *pCur != '(' )
+ {
+ printf( "Cannot find the opening paranthesis.\n" );
+ break;
+ }
+ // find the corresponding closing paranthesis
+ pCur = Io_ReadDsdFindEnd( pCur );
+ if ( pCur == NULL )
+ {
+ printf( "Cannot find the closing paranthesis.\n" );
+ break;
+ }
+ pCur++;
+ }
+ // check the end
+ if ( *pCur == 0 )
+ break;
+ // check symbol
+ if ( *pCur != '*' && *pCur != '+' && *pCur != ',' )
+ {
+ printf( "Wrong separating symbol.\n" );
+ break;
+ }
+ // remember the symbol
+ fAnd |= (*pCur == '*');
+ fXor |= (*pCur == '+');
+ fPri |= (*pCur == ',');
+ *pCur++ = 0;
+ }
+ // check separating symbols
+ if ( fAnd + fXor + fPri > 1 )
+ {
+ printf( "Different types of separating symbol ennPartsed.\n" );
+ return 0;
+ }
+ *pTypeXor = fXor;
+ return nParts;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Recursively parses the formula.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Abc_Obj_t * Io_ReadDsd_rec( Abc_Ntk_t * pNtk, char * pCur, char * pSop )
+{
+ Abc_Obj_t * pObj, * pFanin;
+ char * pEnd, * pParts[32];
+ int i, nParts, TypeExor;
+
+ // consider complemented formula
+ if ( *pCur == '!' )
+ {
+ pObj = Io_ReadDsd_rec( pNtk, pCur + 1, NULL );
+ return Abc_NtkCreateNodeInv( pNtk, pObj );
+ }
+ if ( *pCur == '(' )
+ {
+ assert( pCur[strlen(pCur)-1] == ')' );
+ pCur[strlen(pCur)-1] = 0;
+ nParts = Io_ReadDsdStrSplit( pCur+1, pParts, &TypeExor );
+ if ( nParts == 0 )
+ {
+ Abc_NtkDelete( pNtk );
+ return NULL;
+ }
+ pObj = Abc_NtkCreateNode( pNtk );
+ if ( pSop )
+ {
+// for ( i = nParts - 1; i >= 0; i-- )
+ for ( i = 0; i < nParts; i++ )
+ {
+ pFanin = Io_ReadDsd_rec( pNtk, pParts[i], NULL );
+ if ( pFanin == NULL )
+ return NULL;
+ Abc_ObjAddFanin( pObj, pFanin );
+ }
+ }
+ else
+ {
+ for ( i = 0; i < nParts; i++ )
+ {
+ pFanin = Io_ReadDsd_rec( pNtk, pParts[i], NULL );
+ if ( pFanin == NULL )
+ return NULL;
+ Abc_ObjAddFanin( pObj, pFanin );
+ }
+ }
+ if ( pSop )
+ pObj->pData = Abc_SopRegister( pNtk->pManFunc, pSop );
+ else if ( TypeExor )
+ pObj->pData = Abc_SopCreateXorSpecial( pNtk->pManFunc, nParts );
+ else
+ pObj->pData = Abc_SopCreateAnd( pNtk->pManFunc, nParts, NULL );
+ return pObj;
+ }
+ if ( *pCur >= 'a' && *pCur <= 'z' )
+ {
+ assert( *(pCur+1) == 0 );
+ return Abc_NtkPi( pNtk, *pCur - 'a' );
+ }
+
+ // skip hex truth table
+ pEnd = pCur;
+ while ( (*pEnd >= '0' && *pEnd <= '9') || (*pEnd >= 'A' && *pEnd <= 'F') )
+ pEnd++;
+ if ( *pEnd != '(' )
+ {
+ printf( "Cannot find the end of hexidecimal truth table.\n" );
+ return NULL;
+ }
+
+ // parse the truth table
+ *pEnd = 0;
+ pSop = Abc_SopFromTruthHex( pCur );
+ *pEnd = '(';
+ pObj = Io_ReadDsd_rec( pNtk, pEnd, pSop );
+ free( pSop );
+ return pObj;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Derives the DSD network of the formula.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Abc_Ntk_t * Io_ReadDsd( char * pForm )
+{
+ Abc_Ntk_t * pNtk;
+ Abc_Obj_t * pObj, * pTop;
+ Vec_Ptr_t * vNames;
+ char * pCur, * pFormCopy;
+ int i, nInputs;
+
+ // count the number of elementary variables
+ nInputs = 0;
+ for ( pCur = pForm; *pCur; pCur++ )
+ if ( *pCur >= 'a' && *pCur <= 'z' )
+ nInputs = ABC_MAX( nInputs, *pCur - 'a' );
+ nInputs++;
+
+ // create the network
+ pNtk = Abc_NtkAlloc( ABC_NTK_LOGIC, ABC_FUNC_SOP, 1 );
+ pNtk->pName = Extra_UtilStrsav( "dsd" );
+
+ // create PIs
+ vNames = Abc_NodeGetFakeNames( nInputs );
+ for ( i = 0; i < nInputs; i++ )
+ Abc_ObjAssignName( Abc_NtkCreatePi(pNtk), Vec_PtrEntry(vNames, i), NULL );
+ Abc_NodeFreeNames( vNames );
+
+ // transform the formula by inserting parantheses
+ // this transforms strings like PRIME(a,b,cd) into (PRIME((a),(b),(cd)))
+ pCur = pFormCopy = ALLOC( char, 3 * strlen(pForm) + 10 );
+ *pCur++ = '(';
+ for ( ; *pForm; pForm++ )
+ if ( *pForm == '(' )
+ {
+ *pCur++ = '(';
+ *pCur++ = '(';
+ }
+ else if ( *pForm == ')' )
+ {
+ *pCur++ = ')';
+ *pCur++ = ')';
+ }
+ else if ( *pForm == ',' )
+ {
+ *pCur++ = ')';
+ *pCur++ = ',';
+ *pCur++ = '(';
+ }
+ else
+ *pCur++ = *pForm;
+ *pCur++ = ')';
+ *pCur = 0;
+
+ // parse the formula
+ pObj = Io_ReadDsd_rec( pNtk, pFormCopy, NULL );
+ free( pFormCopy );
+ if ( pObj == NULL )
+ return NULL;
+
+ // create output
+ pTop = Abc_NtkCreatePo(pNtk);
+ Abc_ObjAssignName( pTop, "F", NULL );
+ Abc_ObjAddFanin( pTop, pObj );
+
+ // create the only PO
+ if ( !Abc_NtkCheck( pNtk ) )
+ {
+ fprintf( stdout, "Io_ReadDsd(): Network check has failed.\n" );
+ Abc_NtkDelete( pNtk );
+ return NULL;
+ }
+ return pNtk;
+}
+
+
+
+////////////////////////////////////////////////////////////////////////
+/// END OF FILE ///
+////////////////////////////////////////////////////////////////////////
+
+
+
diff --git a/src/base/io/ioReadEdif.c b/src/base/io/ioReadEdif.c
index 48a1722b..188e5b8c 100644
--- a/src/base/io/ioReadEdif.c
+++ b/src/base/io/ioReadEdif.c
@@ -27,7 +27,7 @@
static Abc_Ntk_t * Io_ReadEdifNetwork( Extra_FileReader_t * p );
////////////////////////////////////////////////////////////////////////
-/// FUNCTION DEFITIONS ///
+/// FUNCTION DEFINITIONS ///
////////////////////////////////////////////////////////////////////////
/**Function*************************************************************
@@ -46,8 +46,11 @@ Abc_Ntk_t * Io_ReadEdif( char * pFileName, int fCheck )
Extra_FileReader_t * p;
Abc_Ntk_t * pNtk;
+ printf( "Currently this parser does not work!\n" );
+ return NULL;
+
// start the file
- p = Extra_FileReaderAlloc( pFileName, "#", "\n", " \t\r()" );
+ p = Extra_FileReaderAlloc( pFileName, "#", "\n\r", " \t()" );
if ( p == NULL )
return NULL;
@@ -114,11 +117,15 @@ Abc_Ntk_t * Io_ReadEdifNetwork( Extra_FileReader_t * p )
vTokens = Extra_FileReaderGetTokens(p);
pGateName = vTokens->pArray[1];
if ( strncmp( pGateName, "Flip", 4 ) == 0 )
+ {
pObj = Abc_NtkCreateLatch( pNtk );
+ Abc_LatchSetInit0( pObj );
+ }
else
{
pObj = Abc_NtkCreateNode( pNtk );
- pObj->pData = Abc_NtkRegisterName( pNtk, pGateName );
+// pObj->pData = Abc_NtkRegisterName( pNtk, pGateName );
+ pObj->pData = Extra_UtilStrsav( pGateName ); // memory leak!!!
}
Abc_ObjAddFanin( pNet, pObj );
}
@@ -178,7 +185,7 @@ Abc_Ntk_t * Io_ReadEdifNetwork( Extra_FileReader_t * p )
else if ( strcmp( vTokens->pArray[0], "design" ) == 0 )
{
free( pNtk->pName );
- pNtk->pName = util_strsav( vTokens->pArray[3] );
+ pNtk->pName = Extra_UtilStrsav( vTokens->pArray[3] );
break;
}
}
@@ -188,7 +195,7 @@ Abc_Ntk_t * Io_ReadEdifNetwork( Extra_FileReader_t * p )
Abc_NtkForEachNode( pNtk, pObj, i )
{
if ( strncmp( pObj->pData, "And", 3 ) == 0 )
- Abc_ObjSetData( pObj, Abc_SopCreateAnd(pNtk->pManFunc, Abc_ObjFaninNum(pObj)) );
+ Abc_ObjSetData( pObj, Abc_SopCreateAnd(pNtk->pManFunc, Abc_ObjFaninNum(pObj), NULL) );
else if ( strncmp( pObj->pData, "Or", 2 ) == 0 )
Abc_ObjSetData( pObj, Abc_SopCreateOr(pNtk->pManFunc, Abc_ObjFaninNum(pObj), NULL) );
else if ( strncmp( pObj->pData, "Nand", 4 ) == 0 )
diff --git a/src/base/io/ioReadEqn.c b/src/base/io/ioReadEqn.c
index 20d30a1a..e04f2b1a 100644
--- a/src/base/io/ioReadEqn.c
+++ b/src/base/io/ioReadEqn.c
@@ -30,7 +30,7 @@ static int Io_ReadEqnStrFind( Vec_Ptr_t * vTokens, char * pName );
static void Io_ReadEqnStrCutAt( char * pStr, char * pStop, int fUniqueOnly, Vec_Ptr_t * vTokens );
////////////////////////////////////////////////////////////////////////
-/// FUNCTION DEFITIONS ///
+/// FUNCTION DEFINITIONS ///
////////////////////////////////////////////////////////////////////////
/**Function*************************************************************
@@ -85,19 +85,20 @@ Abc_Ntk_t * Io_ReadEqnNetwork( Extra_FileReader_t * p )
{
ProgressBar * pProgress;
Vec_Ptr_t * vTokens;
- Vec_Ptr_t * vCubes, * vLits, * vVars;
+ Vec_Ptr_t * vVars;
Abc_Ntk_t * pNtk;
Abc_Obj_t * pNode;
- char * pCubesCopy, * pSopCube, * pVarName;
- int iLine, iNum, i, k;
+ char * pNodeName, * pFormula, * pFormulaCopy, * pVarName;
+ int iLine, i;
// allocate the empty network
- pNtk = Abc_NtkStartRead( Extra_FileReaderGetFileName(p) );
+ pNtk = Abc_NtkAlloc( ABC_NTK_NETLIST, ABC_FUNC_AIG, 1 );
+ // set the specs
+ pNtk->pName = Extra_FileNameGeneric(Extra_FileReaderGetFileName(p));
+ pNtk->pSpec = Extra_UtilStrsav(Extra_FileReaderGetFileName(p));
// go through the lines of the file
- vCubes = Vec_PtrAlloc( 100 );
vVars = Vec_PtrAlloc( 100 );
- vLits = Vec_PtrAlloc( 100 );
pProgress = Extra_ProgressBarStart( stdout, Extra_FileReaderGetFileSize(p) );
for ( iLine = 0; vTokens = Extra_FileReaderGetTokens(p); iLine++ )
{
@@ -131,52 +132,36 @@ Abc_Ntk_t * Io_ReadEqnNetwork( Extra_FileReader_t * p )
}
else
{
- // remove spaces
- pCubesCopy = vTokens->pArray[1];
- Io_ReadEqnStrCompact( pCubesCopy );
+ extern Hop_Obj_t * Parse_FormulaParserEqn( FILE * pOutput, char * pFormInit, Vec_Ptr_t * vVarNames, Hop_Man_t * pMan );
+
+ // get hold of the node name and its formula
+ pNodeName = vTokens->pArray[0];
+ pFormula = vTokens->pArray[1];
+ // compact the formula
+ Io_ReadEqnStrCompact( pFormula );
+
// consider the case of the constant node
- if ( (pCubesCopy[0] == '0' || pCubesCopy[0] == '1') && pCubesCopy[1] == 0 )
+ if ( pFormula[1] == 0 && (pFormula[0] == '0' || pFormula[0] == '1') )
{
- pNode = Io_ReadCreateNode( pNtk, vTokens->pArray[0], NULL, 0 );
- if ( pCubesCopy[0] == '0' )
- pNode->pData = Abc_SopCreateConst0( pNtk->pManFunc );
- else
- pNode->pData = Abc_SopCreateConst1( pNtk->pManFunc );
- continue;
+ pFormulaCopy = NULL;
+ Vec_PtrClear( vVars );
}
- // determine unique variables
- pCubesCopy = util_strsav( pCubesCopy );
- // find the names of the fanins of this node
- Io_ReadEqnStrCutAt( pCubesCopy, "!*+", 1, vVars );
- // create the node
- pNode = Io_ReadCreateNode( pNtk, vTokens->pArray[0], (char **)vVars->pArray, vVars->nSize );
- // split the string into cubes
- Io_ReadEqnStrCutAt( vTokens->pArray[1], "+", 0, vCubes );
- // start the sop
- pNode->pData = Abc_SopStart( pNtk->pManFunc, vCubes->nSize, vVars->nSize );
- // read the cubes
- i = 0;
- Abc_SopForEachCube( pNode->pData, vVars->nSize, pSopCube )
+ else
{
- // split this cube into lits
- Io_ReadEqnStrCutAt( vCubes->pArray[i], "*", 0, vLits );
- // read the literals
- Vec_PtrForEachEntry( vLits, pVarName, k )
- {
- iNum = Io_ReadEqnStrFind( vVars, pVarName + (pVarName[0] == '!') );
- assert( iNum >= 0 );
- pSopCube[iNum] = '1' - (pVarName[0] == '!');
- }
- i++;
+ // make a copy of formula for names
+ pFormulaCopy = Extra_UtilStrsav( pFormula );
+ // find the names of the fanins of this node
+ Io_ReadEqnStrCutAt( pFormulaCopy, "!*+()", 1, vVars );
}
- assert( i == vCubes->nSize );
+ // create the node
+ pNode = Io_ReadCreateNode( pNtk, pNodeName, (char **)Vec_PtrArray(vVars), Vec_PtrSize(vVars) );
+ // derive the function
+ pNode->pData = Parse_FormulaParserEqn( stdout, pFormula, vVars, pNtk->pManFunc );
// remove the cubes
- free( pCubesCopy );
+ FREE( pFormulaCopy );
}
}
Extra_ProgressBarStop( pProgress );
- Vec_PtrFree( vCubes );
- Vec_PtrFree( vLits );
Vec_PtrFree( vVars );
Abc_NtkFinalizeRead( pNtk );
return pNtk;
diff --git a/src/base/io/ioReadPla.c b/src/base/io/ioReadPla.c
index 1e54db5f..fdfdb4f6 100644
--- a/src/base/io/ioReadPla.c
+++ b/src/base/io/ioReadPla.c
@@ -27,7 +27,7 @@
static Abc_Ntk_t * Io_ReadPlaNetwork( Extra_FileReader_t * p );
////////////////////////////////////////////////////////////////////////
-/// FUNCTION DEFITIONS ///
+/// FUNCTION DEFINITIONS ///
////////////////////////////////////////////////////////////////////////
/**Function*************************************************************
@@ -47,7 +47,7 @@ Abc_Ntk_t * Io_ReadPla( char * pFileName, int fCheck )
Abc_Ntk_t * pNtk;
// start the file
- p = Extra_FileReaderAlloc( pFileName, "#", "\n", " \t\r|" );
+ p = Extra_FileReaderAlloc( pFileName, "#", "\n\r", " \t|" );
if ( p == NULL )
return NULL;
@@ -131,7 +131,7 @@ Abc_Ntk_t * Io_ReadPlaNetwork( Extra_FileReader_t * p )
for ( i = 1; i < vTokens->nSize; i++ )
Io_ReadCreatePo( pNtk, vTokens->pArray[i] );
}
- else
+ else
{
// check if the input/output names are given
if ( Abc_NtkPiNum(pNtk) == 0 )
@@ -229,6 +229,7 @@ Abc_Ntk_t * Io_ReadPlaNetwork( Extra_FileReader_t * p )
{
Abc_ObjRemoveFanins(pNode);
pNode->pData = Abc_SopRegister( pNtk->pManFunc, " 0\n" );
+ Vec_StrFree( ppSops[i] );
continue;
}
Vec_StrPush( ppSops[i], 0 );
diff --git a/src/base/io/ioReadVerilog.c b/src/base/io/ioReadVerilog.c
index f4855dde..c64e330c 100644
--- a/src/base/io/ioReadVerilog.c
+++ b/src/base/io/ioReadVerilog.c
@@ -6,7 +6,7 @@
PackageName [Command processing package.]
- Synopsis [Procedures to read a subset of structural Verilog from IWLS 2005 benchmark.]
+ Synopsis [Procedure to read network from file.]
Author [Alan Mishchenko]
@@ -24,144 +24,15 @@
/// DECLARATIONS ///
////////////////////////////////////////////////////////////////////////
-typedef struct Io_ReadVer_t_ Io_ReadVer_t; // all reading info
-struct Io_ReadVer_t_
-{
- // general info about file
- char * pFileName; // the name of the file
- Extra_FileReader_t* pReader; // the input file reader
- // current processing info
- st_table * tKeywords; // mapping of keywords into codes
- Abc_Ntk_t * pNtk; // the primary network
- // the error message
- FILE * Output; // the output stream
- char sError[1000]; // the error string generated during parsing
- int LineCur; // the line currently being parsed
- Vec_Ptr_t * vSkipped; // temporary storage for skipped objects
-};
-
-// verilog keyword types
-typedef enum {
- VER_NONE = 0,
- VER_MODULE = -1,
- VER_ENDMODULE = -2,
- VER_INPUT = -3,
- VER_OUTPUT = -4,
- VER_INOUT = -5,
- VER_WIRE = -6,
- VER_ASSIGN = -7
-} Ver_KeywordType_t;
-
-// the list of verilog keywords
-static char * s_Keywords[10] =
-{
- NULL, // unused
- "module", // -1
- "endmodule", // -2
- "input", // -3
- "output", // -4
- "inout", // -5
- "wire", // -6
- "assign" // -7
-};
-
-// the list of gates in the Cadence library
-static char * s_CadenceGates[40][5] =
-{
- { "INVX1", "1", "1", "0 1\n", NULL }, // 0
- { "INVX2", "1", "1", "0 1\n", NULL }, // 1
- { "INVX4", "1", "1", "0 1\n", NULL }, // 2
- { "INVX8", "1", "1", "0 1\n", NULL }, // 3
- { "BUFX1", "1", "1", "1 1\n", NULL }, // 4
- { "BUFX3", "1", "1", "1 1\n", NULL }, // 5
- { "NOR2X1", "2", "1", "00 1\n", NULL }, // 6
- { "NOR3X1", "3", "1", "000 1\n", NULL }, // 7
- { "NOR4X1", "4", "1", "0000 1\n", NULL }, // 8
- { "NAND2X1", "2", "1", "11 0\n", NULL }, // 9
- { "NAND2X2", "2", "1", "11 0\n", NULL }, // 10
- { "NAND3X1", "3", "1", "111 0\n", NULL }, // 11
- { "NAND4X1", "4", "1", "1111 0\n", NULL }, // 12
- { "OR2X1", "2", "1", "00 0\n", NULL }, // 13
- { "OR4X1", "4", "1", "0000 0\n", NULL }, // 14
- { "AND2X1", "2", "1", "11 1\n", NULL }, // 15
- { "XOR2X1", "2", "1", "01 1\n10 1\n", NULL }, // 16
- { "MX2X1", "3", "1", "01- 1\n1-1 1\n", NULL }, // 17
- { "OAI21X1", "3", "1", "00- 1\n--0 1\n", NULL }, // 18
- { "OAI22X1", "4", "1", "00-- 1\n--00 1\n", NULL }, // 19
- { "OAI33X1", "6", "1", "000--- 1\n---000 1\n", NULL }, // 20
- { "AOI21X1", "3", "1", "11- 0\n--1 0\n", NULL }, // 21
- { "AOI22X1", "4", "1", "11-- 0\n--11 0\n", NULL }, // 22
- { "CLKBUFX1", "1", "1", "1 1\n", NULL }, // 23
- { "CLKBUFX2", "1", "1", "1 1\n", NULL }, // 24
- { "CLKBUFX3", "1", "1", "1 1\n", NULL }, // 25
- { "ADDHX1", "2", "2", "11 1\n", "01 1\n10 1\n" }, // 26
- { "ADDFX1", "3", "2", "11- 1\n-11 1\n1-1 1\n", "001 1\n010 1\n100 1\n111 1\n" }, // 27
- { "DFFSRX1", "1", "1", NULL, NULL }, // 28
- { "DFFX1", "1", "1", NULL, NULL }, // 29
- { "SDFFSRX1", "1", "1", NULL, NULL }, // 30
- { "TLATSRX1", "1", "1", NULL, NULL }, // 31
- { "TLATX1", "1", "1", NULL, NULL }, // 32
- { "TBUFX1", "1", "1", NULL, NULL }, // 33
- { "TBUFX2", "1", "1", NULL, NULL }, // 34
- { "TBUFX4", "1", "1", NULL, NULL }, // 35
- { "TBUFX8", "1", "1", NULL, NULL }, // 36
- { "TINVX1", "1", "1", NULL, NULL } // 37
-};
-
-static Io_ReadVer_t * Io_ReadVerFile( char * pFileName );
-static Abc_Ntk_t * Io_ReadVerNetwork( Io_ReadVer_t * p );
-static bool Io_ReadVerNetworkAssign( Io_ReadVer_t * p, Abc_Ntk_t * pNtk, Vec_Ptr_t * vTokens );
-static bool Io_ReadVerNetworkSignal( Io_ReadVer_t * p, Abc_Ntk_t * pNtk, Vec_Ptr_t * vTokens, int LineType );
-static bool Io_ReadVerNetworkGateSimple( Io_ReadVer_t * p, Abc_Ntk_t * pNtk, Vec_Ptr_t * vTokens, int LineType );
-static bool Io_ReadVerNetworkGateComplex( Io_ReadVer_t * p, Abc_Ntk_t * pNtk, Vec_Ptr_t * vTokens, int LineType );
-static bool Io_ReadVerNetworkLatch( Io_ReadVer_t * p, Abc_Ntk_t * pNtk, Vec_Ptr_t * vTokens );
-static void Io_ReadVerPrintErrorMessage( Io_ReadVer_t * p );
-static void Io_ReadVerFree( Io_ReadVer_t * p );
+extern Abc_Lib_t * Ver_ParseFile( char * pFileName, Abc_Lib_t * pGateLib, int fCheck, int fUseMemMan );
////////////////////////////////////////////////////////////////////////
-/// FUNCTION DEFITIONS ///
+/// FUNCTION DEFINITIONS ///
////////////////////////////////////////////////////////////////////////
/**Function*************************************************************
- Synopsis [Reads the network from a Verilog file.]
-
- Description [Works only for IWLS 2005 benchmarks.]
-
- SideEffects []
-
- SeeAlso []
-
-***********************************************************************/
-Abc_Ntk_t * Io_ReadVerilog( char * pFileName, int fCheck )
-{
- Io_ReadVer_t * p;
- Abc_Ntk_t * pNtk;
-
- // start the file
- p = Io_ReadVerFile( pFileName );
- if ( p == NULL )
- return NULL;
-
- // read the network
- pNtk = Io_ReadVerNetwork( p );
- Io_ReadVerFree( p );
- if ( pNtk == NULL )
- return NULL;
-
- // make sure that everything is okay with the network structure
- if ( fCheck && !Abc_NtkCheckRead( pNtk ) )
- {
- printf( "Io_ReadVerilog: The network check has failed.\n" );
- Abc_NtkDelete( pNtk );
- return NULL;
- }
- return pNtk;
-}
-
-/**Function*************************************************************
-
- Synopsis [Starts the reading data structure.]
+ Synopsis [Reads hierarchical design from the Verilog file.]
Description []
@@ -170,583 +41,45 @@ Abc_Ntk_t * Io_ReadVerilog( char * pFileName, int fCheck )
SeeAlso []
***********************************************************************/
-Io_ReadVer_t * Io_ReadVerFile( char * pFileName )
-{
- Extra_FileReader_t * pReader;
- Io_ReadVer_t * p;
- int i;
-
- // start the reader
- pReader = Extra_FileReaderAlloc( pFileName, "/", ";", " \t\r\n,()" );
- if ( pReader == NULL )
- return NULL;
-
- // start the reading data structure
- p = ALLOC( Io_ReadVer_t, 1 );
- memset( p, 0, sizeof(Io_ReadVer_t) );
- p->pFileName = pFileName;
- p->pReader = pReader;
- p->Output = stdout;
- p->vSkipped = Vec_PtrAlloc( 100 );
-
- // insert the keywords and gate names into the hash table
- p->tKeywords = st_init_table(strcmp, st_strhash);
- for ( i = 0; i < 10; i++ )
- if ( s_Keywords[i] )
- st_insert( p->tKeywords, (char *)s_Keywords[i], (char *)-i );
- for ( i = 0; i < 40; i++ )
- if ( s_CadenceGates[i][0] )
- st_insert( p->tKeywords, (char *)s_CadenceGates[i][0], (char *)i );
- return p;
-}
-
-/**Function*************************************************************
-
- Synopsis [Frees the data structure.]
-
- Description []
-
- SideEffects []
-
- SeeAlso []
-
-***********************************************************************/
-void Io_ReadVerFree( Io_ReadVer_t * p )
-{
- Extra_FileReaderFree( p->pReader );
- Vec_PtrFree( p->vSkipped );
- st_free_table( p->tKeywords );
- FREE( p );
-}
-
-/**Function*************************************************************
-
- Synopsis [Prints the error message including the file name and line number.]
-
- Description []
-
- SideEffects []
-
- SeeAlso []
-
-***********************************************************************/
-void Io_ReadVerPrintErrorMessage( Io_ReadVer_t * p )
-{
- if ( p->LineCur == 0 ) // the line number is not given
- fprintf( p->Output, "%s: %s\n", p->pFileName, p->sError );
- else // print the error message with the line number
- fprintf( p->Output, "%s (line %d): %s\n", p->pFileName, p->LineCur, p->sError );
-}
-
-/**Function*************************************************************
-
- Synopsis [Reads the verilog file.]
-
- Description []
-
- SideEffects []
-
- SeeAlso []
-
-***********************************************************************/
-Abc_Ntk_t * Io_ReadVerNetwork( Io_ReadVer_t * p )
+Abc_Ntk_t * Io_ReadVerilog( char * pFileName, int fCheck )
{
- char Buffer[1000];
- ProgressBar * pProgress;
- Ver_KeywordType_t LineType;
- Vec_Ptr_t * vTokens;
Abc_Ntk_t * pNtk;
- char * pModelName;
- int i;
+ Abc_Lib_t * pDesign;
+ int RetValue;
- // read the model name
- vTokens = Extra_FileReaderGetTokens( p->pReader );
- if ( vTokens == NULL || strcmp( vTokens->pArray[0], "module" ) )
- {
- p->LineCur = 0;
- sprintf( p->sError, "Wrong input file format." );
- Io_ReadVerPrintErrorMessage( p );
+ // parse the verilog file
+ pDesign = Ver_ParseFile( pFileName, NULL, fCheck, 1 );
+ if ( pDesign == NULL )
return NULL;
- }
- pModelName = vTokens->pArray[1];
-
- // allocate the empty network
- pNtk = Abc_NtkAlloc( ABC_TYPE_NETLIST, ABC_FUNC_SOP );
- pNtk->pName = util_strsav( pModelName );
- pNtk->pSpec = util_strsav( p->pFileName );
-
- // create constant nodes and nets
- Abc_NtkFindOrCreateNet( pNtk, "1'b0" );
- Abc_NtkFindOrCreateNet( pNtk, "1'b1" );
- Io_ReadCreateConst( pNtk, "1'b0", 0 );
- Io_ReadCreateConst( pNtk, "1'b1", 1 );
-
- // read the inputs/outputs
- pProgress = Extra_ProgressBarStart( stdout, Extra_FileReaderGetFileSize(p->pReader) );
- for ( i = 0; vTokens = Extra_FileReaderGetTokens(p->pReader); i++ )
- {
- Extra_ProgressBarUpdate( pProgress, Extra_FileReaderGetCurPosition(p->pReader), NULL );
-
- // get the line type
- if ( !st_lookup( p->tKeywords, vTokens->pArray[0], (char **)&LineType ) )
- {
- p->LineCur = Extra_FileReaderGetLineNumber( p->pReader, 0 );
- sprintf( p->sError, "The first token \"%s\" cannot be recognized.", vTokens->pArray[0] );
- Io_ReadVerPrintErrorMessage( p );
- return NULL;
- }
- // consider Verilog directives
- if ( LineType < 0 )
- {
- if ( LineType == VER_ENDMODULE )
- break;
- if ( LineType == VER_ASSIGN )
- {
- if ( !Io_ReadVerNetworkAssign( p, pNtk, vTokens ) )
- return NULL;
- continue;
- }
- if ( !Io_ReadVerNetworkSignal( p, pNtk, vTokens, LineType ) )
- return NULL;
- continue;
- }
- // proces single output gates
- if ( LineType < 26 )
- {
- if ( !Io_ReadVerNetworkGateSimple( p, pNtk, vTokens, LineType ) )
- return NULL;
- continue;
- }
- // process complex gates
- if ( LineType < 28 )
- {
- if ( !Io_ReadVerNetworkGateComplex( p, pNtk, vTokens, LineType ) )
- return NULL;
- continue;
-
- }
- // process the latches
- if ( LineType < 33 )
- {
- if ( !Io_ReadVerNetworkLatch( p, pNtk, vTokens ) )
- return NULL;
- continue;
- }
- // add the tri-state element to the skipped ones
- sprintf( Buffer, "%s %s", vTokens->pArray[0], vTokens->pArray[1] );
- Vec_PtrPush( p->vSkipped, util_strsav(Buffer) );
- }
- Extra_ProgressBarStop( pProgress );
-
- if ( p->vSkipped->nSize > 0 )
- {
- printf( "IoReadVerilog() skipped %d tri-state elements:\n", p->vSkipped->nSize );
- for ( i = 0; i < p->vSkipped->nSize; i++ )
- {
- if ( i < 2 )
- printf( "%s,\n", p->vSkipped->pArray[i] );
- else
- {
- printf( "%s, etc.\n", p->vSkipped->pArray[i] );
- break;
- }
- }
- for ( i = 0; i < p->vSkipped->nSize; i++ )
- free( p->vSkipped->pArray[i] );
- }
- Abc_NtkFinalizeRead( pNtk );
- return pNtk;
-}
-
-/**Function*************************************************************
- Synopsis [Reads one assign directive in the verilog file.]
-
- Description []
-
- SideEffects []
+ // detect top-level model
+ RetValue = Abc_LibFindTopLevelModels( pDesign );
+ pNtk = Vec_PtrEntry( pDesign->vTops, 0 );
+ if ( RetValue > 1 )
+ printf( "Warning: The design has %d root-level modules. The first one (%s) will be used.\n",
+ Vec_PtrSize(pDesign->vTops), pNtk->pName );
- SeeAlso []
+ // extract the master network
+ pNtk->pDesign = pDesign;
+ pDesign->pManFunc = NULL;
-***********************************************************************/
-bool Io_ReadVerNetworkAssign( Io_ReadVer_t * p, Abc_Ntk_t * pNtk, Vec_Ptr_t * vTokens )
-{
- assert( strcmp( vTokens->pArray[0], "assign" ) == 0 );
- // make sure the driving variable exists
- if ( !Abc_NtkFindNet( pNtk, vTokens->pArray[3] ) )
- {
- p->LineCur = Extra_FileReaderGetLineNumber( p->pReader, 0 );
- sprintf( p->sError, "Cannot find net \"%s\". The assign operator is handled only for assignment to a variable and a constant.", vTokens->pArray[3] );
- Io_ReadVerPrintErrorMessage( p );
- return 0;
- }
- // make sure the driven variable exists
- if ( !Abc_NtkFindNet( pNtk, vTokens->pArray[1] ) )
+ // verify the design for cyclic dependence
+ assert( Vec_PtrSize(pDesign->vModules) > 0 );
+ if ( Vec_PtrSize(pDesign->vModules) == 1 )
{
- p->LineCur = Extra_FileReaderGetLineNumber( p->pReader, 0 );
- sprintf( p->sError, "Cannot find net \"%s\".", vTokens->pArray[1] );
- Io_ReadVerPrintErrorMessage( p );
- return 0;
- }
- // create a buffer
- Io_ReadCreateBuf( pNtk, vTokens->pArray[3], vTokens->pArray[1] );
- return 1;
-}
-
-/**Function*************************************************************
-
- Synopsis [Reads one signal the verilog file.]
-
- Description []
-
- SideEffects []
-
- SeeAlso []
-
-***********************************************************************/
-bool Io_ReadVerNetworkSignal( Io_ReadVer_t * p, Abc_Ntk_t * pNtk, Vec_Ptr_t * vTokens, int LineType )
-{
- Abc_Obj_t * pNet;
- char Buffer[1000];
- char * pToken;
- int nSignals, k, Start, s;
-
- nSignals = 0;
- pToken = vTokens->pArray[1];
- if ( pToken[0] == '[' )
- {
- nSignals = atoi(pToken + 1) + 1;
- if ( nSignals < 1 || nSignals > 1024 )
- {
- p->LineCur = Extra_FileReaderGetLineNumber( p->pReader, 0 );
- sprintf( p->sError, "Incorrect number of signals in the expression \"%s\".", pToken );
- Io_ReadVerPrintErrorMessage( p );
- return 0;
- }
- if ( nSignals == 1 )
- nSignals = 0;
- Start = 2;
+// printf( "Warning: The design is not hierarchical.\n" );
+ Abc_LibFree( pDesign, pNtk );
+ pNtk->pDesign = NULL;
+ pNtk->pSpec = Extra_UtilStrsav( pFileName );
}
else
- Start = 1;
- for ( k = Start; k < vTokens->nSize; k++ )
- {
- pToken = vTokens->pArray[k];
- // print the signal name
- if ( nSignals )
- {
- for ( s = 0; s < nSignals; s++ )
- {
- sprintf( Buffer, "%s[%d]", pToken, s );
- if ( LineType == VER_INPUT || LineType == VER_INOUT )
- Io_ReadCreatePi( pNtk, Buffer );
- if ( LineType == VER_OUTPUT || LineType == VER_INOUT )
- Io_ReadCreatePo( pNtk, Buffer );
- if ( LineType != VER_INPUT && LineType != VER_OUTPUT && LineType != VER_INOUT )
- pNet = Abc_NtkFindOrCreateNet( pNtk, Buffer );
- }
- }
- else
- {
- if ( LineType == VER_INPUT || LineType == VER_INOUT )
- Io_ReadCreatePi( pNtk, pToken );
- if ( LineType == VER_OUTPUT || LineType == VER_INOUT )
- Io_ReadCreatePo( pNtk, pToken );
- if ( LineType != VER_INPUT && LineType != VER_OUTPUT && LineType != VER_INOUT )
- pNet = Abc_NtkFindOrCreateNet( pNtk, pToken );
- }
- }
- return 1;
-}
-
-/**Function*************************************************************
-
- Synopsis [Reads a simple gate from the verilog file.]
-
- Description []
-
- SideEffects []
-
- SeeAlso []
-
-***********************************************************************/
-bool Io_ReadVerNetworkGateSimple( Io_ReadVer_t * p, Abc_Ntk_t * pNtk, Vec_Ptr_t * vTokens, int LineType )
-{
- Abc_Obj_t * pNet, * pNode;
- char * pToken;
- int nFanins, k;
-
- // create the node
- pNode = Abc_NtkCreateNode( pNtk );
- // add the fanin nets
- nFanins = s_CadenceGates[LineType][1][0] - '0';
- // skip the gate type and gate name
- for ( k = 2; k < vTokens->nSize - 1; k++ )
- {
- pToken = vTokens->pArray[k];
- if ( pToken[0] == '.' )
- continue;
- pNet = Abc_NtkFindNet( pNtk, pToken );
- if ( pNet )
- {
- Abc_ObjAddFanin( pNode, pNet );
- continue;
- }
- p->LineCur = Extra_FileReaderGetLineNumber( p->pReader, 0 );
- sprintf( p->sError, "Cannot find net \"%s\".", pToken );
- Io_ReadVerPrintErrorMessage( p );
- return 0;
- }
- if ( Abc_ObjFaninNum(pNode) != nFanins )
- {
- p->LineCur = Extra_FileReaderGetLineNumber( p->pReader, 0 );
- sprintf( p->sError, "Gate \"%s\" has a wrong number of inputs.", vTokens->pArray[1] );
- Io_ReadVerPrintErrorMessage( p );
- return 0;
- }
-
- // add the fanout net
- pToken = vTokens->pArray[vTokens->nSize - 1];
- if ( pToken[0] == '.' )
- {
- p->LineCur = Extra_FileReaderGetLineNumber( p->pReader, 0 );
- sprintf( p->sError, "Gate \"%s\" does not have a fanout.", vTokens->pArray[1] );
- Io_ReadVerPrintErrorMessage( p );
- return 0;
- }
- pNet = Abc_NtkFindNet( pNtk, pToken );
- if ( pNet == NULL )
- {
- p->LineCur = Extra_FileReaderGetLineNumber( p->pReader, 0 );
- sprintf( p->sError, "Cannot find net \"%s\".", pToken );
- Io_ReadVerPrintErrorMessage( p );
- return 0;
- }
- Abc_ObjAddFanin( pNet, pNode );
- // set the function
- Abc_ObjSetData( pNode, Abc_SopRegister(pNtk->pManFunc, s_CadenceGates[LineType][3]) );
- return 1;
-}
-
-/**Function*************************************************************
-
- Synopsis [Reads a complex gate from the verilog file.]
-
- Description []
-
- SideEffects []
-
- SeeAlso []
-
-***********************************************************************/
-bool Io_ReadVerNetworkGateComplex( Io_ReadVer_t * p, Abc_Ntk_t * pNtk, Vec_Ptr_t * vTokens, int LineType )
-{
- Abc_Obj_t * pNode1, * pNode2, * pNet;
- char * pToken, * pToken1, * pToken2;
- int nFanins, k;
-
- // create the nodes
- pNode1 = Abc_NtkCreateNode( pNtk );
- pNode2 = Abc_NtkCreateNode( pNtk );
- // skip the gate type and gate name
- // add the fanin nets
- nFanins = s_CadenceGates[LineType][1][0] - '0';
- for ( k = 2; k < vTokens->nSize; k++ )
- {
- pToken = vTokens->pArray[k];
- if ( pToken[0] == '.' )
- continue;
- pNet = Abc_NtkFindNet( pNtk, pToken );
- if ( pNet == NULL )
- {
- p->LineCur = Extra_FileReaderGetLineNumber( p->pReader, 0 );
- sprintf( p->sError, "Cannot find net \"%s\".", pToken );
- Io_ReadVerPrintErrorMessage( p );
- return 0;
- }
- Abc_ObjAddFanin( pNode1, pNet );
- Abc_ObjAddFanin( pNode2, pNet );
- if ( Abc_ObjFaninNum(pNode1) == nFanins )
- {
- k++;
- break;
- }
- }
- // find the tokens corresponding to the output
- pToken1 = pToken2 = NULL;
- for ( ; k < vTokens->nSize; k++ )
{
- pToken = vTokens->pArray[k];
- if ( pToken[0] == '.' )
- continue;
- if ( pToken1 == NULL )
- pToken1 = pToken;
- else
- pToken2 = pToken;
+ // check that there is no cyclic dependency
+ Abc_NtkIsAcyclicHierarchy( pNtk );
}
- // quit if one of the tokens is not given
- if ( pToken1 == NULL || pToken2 == NULL )
- {
- p->LineCur = Extra_FileReaderGetLineNumber( p->pReader, 0 );
- sprintf( p->sError, "An output of a two-output gate \"%s\" is not specified.", vTokens->pArray[1] );
- Io_ReadVerPrintErrorMessage( p );
- return 0;
- }
-
- // add the fanout net
- pNet = Abc_NtkFindNet( pNtk, pToken1 );
- if ( pNet == NULL )
- {
- p->LineCur = Extra_FileReaderGetLineNumber( p->pReader, 0 );
- sprintf( p->sError, "Cannot find net \"%s\".", pToken1 );
- Io_ReadVerPrintErrorMessage( p );
- return 0;
- }
- Abc_ObjAddFanin( pNet, pNode1 );
- // add the fanout net
- pNet = Abc_NtkFindNet( pNtk, pToken2 );
- if ( pNet == NULL )
- {
- p->LineCur = Extra_FileReaderGetLineNumber( p->pReader, 0 );
- sprintf( p->sError, "Cannot find net \"%s\".", pToken2 );
- Io_ReadVerPrintErrorMessage( p );
- return 0;
- }
- Abc_ObjAddFanin( pNet, pNode2 );
- Abc_ObjSetData( pNode1, Abc_SopRegister(pNtk->pManFunc, s_CadenceGates[LineType][3]) );
- Abc_ObjSetData( pNode2, Abc_SopRegister(pNtk->pManFunc, s_CadenceGates[LineType][4]) );
- return 1;
-}
-
-/**Function*************************************************************
-
- Synopsis [Reads a latch from the verilog file.]
-
- Description [This procedure treats T-latch as if it were D-latch.]
-
- SideEffects []
-
- SeeAlso []
-
-***********************************************************************/
-bool Io_ReadVerNetworkLatch( Io_ReadVer_t * p, Abc_Ntk_t * pNtk, Vec_Ptr_t * vTokens )
-{
- Abc_Obj_t * pLatch, * pNet;
- char * pLatchName;
- char * pToken, * pToken2, * pTokenRN, * pTokenSN, * pTokenSI, * pTokenSE, * pTokenD, * pTokenQ, * pTokenQN;
- int k, fRN1, fSN1;
-
- // get the latch name
- pLatchName = vTokens->pArray[1];
-
- // collect the FF signals
- pTokenRN = pTokenSN = pTokenSI = pTokenSE = pTokenD = pTokenQ = pTokenQN = NULL;
- for ( k = 2; k < vTokens->nSize-1; k++ )
- {
- pToken = vTokens->pArray[k];
- pToken2 = vTokens->pArray[k+1];
- if ( pToken[1] == 'R' && pToken[2] == 'N' && pToken[3] == 0 )
- pTokenRN = (pToken2[0] == '.')? NULL : pToken2;
- else if ( pToken[1] == 'S' && pToken[2] == 'N' && pToken[3] == 0 )
- pTokenSN = (pToken2[0] == '.')? NULL : pToken2;
- else if ( pToken[1] == 'S' && pToken[2] == 'I' && pToken[3] == 0 )
- pTokenSI = (pToken2[0] == '.')? NULL : pToken2;
- else if ( pToken[1] == 'S' && pToken[2] == 'E' && pToken[3] == 0 )
- pTokenSE = (pToken2[0] == '.')? NULL : pToken2;
- else if ( pToken[1] == 'D' && pToken[2] == 0 )
- pTokenD = (pToken2[0] == '.')? NULL : pToken2;
- else if ( pToken[1] == 'Q' && pToken[2] == 0 )
- pTokenQ = (pToken2[0] == '.')? NULL : pToken2;
- else if ( pToken[1] == 'Q' && pToken[2] == 'N' && pToken[3] == 0 )
- pTokenQN = (pToken2[0] == '.')? NULL : pToken2;
- else if ( pToken[1] == 'C' && pToken[2] == 'K' && pToken[3] == 0 ) {}
- else
- assert( 0 );
- if ( pToken2[0] != '.' )
- k++;
- }
-
- if ( pTokenD == NULL )
- {
- p->LineCur = Extra_FileReaderGetLineNumber( p->pReader, 1 );
- sprintf( p->sError, "Cannot read pin D of the latch \"%s\".", pLatchName );
- Io_ReadVerPrintErrorMessage( p );
- return 0;
- }
- if ( pTokenQ == NULL && pTokenQN == NULL )
- {
- p->LineCur = Extra_FileReaderGetLineNumber( p->pReader, 1 );
- sprintf( p->sError, "Cannot read pins Q/QN of the latch \"%s\".", pLatchName );
- Io_ReadVerPrintErrorMessage( p );
- return 0;
- }
- if ( (pTokenRN == NULL) ^ (pTokenSN == NULL) )
- {
- p->LineCur = Extra_FileReaderGetLineNumber( p->pReader, 1 );
- sprintf( p->sError, "Cannot read pins RN/SN of the latch \"%s\".", pLatchName );
- Io_ReadVerPrintErrorMessage( p );
- return 0;
- }
- if ( Abc_NtkFindNet( pNtk, pTokenD ) == NULL )
- {
- p->LineCur = Extra_FileReaderGetLineNumber( p->pReader, 0 );
- sprintf( p->sError, "Cannot find latch input net \"%s\".", pTokenD );
- Io_ReadVerPrintErrorMessage( p );
- return 0;
- }
-
- // create the latch
- pLatch = Io_ReadCreateLatch( pNtk, pTokenD, pLatchName );
-
- // create the buffer if Q signal is available
- if ( pTokenQ )
- {
- pNet = Abc_NtkFindNet( pNtk, pTokenQ );
- if ( pNet == NULL )
- {
- p->LineCur = Extra_FileReaderGetLineNumber( p->pReader, 0 );
- sprintf( p->sError, "Cannot find latch output net \"%s\".", pTokenQ );
- Io_ReadVerPrintErrorMessage( p );
- return 0;
- }
- Io_ReadCreateBuf( pNtk, pLatchName, pTokenQ );
- }
- if ( pTokenQN )
- {
- pNet = Abc_NtkFindNet( pNtk, pTokenQN );
- if ( pNet == NULL )
- {
- p->LineCur = Extra_FileReaderGetLineNumber( p->pReader, 0 );
- sprintf( p->sError, "Cannot find latch output net \"%s\".", pTokenQN );
- Io_ReadVerPrintErrorMessage( p );
- return 0;
- }
- Io_ReadCreateInv( pNtk, pLatchName, pTokenQN );
- }
-
- // set the initial value
- if ( pTokenRN == NULL && pTokenSN == NULL )
- Abc_LatchSetInitDc( pLatch );
- else
- {
- fRN1 = (strcmp( pTokenRN, "1'b1" ) == 0);
- fSN1 = (strcmp( pTokenSN, "1'b1" ) == 0);
- if ( fRN1 && fSN1 )
- Abc_LatchSetInitDc( pLatch );
- else if ( fRN1 )
- Abc_LatchSetInit1( pLatch );
- else if ( fSN1 )
- Abc_LatchSetInit0( pLatch );
- else
- {
- p->LineCur = Extra_FileReaderGetLineNumber( p->pReader, 0 );
- sprintf( p->sError, "Cannot read the initial value of latch \"%s\".", pLatchName );
- Io_ReadVerPrintErrorMessage( p );
- return 0;
- }
- }
- return 1;
+//Io_WriteVerilog( pNtk, "_temp.v" );
+ return pNtk;
}
////////////////////////////////////////////////////////////////////////
diff --git a/src/base/io/ioUtil.c b/src/base/io/ioUtil.c
index 132684cc..4f9f2e9f 100644
--- a/src/base/io/ioUtil.c
+++ b/src/base/io/ioUtil.c
@@ -25,11 +25,442 @@
////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////
-/// FUNCTION DEFITIONS ///
+/// FUNCTION DEFINITIONS ///
////////////////////////////////////////////////////////////////////////
/**Function*************************************************************
+ Synopsis [Returns the file type.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Io_FileType_t Io_ReadFileType( char * pFileName )
+{
+ char * pExt;
+ if ( pFileName == NULL )
+ return IO_FILE_NONE;
+ pExt = Extra_FileNameExtension( pFileName );
+ if ( pExt == NULL )
+ return IO_FILE_NONE;
+ if ( !strcmp( pExt, "aig" ) )
+ return IO_FILE_AIGER;
+ if ( !strcmp( pExt, "baf" ) )
+ return IO_FILE_BAF;
+ if ( !strcmp( pExt, "blif" ) )
+ return IO_FILE_BLIF;
+ if ( !strcmp( pExt, "bench" ) )
+ return IO_FILE_BENCH;
+ if ( !strcmp( pExt, "cnf" ) )
+ return IO_FILE_CNF;
+ if ( !strcmp( pExt, "dot" ) )
+ return IO_FILE_DOT;
+ if ( !strcmp( pExt, "edif" ) )
+ return IO_FILE_EDIF;
+ if ( !strcmp( pExt, "eqn" ) )
+ return IO_FILE_EQN;
+ if ( !strcmp( pExt, "gml" ) )
+ return IO_FILE_GML;
+ if ( !strcmp( pExt, "list" ) )
+ return IO_FILE_LIST;
+ if ( !strcmp( pExt, "mv" ) )
+ return IO_FILE_BLIFMV;
+ if ( !strcmp( pExt, "pla" ) )
+ return IO_FILE_PLA;
+ if ( !strcmp( pExt, "v" ) )
+ return IO_FILE_VERILOG;
+ return IO_FILE_UNKNOWN;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Read the network from a file.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Abc_Ntk_t * Io_ReadNetlist( char * pFileName, Io_FileType_t FileType, int fCheck )
+{
+ FILE * pFile;
+ Abc_Ntk_t * pNtk;
+ if ( FileType == IO_FILE_NONE || FileType == IO_FILE_UNKNOWN )
+ {
+ fprintf( stdout, "The generic file reader requires a known file extension.\n" );
+ return NULL;
+ }
+ // check if the file exists
+ pFile = fopen( pFileName, "r" );
+ if ( pFile == NULL )
+ {
+ fprintf( stdout, "Cannot open input file \"%s\". ", pFileName );
+ if ( pFileName = Extra_FileGetSimilarName( pFileName, ".blif", ".bench", ".pla", ".baf", ".aig" ) )
+ fprintf( stdout, "Did you mean \"%s\"?", pFileName );
+ fprintf( stdout, "\n" );
+ return NULL;
+ }
+ fclose( pFile );
+ // read the AIG
+ if ( FileType == IO_FILE_AIGER || FileType == IO_FILE_BAF )
+ {
+ if ( FileType == IO_FILE_AIGER )
+ pNtk = Io_ReadAiger( pFileName, fCheck );
+ else // if ( FileType == IO_FILE_BAF )
+ pNtk = Io_ReadBaf( pFileName, fCheck );
+ if ( pNtk == NULL )
+ {
+ fprintf( stdout, "Reading AIG from file has failed.\n" );
+ return NULL;
+ }
+ return pNtk;
+ }
+ // read the new netlist
+ if ( FileType == IO_FILE_BLIF )
+// pNtk = Io_ReadBlif( pFileName, fCheck );
+ pNtk = Io_ReadBlifMv( pFileName, 0, fCheck );
+ else if ( Io_ReadFileType(pFileName) == IO_FILE_BLIFMV )
+ pNtk = Io_ReadBlifMv( pFileName, 1, fCheck );
+ else if ( FileType == IO_FILE_BENCH )
+ pNtk = Io_ReadBench( pFileName, fCheck );
+ else if ( FileType == IO_FILE_EDIF )
+ pNtk = Io_ReadEdif( pFileName, fCheck );
+ else if ( FileType == IO_FILE_EQN )
+ pNtk = Io_ReadEqn( pFileName, fCheck );
+ else if ( FileType == IO_FILE_PLA )
+ pNtk = Io_ReadPla( pFileName, fCheck );
+ else if ( FileType == IO_FILE_VERILOG )
+ pNtk = Io_ReadVerilog( pFileName, fCheck );
+ else
+ {
+ fprintf( stderr, "Unknown file format.\n" );
+ return NULL;
+ }
+ if ( pNtk == NULL )
+ {
+ fprintf( stdout, "Reading network from file has failed.\n" );
+ return NULL;
+ }
+ if ( Abc_NtkBlackboxNum(pNtk) || Abc_NtkWhiteboxNum(pNtk) )
+ fprintf( stdout, "Warning: The network contains hierarchy.\n" );
+ return pNtk;
+}
+
+
+/**Function*************************************************************
+
+ Synopsis [Read the network from a file.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Abc_Ntk_t * Io_Read( char * pFileName, Io_FileType_t FileType, int fCheck )
+{
+ Abc_Ntk_t * pNtk, * pTemp;
+ // get the netlist
+ pNtk = Io_ReadNetlist( pFileName, FileType, fCheck );
+ if ( pNtk == NULL )
+ return NULL;
+ if ( !Abc_NtkIsNetlist(pNtk) )
+ return pNtk;
+ // flatten logic hierarchy
+ assert( Abc_NtkIsNetlist(pNtk) );
+ if ( Abc_NtkWhiteboxNum(pNtk) > 0 )
+ {
+ pNtk = Abc_NtkFlattenLogicHierarchy( pTemp = pNtk );
+ Abc_NtkDelete( pTemp );
+ if ( pNtk == NULL )
+ {
+ fprintf( stdout, "Flattening logic hierarchy has failed.\n" );
+ return NULL;
+ }
+ }
+ // convert blackboxes
+ if ( Abc_NtkBlackboxNum(pNtk) > 0 )
+ {
+ printf( "Hierarchy reader converted %d instances of blackboxes.\n", Abc_NtkBlackboxNum(pNtk) );
+ pNtk = Abc_NtkConvertBlackboxes( pTemp = pNtk );
+ Abc_NtkDelete( pTemp );
+ if ( pNtk == NULL )
+ {
+ fprintf( stdout, "Converting blackboxes has failed.\n" );
+ return NULL;
+ }
+ }
+ // consider the case of BLIF-MV
+ if ( Io_ReadFileType(pFileName) == IO_FILE_BLIFMV )
+ {
+//Abc_NtkPrintStats( stdout, pNtk, 0 );
+// Io_WriteBlifMv( pNtk, "_temp_.mv" );
+ pNtk = Abc_NtkStrashBlifMv( pTemp = pNtk );
+ Abc_NtkDelete( pTemp );
+ if ( pNtk == NULL )
+ {
+ fprintf( stdout, "Converting BLIF-MV to AIG has failed.\n" );
+ return NULL;
+ }
+ return pNtk;
+ }
+ // convert the netlist into the logic network
+ pNtk = Abc_NtkToLogic( pTemp = pNtk );
+ Abc_NtkDelete( pTemp );
+ if ( pNtk == NULL )
+ {
+ fprintf( stdout, "Converting netlist to logic network after reading has failed.\n" );
+ return NULL;
+ }
+ return pNtk;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Write the network into file.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Io_Write( Abc_Ntk_t * pNtk, char * pFileName, Io_FileType_t FileType )
+{
+ Abc_Ntk_t * pNtkTemp, * pNtkCopy;
+ // check if the current network is available
+ if ( pNtk == NULL )
+ {
+ fprintf( stdout, "Empty network.\n" );
+ return;
+ }
+ // check if the file extension if given
+ if ( FileType == IO_FILE_NONE || FileType == IO_FILE_UNKNOWN )
+ {
+ fprintf( stdout, "The generic file writer requires a known file extension.\n" );
+ return;
+ }
+ // write the AIG formats
+ if ( FileType == IO_FILE_AIGER || FileType == IO_FILE_BAF )
+ {
+ if ( !Abc_NtkIsStrash(pNtk) )
+ {
+ fprintf( stdout, "Writing this format is only possible for structurally hashed AIGs.\n" );
+ return;
+ }
+ if ( FileType == IO_FILE_AIGER )
+ Io_WriteAiger( pNtk, pFileName, 1, 0 );
+ else // if ( FileType == IO_FILE_BAF )
+ Io_WriteBaf( pNtk, pFileName );
+ return;
+ }
+ // write non-netlist types
+ if ( FileType == IO_FILE_CNF )
+ {
+ Io_WriteCnf( pNtk, pFileName, 0 );
+ return;
+ }
+ if ( FileType == IO_FILE_DOT )
+ {
+ Io_WriteDot( pNtk, pFileName );
+ return;
+ }
+ if ( FileType == IO_FILE_GML )
+ {
+ Io_WriteGml( pNtk, pFileName );
+ return;
+ }
+/*
+ if ( FileType == IO_FILE_BLIFMV )
+ {
+ Io_WriteBlifMv( pNtk, pFileName );
+ return;
+ }
+*/
+ // convert logic network into netlist
+ if ( FileType == IO_FILE_PLA )
+ {
+ if ( Abc_NtkLevel(pNtk) > 1 )
+ {
+ fprintf( stdout, "PLA writing is available for collapsed networks.\n" );
+ return;
+ }
+ if ( Abc_NtkIsComb(pNtk) )
+ pNtkTemp = Abc_NtkToNetlist( pNtk );
+ else
+ {
+ fprintf( stdout, "Latches are writen into the PLA file at PI/PO pairs.\n" );
+ pNtkCopy = Abc_NtkDup( pNtk );
+ Abc_NtkMakeComb( pNtkCopy );
+ pNtkTemp = Abc_NtkToNetlist( pNtk );
+ Abc_NtkDelete( pNtkCopy );
+ }
+ if ( !Abc_NtkToSop( pNtk, 1 ) )
+ return;
+ }
+ else if ( FileType == IO_FILE_BENCH )
+ {
+ if ( !Abc_NtkIsStrash(pNtk) )
+ {
+ fprintf( stdout, "Writing traditional BENCH is available for AIGs only (use \"write_bench\").\n" );
+ return;
+ }
+ pNtkTemp = Abc_NtkToNetlistBench( pNtk );
+ }
+ else
+ pNtkTemp = Abc_NtkToNetlist( pNtk );
+
+ if ( pNtkTemp == NULL )
+ {
+ fprintf( stdout, "Converting to netlist has failed.\n" );
+ return;
+ }
+
+ if ( FileType == IO_FILE_BLIF )
+ {
+ if ( !Abc_NtkHasSop(pNtkTemp) && !Abc_NtkHasMapping(pNtkTemp) )
+ Abc_NtkToSop( pNtkTemp, 0 );
+ Io_WriteBlif( pNtkTemp, pFileName, 1 );
+ }
+ else if ( FileType == IO_FILE_BLIFMV )
+ {
+ if ( !Abc_NtkConvertToBlifMv( pNtkTemp ) )
+ return;
+ Io_WriteBlifMv( pNtkTemp, pFileName );
+ }
+ else if ( FileType == IO_FILE_BENCH )
+ Io_WriteBench( pNtkTemp, pFileName );
+ else if ( FileType == IO_FILE_PLA )
+ Io_WritePla( pNtkTemp, pFileName );
+ else if ( FileType == IO_FILE_EQN )
+ {
+ if ( !Abc_NtkHasAig(pNtkTemp) )
+ Abc_NtkToAig( pNtkTemp );
+ Io_WriteEqn( pNtkTemp, pFileName );
+ }
+ else if ( FileType == IO_FILE_VERILOG )
+ {
+ if ( !Abc_NtkHasAig(pNtkTemp) && !Abc_NtkHasMapping(pNtkTemp) )
+ Abc_NtkToAig( pNtkTemp );
+ Io_WriteVerilog( pNtkTemp, pFileName );
+ }
+ else
+ fprintf( stderr, "Unknown file format.\n" );
+ Abc_NtkDelete( pNtkTemp );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Write the network into file.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Io_WriteHie( Abc_Ntk_t * pNtk, char * pBaseName, char * pFileName )
+{
+ Abc_Ntk_t * pNtkTemp, * pNtkResult, * pNtkBase = NULL;
+ // check if the current network is available
+ if ( pNtk == NULL )
+ {
+ fprintf( stdout, "Empty network.\n" );
+ return;
+ }
+
+ // read the base network
+ assert( Abc_NtkIsStrash(pNtk) || Abc_NtkIsLogic(pNtk) );
+ if ( Io_ReadFileType(pBaseName) == IO_FILE_BLIF )
+ pNtkBase = Io_ReadBlifMv( pBaseName, 0, 1 );
+ else if ( Io_ReadFileType(pBaseName) == IO_FILE_BLIFMV )
+ pNtkBase = Io_ReadBlifMv( pBaseName, 1, 1 );
+ else if ( Io_ReadFileType(pBaseName) == IO_FILE_VERILOG )
+ pNtkBase = Io_ReadVerilog( pBaseName, 1 );
+ else
+ fprintf( stderr, "Unknown input file format.\n" );
+ if ( pNtkBase == NULL )
+ return;
+
+ // flatten logic hierarchy if present
+ if ( Abc_NtkWhiteboxNum(pNtkBase) > 0 )
+ {
+ pNtkBase = Abc_NtkFlattenLogicHierarchy( pNtkTemp = pNtkBase );
+ if ( pNtkBase == NULL )
+ return;
+ Abc_NtkDelete( pNtkTemp );
+ }
+
+ // reintroduce the boxes into the netlist
+ if ( Io_ReadFileType(pBaseName) == IO_FILE_BLIFMV )
+ {
+ if ( Abc_NtkBlackboxNum(pNtkBase) > 0 )
+ {
+ printf( "Hierarchy writer does not support BLIF-MV with blackboxes.\n" );
+ Abc_NtkDelete( pNtkBase );
+ return;
+ }
+ // convert the current network to BLIF-MV
+ assert( !Abc_NtkIsNetlist(pNtk) );
+ pNtkResult = Abc_NtkToNetlist( pNtk );
+ if ( !Abc_NtkConvertToBlifMv( pNtkResult ) )
+ return;
+ // reintroduce the network
+ pNtkResult = Abc_NtkInsertBlifMv( pNtkBase, pNtkTemp = pNtkResult );
+ Abc_NtkDelete( pNtkTemp );
+ }
+ else if ( Abc_NtkBlackboxNum(pNtkBase) > 0 )
+ {
+ // derive the netlist
+ pNtkResult = Abc_NtkToNetlist( pNtk );
+ pNtkResult = Abc_NtkInsertNewLogic( pNtkBase, pNtkTemp = pNtkResult );
+ Abc_NtkDelete( pNtkTemp );
+ if ( pNtkResult )
+ printf( "Hierarchy writer reintroduced %d instances of blackboxes.\n", Abc_NtkBlackboxNum(pNtkBase) );
+ }
+ else
+ {
+ printf( "Warning: The output network does not contain blackboxes.\n" );
+ pNtkResult = Abc_NtkToNetlist( pNtk );
+ }
+ Abc_NtkDelete( pNtkBase );
+ if ( pNtkResult == NULL )
+ return;
+
+ // write the resulting network
+ if ( Io_ReadFileType(pFileName) == IO_FILE_BLIF )
+ {
+ if ( !Abc_NtkHasSop(pNtkResult) && !Abc_NtkHasMapping(pNtkResult) )
+ Abc_NtkToSop( pNtkResult, 0 );
+ Io_WriteBlif( pNtkResult, pFileName, 1 );
+ }
+ else if ( Io_ReadFileType(pFileName) == IO_FILE_VERILOG )
+ {
+ if ( !Abc_NtkHasAig(pNtkResult) && !Abc_NtkHasMapping(pNtkResult) )
+ Abc_NtkToAig( pNtkResult );
+ Io_WriteVerilog( pNtkResult, pFileName );
+ }
+ else if ( Io_ReadFileType(pFileName) == IO_FILE_BLIFMV )
+ {
+ Io_WriteBlifMv( pNtkResult, pFileName );
+ }
+ else
+ fprintf( stderr, "Unknown output file format.\n" );
+
+ Abc_NtkDelete( pNtkResult );
+}
+
+/**Function*************************************************************
+
Synopsis [Creates PI terminal and net.]
Description []
@@ -80,7 +511,7 @@ Abc_Obj_t * Io_ReadCreatePo( Abc_Ntk_t * pNtk, char * pName )
/**Function*************************************************************
- Synopsis [Create a latch with the given input/output.]
+ Synopsis [Creates PO terminal and net.]
Description []
@@ -89,17 +520,82 @@ Abc_Obj_t * Io_ReadCreatePo( Abc_Ntk_t * pNtk, char * pName )
SeeAlso []
***********************************************************************/
+Abc_Obj_t * Io_ReadCreateAssert( Abc_Ntk_t * pNtk, char * pName )
+{
+ Abc_Obj_t * pNet, * pTerm;
+ // get the PO net
+ pNet = Abc_NtkFindNet( pNtk, pName );
+ if ( pNet && Abc_ObjFaninNum(pNet) == 0 )
+ printf( "Warning: Assert \"%s\" appears twice in the list.\n", pName );
+ pNet = Abc_NtkFindOrCreateNet( pNtk, pName );
+ // add the PO node
+ pTerm = Abc_NtkCreateAssert( pNtk );
+ Abc_ObjAddFanin( pTerm, pNet );
+ return pTerm;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Create a latch with the given input/output.]
+
+ Description [By default, the latch value is unknown (ABC_INIT_NONE).]
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
Abc_Obj_t * Io_ReadCreateLatch( Abc_Ntk_t * pNtk, char * pNetLI, char * pNetLO )
{
- Abc_Obj_t * pLatch, * pNet;
- // create a new latch and add it to the network
- pLatch = Abc_NtkCreateLatch( pNtk );
+ Abc_Obj_t * pLatch, * pTerm, * pNet;
// get the LI net
pNet = Abc_NtkFindOrCreateNet( pNtk, pNetLI );
- Abc_ObjAddFanin( pLatch, pNet );
+ // add the BO terminal
+ pTerm = Abc_NtkCreateBi( pNtk );
+ Abc_ObjAddFanin( pTerm, pNet );
+ // add the latch box
+ pLatch = Abc_NtkCreateLatch( pNtk );
+ Abc_ObjAddFanin( pLatch, pTerm );
+ // add the BI terminal
+ pTerm = Abc_NtkCreateBo( pNtk );
+ Abc_ObjAddFanin( pTerm, pLatch );
// get the LO net
pNet = Abc_NtkFindOrCreateNet( pNtk, pNetLO );
- Abc_ObjAddFanin( pNet, pLatch );
+ Abc_ObjAddFanin( pNet, pTerm );
+ // set latch name
+ Abc_ObjAssignName( pLatch, pNetLO, "L" );
+ return pLatch;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Create the reset latch with data=1 and init=0.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Abc_Obj_t * Io_ReadCreateResetLatch( Abc_Ntk_t * pNtk, int fBlifMv )
+{
+ Abc_Obj_t * pLatch, * pNode;
+ Abc_Obj_t * pNetLI, * pNetLO;
+ // create latch with 0 init value
+// pLatch = Io_ReadCreateLatch( pNtk, "_resetLI_", "_resetLO_" );
+ pNetLI = Abc_NtkCreateNet( pNtk );
+ pNetLO = Abc_NtkCreateNet( pNtk );
+ Abc_ObjAssignName( pNetLI, Abc_ObjName(pNetLI), NULL );
+ Abc_ObjAssignName( pNetLO, Abc_ObjName(pNetLO), NULL );
+ pLatch = Io_ReadCreateLatch( pNtk, Abc_ObjName(pNetLI), Abc_ObjName(pNetLO) );
+ // set the initial value
+ Abc_LatchSetInit0( pLatch );
+ // feed the latch with constant1- node
+// pNode = Abc_NtkCreateNode( pNtk );
+// pNode->pData = Abc_SopRegister( pNtk->pManFunc, "2\n1\n" );
+ pNode = Abc_NtkCreateNodeConst1( pNtk );
+ Abc_ObjAddFanin( Abc_ObjFanin0(Abc_ObjFanin0(pLatch)), pNode );
return pLatch;
}
@@ -146,7 +642,7 @@ Abc_Obj_t * Io_ReadCreateNode( Abc_Ntk_t * pNtk, char * pNameOut, char * pNamesI
Abc_Obj_t * Io_ReadCreateConst( Abc_Ntk_t * pNtk, char * pName, bool fConst1 )
{
Abc_Obj_t * pNet, * pTerm;
- pTerm = fConst1? Abc_NodeCreateConst1(pNtk) : Abc_NodeCreateConst0(pNtk);
+ pTerm = fConst1? Abc_NtkCreateNodeConst1(pNtk) : Abc_NtkCreateNodeConst0(pNtk);
pNet = Abc_NtkFindNet(pNtk, pName); assert( pNet );
Abc_ObjAddFanin( pNet, pTerm );
return pTerm;
@@ -167,7 +663,7 @@ Abc_Obj_t * Io_ReadCreateInv( Abc_Ntk_t * pNtk, char * pNameIn, char * pNameOut
{
Abc_Obj_t * pNet, * pNode;
pNet = Abc_NtkFindNet(pNtk, pNameIn); assert( pNet );
- pNode = Abc_NodeCreateInv(pNtk, pNet);
+ pNode = Abc_NtkCreateNodeInv(pNtk, pNet);
pNet = Abc_NtkFindNet(pNtk, pNameOut); assert( pNet );
Abc_ObjAddFanin( pNet, pNode );
return pNode;
@@ -188,12 +684,67 @@ Abc_Obj_t * Io_ReadCreateBuf( Abc_Ntk_t * pNtk, char * pNameIn, char * pNameOut
{
Abc_Obj_t * pNet, * pNode;
pNet = Abc_NtkFindNet(pNtk, pNameIn); assert( pNet );
- pNode = Abc_NodeCreateBuf(pNtk, pNet);
+ pNode = Abc_NtkCreateNodeBuf(pNtk, pNet);
pNet = Abc_NtkFindNet(pNtk, pNameOut); assert( pNet );
Abc_ObjAddFanin( pNet, pNode );
return pNet;
}
+
+/**Function*************************************************************
+
+ Synopsis [Provide an fopen replacement with path lookup]
+
+ Description [Provide an fopen replacement where the path stored
+ in pathvar MVSIS variable is used to look up the path
+ for name. Returns NULL if file cannot be opened.]
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+FILE * Io_FileOpen( const char * FileName, const char * PathVar, const char * Mode, int fVerbose )
+{
+ char * t = 0, * c = 0, * i;
+ extern char * Abc_FrameReadFlag( char * pFlag );
+
+ if ( PathVar == 0 )
+ {
+ return fopen( FileName, Mode );
+ }
+ else
+ {
+ if ( c = Abc_FrameReadFlag( (char*)PathVar ) )
+ {
+ char ActualFileName[4096];
+ FILE * fp = 0;
+ t = Extra_UtilStrsav( c );
+ for (i = strtok( t, ":" ); i != 0; i = strtok( 0, ":") )
+ {
+#ifdef WIN32
+ _snprintf ( ActualFileName, 4096, "%s/%s", i, FileName );
+#else
+ snprintf ( ActualFileName, 4096, "%s/%s", i, FileName );
+#endif
+ if ( ( fp = fopen ( ActualFileName, Mode ) ) )
+ {
+ if ( fVerbose )
+ fprintf ( stdout, "Using file %s\n", ActualFileName );
+ free( t );
+ return fp;
+ }
+ }
+ free( t );
+ return 0;
+ }
+ else
+ {
+ return fopen( FileName, Mode );
+ }
+ }
+}
+
////////////////////////////////////////////////////////////////////////
/// END OF FILE ///
////////////////////////////////////////////////////////////////////////
diff --git a/src/base/io/ioWriteAiger.c b/src/base/io/ioWriteAiger.c
new file mode 100644
index 00000000..758e5335
--- /dev/null
+++ b/src/base/io/ioWriteAiger.c
@@ -0,0 +1,375 @@
+/**CFile****************************************************************
+
+ FileName [ioWriteAiger.c]
+
+ SystemName [ABC: Logic synthesis and verification system.]
+
+ PackageName [Command processing package.]
+
+ Synopsis [Procedures to write binary AIGER format developed by
+ Armin Biere, Johannes Kepler University (http://fmv.jku.at/)]
+
+ Author [Alan Mishchenko]
+
+ Affiliation [UC Berkeley]
+
+ Date [Ver. 1.0. Started - December 16, 2006.]
+
+ Revision [$Id: ioWriteAiger.c,v 1.00 2006/12/16 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "io.h"
+
+////////////////////////////////////////////////////////////////////////
+/// DECLARATIONS ///
+////////////////////////////////////////////////////////////////////////
+
+/*
+ The following is taken from the AIGER format description,
+ which can be found at http://fmv.jku.at/aiger
+*/
+
+
+/*
+ The AIGER And-Inverter Graph (AIG) Format Version 20061129
+ ----------------------------------------------------------
+ Armin Biere, Johannes Kepler University, 2006
+
+ This report describes the AIG file format as used by the AIGER library.
+ The purpose of this report is not only to motivate and document the
+ format, but also to allow independent implementations of writers and
+ readers by giving precise and unambiguous definitions.
+
+ ...
+
+Introduction
+
+ The name AIGER contains as one part the acronym AIG of And-Inverter
+ Graphs and also if pronounced in German sounds like the name of the
+ 'Eiger', a mountain in the Swiss alps. This choice should emphasize the
+ origin of this format. It was first openly discussed at the Alpine
+ Verification Meeting 2006 in Ascona as a way to provide a simple, compact
+ file format for a model checking competition affiliated to CAV 2007.
+
+ ...
+
+Binary Format Definition
+
+ The binary format is semantically a subset of the ASCII format with a
+ slightly different syntax. The binary format may need to reencode
+ literals, but translating a file in binary format into ASCII format and
+ then back in to binary format will result in the same file.
+
+ The main differences of the binary format to the ASCII format are as
+ follows. After the header the list of input literals and all the
+ current state literals of a latch can be omitted. Furthermore the
+ definitions of the AND gates are binary encoded. However, the symbol
+ table and the comment section are as in the ASCII format.
+
+ The header of an AIGER file in binary format has 'aig' as format
+ identifier, but otherwise is identical to the ASCII header. The standard
+ file extension for the binary format is therefore '.aig'.
+
+ A header for the binary format is still in ASCII encoding:
+
+ aig M I L O A
+
+ Constants, variables and literals are handled in the same way as in the
+ ASCII format. The first simplifying restriction is on the variable
+ indices of inputs and latches. The variable indices of inputs come first,
+ followed by the pseudo-primary inputs of the latches and then the variable
+ indices of all LHS of AND gates:
+
+ input variable indices 1, 2, ... , I
+ latch variable indices I+1, I+2, ... , (I+L)
+ AND variable indices I+L+1, I+L+2, ... , (I+L+A) == M
+
+ The corresponding unsigned literals are
+
+ input literals 2, 4, ... , 2*I
+ latch literals 2*I+2, 2*I+4, ... , 2*(I+L)
+ AND literals 2*(I+L)+2, 2*(I+L)+4, ... , 2*(I+L+A) == 2*M
+
+ All literals have to be defined, and therefore 'M = I + L + A'. With this
+ restriction it becomes possible that the inputs and the current state
+ literals of the latches do not have to be listed explicitly. Therefore,
+ after the header only the list of 'L' next state literals follows, one per
+ latch on a single line, and then the 'O' outputs, again one per line.
+
+ In the binary format we assume that the AND gates are ordered and respect
+ the child parent relation. AND gates with smaller literals on the LHS
+ come first. Therefore we can assume that the literals on the right-hand
+ side of a definition of an AND gate are smaller than the LHS literal.
+ Furthermore we can sort the literals on the RHS, such that the larger
+ literal comes first. A definition thus consists of three literals
+
+ lhs rhs0 rhs1
+
+ with 'lhs' even and 'lhs > rhs0 >= rhs1'. Also the variable indices are
+ pairwise different to avoid combinational self loops. Since the LHS
+ indices of the definitions are all consecutive (as even integers),
+ the binary format does not have to keep 'lhs'. In addition, we can use
+ the order restriction and only write the differences 'delta0' and 'delta1'
+ instead of 'rhs0' and 'rhs1', with
+
+ delta0 = lhs - rhs0, delta1 = rhs0 - rhs1
+
+ The differences will all be strictly positive, and in practice often very
+ small. We can take advantage of this fact by the simple little-endian
+ encoding of unsigned integers of the next section. After the binary delta
+ encoding of the RHSs of all AND gates, the optional symbol table and
+ optional comment section start in the same format as in the ASCII case.
+
+ ...
+
+*/
+
+static unsigned Io_ObjMakeLit( int Var, int fCompl ) { return (Var << 1) | fCompl; }
+static unsigned Io_ObjAigerNum( Abc_Obj_t * pObj ) { return (unsigned)pObj->pCopy; }
+static void Io_ObjSetAigerNum( Abc_Obj_t * pObj, unsigned Num ) { pObj->pCopy = (void *)Num; }
+
+////////////////////////////////////////////////////////////////////////
+/// FUNCTION DEFINITIONS ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+ Synopsis [Adds one unsigned AIG edge to the output buffer.]
+
+ Description [This procedure is a slightly modified version of Armin Biere's
+ procedure "void encode (FILE * file, unsigned x)" ]
+
+ SideEffects [Returns the current writing position.]
+
+ SeeAlso []
+
+***********************************************************************/
+int Io_WriteAigerEncode( char * pBuffer, int Pos, unsigned x )
+{
+ unsigned char ch;
+ while (x & ~0x7f)
+ {
+ ch = (x & 0x7f) | 0x80;
+// putc (ch, file);
+ pBuffer[Pos++] = ch;
+ x >>= 7;
+ }
+ ch = x;
+// putc (ch, file);
+ pBuffer[Pos++] = ch;
+ return Pos;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Create the array of literals to be written.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Vec_Int_t * Io_WriteAigerLiterals( Abc_Ntk_t * pNtk )
+{
+ Vec_Int_t * vLits;
+ Abc_Obj_t * pObj, * pDriver;
+ int i;
+ vLits = Vec_IntAlloc( Abc_NtkCoNum(pNtk) );
+ Abc_NtkForEachLatchInput( pNtk, pObj, i )
+ {
+ pDriver = Abc_ObjFanin0(pObj);
+ Vec_IntPush( vLits, Io_ObjMakeLit( Io_ObjAigerNum(pDriver), Abc_ObjFaninC0(pObj) ^ (Io_ObjAigerNum(pDriver) == 0) ) );
+ }
+ Abc_NtkForEachPo( pNtk, pObj, i )
+ {
+ pDriver = Abc_ObjFanin0(pObj);
+ Vec_IntPush( vLits, Io_ObjMakeLit( Io_ObjAigerNum(pDriver), Abc_ObjFaninC0(pObj) ^ (Io_ObjAigerNum(pDriver) == 0) ) );
+ }
+ return vLits;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Creates the binary encoded array of literals.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Vec_Str_t * Io_WriteEncodeLiterals( Vec_Int_t * vLits )
+{
+ Vec_Str_t * vBinary;
+ int Pos = 0, Lit, LitPrev, Diff, i;
+ vBinary = Vec_StrAlloc( 2 * Vec_IntSize(vLits) );
+ LitPrev = Vec_IntEntry( vLits, 0 );
+ Pos = Io_WriteAigerEncode( Vec_StrArray(vBinary), Pos, LitPrev );
+ Vec_IntForEachEntryStart( vLits, Lit, i, 1 )
+ {
+ Diff = Lit - LitPrev;
+ Diff = (Lit < LitPrev)? -Diff : Diff;
+ Diff = (Diff << 1) | (int)(Lit < LitPrev);
+ Pos = Io_WriteAigerEncode( Vec_StrArray(vBinary), Pos, Diff );
+ LitPrev = Lit;
+ if ( Pos + 10 > vBinary->nCap )
+ Vec_StrGrow( vBinary, vBinary->nCap+1 );
+ }
+ vBinary->nSize = Pos;
+/*
+ // verify
+ {
+ extern Vec_Int_t * Io_WriteDecodeLiterals( char ** ppPos, int nEntries );
+ char * pPos = Vec_StrArray( vBinary );
+ Vec_Int_t * vTemp = Io_WriteDecodeLiterals( &pPos, Vec_IntSize(vLits) );
+ for ( i = 0; i < Vec_IntSize(vLits); i++ )
+ {
+ int Entry1 = Vec_IntEntry(vLits,i);
+ int Entry2 = Vec_IntEntry(vTemp,i);
+ assert( Entry1 == Entry2 );
+ }
+ }
+*/
+ return vBinary;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Writes the AIG in the binary AIGER format.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Io_WriteAiger( Abc_Ntk_t * pNtk, char * pFileName, int fWriteSymbols, int fCompact )
+{
+ ProgressBar * pProgress;
+ FILE * pFile;
+ Abc_Obj_t * pObj, * pDriver;
+ int i, nNodes, Pos, nBufferSize;
+ unsigned char * pBuffer;
+ unsigned uLit0, uLit1, uLit;
+
+ assert( Abc_NtkIsStrash(pNtk) );
+ // start the output stream
+ pFile = fopen( pFileName, "wb" );
+ if ( pFile == NULL )
+ {
+ fprintf( stdout, "Io_WriteAiger(): Cannot open the output file \"%s\".\n", pFileName );
+ return;
+ }
+ Abc_NtkForEachLatch( pNtk, pObj, i )
+ if ( !Abc_LatchIsInit0(pObj) )
+ {
+ fprintf( stdout, "Io_WriteAiger(): Cannot write AIGER format with non-0 latch init values. Run \"zero\".\n" );
+ return;
+ }
+
+ // set the node numbers to be used in the output file
+ nNodes = 0;
+ Io_ObjSetAigerNum( Abc_AigConst1(pNtk), nNodes++ );
+ Abc_NtkForEachCi( pNtk, pObj, i )
+ Io_ObjSetAigerNum( pObj, nNodes++ );
+ Abc_AigForEachAnd( pNtk, pObj, i )
+ Io_ObjSetAigerNum( pObj, nNodes++ );
+
+ // write the header "M I L O A" where M = I + L + A
+ fprintf( pFile, "aig%s %u %u %u %u %u\n",
+ fCompact? "2" : "",
+ Abc_NtkPiNum(pNtk) + Abc_NtkLatchNum(pNtk) + Abc_NtkNodeNum(pNtk),
+ Abc_NtkPiNum(pNtk),
+ Abc_NtkLatchNum(pNtk),
+ Abc_NtkPoNum(pNtk),
+ Abc_NtkNodeNum(pNtk) );
+
+ // if the driver node is a constant, we need to complement the literal below
+ // because, in the AIGER format, literal 0/1 is represented as number 0/1
+ // while, in ABC, constant 1 node has number 0 and so literal 0/1 will be 1/0
+
+ if ( !fCompact )
+ {
+ // write latch drivers
+ Abc_NtkForEachLatchInput( pNtk, pObj, i )
+ {
+ pDriver = Abc_ObjFanin0(pObj);
+ fprintf( pFile, "%u\n", Io_ObjMakeLit( Io_ObjAigerNum(pDriver), Abc_ObjFaninC0(pObj) ^ (Io_ObjAigerNum(pDriver) == 0) ) );
+ }
+ // write PO drivers
+ Abc_NtkForEachPo( pNtk, pObj, i )
+ {
+ pDriver = Abc_ObjFanin0(pObj);
+ fprintf( pFile, "%u\n", Io_ObjMakeLit( Io_ObjAigerNum(pDriver), Abc_ObjFaninC0(pObj) ^ (Io_ObjAigerNum(pDriver) == 0) ) );
+ }
+ }
+ else
+ {
+ Vec_Int_t * vLits = Io_WriteAigerLiterals( pNtk );
+ Vec_Str_t * vBinary = Io_WriteEncodeLiterals( vLits );
+ fwrite( Vec_StrArray(vBinary), 1, Vec_StrSize(vBinary), pFile );
+ Vec_StrFree( vBinary );
+ Vec_IntFree( vLits );
+ }
+
+ // write the nodes into the buffer
+ Pos = 0;
+ nBufferSize = 6 * Abc_NtkNodeNum(pNtk) + 100; // skeptically assuming 3 chars per one AIG edge
+ pBuffer = ALLOC( unsigned char, nBufferSize );
+ pProgress = Extra_ProgressBarStart( stdout, Abc_NtkObjNumMax(pNtk) );
+ Abc_AigForEachAnd( pNtk, pObj, i )
+ {
+ Extra_ProgressBarUpdate( pProgress, i, NULL );
+ uLit = Io_ObjMakeLit( Io_ObjAigerNum(pObj), 0 );
+ uLit0 = Io_ObjMakeLit( Io_ObjAigerNum(Abc_ObjFanin0(pObj)), Abc_ObjFaninC0(pObj) );
+ uLit1 = Io_ObjMakeLit( Io_ObjAigerNum(Abc_ObjFanin1(pObj)), Abc_ObjFaninC1(pObj) );
+ assert( uLit0 < uLit1 );
+ Pos = Io_WriteAigerEncode( pBuffer, Pos, (unsigned)(uLit - uLit1) );
+ Pos = Io_WriteAigerEncode( pBuffer, Pos, (unsigned)(uLit1 - uLit0) );
+ if ( Pos > nBufferSize - 10 )
+ {
+ printf( "Io_WriteAiger(): AIGER generation has failed because the allocated buffer is too small.\n" );
+ fclose( pFile );
+ return;
+ }
+ }
+ assert( Pos < nBufferSize );
+ Extra_ProgressBarStop( pProgress );
+
+ // write the buffer
+ fwrite( pBuffer, 1, Pos, pFile );
+ free( pBuffer );
+
+ // write the symbol table
+ if ( fWriteSymbols )
+ {
+ // write PIs
+ Abc_NtkForEachPi( pNtk, pObj, i )
+ fprintf( pFile, "i%d %s\n", i, Abc_ObjName(pObj) );
+ // write latches
+ Abc_NtkForEachLatch( pNtk, pObj, i )
+ fprintf( pFile, "l%d %s\n", i, Abc_ObjName(Abc_ObjFanout0(pObj)) );
+ // write POs
+ Abc_NtkForEachPo( pNtk, pObj, i )
+ fprintf( pFile, "o%d %s\n", i, Abc_ObjName(pObj) );
+ }
+
+ // write the comment
+ fprintf( pFile, "c\n" );
+ if ( pNtk->pName && strlen(pNtk->pName) > 0 )
+ fprintf( pFile, ".model %s\n", pNtk->pName );
+ fprintf( pFile, "This file was produced by ABC on %s\n", Extra_TimeStamp() );
+ fprintf( pFile, "For information about AIGER format, refer to %s\n", "http://fmv.jku.at/aiger" );
+ fclose( pFile );
+}
+
+////////////////////////////////////////////////////////////////////////
+/// END OF FILE ///
+////////////////////////////////////////////////////////////////////////
+
+
diff --git a/src/base/io/ioWriteBaf.c b/src/base/io/ioWriteBaf.c
new file mode 100644
index 00000000..fc0229a4
--- /dev/null
+++ b/src/base/io/ioWriteBaf.c
@@ -0,0 +1,168 @@
+/**CFile****************************************************************
+
+ FileName [ioWriteBaf.c]
+
+ SystemName [ABC: Logic synthesis and verification system.]
+
+ PackageName [Command processing package.]
+
+ Synopsis [Procedures to write AIG in the binary format.]
+
+ Author [Alan Mishchenko]
+
+ Affiliation [UC Berkeley]
+
+ Date [Ver. 1.0. Started - June 20, 2005.]
+
+ Revision [$Id: ioWriteBaf.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "io.h"
+
+////////////////////////////////////////////////////////////////////////
+/// DECLARATIONS ///
+////////////////////////////////////////////////////////////////////////
+
+/*
+ Binary Aig Format
+
+ The motivation for this format is to have
+ - compact binary representation of large AIGs (~10x more compact than BLIF)
+ - consequently, fast reading/writing of large AIGs (~10x faster than BLIF)
+ - representation for all tech-ind info related to an AIG
+ - human-readable file header
+
+ The header:
+ (1) May contain several lines of human-readable comments.
+ Each comment line begins with symbol '#' and ends with symbol '\n'.
+ (2) Always contains the following data.
+ - benchmark name
+ - number of primary inputs
+ - number of primary outputs
+ - number of latches
+ - number of AIG nodes (excluding the constant 1 node)
+ Each entry is followed by 0-byte (character '\0'):
+ (3) Next follow the names of the PIs, POs, and latches in this order.
+ Each name is followed by 0-byte (character '\0').
+ Inside each set of names (PIs, POs, latches) there should be no
+ identical names but the PO names may coincide with PI/latch names.
+
+ The body:
+ (1) First part of the body contains binary information about the internal AIG nodes.
+ Each internal AIG node is represented using two edges (each edge is a 4-byte integer).
+ Each integer is the fanin ID followed by 1-bit representation of the complemented attribute.
+ (For example, complemented edge to node 10 will be represented as 2*10 + 1 = 21.)
+ The IDs of the nodes are created as follows: Constant 1 node has ID=0.
+ CIs (PIs and latch outputs) have 1-based IDs assigned in that order.
+ Each node in the array of the internal AIG nodes has the ID assigned in that order.
+ The constant 1 node is not written into the file.
+ (2) Second part of the body contains binary information about the edges connecting
+ the COs (POs and latch inputs) to the internal AIG nodes.
+ Each edge is a 4-byte integer the same way as a node fanin.
+ The latch initial value (2 bits) is stored in this integer.
+*/
+
+////////////////////////////////////////////////////////////////////////
+/// FUNCTION DEFINITIONS ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+ Synopsis [Writes the AIG in the binary format.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Io_WriteBaf( Abc_Ntk_t * pNtk, char * pFileName )
+{
+ ProgressBar * pProgress;
+ FILE * pFile;
+ Abc_Obj_t * pObj;
+ int i, nNodes, nAnds, nBufferSize;
+ unsigned * pBufferNode;
+ assert( Abc_NtkIsStrash(pNtk) );
+ // start the output stream
+ pFile = fopen( pFileName, "wb" );
+ if ( pFile == NULL )
+ {
+ fprintf( stdout, "Io_WriteBaf(): Cannot open the output file \"%s\".\n", pFileName );
+ return;
+ }
+
+ // write the comment
+ fprintf( pFile, "# BAF (Binary Aig Format) for \"%s\" written by ABC on %s\n", pNtk->pName, Extra_TimeStamp() );
+
+ // write the network name
+ fprintf( pFile, "%s%c", pNtk->pName, 0 );
+ // write the number of PIs
+ fprintf( pFile, "%d%c", Abc_NtkPiNum(pNtk), 0 );
+ // write the number of POs
+ fprintf( pFile, "%d%c", Abc_NtkPoNum(pNtk), 0 );
+ // write the number of latches
+ fprintf( pFile, "%d%c", Abc_NtkLatchNum(pNtk), 0 );
+ // write the number of internal nodes
+ fprintf( pFile, "%d%c", Abc_NtkNodeNum(pNtk), 0 );
+
+ // write PIs
+ Abc_NtkForEachPi( pNtk, pObj, i )
+ fprintf( pFile, "%s%c", Abc_ObjName(pObj), 0 );
+ // write POs
+ Abc_NtkForEachPo( pNtk, pObj, i )
+ fprintf( pFile, "%s%c", Abc_ObjName(pObj), 0 );
+ // write latches
+ Abc_NtkForEachLatch( pNtk, pObj, i )
+ {
+ fprintf( pFile, "%s%c", Abc_ObjName(pObj), 0 );
+ fprintf( pFile, "%s%c", Abc_ObjName(Abc_ObjFanin0(pObj)), 0 );
+ fprintf( pFile, "%s%c", Abc_ObjName(Abc_ObjFanout0(pObj)), 0 );
+ }
+
+ // set the node numbers to be used in the output file
+ Abc_NtkCleanCopy( pNtk );
+ nNodes = 1;
+ Abc_NtkForEachCi( pNtk, pObj, i )
+ pObj->pCopy = (void *)nNodes++;
+ Abc_AigForEachAnd( pNtk, pObj, i )
+ pObj->pCopy = (void *)nNodes++;
+
+ // write the nodes into the buffer
+ nAnds = 0;
+ nBufferSize = Abc_NtkNodeNum(pNtk) * 2 + Abc_NtkCoNum(pNtk);
+ pBufferNode = ALLOC( int, nBufferSize );
+ pProgress = Extra_ProgressBarStart( stdout, nBufferSize );
+ Abc_AigForEachAnd( pNtk, pObj, i )
+ {
+ Extra_ProgressBarUpdate( pProgress, nAnds, NULL );
+ pBufferNode[nAnds++] = (((int)Abc_ObjFanin0(pObj)->pCopy) << 1) | Abc_ObjFaninC0(pObj);
+ pBufferNode[nAnds++] = (((int)Abc_ObjFanin1(pObj)->pCopy) << 1) | Abc_ObjFaninC1(pObj);
+ }
+
+ // write the COs into the buffer
+ Abc_NtkForEachCo( pNtk, pObj, i )
+ {
+ Extra_ProgressBarUpdate( pProgress, nAnds, NULL );
+ pBufferNode[nAnds] = (((int)Abc_ObjFanin0(pObj)->pCopy) << 1) | Abc_ObjFaninC0(pObj);
+ if ( Abc_ObjFanoutNum(pObj) > 0 && Abc_ObjIsLatch(Abc_ObjFanout0(pObj)) )
+ pBufferNode[nAnds] = (pBufferNode[nAnds] << 2) | ((unsigned)Abc_ObjData(Abc_ObjFanout0(pObj)) & 3);
+ nAnds++;
+ }
+ Extra_ProgressBarStop( pProgress );
+ assert( nBufferSize == nAnds );
+
+ // write the buffer
+ fwrite( pBufferNode, 1, sizeof(int) * nBufferSize, pFile );
+ fclose( pFile );
+ free( pBufferNode );
+}
+
+
+////////////////////////////////////////////////////////////////////////
+/// END OF FILE ///
+////////////////////////////////////////////////////////////////////////
+
+
diff --git a/src/base/io/ioWriteBench.c b/src/base/io/ioWriteBench.c
index df79227d..4b766a47 100644
--- a/src/base/io/ioWriteBench.c
+++ b/src/base/io/ioWriteBench.c
@@ -24,11 +24,16 @@
/// DECLARATIONS ///
////////////////////////////////////////////////////////////////////////
-static int Io_WriteBenchOne( FILE * pFile, Abc_Ntk_t * pNtk );
-static int Io_WriteBenchOneNode( FILE * pFile, Abc_Obj_t * pNode );
+static int Io_WriteBenchCheckNames( Abc_Ntk_t * pNtk );
+
+static int Io_WriteBenchOne( FILE * pFile, Abc_Ntk_t * pNtk );
+static int Io_WriteBenchOneNode( FILE * pFile, Abc_Obj_t * pNode );
+
+static int Io_WriteBenchLutOne( FILE * pFile, Abc_Ntk_t * pNtk );
+static int Io_WriteBenchLutOneNode( FILE * pFile, Abc_Obj_t * pNode, Vec_Int_t * vTruth );
////////////////////////////////////////////////////////////////////////
-/// FUNCTION DEFITIONS ///
+/// FUNCTION DEFINITIONS ///
////////////////////////////////////////////////////////////////////////
/**Function*************************************************************
@@ -47,6 +52,11 @@ int Io_WriteBench( Abc_Ntk_t * pNtk, char * pFileName )
Abc_Ntk_t * pExdc;
FILE * pFile;
assert( Abc_NtkIsSopNetlist(pNtk) );
+ if ( !Io_WriteBenchCheckNames(pNtk) )
+ {
+ fprintf( stdout, "Io_WriteBench(): Signal names in this benchmark contain parantheses making them impossible to reproduce in the BENCH format. Use \"short_names\".\n" );
+ return 0;
+ }
pFile = fopen( pFileName, "w" );
if ( pFile == NULL )
{
@@ -89,7 +99,7 @@ int Io_WriteBenchOne( FILE * pFile, Abc_Ntk_t * pNtk )
fprintf( pFile, "OUTPUT(%s)\n", Abc_ObjName(Abc_ObjFanin0(pNode)) );
Abc_NtkForEachLatch( pNtk, pNode, i )
fprintf( pFile, "%-11s = DFF(%s)\n",
- Abc_ObjName(pNode), Abc_ObjName(Abc_ObjFanin0(pNode)) );
+ Abc_ObjName(Abc_ObjFanout0(Abc_ObjFanout0(pNode))), Abc_ObjName(Abc_ObjFanin0(Abc_ObjFanin0(pNode))) );
// write internal nodes
pProgress = Extra_ProgressBarStart( stdout, Abc_NtkObjNumMax(pNtk) );
@@ -148,6 +158,176 @@ int Io_WriteBenchOneNode( FILE * pFile, Abc_Obj_t * pNode )
return 1;
}
+/**Function*************************************************************
+
+ Synopsis [Writes the network in BENCH format with LUTs and DFFRSE.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Io_WriteBenchLut( Abc_Ntk_t * pNtk, char * pFileName )
+{
+ Abc_Ntk_t * pExdc;
+ FILE * pFile;
+ assert( Abc_NtkIsAigNetlist(pNtk) );
+ if ( !Io_WriteBenchCheckNames(pNtk) )
+ {
+ fprintf( stdout, "Io_WriteBenchLut(): Signal names in this benchmark contain parantheses making them impossible to reproduce in the BENCH format. Use \"short_names\".\n" );
+ return 0;
+ }
+ pFile = fopen( pFileName, "w" );
+ if ( pFile == NULL )
+ {
+ fprintf( stdout, "Io_WriteBench(): Cannot open the output file.\n" );
+ return 0;
+ }
+ fprintf( pFile, "# Benchmark \"%s\" written by ABC on %s\n", pNtk->pName, Extra_TimeStamp() );
+ // write the network
+ Io_WriteBenchLutOne( pFile, pNtk );
+ // write EXDC network if it exists
+ pExdc = Abc_NtkExdc( pNtk );
+ if ( pExdc )
+ printf( "Io_WriteBench: EXDC is not written (warning).\n" );
+ // finalize the file
+ fclose( pFile );
+ return 1;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Writes the network in BENCH format.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Io_WriteBenchLutOne( FILE * pFile, Abc_Ntk_t * pNtk )
+{
+ ProgressBar * pProgress;
+ Abc_Obj_t * pNode;
+ Vec_Int_t * vMemory;
+ int i;
+
+ // write the PIs/POs/latches
+ Abc_NtkForEachPi( pNtk, pNode, i )
+ fprintf( pFile, "INPUT(%s)\n", Abc_ObjName(Abc_ObjFanout0(pNode)) );
+ Abc_NtkForEachPo( pNtk, pNode, i )
+ fprintf( pFile, "OUTPUT(%s)\n", Abc_ObjName(Abc_ObjFanin0(pNode)) );
+ Abc_NtkForEachLatch( pNtk, pNode, i )
+ fprintf( pFile, "%-11s = DFFRSE( %s, gnd, gnd, gnd, gnd )\n",
+ Abc_ObjName(Abc_ObjFanout0(Abc_ObjFanout0(pNode))), Abc_ObjName(Abc_ObjFanin0(Abc_ObjFanin0(pNode))) );
+//Abc_NtkLevel(pNtk);
+ // write internal nodes
+ vMemory = Vec_IntAlloc( 10000 );
+ pProgress = Extra_ProgressBarStart( stdout, Abc_NtkObjNumMax(pNtk) );
+ Abc_NtkForEachNode( pNtk, pNode, i )
+ {
+ Extra_ProgressBarUpdate( pProgress, i, NULL );
+ Io_WriteBenchLutOneNode( pFile, pNode, vMemory );
+ }
+ Extra_ProgressBarStop( pProgress );
+ Vec_IntFree( vMemory );
+ return 1;
+}
+
+
+/**Function*************************************************************
+
+ Synopsis [Writes the network in BENCH format.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Io_WriteBenchLutOneNode( FILE * pFile, Abc_Obj_t * pNode, Vec_Int_t * vTruth )
+{
+ Abc_Obj_t * pFanin;
+ unsigned * pTruth;
+ int i, nFanins;
+ assert( Abc_ObjIsNode(pNode) );
+ nFanins = Abc_ObjFaninNum(pNode);
+ assert( nFanins <= 8 );
+ // compute the truth table
+ pTruth = Abc_ConvertAigToTruth( pNode->pNtk->pManFunc, Hop_Regular(pNode->pData), nFanins, vTruth, 0 );
+ if ( Hop_IsComplement(pNode->pData) )
+ Extra_TruthNot( pTruth, pTruth, nFanins );
+ // consider simple cases
+ if ( Extra_TruthIsConst0(pTruth, nFanins) )
+ {
+ fprintf( pFile, "%-11s = gnd\n", Abc_ObjName(Abc_ObjFanout0(pNode)) );
+ return 1;
+ }
+ if ( Extra_TruthIsConst1(pTruth, nFanins) )
+ {
+ fprintf( pFile, "%-11s = vdd\n", Abc_ObjName(Abc_ObjFanout0(pNode)) );
+ return 1;
+ }
+ if ( nFanins == 1 )
+ {
+ fprintf( pFile, "%-11s = LUT 0x%d ( %s )\n",
+ Abc_ObjName(Abc_ObjFanout0(pNode)),
+ Abc_NodeIsBuf(pNode)? 2 : 1,
+ Abc_ObjName(Abc_ObjFanin0(pNode)) );
+ return 1;
+ }
+ // write it in the hexadecimal form
+ fprintf( pFile, "%-11s = LUT 0x", Abc_ObjName(Abc_ObjFanout0(pNode)) );
+ Extra_PrintHexadecimal( pFile, pTruth, nFanins );
+/*
+ {
+extern void Kit_DsdTest( unsigned * pTruth, int nVars );
+Abc_ObjForEachFanin( pNode, pFanin, i )
+printf( "%c%d ", 'a'+i, Abc_ObjFanin0(pFanin)->Level );
+printf( "\n" );
+Kit_DsdTest( pTruth, nFanins );
+ }
+ if ( pNode->Id % 1000 == 0 )
+ {
+ int x = 0;
+ }
+*/
+ // write the fanins
+ fprintf( pFile, " (" );
+ Abc_ObjForEachFanin( pNode, pFanin, i )
+ fprintf( pFile, " %s%s", Abc_ObjName(pFanin), ((i==nFanins-1)? "" : ",") );
+ fprintf( pFile, " )\n" );
+ return 1;
+}
+
+
+/**Function*************************************************************
+
+ Synopsis [Returns 1 if the names cannot be written into the bench file.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Io_WriteBenchCheckNames( Abc_Ntk_t * pNtk )
+{
+ Abc_Obj_t * pObj;
+ char * pName;
+ int i;
+ Abc_NtkForEachObj( pNtk, pObj, i )
+ for ( pName = Nm_ManFindNameById(pNtk->pManName, i); pName && *pName; pName++ )
+ if ( *pName == '(' || *pName == ')' )
+ return 0;
+ return 1;
+}
+
////////////////////////////////////////////////////////////////////////
/// END OF FILE ///
////////////////////////////////////////////////////////////////////////
diff --git a/src/base/io/ioWriteBlif.c b/src/base/io/ioWriteBlif.c
index 7d6815b9..c0c29d65 100644
--- a/src/base/io/ioWriteBlif.c
+++ b/src/base/io/ioWriteBlif.c
@@ -26,16 +26,19 @@
/// DECLARATIONS ///
////////////////////////////////////////////////////////////////////////
+static void Io_NtkWrite( FILE * pFile, Abc_Ntk_t * pNtk, int fWriteLatches );
static void Io_NtkWriteOne( FILE * pFile, Abc_Ntk_t * pNtk, int fWriteLatches );
static void Io_NtkWritePis( FILE * pFile, Abc_Ntk_t * pNtk, int fWriteLatches );
static void Io_NtkWritePos( FILE * pFile, Abc_Ntk_t * pNtk, int fWriteLatches );
-static void Io_NtkWriteNodeGate( FILE * pFile, Abc_Obj_t * pNode );
+static void Io_NtkWriteSubckt( FILE * pFile, Abc_Obj_t * pNode );
+static void Io_NtkWriteAsserts( FILE * pFile, Abc_Ntk_t * pNtk );
+static void Io_NtkWriteNodeGate( FILE * pFile, Abc_Obj_t * pNode, int Length );
static void Io_NtkWriteNodeFanins( FILE * pFile, Abc_Obj_t * pNode );
-static void Io_NtkWriteNode( FILE * pFile, Abc_Obj_t * pNode );
+static void Io_NtkWriteNode( FILE * pFile, Abc_Obj_t * pNode, int Length );
static void Io_NtkWriteLatch( FILE * pFile, Abc_Obj_t * pLatch );
////////////////////////////////////////////////////////////////////////
-/// FUNCTION DEFITIONS ///
+/// FUNCTION DEFINITIONS ///
////////////////////////////////////////////////////////////////////////
/**Function*************************************************************
@@ -53,7 +56,7 @@ void Io_WriteBlifLogic( Abc_Ntk_t * pNtk, char * FileName, int fWriteLatches )
{
Abc_Ntk_t * pNtkTemp;
// derive the netlist
- pNtkTemp = Abc_NtkLogicToNetlist(pNtk);
+ pNtkTemp = Abc_NtkToNetlist(pNtk);
if ( pNtkTemp == NULL )
{
fprintf( stdout, "Writing BLIF has failed.\n" );
@@ -76,17 +79,52 @@ void Io_WriteBlifLogic( Abc_Ntk_t * pNtk, char * FileName, int fWriteLatches )
***********************************************************************/
void Io_WriteBlif( Abc_Ntk_t * pNtk, char * FileName, int fWriteLatches )
{
- Abc_Ntk_t * pExdc;
FILE * pFile;
+ Abc_Ntk_t * pNtkTemp;
+ int i;
assert( Abc_NtkIsNetlist(pNtk) );
+ // start writing the file
pFile = fopen( FileName, "w" );
if ( pFile == NULL )
{
fprintf( stdout, "Io_WriteBlif(): Cannot open the output file.\n" );
return;
}
- // write the model name
fprintf( pFile, "# Benchmark \"%s\" written by ABC on %s\n", pNtk->pName, Extra_TimeStamp() );
+ // write the master network
+ Io_NtkWrite( pFile, pNtk, fWriteLatches );
+ // make sure there is no logic hierarchy
+ assert( Abc_NtkWhiteboxNum(pNtk) == 0 );
+ // write the hierarchy if present
+ if ( Abc_NtkBlackboxNum(pNtk) > 0 )
+ {
+ Vec_PtrForEachEntry( pNtk->pDesign->vModules, pNtkTemp, i )
+ {
+ if ( pNtkTemp == pNtk )
+ continue;
+ fprintf( pFile, "\n\n" );
+ Io_NtkWrite( pFile, pNtkTemp, fWriteLatches );
+ }
+ }
+ fclose( pFile );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Write the network into a BLIF file with the given name.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Io_NtkWrite( FILE * pFile, Abc_Ntk_t * pNtk, int fWriteLatches )
+{
+ Abc_Ntk_t * pExdc;
+ assert( Abc_NtkIsNetlist(pNtk) );
+ // write the model name
fprintf( pFile, ".model %s\n", Abc_NtkName(pNtk) );
// write the network
Io_NtkWriteOne( pFile, pNtk, fWriteLatches );
@@ -100,7 +138,6 @@ void Io_WriteBlif( Abc_Ntk_t * pNtk, char * FileName, int fWriteLatches )
}
// finalize the file
fprintf( pFile, ".end\n" );
- fclose( pFile );
}
/**Function*************************************************************
@@ -118,7 +155,7 @@ void Io_NtkWriteOne( FILE * pFile, Abc_Ntk_t * pNtk, int fWriteLatches )
{
ProgressBar * pProgress;
Abc_Obj_t * pNode, * pLatch;
- int i;
+ int i, Length;
// write the PIs
fprintf( pFile, ".inputs" );
@@ -130,6 +167,21 @@ void Io_NtkWriteOne( FILE * pFile, Abc_Ntk_t * pNtk, int fWriteLatches )
Io_NtkWritePos( pFile, pNtk, fWriteLatches );
fprintf( pFile, "\n" );
+ // write the assertions
+ if ( Abc_NtkAssertNum(pNtk) )
+ {
+ fprintf( pFile, ".asserts" );
+ Io_NtkWriteAsserts( pFile, pNtk );
+ fprintf( pFile, "\n" );
+ }
+
+ // write the blackbox
+ if ( Abc_NtkHasBlackbox( pNtk ) )
+ {
+ fprintf( pFile, ".blackbox\n" );
+ return;
+ }
+
// write the timing info
Io_WriteTimingInfo( pFile, pNtk );
@@ -142,12 +194,23 @@ void Io_NtkWriteOne( FILE * pFile, Abc_Ntk_t * pNtk, int fWriteLatches )
fprintf( pFile, "\n" );
}
+ // write the subcircuits
+ assert( Abc_NtkWhiteboxNum(pNtk) == 0 );
+ if ( Abc_NtkBlackboxNum(pNtk) > 0 )
+ {
+ fprintf( pFile, "\n" );
+ Abc_NtkForEachBlackbox( pNtk, pNode, i )
+ Io_NtkWriteSubckt( pFile, pNode );
+ fprintf( pFile, "\n" );
+ }
+
// write each internal node
+ Length = Abc_NtkHasMapping(pNtk)? Mio_LibraryReadGateNameMax(pNtk->pManFunc) : 0;
pProgress = Extra_ProgressBarStart( stdout, Abc_NtkObjNumMax(pNtk) );
Abc_NtkForEachNode( pNtk, pNode, i )
{
Extra_ProgressBarUpdate( pProgress, i, NULL );
- Io_NtkWriteNode( pFile, pNode );
+ Io_NtkWriteNode( pFile, pNode, Length );
}
Extra_ProgressBarStop( pProgress );
}
@@ -260,6 +323,8 @@ void Io_NtkWritePos( FILE * pFile, Abc_Ntk_t * pNtk, int fWriteLatches )
{
Abc_NtkForEachCo( pNtk, pTerm, i )
{
+ if ( Abc_ObjIsAssert(pTerm) )
+ continue;
pNet = Abc_ObjFanin0(pTerm);
// get the line length after this name is written
AddedLength = strlen(Abc_ObjName(pNet)) + 1;
@@ -277,6 +342,80 @@ void Io_NtkWritePos( FILE * pFile, Abc_Ntk_t * pNtk, int fWriteLatches )
}
}
+/**Function*************************************************************
+
+ Synopsis [Writes the assertion list.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Io_NtkWriteAsserts( FILE * pFile, Abc_Ntk_t * pNtk )
+{
+ Abc_Obj_t * pTerm, * pNet;
+ int LineLength;
+ int AddedLength;
+ int NameCounter;
+ int i;
+
+ LineLength = 8;
+ NameCounter = 0;
+
+ Abc_NtkForEachAssert( pNtk, pTerm, i )
+ {
+ pNet = Abc_ObjFanin0(pTerm);
+ // get the line length after this name is written
+ AddedLength = strlen(Abc_ObjName(pNet)) + 1;
+ if ( NameCounter && LineLength + AddedLength + 3 > IO_WRITE_LINE_LENGTH )
+ { // write the line extender
+ fprintf( pFile, " \\\n" );
+ // reset the line length
+ LineLength = 0;
+ NameCounter = 0;
+ }
+ fprintf( pFile, " %s", Abc_ObjName(pNet) );
+ LineLength += AddedLength;
+ NameCounter++;
+ }
+}
+
+/**Function*************************************************************
+
+ Synopsis [Write the latch into a file.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Io_NtkWriteSubckt( FILE * pFile, Abc_Obj_t * pNode )
+{
+ Abc_Ntk_t * pModel = pNode->pData;
+ Abc_Obj_t * pTerm;
+ int i;
+ // write the subcircuit
+// fprintf( pFile, ".subckt %s %s", Abc_NtkName(pModel), Abc_ObjName(pNode) );
+ fprintf( pFile, ".subckt %s", Abc_NtkName(pModel) );
+ // write pairs of the formal=actual names
+ Abc_NtkForEachPi( pModel, pTerm, i )
+ {
+ fprintf( pFile, " %s", Abc_ObjName(Abc_ObjFanout0(pTerm)) );
+ pTerm = Abc_ObjFanin( pNode, i );
+ fprintf( pFile, "=%s", Abc_ObjName(Abc_ObjFanin0(pTerm)) );
+ }
+ Abc_NtkForEachPo( pModel, pTerm, i )
+ {
+ fprintf( pFile, " %s", Abc_ObjName(Abc_ObjFanin0(pTerm)) );
+ pTerm = Abc_ObjFanout( pNode, i );
+ fprintf( pFile, "=%s", Abc_ObjName(Abc_ObjFanout0(pTerm)) );
+ }
+ fprintf( pFile, "\n" );
+}
/**Function*************************************************************
@@ -293,14 +432,14 @@ void Io_NtkWriteLatch( FILE * pFile, Abc_Obj_t * pLatch )
{
Abc_Obj_t * pNetLi, * pNetLo;
int Reset;
- pNetLi = Abc_ObjFanin0( pLatch );
- pNetLo = Abc_ObjFanout0( pLatch );
+ pNetLi = Abc_ObjFanin0( Abc_ObjFanin0(pLatch) );
+ pNetLo = Abc_ObjFanout0( Abc_ObjFanout0(pLatch) );
Reset = (int)Abc_ObjData( pLatch );
// write the latch line
fprintf( pFile, ".latch" );
fprintf( pFile, " %10s", Abc_ObjName(pNetLi) );
fprintf( pFile, " %10s", Abc_ObjName(pNetLo) );
- fprintf( pFile, " %d\n", Reset );
+ fprintf( pFile, " %d\n", Reset-1 );
}
@@ -315,13 +454,13 @@ void Io_NtkWriteLatch( FILE * pFile, Abc_Obj_t * pLatch )
SeeAlso []
***********************************************************************/
-void Io_NtkWriteNode( FILE * pFile, Abc_Obj_t * pNode )
+void Io_NtkWriteNode( FILE * pFile, Abc_Obj_t * pNode, int Length )
{
if ( Abc_NtkHasMapping(pNode->pNtk) )
{
// write the .gate line
fprintf( pFile, ".gate" );
- Io_NtkWriteNodeGate( pFile, pNode );
+ Io_NtkWriteNodeGate( pFile, pNode, Length );
fprintf( pFile, "\n" );
}
else
@@ -346,17 +485,17 @@ void Io_NtkWriteNode( FILE * pFile, Abc_Obj_t * pNode )
SeeAlso []
***********************************************************************/
-void Io_NtkWriteNodeGate( FILE * pFile, Abc_Obj_t * pNode )
+void Io_NtkWriteNodeGate( FILE * pFile, Abc_Obj_t * pNode, int Length )
{
Mio_Gate_t * pGate = pNode->pData;
Mio_Pin_t * pGatePin;
int i;
// write the node
- fprintf( pFile, " %s ", Mio_GateReadName(pGate) );
+ fprintf( pFile, " %-*s ", Length, Mio_GateReadName(pGate) );
for ( pGatePin = Mio_GateReadPins(pGate), i = 0; pGatePin; pGatePin = Mio_PinReadNext(pGatePin), i++ )
fprintf( pFile, "%s=%s ", Mio_PinReadName(pGatePin), Abc_ObjName( Abc_ObjFanin(pNode,i) ) );
assert ( i == Abc_ObjFaninNum(pNode) );
- fprintf( pFile, "%s=%s", Mio_GateReadOutName(pGate), Abc_ObjName(pNode) );
+ fprintf( pFile, "%s=%s", Mio_GateReadOutName(pGate), Abc_ObjName( Abc_ObjFanout0(pNode) ) );
}
/**Function*************************************************************
diff --git a/src/base/io/ioWriteBlifMv.c b/src/base/io/ioWriteBlifMv.c
new file mode 100644
index 00000000..775a2e07
--- /dev/null
+++ b/src/base/io/ioWriteBlifMv.c
@@ -0,0 +1,519 @@
+/**CFile****************************************************************
+
+ FileName [ioWriteBlifMv.c]
+
+ SystemName [ABC: Logic synthesis and verification system.]
+
+ PackageName [Command processing package.]
+
+ Synopsis [Procedures to write BLIF-MV files.]
+
+ Author [Alan Mishchenko]
+
+ Affiliation [UC Berkeley]
+
+ Date [Ver. 1.0. Started - June 20, 2005.]
+
+ Revision [$Id: ioWriteBlifMv.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "io.h"
+#include "main.h"
+#include "mio.h"
+
+////////////////////////////////////////////////////////////////////////
+/// DECLARATIONS ///
+////////////////////////////////////////////////////////////////////////
+
+static void Io_NtkWriteBlifMv( FILE * pFile, Abc_Ntk_t * pNtk );
+static void Io_NtkWriteBlifMvOne( FILE * pFile, Abc_Ntk_t * pNtk );
+static void Io_NtkWriteBlifMvPis( FILE * pFile, Abc_Ntk_t * pNtk );
+static void Io_NtkWriteBlifMvPos( FILE * pFile, Abc_Ntk_t * pNtk );
+static void Io_NtkWriteBlifMvAsserts( FILE * pFile, Abc_Ntk_t * pNtk );
+static void Io_NtkWriteBlifMvNodeFanins( FILE * pFile, Abc_Obj_t * pNode );
+static void Io_NtkWriteBlifMvNode( FILE * pFile, Abc_Obj_t * pNode );
+static void Io_NtkWriteBlifMvLatch( FILE * pFile, Abc_Obj_t * pLatch );
+static void Io_NtkWriteBlifMvSubckt( FILE * pFile, Abc_Obj_t * pNode );
+static void Io_NtkWriteBlifMvValues( FILE * pFile, Abc_Obj_t * pNode );
+
+////////////////////////////////////////////////////////////////////////
+/// FUNCTION DEFINITIONS ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+ Synopsis [Write the network into a BLIF file with the given name.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Io_WriteBlifMv( Abc_Ntk_t * pNtk, char * FileName )
+{
+ FILE * pFile;
+ Abc_Ntk_t * pNtkTemp;
+ int i;
+ assert( Abc_NtkIsNetlist(pNtk) );
+ assert( Abc_NtkHasBlifMv(pNtk) );
+ // start writing the file
+ pFile = fopen( FileName, "w" );
+ if ( pFile == NULL )
+ {
+ fprintf( stdout, "Io_WriteBlifMv(): Cannot open the output file.\n" );
+ return;
+ }
+ fprintf( pFile, "# Benchmark \"%s\" written by ABC on %s\n", pNtk->pName, Extra_TimeStamp() );
+ // write the master network
+ Io_NtkWriteBlifMv( pFile, pNtk );
+ // write the remaining networks
+ if ( pNtk->pDesign )
+ {
+ Vec_PtrForEachEntry( pNtk->pDesign->vModules, pNtkTemp, i )
+ {
+ if ( pNtkTemp == pNtk )
+ continue;
+ fprintf( pFile, "\n\n" );
+ Io_NtkWriteBlifMv( pFile, pNtkTemp );
+ }
+ }
+ fclose( pFile );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Write the network into a BLIF file with the given name.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Io_NtkWriteBlifMv( FILE * pFile, Abc_Ntk_t * pNtk )
+{
+ assert( Abc_NtkIsNetlist(pNtk) );
+ // write the model name
+ fprintf( pFile, ".model %s\n", Abc_NtkName(pNtk) );
+ // write the network
+ Io_NtkWriteBlifMvOne( pFile, pNtk );
+ // write EXDC network if it exists
+ if ( Abc_NtkExdc(pNtk) )
+ printf( "Io_NtkWriteBlifMv(): EXDC is not written.\n" );
+ // finalize the file
+ fprintf( pFile, ".end\n\n\n" );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Write one network.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Io_NtkWriteBlifMvOne( FILE * pFile, Abc_Ntk_t * pNtk )
+{
+ ProgressBar * pProgress;
+ Abc_Obj_t * pNode, * pTerm, * pLatch;
+ int i;
+
+ // write the PIs
+ fprintf( pFile, ".inputs" );
+ Io_NtkWriteBlifMvPis( pFile, pNtk );
+ fprintf( pFile, "\n" );
+
+ // write the POs
+ fprintf( pFile, ".outputs" );
+ Io_NtkWriteBlifMvPos( pFile, pNtk );
+ fprintf( pFile, "\n" );
+
+ // write the assertions
+ if ( Abc_NtkAssertNum(pNtk) )
+ {
+ fprintf( pFile, ".asserts" );
+ Io_NtkWriteBlifMvAsserts( pFile, pNtk );
+ fprintf( pFile, "\n" );
+ }
+
+ // write the MV directives
+ fprintf( pFile, "\n" );
+ Abc_NtkForEachCi( pNtk, pTerm, i )
+ if ( Abc_ObjMvVarNum(Abc_ObjFanout0(pTerm)) > 2 )
+ fprintf( pFile, ".mv %s %d\n", Abc_ObjName(Abc_ObjFanout0(pTerm)), Abc_ObjMvVarNum(Abc_ObjFanout0(pTerm)) );
+ Abc_NtkForEachCo( pNtk, pTerm, i )
+ if ( Abc_ObjMvVarNum(Abc_ObjFanin0(pTerm)) > 2 )
+ fprintf( pFile, ".mv %s %d\n", Abc_ObjName(Abc_ObjFanin0(pTerm)), Abc_ObjMvVarNum(Abc_ObjFanin0(pTerm)) );
+
+ // write the blackbox
+ if ( Abc_NtkHasBlackbox( pNtk ) )
+ {
+ fprintf( pFile, ".blackbox\n" );
+ return;
+ }
+
+ // write the timing info
+// Io_WriteTimingInfo( pFile, pNtk );
+
+ // write the latches
+ if ( !Abc_NtkIsComb(pNtk) )
+ {
+ fprintf( pFile, "\n" );
+ Abc_NtkForEachLatch( pNtk, pLatch, i )
+ Io_NtkWriteBlifMvLatch( pFile, pLatch );
+ fprintf( pFile, "\n" );
+ }
+/*
+ // write the subcircuits
+ assert( Abc_NtkWhiteboxNum(pNtk) == 0 );
+ if ( Abc_NtkBlackboxNum(pNtk) > 0 )
+ {
+ fprintf( pFile, "\n" );
+ Abc_NtkForEachBlackbox( pNtk, pNode, i )
+ Io_NtkWriteBlifMvSubckt( pFile, pNode );
+ fprintf( pFile, "\n" );
+ }
+*/
+ if ( Abc_NtkBlackboxNum(pNtk) > 0 || Abc_NtkWhiteboxNum(pNtk) > 0 )
+ {
+ fprintf( pFile, "\n" );
+ Abc_NtkForEachBox( pNtk, pNode, i )
+ {
+ if ( Abc_ObjIsLatch(pNode) )
+ continue;
+ Io_NtkWriteBlifMvSubckt( pFile, pNode );
+ }
+ fprintf( pFile, "\n" );
+ }
+
+ // write each internal node
+ pProgress = Extra_ProgressBarStart( stdout, Abc_NtkObjNumMax(pNtk) );
+ Abc_NtkForEachNode( pNtk, pNode, i )
+ {
+ Extra_ProgressBarUpdate( pProgress, i, NULL );
+ Io_NtkWriteBlifMvNode( pFile, pNode );
+ }
+ Extra_ProgressBarStop( pProgress );
+}
+
+
+/**Function*************************************************************
+
+ Synopsis [Writes the primary input list.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Io_NtkWriteBlifMvPis( FILE * pFile, Abc_Ntk_t * pNtk )
+{
+ Abc_Obj_t * pTerm, * pNet;
+ int LineLength;
+ int AddedLength;
+ int NameCounter;
+ int i;
+
+ LineLength = 7;
+ NameCounter = 0;
+
+ Abc_NtkForEachPi( pNtk, pTerm, i )
+ {
+ pNet = Abc_ObjFanout0(pTerm);
+ // get the line length after this name is written
+ AddedLength = strlen(Abc_ObjName(pNet)) + 1;
+ if ( NameCounter && LineLength + AddedLength + 3 > IO_WRITE_LINE_LENGTH )
+ { // write the line extender
+ fprintf( pFile, " \\\n" );
+ // reset the line length
+ LineLength = 0;
+ NameCounter = 0;
+ }
+ fprintf( pFile, " %s", Abc_ObjName(pNet) );
+ LineLength += AddedLength;
+ NameCounter++;
+ }
+}
+
+/**Function*************************************************************
+
+ Synopsis [Writes the primary input list.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Io_NtkWriteBlifMvPos( FILE * pFile, Abc_Ntk_t * pNtk )
+{
+ Abc_Obj_t * pTerm, * pNet;
+ int LineLength;
+ int AddedLength;
+ int NameCounter;
+ int i;
+
+ LineLength = 8;
+ NameCounter = 0;
+
+ Abc_NtkForEachPo( pNtk, pTerm, i )
+ {
+ pNet = Abc_ObjFanin0(pTerm);
+ // get the line length after this name is written
+ AddedLength = strlen(Abc_ObjName(pNet)) + 1;
+ if ( NameCounter && LineLength + AddedLength + 3 > IO_WRITE_LINE_LENGTH )
+ { // write the line extender
+ fprintf( pFile, " \\\n" );
+ // reset the line length
+ LineLength = 0;
+ NameCounter = 0;
+ }
+ fprintf( pFile, " %s", Abc_ObjName(pNet) );
+ LineLength += AddedLength;
+ NameCounter++;
+ }
+}
+
+/**Function*************************************************************
+
+ Synopsis [Writes the assertion list.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Io_NtkWriteBlifMvAsserts( FILE * pFile, Abc_Ntk_t * pNtk )
+{
+ Abc_Obj_t * pTerm, * pNet;
+ int LineLength;
+ int AddedLength;
+ int NameCounter;
+ int i;
+
+ LineLength = 8;
+ NameCounter = 0;
+
+ Abc_NtkForEachAssert( pNtk, pTerm, i )
+ {
+ pNet = Abc_ObjFanin0(pTerm);
+ // get the line length after this name is written
+ AddedLength = strlen(Abc_ObjName(pNet)) + 1;
+ if ( NameCounter && LineLength + AddedLength + 3 > IO_WRITE_LINE_LENGTH )
+ { // write the line extender
+ fprintf( pFile, " \\\n" );
+ // reset the line length
+ LineLength = 0;
+ NameCounter = 0;
+ }
+ fprintf( pFile, " %s", Abc_ObjName(pNet) );
+ LineLength += AddedLength;
+ NameCounter++;
+ }
+}
+
+/**Function*************************************************************
+
+ Synopsis [Write the latch into a file.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Io_NtkWriteBlifMvLatch( FILE * pFile, Abc_Obj_t * pLatch )
+{
+ Abc_Obj_t * pNetLi, * pNetLo;
+ int Reset;
+ pNetLi = Abc_ObjFanin0( Abc_ObjFanin0(pLatch) );
+ pNetLo = Abc_ObjFanout0( Abc_ObjFanout0(pLatch) );
+ Reset = (int)Abc_ObjData( pLatch );
+ // write the latch line
+ fprintf( pFile, ".latch" );
+ fprintf( pFile, " %10s", Abc_ObjName(pNetLi) );
+ fprintf( pFile, " %10s", Abc_ObjName(pNetLo) );
+ fprintf( pFile, "\n" );
+ // write the reset node
+ fprintf( pFile, ".reset %s\n", Abc_ObjName(pNetLo) );
+ fprintf( pFile, "%d\n", Reset-1 );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Write the latch into a file.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Io_NtkWriteBlifMvSubckt( FILE * pFile, Abc_Obj_t * pNode )
+{
+ Abc_Ntk_t * pModel = pNode->pData;
+ Abc_Obj_t * pTerm;
+ int i;
+ // write the MV directives
+ fprintf( pFile, "\n" );
+ Abc_ObjForEachFanin( pNode, pTerm, i )
+ if ( Abc_ObjMvVarNum(pTerm) > 2 )
+ fprintf( pFile, ".mv %s %d\n", Abc_ObjName(pTerm), Abc_ObjMvVarNum(pTerm) );
+ Abc_ObjForEachFanout( pNode, pTerm, i )
+ if ( Abc_ObjMvVarNum(pTerm) > 2 )
+ fprintf( pFile, ".mv %s %d\n", Abc_ObjName(pTerm), Abc_ObjMvVarNum(pTerm) );
+ // write the subcircuit
+ fprintf( pFile, ".subckt %s %s", Abc_NtkName(pModel), Abc_ObjName(pNode) );
+ // write pairs of the formal=actual names
+ Abc_NtkForEachPi( pModel, pTerm, i )
+ {
+ fprintf( pFile, " %s", Abc_ObjName(Abc_ObjFanout0(pTerm)) );
+ pTerm = Abc_ObjFanin( pNode, i );
+ fprintf( pFile, "=%s", Abc_ObjName(Abc_ObjFanin0(pTerm)) );
+ }
+ Abc_NtkForEachPo( pModel, pTerm, i )
+ {
+ fprintf( pFile, " %s", Abc_ObjName(Abc_ObjFanin0(pTerm)) );
+ pTerm = Abc_ObjFanout( pNode, i );
+ fprintf( pFile, "=%s", Abc_ObjName(Abc_ObjFanout0(pTerm)) );
+ }
+ fprintf( pFile, "\n" );
+}
+
+
+/**Function*************************************************************
+
+ Synopsis [Write the node into a file.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Io_NtkWriteBlifMvNode( FILE * pFile, Abc_Obj_t * pNode )
+{
+ Abc_Obj_t * pFanin;
+ char * pCur;
+ int nValues, iFanin, i;
+
+ // write .mv directives for the fanins
+ fprintf( pFile, "\n" );
+ Abc_ObjForEachFanin( pNode, pFanin, i )
+ {
+// nValues = atoi(pCur);
+ nValues = Abc_ObjMvVarNum( pFanin );
+ if ( nValues > 2 )
+ fprintf( pFile, ".mv %s %d\n", Abc_ObjName(pFanin), nValues );
+// while ( *pCur++ != ' ' );
+ }
+
+ // write .mv directives for the node
+// nValues = atoi(pCur);
+ nValues = Abc_ObjMvVarNum( Abc_ObjFanout0(pNode) );
+ if ( nValues > 2 )
+ fprintf( pFile, ".mv %s %d\n", Abc_ObjName(Abc_ObjFanout0(pNode)), nValues );
+// while ( *pCur++ != '\n' );
+
+ // write the .names line
+ fprintf( pFile, ".table" );
+ Io_NtkWriteBlifMvNodeFanins( pFile, pNode );
+ fprintf( pFile, "\n" );
+
+ // write the cubes
+ pCur = Abc_ObjData(pNode);
+ if ( *pCur == 'd' )
+ {
+ fprintf( pFile, ".default " );
+ pCur++;
+ }
+ // write the literals
+ for ( ; *pCur; pCur++ )
+ {
+ fprintf( pFile, "%c", *pCur );
+ if ( *pCur != '=' )
+ continue;
+ // get the number
+ iFanin = atoi( pCur+1 );
+ fprintf( pFile, "%s", Abc_ObjName(Abc_ObjFanin(pNode,iFanin)) );
+ // scroll on to the next symbol
+ while ( *pCur != ' ' && *pCur != '\n' )
+ pCur++;
+ pCur--;
+ }
+}
+
+/**Function*************************************************************
+
+ Synopsis [Writes the primary input list.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Io_NtkWriteBlifMvNodeFanins( FILE * pFile, Abc_Obj_t * pNode )
+{
+ Abc_Obj_t * pNet;
+ int LineLength;
+ int AddedLength;
+ int NameCounter;
+ char * pName;
+ int i;
+
+ LineLength = 6;
+ NameCounter = 0;
+ Abc_ObjForEachFanin( pNode, pNet, i )
+ {
+ // get the fanin name
+ pName = Abc_ObjName(pNet);
+ // get the line length after the fanin name is written
+ AddedLength = strlen(pName) + 1;
+ if ( NameCounter && LineLength + AddedLength + 3 > IO_WRITE_LINE_LENGTH )
+ { // write the line extender
+ fprintf( pFile, " \\\n" );
+ // reset the line length
+ LineLength = 0;
+ NameCounter = 0;
+ }
+ fprintf( pFile, " %s", pName );
+ LineLength += AddedLength;
+ NameCounter++;
+ }
+
+ // get the output name
+ pName = Abc_ObjName(Abc_ObjFanout0(pNode));
+ // get the line length after the output name is written
+ AddedLength = strlen(pName) + 1;
+ if ( NameCounter && LineLength + AddedLength > 75 )
+ { // write the line extender
+ fprintf( pFile, " \\\n" );
+ // reset the line length
+ LineLength = 0;
+ NameCounter = 0;
+ }
+ fprintf( pFile, " %s", pName );
+}
+
+////////////////////////////////////////////////////////////////////////
+/// END OF FILE ///
+////////////////////////////////////////////////////////////////////////
+
+
diff --git a/src/base/io/ioWriteCnf.c b/src/base/io/ioWriteCnf.c
index 09824f38..e1b2d956 100644
--- a/src/base/io/ioWriteCnf.c
+++ b/src/base/io/ioWriteCnf.c
@@ -19,13 +19,16 @@
***********************************************************************/
#include "io.h"
+#include "satSolver.h"
////////////////////////////////////////////////////////////////////////
/// DECLARATIONS ///
////////////////////////////////////////////////////////////////////////
+
+static Abc_Ntk_t * s_pNtk = NULL;
////////////////////////////////////////////////////////////////////////
-/// FUNCTION DEFITIONS ///
+/// FUNCTION DEFINITIONS ///
////////////////////////////////////////////////////////////////////////
/**Function*************************************************************
@@ -39,33 +42,71 @@
SeeAlso []
***********************************************************************/
-int Io_WriteCnf( Abc_Ntk_t * pNtk, char * pFileName )
+int Io_WriteCnf( Abc_Ntk_t * pNtk, char * pFileName, int fAllPrimes )
{
- solver * pSat;
- if ( !Abc_NtkIsBddLogic(pNtk) )
+ sat_solver * pSat;
+ if ( Abc_NtkIsStrash(pNtk) )
+ printf( "Io_WriteCnf() warning: Generating CNF by applying heuristic AIG to CNF conversion.\n" );
+ else
+ printf( "Io_WriteCnf() warning: Generating CNF by convering logic nodes into CNF clauses.\n" );
+ if ( Abc_NtkPoNum(pNtk) != 1 )
{
- fprintf( stdout, "Io_WriteCnf(): Currently can only process logic networks with BDDs.\n" );
+ fprintf( stdout, "Io_WriteCnf(): Currently can only process the miter (the network with one PO).\n" );
return 0;
}
- if ( Abc_NtkPoNum(pNtk) != 1 )
+ if ( Abc_NtkLatchNum(pNtk) != 0 )
{
- fprintf( stdout, "Io_WriteCnf(): Currently can only solve the miter (the network with one PO).\n" );
+ fprintf( stdout, "Io_WriteCnf(): Currently can only process the miter for combinational circuits.\n" );
return 0;
}
- if ( Abc_NtkLatchNum(pNtk) != 0 )
+ if ( Abc_NtkNodeNum(pNtk) == 0 )
{
- fprintf( stdout, "Io_WriteCnf(): Currently can only solve the miter for combinational circuits.\n" );
+ fprintf( stdout, "The network has no logic nodes. No CNF file is generaled.\n" );
return 0;
}
+ // convert to logic BDD network
+ if ( Abc_NtkIsLogic(pNtk) )
+ Abc_NtkToBdd( pNtk );
// create solver with clauses
- pSat = Abc_NtkMiterSatCreate( pNtk );
+ pSat = Abc_NtkMiterSatCreate( pNtk, fAllPrimes );
+ if ( pSat == NULL )
+ {
+ fprintf( stdout, "The problem is trivially UNSAT. No CNF file is generated.\n" );
+ return 1;
+ }
// write the clauses
- Asat_SolverWriteDimacs( pSat, pFileName );
+ s_pNtk = pNtk;
+ Sat_SolverWriteDimacs( pSat, pFileName, 0, 0, 1 );
+ s_pNtk = NULL;
// free the solver
- solver_delete( pSat );
+ sat_solver_delete( pSat );
return 1;
}
+/**Function*************************************************************
+
+ Synopsis [Output the mapping of PIs into variable numbers.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Io_WriteCnfOutputPiMapping( FILE * pFile, int incrementVars )
+{
+ extern Vec_Int_t * Abc_NtkGetCiSatVarNums( Abc_Ntk_t * pNtk );
+ Abc_Ntk_t * pNtk = s_pNtk;
+ Vec_Int_t * vCiIds;
+ Abc_Obj_t * pObj;
+ int i;
+ vCiIds = Abc_NtkGetCiSatVarNums( pNtk );
+ fprintf( pFile, "c PI variable numbers: <PI_name> <SAT_var_number>\n" );
+ Abc_NtkForEachCi( pNtk, pObj, i )
+ fprintf( pFile, "c %s %d\n", Abc_ObjName(pObj), Vec_IntEntry(vCiIds, i) + (int)(incrementVars > 0) );
+ Vec_IntFree( vCiIds );
+}
////////////////////////////////////////////////////////////////////////
/// END OF FILE ///
diff --git a/src/base/io/ioWriteDot.c b/src/base/io/ioWriteDot.c
index 97258c81..8ae3cc42 100644
--- a/src/base/io/ioWriteDot.c
+++ b/src/base/io/ioWriteDot.c
@@ -19,18 +19,23 @@
***********************************************************************/
#include "io.h"
+#include "main.h"
+#include "mio.h"
////////////////////////////////////////////////////////////////////////
/// DECLARATIONS ///
////////////////////////////////////////////////////////////////////////
+static char * Abc_NtkPrintSop( char * pSop );
+static int Abc_NtkCountLogicNodes( Vec_Ptr_t * vNodes );
+
////////////////////////////////////////////////////////////////////////
-/// FUNCTION DEFITIONS ///
+/// FUNCTION DEFINITIONS ///
////////////////////////////////////////////////////////////////////////
/**Function*************************************************************
- Synopsis [Writes the graph structure of AIG in DOT.]
+ Synopsis [Writes the graph structure of network for DOT.]
Description [Useful for graph visualization using tools such as GraphViz:
http://www.graphviz.org/]
@@ -40,13 +45,36 @@
SeeAlso []
***********************************************************************/
-void Io_WriteDot( Abc_Ntk_t * pNtk, Vec_Ptr_t * vNodes, Vec_Ptr_t * vNodesShow, char * pFileName )
+void Io_WriteDot( Abc_Ntk_t * pNtk, char * FileName )
+{
+ Vec_Ptr_t * vNodes;
+ vNodes = Abc_NtkCollectObjects( pNtk );
+ Io_WriteDotNtk( pNtk, vNodes, NULL, FileName, 0, 0 );
+ Vec_PtrFree( vNodes );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Writes the graph structure of network for DOT.]
+
+ Description [Useful for graph visualization using tools such as GraphViz:
+ http://www.graphviz.org/]
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Io_WriteDotNtk( Abc_Ntk_t * pNtk, Vec_Ptr_t * vNodes, Vec_Ptr_t * vNodesShow, char * pFileName, int fGateNames, int fUseReverse )
{
FILE * pFile;
- Abc_Obj_t * pNode, * pTemp, * pPrev;
- int LevelMin, LevelMax, fHasCos, Level, i;
+ Abc_Obj_t * pNode, * pFanin;
+ char * pSopString;
+ int LevelMin, LevelMax, fHasCos, Level, i, k, fHasBdds, fCompl;
int Limit = 300;
+ assert( Abc_NtkIsStrash(pNtk) || Abc_NtkIsLogic(pNtk) );
+
if ( vNodes->nSize < 1 )
{
printf( "The set has no nodes. DOT file is not written.\n" );
@@ -66,6 +94,16 @@ void Io_WriteDot( Abc_Ntk_t * pNtk, Vec_Ptr_t * vNodes, Vec_Ptr_t * vNodesShow,
return;
}
+ // transform logic functions from BDD to SOP
+ if ( fHasBdds = Abc_NtkIsBddLogic(pNtk) )
+ {
+ if ( !Abc_NtkBddToSop(pNtk, 0) )
+ {
+ printf( "Io_WriteDotNtk(): Converting to SOPs has failed.\n" );
+ return;
+ }
+ }
+
// mark the nodes from the set
Vec_PtrForEachEntry( vNodes, pNode, i )
pNode->fMarkC = 1;
@@ -73,6 +111,17 @@ void Io_WriteDot( Abc_Ntk_t * pNtk, Vec_Ptr_t * vNodes, Vec_Ptr_t * vNodesShow,
Vec_PtrForEachEntry( vNodesShow, pNode, i )
pNode->fMarkB = 1;
+ // get the levels of nodes
+ LevelMax = Abc_NtkLevel( pNtk );
+ if ( fUseReverse )
+ {
+ LevelMin = Abc_NtkLevelReverse( pNtk );
+ assert( LevelMax == LevelMin );
+ Vec_PtrForEachEntry( vNodes, pNode, i )
+ if ( Abc_ObjIsNode(pNode) )
+ pNode->Level = LevelMax - pNode->Level + 1;
+ }
+
// find the largest and the smallest levels
LevelMin = 10000;
LevelMax = -1;
@@ -102,14 +151,17 @@ void Io_WriteDot( Abc_Ntk_t * pNtk, Vec_Ptr_t * vNodes, Vec_Ptr_t * vNodesShow,
}
// write the DOT header
- fprintf( pFile, "# %s\n", "AIG generated by ABC" );
+ fprintf( pFile, "# %s\n", "Network structure generated by ABC" );
fprintf( pFile, "\n" );
- fprintf( pFile, "digraph AIG {\n" );
+ fprintf( pFile, "digraph network {\n" );
fprintf( pFile, "size = \"7.5,10\";\n" );
+// fprintf( pFile, "size = \"10,8.5\";\n" );
+// fprintf( pFile, "size = \"14,11\";\n" );
+// fprintf( pFile, "page = \"8,11\";\n" );
// fprintf( pFile, "ranksep = 0.5;\n" );
// fprintf( pFile, "nodesep = 0.5;\n" );
fprintf( pFile, "center = true;\n" );
-// fprintf( pFile, "orientation = landscape;\n" );
+// fprintf( pFile, "orientation = landscape;\n" );
// fprintf( pFile, "edge [fontsize = 10];\n" );
// fprintf( pFile, "edge [dir = none];\n" );
fprintf( pFile, "edge [dir = back];\n" );
@@ -158,7 +210,7 @@ void Io_WriteDot( Abc_Ntk_t * pNtk, Vec_Ptr_t * vNodes, Vec_Ptr_t * vNodesShow,
fprintf( pFile, " fontsize=20,\n" );
fprintf( pFile, " fontname = \"Times-Roman\",\n" );
fprintf( pFile, " label=\"" );
- fprintf( pFile, "%s", "AIG generated by ABC" );
+ fprintf( pFile, "%s", "Network structure visualized by ABC" );
fprintf( pFile, "\\n" );
fprintf( pFile, "Benchmark \\\"%s\\\". ", pNtk->pName );
fprintf( pFile, "Time was %s. ", Extra_TimeStamp() );
@@ -176,7 +228,10 @@ void Io_WriteDot( Abc_Ntk_t * pNtk, Vec_Ptr_t * vNodes, Vec_Ptr_t * vNodesShow,
fprintf( pFile, " fontsize=18,\n" );
fprintf( pFile, " fontname = \"Times-Roman\",\n" );
fprintf( pFile, " label=\"" );
- fprintf( pFile, "The set contains %d nodes and spans %d levels.", vNodes->nSize, LevelMax - LevelMin );
+ if ( Abc_NtkObjNum(pNtk) == Vec_PtrSize(vNodes) )
+ fprintf( pFile, "The network contains %d logic nodes and %d latches.", Abc_NtkNodeNum(pNtk), Abc_NtkLatchNum(pNtk) );
+ else
+ fprintf( pFile, "The set contains %d logic nodes and spans %d levels.", Abc_NtkCountLogicNodes(vNodes), LevelMax - LevelMin + 1 );
fprintf( pFile, "\\n" );
fprintf( pFile, "\"\n" );
fprintf( pFile, " ];\n" );
@@ -191,14 +246,16 @@ void Io_WriteDot( Abc_Ntk_t * pNtk, Vec_Ptr_t * vNodes, Vec_Ptr_t * vNodesShow,
fprintf( pFile, " rank = same;\n" );
// the labeling node of this level
fprintf( pFile, " Level%d;\n", LevelMax );
- // generat the PO nodes
+ // generate the PO nodes
Vec_PtrForEachEntry( vNodes, pNode, i )
{
if ( !Abc_ObjIsCo(pNode) )
continue;
- fprintf( pFile, " Node%d%s [label = \"%s%s\"", pNode->Id,
- (Abc_ObjIsLatch(pNode)? "_in":""), Abc_ObjName(pNode), (Abc_ObjIsLatch(pNode)? "_in":"") );
- fprintf( pFile, ", shape = %s", (Abc_ObjIsLatch(pNode)? "box":"invtriangle") );
+ fprintf( pFile, " Node%d [label = \"%s%s\"",
+ pNode->Id,
+ (Abc_ObjIsBi(pNode)? Abc_ObjName(Abc_ObjFanout0(pNode)):Abc_ObjName(pNode)),
+ (Abc_ObjIsBi(pNode)? "_in":"") );
+ fprintf( pFile, ", shape = %s", (Abc_ObjIsBi(pNode)? "box":"invtriangle") );
if ( pNode->fMarkB )
fprintf( pFile, ", style = filled" );
fprintf( pFile, ", color = coral, fillcolor = coral" );
@@ -220,7 +277,19 @@ void Io_WriteDot( Abc_Ntk_t * pNtk, Vec_Ptr_t * vNodes, Vec_Ptr_t * vNodesShow,
{
if ( (int)pNode->Level != Level )
continue;
- fprintf( pFile, " Node%d [label = \"%d\"", pNode->Id, pNode->Id );
+ if ( Abc_ObjFaninNum(pNode) == 0 )
+ continue;
+// fprintf( pFile, " Node%d [label = \"%d\"", pNode->Id, pNode->Id );
+ if ( Abc_NtkIsStrash(pNtk) )
+ pSopString = "";
+ else if ( Abc_NtkHasMapping(pNtk) && fGateNames )
+ pSopString = Mio_GateReadName(pNode->pData);
+ else if ( Abc_NtkHasMapping(pNtk) )
+ pSopString = Abc_NtkPrintSop(Mio_GateReadSop(pNode->pData));
+ else
+ pSopString = Abc_NtkPrintSop(pNode->pData);
+ fprintf( pFile, " Node%d [label = \"%d\\n%s\"", pNode->Id, pNode->Id, pSopString );
+
fprintf( pFile, ", shape = ellipse" );
if ( pNode->fMarkB )
fprintf( pFile, ", style = filled" );
@@ -238,14 +307,27 @@ void Io_WriteDot( Abc_Ntk_t * pNtk, Vec_Ptr_t * vNodes, Vec_Ptr_t * vNodesShow,
fprintf( pFile, " rank = same;\n" );
// the labeling node of this level
fprintf( pFile, " Level%d;\n", LevelMin );
- // generat the PO nodes
+ // generate the PO nodes
Vec_PtrForEachEntry( vNodes, pNode, i )
{
if ( !Abc_ObjIsCi(pNode) )
+ {
+ // check if the costant node is present
+ if ( Abc_ObjFaninNum(pNode) == 0 && Abc_ObjFanoutNum(pNode) > 0 )
+ {
+ fprintf( pFile, " Node%d [label = \"Const%d\"", pNode->Id, Abc_NtkIsStrash(pNode->pNtk) || Abc_NodeIsConst1(pNode) );
+ fprintf( pFile, ", shape = ellipse" );
+ if ( pNode->fMarkB )
+ fprintf( pFile, ", style = filled" );
+ fprintf( pFile, ", color = coral, fillcolor = coral" );
+ fprintf( pFile, "];\n" );
+ }
continue;
- fprintf( pFile, " Node%d%s [label = \"%s%s\"", pNode->Id,
- (Abc_ObjIsLatch(pNode)? "_out":""), Abc_ObjName(pNode), (Abc_ObjIsLatch(pNode)? "_out":"") );
- fprintf( pFile, ", shape = %s", (Abc_ObjIsLatch(pNode)? "box":"triangle") );
+ }
+ fprintf( pFile, " Node%d [label = \"%s\"",
+ pNode->Id,
+ (Abc_ObjIsBo(pNode)? Abc_ObjName(Abc_ObjFanin0(pNode)):Abc_ObjName(pNode)) );
+ fprintf( pFile, ", shape = %s", (Abc_ObjIsBo(pNode)? "box":"triangle") );
if ( pNode->fMarkB )
fprintf( pFile, ", style = filled" );
fprintf( pFile, ", color = coral, fillcolor = coral" );
@@ -262,48 +344,387 @@ void Io_WriteDot( Abc_Ntk_t * pNtk, Vec_Ptr_t * vNodes, Vec_Ptr_t * vNodesShow,
{
if ( (int)pNode->Level != LevelMax )
continue;
- fprintf( pFile, "title2 -> Node%d%s [style = invis];\n", pNode->Id,
- (Abc_ObjIsLatch(pNode)? "_in":"") );
+ fprintf( pFile, "title2 -> Node%d [style = invis];\n", pNode->Id );
}
// generate edges
Vec_PtrForEachEntry( vNodes, pNode, i )
{
- if ( Abc_ObjFaninNum(pNode) == 0 )
+ if ( Abc_ObjIsLatch(pNode) )
continue;
- // generate the edge from this node to the next
- if ( Abc_ObjFanin0(pNode)->fMarkC )
+ Abc_ObjForEachFanin( pNode, pFanin, k )
{
- fprintf( pFile, "Node%d%s", pNode->Id, (Abc_ObjIsLatch(pNode)? "_in":"") );
+ if ( Abc_ObjIsLatch(pFanin) )
+ continue;
+ fCompl = 0;
+ if ( Abc_NtkIsStrash(pNtk) )
+ fCompl = Abc_ObjFaninC(pNode, k);
+ // generate the edge from this node to the next
+ fprintf( pFile, "Node%d", pNode->Id );
fprintf( pFile, " -> " );
- fprintf( pFile, "Node%d%s", Abc_ObjFaninId0(pNode), (Abc_ObjIsLatch(Abc_ObjFanin0(pNode))? "_out":"") );
- fprintf( pFile, " [style = %s]", Abc_ObjFaninC0(pNode)? "dotted" : "bold" );
+ fprintf( pFile, "Node%d", pFanin->Id );
+ fprintf( pFile, " [style = %s", fCompl? "dotted" : "bold" );
+// fprintf( pFile, ", label = \"%c\"", 'a' + k );
+ fprintf( pFile, "]" );
fprintf( pFile, ";\n" );
}
- if ( Abc_ObjFaninNum(pNode) == 1 )
+ }
+
+ fprintf( pFile, "}" );
+ fprintf( pFile, "\n" );
+ fprintf( pFile, "\n" );
+ fclose( pFile );
+
+ // unmark the nodes from the set
+ Vec_PtrForEachEntry( vNodes, pNode, i )
+ pNode->fMarkC = 0;
+ if ( vNodesShow )
+ Vec_PtrForEachEntry( vNodesShow, pNode, i )
+ pNode->fMarkB = 0;
+
+ // convert the network back into BDDs if this is how it was
+ if ( fHasBdds )
+ Abc_NtkSopToBdd(pNtk);
+}
+
+
+/**Function*************************************************************
+
+ Synopsis [Writes the graph structure of network for DOT.]
+
+ Description [Useful for graph visualization using tools such as GraphViz:
+ http://www.graphviz.org/]
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Io_WriteDotSeq( Abc_Ntk_t * pNtk, Vec_Ptr_t * vNodes, Vec_Ptr_t * vNodesShow, char * pFileName, int fGateNames, int fUseReverse )
+{
+ FILE * pFile;
+ Abc_Obj_t * pNode, * pFanin;
+ char * pSopString;
+ int LevelMin, LevelMax, fHasCos, Level, i, k, fHasBdds, fCompl;
+ int Limit = 300;
+
+ assert( Abc_NtkIsStrash(pNtk) || Abc_NtkIsLogic(pNtk) );
+
+ if ( vNodes->nSize < 1 )
+ {
+ printf( "The set has no nodes. DOT file is not written.\n" );
+ return;
+ }
+
+ if ( vNodes->nSize > Limit )
+ {
+ printf( "The set has more than %d nodes. DOT file is not written.\n", Limit );
+ return;
+ }
+
+ // start the stream
+ if ( (pFile = fopen( pFileName, "w" )) == NULL )
+ {
+ fprintf( stdout, "Cannot open the intermediate file \"%s\".\n", pFileName );
+ return;
+ }
+
+ // transform logic functions from BDD to SOP
+ if ( fHasBdds = Abc_NtkIsBddLogic(pNtk) )
+ {
+ if ( !Abc_NtkBddToSop(pNtk, 0) )
+ {
+ printf( "Io_WriteDotNtk(): Converting to SOPs has failed.\n" );
+ return;
+ }
+ }
+
+ // mark the nodes from the set
+ Vec_PtrForEachEntry( vNodes, pNode, i )
+ pNode->fMarkC = 1;
+ if ( vNodesShow )
+ Vec_PtrForEachEntry( vNodesShow, pNode, i )
+ pNode->fMarkB = 1;
+
+ // get the levels of nodes
+ LevelMax = Abc_NtkLevel( pNtk );
+ if ( fUseReverse )
+ {
+ LevelMin = Abc_NtkLevelReverse( pNtk );
+ assert( LevelMax == LevelMin );
+ Vec_PtrForEachEntry( vNodes, pNode, i )
+ if ( Abc_ObjIsNode(pNode) )
+ pNode->Level = LevelMax - pNode->Level + 1;
+ }
+
+ // find the largest and the smallest levels
+ LevelMin = 10000;
+ LevelMax = -1;
+ fHasCos = 0;
+ Vec_PtrForEachEntry( vNodes, pNode, i )
+ {
+ if ( Abc_ObjIsCo(pNode) )
+ {
+ fHasCos = 1;
continue;
- // generate the edge from this node to the next
- if ( Abc_ObjFanin1(pNode)->fMarkC )
+ }
+ if ( LevelMin > (int)pNode->Level )
+ LevelMin = pNode->Level;
+ if ( LevelMax < (int)pNode->Level )
+ LevelMax = pNode->Level;
+ }
+
+ // set the level of the CO nodes
+ if ( fHasCos )
+ {
+ LevelMax++;
+ Vec_PtrForEachEntry( vNodes, pNode, i )
{
- fprintf( pFile, "Node%d", pNode->Id );
- fprintf( pFile, " -> " );
- fprintf( pFile, "Node%d%s", Abc_ObjFaninId1(pNode), (Abc_ObjIsLatch(Abc_ObjFanin1(pNode))? "_out":"") );
- fprintf( pFile, " [style = %s]", Abc_ObjFaninC1(pNode)? "dotted" : "bold" );
- fprintf( pFile, ";\n" );
+ if ( Abc_ObjIsCo(pNode) )
+ pNode->Level = LevelMax;
+ }
+ }
+
+ // write the DOT header
+ fprintf( pFile, "# %s\n", "Network structure generated by ABC" );
+ fprintf( pFile, "\n" );
+ fprintf( pFile, "digraph network {\n" );
+ fprintf( pFile, "size = \"7.5,10\";\n" );
+// fprintf( pFile, "size = \"10,8.5\";\n" );
+// fprintf( pFile, "size = \"14,11\";\n" );
+// fprintf( pFile, "page = \"8,11\";\n" );
+// fprintf( pFile, "ranksep = 0.5;\n" );
+// fprintf( pFile, "nodesep = 0.5;\n" );
+ fprintf( pFile, "center = true;\n" );
+// fprintf( pFile, "orientation = landscape;\n" );
+// fprintf( pFile, "edge [fontsize = 10];\n" );
+// fprintf( pFile, "edge [dir = none];\n" );
+ fprintf( pFile, "edge [dir = back];\n" );
+ fprintf( pFile, "\n" );
+
+ // labels on the left of the picture
+ fprintf( pFile, "{\n" );
+ fprintf( pFile, " node [shape = plaintext];\n" );
+ fprintf( pFile, " edge [style = invis];\n" );
+ fprintf( pFile, " LevelTitle1 [label=\"\"];\n" );
+ fprintf( pFile, " LevelTitle2 [label=\"\"];\n" );
+ // generate node names with labels
+ for ( Level = LevelMax; Level >= LevelMin; Level-- )
+ {
+ // the visible node name
+ fprintf( pFile, " Level%d", Level );
+ fprintf( pFile, " [label = " );
+ // label name
+ fprintf( pFile, "\"" );
+ fprintf( pFile, "\"" );
+ fprintf( pFile, "];\n" );
+ }
+
+ // genetate the sequence of visible/invisible nodes to mark levels
+ fprintf( pFile, " LevelTitle1 -> LevelTitle2 ->" );
+ for ( Level = LevelMax; Level >= LevelMin; Level-- )
+ {
+ // the visible node name
+ fprintf( pFile, " Level%d", Level );
+ // the connector
+ if ( Level != LevelMin )
+ fprintf( pFile, " ->" );
+ else
+ fprintf( pFile, ";" );
+ }
+ fprintf( pFile, "\n" );
+ fprintf( pFile, "}" );
+ fprintf( pFile, "\n" );
+ fprintf( pFile, "\n" );
+
+ // generate title box on top
+ fprintf( pFile, "{\n" );
+ fprintf( pFile, " rank = same;\n" );
+ fprintf( pFile, " LevelTitle1;\n" );
+ fprintf( pFile, " title1 [shape=plaintext,\n" );
+ fprintf( pFile, " fontsize=20,\n" );
+ fprintf( pFile, " fontname = \"Times-Roman\",\n" );
+ fprintf( pFile, " label=\"" );
+ fprintf( pFile, "%s", "Network structure visualized by ABC" );
+ fprintf( pFile, "\\n" );
+ fprintf( pFile, "Benchmark \\\"%s\\\". ", pNtk->pName );
+ fprintf( pFile, "Time was %s. ", Extra_TimeStamp() );
+ fprintf( pFile, "\"\n" );
+ fprintf( pFile, " ];\n" );
+ fprintf( pFile, "}" );
+ fprintf( pFile, "\n" );
+ fprintf( pFile, "\n" );
+
+ // generate statistics box
+ fprintf( pFile, "{\n" );
+ fprintf( pFile, " rank = same;\n" );
+ fprintf( pFile, " LevelTitle2;\n" );
+ fprintf( pFile, " title2 [shape=plaintext,\n" );
+ fprintf( pFile, " fontsize=18,\n" );
+ fprintf( pFile, " fontname = \"Times-Roman\",\n" );
+ fprintf( pFile, " label=\"" );
+ if ( Abc_NtkObjNum(pNtk) == Vec_PtrSize(vNodes) )
+ fprintf( pFile, "The network contains %d logic nodes and %d latches.", Abc_NtkNodeNum(pNtk), Abc_NtkLatchNum(pNtk) );
+ else
+ fprintf( pFile, "The set contains %d logic nodes and spans %d levels.", Abc_NtkCountLogicNodes(vNodes), LevelMax - LevelMin + 1 );
+ fprintf( pFile, "\\n" );
+ fprintf( pFile, "\"\n" );
+ fprintf( pFile, " ];\n" );
+ fprintf( pFile, "}" );
+ fprintf( pFile, "\n" );
+ fprintf( pFile, "\n" );
+
+ // generate the POs
+ if ( fHasCos )
+ {
+ fprintf( pFile, "{\n" );
+ fprintf( pFile, " rank = same;\n" );
+ // the labeling node of this level
+ fprintf( pFile, " Level%d;\n", LevelMax );
+ // generate the PO nodes
+ Vec_PtrForEachEntry( vNodes, pNode, i )
+ {
+ if ( !Abc_ObjIsPo(pNode) )
+ continue;
+ fprintf( pFile, " Node%d [label = \"%s\"", pNode->Id, Abc_ObjName(pNode) );
+ fprintf( pFile, ", shape = %s", "invtriangle" );
+ if ( pNode->fMarkB )
+ fprintf( pFile, ", style = filled" );
+ fprintf( pFile, ", color = coral, fillcolor = coral" );
+ fprintf( pFile, "];\n" );
+ }
+ fprintf( pFile, "}" );
+ fprintf( pFile, "\n" );
+ fprintf( pFile, "\n" );
+ }
+
+ // generate nodes of each rank
+ for ( Level = LevelMax - fHasCos; Level >= LevelMin && Level > 0; Level-- )
+ {
+ fprintf( pFile, "{\n" );
+ fprintf( pFile, " rank = same;\n" );
+ // the labeling node of this level
+ fprintf( pFile, " Level%d;\n", Level );
+ Abc_NtkForEachNode( pNtk, pNode, i )
+ {
+ if ( (int)pNode->Level != Level )
+ continue;
+// fprintf( pFile, " Node%d [label = \"%d\"", pNode->Id, pNode->Id );
+ if ( Abc_NtkIsStrash(pNtk) )
+ pSopString = "";
+ else if ( Abc_NtkHasMapping(pNtk) && fGateNames )
+ pSopString = Mio_GateReadName(pNode->pData);
+ else if ( Abc_NtkHasMapping(pNtk) )
+ pSopString = Abc_NtkPrintSop(Mio_GateReadSop(pNode->pData));
+ else
+ pSopString = Abc_NtkPrintSop(pNode->pData);
+ fprintf( pFile, " Node%d [label = \"%d\\n%s\"", pNode->Id, pNode->Id, pSopString );
+
+ fprintf( pFile, ", shape = ellipse" );
+ if ( pNode->fMarkB )
+ fprintf( pFile, ", style = filled" );
+ fprintf( pFile, "];\n" );
+ }
+ fprintf( pFile, "}" );
+ fprintf( pFile, "\n" );
+ fprintf( pFile, "\n" );
+ }
+
+ // generate the PI nodes if any
+ if ( LevelMin == 0 )
+ {
+ fprintf( pFile, "{\n" );
+ fprintf( pFile, " rank = same;\n" );
+ // the labeling node of this level
+ fprintf( pFile, " Level%d;\n", LevelMin );
+ // generate the PO nodes
+ Vec_PtrForEachEntry( vNodes, pNode, i )
+ {
+ if ( pNode->Level > 0 )
+ continue;
+ if ( !Abc_ObjIsPi(pNode) )
+ {
+ // check if the costant node is present
+ if ( Abc_ObjFaninNum(pNode) == 0 && Abc_ObjFanoutNum(pNode) > 0 )
+ {
+ fprintf( pFile, " Node%d [label = \"Const1\"", pNode->Id );
+ fprintf( pFile, ", shape = ellipse" );
+ if ( pNode->fMarkB )
+ fprintf( pFile, ", style = filled" );
+ fprintf( pFile, ", color = coral, fillcolor = coral" );
+ fprintf( pFile, "];\n" );
+ }
+ continue;
+ }
+ fprintf( pFile, " Node%d [label = \"%s\"", pNode->Id, Abc_ObjName(pNode) );
+ fprintf( pFile, ", shape = %s", "triangle" );
+ if ( pNode->fMarkB )
+ fprintf( pFile, ", style = filled" );
+ fprintf( pFile, ", color = coral, fillcolor = coral" );
+ fprintf( pFile, "];\n" );
}
- // generate the edges between the equivalent nodes
- pPrev = pNode;
- for ( pTemp = pNode->pData; pTemp; pTemp = pTemp->pData )
+ fprintf( pFile, "}" );
+ fprintf( pFile, "\n" );
+ fprintf( pFile, "\n" );
+ }
+
+// fprintf( pFile, "{\n" );
+ Vec_PtrForEachEntry( vNodes, pNode, i )
+ {
+ if ( !Abc_ObjIsLatch(pNode) )
+ continue;
+ fprintf( pFile, "Node%d [label = \"%s\"", pNode->Id, Abc_ObjName(pNode) );
+ fprintf( pFile, ", shape = box" );
+ if ( pNode->fMarkB )
+ fprintf( pFile, ", style = filled" );
+ fprintf( pFile, ", color = coral, fillcolor = coral" );
+ fprintf( pFile, "];\n" );
+ }
+// fprintf( pFile, "}" );
+// fprintf( pFile, "\n" );
+ fprintf( pFile, "\n" );
+
+ // generate invisible edges from the square down
+ fprintf( pFile, "title1 -> title2 [style = invis];\n" );
+ Vec_PtrForEachEntry( vNodes, pNode, i )
+ {
+ if ( (int)pNode->Level != LevelMax )
+ continue;
+ if ( !Abc_ObjIsPo(pNode) )
+ continue;
+ fprintf( pFile, "title2 -> Node%d [style = invis];\n", pNode->Id );
+ }
+
+ // generate edges
+ Vec_PtrForEachEntry( vNodes, pNode, i )
+ {
+ if ( Abc_ObjIsBi(pNode) || Abc_ObjIsBo(pNode) )
+ continue;
+ Abc_ObjForEachFanin( pNode, pFanin, k )
{
- if ( pTemp->fMarkC )
+ fCompl = 0;
+ if ( Abc_NtkIsStrash(pNtk) )
{
- fprintf( pFile, "Node%d", pPrev->Id );
- fprintf( pFile, " -> " );
- fprintf( pFile, "Node%d", pTemp->Id );
- fprintf( pFile, " [style = %s]", (pPrev->fPhase ^ pTemp->fPhase)? "dotted" : "bold" );
- fprintf( pFile, ";\n" );
- pPrev = pTemp;
+ if ( Abc_ObjIsBi(pFanin) )
+ fCompl = Abc_ObjFaninC(pFanin, k);
+ else
+ fCompl = Abc_ObjFaninC(pNode, k);
}
+ if ( Abc_ObjIsBi(pFanin) || Abc_ObjIsBo(pFanin) )
+ pFanin = Abc_ObjFanin0(pFanin);
+ if ( Abc_ObjIsBi(pFanin) || Abc_ObjIsBo(pFanin) )
+ pFanin = Abc_ObjFanin0(pFanin);
+ if ( !pFanin->fMarkC )
+ continue;
+
+ // generate the edge from this node to the next
+ fprintf( pFile, "Node%d", pNode->Id );
+ fprintf( pFile, " -> " );
+ fprintf( pFile, "Node%d", pFanin->Id );
+ fprintf( pFile, " [style = %s", fCompl? "dotted" : "bold" );
+// fprintf( pFile, ", label = \"%c\"", 'a' + k );
+ fprintf( pFile, "]" );
+ fprintf( pFile, ";\n" );
}
}
@@ -318,6 +739,67 @@ void Io_WriteDot( Abc_Ntk_t * pNtk, Vec_Ptr_t * vNodes, Vec_Ptr_t * vNodesShow,
if ( vNodesShow )
Vec_PtrForEachEntry( vNodesShow, pNode, i )
pNode->fMarkB = 0;
+
+ // convert the network back into BDDs if this is how it was
+ if ( fHasBdds )
+ Abc_NtkSopToBdd(pNtk);
+}
+
+
+/**Function*************************************************************
+
+ Synopsis [Computes the printable SOP form.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+char * Abc_NtkPrintSop( char * pSop )
+{
+ static char Buffer[1000];
+ char * pGet, * pSet;
+ pSet = Buffer;
+ for ( pGet = pSop; *pGet; pGet++ )
+ {
+ if ( *pGet == '\n' )
+ {
+ *pSet++ = '\\';
+ *pSet++ = 'n';
+ }
+ else
+ *pSet++ = *pGet;
+ }
+ *(pSet-2) = 0;
+ return Buffer;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Computes the printable SOP form.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Abc_NtkCountLogicNodes( Vec_Ptr_t * vNodes )
+{
+ Abc_Obj_t * pObj;
+ int i, Counter = 0;
+ Vec_PtrForEachEntry( vNodes, pObj, i )
+ {
+ if ( !Abc_ObjIsNode(pObj) )
+ continue;
+ if ( Abc_ObjFaninNum(pObj) == 0 && Abc_ObjFanoutNum(pObj) == 0 )
+ continue;
+ Counter ++;
+ }
+ return Counter;
}
////////////////////////////////////////////////////////////////////////
diff --git a/src/base/io/ioWriteEqn.c b/src/base/io/ioWriteEqn.c
index 6c2893b5..95c54577 100644
--- a/src/base/io/ioWriteEqn.c
+++ b/src/base/io/ioWriteEqn.c
@@ -25,12 +25,12 @@
////////////////////////////////////////////////////////////////////////
static void Io_NtkWriteEqnOne( FILE * pFile, Abc_Ntk_t * pNtk );
-static void Io_NtkWriteEqnPis( FILE * pFile, Abc_Ntk_t * pNtk );
-static void Io_NtkWriteEqnPos( FILE * pFile, Abc_Ntk_t * pNtk );
-static void Io_NtkWriteEqnNode( FILE * pFile, Abc_Obj_t * pNode );
+static void Io_NtkWriteEqnCis( FILE * pFile, Abc_Ntk_t * pNtk );
+static void Io_NtkWriteEqnCos( FILE * pFile, Abc_Ntk_t * pNtk );
+static int Io_NtkWriteEqnCheck( Abc_Ntk_t * pNtk );
////////////////////////////////////////////////////////////////////////
-/// FUNCTION DEFITIONS ///
+/// FUNCTION DEFINITIONS ///
////////////////////////////////////////////////////////////////////////
/**Function*************************************************************
@@ -48,10 +48,14 @@ void Io_WriteEqn( Abc_Ntk_t * pNtk, char * pFileName )
{
FILE * pFile;
- assert( Abc_NtkIsSopNetlist(pNtk) );
+ assert( Abc_NtkIsAigNetlist(pNtk) );
if ( Abc_NtkLatchNum(pNtk) > 0 )
printf( "Warning: only combinational portion is being written.\n" );
+ // check that the names are fine for the EQN format
+ if ( !Io_NtkWriteEqnCheck(pNtk) )
+ return;
+
// start the output stream
pFile = fopen( pFileName, "w" );
if ( pFile == NULL )
@@ -80,28 +84,37 @@ void Io_WriteEqn( Abc_Ntk_t * pNtk, char * pFileName )
***********************************************************************/
void Io_NtkWriteEqnOne( FILE * pFile, Abc_Ntk_t * pNtk )
{
+ Vec_Vec_t * vLevels;
ProgressBar * pProgress;
- Abc_Obj_t * pNode;
- int i;
+ Abc_Obj_t * pNode, * pFanin;
+ int i, k;
// write the PIs
fprintf( pFile, "INORDER =" );
- Io_NtkWriteEqnPis( pFile, pNtk );
+ Io_NtkWriteEqnCis( pFile, pNtk );
fprintf( pFile, ";\n" );
// write the POs
fprintf( pFile, "OUTORDER =" );
- Io_NtkWriteEqnPos( pFile, pNtk );
+ Io_NtkWriteEqnCos( pFile, pNtk );
fprintf( pFile, ";\n" );
// write each internal node
+ vLevels = Vec_VecAlloc( 10 );
pProgress = Extra_ProgressBarStart( stdout, Abc_NtkObjNumMax(pNtk) );
Abc_NtkForEachNode( pNtk, pNode, i )
{
Extra_ProgressBarUpdate( pProgress, i, NULL );
- Io_NtkWriteEqnNode( pFile, pNode );
+ fprintf( pFile, "%s = ", Abc_ObjName(Abc_ObjFanout0(pNode)) );
+ // set the input names
+ Abc_ObjForEachFanin( pNode, pFanin, k )
+ Hop_IthVar(pNtk->pManFunc, k)->pData = Abc_ObjName(pFanin);
+ // write the formula
+ Hop_ObjPrintEqn( pFile, pNode->pData, vLevels, 0 );
+ fprintf( pFile, ";\n" );
}
Extra_ProgressBarStop( pProgress );
+ Vec_VecFree( vLevels );
}
@@ -116,7 +129,7 @@ void Io_NtkWriteEqnOne( FILE * pFile, Abc_Ntk_t * pNtk )
SeeAlso []
***********************************************************************/
-void Io_NtkWriteEqnPis( FILE * pFile, Abc_Ntk_t * pNtk )
+void Io_NtkWriteEqnCis( FILE * pFile, Abc_Ntk_t * pNtk )
{
Abc_Obj_t * pTerm, * pNet;
int LineLength;
@@ -156,7 +169,7 @@ void Io_NtkWriteEqnPis( FILE * pFile, Abc_Ntk_t * pNtk )
SeeAlso []
***********************************************************************/
-void Io_NtkWriteEqnPos( FILE * pFile, Abc_Ntk_t * pNtk )
+void Io_NtkWriteEqnCos( FILE * pFile, Abc_Ntk_t * pNtk )
{
Abc_Obj_t * pTerm, * pNet;
int LineLength;
@@ -187,73 +200,51 @@ void Io_NtkWriteEqnPos( FILE * pFile, Abc_Ntk_t * pNtk )
/**Function*************************************************************
- Synopsis [Write the node into a file.]
+ Synopsis [Make sure the network does not have offending names.]
Description []
-
+
SideEffects []
SeeAlso []
***********************************************************************/
-void Io_NtkWriteEqnNode( FILE * pFile, Abc_Obj_t * pNode )
+int Io_NtkWriteEqnCheck( Abc_Ntk_t * pNtk )
{
- Abc_Obj_t * pNet;
- int LineLength;
- int AddedLength;
- int NameCounter;
- char * pCube;
- int Value, fFirstLit, i;
-
- fprintf( pFile, "%s = ", Abc_ObjName(pNode) );
-
- if ( Abc_SopIsConst0(pNode->pData) )
- {
- fprintf( pFile, "0;\n" );
- return;
- }
- if ( Abc_SopIsConst1(pNode->pData) )
- {
- fprintf( pFile, "1;\n" );
- return;
- }
+ Abc_Obj_t * pObj;
+ char * pName;
+ int i, k, Length;
+ int RetValue = 1;
- NameCounter = 0;
- LineLength = strlen(Abc_ObjName(pNode)) + 3;
- Abc_SopForEachCube( pNode->pData, Abc_ObjFaninNum(pNode), pCube )
+ // make sure the network does not have proper names, such as "0" or "1" or containing parantheses
+ Abc_NtkForEachObj( pNtk, pObj, i )
{
- if ( pCube != pNode->pData )
+ pName = Nm_ManFindNameById(pNtk->pManName, i);
+ if ( pName == NULL )
+ continue;
+ Length = strlen(pName);
+ if ( pName[0] == '0' || pName[0] == '1' )
{
- fprintf( pFile, " + " );
- LineLength += 3;
+ RetValue = 0;
+ break;
}
-
- // add the cube
- fFirstLit = 1;
- Abc_CubeForEachVar( pCube, Value, i )
- {
- if ( Value == '-' )
- continue;
- pNet = Abc_ObjFanin( pNode, i );
- // get the line length after this name is written
- AddedLength = !fFirstLit + (Value == '0') + strlen(Abc_ObjName(pNet));
- if ( NameCounter && LineLength + AddedLength + 6 > IO_WRITE_LINE_LENGTH )
- { // write the line extender
- fprintf( pFile, " \n " );
- // reset the line length
- LineLength = 0;
- NameCounter = 0;
+ for ( k = 0; k < Length; k++ )
+ if ( pName[k] == '(' || pName[k] == ')' || pName[k] == '!' || pName[k] == '*' || pName[k] == '+' )
+ {
+ RetValue = 0;
+ break;
}
- fprintf( pFile, "%s%s%s", (fFirstLit? "": "*"), ((Value == '0')? "!":""), Abc_ObjName(pNet) );
- LineLength += AddedLength;
- NameCounter++;
- fFirstLit = 0;
- }
+ if ( k < Length )
+ break;
}
- fprintf( pFile, ";\n" );
+ if ( RetValue == 0 )
+ {
+ printf( "The network cannot be written in the EQN format because object %d has name \"%s\".\n", i, pName );
+ printf( "Consider renaming the objects using command \"short_names\" and trying again.\n" );
+ }
+ return RetValue;
}
-
////////////////////////////////////////////////////////////////////////
/// END OF FILE ///
////////////////////////////////////////////////////////////////////////
diff --git a/src/base/io/ioWriteGml.c b/src/base/io/ioWriteGml.c
index ab9f1143..dc897300 100644
--- a/src/base/io/ioWriteGml.c
+++ b/src/base/io/ioWriteGml.c
@@ -25,7 +25,7 @@
////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////
-/// FUNCTION DEFITIONS ///
+/// FUNCTION DEFINITIONS ///
////////////////////////////////////////////////////////////////////////
/**Function*************************************************************
diff --git a/src/base/io/ioWriteList.c b/src/base/io/ioWriteList.c
new file mode 100644
index 00000000..71af7c53
--- /dev/null
+++ b/src/base/io/ioWriteList.c
@@ -0,0 +1,288 @@
+/**CFile****************************************************************
+
+ FileName [ioWriteList.c]
+
+ SystemName [ABC: Logic synthesis and verification system.]
+
+ PackageName [Command processing package.]
+
+ Synopsis [Procedures to write the graph structure of sequential AIG.]
+
+ Author [Alan Mishchenko]
+
+ Affiliation [UC Berkeley]
+
+ Date [Ver. 1.0. Started - June 20, 2005.]
+
+ Revision [$Id: ioWriteList.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "io.h"
+
+/*
+-------- Original Message --------
+Subject: Re: abc release and retiming
+Date: Sun, 13 Nov 2005 20:31:18 -0500 (EST)
+From: Luca Carloni <luca@cs.columbia.edu>
+To: Alan Mishchenko <alanmi@eecs.berkeley.edu>
+
+Alan,
+
+My graph-representation file format is based on an adjacency list
+representation and is indeed quite simple, in fact maybe too simple... I
+used it in order to reason on relatively small weighed direct graphs. I
+simply list all vertices, one per line and for each vertex "V_source" I
+list all vertices that are "sinks" with respect to it, i.e. such that
+there is a distinct arc between "V_source" and each of them (in
+paranthesis I list the name of the edge and its weight (number of latency
+on that path). For instance, if you look at the following graph, you have
+that vertex "v_5" is connected to vertex "v_6" through a directed arc
+called "v_5_to_v_6" whose latency is equal to 3, i.e. there are three
+flip-flops on this arc. Still, notice that I sometime interpret the graph
+also as the representation of a LIS where each node corresponds to a
+shell encapsulating a sequential core module (i.e. a module which does not
+contain any combinational path between its inputs and its outputs). With
+this representation an arc of latency 3 is interpreted as a wire where two
+relay stations have been inserted in addition to the flip-flop terminating
+the output of the core module.
+
+Finally, notice that the name of the arc does not necessarily have to be
+"v_5_to_v_6", but it could have been something like "arc_222" or "xyz" as
+long as it is a unique name in the graph.
+
+Thanks,
+Luca
+
+Example of graph representation
+-----------------------------------------------------------------------------
+v_5 > v_6 ([v_5_to_v_6] = 3), v_12 ([v_5_to_v_12] = 2).
+v_2 > v_4 ([v_2_to_v_4] = 1), v_10_s0 ([v_2_to_v_10_s0] = 6), v_12 ([v_2_to_v_12] = 3).
+v_9 > v_10_s0 ([v_9_to_v_10_s0] = 5), v_12 ([v_9_to_v_12] = 2).
+v_12 > v_13 ([v_12_to_v_13] = 5).
+v_13 > v_14 ([v_13_to_v_14] = 1).
+v_6 > v_7 ([v_6_to_v_7] = 2).
+v_4 > v_5 ([v_4_to_v_5] = 2).
+v_1 > v_2 ([v_1_to_v_2] = 1).
+v_7 > v_8 ([v_7_to_v_8] = 2).
+t > .
+v_14 > t ([v_14_to_t] = 1), v_5 ([v_14_to_v_5] = 1).
+v_8 > v_9 ([v_8_to_v_9] = 2).
+s > v_1 ([s_to_v_1] = 1).
+v_10_s0 > v_10_s1 ([v_10_s0_to_v_10_s1] = 1).
+v_10_s1 > v_4 ([v_10_s1__v_4] = 1), v_8 ([v_10_s1__v_8] = 1).
+-----------------------------------------------------------------------------
+*/
+
+////////////////////////////////////////////////////////////////////////
+/// DECLARATIONS ///
+////////////////////////////////////////////////////////////////////////
+
+static void Io_WriteListEdge( FILE * pFile, Abc_Obj_t * pObj );
+static void Io_WriteListHost( FILE * pFile, Abc_Ntk_t * pNtk );
+
+////////////////////////////////////////////////////////////////////////
+/// FUNCTION DEFINITIONS ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+ Synopsis [Writes the adjacency list for a sequential AIG.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Io_WriteList( Abc_Ntk_t * pNtk, char * pFileName, int fUseHost )
+{
+ FILE * pFile;
+ Abc_Obj_t * pObj;
+ int i;
+
+// assert( Abc_NtkIsSeq(pNtk) );
+
+ // start the output stream
+ pFile = fopen( pFileName, "w" );
+ if ( pFile == NULL )
+ {
+ fprintf( stdout, "Io_WriteList(): Cannot open the output file \"%s\".\n", pFileName );
+ return;
+ }
+
+ fprintf( pFile, "# Adjacency list for sequential AIG \"%s\"\n", pNtk->pName );
+ fprintf( pFile, "# written by ABC on %s\n", Extra_TimeStamp() );
+
+ // write the constant node
+ if ( Abc_ObjFanoutNum( Abc_AigConst1(pNtk) ) > 0 )
+ Io_WriteListEdge( pFile, Abc_AigConst1(pNtk) );
+
+ // write the PI edges
+ Abc_NtkForEachPi( pNtk, pObj, i )
+ Io_WriteListEdge( pFile, pObj );
+
+ // write the internal nodes
+ Abc_AigForEachAnd( pNtk, pObj, i )
+ Io_WriteListEdge( pFile, pObj );
+
+ // write the host node
+ if ( fUseHost )
+ Io_WriteListHost( pFile, pNtk );
+ else
+ Abc_NtkForEachPo( pNtk, pObj, i )
+ Io_WriteListEdge( pFile, pObj );
+
+ fprintf( pFile, "\n" );
+ fclose( pFile );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Writes the adjacency list for one edge in a sequential AIG.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Io_WriteListEdge( FILE * pFile, Abc_Obj_t * pObj )
+{
+ Abc_Obj_t * pFanout;
+ int i;
+ fprintf( pFile, "%-10s > ", Abc_ObjName(pObj) );
+ Abc_ObjForEachFanout( pObj, pFanout, i )
+ {
+ fprintf( pFile, " %s", Abc_ObjName(pFanout) );
+ fprintf( pFile, " ([%s_to_", Abc_ObjName(pObj) );
+// fprintf( pFile, "%s] = %d)", Abc_ObjName(pFanout), Seq_ObjFanoutL(pObj, pFanout) );
+ fprintf( pFile, "%s] = %d)", Abc_ObjName(pFanout), 0 );
+ if ( i != Abc_ObjFanoutNum(pObj) - 1 )
+ fprintf( pFile, "," );
+ }
+ fprintf( pFile, "." );
+ fprintf( pFile, "\n" );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Writes the adjacency list for one edge in a sequential AIG.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Io_WriteListHost( FILE * pFile, Abc_Ntk_t * pNtk )
+{
+ Abc_Obj_t * pObj;
+ int i;
+
+ Abc_NtkForEachPo( pNtk, pObj, i )
+ {
+ fprintf( pFile, "%-10s > ", Abc_ObjName(pObj) );
+ fprintf( pFile, " %s ([%s_to_%s] = %d)", "HOST", Abc_ObjName(pObj), "HOST", 0 );
+ fprintf( pFile, "." );
+ fprintf( pFile, "\n" );
+ }
+
+ fprintf( pFile, "%-10s > ", "HOST" );
+ Abc_NtkForEachPi( pNtk, pObj, i )
+ {
+ fprintf( pFile, " %s", Abc_ObjName(pObj) );
+ fprintf( pFile, " ([%s_to_%s] = %d)", "HOST", Abc_ObjName(pObj), 0 );
+ if ( i != Abc_NtkPiNum(pNtk) - 1 )
+ fprintf( pFile, "," );
+ }
+ fprintf( pFile, "." );
+ fprintf( pFile, "\n" );
+}
+
+
+/**Function*************************************************************
+
+ Synopsis [Writes the adjacency list for a sequential AIG.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Io_WriteCellNet( Abc_Ntk_t * pNtk, char * pFileName )
+{
+ FILE * pFile;
+ Abc_Obj_t * pObj, * pFanout;
+ int i, k;
+
+ assert( Abc_NtkIsLogic(pNtk) );
+
+ // start the output stream
+ pFile = fopen( pFileName, "w" );
+ if ( pFile == NULL )
+ {
+ fprintf( stdout, "Io_WriteCellNet(): Cannot open the output file \"%s\".\n", pFileName );
+ return;
+ }
+
+ fprintf( pFile, "# CellNet file for network \"%s\" written by ABC on %s\n", pNtk->pName, Extra_TimeStamp() );
+
+ // the only tricky part with writing is handling latches:
+ // each latch comes with (a) single-input latch-input node, (b) latch proper, (c) single-input latch-output node
+ // we arbitrarily decide to use the interger ID of the latch-input node to represent the latch in the file
+ // (this ID is used for both the cell and the net driven by that cell)
+
+ // write the PIs
+ Abc_NtkForEachPi( pNtk, pObj, i )
+ fprintf( pFile, "cell %d is 0\n", pObj->Id );
+ // write the POs
+ Abc_NtkForEachPo( pNtk, pObj, i )
+ fprintf( pFile, "cell %d is 1\n", pObj->Id );
+ // write the latches (use the ID of latch input)
+ Abc_NtkForEachLatch( pNtk, pObj, i )
+ fprintf( pFile, "cell %d is 2\n", Abc_ObjFanin0(pObj)->Id );
+ // write the logic nodes
+ Abc_NtkForEachNode( pNtk, pObj, i )
+ fprintf( pFile, "cell %d is %d\n", pObj->Id, 3+Abc_ObjFaninNum(pObj) );
+
+ // write the nets driven by PIs
+ Abc_NtkForEachPi( pNtk, pObj, i )
+ {
+ fprintf( pFile, "net %d %d 0", pObj->Id, pObj->Id );
+ Abc_ObjForEachFanout( pObj, pFanout, k )
+ fprintf( pFile, " %d %d", pFanout->Id, 1 + Abc_ObjFanoutFaninNum(pFanout, pObj) );
+ fprintf( pFile, "\n" );
+ }
+ // write the nets driven by latches
+ Abc_NtkForEachLatch( pNtk, pObj, i )
+ {
+ fprintf( pFile, "net %d %d 0", Abc_ObjFanin0(pObj)->Id, Abc_ObjFanin0(pObj)->Id );
+ pObj = Abc_ObjFanout0(pObj);
+ Abc_ObjForEachFanout( pObj, pFanout, k )
+ fprintf( pFile, " %d %d", pFanout->Id, 1 + Abc_ObjFanoutFaninNum(pFanout, pObj) );
+ fprintf( pFile, "\n" );
+ }
+ // write the nets driven by nodes
+ Abc_NtkForEachNode( pNtk, pObj, i )
+ {
+ fprintf( pFile, "net %d %d 0", pObj->Id, pObj->Id );
+ Abc_ObjForEachFanout( pObj, pFanout, k )
+ fprintf( pFile, " %d %d", pFanout->Id, 1 + Abc_ObjFanoutFaninNum(pFanout, pObj) );
+ fprintf( pFile, "\n" );
+ }
+
+ fprintf( pFile, "\n" );
+ fclose( pFile );
+}
+
+////////////////////////////////////////////////////////////////////////
+/// END OF FILE ///
+////////////////////////////////////////////////////////////////////////
+
+
diff --git a/src/base/io/ioWritePla.c b/src/base/io/ioWritePla.c
index 25a68978..b119751c 100644
--- a/src/base/io/ioWritePla.c
+++ b/src/base/io/ioWritePla.c
@@ -27,7 +27,7 @@
static int Io_WritePlaOne( FILE * pFile, Abc_Ntk_t * pNtk );
////////////////////////////////////////////////////////////////////////
-/// FUNCTION DEFITIONS ///
+/// FUNCTION DEFINITIONS ///
////////////////////////////////////////////////////////////////////////
/**Function*************************************************************
@@ -47,7 +47,7 @@ int Io_WritePla( Abc_Ntk_t * pNtk, char * pFileName )
FILE * pFile;
assert( Abc_NtkIsSopNetlist(pNtk) );
- assert( Abc_NtkGetLevelNum(pNtk) == 1 );
+ assert( Abc_NtkLevel(pNtk) == 1 );
pFile = fopen( pFileName, "w" );
if ( pFile == NULL )
@@ -88,7 +88,7 @@ int Io_WritePlaOne( FILE * pFile, Abc_Ntk_t * pNtk )
nProducts = 0;
Abc_NtkForEachCo( pNtk, pNode, i )
{
- pDriver = Abc_ObjFanin0Ntk(pNode);
+ pDriver = Abc_ObjFanin0Ntk( Abc_ObjFanin0(pNode) );
if ( !Abc_ObjIsNode(pDriver) )
{
nProducts++;
@@ -138,9 +138,10 @@ int Io_WritePlaOne( FILE * pFile, Abc_Ntk_t * pNtk )
pCubeOut[i] = '1';
// consider special cases of nodes
- pDriver = Abc_ObjFanin0Ntk(pNode);
+ pDriver = Abc_ObjFanin0Ntk( Abc_ObjFanin0(pNode) );
if ( !Abc_ObjIsNode(pDriver) )
{
+ assert( Abc_ObjIsCi(pDriver) );
pCubeIn[(int)pDriver->pCopy] = '1' - Abc_ObjFaninC0(pNode);
fprintf( pFile, "%s %s\n", pCubeIn, pCubeOut );
pCubeIn[(int)pDriver->pCopy] = '-';
@@ -152,17 +153,29 @@ int Io_WritePlaOne( FILE * pFile, Abc_Ntk_t * pNtk )
fprintf( pFile, "%s %s\n", pCubeIn, pCubeOut );
continue;
}
+
+ // make sure the cover is not complemented
+ assert( !Abc_SopIsComplement( pDriver->pData ) );
+
// write the cubes
nFanins = Abc_ObjFaninNum(pDriver);
Abc_SopForEachCube( pDriver->pData, nFanins, pCube )
{
Abc_ObjForEachFanin( pDriver, pFanin, k )
+ {
+ pFanin = Abc_ObjFanin0Ntk(pFanin);
+ assert( (int)pFanin->pCopy < nInputs );
pCubeIn[(int)pFanin->pCopy] = pCube[k];
+ }
fprintf( pFile, "%s %s\n", pCubeIn, pCubeOut );
}
// clean the cube for future writing
Abc_ObjForEachFanin( pDriver, pFanin, k )
+ {
+ pFanin = Abc_ObjFanin0Ntk(pFanin);
+ assert( Abc_ObjIsCi(pFanin) );
pCubeIn[(int)pFanin->pCopy] = '-';
+ }
Extra_ProgressBarUpdate( pProgress, i, NULL );
}
Extra_ProgressBarStop( pProgress );
@@ -171,6 +184,8 @@ int Io_WritePlaOne( FILE * pFile, Abc_Ntk_t * pNtk )
// clean the CI nodes
Abc_NtkForEachCi( pNtk, pNode, i )
pNode->pCopy = NULL;
+ free( pCubeIn );
+ free( pCubeOut );
return 1;
}
diff --git a/src/base/io/ioWriteVerilog.c b/src/base/io/ioWriteVerilog.c
new file mode 100644
index 00000000..9e71e3e4
--- /dev/null
+++ b/src/base/io/ioWriteVerilog.c
@@ -0,0 +1,639 @@
+/**CFile****************************************************************
+
+ FileName [ioWriteVerilog.c]
+
+ SystemName [ABC: Logic synthesis and verification system.]
+
+ PackageName [Command processing package.]
+
+ Synopsis [Procedures to output a special subset of Verilog.]
+
+ Author [Alan Mishchenko]
+
+ Affiliation [UC Berkeley]
+
+ Date [Ver. 1.0. Started - June 20, 2005.]
+
+ Revision [$Id: ioWriteVerilog.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "io.h"
+#include "main.h"
+#include "mio.h"
+
+////////////////////////////////////////////////////////////////////////
+/// DECLARATIONS ///
+////////////////////////////////////////////////////////////////////////
+
+static void Io_WriteVerilogInt( FILE * pFile, Abc_Ntk_t * pNtk );
+static void Io_WriteVerilogPis( FILE * pFile, Abc_Ntk_t * pNtk, int Start );
+static void Io_WriteVerilogPos( FILE * pFile, Abc_Ntk_t * pNtk, int Start );
+static void Io_WriteVerilogWires( FILE * pFile, Abc_Ntk_t * pNtk, int Start );
+static void Io_WriteVerilogRegs( FILE * pFile, Abc_Ntk_t * pNtk, int Start );
+static void Io_WriteVerilogLatches( FILE * pFile, Abc_Ntk_t * pNtk );
+static void Io_WriteVerilogObjects( FILE * pFile, Abc_Ntk_t * pNtk );
+static int Io_WriteVerilogWiresCount( Abc_Ntk_t * pNtk );
+static char * Io_WriteVerilogGetName( char * pName );
+
+////////////////////////////////////////////////////////////////////////
+/// FUNCTION DEFINITIONS ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+ Synopsis [Write verilog.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Io_WriteVerilog( Abc_Ntk_t * pNtk, char * pFileName )
+{
+ Abc_Ntk_t * pNetlist;
+ FILE * pFile;
+ int i;
+ // can only write nodes represented using local AIGs
+ if ( !Abc_NtkIsAigNetlist(pNtk) && !Abc_NtkIsMappedNetlist(pNtk) )
+ {
+ printf( "Io_WriteVerilog(): Can produce Verilog for mapped or AIG netlists only.\n" );
+ return;
+ }
+ // start the output stream
+ pFile = fopen( pFileName, "w" );
+ if ( pFile == NULL )
+ {
+ fprintf( stdout, "Io_WriteVerilog(): Cannot open the output file \"%s\".\n", pFileName );
+ return;
+ }
+
+ // write the equations for the network
+ fprintf( pFile, "// Benchmark \"%s\" written by ABC on %s\n", pNtk->pName, Extra_TimeStamp() );
+ fprintf( pFile, "\n" );
+
+ // write modules
+ if ( pNtk->pDesign )
+ {
+ // write the network first
+ Io_WriteVerilogInt( pFile, pNtk );
+ // write other things
+ Vec_PtrForEachEntry( pNtk->pDesign->vModules, pNetlist, i )
+ {
+ assert( Abc_NtkIsNetlist(pNetlist) );
+ if ( pNetlist == pNtk )
+ continue;
+ fprintf( pFile, "\n" );
+ Io_WriteVerilogInt( pFile, pNetlist );
+ }
+ }
+ else
+ {
+ Io_WriteVerilogInt( pFile, pNtk );
+ }
+
+ fprintf( pFile, "\n" );
+ fclose( pFile );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Writes verilog.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Io_WriteVerilogInt( FILE * pFile, Abc_Ntk_t * pNtk )
+{
+ // write inputs and outputs
+// fprintf( pFile, "module %s ( gclk,\n ", Abc_NtkName(pNtk) );
+ fprintf( pFile, "module %s ( ", Abc_NtkName(pNtk) );
+ // add the clock signal if it does not exist
+ if ( Abc_NtkLatchNum(pNtk) > 0 && Nm_ManFindIdByName(pNtk->pManName, "clock", ABC_OBJ_PI) == -1 )
+ fprintf( pFile, "clock, " );
+ // write other primary inputs
+ fprintf( pFile, "\n " );
+ if ( Abc_NtkPiNum(pNtk) > 0 )
+ {
+ Io_WriteVerilogPis( pFile, pNtk, 3 );
+ fprintf( pFile, ",\n " );
+ }
+ if ( Abc_NtkPoNum(pNtk) > 0 )
+ Io_WriteVerilogPos( pFile, pNtk, 3 );
+ fprintf( pFile, " );\n" );
+ // add the clock signal if it does not exist
+ if ( Abc_NtkLatchNum(pNtk) > 0 && Nm_ManFindIdByName(pNtk->pManName, "clock", ABC_OBJ_PI) == -1 )
+ fprintf( pFile, " input clock;\n" );
+ // write inputs, outputs, registers, and wires
+ if ( Abc_NtkPiNum(pNtk) > 0 )
+ {
+// fprintf( pFile, " input gclk," );
+ fprintf( pFile, " input " );
+ Io_WriteVerilogPis( pFile, pNtk, 10 );
+ fprintf( pFile, ";\n" );
+ }
+ if ( Abc_NtkPoNum(pNtk) > 0 )
+ {
+ fprintf( pFile, " output" );
+ Io_WriteVerilogPos( pFile, pNtk, 5 );
+ fprintf( pFile, ";\n" );
+ }
+ // if this is not a blackbox, write internal signals
+ if ( !Abc_NtkHasBlackbox(pNtk) )
+ {
+ if ( Abc_NtkLatchNum(pNtk) > 0 )
+ {
+ fprintf( pFile, " reg" );
+ Io_WriteVerilogRegs( pFile, pNtk, 4 );
+ fprintf( pFile, ";\n" );
+ }
+ if ( Io_WriteVerilogWiresCount(pNtk) > 0 )
+ {
+ fprintf( pFile, " wire" );
+ Io_WriteVerilogWires( pFile, pNtk, 4 );
+ fprintf( pFile, ";\n" );
+ }
+ // write nodes
+ Io_WriteVerilogObjects( pFile, pNtk );
+ // write registers
+ if ( Abc_NtkLatchNum(pNtk) > 0 )
+ Io_WriteVerilogLatches( pFile, pNtk );
+ }
+ // finalize the file
+ fprintf( pFile, "endmodule\n\n" );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Writes the primary inputs.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Io_WriteVerilogPis( FILE * pFile, Abc_Ntk_t * pNtk, int Start )
+{
+ Abc_Obj_t * pTerm, * pNet;
+ int LineLength;
+ int AddedLength;
+ int NameCounter;
+ int i;
+
+ LineLength = Start;
+ NameCounter = 0;
+ Abc_NtkForEachPi( pNtk, pTerm, i )
+ {
+ pNet = Abc_ObjFanout0(pTerm);
+ // get the line length after this name is written
+ AddedLength = strlen(Io_WriteVerilogGetName(Abc_ObjName(pNet))) + 2;
+ if ( NameCounter && LineLength + AddedLength + 3 > IO_WRITE_LINE_LENGTH )
+ { // write the line extender
+ fprintf( pFile, "\n " );
+ // reset the line length
+ LineLength = 3;
+ NameCounter = 0;
+ }
+ fprintf( pFile, " %s%s", Io_WriteVerilogGetName(Abc_ObjName(pNet)), (i==Abc_NtkPiNum(pNtk)-1)? "" : "," );
+ LineLength += AddedLength;
+ NameCounter++;
+ }
+}
+
+/**Function*************************************************************
+
+ Synopsis [Writes the primary outputs.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Io_WriteVerilogPos( FILE * pFile, Abc_Ntk_t * pNtk, int Start )
+{
+ Abc_Obj_t * pTerm, * pNet, * pSkip;
+ int LineLength;
+ int AddedLength;
+ int NameCounter;
+ int i;
+ int nskip;
+
+ pSkip = 0;
+ nskip = 0;
+
+ LineLength = Start;
+ NameCounter = 0;
+ Abc_NtkForEachPo( pNtk, pTerm, i )
+ {
+ pNet = Abc_ObjFanin0(pTerm);
+
+ if ( Abc_ObjIsPi(Abc_ObjFanin0(pNet)) )
+ {
+ // Skip this output since it is a feedthrough -- the same
+ // name will appear as an input and an output which other
+ // tools reading verilog do not like.
+
+ nskip++;
+ pSkip = pNet; // save an example of skipped net
+ continue;
+ }
+
+ // get the line length after this name is written
+ AddedLength = strlen(Io_WriteVerilogGetName(Abc_ObjName(pNet))) + 2;
+ if ( NameCounter && LineLength + AddedLength + 3 > IO_WRITE_LINE_LENGTH )
+ { // write the line extender
+ fprintf( pFile, "\n " );
+ // reset the line length
+ LineLength = 3;
+ NameCounter = 0;
+ }
+ fprintf( pFile, " %s%s", Io_WriteVerilogGetName(Abc_ObjName(pNet)), (i==Abc_NtkPoNum(pNtk)-1)? "" : "," );
+ LineLength += AddedLength;
+ NameCounter++;
+ }
+
+ if (nskip != 0)
+ {
+ assert (pSkip);
+ printf( "Io_WriteVerilogPos(): Omitted %d feedthrough nets from output list of module (e.g. %s).\n", nskip, Abc_ObjName(pSkip) );
+ return;
+ }
+
+}
+
+/**Function*************************************************************
+
+ Synopsis [Writes the wires.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Io_WriteVerilogWires( FILE * pFile, Abc_Ntk_t * pNtk, int Start )
+{
+ Abc_Obj_t * pObj, * pNet, * pBox, * pTerm;
+ int LineLength;
+ int AddedLength;
+ int NameCounter;
+ int i, k, Counter, nNodes;
+
+ // count the number of wires
+ nNodes = Io_WriteVerilogWiresCount( pNtk );
+
+ // write the wires
+ Counter = 0;
+ LineLength = Start;
+ NameCounter = 0;
+ Abc_NtkForEachNode( pNtk, pObj, i )
+ {
+ if ( i == 0 )
+ continue;
+ pNet = Abc_ObjFanout0(pObj);
+ if ( Abc_ObjFanoutNum(pNet) > 0 && Abc_ObjIsCo(Abc_ObjFanout0(pNet)) )
+ continue;
+ Counter++;
+ // get the line length after this name is written
+ AddedLength = strlen(Io_WriteVerilogGetName(Abc_ObjName(pNet))) + 2;
+ if ( NameCounter && LineLength + AddedLength + 3 > IO_WRITE_LINE_LENGTH )
+ { // write the line extender
+ fprintf( pFile, "\n " );
+ // reset the line length
+ LineLength = 3;
+ NameCounter = 0;
+ }
+ fprintf( pFile, " %s%s", Io_WriteVerilogGetName(Abc_ObjName(pNet)), (Counter==nNodes)? "" : "," );
+ LineLength += AddedLength;
+ NameCounter++;
+ }
+ Abc_NtkForEachLatch( pNtk, pObj, i )
+ {
+ pNet = Abc_ObjFanin0(Abc_ObjFanin0(pObj));
+ Counter++;
+ // get the line length after this name is written
+ AddedLength = strlen(Io_WriteVerilogGetName(Abc_ObjName(pNet))) + 2;
+ if ( NameCounter && LineLength + AddedLength + 3 > IO_WRITE_LINE_LENGTH )
+ { // write the line extender
+ fprintf( pFile, "\n " );
+ // reset the line length
+ LineLength = 3;
+ NameCounter = 0;
+ }
+ fprintf( pFile, " %s%s", Io_WriteVerilogGetName(Abc_ObjName(pNet)), (Counter==nNodes)? "" : "," );
+ LineLength += AddedLength;
+ NameCounter++;
+ }
+ Abc_NtkForEachBox( pNtk, pBox, i )
+ {
+ if ( Abc_ObjIsLatch(pBox) )
+ continue;
+ Abc_ObjForEachFanin( pBox, pTerm, k )
+ {
+ pNet = Abc_ObjFanin0(pTerm);
+ Counter++;
+ // get the line length after this name is written
+ AddedLength = strlen(Io_WriteVerilogGetName(Abc_ObjName(pNet))) + 2;
+ if ( NameCounter && LineLength + AddedLength + 3 > IO_WRITE_LINE_LENGTH )
+ { // write the line extender
+ fprintf( pFile, "\n " );
+ // reset the line length
+ LineLength = 3;
+ NameCounter = 0;
+ }
+ fprintf( pFile, " %s%s", Io_WriteVerilogGetName(Abc_ObjName(pNet)), (Counter==nNodes)? "" : "," );
+ LineLength += AddedLength;
+ NameCounter++;
+ }
+ Abc_ObjForEachFanout( pBox, pTerm, k )
+ {
+ pNet = Abc_ObjFanout0(pTerm);
+ if ( Abc_ObjFanoutNum(pNet) > 0 && Abc_ObjIsCo(Abc_ObjFanout0(pNet)) )
+ continue;
+ Counter++;
+ // get the line length after this name is written
+ AddedLength = strlen(Io_WriteVerilogGetName(Abc_ObjName(pNet))) + 2;
+ if ( NameCounter && LineLength + AddedLength + 3 > IO_WRITE_LINE_LENGTH )
+ { // write the line extender
+ fprintf( pFile, "\n " );
+ // reset the line length
+ LineLength = 3;
+ NameCounter = 0;
+ }
+ fprintf( pFile, " %s%s", Io_WriteVerilogGetName(Abc_ObjName(pNet)), (Counter==nNodes)? "" : "," );
+ LineLength += AddedLength;
+ NameCounter++;
+ }
+ }
+ assert( Counter == nNodes );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Writes the regs.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Io_WriteVerilogRegs( FILE * pFile, Abc_Ntk_t * pNtk, int Start )
+{
+ Abc_Obj_t * pLatch, * pNet;
+ int LineLength;
+ int AddedLength;
+ int NameCounter;
+ int i, Counter, nNodes;
+
+ // count the number of latches
+ nNodes = Abc_NtkLatchNum(pNtk);
+
+ // write the wires
+ Counter = 0;
+ LineLength = Start;
+ NameCounter = 0;
+ Abc_NtkForEachLatch( pNtk, pLatch, i )
+ {
+ pNet = Abc_ObjFanout0(Abc_ObjFanout0(pLatch));
+ Counter++;
+ // get the line length after this name is written
+ AddedLength = strlen(Io_WriteVerilogGetName(Abc_ObjName(pNet))) + 2;
+ if ( NameCounter && LineLength + AddedLength + 3 > IO_WRITE_LINE_LENGTH )
+ { // write the line extender
+ fprintf( pFile, "\n " );
+ // reset the line length
+ LineLength = 3;
+ NameCounter = 0;
+ }
+ fprintf( pFile, " %s%s", Io_WriteVerilogGetName(Abc_ObjName(pNet)), (Counter==nNodes)? "" : "," );
+ LineLength += AddedLength;
+ NameCounter++;
+ }
+}
+
+/**Function*************************************************************
+
+ Synopsis [Writes the latches.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Io_WriteVerilogLatches( FILE * pFile, Abc_Ntk_t * pNtk )
+{
+ Abc_Obj_t * pLatch;
+ int i;
+ if ( Abc_NtkLatchNum(pNtk) == 0 )
+ return;
+ // write the latches
+// fprintf( pFile, " always @(posedge %s) begin\n", Io_WriteVerilogGetName(Abc_ObjFanout0(Abc_NtkPi(pNtk,0))) );
+// fprintf( pFile, " always begin\n" );
+ fprintf( pFile, " always @ (posedge clock) begin\n" );
+ Abc_NtkForEachLatch( pNtk, pLatch, i )
+ {
+ fprintf( pFile, " %s", Io_WriteVerilogGetName(Abc_ObjName(Abc_ObjFanout0(Abc_ObjFanout0(pLatch)))) );
+ fprintf( pFile, " <= %s;\n", Io_WriteVerilogGetName(Abc_ObjName(Abc_ObjFanin0(Abc_ObjFanin0(pLatch)))) );
+ }
+ fprintf( pFile, " end\n" );
+ // check if there are initial values
+ Abc_NtkForEachLatch( pNtk, pLatch, i )
+ if ( Abc_LatchInit(pLatch) == ABC_INIT_ZERO || Abc_LatchInit(pLatch) == ABC_INIT_ONE )
+ break;
+ if ( i == Abc_NtkLatchNum(pNtk) )
+ return;
+ // write the initial values
+ fprintf( pFile, " initial begin\n", Io_WriteVerilogGetName(Abc_ObjName(Abc_ObjFanout0(Abc_NtkPi(pNtk,0)))) );
+ Abc_NtkForEachLatch( pNtk, pLatch, i )
+ {
+ if ( Abc_LatchInit(pLatch) == ABC_INIT_ZERO )
+ fprintf( pFile, " %s <= 1\'b0;\n", Io_WriteVerilogGetName(Abc_ObjName(Abc_ObjFanout0(Abc_ObjFanout0(pLatch)))) );
+ else if ( Abc_LatchInit(pLatch) == ABC_INIT_ONE )
+ fprintf( pFile, " %s <= 1\'b1;\n", Io_WriteVerilogGetName(Abc_ObjName(Abc_ObjFanout0(Abc_ObjFanout0(pLatch)))) );
+ }
+ fprintf( pFile, " end\n" );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Writes the nodes and boxes.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Io_WriteVerilogObjects( FILE * pFile, Abc_Ntk_t * pNtk )
+{
+ Vec_Vec_t * vLevels;
+ Abc_Ntk_t * pNtkBox;
+ Abc_Obj_t * pObj, * pTerm, * pFanin;
+ Hop_Obj_t * pFunc;
+ int i, k, Counter, nDigits, Length;
+
+ // write boxes
+ nDigits = Extra_Base10Log( Abc_NtkBoxNum(pNtk)-Abc_NtkLatchNum(pNtk) );
+ Counter = 0;
+ Abc_NtkForEachBox( pNtk, pObj, i )
+ {
+ if ( Abc_ObjIsLatch(pObj) )
+ continue;
+ pNtkBox = pObj->pData;
+ fprintf( pFile, " %s box%0*d", pNtkBox->pName, nDigits, Counter++ );
+ fprintf( pFile, "(" );
+ Abc_NtkForEachPi( pNtkBox, pTerm, k )
+ {
+ fprintf( pFile, ".%s", Io_WriteVerilogGetName(Abc_ObjName(Abc_ObjFanout0(pTerm))) );
+ fprintf( pFile, "(%s), ", Io_WriteVerilogGetName(Abc_ObjName(Abc_ObjFanin0(Abc_ObjFanin(pObj,k)))) );
+ }
+ Abc_NtkForEachPo( pNtkBox, pTerm, k )
+ {
+ fprintf( pFile, ".%s", Io_WriteVerilogGetName(Abc_ObjName(Abc_ObjFanin0(pTerm))) );
+ fprintf( pFile, "(%s)%s", Io_WriteVerilogGetName(Abc_ObjName(Abc_ObjFanout0(Abc_ObjFanout(pObj,k)))), k==Abc_NtkPoNum(pNtkBox)-1? "":", " );
+ }
+ fprintf( pFile, ");\n" );
+ }
+ // write nodes
+ if ( Abc_NtkHasMapping(pNtk) )
+ {
+ Length = Mio_LibraryReadGateNameMax(pNtk->pManFunc);
+ nDigits = Extra_Base10Log( Abc_NtkNodeNum(pNtk) );
+ Counter = 0;
+ Abc_NtkForEachNode( pNtk, pObj, k )
+ {
+ Mio_Gate_t * pGate = pObj->pData;
+ Mio_Pin_t * pGatePin;
+ // write the node
+ fprintf( pFile, " %-*s g%0*d", Length, Mio_GateReadName(pGate), nDigits, Counter++ );
+ fprintf( pFile, "(" );
+ for ( pGatePin = Mio_GateReadPins(pGate), i = 0; pGatePin; pGatePin = Mio_PinReadNext(pGatePin), i++ )
+ {
+ fprintf( pFile, ".%s", Io_WriteVerilogGetName(Mio_PinReadName(pGatePin)) );
+ fprintf( pFile, "(%s), ", Io_WriteVerilogGetName(Abc_ObjName( Abc_ObjFanin(pObj,i) )) );
+ }
+ assert ( i == Abc_ObjFaninNum(pObj) );
+ fprintf( pFile, ".%s", Io_WriteVerilogGetName(Mio_GateReadOutName(pGate)) );
+ fprintf( pFile, "(%s)", Io_WriteVerilogGetName(Abc_ObjName( Abc_ObjFanout0(pObj) )) );
+ fprintf( pFile, ");\n" );
+ }
+ }
+ else
+ {
+ vLevels = Vec_VecAlloc( 10 );
+ Abc_NtkForEachNode( pNtk, pObj, i )
+ {
+ pFunc = pObj->pData;
+ fprintf( pFile, " assign %s = ", Io_WriteVerilogGetName(Abc_ObjName(Abc_ObjFanout0(pObj))) );
+ // set the input names
+ Abc_ObjForEachFanin( pObj, pFanin, k )
+ Hop_IthVar(pNtk->pManFunc, k)->pData = Extra_UtilStrsav(Io_WriteVerilogGetName(Abc_ObjName(pFanin)));
+ // write the formula
+ Hop_ObjPrintVerilog( pFile, pFunc, vLevels, 0 );
+ fprintf( pFile, ";\n" );
+ // clear the input names
+ Abc_ObjForEachFanin( pObj, pFanin, k )
+ free( Hop_IthVar(pNtk->pManFunc, k)->pData );
+ }
+ Vec_VecFree( vLevels );
+ }
+}
+
+/**Function*************************************************************
+
+ Synopsis [Counts the number of wires.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Io_WriteVerilogWiresCount( Abc_Ntk_t * pNtk )
+{
+ Abc_Obj_t * pObj, * pNet, * pBox;
+ int i, k, nWires;
+ nWires = Abc_NtkLatchNum(pNtk);
+ Abc_NtkForEachNode( pNtk, pObj, i )
+ {
+ if ( i == 0 )
+ continue;
+ pNet = Abc_ObjFanout0(pObj);
+ if ( Abc_ObjFanoutNum(pNet) > 0 && Abc_ObjIsCo(Abc_ObjFanout0(pNet)) )
+ continue;
+ nWires++;
+ }
+ Abc_NtkForEachBox( pNtk, pBox, i )
+ {
+ if ( Abc_ObjIsLatch(pBox) )
+ continue;
+ nWires += Abc_ObjFaninNum(pBox);
+ Abc_ObjForEachFanout( pBox, pObj, k )
+ {
+ pNet = Abc_ObjFanout0(pObj);
+ if ( Abc_ObjFanoutNum(pNet) > 0 && Abc_ObjIsCo(Abc_ObjFanout0(pNet)) )
+ continue;
+ nWires++;
+ }
+ }
+ return nWires;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Prepares the name for writing the Verilog file.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+char * Io_WriteVerilogGetName( char * pName )
+{
+ static char Buffer[500];
+ int Length, i;
+ Length = strlen(pName);
+ // consider the case of a signal having name "0" or "1"
+ if ( !(Length == 1 && (pName[0] == '0' || pName[0] == '1')) )
+ {
+ for ( i = 0; i < Length; i++ )
+ if ( !((pName[i] >= 'a' && pName[i] <= 'z') ||
+ (pName[i] >= 'A' && pName[i] <= 'Z') ||
+ (pName[i] >= '0' && pName[i] <= '9') || pName[i] == '_') )
+ break;
+ if ( i == Length )
+ return pName;
+ }
+ // create Verilog style name
+ Buffer[0] = '\\';
+ for ( i = 0; i < Length; i++ )
+ Buffer[i+1] = pName[i];
+ Buffer[Length+1] = ' ';
+ Buffer[Length+2] = 0;
+ return Buffer;
+}
+
+////////////////////////////////////////////////////////////////////////
+/// END OF FILE ///
+////////////////////////////////////////////////////////////////////////
+
+
diff --git a/src/base/io/io_.c b/src/base/io/io_.c
new file mode 100644
index 00000000..62dd60e5
--- /dev/null
+++ b/src/base/io/io_.c
@@ -0,0 +1,48 @@
+/**CFile****************************************************************
+
+ FileName [io_.c]
+
+ SystemName [ABC: Logic synthesis and verification system.]
+
+ PackageName [Command processing package.]
+
+ Synopsis [Procedure to read network from file.]
+
+ Author [Alan Mishchenko]
+
+ Affiliation [UC Berkeley]
+
+ Date [Ver. 1.0. Started - June 20, 2005.]
+
+ Revision [$Id: io_.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "io.h"
+
+////////////////////////////////////////////////////////////////////////
+/// DECLARATIONS ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+/// FUNCTION DEFINITIONS ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+
+////////////////////////////////////////////////////////////////////////
+/// END OF FILE ///
+////////////////////////////////////////////////////////////////////////
+
+
+
diff --git a/src/base/io/module.make b/src/base/io/module.make
index 34582473..bb35a7fc 100644
--- a/src/base/io/module.make
+++ b/src/base/io/module.make
@@ -1,16 +1,25 @@
SRC += src/base/io/io.c \
- src/base/io/ioRead.c \
+ src/base/io/ioReadAiger.c \
+ src/base/io/ioReadBaf.c \
src/base/io/ioReadBench.c \
src/base/io/ioReadBlif.c \
+ src/base/io/ioReadBlifAig.c \
+ src/base/io/ioReadBlifMv.c \
+ src/base/io/ioReadDsd.c \
src/base/io/ioReadEdif.c \
src/base/io/ioReadEqn.c \
src/base/io/ioReadPla.c \
src/base/io/ioReadVerilog.c \
src/base/io/ioUtil.c \
+ src/base/io/ioWriteAiger.c \
+ src/base/io/ioWriteBaf.c \
src/base/io/ioWriteBench.c \
src/base/io/ioWriteBlif.c \
+ src/base/io/ioWriteBlifMv.c \
src/base/io/ioWriteCnf.c \
src/base/io/ioWriteDot.c \
src/base/io/ioWriteEqn.c \
src/base/io/ioWriteGml.c \
- src/base/io/ioWritePla.c
+ src/base/io/ioWriteList.c \
+ src/base/io/ioWritePla.c \
+ src/base/io/ioWriteVerilog.c
diff --git a/src/base/main/libSupport.c b/src/base/main/libSupport.c
new file mode 100644
index 00000000..471ea09e
--- /dev/null
+++ b/src/base/main/libSupport.c
@@ -0,0 +1,193 @@
+/**CFile****************************************************************
+
+ FileName [libSupport.c]
+
+ SystemName [ABC: Logic synthesis and verification system.]
+
+ PackageName [The main package.]
+
+ Synopsis [Support for external libaries.]
+
+ Author [Mike Case]
+
+ Affiliation [UC Berkeley]
+
+ Date [Ver. 1.0. Started - June 20, 2005.]
+
+ Revision [$Id: libSupport.c,v 1.1 2005/09/06 19:59:51 casem Exp $]
+
+***********************************************************************/
+
+#include "mainInt.h"
+#include <stdio.h>
+#include <string.h>
+
+#ifndef WIN32
+# include <sys/types.h>
+# include <dirent.h>
+# include <dlfcn.h>
+#endif
+
+#define MAX_LIBS 256
+static void* libHandles[MAX_LIBS+1]; // will be null terminated
+
+typedef void (*lib_init_end_func) (Abc_Frame_t * pAbc);
+
+////////////////////////////////////////////////////////////////////////////////////////////////////
+// This will find all the ABC library extensions in the current directory and load them all.
+////////////////////////////////////////////////////////////////////////////////////////////////////
+void open_libs() {
+ int curr_lib = 0;
+
+#ifdef WIN32
+// printf("Warning: open_libs WIN32 not implemented.\n");
+#else
+ DIR* dirp;
+ struct dirent* dp;
+ char *env, *init_p, *p;
+ int done;
+
+ env = getenv ("ABC_LIB_PATH");
+ if (env == NULL) {
+// printf("Warning: ABC_LIB_PATH not defined. Looking into the current directory.\n");
+ init_p = malloc (2*sizeof(char));
+ init_p[0]='.'; init_p[1] = 0;
+ } else {
+ init_p = malloc ((strlen(env)+1)*sizeof(char));
+ strcpy (init_p, env);
+ }
+
+ // Extract directories and read libraries
+ done = 0;
+ p = init_p;
+ while (!done) {
+ char *endp = strchr (p,':');
+ if (endp == NULL) done = 1; // last directory in the list
+ else *endp = 0; // end of string
+
+ dirp = opendir(p);
+ if (dirp == NULL) {
+// printf("Warning: directory in ABC_LIB_PATH does not exist (%s).\n", p);
+ continue;
+ }
+
+ while ((dp = readdir(dirp)) != NULL) {
+ if ((strncmp("libabc_", dp->d_name, 7) == 0) &&
+ (strcmp(".so", dp->d_name + strlen(dp->d_name) - 3) == 0)) {
+
+ // make sure we don't overflow the handle array
+ if (curr_lib >= MAX_LIBS) {
+ printf("Warning: maximum number of ABC libraries (%d) exceeded. Not loading %s.\n",
+ MAX_LIBS,
+ dp->d_name);
+ }
+
+ // attempt to load it
+ else {
+ char* szPrefixed = malloc((strlen(dp->d_name) + strlen(p) + 2) *
+ sizeof(char));
+ sprintf(szPrefixed, "%s/", p);
+ strcat(szPrefixed, dp->d_name);
+ libHandles[curr_lib] = dlopen(szPrefixed, RTLD_NOW | RTLD_LOCAL);
+
+ // did the load succeed?
+ if (libHandles[curr_lib] != 0) {
+ printf("Loaded ABC library: %s (Abc library extension #%d)\n", szPrefixed, curr_lib);
+ curr_lib++;
+ } else {
+ printf("Warning: failed to load ABC library %s:\n\t%s\n", szPrefixed, dlerror());
+ }
+
+ free(szPrefixed);
+ }
+ }
+ }
+ closedir(dirp);
+ p = endp+1;
+ }
+
+ free(init_p);
+#endif
+
+ // null terminate the list of handles
+ libHandles[curr_lib] = 0;
+}
+
+////////////////////////////////////////////////////////////////////////////////////////////////////
+// This will close all open ABC library extensions
+////////////////////////////////////////////////////////////////////////////////////////////////////
+void close_libs() {
+#ifdef WIN32
+ printf("Warning: close_libs WIN32 not implemented.\n");
+#else
+ int i;
+ for (i = 0; libHandles[i] != 0; i++) {
+ if (dlclose(libHandles[i]) != 0) {
+ printf("Warning: failed to close library %d\n", i);
+ }
+ libHandles[i] = 0;
+ }
+#endif
+}
+
+////////////////////////////////////////////////////////////////////////////////////////////////////
+// This will get a pointer to a function inside of an open library
+////////////////////////////////////////////////////////////////////////////////////////////////////
+void* get_fnct_ptr(int lib_num, char* sym_name) {
+#ifdef WIN32
+ printf("Warning: get_fnct_ptr WIN32 not implemented.\n");
+ return 0;
+#else
+ return dlsym(libHandles[lib_num], sym_name);
+#endif
+}
+
+////////////////////////////////////////////////////////////////////////////////////////////////////
+// This will call an initialization function in every open library.
+////////////////////////////////////////////////////////////////////////////////////////////////////
+void call_inits(Abc_Frame_t* pAbc) {
+ int i;
+ lib_init_end_func init_func;
+ for (i = 0; libHandles[i] != 0; i++) {
+ init_func = (lib_init_end_func) get_fnct_ptr(i, "abc_init");
+ if (init_func == 0) {
+ printf("Warning: Failed to initialize library %d.\n", i);
+ } else {
+ (*init_func)(pAbc);
+ }
+ }
+}
+
+////////////////////////////////////////////////////////////////////////////////////////////////////
+// This will call a shutdown function in every open library.
+////////////////////////////////////////////////////////////////////////////////////////////////////
+void call_ends(Abc_Frame_t* pAbc) {
+ int i;
+ lib_init_end_func end_func;
+ for (i = 0; libHandles[i] != 0; i++) {
+ end_func = (lib_init_end_func) get_fnct_ptr(i, "abc_end");
+ if (end_func == 0) {
+ printf("Warning: Failed to end library %d.\n", i);
+ } else {
+ (*end_func)(pAbc);
+ }
+ }
+}
+
+void Libs_Init(Abc_Frame_t * pAbc)
+{
+ open_libs();
+ call_inits(pAbc);
+}
+
+void Libs_End(Abc_Frame_t * pAbc)
+{
+ call_ends(pAbc);
+
+ // It's good practice to close our libraries at this point, but this can mess up any backtrace printed by Valgind.
+ // close_libs();
+}
+
+////////////////////////////////////////////////////////////////////////
+/// END OF FILE ///
+////////////////////////////////////////////////////////////////////////
diff --git a/src/base/main/main.c b/src/base/main/main.c
index 0622a3bd..8f43c605 100644
--- a/src/base/main/main.c
+++ b/src/base/main/main.c
@@ -20,6 +20,9 @@
#include "mainInt.h"
+// this line should be included in the library project
+//#define _LIB
+
////////////////////////////////////////////////////////////////////////
/// DECLARATIONS ///
////////////////////////////////////////////////////////////////////////
@@ -27,9 +30,11 @@
static int TypeCheck( Abc_Frame_t * pAbc, char * s);
////////////////////////////////////////////////////////////////////////
-/// FUNCTION DEFITIONS ///
+/// FUNCTION DEFINITIONS ///
////////////////////////////////////////////////////////////////////////
+#ifndef _LIB
+
/**Function*************************************************************
Synopsis [The main() procedure.]
@@ -48,11 +53,14 @@ int main( int argc, char * argv[] )
char * sCommand, * sOutFile, * sInFile;
int fStatus = 0;
bool fBatch, fInitSource, fInitRead, fFinalWrite;
-
+
// added to detect memory leaks:
#ifdef _DEBUG
_CrtSetDbgFlag( _CRTDBG_ALLOC_MEM_DF | _CRTDBG_LEAK_CHECK_DF );
#endif
+
+// Npn_Experiment();
+// Npn_Generate();
// get global frame (singleton pattern)
// will be initialized on first call
@@ -64,24 +72,24 @@ int main( int argc, char * argv[] )
fInitRead = 0;
fFinalWrite = 0;
sInFile = sOutFile = NULL;
- sprintf( sReadCmd, "read_blif_mv" );
- sprintf( sWriteCmd, "write_blif_mv" );
+ sprintf( sReadCmd, "read" );
+ sprintf( sWriteCmd, "write" );
- util_getopt_reset();
- while ((c = util_getopt(argc, argv, "c:hf:F:o:st:T:x")) != EOF) {
+ Extra_UtilGetoptReset();
+ while ((c = Extra_UtilGetopt(argc, argv, "c:hf:F:o:st:T:x")) != EOF) {
switch(c) {
case 'c':
- strcpy( sCommandUsr, util_optarg );
+ strcpy( sCommandUsr, globalUtilOptarg );
fBatch = 1;
break;
case 'f':
- sprintf(sCommandUsr, "source %s", util_optarg);
+ sprintf(sCommandUsr, "source %s", globalUtilOptarg);
fBatch = 1;
break;
case 'F':
- sprintf(sCommandUsr, "source -x %s", util_optarg);
+ sprintf(sCommandUsr, "source -x %s", globalUtilOptarg);
fBatch = 1;
break;
@@ -90,7 +98,7 @@ int main( int argc, char * argv[] )
break;
case 'o':
- sOutFile = util_optarg;
+ sOutFile = globalUtilOptarg;
fFinalWrite = 1;
break;
@@ -99,12 +107,12 @@ int main( int argc, char * argv[] )
break;
case 't':
- if ( TypeCheck( pAbc, util_optarg ) )
+ if ( TypeCheck( pAbc, globalUtilOptarg ) )
{
- if ( !strcmp(util_optarg, "none") == 0 )
+ if ( !strcmp(globalUtilOptarg, "none") == 0 )
{
fInitRead = 1;
- sprintf( sReadCmd, "read_%s", util_optarg );
+ sprintf( sReadCmd, "read_%s", globalUtilOptarg );
}
}
else {
@@ -114,12 +122,12 @@ int main( int argc, char * argv[] )
break;
case 'T':
- if ( TypeCheck( pAbc, util_optarg ) )
+ if ( TypeCheck( pAbc, globalUtilOptarg ) )
{
- if (!strcmp(util_optarg, "none") == 0)
+ if (!strcmp(globalUtilOptarg, "none") == 0)
{
fFinalWrite = 1;
- sprintf( sWriteCmd, "write_%s", util_optarg);
+ sprintf( sWriteCmd, "write_%s", globalUtilOptarg);
}
}
else {
@@ -143,14 +151,14 @@ int main( int argc, char * argv[] )
{
pAbc->fBatchMode = 1;
- if (argc - util_optind == 0)
+ if (argc - globalUtilOptind == 0)
{
sInFile = NULL;
}
- else if (argc - util_optind == 1)
+ else if (argc - globalUtilOptind == 1)
{
fInitRead = 1;
- sInFile = argv[util_optind];
+ sInFile = argv[globalUtilOptind];
}
else
{
@@ -209,14 +217,11 @@ int main( int argc, char * argv[] )
break;
}
}
-
+
// if the memory should be freed, quit packages
- if ( fStatus == -2 )
+ if ( fStatus < 0 )
{
- // perform uninitializations
- Abc_FrameEnd( pAbc );
- // stop the framework
- Abc_FrameDeallocate( pAbc );
+ Abc_Stop();
}
return 0;
@@ -226,6 +231,58 @@ usage:
return 1;
}
+#endif
+
+/**Function*************************************************************
+
+ Synopsis [Initialization procedure for the library project.]
+
+ Description [Note that when Abc_Start() is run in a static library
+ project, it does not load the resource file by default. As a result,
+ ABC is not set up the same way, as when it is run on a command line.
+ For example, some error messages while parsing files will not be
+ produced, and intermediate networks will not be checked for consistancy.
+ One possibility is to load the resource file after Abc_Start() as follows:
+ Abc_UtilsSource( Abc_FrameGetGlobalFrame() );]
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Abc_Start()
+{
+ Abc_Frame_t * pAbc;
+ // added to detect memory leaks:
+#ifdef _DEBUG
+ _CrtSetDbgFlag( _CRTDBG_ALLOC_MEM_DF | _CRTDBG_LEAK_CHECK_DF );
+#endif
+ // start the glocal frame
+ pAbc = Abc_FrameGetGlobalFrame();
+ // source the resource file
+// Abc_UtilsSource( pAbc );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Deallocation procedure for the library project.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Abc_Stop()
+{
+ Abc_Frame_t * pAbc;
+ pAbc = Abc_FrameGetGlobalFrame();
+ // perform uninitializations
+ Abc_FrameEnd( pAbc );
+ // stop the framework
+ Abc_FrameDeallocate( pAbc );
+}
/**Function********************************************************************
diff --git a/src/base/main/main.h b/src/base/main/main.h
index 0d47dec5..4433a8b4 100644
--- a/src/base/main/main.h
+++ b/src/base/main/main.h
@@ -21,6 +21,10 @@
#ifndef __MAIN_H__
#define __MAIN_H__
+#ifdef __cplusplus
+extern "C" {
+#endif
+
////////////////////////////////////////////////////////////////////////
/// TYPEDEFS ///
////////////////////////////////////////////////////////////////////////
@@ -40,17 +44,10 @@ typedef struct Abc_Frame_t_ Abc_Frame_t;
// it is used to catch memory leaks on Windows
#include "leaks.h"
-// standard includes
-#include <stdio.h>
-#include <string.h>
-
-// includes from GLU
-#include "util.h"
-#include "st.h"
-
// data structure packages
#include "extra.h"
#include "vec.h"
+#include "st.h"
// core packages
#include "abc.h"
@@ -66,20 +63,25 @@ typedef struct Abc_Frame_t_ Abc_Frame_t;
////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////
-/// MACRO DEFITIONS ///
+/// MACRO DEFINITIONS ///
////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////
-/// FUNCTION DEFITIONS ///
+/// FUNCTION DEFINITIONS ///
////////////////////////////////////////////////////////////////////////
-/*=== mvFrame.c ===========================================================*/
-extern Abc_Ntk_t * Abc_FrameReadNet( Abc_Frame_t * p );
+/*=== main.c ===========================================================*/
+extern void Abc_Start();
+extern void Abc_Stop();
+
+/*=== mainFrame.c ===========================================================*/
+extern Abc_Ntk_t * Abc_FrameReadNtk( Abc_Frame_t * p );
extern FILE * Abc_FrameReadOut( Abc_Frame_t * p );
extern FILE * Abc_FrameReadErr( Abc_Frame_t * p );
extern bool Abc_FrameReadMode( Abc_Frame_t * p );
extern bool Abc_FrameSetMode( Abc_Frame_t * p, bool fNameMode );
extern void Abc_FrameRestart( Abc_Frame_t * p );
+extern bool Abc_FrameShowProgress( Abc_Frame_t * p );
extern void Abc_FrameSetCurrentNetwork( Abc_Frame_t * p, Abc_Ntk_t * pNet );
extern void Abc_FrameSwapCurrentAndBackup( Abc_Frame_t * p );
@@ -90,11 +92,12 @@ extern void Abc_FrameDeleteAllNetworks( Abc_Frame_t * p );
extern void Abc_FrameSetGlobalFrame( Abc_Frame_t * p );
extern Abc_Frame_t * Abc_FrameGetGlobalFrame();
-extern Abc_Ntk_t * Abc_FrameReadNtkStore();
-extern int Abc_FrameReadNtkStoreSize();
+extern Vec_Ptr_t * Abc_FrameReadStore();
+extern int Abc_FrameReadStoreSize();
extern void * Abc_FrameReadLibLut();
extern void * Abc_FrameReadLibGen();
extern void * Abc_FrameReadLibSuper();
+extern void * Abc_FrameReadLibVer();
extern void * Abc_FrameReadManDd();
extern void * Abc_FrameReadManDec();
extern char * Abc_FrameReadFlag( char * pFlag );
@@ -105,10 +108,15 @@ extern void Abc_FrameSetNtkStoreSize( int nStored );
extern void Abc_FrameSetLibLut( void * pLib );
extern void Abc_FrameSetLibGen( void * pLib );
extern void Abc_FrameSetLibSuper( void * pLib );
+extern void Abc_FrameSetLibVer( void * pLib );
extern void Abc_FrameSetFlag( char * pFlag, char * pValue );
+#ifdef __cplusplus
+}
+#endif
+
+#endif
+
////////////////////////////////////////////////////////////////////////
/// END OF FILE ///
////////////////////////////////////////////////////////////////////////
-
-#endif
diff --git a/src/base/main/mainFrame.c b/src/base/main/mainFrame.c
index 77c9f579..eae8b7a6 100644
--- a/src/base/main/mainFrame.c
+++ b/src/base/main/mainFrame.c
@@ -29,7 +29,7 @@
static Abc_Frame_t * s_GlobalFrame = NULL;
////////////////////////////////////////////////////////////////////////
-/// FUNCTION DEFITIONS ///
+/// FUNCTION DEFINITIONS ///
////////////////////////////////////////////////////////////////////////
/**Function*************************************************************
@@ -43,20 +43,20 @@ static Abc_Frame_t * s_GlobalFrame = NULL;
SeeAlso []
***********************************************************************/
-Abc_Ntk_t * Abc_FrameReadNtkStore() { return s_GlobalFrame->pStored; }
-int Abc_FrameReadNtkStoreSize() { return s_GlobalFrame->nStored; }
+Vec_Ptr_t * Abc_FrameReadStore() { return s_GlobalFrame->vStore; }
+int Abc_FrameReadStoreSize() { return Vec_PtrSize(s_GlobalFrame->vStore); }
void * Abc_FrameReadLibLut() { return s_GlobalFrame->pLibLut; }
void * Abc_FrameReadLibGen() { return s_GlobalFrame->pLibGen; }
void * Abc_FrameReadLibSuper() { return s_GlobalFrame->pLibSuper; }
-void * Abc_FrameReadManDd() { return s_GlobalFrame->dd; }
-void * Abc_FrameReadManDec() { return s_GlobalFrame->pManDec; }
+void * Abc_FrameReadLibVer() { return s_GlobalFrame->pLibVer; }
+void * Abc_FrameReadManDd() { if ( s_GlobalFrame->dd == NULL ) s_GlobalFrame->dd = Cudd_Init( 0, 0, CUDD_UNIQUE_SLOTS, CUDD_CACHE_SLOTS, 0 ); return s_GlobalFrame->dd; }
+void * Abc_FrameReadManDec() { if ( s_GlobalFrame->pManDec == NULL ) s_GlobalFrame->pManDec = Dec_ManStart(); return s_GlobalFrame->pManDec; }
char * Abc_FrameReadFlag( char * pFlag ) { return Cmd_FlagReadByName( s_GlobalFrame, pFlag ); }
-void Abc_FrameSetNtkStore( Abc_Ntk_t * pNtk ) { s_GlobalFrame->pStored = pNtk; }
-void Abc_FrameSetNtkStoreSize( int nStored ) { s_GlobalFrame->nStored = nStored; }
void Abc_FrameSetLibLut( void * pLib ) { s_GlobalFrame->pLibLut = pLib; }
void Abc_FrameSetLibGen( void * pLib ) { s_GlobalFrame->pLibGen = pLib; }
void Abc_FrameSetLibSuper( void * pLib ) { s_GlobalFrame->pLibSuper = pLib; }
+void Abc_FrameSetLibVer( void * pLib ) { s_GlobalFrame->pLibVer = pLib; }
void Abc_FrameSetFlag( char * pFlag, char * pValue ) { Cmd_FlagUpdateValue( s_GlobalFrame, pFlag, pValue ); }
/**Function*************************************************************
@@ -97,7 +97,8 @@ bool Abc_FrameIsFlagEnabled( char * pFlag )
Abc_Frame_t * Abc_FrameAllocate()
{
Abc_Frame_t * p;
-
+ extern void define_cube_size( int n );
+ extern void set_espresso_flags();
// allocate and clean
p = ALLOC( Abc_Frame_t, 1 );
memset( p, 0, sizeof(Abc_Frame_t) );
@@ -110,9 +111,13 @@ Abc_Frame_t * Abc_FrameAllocate()
// set the starting step
p->nSteps = 1;
p->fBatchMode = 0;
+ // networks to be used by choice
+ p->vStore = Vec_PtrAlloc( 16 );
// initialize decomposition manager
- p->pManDec = Dec_ManStart();
- p->dd = Cudd_Init( 0, 0, CUDD_UNIQUE_SLOTS, CUDD_CACHE_SLOTS, 0 );
+ define_cube_size(20);
+ set_espresso_flags();
+ // initialize the trace manager
+// Abc_HManStart();
return p;
}
@@ -130,11 +135,20 @@ Abc_Frame_t * Abc_FrameAllocate()
***********************************************************************/
void Abc_FrameDeallocate( Abc_Frame_t * p )
{
- Dec_ManStop( p->pManDec );
- Extra_StopManager( p->dd );
+ extern void Rwt_ManGlobalStop();
+ extern void undefine_cube_size();
+// extern void Ivy_TruthManStop();
+// Abc_HManStop();
+ undefine_cube_size();
+ Rwt_ManGlobalStop();
+// Ivy_TruthManStop();
+ if ( p->pLibVer ) Abc_LibFree( p->pLibVer, NULL );
+ if ( p->pManDec ) Dec_ManStop( p->pManDec );
+ if ( p->dd ) Extra_StopManager( p->dd );
+ if ( p->vStore ) Vec_PtrFree( p->vStore );
Abc_FrameDeleteAllNetworks( p );
free( p );
- p = NULL;
+ s_GlobalFrame = NULL;
}
/**Function*************************************************************
@@ -152,6 +166,22 @@ void Abc_FrameRestart( Abc_Frame_t * p )
{
}
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+bool Abc_FrameShowProgress( Abc_Frame_t * p )
+{
+ return Abc_FrameIsFlagEnabled( "progressbar" );
+}
+
/**Function*************************************************************
@@ -164,7 +194,7 @@ void Abc_FrameRestart( Abc_Frame_t * p )
SeeAlso []
***********************************************************************/
-Abc_Ntk_t * Abc_FrameReadNet( Abc_Frame_t * p )
+Abc_Ntk_t * Abc_FrameReadNtk( Abc_Frame_t * p )
{
return p->pNtkCur;
}
@@ -397,7 +427,7 @@ void Abc_FrameUnmapAllNetworks( Abc_Frame_t * p )
Abc_Ntk_t * pNtk;
for ( pNtk = p->pNtkCur; pNtk; pNtk = Abc_NtkBackup(pNtk) )
if ( Abc_NtkHasMapping(pNtk) )
- Abc_NtkUnmap( pNtk );
+ Abc_NtkMapToSop( pNtk );
}
/**Function*************************************************************
@@ -423,7 +453,7 @@ void Abc_FrameDeleteAllNetworks( Abc_Frame_t * p )
Abc_NtkDelete( pNtk );
// set the current network empty
p->pNtkCur = NULL;
- fprintf( p->Out, "All networks have been deleted.\n" );
+// fprintf( p->Out, "All networks have been deleted.\n" );
}
/**Function*************************************************************
diff --git a/src/base/main/mainInit.c b/src/base/main/mainInit.c
index 13710dcb..03953e5b 100644
--- a/src/base/main/mainInit.c
+++ b/src/base/main/mainInit.c
@@ -14,7 +14,7 @@
Date [Ver. 1.0. Started - June 20, 2005.]
- Revision [$Id: mainInit.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
+ Revision [$Id: mainInit.c,v 1.3 2005/09/14 22:53:37 casem Exp $]
***********************************************************************/
@@ -38,9 +38,11 @@ extern void Mio_Init( Abc_Frame_t * pAbc );
extern void Mio_End ( Abc_Frame_t * pAbc );
extern void Super_Init( Abc_Frame_t * pAbc );
extern void Super_End ( Abc_Frame_t * pAbc );
+extern void Libs_Init(Abc_Frame_t * pAbc);
+extern void Libs_End(Abc_Frame_t * pAbc);
////////////////////////////////////////////////////////////////////////
-/// FUNCTION DEFITIONS ///
+/// FUNCTION DEFINITIONS ///
////////////////////////////////////////////////////////////////////////
/**Function*************************************************************
@@ -63,6 +65,7 @@ void Abc_FrameInit( Abc_Frame_t * pAbc )
Map_Init( pAbc );
Mio_Init( pAbc );
Super_Init( pAbc );
+ Libs_Init( pAbc );
}
@@ -86,6 +89,7 @@ void Abc_FrameEnd( Abc_Frame_t * pAbc )
Map_End( pAbc );
Mio_End( pAbc );
Super_End( pAbc );
+ Libs_End( pAbc );
}
diff --git a/src/base/main/mainInt.h b/src/base/main/mainInt.h
index 6b929854..09ad96f3 100644
--- a/src/base/main/mainInt.h
+++ b/src/base/main/mainInt.h
@@ -18,8 +18,8 @@
***********************************************************************/
-#ifndef __Abc_INT_H__
-#define __Abc_INT_H__
+#ifndef __MAIN_INT_H__
+#define __MAIN_INT_H__
////////////////////////////////////////////////////////////////////////
/// INCLUDES ///
@@ -63,8 +63,7 @@ struct Abc_Frame_t_
int TimeCommand; // the runtime of the last command
int TimeTotal; // the total runtime of all commands
// temporary storage for structural choices
- Abc_Ntk_t * pStored; // the stored networks
- int nStored; // the number of stored networks
+ Vec_Ptr_t * vStore; // networks to be used by choice
// decomposition package
void * pManDec; // decomposition manager
DdManager * dd; // temporary BDD package
@@ -72,6 +71,7 @@ struct Abc_Frame_t_
void * pLibLut; // the current LUT library
void * pLibGen; // the current genlib
void * pLibSuper; // the current supergate library
+ void * pLibVer; // the current Verilog library
};
////////////////////////////////////////////////////////////////////////
@@ -79,12 +79,12 @@ struct Abc_Frame_t_
////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////
-/// MACRO DEFITIONS ///
+/// MACRO DEFINITIONS ///
////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////
-/// FUNCTION DEFITIONS ///
+/// FUNCTION DEFINITIONS ///
////////////////////////////////////////////////////////////////////////
/*=== mvMain.c ===========================================================*/
@@ -102,8 +102,8 @@ extern void Abc_UtilsPrintHello( Abc_Frame_t * pAbc );
extern void Abc_UtilsPrintUsage( Abc_Frame_t * pAbc, char * ProgName );
extern void Abc_UtilsSource( Abc_Frame_t * pAbc );
+#endif
+
////////////////////////////////////////////////////////////////////////
/// END OF FILE ///
////////////////////////////////////////////////////////////////////////
-
-#endif
diff --git a/src/base/main/mainUtils.c b/src/base/main/mainUtils.c
index 9d1201fa..58cc33ec 100644
--- a/src/base/main/mainUtils.c
+++ b/src/base/main/mainUtils.c
@@ -20,13 +20,17 @@
#include "mainInt.h"
+#ifndef _WIN32
+#include "readline/readline.h"
+#endif
+
////////////////////////////////////////////////////////////////////////
/// DECLARATIONS ///
////////////////////////////////////////////////////////////////////////
static char * DateReadFromDateString(char * datestr);
////////////////////////////////////////////////////////////////////////
-/// FUNCTION DEFITIONS ///
+/// FUNCTION DEFINITIONS ///
////////////////////////////////////////////////////////////////////////
/**Function*************************************************************
@@ -62,9 +66,18 @@ char * Abc_UtilsGetUsersInput( Abc_Frame_t * pAbc )
{
static char Buffer[1000], Prompt[1000];
sprintf( Prompt, "abc %02d> ", pAbc->nSteps );
+#ifdef _WIN32
fprintf( pAbc->Out, "%s", Prompt );
fgets( Buffer, 999, stdin );
return Buffer;
+#else
+ static char* line = NULL;
+ if (line != NULL) free(line);
+ line = readline(Prompt);
+ if (line == NULL){ printf("***EOF***\n"); exit(0); }
+ add_history(line);
+ return line;
+#endif
}
/**Function*************************************************************
@@ -134,32 +147,72 @@ void Abc_UtilsSource( Abc_Frame_t * pAbc )
printf( "Loaded \"abc.rc\" from the grandparent directory.\n" );
}
#else
+
+#if 0
{
- char * sPath1, * sPath2;
+ char * sPath1, * sPath2;
- // If .rc is present in both the home and current directories, then read
- // it from the home directory. Otherwise, read it from wherever it's located.
- sPath1 = util_file_search(".rc", "~/", "r");
- sPath2 = util_file_search(".rc", ".", "r");
+ // If .rc is present in both the home and current directories, then read
+ // it from the home directory. Otherwise, read it from wherever it's located.
+ sPath1 = Extra_UtilFileSearch(".rc", "~/", "r");
+ sPath2 = Extra_UtilFileSearch(".rc", ".", "r");
- if ( sPath1 && sPath2 ) {
- /* ~/.rc == .rc : Source the file only once */
- (void) Cmd_CommandExecute(pAbc, "source -s ~/.rc");
- }
- else {
- if (sPath1) {
+ if ( sPath1 && sPath2 ) {
+ /* ~/.rc == .rc : Source the file only once */
(void) Cmd_CommandExecute(pAbc, "source -s ~/.rc");
}
- if (sPath2) {
- (void) Cmd_CommandExecute(pAbc, "source -s .rc");
+ else {
+ if (sPath1) {
+ (void) Cmd_CommandExecute(pAbc, "source -s ~/.rc");
+ }
+ if (sPath2) {
+ (void) Cmd_CommandExecute(pAbc, "source -s .rc");
+ }
}
- }
- if ( sPath1 ) FREE(sPath1);
- if ( sPath2 ) FREE(sPath2);
+ if ( sPath1 ) FREE(sPath1);
+ if ( sPath2 ) FREE(sPath2);
- /* execute the abc script which can be open with the "open_path" */
- Cmd_CommandExecute( pAbc, "source -s abc.rc" );
+ /* execute the abc script which can be open with the "open_path" */
+ Cmd_CommandExecute( pAbc, "source -s abc.rc" );
}
+#endif
+
+ {
+ char * sPath1, * sPath2;
+ char * home;
+
+ // If .rc is present in both the home and current directories, then read
+ // it from the home directory. Otherwise, read it from wherever it's located.
+ home = getenv("HOME");
+ if (home){
+ char * sPath3 = ALLOC(char, strlen(home) + 2);
+ (void) sprintf(sPath3, "%s/", home);
+ sPath1 = Extra_UtilFileSearch(".abc.rc", sPath3, "r");
+ FREE(sPath3);
+ }else
+ sPath1 = NULL;
+
+ sPath2 = Extra_UtilFileSearch(".abc.rc", ".", "r");
+
+ if ( sPath1 && sPath2 ) {
+ /* ~/.rc == .rc : Source the file only once */
+ (void) Cmd_CommandExecute(pAbc, "source -s ~/.abc.rc");
+ }
+ else {
+ if (sPath1) {
+ (void) Cmd_CommandExecute(pAbc, "source -s ~/.abc.rc");
+ }
+ if (sPath2) {
+ (void) Cmd_CommandExecute(pAbc, "source -s .abc.rc");
+ }
+ }
+ if ( sPath1 ) FREE(sPath1);
+ if ( sPath2 ) FREE(sPath2);
+
+ /* execute the abc script which can be open with the "open_path" */
+ Cmd_CommandExecute( pAbc, "source -s abc.rc" );
+ }
+
#endif //WIN32
{
// reset command history
diff --git a/src/base/main/module.make b/src/base/main/module.make
index 59e1315e..367f89f6 100644
--- a/src/base/main/module.make
+++ b/src/base/main/module.make
@@ -1,4 +1,5 @@
SRC += src/base/main/main.c \
src/base/main/mainFrame.c \
src/base/main/mainInit.c \
+ src/base/main/libSupport.c \
src/base/main/mainUtils.c
diff --git a/src/base/seq/module.make b/src/base/seq/module.make
new file mode 100644
index 00000000..c7716180
--- /dev/null
+++ b/src/base/seq/module.make
@@ -0,0 +1,14 @@
+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
new file mode 100644
index 00000000..d3c9abda
--- /dev/null
+++ b/src/base/seq/seq.h
@@ -0,0 +1,101 @@
+/**CFile****************************************************************
+
+ FileName [seq.h]
+
+ SystemName [ABC: Logic synthesis and verification system.]
+
+ PackageName [Construction and manipulation of sequential AIGs.]
+
+ Synopsis [External declarations.]
+
+ Author [Alan Mishchenko]
+
+ Affiliation [UC Berkeley]
+
+ Date [Ver. 1.0. Started - June 20, 2005.]
+
+ Revision [$Id: seq.h,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#ifndef __SEQ_H__
+#define __SEQ_H__
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+////////////////////////////////////////////////////////////////////////
+/// INCLUDES ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+/// PARAMETERS ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+/// BASIC TYPES ///
+////////////////////////////////////////////////////////////////////////
+
+typedef struct Abc_Seq_t_ Abc_Seq_t;
+
+////////////////////////////////////////////////////////////////////////
+/// MACRO DEFINITIONS ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+/// FUNCTION DECLARATIONS ///
+////////////////////////////////////////////////////////////////////////
+
+/*=== seqAigCore.c ===========================================================*/
+extern void Seq_NtkSeqRetimeDelay( Abc_Ntk_t * pNtk, int nMaxIters, int fInitial, int fVerbose );
+extern void Seq_NtkSeqRetimeForward( Abc_Ntk_t * pNtk, int fInitial, int fVerbose );
+extern void Seq_NtkSeqRetimeBackward( Abc_Ntk_t * pNtk, int fInitial, int fVerbose );
+/*=== seqFpgaCore.c ===============================================================*/
+extern Abc_Ntk_t * Seq_NtkFpgaMapRetime( Abc_Ntk_t * pNtk, int nMaxIters, int fVerbose );
+/*=== seqMapCore.c ===============================================================*/
+extern Abc_Ntk_t * Seq_MapRetime( Abc_Ntk_t * pNtk, int nMaxIters, int fVerbose );
+/*=== seqRetCore.c ===========================================================*/
+extern Abc_Ntk_t * Seq_NtkRetime( Abc_Ntk_t * pNtk, int nMaxIters, int fInitial, int fVerbose );
+/*=== seqLatch.c ===============================================================*/
+extern void Seq_NodeDupLats( Abc_Obj_t * pObjNew, Abc_Obj_t * pObj, int Edge );
+extern int Seq_NodeCompareLats( Abc_Obj_t * pObj1, int Edge1, Abc_Obj_t * pObj2, int Edge2 );
+/*=== seqMan.c ===============================================================*/
+extern Abc_Seq_t * Seq_Create( Abc_Ntk_t * pNtk );
+extern void Seq_Resize( Abc_Seq_t * p, int nMaxId );
+extern void Seq_Delete( Abc_Seq_t * p );
+/*=== seqMaxMeanCycle.c ======================================================*/
+extern float Seq_NtkHoward( Abc_Ntk_t * pNtk, int fVerbose );
+extern void Seq_NtkSkewForward( Abc_Ntk_t * pNtk, float period, int fMinimize );
+/*=== abcSeq.c ===============================================================*/
+extern Abc_Ntk_t * Abc_NtkAigToSeq( Abc_Ntk_t * pNtk );
+extern Abc_Ntk_t * Abc_NtkSeqToLogicSop( Abc_Ntk_t * pNtk );
+extern bool Abc_NtkSeqCheck( Abc_Ntk_t * pNtk );
+/*=== seqShare.c =============================================================*/
+extern void Seq_NtkShareFanouts( Abc_Ntk_t * pNtk );
+extern void Seq_NtkShareLatches( Abc_Ntk_t * pNtkNew, Abc_Ntk_t * pNtk );
+extern void Seq_NtkShareLatchesMapping( Abc_Ntk_t * pNtkNew, Abc_Ntk_t * pNtk, Vec_Ptr_t * vMapAnds, int fFpga );
+extern void Seq_NtkShareLatchesClean( Abc_Ntk_t * pNtk );
+/*=== seqUtil.c ==============================================================*/
+extern char * Seq_ObjFaninGetInitPrintable( Abc_Obj_t * pObj, int Edge );
+extern void Seq_NtkLatchSetValues( Abc_Ntk_t * pNtk, Abc_InitType_t Init );
+extern int Seq_NtkLatchNum( Abc_Ntk_t * pNtk );
+extern int Seq_NtkLatchNumMax( Abc_Ntk_t * pNtk );
+extern int Seq_NtkLatchNumShared( Abc_Ntk_t * pNtk );
+extern void Seq_NtkLatchGetInitNums( Abc_Ntk_t * pNtk, int * pInits );
+extern int Seq_NtkLatchGetEqualFaninNum( Abc_Ntk_t * pNtk );
+extern int Seq_NtkCountNodesAboveLimit( Abc_Ntk_t * pNtk, int Limit );
+extern int Seq_MapComputeAreaFlows( Abc_Ntk_t * pNtk, int fVerbose );
+extern Vec_Ptr_t * Seq_NtkReachNodes( Abc_Ntk_t * pNtk, int fFromPos );
+extern int Seq_NtkCleanup( Abc_Ntk_t * pNtk, int fVerbose );
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
+
+////////////////////////////////////////////////////////////////////////
+/// END OF FILE ///
+////////////////////////////////////////////////////////////////////////
+
diff --git a/src/base/seq/seqAigCore.c b/src/base/seq/seqAigCore.c
new file mode 100644
index 00000000..42fa14a2
--- /dev/null
+++ b/src/base/seq/seqAigCore.c
@@ -0,0 +1,977 @@
+/**CFile****************************************************************
+
+ FileName [seqRetCore.c]
+
+ SystemName [ABC: Logic synthesis and verification system.]
+
+ PackageName [Construction and manipulation of sequential AIGs.]
+
+ Synopsis [The core of retiming procedures.]
+
+ Author [Alan Mishchenko]
+
+ Affiliation [UC Berkeley]
+
+ Date [Ver. 1.0. Started - June 20, 2005.]
+
+ Revision [$Id: seqRetCore.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "seqInt.h"
+
+////////////////////////////////////////////////////////////////////////
+/// DECLARATIONS ///
+////////////////////////////////////////////////////////////////////////
+
+/*
+ Retiming can be represented in three equivalent forms:
+ - as a set of integer lags for each node (array of chars by node ID)
+ - as a set of node numbers with lag for each, fwd and bwd (two arrays of Seq_RetStep_t_)
+ - as a set of latch moves over the nodes, fwd and bwd (two arrays of node pointers Abc_Obj_t *)
+*/
+
+static void Abc_ObjRetimeForward( Abc_Obj_t * pObj );
+static int Abc_ObjRetimeBackward( Abc_Obj_t * pObj, Abc_Ntk_t * pNtk, stmm_table * tTable, Vec_Int_t * vValues );
+static void Abc_ObjRetimeBackwardUpdateEdge( Abc_Obj_t * pObj, int Edge, stmm_table * tTable );
+static void Abc_NtkRetimeSetInitialValues( Abc_Ntk_t * pNtk, stmm_table * tTable, int * pModel );
+
+static void Seq_NtkImplementRetimingForward( Abc_Ntk_t * pNtk, Vec_Ptr_t * vMoves );
+static int Seq_NtkImplementRetimingBackward( Abc_Ntk_t * pNtk, Vec_Ptr_t * vMoves, int fVerbose );
+static void Abc_ObjRetimeForward( Abc_Obj_t * pObj );
+static int Abc_ObjRetimeBackward( Abc_Obj_t * pObj, Abc_Ntk_t * pNtk, stmm_table * tTable, Vec_Int_t * vValues );
+static void Abc_ObjRetimeBackwardUpdateEdge( Abc_Obj_t * pObj, int Edge, stmm_table * tTable );
+static void Abc_NtkRetimeSetInitialValues( Abc_Ntk_t * pNtk, stmm_table * tTable, int * pModel );
+
+static Vec_Ptr_t * Abc_NtkUtilRetimingTry( Abc_Ntk_t * pNtk, bool fForward );
+static Vec_Ptr_t * Abc_NtkUtilRetimingGetMoves( Abc_Ntk_t * pNtk, Vec_Int_t * vSteps, bool fForward );
+static Vec_Int_t * Abc_NtkUtilRetimingSplit( Vec_Str_t * vLags, int fForward );
+static void Abc_ObjRetimeForwardTry( Abc_Obj_t * pObj, int nLatches );
+static void Abc_ObjRetimeBackwardTry( Abc_Obj_t * pObj, int nLatches );
+
+
+////////////////////////////////////////////////////////////////////////
+/// FUNCTION DEFINITIONS ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+ Synopsis [Performs performs optimal delay retiming.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Seq_NtkSeqRetimeDelay( Abc_Ntk_t * pNtk, int nMaxIters, int fInitial, int fVerbose )
+{
+ Abc_Seq_t * p = pNtk->pManFunc;
+ int RetValue;
+ if ( !fInitial )
+ Seq_NtkLatchSetValues( pNtk, ABC_INIT_DC );
+ // get the retiming lags
+ p->nMaxIters = nMaxIters;
+ if ( !Seq_AigRetimeDelayLags( pNtk, fVerbose ) )
+ return;
+ // implement this retiming
+ RetValue = Seq_NtkImplementRetiming( pNtk, p->vLags, fVerbose );
+ if ( RetValue == 0 )
+ printf( "Retiming completed but initial state computation has failed.\n" );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Performs most forward retiming.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Seq_NtkSeqRetimeForward( Abc_Ntk_t * pNtk, int fInitial, int fVerbose )
+{
+ Vec_Ptr_t * vMoves;
+ Abc_Obj_t * pNode;
+ int i;
+ if ( !fInitial )
+ Seq_NtkLatchSetValues( pNtk, ABC_INIT_DC );
+ // get the forward moves
+ vMoves = Abc_NtkUtilRetimingTry( pNtk, 1 );
+ // undo the forward moves
+ Vec_PtrForEachEntryReverse( vMoves, pNode, i )
+ Abc_ObjRetimeBackwardTry( pNode, 1 );
+ // implement this forward retiming
+ Seq_NtkImplementRetimingForward( pNtk, vMoves );
+ Vec_PtrFree( vMoves );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Performs most backward retiming.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Seq_NtkSeqRetimeBackward( Abc_Ntk_t * pNtk, int fInitial, int fVerbose )
+{
+ Vec_Ptr_t * vMoves;
+ Abc_Obj_t * pNode;
+ int i, RetValue;
+ if ( !fInitial )
+ Seq_NtkLatchSetValues( pNtk, ABC_INIT_DC );
+ // get the backward moves
+ vMoves = Abc_NtkUtilRetimingTry( pNtk, 0 );
+ // undo the backward moves
+ Vec_PtrForEachEntryReverse( vMoves, pNode, i )
+ Abc_ObjRetimeForwardTry( pNode, 1 );
+ // implement this backward retiming
+ RetValue = Seq_NtkImplementRetimingBackward( pNtk, vMoves, fVerbose );
+ Vec_PtrFree( vMoves );
+ if ( RetValue == 0 )
+ printf( "Retiming completed but initial state computation has failed.\n" );
+}
+
+
+
+
+/**Function*************************************************************
+
+ Synopsis [Implements the retiming on the sequential AIG.]
+
+ Description [Split the retiming into forward and backward.]
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Seq_NtkImplementRetiming( Abc_Ntk_t * pNtk, Vec_Str_t * vLags, int fVerbose )
+{
+ Vec_Int_t * vSteps;
+ Vec_Ptr_t * vMoves;
+ int RetValue;
+
+ // forward retiming
+ vSteps = Abc_NtkUtilRetimingSplit( vLags, 1 );
+ // translate each set of steps into moves
+ if ( fVerbose )
+ printf( "The number of forward steps = %6d.\n", Vec_IntSize(vSteps) );
+ vMoves = Abc_NtkUtilRetimingGetMoves( pNtk, vSteps, 1 );
+ if ( fVerbose )
+ printf( "The number of forward moves = %6d.\n", Vec_PtrSize(vMoves) );
+ // implement this retiming
+ Seq_NtkImplementRetimingForward( pNtk, vMoves );
+ Vec_IntFree( vSteps );
+ Vec_PtrFree( vMoves );
+
+ // backward retiming
+ vSteps = Abc_NtkUtilRetimingSplit( vLags, 0 );
+ // translate each set of steps into moves
+ if ( fVerbose )
+ printf( "The number of backward steps = %6d.\n", Vec_IntSize(vSteps) );
+ vMoves = Abc_NtkUtilRetimingGetMoves( pNtk, vSteps, 0 );
+ if ( fVerbose )
+ printf( "The number of backward moves = %6d.\n", Vec_PtrSize(vMoves) );
+ // implement this retiming
+ RetValue = Seq_NtkImplementRetimingBackward( pNtk, vMoves, fVerbose );
+ Vec_IntFree( vSteps );
+ Vec_PtrFree( vMoves );
+ return RetValue;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Implements the given retiming on the sequential AIG.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Seq_NtkImplementRetimingForward( Abc_Ntk_t * pNtk, Vec_Ptr_t * vMoves )
+{
+ Abc_Obj_t * pNode;
+ int i;
+ Vec_PtrForEachEntry( vMoves, pNode, i )
+ Abc_ObjRetimeForward( pNode );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Retimes node forward by one latch.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Abc_ObjRetimeForward( Abc_Obj_t * pObj )
+{
+ Abc_Obj_t * pFanout;
+ int Init0, Init1, Init, i;
+ assert( Abc_ObjFaninNum(pObj) == 2 );
+ assert( Seq_ObjFaninL0(pObj) >= 1 );
+ assert( Seq_ObjFaninL1(pObj) >= 1 );
+ // remove the init values from the fanins
+ Init0 = Seq_NodeDeleteFirst( pObj, 0 );
+ Init1 = Seq_NodeDeleteFirst( pObj, 1 );
+ assert( Init0 != ABC_INIT_NONE );
+ assert( Init1 != ABC_INIT_NONE );
+ // take into account the complements in the node
+ if ( Abc_ObjFaninC0(pObj) )
+ {
+ if ( Init0 == ABC_INIT_ZERO )
+ Init0 = ABC_INIT_ONE;
+ else if ( Init0 == ABC_INIT_ONE )
+ Init0 = ABC_INIT_ZERO;
+ }
+ if ( Abc_ObjFaninC1(pObj) )
+ {
+ if ( Init1 == ABC_INIT_ZERO )
+ Init1 = ABC_INIT_ONE;
+ else if ( Init1 == ABC_INIT_ONE )
+ Init1 = ABC_INIT_ZERO;
+ }
+ // compute the value at the output of the node
+ if ( Init0 == ABC_INIT_ZERO || Init1 == ABC_INIT_ZERO )
+ Init = ABC_INIT_ZERO;
+ else if ( Init0 == ABC_INIT_ONE && Init1 == ABC_INIT_ONE )
+ Init = ABC_INIT_ONE;
+ else
+ Init = ABC_INIT_DC;
+
+ // make sure the label is clean
+ Abc_ObjForEachFanout( pObj, pFanout, i )
+ assert( pFanout->fMarkC == 0 );
+ // add the init values to the fanouts
+ Abc_ObjForEachFanout( pObj, pFanout, i )
+ {
+ if ( pFanout->fMarkC )
+ continue;
+ pFanout->fMarkC = 1;
+ if ( Abc_ObjFaninId0(pFanout) != Abc_ObjFaninId1(pFanout) )
+ Seq_NodeInsertLast( pFanout, Abc_ObjFanoutEdgeNum(pObj, pFanout), Init );
+ else
+ {
+ assert( Abc_ObjFanin0(pFanout) == pObj );
+ Seq_NodeInsertLast( pFanout, 0, Init );
+ Seq_NodeInsertLast( pFanout, 1, Init );
+ }
+ }
+ // clean the label
+ Abc_ObjForEachFanout( pObj, pFanout, i )
+ pFanout->fMarkC = 0;
+}
+
+
+/**Function*************************************************************
+
+ Synopsis [Implements the given retiming on the sequential AIG.]
+
+ Description [Returns 0 of initial state computation fails.]
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Seq_NtkImplementRetimingBackward( Abc_Ntk_t * pNtk, Vec_Ptr_t * vMoves, int fVerbose )
+{
+ Seq_RetEdge_t RetEdge;
+ stmm_table * tTable;
+ stmm_generator * gen;
+ Vec_Int_t * vValues;
+ Abc_Ntk_t * pNtkProb, * pNtkMiter, * pNtkCnf;
+ Abc_Obj_t * pNode, * pNodeNew;
+ int * pModel, RetValue, i, clk;
+
+ // return if the retiming is trivial
+ if ( Vec_PtrSize(vMoves) == 0 )
+ return 1;
+
+ // create the network for the initial state computation
+ // start the table and the array of PO values
+ pNtkProb = Abc_NtkAlloc( ABC_NTK_LOGIC, ABC_FUNC_SOP, 1 );
+ tTable = stmm_init_table( stmm_numcmp, stmm_numhash );
+ vValues = Vec_IntAlloc( 100 );
+
+ // perform the backward moves and build the network for initial state computation
+ RetValue = 0;
+ Vec_PtrForEachEntry( vMoves, pNode, i )
+ RetValue |= Abc_ObjRetimeBackward( pNode, pNtkProb, tTable, vValues );
+
+ // add the PIs corresponding to the white spots
+ stmm_foreach_item( tTable, gen, (char **)&RetEdge, (char **)&pNodeNew )
+ Abc_ObjAddFanin( pNodeNew, Abc_NtkCreatePi(pNtkProb) );
+
+ // add the PI/PO names
+ Abc_NtkAddDummyPiNames( pNtkProb );
+ Abc_NtkAddDummyPoNames( pNtkProb );
+ Abc_NtkAddDummyAssertNames( pNtkProb );
+
+ // make sure everything is okay with the network structure
+ if ( !Abc_NtkDoCheck( pNtkProb ) )
+ {
+ printf( "Seq_NtkImplementRetimingBackward: The internal network check has failed.\n" );
+ Abc_NtkRetimeSetInitialValues( pNtk, tTable, NULL );
+ Abc_NtkDelete( pNtkProb );
+ stmm_free_table( tTable );
+ Vec_IntFree( vValues );
+ return 0;
+ }
+
+ // check if conflict is found
+ if ( RetValue )
+ {
+ printf( "Seq_NtkImplementRetimingBackward: A top level conflict is detected. DC latch values are used.\n" );
+ Abc_NtkRetimeSetInitialValues( pNtk, tTable, NULL );
+ Abc_NtkDelete( pNtkProb );
+ stmm_free_table( tTable );
+ Vec_IntFree( vValues );
+ return 0;
+ }
+
+ // get the miter cone
+ pNtkMiter = Abc_NtkCreateTarget( pNtkProb, pNtkProb->vCos, vValues );
+ Abc_NtkDelete( pNtkProb );
+ Vec_IntFree( vValues );
+
+ if ( fVerbose )
+ printf( "The number of ANDs in the AIG = %5d.\n", Abc_NtkNodeNum(pNtkMiter) );
+
+ // transform the miter into a logic network for efficient CNF construction
+// pNtkCnf = Abc_Ntk_Renode( pNtkMiter, 0, 100, 1, 0, 0 );
+// Abc_NtkDelete( pNtkMiter );
+ pNtkCnf = pNtkMiter;
+
+ // solve the miter
+clk = clock();
+// RetValue = Abc_NtkMiterSat_OldAndRusty( pNtkCnf, 30, 0 );
+ RetValue = Abc_NtkMiterSat( pNtkCnf, (sint64)500000, (sint64)50000000, 0, 0, NULL, NULL );
+if ( fVerbose )
+if ( clock() - clk > 100 )
+{
+PRT( "SAT solving time", clock() - clk );
+}
+ pModel = pNtkCnf->pModel; pNtkCnf->pModel = NULL;
+ Abc_NtkDelete( pNtkCnf );
+
+ // analyze the result
+ if ( RetValue == -1 || RetValue == 1 )
+ {
+ Abc_NtkRetimeSetInitialValues( pNtk, tTable, NULL );
+ if ( RetValue == 1 )
+ printf( "Seq_NtkImplementRetimingBackward: The problem is unsatisfiable. DC latch values are used.\n" );
+ else
+ printf( "Seq_NtkImplementRetimingBackward: The SAT problem timed out. DC latch values are used.\n" );
+ stmm_free_table( tTable );
+ return 0;
+ }
+
+ // set the values of the latches
+ Abc_NtkRetimeSetInitialValues( pNtk, tTable, pModel );
+ stmm_free_table( tTable );
+ free( pModel );
+ return 1;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Retimes node backward by one latch.]
+
+ Description [Constructs the problem for initial state computation.
+ Returns 1 if the conflict is found.]
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Abc_ObjRetimeBackward( Abc_Obj_t * pObj, Abc_Ntk_t * pNtkNew, stmm_table * tTable, Vec_Int_t * vValues )
+{
+ Abc_Obj_t * pFanout;
+ Abc_InitType_t Init, Value;
+ Seq_RetEdge_t RetEdge;
+ Abc_Obj_t * pNodeNew, * pFanoutNew, * pBuffer;
+ int i, Edge, fMet0, fMet1, fMetN;
+
+ // make sure the node can be retimed
+ assert( Seq_ObjFanoutLMin(pObj) > 0 );
+ // get the fanout values
+ fMet0 = fMet1 = fMetN = 0;
+ Abc_ObjForEachFanout( pObj, pFanout, i )
+ {
+ if ( Abc_ObjFaninId0(pFanout) == pObj->Id )
+ {
+ Init = Seq_NodeGetInitLast( pFanout, 0 );
+ if ( Init == ABC_INIT_ZERO )
+ fMet0 = 1;
+ else if ( Init == ABC_INIT_ONE )
+ fMet1 = 1;
+ else if ( Init == ABC_INIT_NONE )
+ fMetN = 1;
+ }
+ if ( Abc_ObjFaninId1(pFanout) == pObj->Id )
+ {
+ Init = Seq_NodeGetInitLast( pFanout, 1 );
+ if ( Init == ABC_INIT_ZERO )
+ fMet0 = 1;
+ else if ( Init == ABC_INIT_ONE )
+ fMet1 = 1;
+ else if ( Init == ABC_INIT_NONE )
+ fMetN = 1;
+ }
+ }
+
+ // consider the case when all fanout latches have don't-care values
+ // the new values on the fanin edges will be don't-cares
+ if ( !fMet0 && !fMet1 && !fMetN )
+ {
+ // make sure the label is clean
+ Abc_ObjForEachFanout( pObj, pFanout, i )
+ assert( pFanout->fMarkC == 0 );
+ // update the fanout edges
+ Abc_ObjForEachFanout( pObj, pFanout, i )
+ {
+ if ( pFanout->fMarkC )
+ continue;
+ pFanout->fMarkC = 1;
+ if ( Abc_ObjFaninId0(pFanout) == pObj->Id )
+ Seq_NodeDeleteLast( pFanout, 0 );
+ if ( Abc_ObjFaninId1(pFanout) == pObj->Id )
+ Seq_NodeDeleteLast( pFanout, 1 );
+ }
+ // clean the label
+ Abc_ObjForEachFanout( pObj, pFanout, i )
+ pFanout->fMarkC = 0;
+ // update the fanin edges
+ Abc_ObjRetimeBackwardUpdateEdge( pObj, 0, tTable );
+ Abc_ObjRetimeBackwardUpdateEdge( pObj, 1, tTable );
+ Seq_NodeInsertFirst( pObj, 0, ABC_INIT_DC );
+ Seq_NodeInsertFirst( pObj, 1, ABC_INIT_DC );
+ return 0;
+ }
+ // the initial values on the fanout edges contain 0, 1, or unknown
+ // the new values on the fanin edges will be unknown
+
+ // add new AND-gate to the network
+ pNodeNew = Abc_NtkCreateNode( pNtkNew );
+ pNodeNew->pData = Abc_SopCreateAnd2( pNtkNew->pManFunc, Abc_ObjFaninC0(pObj), Abc_ObjFaninC1(pObj) );
+
+ // add PO fanouts if any
+ if ( fMet0 )
+ {
+ Abc_ObjAddFanin( Abc_NtkCreatePo(pNtkNew), pNodeNew );
+ Vec_IntPush( vValues, 0 );
+ }
+ if ( fMet1 )
+ {
+ Abc_ObjAddFanin( Abc_NtkCreatePo(pNtkNew), pNodeNew );
+ Vec_IntPush( vValues, 1 );
+ }
+
+ // make sure the label is clean
+ Abc_ObjForEachFanout( pObj, pFanout, i )
+ assert( pFanout->fMarkC == 0 );
+ // perform the changes
+ Abc_ObjForEachFanout( pObj, pFanout, i )
+ {
+ if ( pFanout->fMarkC )
+ continue;
+ pFanout->fMarkC = 1;
+ if ( Abc_ObjFaninId0(pFanout) == pObj->Id )
+ {
+ Edge = 0;
+ Value = Seq_NodeDeleteLast( pFanout, Edge );
+ if ( Value == ABC_INIT_NONE )
+ {
+ // value is unknown, remove it from the table
+ RetEdge.iNode = pFanout->Id;
+ RetEdge.iEdge = Edge;
+ RetEdge.iLatch = Seq_ObjFaninL( pFanout, Edge ); // after edge is removed
+ if ( !stmm_delete( tTable, (char **)&RetEdge, (char **)&pFanoutNew ) )
+ assert( 0 );
+ // create the fanout of the AND gate
+ Abc_ObjAddFanin( pFanoutNew, pNodeNew );
+ }
+ }
+ if ( Abc_ObjFaninId1(pFanout) == pObj->Id )
+ {
+ Edge = 1;
+ Value = Seq_NodeDeleteLast( pFanout, Edge );
+ if ( Value == ABC_INIT_NONE )
+ {
+ // value is unknown, remove it from the table
+ RetEdge.iNode = pFanout->Id;
+ RetEdge.iEdge = Edge;
+ RetEdge.iLatch = Seq_ObjFaninL( pFanout, Edge ); // after edge is removed
+ if ( !stmm_delete( tTable, (char **)&RetEdge, (char **)&pFanoutNew ) )
+ assert( 0 );
+ // create the fanout of the AND gate
+ Abc_ObjAddFanin( pFanoutNew, pNodeNew );
+ }
+ }
+ }
+ // clean the label
+ Abc_ObjForEachFanout( pObj, pFanout, i )
+ pFanout->fMarkC = 0;
+
+ // update the fanin edges
+ Abc_ObjRetimeBackwardUpdateEdge( pObj, 0, tTable );
+ Abc_ObjRetimeBackwardUpdateEdge( pObj, 1, tTable );
+ Seq_NodeInsertFirst( pObj, 0, ABC_INIT_NONE );
+ Seq_NodeInsertFirst( pObj, 1, ABC_INIT_NONE );
+
+ // add the buffer
+ pBuffer = Abc_NtkCreateNode( pNtkNew );
+ pBuffer->pData = Abc_SopCreateBuf( pNtkNew->pManFunc );
+ Abc_ObjAddFanin( pNodeNew, pBuffer );
+ // point to it from the table
+ RetEdge.iNode = pObj->Id;
+ RetEdge.iEdge = 0;
+ RetEdge.iLatch = 0;
+ if ( stmm_insert( tTable, (char *)Seq_RetEdge2Int(RetEdge), (char *)pBuffer ) )
+ assert( 0 );
+
+ // add the buffer
+ pBuffer = Abc_NtkCreateNode( pNtkNew );
+ pBuffer->pData = Abc_SopCreateBuf( pNtkNew->pManFunc );
+ Abc_ObjAddFanin( pNodeNew, pBuffer );
+ // point to it from the table
+ RetEdge.iNode = pObj->Id;
+ RetEdge.iEdge = 1;
+ RetEdge.iLatch = 0;
+ if ( stmm_insert( tTable, (char *)Seq_RetEdge2Int(RetEdge), (char *)pBuffer ) )
+ assert( 0 );
+
+ // report conflict is found
+ return fMet0 && fMet1;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Generates the printable edge label with the initial state.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Abc_ObjRetimeBackwardUpdateEdge( Abc_Obj_t * pObj, int Edge, stmm_table * tTable )
+{
+ Abc_Obj_t * pFanoutNew;
+ Seq_RetEdge_t RetEdge;
+ Abc_InitType_t Init;
+ int nLatches, i;
+
+ // get the number of latches on the edge
+ nLatches = Seq_ObjFaninL( pObj, Edge );
+ for ( i = nLatches - 1; i >= 0; i-- )
+ {
+ // get the value of this latch
+ Init = Seq_NodeGetInitOne( pObj, Edge, i );
+ if ( Init != ABC_INIT_NONE )
+ continue;
+ // get the retiming edge
+ RetEdge.iNode = pObj->Id;
+ RetEdge.iEdge = Edge;
+ RetEdge.iLatch = i;
+ // remove entry from table and add it with a different key
+ if ( !stmm_delete( tTable, (char **)&RetEdge, (char **)&pFanoutNew ) )
+ assert( 0 );
+ RetEdge.iLatch++;
+ if ( stmm_insert( tTable, (char *)Seq_RetEdge2Int(RetEdge), (char *)pFanoutNew ) )
+ assert( 0 );
+ }
+}
+
+/**Function*************************************************************
+
+ Synopsis [Sets the initial values.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Abc_NtkRetimeSetInitialValues( Abc_Ntk_t * pNtk, stmm_table * tTable, int * pModel )
+{
+ Abc_Obj_t * pNode;
+ stmm_generator * gen;
+ Seq_RetEdge_t RetEdge;
+ Abc_InitType_t Init;
+ int i;
+
+ i = 0;
+ stmm_foreach_item( tTable, gen, (char **)&RetEdge, NULL )
+ {
+ pNode = Abc_NtkObj( pNtk, RetEdge.iNode );
+ Init = pModel? (pModel[i]? ABC_INIT_ONE : ABC_INIT_ZERO) : ABC_INIT_DC;
+ Seq_NodeSetInitOne( pNode, RetEdge.iEdge, RetEdge.iLatch, Init );
+ i++;
+ }
+}
+
+
+
+/**Function*************************************************************
+
+ Synopsis [Performs forward retiming of the sequential AIG.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Vec_Ptr_t * Abc_NtkUtilRetimingTry( Abc_Ntk_t * pNtk, bool fForward )
+{
+ Vec_Ptr_t * vNodes, * vMoves;
+ Abc_Obj_t * pNode, * pFanout, * pFanin;
+ int i, k, nLatches;
+ assert( Abc_NtkIsSeq( pNtk ) );
+ // assume that all nodes can be retimed
+ vNodes = Vec_PtrAlloc( 100 );
+ Abc_AigForEachAnd( pNtk, pNode, i )
+ {
+ Vec_PtrPush( vNodes, pNode );
+ pNode->fMarkA = 1;
+ }
+ // process the nodes
+ vMoves = Vec_PtrAlloc( 100 );
+ Vec_PtrForEachEntry( vNodes, pNode, i )
+ {
+// printf( "(%d,%d) ", Seq_ObjFaninL0(pNode), Seq_ObjFaninL0(pNode) );
+ // unmark the node as processed
+ pNode->fMarkA = 0;
+ // get the number of latches to retime
+ if ( fForward )
+ nLatches = Seq_ObjFaninLMin(pNode);
+ else
+ nLatches = Seq_ObjFanoutLMin(pNode);
+ if ( nLatches == 0 )
+ continue;
+ assert( nLatches > 0 );
+ // retime the latches forward
+ if ( fForward )
+ Abc_ObjRetimeForwardTry( pNode, nLatches );
+ else
+ Abc_ObjRetimeBackwardTry( pNode, nLatches );
+ // write the moves
+ for ( k = 0; k < nLatches; k++ )
+ Vec_PtrPush( vMoves, pNode );
+ // schedule fanouts for updating
+ if ( fForward )
+ {
+ Abc_ObjForEachFanout( pNode, pFanout, k )
+ {
+ if ( Abc_ObjFaninNum(pFanout) != 2 || pFanout->fMarkA )
+ continue;
+ pFanout->fMarkA = 1;
+ Vec_PtrPush( vNodes, pFanout );
+ }
+ }
+ else
+ {
+ Abc_ObjForEachFanin( pNode, pFanin, k )
+ {
+ if ( Abc_ObjFaninNum(pFanin) != 2 || pFanin->fMarkA )
+ continue;
+ pFanin->fMarkA = 1;
+ Vec_PtrPush( vNodes, pFanin );
+ }
+ }
+ }
+ Vec_PtrFree( vNodes );
+ // make sure the marks are clean the the retiming is final
+ Abc_AigForEachAnd( pNtk, pNode, i )
+ {
+ assert( pNode->fMarkA == 0 );
+ if ( fForward )
+ assert( Seq_ObjFaninLMin(pNode) == 0 );
+ else
+ assert( Seq_ObjFanoutLMin(pNode) == 0 );
+ }
+ return vMoves;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Translates retiming steps into retiming moves.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Vec_Ptr_t * Abc_NtkUtilRetimingGetMoves( Abc_Ntk_t * pNtk, Vec_Int_t * vSteps, bool fForward )
+{
+ Seq_RetStep_t RetStep;
+ Vec_Ptr_t * vMoves;
+ Abc_Obj_t * pNode;
+ int i, k, iNode, nLatches, Number;
+ int fChange;
+ assert( Abc_NtkIsSeq( pNtk ) );
+
+/*
+ // try implementing all the moves at once
+ Vec_IntForEachEntry( vSteps, Number, i )
+ {
+ // get the retiming step
+ RetStep = Seq_Int2RetStep( Number );
+ // get the node to be retimed
+ pNode = Abc_NtkObj( pNtk, RetStep.iNode );
+ assert( RetStep.nLatches > 0 );
+ nLatches = RetStep.nLatches;
+
+ if ( fForward )
+ Abc_ObjRetimeForwardTry( pNode, nLatches );
+ else
+ Abc_ObjRetimeBackwardTry( pNode, nLatches );
+ }
+ // now look if any node has wrong number of latches
+ Abc_AigForEachAnd( pNtk, pNode, i )
+ {
+ if ( Seq_ObjFaninL0(pNode) < 0 )
+ printf( "Wrong 0node %d.\n", pNode->Id );
+ if ( Seq_ObjFaninL1(pNode) < 0 )
+ printf( "Wrong 1node %d.\n", pNode->Id );
+ }
+ // try implementing all the moves at once
+ Vec_IntForEachEntry( vSteps, Number, i )
+ {
+ // get the retiming step
+ RetStep = Seq_Int2RetStep( Number );
+ // get the node to be retimed
+ pNode = Abc_NtkObj( pNtk, RetStep.iNode );
+ assert( RetStep.nLatches > 0 );
+ nLatches = RetStep.nLatches;
+
+ if ( !fForward )
+ Abc_ObjRetimeForwardTry( pNode, nLatches );
+ else
+ Abc_ObjRetimeBackwardTry( pNode, nLatches );
+ }
+*/
+
+ // process the nodes
+ vMoves = Vec_PtrAlloc( 100 );
+ while ( Vec_IntSize(vSteps) > 0 )
+ {
+ iNode = 0;
+ fChange = 0;
+ Vec_IntForEachEntry( vSteps, Number, i )
+ {
+ // get the retiming step
+ RetStep = Seq_Int2RetStep( Number );
+ // get the node to be retimed
+ pNode = Abc_NtkObj( pNtk, RetStep.iNode );
+ assert( RetStep.nLatches > 0 );
+ // get the number of latches that can be retimed
+ if ( fForward )
+ nLatches = Seq_ObjFaninLMin(pNode);
+ else
+ nLatches = Seq_ObjFanoutLMin(pNode);
+ if ( nLatches == 0 )
+ {
+ Vec_IntWriteEntry( vSteps, iNode++, Seq_RetStep2Int(RetStep) );
+ continue;
+ }
+ assert( nLatches > 0 );
+ fChange = 1;
+ // get the number of latches to be retimed over this node
+ nLatches = ABC_MIN( nLatches, (int)RetStep.nLatches );
+ // retime the latches forward
+ if ( fForward )
+ Abc_ObjRetimeForwardTry( pNode, nLatches );
+ else
+ Abc_ObjRetimeBackwardTry( pNode, nLatches );
+ // write the moves
+ for ( k = 0; k < nLatches; k++ )
+ Vec_PtrPush( vMoves, pNode );
+ // subtract the retiming performed
+ RetStep.nLatches -= nLatches;
+ // store the node if it is not retimed completely
+ if ( RetStep.nLatches > 0 )
+ Vec_IntWriteEntry( vSteps, iNode++, Seq_RetStep2Int(RetStep) );
+ }
+ // reduce the array
+ Vec_IntShrink( vSteps, iNode );
+ if ( !fChange )
+ {
+ printf( "Warning: %d strange steps (a minor bug to be fixed later).\n", Vec_IntSize(vSteps) );
+/*
+ Vec_IntForEachEntry( vSteps, Number, i )
+ {
+ RetStep = Seq_Int2RetStep( Number );
+ printf( "%d(%d) ", RetStep.iNode, RetStep.nLatches );
+ }
+ printf( "\n" );
+*/
+ break;
+ }
+ }
+ // undo the tentative retiming
+ if ( fForward )
+ {
+ Vec_PtrForEachEntryReverse( vMoves, pNode, i )
+ Abc_ObjRetimeBackwardTry( pNode, 1 );
+ }
+ else
+ {
+ Vec_PtrForEachEntryReverse( vMoves, pNode, i )
+ Abc_ObjRetimeForwardTry( pNode, 1 );
+ }
+ return vMoves;
+}
+
+
+/**Function*************************************************************
+
+ Synopsis [Splits retiming into forward and backward.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Vec_Int_t * Abc_NtkUtilRetimingSplit( Vec_Str_t * vLags, int fForward )
+{
+ Vec_Int_t * vNodes;
+ Seq_RetStep_t RetStep;
+ int Value, i;
+ vNodes = Vec_IntAlloc( 100 );
+ Vec_StrForEachEntry( vLags, Value, i )
+ {
+ if ( Value < 0 && fForward )
+ {
+ RetStep.iNode = i;
+ RetStep.nLatches = -Value;
+ Vec_IntPush( vNodes, Seq_RetStep2Int(RetStep) );
+ }
+ else if ( Value > 0 && !fForward )
+ {
+ RetStep.iNode = i;
+ RetStep.nLatches = Value;
+ Vec_IntPush( vNodes, Seq_RetStep2Int(RetStep) );
+ }
+ }
+ return vNodes;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Retime node forward without initial states.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Abc_ObjRetimeForwardTry( Abc_Obj_t * pObj, int nLatches )
+{
+ Abc_Obj_t * pFanout;
+ int i;
+ // make sure it is an AND gate
+ assert( Abc_ObjFaninNum(pObj) == 2 );
+ // make sure it has enough latches
+// assert( Seq_ObjFaninL0(pObj) >= nLatches );
+// assert( Seq_ObjFaninL1(pObj) >= nLatches );
+ // subtract these latches on the fanin side
+ Seq_ObjAddFaninL0( pObj, -nLatches );
+ Seq_ObjAddFaninL1( pObj, -nLatches );
+ // make sure the label is clean
+ Abc_ObjForEachFanout( pObj, pFanout, i )
+ assert( pFanout->fMarkC == 0 );
+ // add these latches on the fanout side
+ Abc_ObjForEachFanout( pObj, pFanout, i )
+ {
+ if ( pFanout->fMarkC )
+ continue;
+ pFanout->fMarkC = 1;
+ if ( Abc_ObjFaninId0(pFanout) != Abc_ObjFaninId1(pFanout) )
+ Seq_ObjAddFanoutL( pObj, pFanout, nLatches );
+ else
+ {
+ assert( Abc_ObjFanin0(pFanout) == pObj );
+ Seq_ObjAddFaninL0( pFanout, nLatches );
+ Seq_ObjAddFaninL1( pFanout, nLatches );
+ }
+ }
+ // clean the label
+ Abc_ObjForEachFanout( pObj, pFanout, i )
+ pFanout->fMarkC = 0;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Retime node backward without initial states.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Abc_ObjRetimeBackwardTry( Abc_Obj_t * pObj, int nLatches )
+{
+ Abc_Obj_t * pFanout;
+ int i;
+ // make sure it is an AND gate
+ assert( Abc_ObjFaninNum(pObj) == 2 );
+ // make sure the label is clean
+ Abc_ObjForEachFanout( pObj, pFanout, i )
+ assert( pFanout->fMarkC == 0 );
+ // subtract these latches on the fanout side
+ Abc_ObjForEachFanout( pObj, pFanout, i )
+ {
+ if ( pFanout->fMarkC )
+ continue;
+ pFanout->fMarkC = 1;
+// assert( Abc_ObjFanoutL(pObj, pFanout) >= nLatches );
+ if ( Abc_ObjFaninId0(pFanout) != Abc_ObjFaninId1(pFanout) )
+ Seq_ObjAddFanoutL( pObj, pFanout, -nLatches );
+ else
+ {
+ assert( Abc_ObjFanin0(pFanout) == pObj );
+ Seq_ObjAddFaninL0( pFanout, -nLatches );
+ Seq_ObjAddFaninL1( pFanout, -nLatches );
+ }
+ }
+ // clean the label
+ Abc_ObjForEachFanout( pObj, pFanout, i )
+ pFanout->fMarkC = 0;
+ // add these latches on the fanin side
+ Seq_ObjAddFaninL0( pObj, nLatches );
+ Seq_ObjAddFaninL1( pObj, nLatches );
+}
+
+////////////////////////////////////////////////////////////////////////
+/// END OF FILE ///
+////////////////////////////////////////////////////////////////////////
+
+
diff --git a/src/base/seq/seqAigIter.c b/src/base/seq/seqAigIter.c
new file mode 100644
index 00000000..392638b8
--- /dev/null
+++ b/src/base/seq/seqAigIter.c
@@ -0,0 +1,268 @@
+/**CFile****************************************************************
+
+ FileName [seqRetIter.c]
+
+ SystemName [ABC: Logic synthesis and verification system.]
+
+ PackageName [Construction and manipulation of sequential AIGs.]
+
+ Synopsis [The iterative L-Value computation for retiming procedures.]
+
+ Author [Alan Mishchenko]
+
+ Affiliation [UC Berkeley]
+
+ Date [Ver. 1.0. Started - June 20, 2005.]
+
+ Revision [$Id: seqRetIter.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "seqInt.h"
+
+////////////////////////////////////////////////////////////////////////
+/// DECLARATIONS ///
+////////////////////////////////////////////////////////////////////////
+
+// the internal procedures
+static int Seq_RetimeSearch_rec( Abc_Ntk_t * pNtk, int FiMin, int FiMax, int fVerbose );
+static int Seq_RetimeForPeriod( Abc_Ntk_t * pNtk, int Fi, int fVerbose );
+static int Seq_RetimeNodeUpdateLValue( Abc_Obj_t * pObj, int Fi );
+
+////////////////////////////////////////////////////////////////////////
+/// FUNCTION DEFINITIONS ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+ Synopsis [Retimes AIG for optimal delay using Pan's algorithm.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Seq_AigRetimeDelayLags( Abc_Ntk_t * pNtk, int fVerbose )
+{
+ Abc_Seq_t * p = pNtk->pManFunc;
+ Abc_Obj_t * pNode;
+ int i, FiMax, RetValue, clk, clkIter;
+ char NodeLag;
+
+ assert( Abc_NtkIsSeq( pNtk ) );
+
+ // get the upper bound on the clock period
+ FiMax = 2 + Seq_NtkLevelMax(pNtk);
+
+ // make sure this clock period is feasible
+ if ( !Seq_RetimeForPeriod( pNtk, FiMax, fVerbose ) )
+ {
+ Vec_StrFill( p->vLags, p->nSize, 0 );
+ printf( "Error: The upper bound on the clock period cannot be computed.\n" );
+ printf( "The reason for this error may be the presence in the circuit of logic\n" );
+ printf( "that is not reachable from the PIs. Mapping/retiming is not performed.\n" );
+ return 0;
+ }
+
+ // search for the optimal clock period between 0 and nLevelMax
+clk = clock();
+ p->FiBestInt = Seq_RetimeSearch_rec( pNtk, 0, FiMax, fVerbose );
+clkIter = clock() - clk;
+
+ // recompute the best l-values
+ RetValue = Seq_RetimeForPeriod( pNtk, p->FiBestInt, fVerbose );
+ assert( RetValue );
+
+ // fix the problem with non-converged delays
+ Abc_AigForEachAnd( pNtk, pNode, i )
+ if ( Seq_NodeGetLValue(pNode) < -ABC_INFINITY/2 )
+ Seq_NodeSetLValue( pNode, 0 );
+
+ // write the retiming lags
+ Vec_StrFill( p->vLags, p->nSize, 0 );
+ Abc_AigForEachAnd( pNtk, pNode, i )
+ {
+ NodeLag = Seq_NodeComputeLag( Seq_NodeGetLValue(pNode), p->FiBestInt );
+ Seq_NodeSetLag( pNode, NodeLag );
+ }
+
+ // print the result
+ if ( fVerbose )
+ printf( "The best clock period is %3d.\n", p->FiBestInt );
+
+/*
+ printf( "lvalues and lags : " );
+ Abc_AigForEachAnd( pNtk, pNode, i )
+ printf( "%d=%d(%d) ", pNode->Id, Seq_NodeGetLValue(pNode), Seq_NodeGetLag(pNode) );
+ printf( "\n" );
+*/
+/*
+ {
+ FILE * pTable;
+ pTable = fopen( "stats.txt", "a+" );
+ fprintf( pTable, "%s ", pNtk->pName );
+ fprintf( pTable, "%d ", FiBest );
+ fprintf( pTable, "\n" );
+ fclose( pTable );
+ }
+*/
+/*
+ {
+ FILE * pTable;
+ pTable = fopen( "stats.txt", "a+" );
+ fprintf( pTable, "%s ", pNtk->pName );
+ fprintf( pTable, "%.2f ", (float)(p->timeCuts)/(float)(CLOCKS_PER_SEC) );
+ fprintf( pTable, "%.2f ", (float)(clkIter)/(float)(CLOCKS_PER_SEC) );
+ fprintf( pTable, "\n" );
+ fclose( pTable );
+ }
+*/
+ return 1;
+
+}
+
+/**Function*************************************************************
+
+ Synopsis [Performs binary search for the optimal clock period.]
+
+ Description [Assumes that FiMin is infeasible while FiMax is feasible.]
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Seq_RetimeSearch_rec( Abc_Ntk_t * pNtk, int FiMin, int FiMax, int fVerbose )
+{
+ int Median;
+ assert( FiMin < FiMax );
+ if ( FiMin + 1 == FiMax )
+ return FiMax;
+ Median = FiMin + (FiMax - FiMin)/2;
+ if ( Seq_RetimeForPeriod( pNtk, Median, fVerbose ) )
+ return Seq_RetimeSearch_rec( pNtk, FiMin, Median, fVerbose ); // Median is feasible
+ else
+ return Seq_RetimeSearch_rec( pNtk, Median, FiMax, fVerbose ); // Median is infeasible
+}
+
+/**Function*************************************************************
+
+ Synopsis [Returns 1 if retiming with this clock period is feasible.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Seq_RetimeForPeriod( Abc_Ntk_t * pNtk, int Fi, int fVerbose )
+{
+ Abc_Seq_t * p = pNtk->pManFunc;
+ Abc_Obj_t * pObj;
+ int i, c, RetValue, fChange, Counter;
+ char * pReason = "";
+
+ // set l-values of all nodes to be minus infinity
+ Vec_IntFill( p->vLValues, p->nSize, -ABC_INFINITY );
+
+ // set l-values of constants and PIs
+ pObj = Abc_NtkObj( pNtk, 0 );
+ Seq_NodeSetLValue( pObj, 0 );
+ Abc_NtkForEachPi( pNtk, pObj, i )
+ Seq_NodeSetLValue( pObj, 0 );
+
+ // update all values iteratively
+ Counter = 0;
+ for ( c = 0; c < p->nMaxIters; c++ )
+ {
+ fChange = 0;
+ Abc_AigForEachAnd( pNtk, pObj, i )
+ {
+ Counter++;
+ if ( Seq_NodeCutMan(pObj) )
+ RetValue = Seq_FpgaNodeUpdateLValue( pObj, Fi );
+ else
+ RetValue = Seq_RetimeNodeUpdateLValue( pObj, Fi );
+ if ( RetValue == SEQ_UPDATE_YES )
+ fChange = 1;
+ }
+ Abc_NtkForEachPo( pNtk, pObj, i )
+ {
+ if ( Seq_NodeCutMan(pObj) )
+ RetValue = Seq_FpgaNodeUpdateLValue( pObj, Fi );
+ else
+ RetValue = Seq_RetimeNodeUpdateLValue( pObj, Fi );
+ if ( RetValue == SEQ_UPDATE_FAIL )
+ break;
+ }
+ if ( RetValue == SEQ_UPDATE_FAIL )
+ break;
+ if ( fChange == 0 )
+ break;
+ }
+ if ( c == p->nMaxIters )
+ {
+ RetValue = SEQ_UPDATE_FAIL;
+ pReason = "(timeout)";
+ }
+ else
+ c++;
+ // report the results
+ if ( fVerbose )
+ {
+ if ( RetValue == SEQ_UPDATE_FAIL )
+ printf( "Period = %3d. Iterations = %3d. Updates = %10d. Infeasible %s\n", Fi, c, Counter, pReason );
+ else
+ printf( "Period = %3d. Iterations = %3d. Updates = %10d. Feasible\n", Fi, c, Counter );
+ }
+/*
+ // check if any AND gates have infinite delay
+ Counter = 0;
+ Abc_AigForEachAnd( pNtk, pObj, i )
+ Counter += (Seq_NodeGetLValue(pObj) < -ABC_INFINITY/2);
+ if ( Counter > 0 )
+ printf( "Warning: %d internal nodes have wrong l-values!\n", Counter );
+*/
+ return RetValue != SEQ_UPDATE_FAIL;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Computes the l-value of the node.]
+
+ Description [The node can be internal or a PO.]
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Seq_RetimeNodeUpdateLValue( Abc_Obj_t * pObj, int Fi )
+{
+ int lValueNew, lValueOld, lValue0, lValue1;
+ assert( !Abc_ObjIsPi(pObj) );
+ assert( Abc_ObjFaninNum(pObj) > 0 );
+ lValue0 = Seq_NodeGetLValue(Abc_ObjFanin0(pObj)) - Fi * Seq_ObjFaninL0(pObj);
+ if ( Abc_ObjIsPo(pObj) )
+ return (lValue0 > Fi)? SEQ_UPDATE_FAIL : SEQ_UPDATE_NO;
+ if ( Abc_ObjFaninNum(pObj) == 2 )
+ lValue1 = Seq_NodeGetLValue(Abc_ObjFanin1(pObj)) - Fi * Seq_ObjFaninL1(pObj);
+ else
+ lValue1 = -ABC_INFINITY;
+ lValueNew = 1 + ABC_MAX( lValue0, lValue1 );
+ lValueOld = Seq_NodeGetLValue(pObj);
+// if ( lValueNew == lValueOld )
+ if ( lValueNew <= lValueOld )
+ return SEQ_UPDATE_NO;
+ Seq_NodeSetLValue( pObj, lValueNew );
+ return SEQ_UPDATE_YES;
+}
+
+////////////////////////////////////////////////////////////////////////
+/// END OF FILE ///
+////////////////////////////////////////////////////////////////////////
+
+
diff --git a/src/base/seq/seqCreate.c b/src/base/seq/seqCreate.c
new file mode 100644
index 00000000..16c7cc92
--- /dev/null
+++ b/src/base/seq/seqCreate.c
@@ -0,0 +1,482 @@
+/**CFile****************************************************************
+
+ FileName [seqCreate.c]
+
+ SystemName [ABC: Logic synthesis and verification system.]
+
+ PackageName [Construction and manipulation of sequential AIGs.]
+
+ Synopsis [Transformations to and from the sequential AIG.]
+
+ Author [Alan Mishchenko]
+
+ Affiliation [UC Berkeley]
+
+ Date [Ver. 1.0. Started - June 20, 2005.]
+
+ Revision [$Id: seqCreate.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "seqInt.h"
+
+/*
+ A sequential network is similar to AIG in that it contains only
+ AND gates. However, the AND-gates are currently not hashed.
+
+ When converting AIG into sequential AIG:
+ - Const1/PIs/POs remain the same as in the original AIG.
+ - Instead of the latches, a new cutset is added, which is currently
+ defined as a set of AND gates that have a latch among their fanouts.
+ - The edges of a sequential AIG are labeled with latch attributes
+ in addition to the complementation attibutes.
+ - The attributes contain information about the number of latches
+ and their initial states.
+ - The number of latches is stored directly on the edges. The initial
+ states are stored in the sequential AIG manager.
+
+ In the current version of the code, the sequential AIG is static
+ in the sense that the new AIG nodes are never created.
+ The retiming (or retiming/mapping) is performed by moving the
+ latches over the static nodes of the AIG.
+ The new initial state after backward retiming is computed
+ by setting up and solving a SAT problem.
+*/
+
+////////////////////////////////////////////////////////////////////////
+/// DECLARATIONS ///
+////////////////////////////////////////////////////////////////////////
+
+static Abc_Obj_t * Abc_NodeAigToSeq( Abc_Obj_t * pObjNew, Abc_Obj_t * pObj, int Edge, Vec_Int_t * vInitValues );
+static void Abc_NtkAigCutsetCopy( Abc_Ntk_t * pNtk );
+static Abc_Obj_t * Abc_NodeSeqToLogic( Abc_Ntk_t * pNtkNew, Abc_Obj_t * pFanin, Seq_Lat_t * pRing, int nLatches );
+
+////////////////////////////////////////////////////////////////////////
+/// FUNCTION DEFINITIONS ///
+////////////////////////////////////////////////////////////////////////
+
+
+/**Function*************************************************************
+
+ Synopsis [Converts combinational AIG with latches into sequential AIG.]
+
+ Description [The const/PI/PO nodes are duplicated. The internal
+ nodes are duplicated in the topological order. The dangling nodes
+ are not duplicated. The choice nodes are duplicated.]
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Abc_Ntk_t * Abc_NtkAigToSeq( Abc_Ntk_t * pNtk )
+{
+ Abc_Ntk_t * pNtkNew;
+ Abc_Obj_t * pObj, * pFaninNew;
+ Vec_Int_t * vInitValues;
+ Abc_InitType_t Init;
+ int i, k, RetValue;
+
+ // make sure it is an AIG without self-feeding latches
+ assert( Abc_NtkIsStrash(pNtk) );
+ assert( Abc_NtkIsDfsOrdered(pNtk) );
+
+ if ( RetValue = Abc_NtkRemoveSelfFeedLatches(pNtk) )
+ printf( "Modified %d self-feeding latches. The result may not verify.\n", RetValue );
+ assert( Abc_NtkCountSelfFeedLatches(pNtk) == 0 );
+
+ // start the network
+ pNtkNew = Abc_NtkAlloc( ABC_NTK_SEQ, ABC_FUNC_AIG, 1 );
+ // duplicate the name and the spec
+ pNtkNew->pName = Extra_UtilStrsav(pNtk->pName);
+ pNtkNew->pSpec = Extra_UtilStrsav(pNtk->pSpec);
+
+ // map the constant nodes
+ Abc_NtkCleanCopy( pNtk );
+ Abc_AigConst1(pNtk)->pCopy = Abc_AigConst1(pNtkNew);
+
+ // copy all objects, except the latches and constant
+ Vec_PtrFill( pNtkNew->vObjs, Abc_NtkObjNumMax(pNtk), NULL );
+ Vec_PtrWriteEntry( pNtkNew->vObjs, 0, Abc_AigConst1(pNtk)->pCopy );
+ Abc_NtkForEachObj( pNtk, pObj, i )
+ {
+ if ( i == 0 || Abc_ObjIsLatch(pObj) )
+ continue;
+ pObj->pCopy = Abc_ObjAlloc( pNtkNew, pObj->Type );
+ pObj->pCopy->Id = pObj->Id; // the ID is the same for both
+ pObj->pCopy->fPhase = pObj->fPhase; // used to work with choices
+ pObj->pCopy->Level = pObj->Level; // used for upper bound on clock cycle
+ Vec_PtrWriteEntry( pNtkNew->vObjs, pObj->pCopy->Id, pObj->pCopy );
+ pNtkNew->nObjs++;
+ }
+ pNtkNew->nObjCounts[ABC_OBJ_NODE] = pNtk->nObjCounts[ABC_OBJ_NODE];
+
+ // create PI/PO and their names
+ Abc_NtkForEachPi( pNtk, pObj, i )
+ {
+ Vec_PtrPush( pNtkNew->vPis, pObj->pCopy );
+ Vec_PtrPush( pNtkNew->vCis, pObj->pCopy );
+ Abc_ObjAssignName( pObj->pCopy, Abc_ObjName(pObj), NULL );
+ }
+ Abc_NtkForEachPo( pNtk, pObj, i )
+ {
+ Vec_PtrPush( pNtkNew->vPos, pObj->pCopy );
+ Vec_PtrPush( pNtkNew->vCos, pObj->pCopy );
+ Abc_ObjAssignName( pObj->pCopy, Abc_ObjName(pObj), NULL );
+ }
+ Abc_NtkForEachAssert( pNtk, pObj, i )
+ {
+ Vec_PtrPush( pNtkNew->vAsserts, pObj->pCopy );
+ Vec_PtrPush( pNtkNew->vCos, pObj->pCopy );
+ Abc_ObjAssignName( pObj->pCopy, Abc_ObjName(pObj), NULL );
+ }
+
+ // relink the choice nodes
+ Abc_AigForEachAnd( pNtk, pObj, i )
+ if ( pObj->pData )
+ pObj->pCopy->pData = ((Abc_Obj_t *)pObj->pData)->pCopy;
+
+ // start the storage for initial states
+ Seq_Resize( pNtkNew->pManFunc, Abc_NtkObjNumMax(pNtkNew) );
+ // reconnect the internal nodes
+ vInitValues = Vec_IntAlloc( 100 );
+ Abc_NtkForEachObj( pNtk, pObj, i )
+ {
+ // skip constants, PIs, and latches
+ if ( Abc_ObjFaninNum(pObj) == 0 || Abc_ObjIsLatch(pObj) )
+ continue;
+ // process the first fanin
+ Vec_IntClear( vInitValues );
+ pFaninNew = Abc_NodeAigToSeq( pObj->pCopy, pObj, 0, vInitValues );
+ Abc_ObjAddFanin( pObj->pCopy, pFaninNew );
+ // store the initial values
+ Vec_IntForEachEntry( vInitValues, Init, k )
+ Seq_NodeInsertFirst( pObj->pCopy, 0, Init );
+ // skip single-input nodes
+ if ( Abc_ObjFaninNum(pObj) == 1 )
+ continue;
+ // process the second fanin
+ Vec_IntClear( vInitValues );
+ pFaninNew = Abc_NodeAigToSeq( pObj->pCopy, pObj, 1, vInitValues );
+ Abc_ObjAddFanin( pObj->pCopy, pFaninNew );
+ // store the initial values
+ Vec_IntForEachEntry( vInitValues, Init, k )
+ Seq_NodeInsertFirst( pObj->pCopy, 1, Init );
+ }
+ Vec_IntFree( vInitValues );
+
+ // set the cutset composed of latch drivers
+ Abc_NtkAigCutsetCopy( pNtk );
+ Seq_NtkLatchGetEqualFaninNum( pNtkNew );
+
+ // copy EXDC and check correctness
+ if ( pNtk->pExdc )
+ fprintf( stdout, "Warning: EXDC is not copied when converting to sequential AIG.\n" );
+ if ( !Abc_NtkCheck( pNtkNew ) )
+ fprintf( stdout, "Abc_NtkAigToSeq(): Network check has failed.\n" );
+ return pNtkNew;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Determines the fanin that is transparent for latches.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Abc_Obj_t * Abc_NodeAigToSeq( Abc_Obj_t * pObjNew, Abc_Obj_t * pObj, int Edge, Vec_Int_t * vInitValues )
+{
+ Abc_Obj_t * pFanin, * pFaninNew;
+ Abc_InitType_t Init;
+ // get the given fanin of the node
+ pFanin = Abc_ObjFanin( pObj, Edge );
+ // if fanin is the internal node, return its copy in the corresponding polarity
+ if ( !Abc_ObjIsLatch(pFanin) )
+ return Abc_ObjNotCond( pFanin->pCopy, Abc_ObjFaninC(pObj, Edge) );
+ // fanin is a latch
+ // get the new fanins
+ pFaninNew = Abc_NodeAigToSeq( pObjNew, pFanin, 0, vInitValues );
+ // get the initial state
+ Init = Abc_LatchInit(pFanin);
+ // complement the initial state if the inv is retimed over the latch
+ if ( Abc_ObjIsComplement(pFaninNew) )
+ {
+ if ( Init == ABC_INIT_ZERO )
+ Init = ABC_INIT_ONE;
+ else if ( Init == ABC_INIT_ONE )
+ Init = ABC_INIT_ZERO;
+ else if ( Init != ABC_INIT_DC )
+ assert( 0 );
+ }
+ // record the initial state
+ Vec_IntPush( vInitValues, Init );
+ return Abc_ObjNotCond( pFaninNew, Abc_ObjFaninC(pObj, Edge) );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Collects the cut set nodes.]
+
+ Description [These are internal AND gates that have latch fanouts.]
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Abc_NtkAigCutsetCopy( Abc_Ntk_t * pNtk )
+{
+ Abc_Obj_t * pLatch, * pDriver, * pDriverNew;
+ int i;
+ Abc_NtkIncrementTravId(pNtk);
+ Abc_NtkForEachLatch( pNtk, pLatch, i )
+ {
+ pDriver = Abc_ObjFanin0(pLatch);
+ if ( Abc_NodeIsTravIdCurrent(pDriver) || !Abc_AigNodeIsAnd(pDriver) )
+ continue;
+ Abc_NodeSetTravIdCurrent(pDriver);
+ pDriverNew = pDriver->pCopy;
+ Vec_PtrPush( pDriverNew->pNtk->vCutSet, pDriverNew );
+ }
+}
+
+/**Function*************************************************************
+
+ Synopsis [Converts a sequential AIG into a logic SOP network.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Abc_Ntk_t * Abc_NtkSeqToLogicSop( Abc_Ntk_t * pNtk )
+{
+ Abc_Ntk_t * pNtkNew;
+ Abc_Obj_t * pObj, * pFaninNew;
+ Seq_Lat_t * pRing;
+ int i;
+
+ assert( Abc_NtkIsSeq(pNtk) );
+ // start the network without latches
+ pNtkNew = Abc_NtkStartFrom( pNtk, ABC_NTK_LOGIC, ABC_FUNC_SOP );
+ // duplicate the nodes
+ Abc_AigForEachAnd( pNtk, pObj, i )
+ {
+ Abc_NtkDupObj(pNtkNew, pObj, 0);
+ pObj->pCopy->pData = Abc_SopCreateAnd2( pNtkNew->pManFunc, Abc_ObjFaninC0(pObj), Abc_ObjFaninC1(pObj) );
+ }
+ // share and create the latches
+ Seq_NtkShareLatches( pNtkNew, pNtk );
+ // connect the objects
+ Abc_AigForEachAnd( pNtk, pObj, i )
+ {
+ if ( pRing = Seq_NodeGetRing(pObj,0) )
+ pFaninNew = pRing->pLatch;
+ else
+ pFaninNew = Abc_ObjFanin0(pObj)->pCopy;
+ Abc_ObjAddFanin( pObj->pCopy, pFaninNew );
+
+ if ( pRing = Seq_NodeGetRing(pObj,1) )
+ pFaninNew = pRing->pLatch;
+ else
+ pFaninNew = Abc_ObjFanin1(pObj)->pCopy;
+ Abc_ObjAddFanin( pObj->pCopy, pFaninNew );
+ }
+ // connect the POs
+ Abc_NtkForEachPo( pNtk, pObj, i )
+ {
+ if ( pRing = Seq_NodeGetRing(pObj,0) )
+ pFaninNew = pRing->pLatch;
+ else
+ pFaninNew = Abc_ObjFanin0(pObj)->pCopy;
+ pFaninNew = Abc_ObjNotCond( pFaninNew, Abc_ObjFaninC0(pObj) );
+ Abc_ObjAddFanin( pObj->pCopy, pFaninNew );
+ }
+ // clean the latch pointers
+ Seq_NtkShareLatchesClean( pNtk );
+
+ // add the latches and their names
+ Abc_NtkAddDummyBoxNames( pNtkNew );
+ Abc_NtkOrderCisCos( pNtkNew );
+ // fix the problem with complemented and duplicated CO edges
+ Abc_NtkLogicMakeSimpleCos( pNtkNew, 0 );
+ if ( !Abc_NtkCheck( pNtkNew ) )
+ fprintf( stdout, "Abc_NtkSeqToLogicSop(): Network check has failed.\n" );
+ return pNtkNew;
+}
+
+
+/**Function*************************************************************
+
+ Synopsis [Converts a sequential AIG into a logic SOP network.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Abc_Ntk_t * Abc_NtkSeqToLogicSop_old( Abc_Ntk_t * pNtk )
+{
+ Abc_Ntk_t * pNtkNew;
+ Abc_Obj_t * pObj, * pFaninNew;
+ int i;
+
+ assert( Abc_NtkIsSeq(pNtk) );
+ // start the network without latches
+ pNtkNew = Abc_NtkStartFrom( pNtk, ABC_NTK_LOGIC, ABC_FUNC_SOP );
+
+ // duplicate the nodes, create node functions
+ Abc_NtkForEachNode( pNtk, pObj, i )
+ {
+ // skip the constant
+ if ( Abc_ObjFaninNum(pObj) == 0 )
+ continue;
+ // duplicate the node
+ Abc_NtkDupObj(pNtkNew, pObj, 0);
+ if ( Abc_ObjFaninNum(pObj) == 1 )
+ {
+ assert( !Abc_ObjFaninC0(pObj) );
+ pObj->pCopy->pData = Abc_SopCreateBuf( pNtkNew->pManFunc );
+ continue;
+ }
+ pObj->pCopy->pData = Abc_SopCreateAnd2( pNtkNew->pManFunc, Abc_ObjFaninC0(pObj), Abc_ObjFaninC1(pObj) );
+ }
+ // connect the objects
+ Abc_NtkForEachObj( pNtk, pObj, i )
+ {
+ assert( (int)pObj->Id == i );
+ // skip PIs and the constant
+ if ( Abc_ObjFaninNum(pObj) == 0 )
+ continue;
+ // create the edge
+ pFaninNew = Abc_NodeSeqToLogic( pNtkNew, Abc_ObjFanin0(pObj), Seq_NodeGetRing(pObj,0), Seq_ObjFaninL0(pObj) );
+ Abc_ObjAddFanin( pObj->pCopy, pFaninNew );
+ if ( Abc_ObjFaninNum(pObj) == 1 )
+ {
+ // create the complemented edge
+ if ( Abc_ObjFaninC0(pObj) )
+ Abc_ObjSetFaninC( pObj->pCopy, 0 );
+ continue;
+ }
+ // create the edge
+ pFaninNew = Abc_NodeSeqToLogic( pNtkNew, Abc_ObjFanin1(pObj), Seq_NodeGetRing(pObj,1), Seq_ObjFaninL1(pObj) );
+ Abc_ObjAddFanin( pObj->pCopy, pFaninNew );
+ // the complemented edges are subsumed by the node function
+ }
+ // add the latches and their names
+ Abc_NtkAddDummyBoxNames( pNtkNew );
+ Abc_NtkOrderCisCos( pNtkNew );
+ // fix the problem with complemented and duplicated CO edges
+ Abc_NtkLogicMakeSimpleCos( pNtkNew, 0 );
+ if ( !Abc_NtkCheck( pNtkNew ) )
+ fprintf( stdout, "Abc_NtkSeqToLogicSop(): Network check has failed.\n" );
+ return pNtkNew;
+}
+
+
+/**Function*************************************************************
+
+ Synopsis [Creates latches on one edge.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Abc_Obj_t * Abc_NodeSeqToLogic( Abc_Ntk_t * pNtkNew, Abc_Obj_t * pFanin, Seq_Lat_t * pRing, int nLatches )
+{
+ Abc_Obj_t * pLatch;
+ if ( nLatches == 0 )
+ {
+ assert( pFanin->pCopy );
+ return pFanin->pCopy;
+ }
+ pFanin = Abc_NodeSeqToLogic( pNtkNew, pFanin, Seq_LatNext(pRing), nLatches - 1 );
+ pLatch = Abc_NtkCreateLatch( pNtkNew );
+ pLatch->pData = (void *)Seq_LatInit( pRing );
+ Abc_ObjAddFanin( pLatch, pFanin );
+ return pLatch;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Makes sure that every node in the table is in the network and vice versa.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+bool Abc_NtkSeqCheck( Abc_Ntk_t * pNtk )
+{
+ Abc_Obj_t * pObj;
+ int i, nFanins;
+ Abc_NtkForEachNode( pNtk, pObj, i )
+ {
+ nFanins = Abc_ObjFaninNum(pObj);
+ if ( nFanins == 0 )
+ {
+ if ( pObj != Abc_AigConst1(pNtk) )
+ {
+ printf( "Abc_SeqCheck: The AIG has non-standard constant nodes.\n" );
+ return 0;
+ }
+ continue;
+ }
+ if ( nFanins == 1 )
+ {
+ printf( "Abc_SeqCheck: The AIG has single input nodes.\n" );
+ return 0;
+ }
+ if ( nFanins > 2 )
+ {
+ printf( "Abc_SeqCheck: The AIG has non-standard nodes.\n" );
+ return 0;
+ }
+ }
+ // check the correctness of the internal representation of the initial states
+ Abc_NtkForEachObj( pNtk, pObj, i )
+ {
+ nFanins = Abc_ObjFaninNum(pObj);
+ if ( nFanins == 0 )
+ continue;
+ if ( nFanins == 1 )
+ {
+ if ( Seq_NodeCountLats(pObj, 0) != Seq_ObjFaninL0(pObj) )
+ {
+ printf( "Abc_SeqCheck: Node %d has mismatch in the number of latches.\n", Abc_ObjName(pObj) );
+ return 0;
+ }
+ }
+ // look at both inputs
+ if ( Seq_NodeCountLats(pObj, 0) != Seq_ObjFaninL0(pObj) )
+ {
+ printf( "Abc_SeqCheck: The first fanin of node %d has mismatch in the number of latches.\n", Abc_ObjName(pObj) );
+ return 0;
+ }
+ if ( Seq_NodeCountLats(pObj, 1) != Seq_ObjFaninL1(pObj) )
+ {
+ printf( "Abc_SeqCheck: The second fanin of node %d has mismatch in the number of latches.\n", Abc_ObjName(pObj) );
+ return 0;
+ }
+ }
+ return 1;
+}
+
+////////////////////////////////////////////////////////////////////////
+/// END OF FILE ///
+////////////////////////////////////////////////////////////////////////
+
+
diff --git a/src/base/seq/seqFpgaCore.c b/src/base/seq/seqFpgaCore.c
new file mode 100644
index 00000000..b106ded2
--- /dev/null
+++ b/src/base/seq/seqFpgaCore.c
@@ -0,0 +1,643 @@
+/**CFile****************************************************************
+
+ FileName [seqFpgaCore.c]
+
+ SystemName [ABC: Logic synthesis and verification system.]
+
+ PackageName [Construction and manipulation of sequential AIGs.]
+
+ Synopsis [The core of FPGA mapping/retiming package.]
+
+ Author [Alan Mishchenko]
+
+ Affiliation [UC Berkeley]
+
+ Date [Ver. 1.0. Started - June 20, 2005.]
+
+ Revision [$Id: seqFpgaCore.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "seqInt.h"
+
+////////////////////////////////////////////////////////////////////////
+/// DECLARATIONS ///
+////////////////////////////////////////////////////////////////////////
+
+static Abc_Ntk_t * Seq_NtkFpgaDup( Abc_Ntk_t * pNtk );
+static int Seq_NtkFpgaInitCompatible( Abc_Ntk_t * pNtk, int fVerbose );
+static Abc_Ntk_t * Seq_NtkSeqFpgaMapped( Abc_Ntk_t * pNtkNew );
+static int Seq_FpgaMappingCount( Abc_Ntk_t * pNtk );
+static int Seq_FpgaMappingCount_rec( Abc_Ntk_t * pNtk, unsigned SeqEdge, Vec_Ptr_t * vLeaves );
+static Abc_Obj_t * Seq_FpgaMappingBuild_rec( Abc_Ntk_t * pNtkNew, Abc_Ntk_t * pNtk, unsigned SeqEdge, int fTop, int LagCut, Vec_Ptr_t * vLeaves );
+static DdNode * Seq_FpgaMappingBdd_rec( DdManager * dd, Abc_Ntk_t * pNtk, unsigned SeqEdge, Vec_Ptr_t * vLeaves );
+static void Seq_FpgaMappingEdges_rec( Abc_Ntk_t * pNtk, unsigned SeqEdge, Abc_Obj_t * pPrev, Vec_Ptr_t * vLeaves, Vec_Vec_t * vMapEdges );
+static void Seq_FpgaMappingConnect_rec( Abc_Ntk_t * pNtk, unsigned SeqEdge, Abc_Obj_t * pPrev, int Edge, Abc_Obj_t * pRoot, Vec_Ptr_t * vLeaves );
+static DdNode * Seq_FpgaMappingConnectBdd_rec( Abc_Ntk_t * pNtk, unsigned SeqEdge, Abc_Obj_t * pPrev, int Edge, Abc_Obj_t * pRoot, Vec_Ptr_t * vLeaves );
+
+////////////////////////////////////////////////////////////////////////
+/// FUNCTION DEFINITIONS ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+ Synopsis [Performs FPGA mapping and retiming.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Abc_Ntk_t * Seq_NtkFpgaMapRetime( Abc_Ntk_t * pNtk, int nMaxIters, int fVerbose )
+{
+ Abc_Seq_t * p = pNtk->pManFunc;
+ Abc_Ntk_t * pNtkNew;
+ Abc_Ntk_t * pNtkMap;
+ int RetValue;
+
+ // get the LUT library
+ p->nVarsMax = Fpga_LutLibReadVarMax( Abc_FrameReadLibLut() );
+ p->nMaxIters = nMaxIters;
+
+ // find the best mapping and retiming for all nodes (p->vLValues, p->vBestCuts, p->vLags)
+ if ( !Seq_FpgaMappingDelays( pNtk, fVerbose ) )
+ return NULL;
+ if ( RetValue = Abc_NtkGetChoiceNum(pNtk) )
+ {
+ printf( "The network has %d choices. The resulting network is not derived (this is temporary).\n", RetValue );
+ printf( "The mininum clock period computed is %d.\n", p->FiBestInt );
+ return NULL;
+ }
+
+ // duplicate the nodes contained in multiple cuts
+ pNtkNew = Seq_NtkFpgaDup( pNtk );
+// return pNtkNew;
+
+ // implement the retiming
+ RetValue = Seq_NtkImplementRetiming( pNtkNew, ((Abc_Seq_t *)pNtkNew->pManFunc)->vLags, fVerbose );
+ if ( RetValue == 0 )
+ printf( "Retiming completed but initial state computation has failed.\n" );
+// return pNtkNew;
+
+ // check the compatibility of initial states computed
+ if ( RetValue = Seq_NtkFpgaInitCompatible( pNtkNew, fVerbose ) )
+ printf( "The number of LUTs with incompatible edges = %d.\n", RetValue );
+
+ // create the final mapped network
+ pNtkMap = Seq_NtkSeqFpgaMapped( pNtkNew );
+ Abc_NtkDelete( pNtkNew );
+ if ( RetValue )
+ printf( "The number of LUTs with more than %d inputs = %d.\n",
+ p->nVarsMax, Seq_NtkCountNodesAboveLimit(pNtkMap, p->nVarsMax) );
+ return pNtkMap;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Derives the network by duplicating some of the nodes.]
+
+ Description [Information about mapping is given as mapping nodes (p->vMapAnds)
+ and best cuts for each node (p->vMapCuts).]
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Abc_Ntk_t * Seq_NtkFpgaDup( Abc_Ntk_t * pNtk )
+{
+ Abc_Seq_t * pNew, * p = pNtk->pManFunc;
+ Abc_Ntk_t * pNtkNew;
+ Abc_Obj_t * pObj, * pLeaf;
+ Vec_Ptr_t * vLeaves;
+ unsigned SeqEdge;
+ int i, k, nObjsNew, Lag;
+
+ assert( Abc_NtkIsSeq(pNtk) );
+
+ // start the expanded network
+ pNtkNew = Abc_NtkStartFrom( pNtk, pNtk->ntkType, pNtk->ntkFunc );
+
+ // start the new sequential AIG manager
+ nObjsNew = 1 + Abc_NtkPiNum(pNtk) + Abc_NtkPoNum(pNtk) + Seq_FpgaMappingCount(pNtk);
+ Seq_Resize( pNtkNew->pManFunc, nObjsNew );
+
+ // duplicate the nodes in the mapping
+ Vec_PtrForEachEntry( p->vMapAnds, pObj, i )
+ Abc_NtkDupObj( pNtkNew, pObj, 0 );
+
+ // recursively construct the internals of each node
+ Vec_PtrForEachEntry( p->vMapAnds, pObj, i )
+ {
+ vLeaves = Vec_VecEntry( p->vMapCuts, i );
+ Seq_FpgaMappingBuild_rec( pNtkNew, pNtk, pObj->Id << 8, 1, Seq_NodeGetLag(pObj), vLeaves );
+ }
+ assert( nObjsNew == pNtkNew->nObjs );
+
+ // set the POs
+ Abc_NtkFinalize( pNtk, pNtkNew );
+ // duplicate the latches on the PO edges
+ Abc_NtkForEachPo( pNtk, pObj, i )
+ Seq_NodeDupLats( pObj->pCopy, pObj, 0 );
+
+ // transfer the mapping info to the new manager
+ Vec_PtrForEachEntry( p->vMapAnds, pObj, i )
+ {
+ // get the leaves of the cut
+ vLeaves = Vec_VecEntry( p->vMapCuts, i );
+ // convert the leaf nodes
+ Vec_PtrForEachEntry( vLeaves, pLeaf, k )
+ {
+ SeqEdge = (unsigned)pLeaf;
+ pLeaf = Abc_NtkObj( pNtk, SeqEdge >> 8 );
+ Lag = (SeqEdge & 255) + Seq_NodeGetLag(pObj) - Seq_NodeGetLag(pLeaf);
+ assert( Lag >= 0 );
+ // translate the old leaf into the leaf in the new network
+ Vec_PtrWriteEntry( vLeaves, k, (void *)((pLeaf->pCopy->Id << 8) | Lag) );
+// printf( "%d -> %d\n", pLeaf->Id, pLeaf->pCopy->Id );
+ }
+ // convert the root node
+ Vec_PtrWriteEntry( p->vMapAnds, i, pObj->pCopy );
+ }
+ pNew = pNtkNew->pManFunc;
+ pNew->nVarsMax = p->nVarsMax;
+ pNew->vMapAnds = p->vMapAnds; p->vMapAnds = NULL;
+ pNew->vMapCuts = p->vMapCuts; p->vMapCuts = NULL;
+
+ if ( !Abc_NtkCheck( pNtkNew ) )
+ fprintf( stdout, "Seq_NtkFpgaDup(): Network check has failed.\n" );
+ return pNtkNew;
+}
+
+
+/**Function*************************************************************
+
+ Synopsis [Checks if the initial states are compatible.]
+
+ Description [Checks of all the initial states on the fanins edges
+ of the cut have compatible number of latches and initial states.
+ If this is not true, then the mapped network with the does not have initial
+ state. Returns the number of LUTs with incompatible edges.]
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Seq_NtkFpgaInitCompatible( Abc_Ntk_t * pNtk, int fVerbose )
+{
+ Abc_Seq_t * p = pNtk->pManFunc;
+ Abc_Obj_t * pAnd, * pLeaf, * pFanout0, * pFanout1;
+ Vec_Vec_t * vTotalEdges;
+ Vec_Ptr_t * vLeaves, * vEdges;
+ int i, k, m, Edge0, Edge1, nLatchAfter, nLatches1, nLatches2;
+ unsigned SeqEdge;
+ int CountBad = 0, CountAll = 0;
+
+ vTotalEdges = Vec_VecStart( p->nVarsMax );
+ // go through all the nodes (cuts) used in the mapping
+ Vec_PtrForEachEntry( p->vMapAnds, pAnd, i )
+ {
+// printf( "*** Node %d.\n", pAnd->Id );
+
+ // get the cut of this gate
+ vLeaves = Vec_VecEntry( p->vMapCuts, i );
+
+ // get the edges pointing to the leaves
+ Vec_VecClear( vTotalEdges );
+ Seq_FpgaMappingEdges_rec( pNtk, pAnd->Id << 8, NULL, vLeaves, vTotalEdges );
+
+ // for each leaf, consider its edges
+ Vec_PtrForEachEntry( vLeaves, pLeaf, k )
+ {
+ SeqEdge = (unsigned)pLeaf;
+ pLeaf = Abc_NtkObj( pNtk, SeqEdge >> 8 );
+ nLatchAfter = SeqEdge & 255;
+ if ( nLatchAfter == 0 )
+ continue;
+
+ // go through the edges
+ vEdges = Vec_VecEntry( vTotalEdges, k );
+ pFanout0 = NULL;
+ Vec_PtrForEachEntry( vEdges, pFanout1, m )
+ {
+ Edge1 = Abc_ObjIsComplement(pFanout1);
+ pFanout1 = Abc_ObjRegular(pFanout1);
+//printf( "Fanin = %d. Fanout = %d.\n", pLeaf->Id, pFanout1->Id );
+
+ // make sure this is the same fanin
+ if ( Edge1 )
+ assert( pLeaf == Abc_ObjFanin1(pFanout1) );
+ else
+ assert( pLeaf == Abc_ObjFanin0(pFanout1) );
+
+ // save the first one
+ if ( pFanout0 == NULL )
+ {
+ pFanout0 = pFanout1;
+ Edge0 = Edge1;
+ continue;
+ }
+ // compare the rings
+ // if they have different number of latches, this is the bug
+ nLatches1 = Seq_NodeCountLats(pFanout0, Edge0);
+ nLatches2 = Seq_NodeCountLats(pFanout1, Edge1);
+ assert( nLatches1 == nLatches2 );
+ assert( nLatches1 == nLatchAfter );
+ assert( nLatches1 > 0 );
+
+ // if they have different initial states, this is the problem
+ if ( !Seq_NodeCompareLats(pFanout0, Edge0, pFanout1, Edge1) )
+ {
+ CountBad++;
+ break;
+ }
+ CountAll++;
+ }
+ }
+ }
+ if ( fVerbose )
+ printf( "The number of pairs of edges checked = %d.\n", CountAll );
+ Vec_VecFree( vTotalEdges );
+ return CountBad;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Derives the final mapped network.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Abc_Ntk_t * Seq_NtkSeqFpgaMapped( Abc_Ntk_t * pNtk )
+{
+ Abc_Seq_t * p = pNtk->pManFunc;
+ Abc_Ntk_t * pNtkMap;
+ Vec_Ptr_t * vLeaves;
+ Abc_Obj_t * pObj, * pFaninNew;
+ Seq_Lat_t * pRing;
+ int i;
+
+ assert( Abc_NtkIsSeq(pNtk) );
+
+ // start the network
+ pNtkMap = Abc_NtkStartFrom( pNtk, ABC_NTK_LOGIC, ABC_FUNC_BDD );
+
+ // duplicate the nodes used in the mapping
+ Vec_PtrForEachEntry( p->vMapAnds, pObj, i )
+ pObj->pCopy = Abc_NtkCreateNode( pNtkMap );
+
+ // create and share the latches
+ Seq_NtkShareLatchesMapping( pNtkMap, pNtk, p->vMapAnds, 1 );
+
+ // connect the nodes
+ Vec_PtrForEachEntry( p->vMapAnds, pObj, i )
+ {
+ // get the leaves of this gate
+ vLeaves = Vec_VecEntry( p->vMapCuts, i );
+ // get the BDD of the node
+ pObj->pCopy->pData = Seq_FpgaMappingConnectBdd_rec( pNtk, pObj->Id << 8, NULL, -1, pObj, vLeaves );
+ Cudd_Ref( pObj->pCopy->pData );
+ // complement the BDD of the cut if it came from the opposite polarity choice cut
+// if ( Vec_StrEntry(p->vPhase, i) )
+// pObj->pCopy->pData = Cudd_Not( pObj->pCopy->pData );
+ }
+
+ // set the POs
+ Abc_NtkForEachPo( pNtk, pObj, i )
+ {
+ if ( pRing = Seq_NodeGetRing(pObj,0) )
+ pFaninNew = pRing->pLatch;
+ else
+ pFaninNew = Abc_ObjFanin0(pObj)->pCopy;
+ pFaninNew = Abc_ObjNotCond( pFaninNew, Abc_ObjFaninC0(pObj) );
+ Abc_ObjAddFanin( pObj->pCopy, pFaninNew );
+ }
+
+ // add the latches and their names
+ Abc_NtkAddDummyBoxNames( pNtkMap );
+ Abc_NtkOrderCisCos( pNtkMap );
+ // fix the problem with complemented and duplicated CO edges
+ Abc_NtkLogicMakeSimpleCos( pNtkMap, 1 );
+ // make the network minimum base
+ Abc_NtkMinimumBase( pNtkMap );
+ if ( !Abc_NtkCheck( pNtkMap ) )
+ fprintf( stdout, "Seq_NtkSeqFpgaMapped(): Network check has failed.\n" );
+ return pNtkMap;
+}
+
+
+/**Function*************************************************************
+
+ Synopsis [Counts the number of nodes in the bag.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Seq_FpgaMappingCount( Abc_Ntk_t * pNtk )
+{
+ Abc_Seq_t * p = pNtk->pManFunc;
+ Vec_Ptr_t * vLeaves;
+ Abc_Obj_t * pAnd;
+ int i, Counter = 0;
+ Vec_PtrForEachEntry( p->vMapAnds, pAnd, i )
+ {
+ vLeaves = Vec_VecEntry( p->vMapCuts, i );
+ Counter += Seq_FpgaMappingCount_rec( pNtk, pAnd->Id << 8, vLeaves );
+ }
+ return Counter;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Counts the number of nodes in the bag.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Seq_FpgaMappingCount_rec( Abc_Ntk_t * pNtk, unsigned SeqEdge, Vec_Ptr_t * vLeaves )
+{
+ Abc_Obj_t * pObj, * pLeaf;
+ unsigned SeqEdge0, SeqEdge1;
+ int Lag, i;
+ // get the object and the lag
+ pObj = Abc_NtkObj( pNtk, SeqEdge >> 8 );
+ Lag = SeqEdge & 255;
+ // if the node is the fanin of the cut, return
+ Vec_PtrForEachEntry( vLeaves, pLeaf, i )
+ if ( SeqEdge == (unsigned)pLeaf )
+ return 0;
+ // continue unfolding
+ assert( Abc_AigNodeIsAnd(pObj) );
+ // get new sequential edges
+ assert( Lag + Seq_ObjFaninL0(pObj) < 255 );
+ assert( Lag + Seq_ObjFaninL1(pObj) < 255 );
+ SeqEdge0 = (Abc_ObjFanin0(pObj)->Id << 8) + Lag + Seq_ObjFaninL0(pObj);
+ SeqEdge1 = (Abc_ObjFanin1(pObj)->Id << 8) + Lag + Seq_ObjFaninL1(pObj);
+ // call for the children
+ return 1 + Seq_FpgaMappingCount_rec( pNtk, SeqEdge0, vLeaves ) +
+ Seq_FpgaMappingCount_rec( pNtk, SeqEdge1, vLeaves );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Collects the edges pointing to the leaves of the cut.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Abc_Obj_t * Seq_FpgaMappingBuild_rec( Abc_Ntk_t * pNtkNew, Abc_Ntk_t * pNtk, unsigned SeqEdge, int fTop, int LagCut, Vec_Ptr_t * vLeaves )
+{
+ Abc_Obj_t * pObj, * pObjNew, * pLeaf, * pFaninNew0, * pFaninNew1;
+ unsigned SeqEdge0, SeqEdge1;
+ int Lag, i;
+ // get the object and the lag
+ pObj = Abc_NtkObj( pNtk, SeqEdge >> 8 );
+ Lag = SeqEdge & 255;
+ // if the node is the fanin of the cut, return
+ Vec_PtrForEachEntry( vLeaves, pLeaf, i )
+ if ( SeqEdge == (unsigned)pLeaf )
+ return pObj->pCopy;
+ // continue unfolding
+ assert( Abc_AigNodeIsAnd(pObj) );
+ // get new sequential edges
+ assert( Lag + Seq_ObjFaninL0(pObj) < 255 );
+ assert( Lag + Seq_ObjFaninL1(pObj) < 255 );
+ SeqEdge0 = (Abc_ObjFanin0(pObj)->Id << 8) + Lag + Seq_ObjFaninL0(pObj);
+ SeqEdge1 = (Abc_ObjFanin1(pObj)->Id << 8) + Lag + Seq_ObjFaninL1(pObj);
+ // call for the children
+ pObjNew = fTop? pObj->pCopy : Abc_NtkCreateNode( pNtkNew );
+ // solve subproblems
+ pFaninNew0 = Seq_FpgaMappingBuild_rec( pNtkNew, pNtk, SeqEdge0, 0, LagCut, vLeaves );
+ pFaninNew1 = Seq_FpgaMappingBuild_rec( pNtkNew, pNtk, SeqEdge1, 0, LagCut, vLeaves );
+ // add the fanins to the node
+ Abc_ObjAddFanin( pObjNew, Abc_ObjNotCond( pFaninNew0, Abc_ObjFaninC0(pObj) ) );
+ Abc_ObjAddFanin( pObjNew, Abc_ObjNotCond( pFaninNew1, Abc_ObjFaninC1(pObj) ) );
+ Seq_NodeDupLats( pObjNew, pObj, 0 );
+ Seq_NodeDupLats( pObjNew, pObj, 1 );
+ // set the lag of the new node equal to the internal lag plus mapping/retiming lag
+ Seq_NodeSetLag( pObjNew, (char)(Lag + LagCut) );
+// Seq_NodeSetLag( pObjNew, (char)(Lag) );
+ return pObjNew;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Derives the BDD of the selected cut.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+DdNode * Seq_FpgaMappingBdd_rec( DdManager * dd, Abc_Ntk_t * pNtk, unsigned SeqEdge, Vec_Ptr_t * vLeaves )
+{
+ Abc_Obj_t * pObj, * pLeaf;
+ DdNode * bFunc0, * bFunc1, * bFunc;
+ unsigned SeqEdge0, SeqEdge1;
+ int Lag, i;
+ // get the object and the lag
+ pObj = Abc_NtkObj( pNtk, SeqEdge >> 8 );
+ Lag = SeqEdge & 255;
+ // if the node is the fanin of the cut, return
+ Vec_PtrForEachEntry( vLeaves, pLeaf, i )
+ if ( SeqEdge == (unsigned)pLeaf )
+ return Cudd_bddIthVar( dd, i );
+ // continue unfolding
+ assert( Abc_AigNodeIsAnd(pObj) );
+ // get new sequential edges
+ assert( Lag + Seq_ObjFaninL0(pObj) < 255 );
+ assert( Lag + Seq_ObjFaninL1(pObj) < 255 );
+ SeqEdge0 = (Abc_ObjFanin0(pObj)->Id << 8) + Lag + Seq_ObjFaninL0(pObj);
+ SeqEdge1 = (Abc_ObjFanin1(pObj)->Id << 8) + Lag + Seq_ObjFaninL1(pObj);
+ // call for the children
+ bFunc0 = Seq_FpgaMappingBdd_rec( dd, pNtk, SeqEdge0, vLeaves ); Cudd_Ref( bFunc0 );
+ bFunc1 = Seq_FpgaMappingBdd_rec( dd, pNtk, SeqEdge1, vLeaves ); Cudd_Ref( bFunc1 );
+ bFunc0 = Cudd_NotCond( bFunc0, Abc_ObjFaninC0(pObj) );
+ bFunc1 = Cudd_NotCond( bFunc1, Abc_ObjFaninC1(pObj) );
+ // get the BDD of the node
+ bFunc = Cudd_bddAnd( dd, bFunc0, bFunc1 ); Cudd_Ref( bFunc );
+ Cudd_RecursiveDeref( dd, bFunc0 );
+ Cudd_RecursiveDeref( dd, bFunc1 );
+ // return the BDD
+ Cudd_Deref( bFunc );
+ return bFunc;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Collects the edges pointing to the leaves of the cut.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Seq_FpgaMappingEdges_rec( Abc_Ntk_t * pNtk, unsigned SeqEdge, Abc_Obj_t * pPrev, Vec_Ptr_t * vLeaves, Vec_Vec_t * vMapEdges )
+{
+ Abc_Obj_t * pObj, * pLeaf;
+ unsigned SeqEdge0, SeqEdge1;
+ int Lag, i;
+ // get the object and the lag
+ pObj = Abc_NtkObj( pNtk, SeqEdge >> 8 );
+ Lag = SeqEdge & 255;
+ // if the node is the fanin of the cut, return
+ Vec_PtrForEachEntry( vLeaves, pLeaf, i )
+ {
+ if ( SeqEdge == (unsigned)pLeaf )
+ {
+ assert( pPrev != NULL );
+ Vec_VecPush( vMapEdges, i, pPrev );
+ return;
+ }
+ }
+ // continue unfolding
+ assert( Abc_AigNodeIsAnd(pObj) );
+ // get new sequential edges
+ assert( Lag + Seq_ObjFaninL0(pObj) < 255 );
+ assert( Lag + Seq_ObjFaninL1(pObj) < 255 );
+ SeqEdge0 = (Abc_ObjFanin0(pObj)->Id << 8) + Lag + Seq_ObjFaninL0(pObj);
+ SeqEdge1 = (Abc_ObjFanin1(pObj)->Id << 8) + Lag + Seq_ObjFaninL1(pObj);
+ // call for the children
+ Seq_FpgaMappingEdges_rec( pNtk, SeqEdge0, pObj , vLeaves, vMapEdges );
+ Seq_FpgaMappingEdges_rec( pNtk, SeqEdge1, Abc_ObjNot(pObj), vLeaves, vMapEdges );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Collects the edges pointing to the leaves of the cut.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Seq_FpgaMappingConnect_rec( Abc_Ntk_t * pNtk, unsigned SeqEdge, Abc_Obj_t * pPrev, int Edge, Abc_Obj_t * pRoot, Vec_Ptr_t * vLeaves )
+{
+ Seq_Lat_t * pRing;
+ Abc_Obj_t * pObj, * pLeaf, * pFanin, * pFaninNew;
+ unsigned SeqEdge0, SeqEdge1;
+ int Lag, i, k;
+ // get the object and the lag
+ pObj = Abc_NtkObj( pNtk, SeqEdge >> 8 );
+ Lag = SeqEdge & 255;
+ // if the node is the fanin of the cut, add the connection and return
+ Vec_PtrForEachEntry( vLeaves, pLeaf, i )
+ {
+ if ( SeqEdge == (unsigned)pLeaf )
+ {
+ assert( pPrev != NULL );
+ if ( pRing = Seq_NodeGetRing(pPrev,Edge) )
+ pFaninNew = pRing->pLatch;
+ else
+ pFaninNew = Abc_ObjFanin(pPrev,Edge)->pCopy;
+ // check if the root already has this fanin
+ Abc_ObjForEachFanin( pRoot, pFanin, k )
+ if ( pFanin == pFaninNew )
+ return;
+ Abc_ObjAddFanin( pRoot->pCopy, pFaninNew );
+ return;
+ }
+ }
+ // continue unfolding
+ assert( Abc_AigNodeIsAnd(pObj) );
+ // get new sequential edges
+ assert( Lag + Seq_ObjFaninL0(pObj) < 255 );
+ assert( Lag + Seq_ObjFaninL1(pObj) < 255 );
+ SeqEdge0 = (Abc_ObjFanin0(pObj)->Id << 8) + Lag + Seq_ObjFaninL0(pObj);
+ SeqEdge1 = (Abc_ObjFanin1(pObj)->Id << 8) + Lag + Seq_ObjFaninL1(pObj);
+ // call for the children
+ Seq_FpgaMappingConnect_rec( pNtk, SeqEdge0, pObj, 0, pRoot, vLeaves );
+ Seq_FpgaMappingConnect_rec( pNtk, SeqEdge1, pObj, 1, pRoot, vLeaves );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Collects the edges pointing to the leaves of the cut.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+DdNode * Seq_FpgaMappingConnectBdd_rec( Abc_Ntk_t * pNtk, unsigned SeqEdge, Abc_Obj_t * pPrev, int Edge, Abc_Obj_t * pRoot, Vec_Ptr_t * vLeaves )
+{
+ Seq_Lat_t * pRing;
+ Abc_Obj_t * pObj, * pLeaf, * pFanin, * pFaninNew;
+ unsigned SeqEdge0, SeqEdge1;
+ DdManager * dd = pRoot->pCopy->pNtk->pManFunc;
+ DdNode * bFunc, * bFunc0, * bFunc1;
+ int Lag, i, k;
+ // get the object and the lag
+ pObj = Abc_NtkObj( pNtk, SeqEdge >> 8 );
+ Lag = SeqEdge & 255;
+ // if the node is the fanin of the cut, add the connection and return
+ Vec_PtrForEachEntry( vLeaves, pLeaf, i )
+ {
+ if ( SeqEdge == (unsigned)pLeaf )
+ {
+ assert( pPrev != NULL );
+ if ( pRing = Seq_NodeGetRing(pPrev,Edge) )
+ pFaninNew = pRing->pLatch;
+ else
+ pFaninNew = Abc_ObjFanin(pPrev,Edge)->pCopy;
+ // check if the root already has this fanin
+ Abc_ObjForEachFanin( pRoot->pCopy, pFanin, k )
+ if ( pFanin == pFaninNew )
+ return Cudd_bddIthVar( dd, k );
+ Abc_ObjAddFanin( pRoot->pCopy, pFaninNew );
+ return Cudd_bddIthVar( dd, k );
+ }
+ }
+ // continue unfolding
+ assert( Abc_AigNodeIsAnd(pObj) );
+ // get new sequential edges
+ assert( Lag + Seq_ObjFaninL0(pObj) < 255 );
+ assert( Lag + Seq_ObjFaninL1(pObj) < 255 );
+ SeqEdge0 = (Abc_ObjFanin0(pObj)->Id << 8) + Lag + Seq_ObjFaninL0(pObj);
+ SeqEdge1 = (Abc_ObjFanin1(pObj)->Id << 8) + Lag + Seq_ObjFaninL1(pObj);
+ // call for the children
+ bFunc0 = Seq_FpgaMappingConnectBdd_rec( pNtk, SeqEdge0, pObj, 0, pRoot, vLeaves ); Cudd_Ref( bFunc0 );
+ bFunc1 = Seq_FpgaMappingConnectBdd_rec( pNtk, SeqEdge1, pObj, 1, pRoot, vLeaves ); Cudd_Ref( bFunc1 );
+ bFunc0 = Cudd_NotCond( bFunc0, Abc_ObjFaninC0(pObj) );
+ bFunc1 = Cudd_NotCond( bFunc1, Abc_ObjFaninC1(pObj) );
+ // get the BDD of the node
+ bFunc = Cudd_bddAnd( dd, bFunc0, bFunc1 ); Cudd_Ref( bFunc );
+ Cudd_RecursiveDeref( dd, bFunc0 );
+ Cudd_RecursiveDeref( dd, bFunc1 );
+ // return the BDD
+ Cudd_Deref( bFunc );
+ return bFunc;
+}
+
+////////////////////////////////////////////////////////////////////////
+/// END OF FILE ///
+////////////////////////////////////////////////////////////////////////
+
+
diff --git a/src/base/seq/seqFpgaIter.c b/src/base/seq/seqFpgaIter.c
new file mode 100644
index 00000000..a300b362
--- /dev/null
+++ b/src/base/seq/seqFpgaIter.c
@@ -0,0 +1,270 @@
+/**CFile****************************************************************
+
+ FileName [seqFpgaIter.c]
+
+ SystemName [ABC: Logic synthesis and verification system.]
+
+ PackageName [Construction and manipulation of sequential AIGs.]
+
+ Synopsis [Iterative delay computation in FPGA mapping/retiming package.]
+
+ Author [Alan Mishchenko]
+
+ Affiliation [UC Berkeley]
+
+ Date [Ver. 1.0. Started - June 20, 2005.]
+
+ Revision [$Id: seqFpgaIter.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "seqInt.h"
+#include "main.h"
+#include "fpga.h"
+
+////////////////////////////////////////////////////////////////////////
+/// DECLARATIONS ///
+////////////////////////////////////////////////////////////////////////
+
+static void Seq_FpgaMappingCollectNode_rec( Abc_Obj_t * pAnd, Vec_Ptr_t * vMapping, Vec_Vec_t * vMapCuts );
+static Cut_Cut_t * Seq_FpgaMappingSelectCut( Abc_Obj_t * pAnd );
+
+extern Cut_Man_t * Abc_NtkSeqCuts( Abc_Ntk_t * pNtk, Cut_Params_t * pParams );
+extern Cut_Man_t * Abc_NtkCuts( Abc_Ntk_t * pNtk, Cut_Params_t * pParams );
+
+////////////////////////////////////////////////////////////////////////
+/// FUNCTION DEFINITIONS ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+ Synopsis [Computes the retiming lags for FPGA mapping.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Seq_FpgaMappingDelays( Abc_Ntk_t * pNtk, int fVerbose )
+{
+ Abc_Seq_t * p = pNtk->pManFunc;
+ Cut_Params_t Params, * pParams = &Params;
+ Abc_Obj_t * pObj;
+ int i, clk;
+
+ // set defaults for cut computation
+ memset( pParams, 0, sizeof(Cut_Params_t) );
+ pParams->nVarsMax = p->nVarsMax; // the max cut size ("k" of the k-feasible cuts)
+ pParams->nKeepMax = 1000; // the max number of cuts kept at a node
+ pParams->fTruth = 0; // compute truth tables
+ pParams->fFilter = 1; // filter dominated cuts
+ pParams->fSeq = 1; // compute sequential cuts
+ pParams->fVerbose = fVerbose; // the verbosiness flag
+
+ // compute the cuts
+clk = clock();
+ p->pCutMan = Abc_NtkSeqCuts( pNtk, pParams );
+// pParams->fSeq = 0;
+// p->pCutMan = Abc_NtkCuts( pNtk, pParams );
+p->timeCuts = clock() - clk;
+
+ if ( fVerbose )
+ Cut_ManPrintStats( p->pCutMan );
+
+ // compute area flows
+// Seq_MapComputeAreaFlows( pNtk, fVerbose );
+
+ // compute the delays
+clk = clock();
+ if ( !Seq_AigRetimeDelayLags( pNtk, fVerbose ) )
+ return 0;
+ p->timeDelay = clock() - clk;
+
+ // collect the nodes and cuts used in the mapping
+ p->vMapAnds = Vec_PtrAlloc( 1000 );
+ p->vMapCuts = Vec_VecAlloc( 1000 );
+ Abc_NtkIncrementTravId( pNtk );
+ Abc_NtkForEachPo( pNtk, pObj, i )
+ Seq_FpgaMappingCollectNode_rec( Abc_ObjFanin0(pObj), p->vMapAnds, p->vMapCuts );
+
+ if ( fVerbose )
+ printf( "The number of LUTs = %d.\n", Vec_PtrSize(p->vMapAnds) );
+
+ // remove the cuts
+ Cut_ManStop( p->pCutMan );
+ p->pCutMan = NULL;
+ return 1;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Derives the parameters of the best mapping/retiming for one node.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Seq_FpgaMappingCollectNode_rec( Abc_Obj_t * pAnd, Vec_Ptr_t * vMapping, Vec_Vec_t * vMapCuts )
+{
+ Abc_Obj_t * pFanin;
+ Cut_Cut_t * pCutBest;
+ int k;
+
+ // skip if this is a non-PI node
+ if ( !Abc_AigNodeIsAnd(pAnd) )
+ return;
+ // skip a visited node
+ if ( Abc_NodeIsTravIdCurrent(pAnd) )
+ return;
+ Abc_NodeSetTravIdCurrent(pAnd);
+
+ // visit the fanins of the node
+ pCutBest = Seq_FpgaMappingSelectCut( pAnd );
+ for ( k = 0; k < (int)pCutBest->nLeaves; k++ )
+ {
+ pFanin = Abc_NtkObj( pAnd->pNtk, pCutBest->pLeaves[k] >> 8 );
+ Seq_FpgaMappingCollectNode_rec( pFanin, vMapping, vMapCuts );
+ }
+
+ // add this node
+ Vec_PtrPush( vMapping, pAnd );
+ for ( k = 0; k < (int)pCutBest->nLeaves; k++ )
+ Vec_VecPush( vMapCuts, Vec_PtrSize(vMapping)-1, (void *)pCutBest->pLeaves[k] );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Selects the best cut to represent the node in the mapping.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Cut_Cut_t * Seq_FpgaMappingSelectCut( Abc_Obj_t * pAnd )
+{
+ Abc_Obj_t * pFanin;
+ Cut_Cut_t * pCut, * pCutBest, * pList;
+ float CostCur, CostMin = ABC_INFINITY;
+ int ArrivalCut, ArrivalMin, i;
+ // get the arrival time of the best non-trivial cut
+ ArrivalMin = Seq_NodeGetLValue( pAnd );
+ // iterate through the cuts and select the one with the minimum cost
+ pList = Abc_NodeReadCuts( Seq_NodeCutMan(pAnd), pAnd );
+ CostMin = ABC_INFINITY;
+ pCutBest = NULL;
+ for ( pCut = pList->pNext; pCut; pCut = pCut->pNext )
+ {
+ ArrivalCut = *((int *)&pCut->uSign);
+// assert( ArrivalCut >= ArrivalMin );
+ if ( ArrivalCut > ArrivalMin )
+ continue;
+ CostCur = 0.0;
+ for ( i = 0; i < (int)pCut->nLeaves; i++ )
+ {
+ pFanin = Abc_NtkObj( pAnd->pNtk, pCut->pLeaves[i] >> 8 );
+ if ( Abc_ObjIsPi(pFanin) )
+ continue;
+ if ( Abc_NodeIsTravIdCurrent(pFanin) )
+ continue;
+ CostCur += (float)(1.0 / Abc_ObjFanoutNum(pFanin));
+// CostCur += Seq_NodeGetFlow( pFanin );
+ }
+ if ( CostMin > CostCur )
+ {
+ CostMin = CostCur;
+ pCutBest = pCut;
+ }
+ }
+ assert( pCutBest != NULL );
+ return pCutBest;
+}
+
+
+/**Function*************************************************************
+
+ Synopsis [Computes the l-value of the cut.]
+
+ Description [The node should be internal.]
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+static inline int Seq_FpgaCutUpdateLValue( Cut_Cut_t * pCut, Abc_Obj_t * pObj, int Fi )
+{
+ Abc_Obj_t * pFanin;
+ int i, lValueMax, lValueCur;
+ assert( Abc_AigNodeIsAnd(pObj) );
+ lValueMax = -ABC_INFINITY;
+ for ( i = 0; i < (int)pCut->nLeaves; i++ )
+ {
+// lValue0 = Seq_NodeGetLValue(Abc_ObjFanin0(pObj)) - Fi * Abc_ObjFaninL0(pObj);
+ pFanin = Abc_NtkObj(pObj->pNtk, pCut->pLeaves[i] >> 8);
+ lValueCur = Seq_NodeGetLValue(pFanin) - Fi * (pCut->pLeaves[i] & 255);
+ if ( lValueMax < lValueCur )
+ lValueMax = lValueCur;
+ }
+ lValueMax += 1;
+ *((int *)&pCut->uSign) = lValueMax;
+ return lValueMax;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Computes the l-value of the node.]
+
+ Description [The node can be internal or a PO.]
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Seq_FpgaNodeUpdateLValue( Abc_Obj_t * pObj, int Fi )
+{
+ Cut_Cut_t * pCut, * pList;
+ int lValueNew, lValueOld, lValueCut;
+ assert( !Abc_ObjIsPi(pObj) );
+ assert( Abc_ObjFaninNum(pObj) > 0 );
+ if ( Abc_ObjIsPo(pObj) )
+ {
+ lValueNew = Seq_NodeGetLValue(Abc_ObjFanin0(pObj)) - Fi * Seq_ObjFaninL0(pObj);
+ return (lValueNew > Fi)? SEQ_UPDATE_FAIL : SEQ_UPDATE_NO;
+ }
+ // get the arrival time of the best non-trivial cut
+ pList = Abc_NodeReadCuts( Seq_NodeCutMan(pObj), pObj );
+ // skip the choice nodes
+ if ( pList == NULL )
+ return SEQ_UPDATE_NO;
+ lValueNew = ABC_INFINITY;
+ for ( pCut = pList->pNext; pCut; pCut = pCut->pNext )
+ {
+ lValueCut = Seq_FpgaCutUpdateLValue( pCut, pObj, Fi );
+ if ( lValueNew > lValueCut )
+ lValueNew = lValueCut;
+ }
+ // compare the arrival time with the previous arrival time
+ lValueOld = Seq_NodeGetLValue(pObj);
+// if ( lValueNew == lValueOld )
+ if ( lValueNew <= lValueOld )
+ return SEQ_UPDATE_NO;
+ Seq_NodeSetLValue( pObj, lValueNew );
+//printf( "%d -> %d ", lValueOld, lValueNew );
+ return SEQ_UPDATE_YES;
+}
+
+
+////////////////////////////////////////////////////////////////////////
+/// END OF FILE ///
+////////////////////////////////////////////////////////////////////////
+
+
diff --git a/src/base/seq/seqInt.h b/src/base/seq/seqInt.h
new file mode 100644
index 00000000..221efc91
--- /dev/null
+++ b/src/base/seq/seqInt.h
@@ -0,0 +1,256 @@
+/**CFile****************************************************************
+
+ FileName [seqInt.h]
+
+ SystemName [ABC: Logic synthesis and verification system.]
+
+ PackageName [Construction and manipulation of sequential AIGs.]
+
+ Synopsis [Internal declarations.]
+
+ Author [Alan Mishchenko]
+
+ Affiliation [UC Berkeley]
+
+ Date [Ver. 1.0. Started - June 20, 2005.]
+
+ Revision [$Id: seqInt.h,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#ifndef __SEQ_INT_H__
+#define __SEQ_INT_H__
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+////////////////////////////////////////////////////////////////////////
+/// INCLUDES ///
+////////////////////////////////////////////////////////////////////////
+
+#include "abc.h"
+#include "cut.h"
+#include "main.h"
+#include "mio.h"
+#include "mapper.h"
+#include "fpga.h"
+#include "seq.h"
+
+////////////////////////////////////////////////////////////////////////
+/// PARAMETERS ///
+////////////////////////////////////////////////////////////////////////
+
+#define SEQ_FULL_MASK 0xFFFFFFFF
+
+// node status after updating its arrival time
+enum { SEQ_UPDATE_FAIL, SEQ_UPDATE_NO, SEQ_UPDATE_YES };
+
+////////////////////////////////////////////////////////////////////////
+/// BASIC TYPES ///
+////////////////////////////////////////////////////////////////////////
+
+// manager of sequential AIG
+struct Abc_Seq_t_
+{
+ // sequential information
+ Abc_Ntk_t * pNtk; // the network
+ int nSize; // the number of entries in all internal arrays
+ Vec_Int_t * vNums; // the number of latches on each edge in the AIG
+ Vec_Ptr_t * vInits; // the initial states for each edge in the AIG
+ Extra_MmFixed_t * pMmInits; // memory manager for latch structures used to remember init states
+ int fVerbose; // the verbose flag
+ float fEpsilon; // the accuracy for delay computation
+ int fStandCells; // the flag denoting standard cell mapping
+ int nMaxIters; // the max number of iterations
+ int FiBestInt; // the best clock period
+ float FiBestFloat; // the best clock period
+ // K-feasible cuts
+ int nVarsMax; // the max cut size
+ Cut_Man_t * pCutMan; // cut manager
+ Map_SuperLib_t * pSuperLib; // the current supergate library
+ // sequential arrival time computation
+ Vec_Int_t * vAFlows; // the area flow of each cut
+ Vec_Int_t * vLValues; // the arrival times (L-Values of nodes)
+ Vec_Int_t * vLValuesN; // the arrival times (L-Values of nodes)
+ Vec_Str_t * vLags; // the lags of the mapped nodes
+ Vec_Str_t * vLagsN; // the lags of the mapped nodes
+ Vec_Str_t * vUses; // the phase usage
+ // representation of the mapping
+ Vec_Ptr_t * vMapAnds; // nodes visible in the mapping
+ Vec_Vec_t * vMapCuts; // best cuts for each node
+ Vec_Vec_t * vMapDelays; // the delay of each fanin
+ Vec_Vec_t * vMapFanins; // the delay of each fanin
+ // runtime stats
+ int timeCuts; // runtime to compute the cuts
+ int timeDelay; // runtime to compute the L-values
+ int timeRet; // runtime to retime the resulting network
+ int timeNtk; // runtime to create the final network
+
+};
+
+// data structure to store initial state
+typedef struct Seq_Lat_t_ Seq_Lat_t;
+struct Seq_Lat_t_
+{
+ Seq_Lat_t * pNext; // the next Lat in the ring
+ Seq_Lat_t * pPrev; // the prev Lat in the ring
+ Abc_Obj_t * pLatch; // the real latch corresponding to Lat
+};
+
+// representation of latch on the edge
+typedef struct Seq_RetEdge_t_ Seq_RetEdge_t;
+struct Seq_RetEdge_t_ // 1 word
+{
+ unsigned iNode : 24; // the ID of the node
+ unsigned iEdge : 1; // the edge of the node
+ unsigned iLatch : 7; // the latch number counting from the node
+};
+
+// representation of one retiming step
+typedef struct Seq_RetStep_t_ Seq_RetStep_t;
+struct Seq_RetStep_t_ // 1 word
+{
+ unsigned iNode : 24; // the ID of the node
+ unsigned nLatches : 8; // the number of latches to retime
+};
+
+// representation of one mapping match
+typedef struct Seq_Match_t_ Seq_Match_t;
+struct Seq_Match_t_ // 3 words
+{
+ Abc_Obj_t * pAnd; // the AND gate used in the mapping
+ Cut_Cut_t * pCut; // the cut used to map it
+ Map_Super_t * pSuper; // the supergate used to implement the cut
+ unsigned fCompl : 1; // the polarity of the AND gate
+ unsigned fCutInv : 1; // the polarity of the cut
+ unsigned PolUse : 2; // the polarity use of this node
+ unsigned uPhase : 14; // the phase assignment at the boundary
+ unsigned uPhaseR : 14; // the real phase assignment at the boundary
+};
+
+////////////////////////////////////////////////////////////////////////
+/// MACRO DEFINITIONS ///
+////////////////////////////////////////////////////////////////////////
+
+// transforming retedges into ints and back
+static inline int Seq_RetEdge2Int( Seq_RetEdge_t Val ) { return *((int *)&Val); }
+static inline Seq_RetEdge_t Seq_Int2RetEdge( int Num ) { return *((Seq_RetEdge_t *)&Num); }
+// transforming retsteps into ints and back
+static inline int Seq_RetStep2Int( Seq_RetStep_t Val ) { return *((int *)&Val); }
+static inline Seq_RetStep_t Seq_Int2RetStep( int Num ) { return *((Seq_RetStep_t *)&Num); }
+
+// manipulating the number of latches on each edge
+static inline Vec_Int_t * Seq_ObjLNums( Abc_Obj_t * pObj ) { return ((Abc_Seq_t*)pObj->pNtk->pManFunc)->vNums; }
+static inline int Seq_ObjFaninL( Abc_Obj_t * pObj, int i ) { return Vec_IntEntry(Seq_ObjLNums(pObj), 2*pObj->Id + i); }
+static inline int Seq_ObjFaninL0( Abc_Obj_t * pObj ) { return Vec_IntEntry(Seq_ObjLNums(pObj), 2*pObj->Id + 0); }
+static inline int Seq_ObjFaninL1( Abc_Obj_t * pObj ) { return Vec_IntEntry(Seq_ObjLNums(pObj), 2*pObj->Id + 1); }
+static inline void Seq_ObjSetFaninL( Abc_Obj_t * pObj, int i, int nLats ) { Vec_IntWriteEntry(Seq_ObjLNums(pObj), 2*pObj->Id + i, nLats); }
+static inline void Seq_ObjSetFaninL0( Abc_Obj_t * pObj, int nLats ) { Vec_IntWriteEntry(Seq_ObjLNums(pObj), 2*pObj->Id + 0, nLats); }
+static inline void Seq_ObjSetFaninL1( Abc_Obj_t * pObj, int nLats ) { Vec_IntWriteEntry(Seq_ObjLNums(pObj), 2*pObj->Id + 1, nLats); }
+static inline void Seq_ObjAddFaninL( Abc_Obj_t * pObj, int i, int nLats ) { Vec_IntAddToEntry(Seq_ObjLNums(pObj), 2*pObj->Id + i, nLats); }
+static inline void Seq_ObjAddFaninL0( Abc_Obj_t * pObj, int nLats ) { Vec_IntAddToEntry(Seq_ObjLNums(pObj), 2*pObj->Id + 0, nLats); }
+static inline void Seq_ObjAddFaninL1( Abc_Obj_t * pObj, int nLats ) { Vec_IntAddToEntry(Seq_ObjLNums(pObj), 2*pObj->Id + 1, nLats); }
+static inline int Seq_ObjFanoutL( Abc_Obj_t * pObj, Abc_Obj_t * pFanout ) { return Seq_ObjFaninL( pFanout, Abc_ObjFanoutEdgeNum(pObj,pFanout) ); }
+static inline void Seq_ObjSetFanoutL( Abc_Obj_t * pObj, Abc_Obj_t * pFanout, int nLats ) { Seq_ObjSetFaninL( pFanout, Abc_ObjFanoutEdgeNum(pObj,pFanout), nLats ); }
+static inline void Seq_ObjAddFanoutL( Abc_Obj_t * pObj, Abc_Obj_t * pFanout, int nLats ) { Seq_ObjAddFaninL( pFanout, Abc_ObjFanoutEdgeNum(pObj,pFanout), nLats ); }
+static inline int Seq_ObjFaninLMin( Abc_Obj_t * pObj ) { assert( Abc_ObjIsNode(pObj) ); return ABC_MIN( Seq_ObjFaninL0(pObj), Seq_ObjFaninL1(pObj) ); }
+static inline int Seq_ObjFaninLMax( Abc_Obj_t * pObj ) { assert( Abc_ObjIsNode(pObj) ); return ABC_MAX( Seq_ObjFaninL0(pObj), Seq_ObjFaninL1(pObj) ); }
+
+// reading l-values and lags
+static inline Vec_Int_t * Seq_NodeLValues( Abc_Obj_t * pNode ) { return ((Abc_Seq_t *)(pNode)->pNtk->pManFunc)->vLValues; }
+static inline Vec_Int_t * Seq_NodeLValuesN( Abc_Obj_t * pNode ) { return ((Abc_Seq_t *)(pNode)->pNtk->pManFunc)->vLValuesN; }
+static inline int Seq_NodeGetLValue( Abc_Obj_t * pNode ) { return Vec_IntEntry( Seq_NodeLValues(pNode), (pNode)->Id ); }
+static inline void Seq_NodeSetLValue( Abc_Obj_t * pNode, int Value ) { Vec_IntWriteEntry( Seq_NodeLValues(pNode), (pNode)->Id, Value ); }
+static inline float Seq_NodeGetLValueP( Abc_Obj_t * pNode ) { return Abc_Int2Float( Vec_IntEntry( Seq_NodeLValues(pNode), (pNode)->Id ) ); }
+static inline float Seq_NodeGetLValueN( Abc_Obj_t * pNode ) { return Abc_Int2Float( Vec_IntEntry( Seq_NodeLValuesN(pNode), (pNode)->Id ) ); }
+static inline void Seq_NodeSetLValueP( Abc_Obj_t * pNode, float Value ) { Vec_IntWriteEntry( Seq_NodeLValues(pNode), (pNode)->Id, Abc_Float2Int(Value) ); }
+static inline void Seq_NodeSetLValueN( Abc_Obj_t * pNode, float Value ) { Vec_IntWriteEntry( Seq_NodeLValuesN(pNode), (pNode)->Id, Abc_Float2Int(Value) ); }
+
+// reading area flows
+static inline Vec_Int_t * Seq_NodeFlow( Abc_Obj_t * pNode ) { return ((Abc_Seq_t *)(pNode)->pNtk->pManFunc)->vAFlows; }
+static inline float Seq_NodeGetFlow( Abc_Obj_t * pNode ) { return Abc_Int2Float( Vec_IntEntry( Seq_NodeFlow(pNode), (pNode)->Id ) ); }
+static inline void Seq_NodeSetFlow( Abc_Obj_t * pNode, float Value ) { Vec_IntWriteEntry( Seq_NodeFlow(pNode), (pNode)->Id, Abc_Float2Int(Value) ); }
+
+// reading the contents of the lat
+static inline Abc_InitType_t Seq_LatInit( Seq_Lat_t * pLat ) { return ((unsigned)pLat->pPrev) & 3; }
+static inline Seq_Lat_t * Seq_LatNext( Seq_Lat_t * pLat ) { return pLat->pNext; }
+static inline Seq_Lat_t * Seq_LatPrev( Seq_Lat_t * pLat ) { return (void *)(((unsigned)pLat->pPrev) & (SEQ_FULL_MASK << 2)); }
+
+// setting the contents of the lat
+static inline void Seq_LatSetInit( Seq_Lat_t * pLat, Abc_InitType_t Init ) { pLat->pPrev = (void *)( (3 & Init) | (((unsigned)pLat->pPrev) & (SEQ_FULL_MASK << 2)) ); }
+static inline void Seq_LatSetNext( Seq_Lat_t * pLat, Seq_Lat_t * pNext ) { pLat->pNext = pNext; }
+static inline void Seq_LatSetPrev( Seq_Lat_t * pLat, Seq_Lat_t * pPrev ) { Abc_InitType_t Init = Seq_LatInit(pLat); pLat->pPrev = pPrev; Seq_LatSetInit(pLat, Init); }
+
+// accessing retiming lags
+static inline Cut_Man_t * Seq_NodeCutMan( Abc_Obj_t * pNode ) { return ((Abc_Seq_t *)(pNode)->pNtk->pManFunc)->pCutMan; }
+static inline Vec_Str_t * Seq_NodeLags( Abc_Obj_t * pNode ) { return ((Abc_Seq_t *)(pNode)->pNtk->pManFunc)->vLags; }
+static inline Vec_Str_t * Seq_NodeLagsN( Abc_Obj_t * pNode ) { return ((Abc_Seq_t *)(pNode)->pNtk->pManFunc)->vLagsN; }
+static inline char Seq_NodeGetLag( Abc_Obj_t * pNode ) { return Vec_StrEntry( Seq_NodeLags(pNode), (pNode)->Id ); }
+static inline char Seq_NodeGetLagN( Abc_Obj_t * pNode ) { return Vec_StrEntry( Seq_NodeLagsN(pNode), (pNode)->Id ); }
+static inline void Seq_NodeSetLag( Abc_Obj_t * pNode, char Value ) { Vec_StrWriteEntry( Seq_NodeLags(pNode), (pNode)->Id, (Value) ); }
+static inline void Seq_NodeSetLagN( Abc_Obj_t * pNode, char Value ) { Vec_StrWriteEntry( Seq_NodeLagsN(pNode), (pNode)->Id, (Value) ); }
+static inline int Seq_NodeComputeLag( int LValue, int Fi ) { return (LValue + 1024*Fi)/Fi - 1024 - (int)(LValue % Fi == 0); }
+static inline int Seq_NodeComputeLagFloat( float LValue, float Fi ) { return ((int)ceil(LValue/Fi)) - 1; }
+
+// phase usage
+static inline Vec_Str_t * Seq_NodeUses( Abc_Obj_t * pNode ) { return ((Abc_Seq_t *)(pNode)->pNtk->pManFunc)->vUses; }
+static inline char Seq_NodeGetUses( Abc_Obj_t * pNode ) { return Vec_StrEntry( Seq_NodeUses(pNode), (pNode)->Id ); }
+static inline void Seq_NodeSetUses( Abc_Obj_t * pNode, char Value ) { Vec_StrWriteEntry( Seq_NodeUses(pNode), (pNode)->Id, (Value) ); }
+
+// accessing initial states
+static inline Vec_Ptr_t * Seq_NodeLats( Abc_Obj_t * pObj ) { return ((Abc_Seq_t*)pObj->pNtk->pManFunc)->vInits; }
+static inline Seq_Lat_t * Seq_NodeGetRing( Abc_Obj_t * pObj, int Edge ) { return Vec_PtrEntry( Seq_NodeLats(pObj), (pObj->Id<<1)+Edge ); }
+static inline void Seq_NodeSetRing( Abc_Obj_t * pObj, int Edge, Seq_Lat_t * pLat ) { Vec_PtrWriteEntry( Seq_NodeLats(pObj), (pObj->Id<<1)+Edge, pLat ); }
+static inline Seq_Lat_t * Seq_NodeCreateLat( Abc_Obj_t * pObj ) { Seq_Lat_t * p = (Seq_Lat_t *)Extra_MmFixedEntryFetch( ((Abc_Seq_t*)pObj->pNtk->pManFunc)->pMmInits ); p->pNext = p->pPrev = NULL; p->pLatch = NULL; return p; }
+static inline void Seq_NodeRecycleLat( Abc_Obj_t * pObj, Seq_Lat_t * pLat ) { Extra_MmFixedEntryRecycle( ((Abc_Seq_t*)pObj->pNtk->pManFunc)->pMmInits, (char *)pLat ); }
+
+// getting hold of the structure storing initial states of the latches
+static inline Seq_Lat_t * Seq_NodeGetLatFirst( Abc_Obj_t * pObj, int Edge ) { return Seq_NodeGetRing(pObj, Edge); }
+static inline Seq_Lat_t * Seq_NodeGetLatLast( Abc_Obj_t * pObj, int Edge ) { return Seq_LatPrev( Seq_NodeGetRing(pObj, Edge) ); }
+static inline Seq_Lat_t * Seq_NodeGetLat( Abc_Obj_t * pObj, int Edge, int iLat ) { int c; Seq_Lat_t * pLat = Seq_NodeGetRing(pObj, Edge); for ( c = 0; c != iLat; c++ ) pLat = pLat->pNext; return pLat; }
+static inline int Seq_NodeCountLats( Abc_Obj_t * pObj, int Edge ) { int c; Seq_Lat_t * pLat, * pRing = Seq_NodeGetRing(pObj, Edge); if ( pRing == NULL ) return 0; for ( c = 0, pLat = pRing; !c || pLat != pRing; c++ ) pLat = pLat->pNext; return c; }
+static inline void Seq_NodeCleanLats( Abc_Obj_t * pObj, int Edge ) { int c; Seq_Lat_t * pLat, * pRing = Seq_NodeGetRing(pObj, Edge); if ( pRing == NULL ) return ; for ( c = 0, pLat = pRing; !c || pLat != pRing; c++ ) pLat->pLatch = NULL, pLat = pLat->pNext; return; }
+
+// getting/setting initial states of the latches
+static inline Abc_InitType_t Seq_NodeGetInitOne( Abc_Obj_t * pObj, int Edge, int iLat ) { return Seq_LatInit( Seq_NodeGetLat(pObj, Edge, iLat) ); }
+static inline Abc_InitType_t Seq_NodeGetInitFirst( Abc_Obj_t * pObj, int Edge ) { return Seq_LatInit( Seq_NodeGetLatFirst(pObj, Edge) ); }
+static inline Abc_InitType_t Seq_NodeGetInitLast( Abc_Obj_t * pObj, int Edge ) { return Seq_LatInit( Seq_NodeGetLatLast(pObj, Edge) ); }
+static inline void Seq_NodeSetInitOne( Abc_Obj_t * pObj, int Edge, int iLat, Abc_InitType_t Init ) { Seq_LatSetInit( Seq_NodeGetLat(pObj, Edge, iLat), Init ); }
+
+////////////////////////////////////////////////////////////////////////
+/// FUNCTION DECLARATIONS ///
+////////////////////////////////////////////////////////////////////////
+
+/*=== seqAigIter.c =============================================================*/
+extern int Seq_AigRetimeDelayLags( Abc_Ntk_t * pNtk, int fVerbose );
+extern int Seq_NtkImplementRetiming( Abc_Ntk_t * pNtk, Vec_Str_t * vLags, int fVerbose );
+/*=== seqFpgaIter.c ============================================================*/
+extern int Seq_FpgaMappingDelays( Abc_Ntk_t * pNtk, int fVerbose );
+extern int Seq_FpgaNodeUpdateLValue( Abc_Obj_t * pObj, int Fi );
+/*=== seqMapIter.c ============================================================*/
+extern int Seq_MapRetimeDelayLags( Abc_Ntk_t * pNtk, int fVerbose );
+/*=== seqRetIter.c =============================================================*/
+extern int Seq_NtkRetimeDelayLags( Abc_Ntk_t * pNtkOld, Abc_Ntk_t * pNtk, int fVerbose );
+/*=== seqLatch.c ===============================================================*/
+extern void Seq_NodeInsertFirst( Abc_Obj_t * pObj, int Edge, Abc_InitType_t Init );
+extern void Seq_NodeInsertLast( Abc_Obj_t * pObj, int Edge, Abc_InitType_t Init );
+extern Abc_InitType_t Seq_NodeDeleteFirst( Abc_Obj_t * pObj, int Edge );
+extern Abc_InitType_t Seq_NodeDeleteLast( Abc_Obj_t * pObj, int Edge );
+/*=== seqUtil.c ================================================================*/
+extern int Seq_NtkLevelMax( Abc_Ntk_t * pNtk );
+extern int Seq_ObjFanoutLMax( Abc_Obj_t * pObj );
+extern int Seq_ObjFanoutLMin( Abc_Obj_t * pObj );
+extern int Seq_ObjFanoutLSum( Abc_Obj_t * pObj );
+extern int Seq_ObjFaninLSum( Abc_Obj_t * pObj );
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
+
+////////////////////////////////////////////////////////////////////////
+/// END OF FILE ///
+////////////////////////////////////////////////////////////////////////
+
diff --git a/src/base/seq/seqLatch.c b/src/base/seq/seqLatch.c
new file mode 100644
index 00000000..cb3e1e36
--- /dev/null
+++ b/src/base/seq/seqLatch.c
@@ -0,0 +1,223 @@
+/**CFile****************************************************************
+
+ FileName [seqLatch.c]
+
+ SystemName [ABC: Logic synthesis and verification system.]
+
+ PackageName [Construction and manipulation of sequential AIGs.]
+
+ Synopsis [Manipulation of latch data structures representing initial states.]
+
+ Author [Alan Mishchenko]
+
+ Affiliation [UC Berkeley]
+
+ Date [Ver. 1.0. Started - June 20, 2005.]
+
+ Revision [$Id: seqLatch.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "seqInt.h"
+
+////////////////////////////////////////////////////////////////////////
+/// DECLARATIONS ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+/// FUNCTION DEFINITIONS ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+ Synopsis [Insert the first Lat on the edge.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Seq_NodeInsertFirst( Abc_Obj_t * pObj, int Edge, Abc_InitType_t Init )
+{
+ Seq_Lat_t * pLat, * pRing, * pPrev;
+ pRing = Seq_NodeGetRing( pObj, Edge );
+ pLat = Seq_NodeCreateLat( pObj );
+ if ( pRing == NULL )
+ {
+ Seq_LatSetPrev( pLat, pLat );
+ Seq_LatSetNext( pLat, pLat );
+ Seq_NodeSetRing( pObj, Edge, pLat );
+ }
+ else
+ {
+ pPrev = Seq_LatPrev( pRing );
+ Seq_LatSetPrev( pLat, pPrev );
+ Seq_LatSetNext( pPrev, pLat );
+ Seq_LatSetPrev( pRing, pLat );
+ Seq_LatSetNext( pLat, pRing );
+ Seq_NodeSetRing( pObj, Edge, pLat ); // rotate the ring to make pLat the first
+ }
+ Seq_LatSetInit( pLat, Init );
+ Seq_ObjAddFaninL( pObj, Edge, 1 );
+ assert( pLat->pLatch == NULL );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Insert the last Lat on the edge.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Seq_NodeInsertLast( Abc_Obj_t * pObj, int Edge, Abc_InitType_t Init )
+{
+ Seq_Lat_t * pLat, * pRing, * pPrev;
+ pRing = Seq_NodeGetRing( pObj, Edge );
+ pLat = Seq_NodeCreateLat( pObj );
+ if ( pRing == NULL )
+ {
+ Seq_LatSetPrev( pLat, pLat );
+ Seq_LatSetNext( pLat, pLat );
+ Seq_NodeSetRing( pObj, Edge, pLat );
+ }
+ else
+ {
+ pPrev = Seq_LatPrev( pRing );
+ Seq_LatSetPrev( pLat, pPrev );
+ Seq_LatSetNext( pPrev, pLat );
+ Seq_LatSetPrev( pRing, pLat );
+ Seq_LatSetNext( pLat, pRing );
+ }
+ Seq_LatSetInit( pLat, Init );
+ Seq_ObjAddFaninL( pObj, Edge, 1 );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Delete the first Lat on the edge.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Abc_InitType_t Seq_NodeDeleteFirst( Abc_Obj_t * pObj, int Edge )
+{
+ Abc_InitType_t Init;
+ Seq_Lat_t * pLat, * pRing, * pPrev, * pNext;
+ pRing = Seq_NodeGetRing( pObj, Edge );
+ pLat = pRing; // consider the first latch
+ if ( pLat->pNext == pLat )
+ Seq_NodeSetRing( pObj, Edge, NULL );
+ else
+ {
+ pPrev = Seq_LatPrev( pLat );
+ pNext = Seq_LatNext( pLat );
+ Seq_LatSetPrev( pNext, pPrev );
+ Seq_LatSetNext( pPrev, pNext );
+ Seq_NodeSetRing( pObj, Edge, pNext ); // rotate the ring
+ }
+ Init = Seq_LatInit( pLat );
+ Seq_NodeRecycleLat( pObj, pLat );
+ Seq_ObjAddFaninL( pObj, Edge, -1 );
+ return Init;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Delete the last Lat on the edge.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Abc_InitType_t Seq_NodeDeleteLast( Abc_Obj_t * pObj, int Edge )
+{
+ Abc_InitType_t Init;
+ Seq_Lat_t * pLat, * pRing, * pPrev, * pNext;
+ pRing = Seq_NodeGetRing( pObj, Edge );
+ pLat = Seq_LatPrev( pRing ); // consider the last latch
+ if ( pLat->pNext == pLat )
+ Seq_NodeSetRing( pObj, Edge, NULL );
+ else
+ {
+ pPrev = Seq_LatPrev( pLat );
+ pNext = Seq_LatNext( pLat );
+ Seq_LatSetPrev( pNext, pPrev );
+ Seq_LatSetNext( pPrev, pNext );
+ }
+ Init = Seq_LatInit( pLat );
+ Seq_NodeRecycleLat( pObj, pLat );
+ Seq_ObjAddFaninL( pObj, Edge, -1 );
+ return Init;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Insert the last Lat on the edge.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Seq_NodeDupLats( Abc_Obj_t * pObjNew, Abc_Obj_t * pObj, int Edge )
+{
+ Seq_Lat_t * pRing, * pLat;
+ int i, nLatches;
+ pRing = Seq_NodeGetRing( pObj, Edge );
+ if ( pRing == NULL )
+ return;
+ nLatches = Seq_NodeCountLats( pObj, Edge );
+ for ( i = 0, pLat = pRing; i < nLatches; i++, pLat = pLat->pNext )
+ Seq_NodeInsertLast( pObjNew, Edge, Seq_LatInit(pLat) );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Insert the last Lat on the edge.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Seq_NodeCompareLats( Abc_Obj_t * pObj1, int Edge1, Abc_Obj_t * pObj2, int Edge2 )
+{
+ Seq_Lat_t * pRing1, * pRing2, * pLat1, * pLat2;
+ int i, nLatches1, nLatches2;
+
+ nLatches1 = Seq_NodeCountLats( pObj1, Edge1 );
+ nLatches2 = Seq_NodeCountLats( pObj2, Edge2 );
+ if ( nLatches1 != nLatches2 )
+ return 0;
+
+ pRing1 = Seq_NodeGetRing( pObj1, Edge1 );
+ pRing2 = Seq_NodeGetRing( pObj2, Edge2 );
+ for ( i = 0, pLat1 = pRing1, pLat2 = pRing2; i < nLatches1; i++, pLat1 = pLat1->pNext, pLat2 = pLat2->pNext )
+ if ( Seq_LatInit(pLat1) != Seq_LatInit(pLat2) )
+ return 0;
+
+ return 1;
+}
+
+////////////////////////////////////////////////////////////////////////
+/// END OF FILE ///
+////////////////////////////////////////////////////////////////////////
+
+
diff --git a/src/base/seq/seqMan.c b/src/base/seq/seqMan.c
new file mode 100644
index 00000000..bdfb2630
--- /dev/null
+++ b/src/base/seq/seqMan.c
@@ -0,0 +1,133 @@
+/**CFile****************************************************************
+
+ FileName [seqMan.c]
+
+ SystemName [ABC: Logic synthesis and verification system.]
+
+ PackageName [Construction and manipulation of sequential AIGs.]
+
+ Synopsis [Manager of sequential AIG containing.]
+
+ Author [Alan Mishchenko]
+
+ Affiliation [UC Berkeley]
+
+ Date [Ver. 1.0. Started - June 20, 2005.]
+
+ Revision [$Id: seqMan.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "seqInt.h"
+
+////////////////////////////////////////////////////////////////////////
+/// DECLARATIONS ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+/// FUNCTION DEFINITIONS ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+ Synopsis [Allocates sequential AIG manager.]
+
+ Description [The manager contains all the data structures needed to
+ represent sequential AIG and compute stand-alone retiming as well as
+ the integrated mapping/retiming of the sequential AIG.]
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Abc_Seq_t * Seq_Create( Abc_Ntk_t * pNtk )
+{
+ Abc_Seq_t * p;
+ // start the manager
+ p = ALLOC( Abc_Seq_t, 1 );
+ memset( p, 0, sizeof(Abc_Seq_t) );
+ p->pNtk = pNtk;
+ p->nSize = 1000;
+ p->nMaxIters = 15;
+ p->pMmInits = Extra_MmFixedStart( sizeof(Seq_Lat_t) );
+ p->fEpsilon = (float)0.001;
+ // create internal data structures
+ p->vNums = Vec_IntStart( 2 * p->nSize );
+ p->vInits = Vec_PtrStart( 2 * p->nSize );
+ p->vLValues = Vec_IntStart( p->nSize );
+ p->vLags = Vec_StrStart( p->nSize );
+ p->vLValuesN = Vec_IntStart( p->nSize );
+ p->vAFlows = Vec_IntStart( p->nSize );
+ p->vLagsN = Vec_StrStart( p->nSize );
+ p->vUses = Vec_StrStart( p->nSize );
+ return p;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Deallocates sequential AIG manager.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Seq_Resize( Abc_Seq_t * p, int nMaxId )
+{
+ if ( p->nSize > nMaxId )
+ return;
+ p->nSize = nMaxId + 1;
+ Vec_IntFill( p->vNums, 2 * p->nSize, 0 );
+ Vec_PtrFill( p->vInits, 2 * p->nSize, NULL );
+ Vec_IntFill( p->vLValues, p->nSize, 0 );
+ Vec_StrFill( p->vLags, p->nSize, 0 );
+ Vec_IntFill( p->vLValuesN, p->nSize, 0 );
+ Vec_IntFill( p->vAFlows, p->nSize, 0 );
+ Vec_StrFill( p->vLagsN, p->nSize, 0 );
+ Vec_StrFill( p->vUses, p->nSize, 0 );
+}
+
+
+/**Function*************************************************************
+
+ Synopsis [Deallocates sequential AIG manager.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Seq_Delete( Abc_Seq_t * p )
+{
+ if ( p->fStandCells && p->vMapAnds )
+ {
+ void * pVoid; int i;
+ Vec_PtrForEachEntry( p->vMapAnds, pVoid, i )
+ free( pVoid );
+ }
+ if ( p->vMapDelays ) Vec_VecFree( p->vMapDelays ); // the nodes used in the mapping
+ if ( p->vMapFanins ) Vec_VecFree( p->vMapFanins ); // the cuts used in the mapping
+ if ( p->vMapAnds ) Vec_PtrFree( p->vMapAnds ); // the nodes used in the mapping
+ if ( p->vMapCuts ) Vec_VecFree( p->vMapCuts ); // the cuts used in the mapping
+ if ( p->vLValues ) Vec_IntFree( p->vLValues ); // the arrival times (L-Values of nodes)
+ if ( p->vLags ) Vec_StrFree( p->vLags ); // the lags of the mapped nodes
+ if ( p->vLValuesN ) Vec_IntFree( p->vLValuesN ); // the arrival times (L-Values of nodes)
+ if ( p->vAFlows ) Vec_IntFree( p->vAFlows ); // the arrival times (L-Values of nodes)
+ if ( p->vLagsN ) Vec_StrFree( p->vLagsN ); // the lags of the mapped nodes
+ if ( p->vUses ) Vec_StrFree( p->vUses ); // the uses of phases
+ if ( p->vInits ) Vec_PtrFree( p->vInits ); // the initial values of the latches
+ if ( p->vNums ) Vec_IntFree( p->vNums ); // the numbers of latches
+ Extra_MmFixedStop( p->pMmInits );
+ free( p );
+}
+
+////////////////////////////////////////////////////////////////////////
+/// END OF FILE ///
+////////////////////////////////////////////////////////////////////////
+
+
diff --git a/src/base/seq/seqMapCore.c b/src/base/seq/seqMapCore.c
new file mode 100644
index 00000000..c465f31f
--- /dev/null
+++ b/src/base/seq/seqMapCore.c
@@ -0,0 +1,652 @@
+/**CFile****************************************************************
+
+ FileName [seqMapCore.c]
+
+ SystemName [ABC: Logic synthesis and verification system.]
+
+ PackageName [Construction and manipulation of sequential AIGs.]
+
+ Synopsis [The core of SC mapping/retiming package.]
+
+ Author [Alan Mishchenko]
+
+ Affiliation [UC Berkeley]
+
+ Date [Ver. 1.0. Started - June 20, 2005.]
+
+ Revision [$Id: seqMapCore.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "seqInt.h"
+#include "main.h"
+#include "mio.h"
+#include "mapper.h"
+
+////////////////////////////////////////////////////////////////////////
+/// DECLARATIONS ///
+////////////////////////////////////////////////////////////////////////
+
+extern Abc_Ntk_t * Seq_NtkMapDup( Abc_Ntk_t * pNtk );
+extern int Seq_NtkMapInitCompatible( Abc_Ntk_t * pNtk, int fVerbose );
+extern Abc_Ntk_t * Seq_NtkSeqMapMapped( Abc_Ntk_t * pNtk );
+
+static int Seq_MapMappingCount( Abc_Ntk_t * pNtk );
+static int Seq_MapMappingCount_rec( Abc_Ntk_t * pNtk, unsigned SeqEdge, Vec_Ptr_t * vLeaves );
+static Abc_Obj_t * Seq_MapMappingBuild_rec( Abc_Ntk_t * pNtkNew, Abc_Ntk_t * pNtk, unsigned SeqEdge, int fTop, int fCompl, int LagCut, Vec_Ptr_t * vLeaves, unsigned uPhase );
+static DdNode * Seq_MapMappingBdd_rec( DdManager * dd, Abc_Ntk_t * pNtk, unsigned SeqEdge, Vec_Ptr_t * vLeaves );
+static void Seq_MapMappingEdges_rec( Abc_Ntk_t * pNtk, unsigned SeqEdge, Abc_Obj_t * pPrev, Vec_Ptr_t * vLeaves, Vec_Vec_t * vMapEdges );
+static void Seq_MapMappingConnect_rec( Abc_Ntk_t * pNtk, unsigned SeqEdge, Abc_Obj_t * pPrev, int Edge, Abc_Obj_t * pRoot, Vec_Ptr_t * vLeaves );
+static DdNode * Seq_MapMappingConnectBdd_rec( Abc_Ntk_t * pNtk, unsigned SeqEdge, Abc_Obj_t * pPrev, int Edge, Abc_Obj_t * pRoot, Vec_Ptr_t * vLeaves );
+
+////////////////////////////////////////////////////////////////////////
+/// FUNCTION DEFINITIONS ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+ Synopsis [Performs Map mapping and retiming.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Abc_Ntk_t * Seq_MapRetime( Abc_Ntk_t * pNtk, int nMaxIters, int fVerbose )
+{
+ Abc_Seq_t * p = pNtk->pManFunc;
+ Abc_Ntk_t * pNtkNew;
+ Abc_Ntk_t * pNtkMap;
+ int RetValue;
+
+ // derive the supergate library
+ if ( Abc_FrameReadLibSuper() == NULL && Abc_FrameReadLibGen() )
+ {
+ printf( "A simple supergate library is derived from gate library \"%s\".\n",
+ Mio_LibraryReadName(Abc_FrameReadLibGen()) );
+ Map_SuperLibDeriveFromGenlib( Abc_FrameReadLibGen() );
+ }
+ p->pSuperLib = Abc_FrameReadLibSuper();
+ p->nVarsMax = Map_SuperLibReadVarsMax(p->pSuperLib);
+ p->nMaxIters = nMaxIters;
+ p->fStandCells = 1;
+
+ // find the best mapping and retiming for all nodes (p->vLValues, p->vBestCuts, p->vLags)
+ if ( !Seq_MapRetimeDelayLags( pNtk, fVerbose ) )
+ return NULL;
+ if ( RetValue = Abc_NtkGetChoiceNum(pNtk) )
+ {
+ printf( "The network has %d choices. The resulting network is not derived (this is temporary).\n", RetValue );
+ printf( "The mininum clock period computed is %5.2f.\n", p->FiBestFloat );
+ return NULL;
+ }
+ printf( "The mininum clock period computed is %5.2f.\n", p->FiBestFloat );
+ printf( "The resulting network is derived as BDD logic network (this is temporary).\n" );
+
+ // duplicate the nodes contained in multiple cuts
+ pNtkNew = Seq_NtkMapDup( pNtk );
+
+ // implement the retiming
+ RetValue = Seq_NtkImplementRetiming( pNtkNew, ((Abc_Seq_t *)pNtkNew->pManFunc)->vLags, fVerbose );
+ if ( RetValue == 0 )
+ printf( "Retiming completed but initial state computation has failed.\n" );
+
+ // check the compatibility of initial states computed
+ if ( RetValue = Seq_NtkMapInitCompatible( pNtkNew, fVerbose ) )
+ printf( "The number of LUTs with incompatible edges = %d.\n", RetValue );
+// return pNtkNew;
+
+ // create the final mapped network
+ pNtkMap = Seq_NtkSeqMapMapped( pNtkNew );
+ Abc_NtkDelete( pNtkNew );
+ return pNtkMap;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Derives the network by duplicating some of the nodes.]
+
+ Description [Information about mapping is given as mapping nodes (p->vMapAnds)
+ and best cuts for each node (p->vMapCuts).]
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Abc_Ntk_t * Seq_NtkMapDup( Abc_Ntk_t * pNtk )
+{
+ Abc_Seq_t * pNew, * p = pNtk->pManFunc;
+ Seq_Match_t * pMatch;
+ Abc_Ntk_t * pNtkNew;
+ Abc_Obj_t * pObj, * pFanin, * pFaninNew, * pLeaf;
+ Vec_Ptr_t * vLeaves;
+ unsigned SeqEdge;
+ int i, k, nObjsNew, Lag;
+
+ assert( Abc_NtkIsSeq(pNtk) );
+
+ // start the expanded network
+ pNtkNew = Abc_NtkStartFrom( pNtk, pNtk->ntkType, pNtk->ntkFunc );
+ Abc_NtkCleanNext(pNtk);
+
+ // start the new sequential AIG manager
+ nObjsNew = 1 + Abc_NtkPiNum(pNtk) + Abc_NtkPoNum(pNtk) + Seq_MapMappingCount(pNtk);
+ Seq_Resize( pNtkNew->pManFunc, nObjsNew );
+
+ // duplicate the nodes in the mapping
+ Vec_PtrForEachEntry( p->vMapAnds, pMatch, i )
+ {
+// Abc_NtkDupObj( pNtkNew, pMatch->pAnd );
+ if ( !pMatch->fCompl )
+ pMatch->pAnd->pCopy = Abc_NtkCreateNode( pNtkNew );
+ else
+ pMatch->pAnd->pNext = Abc_NtkCreateNode( pNtkNew );
+ }
+
+ // compute the real phase assignment
+ Vec_PtrForEachEntry( p->vMapAnds, pMatch, i )
+ {
+ pMatch->uPhaseR = 0;
+ // get the leaves of the cut
+ vLeaves = Vec_VecEntry( p->vMapCuts, i );
+ // convert the leaf nodes
+ Vec_PtrForEachEntry( vLeaves, pLeaf, k )
+ {
+ SeqEdge = (unsigned)pLeaf;
+ pLeaf = Abc_NtkObj( pNtk, SeqEdge >> 8 );
+
+ // set the phase
+ if ( pMatch->uPhase & (1 << k) ) // neg is required
+ {
+ if ( pLeaf->pNext ) // neg is available
+ pMatch->uPhaseR |= (1 << k); // neg is used
+// else
+// Seq_NodeSetLag( pLeaf, Seq_NodeGetLagN(pLeaf) );
+ }
+ else // pos is required
+ {
+ if ( pLeaf->pCopy == NULL ) // pos is not available
+ pMatch->uPhaseR |= (1 << k); // neg is used
+// else
+// Seq_NodeSetLagN( pLeaf, Seq_NodeGetLag(pLeaf) );
+ }
+ }
+ }
+
+
+ // recursively construct the internals of each node
+ Vec_PtrForEachEntry( p->vMapAnds, pMatch, i )
+ {
+// if ( pMatch->pSuper == NULL )
+// {
+// int x = 0;
+// }
+ vLeaves = Vec_VecEntry( p->vMapCuts, i );
+ if ( !pMatch->fCompl )
+ Seq_MapMappingBuild_rec( pNtkNew, pNtk, pMatch->pAnd->Id << 8, 1, pMatch->fCompl, Seq_NodeGetLag(pMatch->pAnd), vLeaves, pMatch->uPhaseR );
+ else
+ Seq_MapMappingBuild_rec( pNtkNew, pNtk, pMatch->pAnd->Id << 8, 1, pMatch->fCompl, Seq_NodeGetLagN(pMatch->pAnd), vLeaves, pMatch->uPhaseR );
+ }
+ assert( nObjsNew == pNtkNew->nObjs );
+
+ // set the POs
+// Abc_NtkFinalize( pNtk, pNtkNew );
+ Abc_NtkForEachPo( pNtk, pObj, i )
+ {
+ pFanin = Abc_ObjFanin0(pObj);
+ if ( Abc_ObjFaninC0(pObj) )
+ pFaninNew = pFanin->pNext ? pFanin->pNext : pFanin->pCopy;
+ else
+ pFaninNew = pFanin->pCopy ? pFanin->pCopy : pFanin->pNext;
+ pFaninNew = Abc_ObjNotCond( pFaninNew, Abc_ObjFaninC0(pObj) );
+ Abc_ObjAddFanin( pObj->pCopy, pFaninNew );
+ }
+
+ // duplicate the latches on the PO edges
+ Abc_NtkForEachPo( pNtk, pObj, i )
+ Seq_NodeDupLats( pObj->pCopy, pObj, 0 );
+
+ // transfer the mapping info to the new manager
+ Vec_PtrForEachEntry( p->vMapAnds, pMatch, i )
+ {
+ // get the leaves of the cut
+ vLeaves = Vec_VecEntry( p->vMapCuts, i );
+ // convert the leaf nodes
+ Vec_PtrForEachEntry( vLeaves, pLeaf, k )
+ {
+ SeqEdge = (unsigned)pLeaf;
+ pLeaf = Abc_NtkObj( pNtk, SeqEdge >> 8 );
+
+// Lag = (SeqEdge & 255) + Seq_NodeGetLag(pMatch->pAnd) - Seq_NodeGetLag(pLeaf);
+ Lag = (SeqEdge & 255) +
+ (pMatch->fCompl? Seq_NodeGetLagN(pMatch->pAnd) : Seq_NodeGetLag(pMatch->pAnd)) -
+ (((pMatch->uPhaseR & (1 << k)) > 0)? Seq_NodeGetLagN(pLeaf) : Seq_NodeGetLag(pLeaf) );
+
+ assert( Lag >= 0 );
+
+ // translate the old leaf into the leaf in the new network
+// if ( pMatch->uPhase & (1 << k) ) // negative phase is required
+// pFaninNew = pLeaf->pNext? pLeaf->pNext : pLeaf->pCopy;
+// else // positive phase is required
+// pFaninNew = pLeaf->pCopy? pLeaf->pCopy : pLeaf->pNext;
+
+ // translate the old leaf into the leaf in the new network
+ if ( pMatch->uPhaseR & (1 << k) ) // negative phase is required
+ pFaninNew = pLeaf->pNext;
+ else // positive phase is required
+ pFaninNew = pLeaf->pCopy;
+
+ Vec_PtrWriteEntry( vLeaves, k, (void *)((pFaninNew->Id << 8) | Lag) );
+// printf( "%d -> %d\n", pLeaf->Id, pLeaf->pCopy->Id );
+
+ // UPDATE PHASE!!! leaving only those bits that require inverters
+ }
+ // convert the root node
+// Vec_PtrWriteEntry( p->vMapAnds, i, pObj->pCopy );
+ pMatch->pAnd = pMatch->fCompl? pMatch->pAnd->pNext : pMatch->pAnd->pCopy;
+ }
+ pNew = pNtkNew->pManFunc;
+ pNew->nVarsMax = p->nVarsMax;
+ pNew->vMapAnds = p->vMapAnds; p->vMapAnds = NULL;
+ pNew->vMapCuts = p->vMapCuts; p->vMapCuts = NULL;
+ pNew->fStandCells = p->fStandCells; p->fStandCells = 0;
+
+ if ( !Abc_NtkCheck( pNtkNew ) )
+ fprintf( stdout, "Seq_NtkMapDup(): Network check has failed.\n" );
+ return pNtkNew;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Checks if the initial states are compatible.]
+
+ Description [Checks of all the initial states on the fanins edges
+ of the cut have compatible number of latches and initial states.
+ If this is not true, then the mapped network with the does not have initial
+ state. Returns the number of LUTs with incompatible edges.]
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Seq_NtkMapInitCompatible( Abc_Ntk_t * pNtk, int fVerbose )
+{
+ Abc_Seq_t * p = pNtk->pManFunc;
+ Seq_Match_t * pMatch;
+ Abc_Obj_t * pAnd, * pLeaf, * pFanout0, * pFanout1;
+ Vec_Vec_t * vTotalEdges;
+ Vec_Ptr_t * vLeaves, * vEdges;
+ int i, k, m, Edge0, Edge1, nLatchAfter, nLatches1, nLatches2;
+ unsigned SeqEdge;
+ int CountBad = 0, CountAll = 0;
+
+ vTotalEdges = Vec_VecStart( p->nVarsMax );
+ // go through all the nodes (cuts) used in the mapping
+ Vec_PtrForEachEntry( p->vMapAnds, pMatch, i )
+ {
+ pAnd = pMatch->pAnd;
+// printf( "*** Node %d.\n", pAnd->Id );
+
+ // get the cut of this gate
+ vLeaves = Vec_VecEntry( p->vMapCuts, i );
+
+ // get the edges pointing to the leaves
+ Vec_VecClear( vTotalEdges );
+ Seq_MapMappingEdges_rec( pNtk, pAnd->Id << 8, NULL, vLeaves, vTotalEdges );
+
+ // for each leaf, consider its edges
+ Vec_PtrForEachEntry( vLeaves, pLeaf, k )
+ {
+ SeqEdge = (unsigned)pLeaf;
+ pLeaf = Abc_NtkObj( pNtk, SeqEdge >> 8 );
+ nLatchAfter = SeqEdge & 255;
+ if ( nLatchAfter == 0 )
+ continue;
+
+ // go through the edges
+ vEdges = Vec_VecEntry( vTotalEdges, k );
+ pFanout0 = NULL;
+ Vec_PtrForEachEntry( vEdges, pFanout1, m )
+ {
+ Edge1 = Abc_ObjIsComplement(pFanout1);
+ pFanout1 = Abc_ObjRegular(pFanout1);
+//printf( "Fanin = %d. Fanout = %d.\n", pLeaf->Id, pFanout1->Id );
+
+ // make sure this is the same fanin
+ if ( Edge1 )
+ assert( pLeaf == Abc_ObjFanin1(pFanout1) );
+ else
+ assert( pLeaf == Abc_ObjFanin0(pFanout1) );
+
+ // save the first one
+ if ( pFanout0 == NULL )
+ {
+ pFanout0 = pFanout1;
+ Edge0 = Edge1;
+ continue;
+ }
+ // compare the rings
+ // if they have different number of latches, this is the bug
+ nLatches1 = Seq_NodeCountLats(pFanout0, Edge0);
+ nLatches2 = Seq_NodeCountLats(pFanout1, Edge1);
+ assert( nLatches1 == nLatches2 );
+ assert( nLatches1 == nLatchAfter );
+ assert( nLatches1 > 0 );
+
+ // if they have different initial states, this is the problem
+ if ( !Seq_NodeCompareLats(pFanout0, Edge0, pFanout1, Edge1) )
+ {
+ CountBad++;
+ break;
+ }
+ CountAll++;
+ }
+ }
+ }
+ if ( fVerbose )
+ printf( "The number of pairs of edges checked = %d.\n", CountAll );
+ Vec_VecFree( vTotalEdges );
+ return CountBad;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Derives the final mapped network.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Abc_Ntk_t * Seq_NtkSeqMapMapped( Abc_Ntk_t * pNtk )
+{
+ Abc_Seq_t * p = pNtk->pManFunc;
+ Seq_Match_t * pMatch;
+ Abc_Ntk_t * pNtkMap;
+ Vec_Ptr_t * vLeaves;
+ Abc_Obj_t * pObj, * pFaninNew;
+ Seq_Lat_t * pRing;
+ int i;
+
+ assert( Abc_NtkIsSeq(pNtk) );
+
+ // start the network
+ pNtkMap = Abc_NtkStartFrom( pNtk, ABC_NTK_LOGIC, ABC_FUNC_BDD );
+
+ // duplicate the nodes used in the mapping
+ Vec_PtrForEachEntry( p->vMapAnds, pMatch, i )
+ pMatch->pAnd->pCopy = Abc_NtkCreateNode( pNtkMap );
+
+ // create and share the latches
+ Seq_NtkShareLatchesMapping( pNtkMap, pNtk, p->vMapAnds, 0 );
+
+ // connect the nodes
+ Vec_PtrForEachEntry( p->vMapAnds, pMatch, i )
+ {
+ pObj = pMatch->pAnd;
+ // get the leaves of this gate
+ vLeaves = Vec_VecEntry( p->vMapCuts, i );
+ // get the BDD of the node
+ pObj->pCopy->pData = Seq_MapMappingConnectBdd_rec( pNtk, pObj->Id << 8, NULL, -1, pObj, vLeaves );
+ Cudd_Ref( pObj->pCopy->pData );
+ // complement the BDD of the cut if it came from the opposite polarity choice cut
+// if ( Vec_StrEntry(p->vPhase, i) )
+// pObj->pCopy->pData = Cudd_Not( pObj->pCopy->pData );
+ }
+
+ // set the POs
+ Abc_NtkForEachPo( pNtk, pObj, i )
+ {
+ if ( pRing = Seq_NodeGetRing(pObj,0) )
+ pFaninNew = pRing->pLatch;
+ else
+ pFaninNew = Abc_ObjFanin0(pObj)->pCopy;
+ pFaninNew = Abc_ObjNotCond( pFaninNew, Abc_ObjFaninC0(pObj) );
+ Abc_ObjAddFanin( pObj->pCopy, pFaninNew );
+ }
+
+ // add the latches and their names
+ Abc_NtkAddDummyBoxNames( pNtkMap );
+ Abc_NtkOrderCisCos( pNtkMap );
+ // fix the problem with complemented and duplicated CO edges
+ Abc_NtkLogicMakeSimpleCos( pNtkMap, 1 );
+ // make the network minimum base
+ Abc_NtkMinimumBase( pNtkMap );
+ if ( !Abc_NtkCheck( pNtkMap ) )
+ fprintf( stdout, "Seq_NtkSeqFpgaMapped(): Network check has failed.\n" );
+ return pNtkMap;
+}
+
+
+
+/**Function*************************************************************
+
+ Synopsis [Counts the number of nodes in the bag.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Seq_MapMappingCount( Abc_Ntk_t * pNtk )
+{
+ Abc_Seq_t * p = pNtk->pManFunc;
+ Vec_Ptr_t * vLeaves;
+ Seq_Match_t * pMatch;
+ int i, Counter = 0;
+ Vec_PtrForEachEntry( p->vMapAnds, pMatch, i )
+ {
+ vLeaves = Vec_VecEntry( p->vMapCuts, i );
+ Counter += Seq_MapMappingCount_rec( pNtk, pMatch->pAnd->Id << 8, vLeaves );
+ }
+ return Counter;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Counts the number of nodes in the bag.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Seq_MapMappingCount_rec( Abc_Ntk_t * pNtk, unsigned SeqEdge, Vec_Ptr_t * vLeaves )
+{
+ Abc_Obj_t * pObj, * pLeaf;
+ unsigned SeqEdge0, SeqEdge1;
+ int Lag, i;
+ // get the object and the lag
+ pObj = Abc_NtkObj( pNtk, SeqEdge >> 8 );
+ Lag = SeqEdge & 255;
+ // if the node is the fanin of the cut, return
+ Vec_PtrForEachEntry( vLeaves, pLeaf, i )
+ if ( SeqEdge == (unsigned)pLeaf )
+ return 0;
+ // continue unfolding
+ assert( Abc_AigNodeIsAnd(pObj) );
+ // get new sequential edges
+ assert( Lag + Seq_ObjFaninL0(pObj) < 255 );
+ assert( Lag + Seq_ObjFaninL1(pObj) < 255 );
+ SeqEdge0 = (Abc_ObjFanin0(pObj)->Id << 8) + Lag + Seq_ObjFaninL0(pObj);
+ SeqEdge1 = (Abc_ObjFanin1(pObj)->Id << 8) + Lag + Seq_ObjFaninL1(pObj);
+ // call for the children
+ return 1 + Seq_MapMappingCount_rec( pNtk, SeqEdge0, vLeaves ) +
+ Seq_MapMappingCount_rec( pNtk, SeqEdge1, vLeaves );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Collects the edges pointing to the leaves of the cut.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Abc_Obj_t * Seq_MapMappingBuild_rec( Abc_Ntk_t * pNtkNew, Abc_Ntk_t * pNtk, unsigned SeqEdge, int fTop, int fCompl, int LagCut, Vec_Ptr_t * vLeaves, unsigned uPhase )
+{
+ Abc_Obj_t * pObj, * pObjNew, * pLeaf, * pFaninNew0, * pFaninNew1;
+ unsigned SeqEdge0, SeqEdge1;
+ int Lag, i;
+ // get the object and the lag
+ pObj = Abc_NtkObj( pNtk, SeqEdge >> 8 );
+ Lag = SeqEdge & 255;
+ // if the node is the fanin of the cut, return
+ Vec_PtrForEachEntry( vLeaves, pLeaf, i )
+ if ( SeqEdge == (unsigned)pLeaf )
+ {
+// if ( uPhase & (1 << i) ) // negative phase is required
+// return pObj->pNext? pObj->pNext : pObj->pCopy;
+// else // positive phase is required
+// return pObj->pCopy? pObj->pCopy : pObj->pNext;
+
+ if ( uPhase & (1 << i) ) // negative phase is required
+ return pObj->pNext;
+ else // positive phase is required
+ return pObj->pCopy;
+ }
+ // continue unfolding
+ assert( Abc_AigNodeIsAnd(pObj) );
+ // get new sequential edges
+ assert( Lag + Seq_ObjFaninL0(pObj) < 255 );
+ assert( Lag + Seq_ObjFaninL1(pObj) < 255 );
+ SeqEdge0 = (Abc_ObjFanin0(pObj)->Id << 8) + Lag + Seq_ObjFaninL0(pObj);
+ SeqEdge1 = (Abc_ObjFanin1(pObj)->Id << 8) + Lag + Seq_ObjFaninL1(pObj);
+ // call for the children
+ pObjNew = fTop? (fCompl? pObj->pNext : pObj->pCopy) : Abc_NtkCreateNode( pNtkNew );
+ // solve subproblems
+ pFaninNew0 = Seq_MapMappingBuild_rec( pNtkNew, pNtk, SeqEdge0, 0, fCompl, LagCut, vLeaves, uPhase );
+ pFaninNew1 = Seq_MapMappingBuild_rec( pNtkNew, pNtk, SeqEdge1, 0, fCompl, LagCut, vLeaves, uPhase );
+ // add the fanins to the node
+ Abc_ObjAddFanin( pObjNew, Abc_ObjNotCond( pFaninNew0, Abc_ObjFaninC0(pObj) ) );
+ Abc_ObjAddFanin( pObjNew, Abc_ObjNotCond( pFaninNew1, Abc_ObjFaninC1(pObj) ) );
+ Seq_NodeDupLats( pObjNew, pObj, 0 );
+ Seq_NodeDupLats( pObjNew, pObj, 1 );
+ // set the lag of the new node equal to the internal lag plus mapping/retiming lag
+ Seq_NodeSetLag( pObjNew, (char)(Lag + LagCut) );
+// Seq_NodeSetLag( pObjNew, (char)(Lag) );
+ return pObjNew;
+}
+
+
+/**Function*************************************************************
+
+ Synopsis [Collects the edges pointing to the leaves of the cut.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Seq_MapMappingEdges_rec( Abc_Ntk_t * pNtk, unsigned SeqEdge, Abc_Obj_t * pPrev, Vec_Ptr_t * vLeaves, Vec_Vec_t * vMapEdges )
+{
+ Abc_Obj_t * pObj, * pLeaf;
+ unsigned SeqEdge0, SeqEdge1;
+ int Lag, i;
+ // get the object and the lag
+ pObj = Abc_NtkObj( pNtk, SeqEdge >> 8 );
+ Lag = SeqEdge & 255;
+ // if the node is the fanin of the cut, return
+ Vec_PtrForEachEntry( vLeaves, pLeaf, i )
+ {
+ if ( SeqEdge == (unsigned)pLeaf )
+ {
+ assert( pPrev != NULL );
+ Vec_VecPush( vMapEdges, i, pPrev );
+ return;
+ }
+ }
+ // continue unfolding
+ assert( Abc_AigNodeIsAnd(pObj) );
+ // get new sequential edges
+ assert( Lag + Seq_ObjFaninL0(pObj) < 255 );
+ assert( Lag + Seq_ObjFaninL1(pObj) < 255 );
+ SeqEdge0 = (Abc_ObjFanin0(pObj)->Id << 8) + Lag + Seq_ObjFaninL0(pObj);
+ SeqEdge1 = (Abc_ObjFanin1(pObj)->Id << 8) + Lag + Seq_ObjFaninL1(pObj);
+ // call for the children
+ Seq_MapMappingEdges_rec( pNtk, SeqEdge0, pObj , vLeaves, vMapEdges );
+ Seq_MapMappingEdges_rec( pNtk, SeqEdge1, Abc_ObjNot(pObj), vLeaves, vMapEdges );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Collects the edges pointing to the leaves of the cut.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+DdNode * Seq_MapMappingConnectBdd_rec( Abc_Ntk_t * pNtk, unsigned SeqEdge, Abc_Obj_t * pPrev, int Edge, Abc_Obj_t * pRoot, Vec_Ptr_t * vLeaves )
+{
+ Seq_Lat_t * pRing;
+ Abc_Obj_t * pObj, * pLeaf, * pFanin, * pFaninNew;
+ unsigned SeqEdge0, SeqEdge1;
+ DdManager * dd = pRoot->pCopy->pNtk->pManFunc;
+ DdNode * bFunc, * bFunc0, * bFunc1;
+ int Lag, i, k;
+ // get the object and the lag
+ pObj = Abc_NtkObj( pNtk, SeqEdge >> 8 );
+ Lag = SeqEdge & 255;
+ // if the node is the fanin of the cut, add the connection and return
+ Vec_PtrForEachEntry( vLeaves, pLeaf, i )
+ {
+ if ( SeqEdge == (unsigned)pLeaf )
+ {
+ assert( pPrev != NULL );
+ if ( pRing = Seq_NodeGetRing(pPrev,Edge) )
+ pFaninNew = pRing->pLatch;
+ else
+ pFaninNew = Abc_ObjFanin(pPrev,Edge)->pCopy;
+
+ // check if the root already has this fanin
+ Abc_ObjForEachFanin( pRoot->pCopy, pFanin, k )
+ if ( pFanin == pFaninNew )
+ return Cudd_bddIthVar( dd, k );
+ Abc_ObjAddFanin( pRoot->pCopy, pFaninNew );
+ return Cudd_bddIthVar( dd, k );
+ }
+ }
+ // continue unfolding
+ assert( Abc_AigNodeIsAnd(pObj) );
+ // get new sequential edges
+ assert( Lag + Seq_ObjFaninL0(pObj) < 255 );
+ assert( Lag + Seq_ObjFaninL1(pObj) < 255 );
+ SeqEdge0 = (Abc_ObjFanin0(pObj)->Id << 8) + Lag + Seq_ObjFaninL0(pObj);
+ SeqEdge1 = (Abc_ObjFanin1(pObj)->Id << 8) + Lag + Seq_ObjFaninL1(pObj);
+ // call for the children
+ bFunc0 = Seq_MapMappingConnectBdd_rec( pNtk, SeqEdge0, pObj, 0, pRoot, vLeaves ); Cudd_Ref( bFunc0 );
+ bFunc1 = Seq_MapMappingConnectBdd_rec( pNtk, SeqEdge1, pObj, 1, pRoot, vLeaves ); Cudd_Ref( bFunc1 );
+ bFunc0 = Cudd_NotCond( bFunc0, Abc_ObjFaninC0(pObj) );
+ bFunc1 = Cudd_NotCond( bFunc1, Abc_ObjFaninC1(pObj) );
+ // get the BDD of the node
+ bFunc = Cudd_bddAnd( dd, bFunc0, bFunc1 ); Cudd_Ref( bFunc );
+ Cudd_RecursiveDeref( dd, bFunc0 );
+ Cudd_RecursiveDeref( dd, bFunc1 );
+ // return the BDD
+ Cudd_Deref( bFunc );
+ return bFunc;
+}
+
+////////////////////////////////////////////////////////////////////////
+/// END OF FILE ///
+////////////////////////////////////////////////////////////////////////
+
+
diff --git a/src/base/seq/seqMapIter.c b/src/base/seq/seqMapIter.c
new file mode 100644
index 00000000..30333cea
--- /dev/null
+++ b/src/base/seq/seqMapIter.c
@@ -0,0 +1,623 @@
+/**CFile****************************************************************
+
+ FileName [seqMapIter.c]
+
+ SystemName [ABC: Logic synthesis and verification system.]
+
+ PackageName [Construction and manipulation of sequential AIGs.]
+
+ Synopsis [Iterative delay computation in SC mapping/retiming package.]
+
+ Author [Alan Mishchenko]
+
+ Affiliation [UC Berkeley]
+
+ Date [Ver. 1.0. Started - June 20, 2005.]
+
+ Revision [$Id: seqMapIter.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "seqInt.h"
+#include "main.h"
+#include "mio.h"
+#include "mapperInt.h"
+
+// the internal procedures
+static float Seq_MapRetimeDelayLagsInternal( Abc_Ntk_t * pNtk, int fVerbose );
+static float Seq_MapRetimeSearch_rec( Abc_Ntk_t * pNtk, float FiMin, float FiMax, float Delta, int fVerbose );
+static int Seq_MapRetimeForPeriod( Abc_Ntk_t * pNtk, float Fi, int fVerbose );
+static int Seq_MapNodeUpdateLValue( Abc_Obj_t * pObj, float Fi, float DelayInv );
+static float Seq_MapCollectNode_rec( Abc_Obj_t * pAnd, float FiBest, Vec_Ptr_t * vMapping, Vec_Vec_t * vMapCuts );
+static void Seq_MapCanonicizeTruthTables( Abc_Ntk_t * pNtk );
+
+extern Cut_Man_t * Abc_NtkSeqCuts( Abc_Ntk_t * pNtk, Cut_Params_t * pParams );
+
+////////////////////////////////////////////////////////////////////////
+/// FUNCTION DEFINITIONS ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+ Synopsis [Computes the retiming lags for FPGA mapping.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Seq_MapRetimeDelayLags( Abc_Ntk_t * pNtk, int fVerbose )
+{
+ Abc_Seq_t * p = pNtk->pManFunc;
+ Cut_Params_t Params, * pParams = &Params;
+ Abc_Obj_t * pObj;
+ float TotalArea;
+ int i, clk;
+
+ // set defaults for cut computation
+ memset( pParams, 0, sizeof(Cut_Params_t) );
+ pParams->nVarsMax = p->nVarsMax; // the max cut size ("k" of the k-feasible cuts)
+ pParams->nKeepMax = 1000; // the max number of cuts kept at a node
+ pParams->fTruth = 1; // compute truth tables
+ pParams->fFilter = 1; // filter dominated cuts
+ pParams->fSeq = 1; // compute sequential cuts
+ pParams->fVerbose = fVerbose; // the verbosiness flag
+
+ // compute the cuts
+clk = clock();
+ p->pCutMan = Abc_NtkSeqCuts( pNtk, pParams );
+p->timeCuts = clock() - clk;
+ if ( fVerbose )
+ Cut_ManPrintStats( p->pCutMan );
+
+ // compute canonical forms of the truth tables of the cuts
+ Seq_MapCanonicizeTruthTables( pNtk );
+
+ // compute area flows
+// Seq_MapComputeAreaFlows( pNtk, fVerbose );
+
+ // compute the delays
+clk = clock();
+ p->FiBestFloat = Seq_MapRetimeDelayLagsInternal( pNtk, fVerbose );
+ if ( p->FiBestFloat == 0.0 )
+ return 0;
+p->timeDelay = clock() - clk;
+/*
+ {
+ FILE * pTable;
+ pTable = fopen( "stats.txt", "a+" );
+ fprintf( pTable, "%s ", pNtk->pName );
+ fprintf( pTable, "%.2f ", p->FiBestFloat );
+ fprintf( pTable, "%.2f ", (float)(p->timeCuts)/(float)(CLOCKS_PER_SEC) );
+ fprintf( pTable, "%.2f ", (float)(p->timeDelay)/(float)(CLOCKS_PER_SEC) );
+ fprintf( pTable, "\n" );
+ fclose( pTable );
+ }
+*/
+ // clean the marks
+ Abc_NtkForEachObj( pNtk, pObj, i )
+ assert( !pObj->fMarkA && !pObj->fMarkB );
+
+ // collect the nodes and cuts used in the mapping
+ p->vMapAnds = Vec_PtrAlloc( 1000 );
+ p->vMapCuts = Vec_VecAlloc( 1000 );
+ TotalArea = 0.0;
+ Abc_NtkForEachPo( pNtk, pObj, i )
+ TotalArea += Seq_MapCollectNode_rec( Abc_ObjChild0(pObj), p->FiBestFloat, p->vMapAnds, p->vMapCuts );
+
+ // clean the marks
+ Abc_NtkForEachObj( pNtk, pObj, i )
+ pObj->fMarkA = pObj->fMarkB = 0;
+
+ if ( fVerbose )
+ printf( "Total area = %6.2f.\n", TotalArea );
+
+ // remove the cuts
+ Cut_ManStop( p->pCutMan );
+ p->pCutMan = NULL;
+ return 1;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Retimes AIG for optimal delay using Pan's algorithm.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+float Seq_MapRetimeDelayLagsInternal( Abc_Ntk_t * pNtk, int fVerbose )
+{
+ Abc_Seq_t * p = pNtk->pManFunc;
+ Abc_Obj_t * pNode;
+ float FiMax, FiBest, Delta;
+ int i, RetValue;
+ char NodeLag;
+
+ assert( Abc_NtkIsSeq( pNtk ) );
+
+ // assign the accuracy for min-period computation
+ Delta = Mio_LibraryReadDelayNand2Max(Abc_FrameReadLibGen());
+ if ( Delta == 0.0 )
+ {
+ Delta = Mio_LibraryReadDelayAnd2Max(Abc_FrameReadLibGen());
+ if ( Delta == 0.0 )
+ {
+ printf( "Cannot retime/map if the library does not have NAND2 or AND2.\n" );
+ return 0.0;
+ }
+ }
+
+ // get the upper bound on the clock period
+ FiMax = Delta * (5 + Seq_NtkLevelMax(pNtk));
+ Delta /= 2;
+
+ // make sure this clock period is feasible
+ if ( !Seq_MapRetimeForPeriod( pNtk, FiMax, fVerbose ) )
+ {
+ Vec_StrFill( p->vLags, p->nSize, 0 );
+ Vec_StrFill( p->vLagsN, p->nSize, 0 );
+ printf( "Error: The upper bound on the clock period cannot be computed.\n" );
+ printf( "The reason for this error may be the presence in the circuit of logic\n" );
+ printf( "that is not reachable from the PIs. Mapping/retiming is not performed.\n" );
+ return 0;
+ }
+
+ // search for the optimal clock period between 0 and nLevelMax
+ FiBest = Seq_MapRetimeSearch_rec( pNtk, 0.0, FiMax, Delta, fVerbose );
+
+ // recompute the best l-values
+ RetValue = Seq_MapRetimeForPeriod( pNtk, FiBest, fVerbose );
+ assert( RetValue );
+
+ // fix the problem with non-converged delays
+ Abc_AigForEachAnd( pNtk, pNode, i )
+ {
+ if ( Seq_NodeGetLValueP(pNode) < -ABC_INFINITY/2 )
+ Seq_NodeSetLValueP( pNode, 0 );
+ if ( Seq_NodeGetLValueN(pNode) < -ABC_INFINITY/2 )
+ Seq_NodeSetLValueN( pNode, 0 );
+ }
+
+ // write the retiming lags for both phases of each node
+ Vec_StrFill( p->vLags, p->nSize, 0 );
+ Vec_StrFill( p->vLagsN, p->nSize, 0 );
+ Abc_AigForEachAnd( pNtk, pNode, i )
+ {
+ NodeLag = Seq_NodeComputeLagFloat( Seq_NodeGetLValueP(pNode), FiBest );
+ Seq_NodeSetLag( pNode, NodeLag );
+ NodeLag = Seq_NodeComputeLagFloat( Seq_NodeGetLValueN(pNode), FiBest );
+ Seq_NodeSetLagN( pNode, NodeLag );
+//printf( "%6d=(%d,%d) ", pNode->Id, Seq_NodeGetLag(pNode), Seq_NodeGetLagN(pNode) );
+// if ( Seq_NodeGetLag(pNode) != Seq_NodeGetLagN(pNode) )
+// {
+//printf( "%6d=(%d,%d) ", pNode->Id, Seq_NodeGetLag(pNode), Seq_NodeGetLagN(pNode) );
+// }
+ }
+//printf( "\n\n" );
+
+ // print the result
+ if ( fVerbose )
+ printf( "The best clock period after mapping/retiming is %6.2f.\n", FiBest );
+ return FiBest;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Performs binary search for the optimal clock period.]
+
+ Description [Assumes that FiMin is infeasible while FiMax is feasible.]
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+float Seq_MapRetimeSearch_rec( Abc_Ntk_t * pNtk, float FiMin, float FiMax, float Delta, int fVerbose )
+{
+ float Median;
+ assert( FiMin < FiMax );
+ if ( FiMin + Delta >= FiMax )
+ return FiMax;
+ Median = FiMin + (FiMax - FiMin)/2;
+ if ( Seq_MapRetimeForPeriod( pNtk, Median, fVerbose ) )
+ return Seq_MapRetimeSearch_rec( pNtk, FiMin, Median, Delta, fVerbose ); // Median is feasible
+ else
+ return Seq_MapRetimeSearch_rec( pNtk, Median, FiMax, Delta, fVerbose ); // Median is infeasible
+}
+
+/**Function*************************************************************
+
+ Synopsis [Returns 1 if retiming with this clock period is feasible.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Seq_MapRetimeForPeriod( Abc_Ntk_t * pNtk, float Fi, int fVerbose )
+{
+ Abc_Seq_t * p = pNtk->pManFunc;
+ Abc_Obj_t * pObj;
+ float DelayInv = Mio_LibraryReadDelayInvMax(Abc_FrameReadLibGen());
+ int i, c, RetValue, fChange, Counter;
+ char * pReason = "";
+
+ // set l-values of all nodes to be minus infinity
+ Vec_IntFill( p->vLValues, p->nSize, Abc_Float2Int( (float)-ABC_INFINITY ) );
+ Vec_IntFill( p->vLValuesN, p->nSize, Abc_Float2Int( (float)-ABC_INFINITY ) );
+ Vec_StrFill( p->vUses, p->nSize, 0 );
+
+ // set l-values of constants and PIs
+ pObj = Abc_NtkObj( pNtk, 0 );
+ Seq_NodeSetLValueP( pObj, 0.0 );
+ Seq_NodeSetLValueN( pObj, 0.0 );
+ Abc_NtkForEachPi( pNtk, pObj, i )
+ {
+ Seq_NodeSetLValueP( pObj, 0.0 );
+ Seq_NodeSetLValueN( pObj, DelayInv );
+ }
+
+ // update all values iteratively
+ Counter = 0;
+ for ( c = 0; c < p->nMaxIters; c++ )
+ {
+ fChange = 0;
+ Abc_AigForEachAnd( pNtk, pObj, i )
+ {
+ Counter++;
+ RetValue = Seq_MapNodeUpdateLValue( pObj, Fi, DelayInv );
+ if ( RetValue == SEQ_UPDATE_YES )
+ fChange = 1;
+ }
+ Abc_NtkForEachPo( pNtk, pObj, i )
+ {
+ RetValue = Seq_MapNodeUpdateLValue( pObj, Fi, DelayInv );
+ if ( RetValue == SEQ_UPDATE_FAIL )
+ break;
+ }
+ if ( RetValue == SEQ_UPDATE_FAIL )
+ break;
+ if ( fChange == 0 )
+ break;
+//printf( "\n\n" );
+ }
+ if ( c == p->nMaxIters )
+ {
+ RetValue = SEQ_UPDATE_FAIL;
+ pReason = "(timeout)";
+ }
+ else
+ c++;
+
+ // report the results
+ if ( fVerbose )
+ {
+ if ( RetValue == SEQ_UPDATE_FAIL )
+ printf( "Period = %6.2f. Iterations = %3d. Updates = %10d. Infeasible %s\n", Fi, c, Counter, pReason );
+ else
+ printf( "Period = %6.2f. Iterations = %3d. Updates = %10d. Feasible\n", Fi, c, Counter );
+ }
+ return RetValue != SEQ_UPDATE_FAIL;
+}
+
+
+
+/**Function*************************************************************
+
+ Synopsis [Computes the l-value of the cut.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+float Seq_MapSuperGetArrival( Abc_Obj_t * pObj, float Fi, Seq_Match_t * pMatch, float DelayMax )
+{
+ Abc_Seq_t * p = pObj->pNtk->pManFunc;
+ Abc_Obj_t * pFanin;
+ float lValueCur, lValueMax;
+ int i;
+ lValueMax = -ABC_INFINITY;
+ for ( i = pMatch->pCut->nLeaves - 1; i >= 0; i-- )
+ {
+ // get the arrival time of the fanin
+ pFanin = Abc_NtkObj( pObj->pNtk, pMatch->pCut->pLeaves[i] >> 8 );
+ if ( pMatch->uPhase & (1 << i) )
+ lValueCur = Seq_NodeGetLValueN(pFanin) - Fi * (pMatch->pCut->pLeaves[i] & 255);
+ else
+ lValueCur = Seq_NodeGetLValueP(pFanin) - Fi * (pMatch->pCut->pLeaves[i] & 255);
+ // add the arrival time of this pin
+ if ( lValueMax < lValueCur + pMatch->pSuper->tDelaysR[i].Worst )
+ lValueMax = lValueCur + pMatch->pSuper->tDelaysR[i].Worst;
+ if ( lValueMax < lValueCur + pMatch->pSuper->tDelaysF[i].Worst )
+ lValueMax = lValueCur + pMatch->pSuper->tDelaysF[i].Worst;
+ if ( lValueMax > DelayMax + p->fEpsilon )
+ return ABC_INFINITY;
+ }
+ return lValueMax;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Computes the l-value of the cut.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+float Seq_MapNodeComputeCut( Abc_Obj_t * pObj, Cut_Cut_t * pCut, int fCompl, float Fi, Seq_Match_t * pMatchBest )
+{
+ Seq_Match_t Match, * pMatchCur = &Match;
+ Abc_Seq_t * p = pObj->pNtk->pManFunc;
+ Map_Super_t * pSuper, * pSuperList;
+ unsigned uCanon[2];
+ float lValueBest, lValueCur;
+ int i;
+ assert( pCut->nLeaves < 6 );
+ // get the canonical truth table of this cut
+ uCanon[0] = uCanon[1] = (fCompl? pCut->uCanon0 : pCut->uCanon1);
+ if ( uCanon[0] == 0 || ~uCanon[0] == 0 )
+ {
+ if ( pMatchBest )
+ {
+ memset( pMatchBest, 0, sizeof(Seq_Match_t) );
+ pMatchBest->pCut = pCut;
+ }
+ return (float)0.0;
+ }
+ // match the given phase of the cut
+ pSuperList = Map_SuperTableLookupC( p->pSuperLib, uCanon );
+ // compute the arrival times of each supergate
+ lValueBest = ABC_INFINITY;
+ for ( pSuper = pSuperList; pSuper; pSuper = pSuper->pNext )
+ {
+ // create the match
+ pMatchCur->pCut = pCut;
+ pMatchCur->pSuper = pSuper;
+ // get the phase
+ for ( i = 0; i < (int)pSuper->nPhases; i++ )
+ {
+ pMatchCur->uPhase = (fCompl? pCut->Num0 : pCut->Num1) ^ pSuper->uPhases[i];
+ // find the arrival time of this match
+ lValueCur = Seq_MapSuperGetArrival( pObj, Fi, pMatchCur, lValueBest );
+ if ( lValueBest > lValueCur )//&& lValueCur > -ABC_INFINITY/2 )
+ {
+ lValueBest = lValueCur;
+ if ( pMatchBest )
+ *pMatchBest = *pMatchCur;
+ }
+ }
+ }
+// assert( lValueBest < ABC_INFINITY/2 );
+ return lValueBest;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Computes the l-value of the node.]
+
+ Description [The node can be internal or a PO.]
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+float Seq_MapNodeComputePhase( Abc_Obj_t * pObj, int fCompl, float Fi, Seq_Match_t * pMatchBest )
+{
+ Seq_Match_t Match, * pMatchCur = &Match;
+ Cut_Cut_t * pList, * pCut;
+ float lValueBest, lValueCut;
+ // get the list of cuts
+ pList = Abc_NodeReadCuts( Seq_NodeCutMan(pObj), pObj );
+ // get the arrival time of the best non-trivial cut
+ lValueBest = ABC_INFINITY;
+ for ( pCut = pList->pNext; pCut; pCut = pCut->pNext )
+ {
+ lValueCut = Seq_MapNodeComputeCut( pObj, pCut, fCompl, Fi, pMatchBest? pMatchCur : NULL );
+ if ( lValueBest > lValueCut )
+ {
+ lValueBest = lValueCut;
+ if ( pMatchBest )
+ *pMatchBest = *pMatchCur;
+ }
+ }
+// assert( lValueBest < ABC_INFINITY/2 );
+ return lValueBest;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Computes the l-value of the node.]
+
+ Description [The node can be internal or a PO.]
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Seq_MapNodeUpdateLValue( Abc_Obj_t * pObj, float Fi, float DelayInv )
+{
+ Abc_Seq_t * p = pObj->pNtk->pManFunc;
+ Cut_Cut_t * pList;
+ char Use;
+ float lValueOld0, lValueOld1, lValue0, lValue1, lValue;
+ assert( !Abc_ObjIsPi(pObj) );
+ assert( Abc_ObjFaninNum(pObj) > 0 );
+ // consider the case of the PO
+ if ( Abc_ObjIsPo(pObj) )
+ {
+ if ( Abc_ObjFaninC0(pObj) ) // PO requires negative polarity
+ lValue = Seq_NodeGetLValueN(Abc_ObjFanin0(pObj)) - Fi * Seq_ObjFaninL0(pObj);
+ else
+ lValue = Seq_NodeGetLValueP(Abc_ObjFanin0(pObj)) - Fi * Seq_ObjFaninL0(pObj);
+ return (lValue > Fi + p->fEpsilon)? SEQ_UPDATE_FAIL : SEQ_UPDATE_NO;
+ }
+ // get the cuts
+ pList = Abc_NodeReadCuts( Seq_NodeCutMan(pObj), pObj );
+ if ( pList == NULL )
+ return SEQ_UPDATE_NO;
+ // compute the arrival time of both phases
+ lValue0 = Seq_MapNodeComputePhase( pObj, 1, Fi, NULL );
+ lValue1 = Seq_MapNodeComputePhase( pObj, 0, Fi, NULL );
+ // consider the case when negative phase is too slow
+ if ( lValue0 > lValue1 + DelayInv + p->fEpsilon )
+ lValue0 = lValue1 + DelayInv, Use = 2;
+ else if ( lValue1 > lValue0 + DelayInv + p->fEpsilon )
+ lValue1 = lValue0 + DelayInv, Use = 1;
+ else
+ Use = 3;
+ // set the uses of the phases
+ Seq_NodeSetUses( pObj, Use );
+ // get the old arrival times
+ lValueOld0 = Seq_NodeGetLValueN(pObj);
+ lValueOld1 = Seq_NodeGetLValueP(pObj);
+ // compare
+ if ( lValue0 <= lValueOld0 + p->fEpsilon && lValue1 <= lValueOld1 + p->fEpsilon )
+ return SEQ_UPDATE_NO;
+ assert( lValue0 < ABC_INFINITY/2 );
+ assert( lValue1 < ABC_INFINITY/2 );
+ // update the values
+ if ( lValue0 > lValueOld0 + p->fEpsilon )
+ Seq_NodeSetLValueN( pObj, lValue0 );
+ if ( lValue1 > lValueOld1 + p->fEpsilon )
+ Seq_NodeSetLValueP( pObj, lValue1 );
+//printf( "%6d=(%4.2f,%4.2f) ", pObj->Id, Seq_NodeGetLValueP(pObj), Seq_NodeGetLValueN(pObj) );
+ return SEQ_UPDATE_YES;
+}
+
+
+
+/**Function*************************************************************
+
+ Synopsis [Derives the parameters of the best mapping/retiming for one node.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+float Seq_MapCollectNode_rec( Abc_Obj_t * pAnd, float FiBest, Vec_Ptr_t * vMapping, Vec_Vec_t * vMapCuts )
+{
+ Seq_Match_t * pMatch;
+ Abc_Obj_t * pFanin;
+ int k, fCompl, Use;
+ float AreaInv = Mio_LibraryReadAreaInv(Abc_FrameReadLibGen());
+ float Area;
+
+ // get the polarity of the node
+ fCompl = Abc_ObjIsComplement(pAnd);
+ pAnd = Abc_ObjRegular(pAnd);
+
+ // skip visited nodes
+ if ( !fCompl )
+ { // need the positive polarity
+ if ( pAnd->fMarkA )
+ return 0.0;
+ pAnd->fMarkA = 1;
+ }
+ else
+ { // need the negative polarity
+ if ( pAnd->fMarkB )
+ return 0.0;
+ pAnd->fMarkB = 1;
+ }
+
+ // skip if this is a PI or a constant
+ if ( !Abc_AigNodeIsAnd(pAnd) )
+ {
+ if ( Abc_ObjIsPi(pAnd) && fCompl )
+ return AreaInv;
+ return 0.0;
+ }
+
+ // check the uses of this node
+ Use = Seq_NodeGetUses( pAnd );
+ if ( !fCompl && Use == 1 ) // the pos phase is required; only the neg phase is used
+ {
+ Area = Seq_MapCollectNode_rec( Abc_ObjNot(pAnd), FiBest, vMapping, vMapCuts );
+ return Area + AreaInv;
+ }
+ if ( fCompl && Use == 2 ) // the neg phase is required; only the pos phase is used
+ {
+ Area = Seq_MapCollectNode_rec( pAnd, FiBest, vMapping, vMapCuts );
+ return Area + AreaInv;
+ }
+ // both phases are used; the needed one can be selected
+
+ // get the best match
+ pMatch = ALLOC( Seq_Match_t, 1 );
+ memset( pMatch, 1, sizeof(Seq_Match_t) );
+ Seq_MapNodeComputePhase( pAnd, fCompl, FiBest, pMatch );
+ pMatch->pAnd = pAnd;
+ pMatch->fCompl = fCompl;
+ pMatch->fCutInv = pMatch->pCut->fCompl;
+ pMatch->PolUse = Use;
+
+ // call for the fanin cuts
+ Area = pMatch->pSuper? pMatch->pSuper->Area : (float)0.0;
+ for ( k = 0; k < (int)pMatch->pCut->nLeaves; k++ )
+ {
+ pFanin = Abc_NtkObj( pAnd->pNtk, pMatch->pCut->pLeaves[k] >> 8 );
+ if ( pMatch->uPhase & (1 << k) )
+ pFanin = Abc_ObjNot( pFanin );
+ Area += Seq_MapCollectNode_rec( pFanin, FiBest, vMapping, vMapCuts );
+ }
+
+ // add this node
+ Vec_PtrPush( vMapping, pMatch );
+ for ( k = 0; k < (int)pMatch->pCut->nLeaves; k++ )
+ Vec_VecPush( vMapCuts, Vec_PtrSize(vMapping)-1, (void *)pMatch->pCut->pLeaves[k] );
+
+ // the cut will become unavailable when the cuts are deallocated
+ pMatch->pCut = NULL;
+
+ return Area;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Computes the canonical versions of the truth tables.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Seq_MapCanonicizeTruthTables( Abc_Ntk_t * pNtk )
+{
+ Abc_Obj_t * pObj;
+ Cut_Cut_t * pCut, * pList;
+ int i;
+ Abc_AigForEachAnd( pNtk, pObj, i )
+ {
+ pList = Abc_NodeReadCuts( Seq_NodeCutMan(pObj), pObj );
+ if ( pList == NULL )
+ continue;
+ for ( pCut = pList->pNext; pCut; pCut = pCut->pNext )
+ Cut_TruthNCanonicize( pCut );
+ }
+}
+
+
+////////////////////////////////////////////////////////////////////////
+/// END OF FILE ///
+////////////////////////////////////////////////////////////////////////
diff --git a/src/base/seq/seqMaxMeanCycle.c b/src/base/seq/seqMaxMeanCycle.c
new file mode 100644
index 00000000..46d73cbd
--- /dev/null
+++ b/src/base/seq/seqMaxMeanCycle.c
@@ -0,0 +1,567 @@
+/**CFile****************************************************************
+
+ FileName [seqMaxMeanCycle.c]
+
+ SystemName [ABC: Logic synthesis and verification system.]
+
+ PackageName [Construction and manipulation of sequential AIGs.]
+
+ Synopsis [Efficient computation of maximum mean cycle times.]
+
+ Author [Aaron P. Hurst]
+
+ Affiliation [UC Berkeley]
+
+ Date [Ver. 1.0. Started - May 15, 2006.]
+
+ Revision [$Id: seqMaxMeanCycle.c,v 1.00 2005/05/15 00:00:00 ahurst Exp $]
+
+***********************************************************************/
+
+#include "seqInt.h"
+#include "hash.h"
+
+////////////////////////////////////////////////////////////////////////
+/// DECLARATIONS ///
+////////////////////////////////////////////////////////////////////////
+
+struct Abc_ManTime_t_
+{
+ Abc_Time_t tArrDef;
+ Abc_Time_t tReqDef;
+ Vec_Ptr_t * vArrs;
+ Vec_Ptr_t * vReqs;
+};
+
+typedef struct Seq_HowardData_t_
+{
+ char visited;
+ int mark;
+ int policy;
+ float cycle;
+ float skew;
+ float delay;
+} Seq_HowardData_t;
+
+// accessing the arrival and required times of a node
+static inline Abc_Time_t * Abc_NodeArrival( Abc_Obj_t * pNode ) { return pNode->pNtk->pManTime->vArrs->pArray[pNode->Id]; }
+static inline Abc_Time_t * Abc_NodeRequired( Abc_Obj_t * pNode ) { return pNode->pNtk->pManTime->vReqs->pArray[pNode->Id]; }
+
+Hash_Ptr_t * Seq_NtkPathDelays( Abc_Ntk_t * pNtk, int fVerbose );
+void Seq_NtkMergePios( Abc_Ntk_t * pNtk, Hash_Ptr_t * hFwdDelays, int fVerbose );
+
+void Seq_NtkHowardLoop( Abc_Ntk_t * pNtk, Hash_Ptr_t * hFwdDelays,
+ Hash_Ptr_t * hNodeData, int node,
+ int *howardDepth, float *howardDelay, int *howardSink,
+ float *maxMeanCycle);
+void Abc_NtkDfsReverse_rec2( Abc_Obj_t * pNode, Vec_Ptr_t * vNodes, Vec_Ptr_t * vEndpoints );
+
+#define Seq_NtkGetPathDelay( hFwdDelays, from, to ) \
+ (Hash_PtrExists(hFwdDelays, from)?Hash_FltEntry( ((Hash_Flt_t *)Hash_PtrEntry(hFwdDelays, from, 0)), to, 0):0 )
+
+#define HOWARD_EPSILON 1e-3
+#define ZERO_SLOP 1e-5
+#define REMOVE_ZERO_SLOP( x ) \
+ (x = (x > -ZERO_SLOP && x < ZERO_SLOP)?0:x)
+
+////////////////////////////////////////////////////////////////////////
+/// FUNCTION DEFINITIONS ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+ Synopsis [Computes maximum mean cycle time.]
+
+ Description [Uses Howard's algorithm.]
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+float Seq_NtkHoward( Abc_Ntk_t * pNtk, int fVerbose ) {
+
+ Abc_Obj_t * pObj;
+ Hash_Ptr_t * hFwdDelays;
+ Hash_Flt_t * hOutgoing;
+ Hash_Ptr_Entry_t * pSourceEntry, * pNodeEntry;
+ Hash_Flt_Entry_t * pSinkEntry;
+ int i, j, iteration = 0;
+ int source, sink;
+ int fChanged;
+ int howardDepth, howardSink = 0;
+ float delay, howardDelay, t;
+ float maxMeanCycle = -ABC_INFINITY;
+ Hash_Ptr_t * hNodeData;
+ Seq_HowardData_t * pNodeData, * pSourceData, * pSinkData;
+
+ // gather timing constraints
+ hFwdDelays = Seq_NtkPathDelays( pNtk, fVerbose );
+ Seq_NtkMergePios( pNtk, hFwdDelays, fVerbose );
+
+ // initialize data, create initial policy
+ hNodeData = Hash_PtrAlloc( hFwdDelays->nSize );
+ Hash_PtrForEachEntry( hFwdDelays, pSourceEntry, i ) {
+ Hash_PtrWriteEntry( hNodeData, pSourceEntry->key,
+ (pNodeData = ALLOC(Seq_HowardData_t, 1)) );
+ pNodeData->skew = 0.0;
+ pNodeData->policy = 0;
+ hOutgoing = (Hash_Flt_t *)(pSourceEntry->data);
+ assert(hOutgoing);
+
+ Hash_FltForEachEntry( hOutgoing, pSinkEntry, j ) {
+ sink = pSinkEntry->key;
+ delay = pSinkEntry->data;
+ if (delay > pNodeData->skew) {
+ pNodeData->policy = sink;
+ pNodeData->skew = delay;
+ }
+ }
+ }
+
+ // iteratively refine policy
+ do {
+ iteration++;
+ fChanged = 0;
+ howardDelay = 0.0;
+ howardDepth = 0;
+
+ // reset data
+ Hash_PtrForEachEntry( hNodeData, pNodeEntry, i ) {
+ pNodeData = (Seq_HowardData_t *)pNodeEntry->data;
+ pNodeData->skew = -ABC_INFINITY;
+ pNodeData->cycle = -ABC_INFINITY;
+ pNodeData->mark = 0;
+ pNodeData->visited = 0;
+ }
+
+ // find loops in policy graph
+ Hash_PtrForEachEntry( hNodeData, pNodeEntry, i ) {
+ pNodeData = (Seq_HowardData_t *)(pNodeEntry->data);
+ assert(pNodeData);
+ if (!pNodeData->visited)
+ Seq_NtkHowardLoop( pNtk, hFwdDelays,
+ hNodeData, pNodeEntry->key,
+ &howardDepth, &howardDelay, &howardSink, &maxMeanCycle);
+ }
+
+ if (!howardSink) {
+ return -1;
+ }
+
+ // improve policy by tightening loops
+ Hash_PtrForEachEntry( hFwdDelays, pSourceEntry, i ) {
+ source = pSourceEntry->key;
+ pSourceData = (Seq_HowardData_t *)Hash_PtrEntry( hNodeData, source, 0 );
+ assert(pSourceData);
+ hOutgoing = (Hash_Flt_t *)(pSourceEntry->data);
+ assert(hOutgoing);
+ Hash_FltForEachEntry( hOutgoing, pSinkEntry, j ) {
+ sink = pSinkEntry->key;
+ pSinkData = (Seq_HowardData_t *)Hash_PtrEntry( hNodeData, sink, 0 );
+ assert(pSinkData);
+ delay = pSinkEntry->data;
+
+ if (pSinkData->cycle > pSourceData->cycle + HOWARD_EPSILON) {
+ fChanged = 1;
+ pSourceData->cycle = pSinkData->cycle;
+ pSourceData->policy = sink;
+ }
+ }
+ }
+
+ // improve policy by correcting skews
+ if (!fChanged) {
+ Hash_PtrForEachEntry( hFwdDelays, pSourceEntry, i ) {
+ source = pSourceEntry->key;
+ pSourceData = (Seq_HowardData_t *)Hash_PtrEntry( hNodeData, source, 0 );
+ assert(pSourceData);
+ hOutgoing = (Hash_Flt_t *)(pSourceEntry->data);
+ assert(hOutgoing);
+ Hash_FltForEachEntry( hOutgoing, pSinkEntry, j ) {
+ sink = pSinkEntry->key;
+ pSinkData = (Seq_HowardData_t *)Hash_PtrEntry( hNodeData, sink, 0 );
+ assert(pSinkData);
+ delay = pSinkEntry->data;
+
+ if (pSinkData->cycle < 0.0 || pSinkData->cycle < pSourceData->cycle)
+ continue;
+
+ t = delay - pSinkData->cycle + pSinkData->skew;
+ if (t > pSourceData->skew + HOWARD_EPSILON) {
+ fChanged = 1;
+ pSourceData->skew = t;
+ pSourceData->policy = sink;
+ }
+ }
+ }
+ }
+
+ if (fVerbose) printf("Iteration %d \t Period = %.2f\n", iteration, maxMeanCycle);
+ } while (fChanged);
+
+ // set global skew, mmct
+ pNodeData = Hash_PtrEntry( hNodeData, -1, 0 );
+ pNtk->globalSkew = -pNodeData->skew;
+ pNtk->maxMeanCycle = maxMeanCycle;
+
+ // set endpoint skews
+ Vec_FltGrow( pNtk->vSkews, Abc_NtkLatchNum( pNtk ) );
+ pNtk->vSkews->nSize = Abc_NtkLatchNum( pNtk );
+ Abc_NtkForEachLatch( pNtk, pObj, i ) {
+ pNodeData = Hash_PtrEntry( hNodeData, pObj->Id, 0 );
+ // skews are set based on latch # NOT id #
+ Abc_NtkSetLatSkew( pNtk, i, pNodeData->skew );
+ }
+
+ // free node data
+ Hash_PtrForEachEntry( hNodeData, pNodeEntry, i ) {
+ pNodeData = (Seq_HowardData_t *)(pNodeEntry->data);
+ FREE( pNodeData );
+ }
+ Hash_PtrFree(hNodeData);
+
+ // free delay data
+ Hash_PtrForEachEntry( hFwdDelays, pSourceEntry, i ) {
+ Hash_FltFree( (Hash_Flt_t *)(pSourceEntry->data) );
+ }
+ Hash_PtrFree(hFwdDelays);
+
+ return maxMeanCycle;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Computes the mean cycle times of current policy graph.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Seq_NtkHowardLoop( Abc_Ntk_t * pNtk, Hash_Ptr_t * hFwdDelays,
+ Hash_Ptr_t * hNodeData, int node,
+ int *howardDepth, float *howardDelay, int *howardSink,
+ float *maxMeanCycle) {
+
+ Seq_HowardData_t * pNodeData, *pToData;
+ float delay, t;
+
+ pNodeData = (Seq_HowardData_t *)Hash_PtrEntry( hNodeData, node, 0 );
+ assert(pNodeData);
+ pNodeData->visited = 1;
+ pNodeData->mark = ++(*howardDepth);
+ pNodeData->delay = (*howardDelay);
+ if (pNodeData->policy) {
+ pToData = (Seq_HowardData_t *)Hash_PtrEntry( hNodeData, pNodeData->policy, 0 );
+ assert(pToData);
+ delay = Seq_NtkGetPathDelay( hFwdDelays, node, pNodeData->policy );
+ assert(delay > 0.0);
+ (*howardDelay) += delay;
+ if (pToData->mark) {
+ t = (*howardDelay - pToData->delay) / (*howardDepth - pToData->mark + 1);
+ pNodeData->cycle = t;
+ pNodeData->skew = 0.0;
+ if (*maxMeanCycle < t) {
+ *maxMeanCycle = t;
+ *howardSink = pNodeData->policy;
+ }
+ } else {
+ if(!pToData->visited) {
+ Seq_NtkHowardLoop(pNtk, hFwdDelays, hNodeData, pNodeData->policy,
+ howardDepth, howardDelay, howardSink, maxMeanCycle);
+ }
+ if(pToData->cycle > 0) {
+ t = delay - pToData->cycle + pToData->skew;
+ pNodeData->skew = t;
+ pNodeData->cycle = pToData->cycle;
+ }
+ }
+ }
+ *howardDelay = pNodeData->delay;
+ pNodeData->mark = 0;
+ --(*howardDepth);
+}
+
+/**Function*************************************************************
+
+ Synopsis [Computes the register-to-register delays.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Hash_Ptr_t * Seq_NtkPathDelays( Abc_Ntk_t * pNtk, int fVerbose ) {
+
+ Abc_Time_t * pTime, ** ppTimes;
+ Abc_Obj_t * pObj, * pDriver, * pStart, * pFanout;
+ Vec_Ptr_t * vNodes, * vEndpoints;
+ int i, j, nPaths = 0;
+ Hash_Flt_t * hOutgoing;
+ Hash_Ptr_t * hFwdDelays;
+ float nMaxPath = 0, nSumPath = 0;
+
+ extern void Abc_NtkTimePrepare( Abc_Ntk_t * pNtk );
+ extern void Abc_NodeDelayTraceArrival( Abc_Obj_t * pNode );
+
+ if (fVerbose) printf("Gathering path delays...\n");
+
+ hFwdDelays = Hash_PtrAlloc( Abc_NtkCiNum( pNtk ) );
+
+ assert( Abc_NtkIsMappedLogic(pNtk) );
+
+ Abc_NtkTimePrepare( pNtk );
+ ppTimes = (Abc_Time_t **)pNtk->pManTime->vArrs->pArray;
+ vNodes = Vec_PtrAlloc( 100 );
+ vEndpoints = Vec_PtrAlloc( 100 );
+
+ // set the initial times (i.e. ignore all inputs)
+ Abc_NtkForEachObj( pNtk, pObj, i) {
+ pTime = ppTimes[pObj->Id];
+ pTime->Fall = pTime->Rise = pTime->Worst = -ABC_INFINITY;
+ }
+
+ // starting at each Ci, compute timing forward
+ Abc_NtkForEachCi( pNtk, pStart, j ) {
+
+ hOutgoing = Hash_FltAlloc( 10 );
+ Hash_PtrWriteEntry( hFwdDelays, pStart->Id, (void *)(hOutgoing) );
+
+ // seed the starting point of interest
+ pTime = ppTimes[pStart->Id];
+ pTime->Fall = pTime->Rise = pTime->Worst = 0.0;
+
+ // find a DFS ordering from the start
+ Abc_NtkIncrementTravId( pNtk );
+ Abc_NodeSetTravIdCurrent( pStart );
+ pObj = Abc_ObjFanout0Ntk(pStart);
+ Abc_ObjForEachFanout( pObj, pFanout, i )
+ Abc_NtkDfsReverse_rec2( pFanout, vNodes, vEndpoints );
+ if ( Abc_ObjIsCo( pStart ) )
+ Vec_PtrPush( vEndpoints, pStart );
+
+ // do timing analysis
+ for ( i = vNodes->nSize-1; i >= 0; --i )
+ Abc_NodeDelayTraceArrival( vNodes->pArray[i] );
+
+ // there is a path to each set of Co endpoints
+ Vec_PtrForEachEntry( vEndpoints, pObj, i )
+ {
+ assert(pObj);
+ assert( Abc_ObjIsCo( pObj ) );
+ pDriver = Abc_ObjFanin0(pObj);
+ pTime = Abc_NodeArrival(pDriver);
+ if ( pTime->Worst > 0 ) {
+ Hash_FltWriteEntry( hOutgoing, pObj->Id, pTime->Worst );
+ nPaths++;
+ // if (fVerbose) printf("\tpath %d,%d delay = %f\n", pStart->Id, pObj->Id, pTime->Worst);
+ nSumPath += pTime->Worst;
+ if (pTime->Worst > nMaxPath)
+ nMaxPath = pTime->Worst;
+ }
+ }
+
+ // clear the times that were altered
+ for ( i = 0; i < vNodes->nSize; i++ ) {
+ pObj = (Abc_Obj_t *)(vNodes->pArray[i]);
+ pTime = ppTimes[pObj->Id];
+ pTime->Fall = pTime->Rise = pTime->Worst = -ABC_INFINITY;
+ }
+ pTime = ppTimes[pStart->Id];
+ pTime->Fall = pTime->Rise = pTime->Worst = -ABC_INFINITY;
+
+ Vec_PtrClear( vNodes );
+ Vec_PtrClear( vEndpoints );
+ }
+
+ Vec_PtrFree( vNodes );
+
+ // rezero Cis (note: these should be restored to values if they were nonzero)
+ Abc_NtkForEachCi( pNtk, pObj, i) {
+ pTime = ppTimes[pObj->Id];
+ pTime->Fall = pTime->Rise = pTime->Worst = 0.0;
+ }
+
+ if (fVerbose) printf("Num. paths = %d\tMax. Path Delay = %.2f\tAvg. Path Delay = %.2f\n", nPaths, nMaxPath, nSumPath / nPaths);
+ return hFwdDelays;
+}
+
+
+/**Function*************************************************************
+
+ Synopsis [Merges all the Pios together into one ID = -1.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Seq_NtkMergePios( Abc_Ntk_t * pNtk, Hash_Ptr_t * hFwdDelays,
+ int fVerbose ) {
+
+ Abc_Obj_t * pObj;
+ Hash_Flt_Entry_t * pSinkEntry;
+ Hash_Ptr_Entry_t * pSourceEntry;
+ Hash_Flt_t * hOutgoing, * hPioSource;
+ int i, j;
+ int source, sink, nMerges = 0;
+ float delay = 0, max_delay = 0;
+ Vec_Int_t * vFreeList;
+
+ vFreeList = Vec_IntAlloc( 10 );
+
+ // create a new "-1" source entry for the Pios
+ hPioSource = Hash_FltAlloc( 100 );
+ Hash_PtrWriteEntry( hFwdDelays, -1, (void *)(hPioSource) );
+
+ // merge all edges with a Pio as a source
+ Abc_NtkForEachPi( pNtk, pObj, i ) {
+ source = pObj->Id;
+ hOutgoing = (Hash_Flt_t *)Hash_PtrEntry( hFwdDelays, source, 0 );
+ if (!hOutgoing) continue;
+
+ Hash_PtrForEachEntry( hOutgoing, pSinkEntry, j ) {
+ nMerges++;
+ sink = pSinkEntry->key;
+ delay = pSinkEntry->data;
+ if (Hash_FltEntry( hPioSource, sink, 1 ) < delay) {
+ Hash_FltWriteEntry( hPioSource, sink, delay );
+ }
+ }
+
+ Hash_FltFree( hOutgoing );
+ Hash_PtrRemove( hFwdDelays, source );
+ }
+
+ // merge all edges with a Pio as a sink
+ Hash_PtrForEachEntry( hFwdDelays, pSourceEntry, i ) {
+ hOutgoing = (Hash_Flt_t *)(pSourceEntry->data);
+ Hash_FltForEachEntry( hOutgoing, pSinkEntry, j ) {
+ sink = pSinkEntry->key;
+ delay = pSinkEntry->data;
+
+ max_delay = -ABC_INFINITY;
+ if (Abc_ObjIsPo( Abc_NtkObj( pNtk, sink ) )) {
+ nMerges++;
+ if (delay > max_delay)
+ max_delay = delay;
+ Vec_IntPush( vFreeList, sink );
+ }
+ }
+ if (max_delay != -ABC_INFINITY)
+ Hash_FltWriteEntry( hOutgoing, -1, delay );
+ // do freeing
+ while( vFreeList->nSize > 0 ) {
+ Hash_FltRemove( hOutgoing, Vec_IntPop( vFreeList ) );
+ }
+ }
+
+ if (fVerbose) printf("Merged %d paths into one Pio node\n", nMerges);
+
+}
+
+/**Function*************************************************************
+
+ Synopsis [This is a modification of routine from abcDfs.c]
+
+ Description [Recursive DFS from a starting point. Keeps the endpoints.]
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Abc_NtkDfsReverse_rec2( Abc_Obj_t * pNode, Vec_Ptr_t * vNodes, Vec_Ptr_t * vEndpoints )
+{
+ Abc_Obj_t * pFanout;
+ int i;
+ assert( !Abc_ObjIsNet(pNode) );
+ // if this node is already visited, skip
+ if ( Abc_NodeIsTravIdCurrent( pNode ) )
+ return;
+ // mark the node as visited
+ Abc_NodeSetTravIdCurrent( pNode );
+ // terminate at the Co
+ if ( Abc_ObjIsCo(pNode) ) {
+ Vec_PtrPush( vEndpoints, pNode );
+ return;
+ }
+ assert( Abc_ObjIsNode( pNode ) );
+ // visit the transitive fanin of the node
+ pNode = Abc_ObjFanout0Ntk(pNode);
+ Abc_ObjForEachFanout( pNode, pFanout, i )
+ Abc_NtkDfsReverse_rec2( pFanout, vNodes, vEndpoints );
+ // add the node after the fanins have been added
+ Vec_PtrPush( vNodes, pNode );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Converts all skews into forward skews 0<skew<T.]
+
+ Description [Can also minimize total skew by changing global skew.]
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Seq_NtkSkewForward( Abc_Ntk_t * pNtk, float period, int fMinimize ) {
+
+ Abc_Obj_t * pObj;
+ int i;
+ float skew;
+ float currentSum = 0, bestSum = ABC_INFINITY;
+ float currentOffset = 0, nextStep, bestOffset = 0;
+
+ assert( pNtk->vSkews->nSize >= Abc_NtkLatchNum( pNtk )-1 );
+
+ if (fMinimize) {
+ // search all offsets for the one that minimizes sum of skews
+ while(currentOffset < period) {
+ currentSum = 0;
+ nextStep = period;
+ Abc_NtkForEachLatch( pNtk, pObj, i ) {
+ skew = Abc_NtkGetLatSkew( pNtk, i ) + currentOffset;
+ skew = (float)(skew - period*floor(skew/period));
+ currentSum += skew;
+ if (skew > ZERO_SLOP && skew < nextStep) {
+ nextStep = skew;
+ }
+ }
+
+ if (currentSum < bestSum) {
+ bestSum = currentSum;
+ bestOffset = currentOffset;
+ }
+ currentOffset += nextStep;
+ }
+ printf("Offseting all skews by %.2f\n", bestOffset);
+ }
+
+ // convert global skew into forward skew
+ pNtk->globalSkew = pNtk->globalSkew - bestOffset;
+ pNtk->globalSkew = (float)(pNtk->globalSkew - period*floor(pNtk->globalSkew/period));
+ assert(pNtk->globalSkew>= 0 && pNtk->globalSkew < period);
+
+ // convert endpoint skews into forward skews
+ Abc_NtkForEachLatch( pNtk, pObj, i ) {
+ skew = Abc_NtkGetLatSkew( pNtk, i ) + bestOffset;
+ skew = (float)(skew - period*floor(skew/period));
+ REMOVE_ZERO_SLOP( skew );
+ assert(skew >=0 && skew < period);
+
+ Abc_NtkSetLatSkew( pNtk, i, skew );
+ }
+}
+
+////////////////////////////////////////////////////////////////////////
+/// END OF FILE ///
+////////////////////////////////////////////////////////////////////////
diff --git a/src/base/seq/seqRetCore.c b/src/base/seq/seqRetCore.c
new file mode 100644
index 00000000..ddc92cc8
--- /dev/null
+++ b/src/base/seq/seqRetCore.c
@@ -0,0 +1,493 @@
+/**CFile****************************************************************
+
+ FileName [seqRetCore.c]
+
+ SystemName [ABC: Logic synthesis and verification system.]
+
+ PackageName [Construction and manipulation of sequential AIGs.]
+
+ Synopsis [The core of FPGA mapping/retiming package.]
+
+ Author [Alan Mishchenko]
+
+ Affiliation [UC Berkeley]
+
+ Date [Ver. 1.0. Started - June 20, 2005.]
+
+ Revision [$Id: seqRetCore.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "seqInt.h"
+#include "dec.h"
+
+////////////////////////////////////////////////////////////////////////
+/// DECLARATIONS ///
+////////////////////////////////////////////////////////////////////////
+
+static Abc_Ntk_t * Seq_NtkRetimeDerive( Abc_Ntk_t * pNtk, int fVerbose );
+static Abc_Obj_t * Seq_NodeRetimeDerive( Abc_Ntk_t * pNtkNew, Abc_Obj_t * pNode, char * pSop, Vec_Ptr_t * vFanins );
+static Abc_Ntk_t * Seq_NtkRetimeReconstruct( Abc_Ntk_t * pNtkOld, Abc_Ntk_t * pNtkSeq );
+static Abc_Obj_t * Seq_EdgeReconstruct_rec( Abc_Obj_t * pGoal, Abc_Obj_t * pNode );
+static Abc_Obj_t * Seq_EdgeReconstructPO( Abc_Obj_t * pNode );
+
+////////////////////////////////////////////////////////////////////////
+/// FUNCTION DEFINITIONS ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+ Synopsis [Performs FPGA mapping and retiming.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Abc_Ntk_t * Seq_NtkRetime( Abc_Ntk_t * pNtk, int nMaxIters, int fInitial, int fVerbose )
+{
+ Abc_Seq_t * p;
+ Abc_Ntk_t * pNtkSeq, * pNtkNew;
+ int RetValue;
+ assert( !Abc_NtkHasAig(pNtk) );
+ // derive the isomorphic seq AIG
+ pNtkSeq = Seq_NtkRetimeDerive( pNtk, fVerbose );
+ p = pNtkSeq->pManFunc;
+ p->nMaxIters = nMaxIters;
+
+ if ( !fInitial )
+ Seq_NtkLatchSetValues( pNtkSeq, ABC_INIT_DC );
+ // find the best mapping and retiming
+ if ( !Seq_NtkRetimeDelayLags( pNtk, pNtkSeq, fVerbose ) )
+ return NULL;
+
+ // implement the retiming
+ RetValue = Seq_NtkImplementRetiming( pNtkSeq, p->vLags, fVerbose );
+ if ( RetValue == 0 )
+ printf( "Retiming completed but initial state computation has failed.\n" );
+//return pNtkSeq;
+
+ // create the final mapped network
+ pNtkNew = Seq_NtkRetimeReconstruct( pNtk, pNtkSeq );
+ Abc_NtkDelete( pNtkSeq );
+ return pNtkNew;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Derives the isomorphic seq AIG.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Abc_Ntk_t * Seq_NtkRetimeDerive( Abc_Ntk_t * pNtk, int fVerbose )
+{
+ Abc_Seq_t * p;
+ Abc_Ntk_t * pNtkNew;
+ Abc_Obj_t * pObj, * pFanin, * pMirror;
+ Vec_Ptr_t * vMapAnds, * vMirrors;
+ Vec_Vec_t * vMapFanins;
+ int i, k, RetValue, fHasBdds;
+ char * pSop;
+
+ // make sure it is an AIG without self-feeding latches
+ assert( !Abc_NtkHasAig(pNtk) );
+ if ( RetValue = Abc_NtkRemoveSelfFeedLatches(pNtk) )
+ printf( "Modified %d self-feeding latches. The result may not verify.\n", RetValue );
+ assert( Abc_NtkCountSelfFeedLatches(pNtk) == 0 );
+
+ // remove the dangling nodes
+ Abc_NtkCleanup( pNtk, fVerbose );
+
+ // transform logic functions from BDD to SOP
+ if ( fHasBdds = Abc_NtkIsBddLogic(pNtk) )
+ {
+ if ( !Abc_NtkBddToSop(pNtk, 0) )
+ {
+ printf( "Seq_NtkRetimeDerive(): Converting to SOPs has failed.\n" );
+ return NULL;
+ }
+ }
+
+ // start the network
+ pNtkNew = Abc_NtkAlloc( ABC_NTK_SEQ, ABC_FUNC_AIG, 1 );
+ // duplicate the name and the spec
+ pNtkNew->pName = Extra_UtilStrsav(pNtk->pName);
+ pNtkNew->pSpec = Extra_UtilStrsav(pNtk->pSpec);
+
+ // map the constant nodes
+ Abc_NtkCleanCopy( pNtk );
+ // clone the PIs/POs/latches
+ Abc_NtkForEachPi( pNtk, pObj, i )
+ Abc_NtkDupObj( pNtkNew, pObj, 0 );
+ Abc_NtkForEachPo( pNtk, pObj, i )
+ Abc_NtkDupObj( pNtkNew, pObj, 0 );
+ // copy the names
+ Abc_NtkForEachPi( pNtk, pObj, i )
+ Abc_ObjAssignName( pObj->pCopy, Abc_ObjName(pObj), NULL );
+ Abc_NtkForEachPo( pNtk, pObj, i )
+ Abc_ObjAssignName( pObj->pCopy, Abc_ObjName(pObj), NULL );
+
+ // create one AND for each logic node in the topological order
+ vMapAnds = Abc_NtkDfs( pNtk, 0 );
+ Vec_PtrForEachEntry( vMapAnds, pObj, i )
+ {
+ if ( pObj->Id == 0 )
+ {
+ pObj->pCopy = Abc_AigConst1(pNtkNew);
+ continue;
+ }
+ pObj->pCopy = Abc_NtkCreateNode( pNtkNew );
+ }
+
+ // make the new seq AIG point to the old network through pNext
+ Abc_NtkForEachObj( pNtk, pObj, i )
+ if ( pObj->pCopy ) pObj->pCopy->pNext = pObj;
+
+ // make latches point to the latch fanins
+ Abc_NtkForEachLatch( pNtk, pObj, i )
+ {
+ assert( !Abc_ObjIsLatch(Abc_ObjFanin0(pObj)) );
+ pObj->pCopy = Abc_ObjFanin0(pObj)->pCopy;
+ }
+
+ // create internal AND nodes w/o strashing for each logic node (including constants)
+ vMapFanins = Vec_VecStart( Vec_PtrSize(vMapAnds) );
+ Vec_PtrForEachEntry( vMapAnds, pObj, i )
+ {
+ // get the SOP of the node
+ if ( Abc_NtkHasMapping(pNtk) )
+ pSop = Mio_GateReadSop(pObj->pData);
+ else
+ pSop = pObj->pData;
+ pFanin = Seq_NodeRetimeDerive( pNtkNew, pObj, pSop, Vec_VecEntry(vMapFanins, i) );
+ Abc_ObjAddFanin( pObj->pCopy, pFanin );
+ Abc_ObjAddFanin( pObj->pCopy, pFanin );
+ }
+ // connect the POs
+ Abc_NtkForEachPo( pNtk, pObj, i )
+ Abc_ObjAddFanin( pObj->pCopy, Abc_ObjFanin0(pObj)->pCopy );
+
+ // start the storage for initial states
+ p = pNtkNew->pManFunc;
+ Seq_Resize( p, Abc_NtkObjNumMax(pNtkNew) );
+
+ // add the sequential edges
+ Vec_PtrForEachEntry( vMapAnds, pObj, i )
+ {
+ vMirrors = Vec_VecEntry( vMapFanins, i );
+ Abc_ObjForEachFanin( pObj, pFanin, k )
+ {
+ pMirror = Vec_PtrEntry( vMirrors, k );
+ if ( Abc_ObjIsLatch(pFanin) )
+ {
+ Seq_NodeInsertFirst( pMirror, 0, Abc_LatchInit(pFanin) );
+ Seq_NodeInsertFirst( pMirror, 1, Abc_LatchInit(pFanin) );
+ }
+ }
+ }
+ // add the sequential edges to the POs
+ Abc_NtkForEachPo( pNtk, pObj, i )
+ {
+ pFanin = Abc_ObjFanin0(pObj);
+ if ( Abc_ObjIsLatch(pFanin) )
+ Seq_NodeInsertFirst( pObj->pCopy, 0, Abc_LatchInit(pFanin) );
+ }
+
+
+ // save the fanin/delay info
+ p->vMapAnds = vMapAnds;
+ p->vMapFanins = vMapFanins;
+ p->vMapCuts = Vec_VecStart( Vec_PtrSize(p->vMapAnds) );
+ p->vMapDelays = Vec_VecStart( Vec_PtrSize(p->vMapAnds) );
+ Vec_PtrForEachEntry( p->vMapAnds, pObj, i )
+ {
+ // change the node to be the new one
+ Vec_PtrWriteEntry( p->vMapAnds, i, pObj->pCopy );
+ // collect the new fanins of this node
+ Abc_ObjForEachFanin( pObj, pFanin, k )
+ Vec_VecPush( p->vMapCuts, i, (void *)( (pFanin->pCopy->Id << 8) | Abc_ObjIsLatch(pFanin) ) );
+ // collect the delay info
+ if ( !Abc_NtkHasMapping(pNtk) )
+ {
+ Abc_ObjForEachFanin( pObj, pFanin, k )
+ Vec_VecPush( p->vMapDelays, i, (void *)Abc_Float2Int(1.0) );
+ }
+ else
+ {
+ Mio_Pin_t * pPin = Mio_GateReadPins(pObj->pData);
+ float Max, tDelayBlockRise, tDelayBlockFall;
+ Abc_ObjForEachFanin( pObj, pFanin, k )
+ {
+ tDelayBlockRise = (float)Mio_PinReadDelayBlockRise( pPin );
+ tDelayBlockFall = (float)Mio_PinReadDelayBlockFall( pPin );
+ Max = ABC_MAX( tDelayBlockRise, tDelayBlockFall );
+ Vec_VecPush( p->vMapDelays, i, (void *)Abc_Float2Int(Max) );
+ pPin = Mio_PinReadNext(pPin);
+ }
+ }
+ }
+
+ // set the cutset composed of latch drivers
+// Abc_NtkAigCutsetCopy( pNtk );
+// Seq_NtkLatchGetEqualFaninNum( pNtkNew );
+
+ // convert the network back into BDDs if this is how it was
+ if ( fHasBdds )
+ Abc_NtkSopToBdd(pNtk);
+
+ // copy EXDC and check correctness
+ if ( pNtk->pExdc )
+ fprintf( stdout, "Warning: EXDC is not copied when converting to sequential AIG.\n" );
+ if ( !Abc_NtkCheck( pNtkNew ) )
+ fprintf( stdout, "Seq_NtkRetimeDerive(): Network check has failed.\n" );
+ return pNtkNew;
+}
+
+
+/**Function*************************************************************
+
+ Synopsis [Strashes one logic node using its SOP.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Abc_Obj_t * Seq_NodeRetimeDerive( Abc_Ntk_t * pNtkNew, Abc_Obj_t * pRoot, char * pSop, Vec_Ptr_t * vFanins )
+{
+ extern Abc_Obj_t * Dec_GraphToNetworkNoStrash( Abc_Ntk_t * pNtk, Dec_Graph_t * pGraph );
+ Dec_Graph_t * pFForm;
+ Dec_Node_t * pNode;
+ Abc_Obj_t * pResult, * pFanin, * pMirror;
+ int i, nFanins;
+
+ // get the number of node's fanins
+ nFanins = Abc_ObjFaninNum( pRoot );
+ assert( nFanins == Abc_SopGetVarNum(pSop) );
+ if ( nFanins < 2 )
+ {
+ if ( Abc_SopIsConst1(pSop) )
+ pFanin = Abc_AigConst1(pNtkNew);
+ else if ( Abc_SopIsConst0(pSop) )
+ pFanin = Abc_ObjNot( Abc_AigConst1(pNtkNew) );
+ else if ( Abc_SopIsBuf(pSop) )
+ pFanin = Abc_ObjFanin0(pRoot)->pCopy;
+ else if ( Abc_SopIsInv(pSop) )
+ pFanin = Abc_ObjNot( Abc_ObjFanin0(pRoot)->pCopy );
+ else
+ assert( 0 );
+ // create the node with these fanins
+ pMirror = Abc_NtkCreateNode( pNtkNew );
+ Abc_ObjAddFanin( pMirror, pFanin );
+ Abc_ObjAddFanin( pMirror, pFanin );
+ Vec_PtrPush( vFanins, pMirror );
+ return pMirror;
+ }
+
+ // perform factoring
+ pFForm = Dec_Factor( pSop );
+ // collect the fanins
+ Dec_GraphForEachLeaf( pFForm, pNode, i )
+ {
+ pFanin = Abc_ObjFanin(pRoot,i)->pCopy;
+ pMirror = Abc_NtkCreateNode( pNtkNew );
+ Abc_ObjAddFanin( pMirror, pFanin );
+ Abc_ObjAddFanin( pMirror, pFanin );
+ Vec_PtrPush( vFanins, pMirror );
+ pNode->pFunc = pMirror;
+ }
+ // perform strashing
+ pResult = Dec_GraphToNetworkNoStrash( pNtkNew, pFForm );
+ Dec_GraphFree( pFForm );
+ return pResult;
+}
+
+
+/**Function*************************************************************
+
+ Synopsis [Reconstructs the network after retiming.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Abc_Ntk_t * Seq_NtkRetimeReconstruct( Abc_Ntk_t * pNtkOld, Abc_Ntk_t * pNtkSeq )
+{
+ Abc_Seq_t * p = pNtkSeq->pManFunc;
+ Seq_Lat_t * pRing0, * pRing1;
+ Abc_Ntk_t * pNtkNew;
+ Abc_Obj_t * pObj, * pFanin, * pFaninNew, * pMirror;
+ Vec_Ptr_t * vMirrors;
+ int i, k;
+
+ assert( !Abc_NtkIsSeq(pNtkOld) );
+ assert( Abc_NtkIsSeq(pNtkSeq) );
+
+ // transfer the pointers pNtkOld->pNtkSeq from pCopy to pNext
+ Abc_NtkForEachObj( pNtkOld, pObj, i )
+ pObj->pNext = pObj->pCopy;
+
+ // start the final network
+ pNtkNew = Abc_NtkStartFrom( pNtkSeq, pNtkOld->ntkType, pNtkOld->ntkFunc );
+
+ // transfer the pointers to the old network
+ if ( Abc_AigConst1(pNtkOld) )
+ Abc_AigConst1(pNtkOld)->pCopy = Abc_AigConst1(pNtkNew);
+ Abc_NtkForEachPi( pNtkOld, pObj, i )
+ pObj->pCopy = pObj->pNext->pCopy;
+ Abc_NtkForEachPo( pNtkOld, pObj, i )
+ pObj->pCopy = pObj->pNext->pCopy;
+
+ // copy the internal nodes of the old network into the new network
+ // transfer the pointers pNktOld->pNtkNew to pNtkSeq->pNtkNew
+ Abc_NtkForEachNode( pNtkOld, pObj, i )
+ {
+ if ( i == 0 ) continue;
+ Abc_NtkDupObj( pNtkNew, pObj, 0 );
+ pObj->pNext->pCopy = pObj->pCopy;
+ }
+ Abc_NtkForEachLatch( pNtkOld, pObj, i )
+ pObj->pCopy = Abc_ObjFanin0(pObj)->pCopy;
+
+ // share the latches
+ Seq_NtkShareLatches( pNtkNew, pNtkSeq );
+
+ // connect the objects
+// Abc_NtkForEachNode( pNtkOld, pObj, i )
+ Vec_PtrForEachEntry( p->vMapAnds, pObj, i )
+ {
+ // pObj is from pNtkSeq - transform to pNtkOld
+ pObj = pObj->pNext;
+ // iterate through the fanins of this node in the old network
+ vMirrors = Vec_VecEntry( p->vMapFanins, i );
+ Abc_ObjForEachFanin( pObj, pFanin, k )
+ {
+ pMirror = Vec_PtrEntry( vMirrors, k );
+ assert( Seq_ObjFaninL0(pMirror) == Seq_ObjFaninL1(pMirror) );
+ pRing0 = Seq_NodeGetRing( pMirror, 0 );
+ pRing1 = Seq_NodeGetRing( pMirror, 1 );
+ if ( pRing0 == NULL )
+ {
+ Abc_ObjAddFanin( pObj->pCopy, pFanin->pCopy );
+ continue;
+ }
+// assert( pRing0->pLatch == pRing1->pLatch );
+ if ( pRing0->pLatch->pData > pRing1->pLatch->pData )
+ Abc_ObjAddFanin( pObj->pCopy, pRing0->pLatch );
+ else
+ Abc_ObjAddFanin( pObj->pCopy, pRing1->pLatch );
+ }
+ }
+
+ // connect the POs
+ Abc_NtkForEachPo( pNtkOld, pObj, i )
+ {
+ pFanin = Abc_ObjFanin0(pObj);
+ pRing0 = Seq_NodeGetRing( Abc_NtkPo(pNtkSeq, i), 0 );
+ if ( pRing0 )
+ pFaninNew = pRing0->pLatch;
+ else
+ pFaninNew = pFanin->pCopy;
+ assert( pFaninNew != NULL );
+ Abc_ObjAddFanin( pObj->pCopy, pFaninNew );
+ }
+
+ // clean the result of latch sharing
+ Seq_NtkShareLatchesClean( pNtkSeq );
+
+ // add the latches and their names
+ Abc_NtkAddDummyBoxNames( pNtkNew );
+ Abc_NtkOrderCisCos( pNtkNew );
+ // fix the problem with complemented and duplicated CO edges
+ Abc_NtkLogicMakeSimpleCos( pNtkNew, 1 );
+ if ( !Abc_NtkCheck( pNtkNew ) )
+ fprintf( stdout, "Seq_NtkRetimeReconstruct(): Network check has failed.\n" );
+ return pNtkNew;
+
+}
+
+/**Function*************************************************************
+
+ Synopsis [Reconstructs the network after retiming.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Abc_Obj_t * Seq_EdgeReconstruct_rec( Abc_Obj_t * pGoal, Abc_Obj_t * pNode )
+{
+ Seq_Lat_t * pRing;
+ Abc_Obj_t * pFanin, * pRes = NULL;
+
+ if ( !Abc_AigNodeIsAnd(pNode) )
+ return NULL;
+
+ // consider the first fanin
+ pFanin = Abc_ObjFanin0(pNode);
+ if ( pFanin->pCopy == NULL ) // internal node
+ pRes = Seq_EdgeReconstruct_rec( pGoal, pFanin );
+ else if ( pFanin == pGoal )
+ {
+ if ( pRing = Seq_NodeGetRing( pNode, 0 ) )
+ pRes = pRing->pLatch;
+ else
+ pRes = pFanin->pCopy;
+ }
+ if ( pRes != NULL )
+ return pRes;
+
+ // consider the second fanin
+ pFanin = Abc_ObjFanin1(pNode);
+ if ( pFanin->pCopy == NULL ) // internal node
+ pRes = Seq_EdgeReconstruct_rec( pGoal, pFanin );
+ else if ( pFanin == pGoal )
+ {
+ if ( pRing = Seq_NodeGetRing( pNode, 1 ) )
+ pRes = pRing->pLatch;
+ else
+ pRes = pFanin->pCopy;
+ }
+ return pRes;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Reconstructs the network after retiming.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Abc_Obj_t * Seq_EdgeReconstructPO( Abc_Obj_t * pNode )
+{
+ Seq_Lat_t * pRing;
+ assert( Abc_ObjIsPo(pNode) );
+ if ( pRing = Seq_NodeGetRing( pNode, 0 ) )
+ return pRing->pLatch;
+ else
+ return Abc_ObjFanin0(pNode)->pCopy;
+}
+
+////////////////////////////////////////////////////////////////////////
+/// END OF FILE ///
+////////////////////////////////////////////////////////////////////////
+
+
diff --git a/src/base/seq/seqRetIter.c b/src/base/seq/seqRetIter.c
new file mode 100644
index 00000000..99c50914
--- /dev/null
+++ b/src/base/seq/seqRetIter.c
@@ -0,0 +1,403 @@
+/**CFile****************************************************************
+
+ FileName [seqRetIter.c]
+
+ SystemName [ABC: Logic synthesis and verification system.]
+
+ PackageName [Construction and manipulation of sequential AIGs.]
+
+ Synopsis [Iterative delay computation in FPGA mapping/retiming package.]
+
+ Author [Alan Mishchenko]
+
+ Affiliation [UC Berkeley]
+
+ Date [Ver. 1.0. Started - June 20, 2005.]
+
+ Revision [$Id: seqRetIter.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "seqInt.h"
+#include "main.h"
+#include "fpga.h"
+
+////////////////////////////////////////////////////////////////////////
+/// DECLARATIONS ///
+////////////////////////////////////////////////////////////////////////
+
+static float Seq_NtkMappingSearch_rec( Abc_Ntk_t * pNtk, float FiMin, float FiMax, float Delta, int fVerbose );
+static int Seq_NtkMappingForPeriod( Abc_Ntk_t * pNtk, float Fi, int fVerbose );
+static int Seq_NtkNodeUpdateLValue( Abc_Obj_t * pObj, float Fi, Vec_Ptr_t * vLeaves, Vec_Ptr_t * vDelays );
+static void Seq_NodeRetimeSetLag_rec( Abc_Obj_t * pNode, char Lag );
+
+static void Seq_NodePrintInfo( Abc_Obj_t * pNode );
+static void Seq_NodePrintInfoPlus( Abc_Obj_t * pNode );
+
+////////////////////////////////////////////////////////////////////////
+/// FUNCTION DEFINITIONS ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+ Synopsis [Computes the retiming lags for arbitrary network.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Seq_NtkRetimeDelayLags( Abc_Ntk_t * pNtkOld, Abc_Ntk_t * pNtk, int fVerbose )
+{
+ Abc_Seq_t * p = pNtk->pManFunc;
+ Abc_Obj_t * pNode;
+ float FiMax, Delta;
+ int i, RetValue;
+ char NodeLag;
+
+ assert( Abc_NtkIsSeq( pNtk ) );
+
+ // the root AND gates and node delay should be assigned
+ assert( p->vMapAnds );
+ assert( p->vMapCuts );
+ assert( p->vMapDelays );
+ assert( p->vMapFanins );
+
+ // guess the upper bound on the clock period
+ if ( Abc_NtkHasMapping(pNtkOld) )
+ {
+ // assign the accuracy for min-period computation
+ Delta = Mio_LibraryReadDelayNand2Max(Abc_FrameReadLibGen());
+ if ( Delta == 0.0 )
+ {
+ Delta = Mio_LibraryReadDelayAnd2Max(Abc_FrameReadLibGen());
+ if ( Delta == 0.0 )
+ {
+ printf( "Cannot retime/map if the library does not have NAND2 or AND2.\n" );
+ return 0;
+ }
+ }
+ // get the upper bound on the clock period
+ FiMax = Delta * 2 + Abc_NtkDelayTrace(pNtkOld);
+ Delta /= 2;
+ }
+ else
+ {
+ FiMax = (float)2.0 + Abc_NtkGetLevelNum(pNtkOld);
+ Delta = 1;
+ }
+
+ // make sure this clock period is feasible
+ if ( !Seq_NtkMappingForPeriod( pNtk, FiMax, fVerbose ) )
+ {
+ printf( "Error: The upper bound on the clock period cannot be computed.\n" );
+ printf( "The reason for this error may be the presence in the circuit of logic\n" );
+ printf( "that is not reachable from the PIs. Mapping/retiming is not performed.\n" );
+ return 0;
+ }
+
+ // search for the optimal clock period between 0 and nLevelMax
+ p->FiBestFloat = Seq_NtkMappingSearch_rec( pNtk, 0.0, FiMax, Delta, fVerbose );
+
+ // recompute the best l-values
+ RetValue = Seq_NtkMappingForPeriod( pNtk, p->FiBestFloat, fVerbose );
+ assert( RetValue );
+
+ // fix the problem with non-converged delays
+ Vec_PtrForEachEntry( p->vMapAnds, pNode, i )
+ if ( Seq_NodeGetLValueP(pNode) < -ABC_INFINITY/2 )
+ Seq_NodeSetLValueP( pNode, 0 );
+
+ // experiment by adding an epsilon to all LValues
+// Vec_PtrForEachEntry( p->vMapAnds, pNode, i )
+// Seq_NodeSetLValueP( pNode, Seq_NodeGetLValueP(pNode) - p->fEpsilon );
+
+ // save the retiming lags
+ // mark the nodes
+ Vec_PtrForEachEntry( p->vMapAnds, pNode, i )
+ pNode->fMarkA = 1;
+ // process the nodes
+ Vec_StrFill( p->vLags, p->nSize, 0 );
+ Vec_PtrForEachEntry( p->vMapAnds, pNode, i )
+ {
+ if ( Vec_PtrSize( Vec_VecEntry(p->vMapCuts, i) ) == 0 )
+ {
+ Seq_NodeSetLag( pNode, 0 );
+ continue;
+ }
+ NodeLag = Seq_NodeComputeLagFloat( Seq_NodeGetLValueP(pNode), p->FiBestFloat );
+ Seq_NodeRetimeSetLag_rec( pNode, NodeLag );
+ }
+ // unmark the nodes
+ Vec_PtrForEachEntry( p->vMapAnds, pNode, i )
+ pNode->fMarkA = 0;
+
+ // print the result
+ if ( fVerbose )
+ printf( "The best clock period is %6.2f.\n", p->FiBestFloat );
+/*
+ {
+ FILE * pTable;
+ pTable = fopen( "stats.txt", "a+" );
+ fprintf( pTable, "%s ", pNtk->pName );
+ fprintf( pTable, "%.2f ", FiBest );
+ fprintf( pTable, "\n" );
+ fclose( pTable );
+ }
+*/
+// Seq_NodePrintInfo( Abc_NtkObj(pNtk, 847) );
+ return 1;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Performs binary search for the optimal clock period.]
+
+ Description [Assumes that FiMin is infeasible while FiMax is feasible.]
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+float Seq_NtkMappingSearch_rec( Abc_Ntk_t * pNtk, float FiMin, float FiMax, float Delta, int fVerbose )
+{
+ float Median;
+ assert( FiMin < FiMax );
+ if ( FiMin + Delta >= FiMax )
+ return FiMax;
+ Median = FiMin + (FiMax - FiMin)/2;
+ if ( Seq_NtkMappingForPeriod( pNtk, Median, fVerbose ) )
+ return Seq_NtkMappingSearch_rec( pNtk, FiMin, Median, Delta, fVerbose ); // Median is feasible
+ else
+ return Seq_NtkMappingSearch_rec( pNtk, Median, FiMax, Delta, fVerbose ); // Median is infeasible
+}
+
+/**Function*************************************************************
+
+ Synopsis [Returns 1 if retiming with this clock period is feasible.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Seq_NtkMappingForPeriod( Abc_Ntk_t * pNtk, float Fi, int fVerbose )
+{
+ Abc_Seq_t * p = pNtk->pManFunc;
+ Vec_Ptr_t * vLeaves, * vDelays;
+ Abc_Obj_t * pObj;
+ int i, c, RetValue, fChange, Counter;
+ char * pReason = "";
+
+ // set l-values of all nodes to be minus infinity
+ Vec_IntFill( p->vLValues, p->nSize, Abc_Float2Int( (float)-ABC_INFINITY ) );
+
+ // set l-values of constants and PIs
+ pObj = Abc_NtkObj( pNtk, 0 );
+ Seq_NodeSetLValueP( pObj, 0.0 );
+ Abc_NtkForEachPi( pNtk, pObj, i )
+ Seq_NodeSetLValueP( pObj, 0.0 );
+
+ // update all values iteratively
+ Counter = 0;
+ for ( c = 0; c < p->nMaxIters; c++ )
+ {
+ fChange = 0;
+ Vec_PtrForEachEntry( p->vMapAnds, pObj, i )
+ {
+ Counter++;
+ vLeaves = Vec_VecEntry( p->vMapCuts, i );
+ vDelays = Vec_VecEntry( p->vMapDelays, i );
+ if ( Vec_PtrSize(vLeaves) == 0 )
+ {
+ Seq_NodeSetLValueP( pObj, 0.0 );
+ continue;
+ }
+ RetValue = Seq_NtkNodeUpdateLValue( pObj, Fi, vLeaves, vDelays );
+ if ( RetValue == SEQ_UPDATE_YES )
+ fChange = 1;
+ }
+ Abc_NtkForEachPo( pNtk, pObj, i )
+ {
+ RetValue = Seq_NtkNodeUpdateLValue( pObj, Fi, NULL, NULL );
+ if ( RetValue == SEQ_UPDATE_FAIL )
+ break;
+ }
+ if ( RetValue == SEQ_UPDATE_FAIL )
+ break;
+ if ( fChange == 0 )
+ break;
+ }
+ if ( c == p->nMaxIters )
+ {
+ RetValue = SEQ_UPDATE_FAIL;
+ pReason = "(timeout)";
+ }
+ else
+ c++;
+
+ // report the results
+ if ( fVerbose )
+ {
+ if ( RetValue == SEQ_UPDATE_FAIL )
+ printf( "Period = %6.2f. Iterations = %3d. Updates = %10d. Infeasible %s\n", Fi, c, Counter, pReason );
+ else
+ printf( "Period = %6.2f. Iterations = %3d. Updates = %10d. Feasible\n", Fi, c, Counter );
+ }
+ return RetValue != SEQ_UPDATE_FAIL;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Computes the l-value of the node.]
+
+ Description [The node can be internal or a PO.]
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Seq_NtkNodeUpdateLValue( Abc_Obj_t * pObj, float Fi, Vec_Ptr_t * vLeaves, Vec_Ptr_t * vDelays )
+{
+ Abc_Seq_t * p = pObj->pNtk->pManFunc;
+ float lValueOld, lValueNew, lValueCur, lValuePin;
+ unsigned SeqEdge;
+ Abc_Obj_t * pLeaf;
+ int i;
+
+ assert( !Abc_ObjIsPi(pObj) );
+ assert( Abc_ObjFaninNum(pObj) > 0 );
+ // consider the case of the PO
+ if ( Abc_ObjIsPo(pObj) )
+ {
+ lValueCur = Seq_NodeGetLValueP(Abc_ObjFanin0(pObj)) - Fi * Seq_ObjFaninL0(pObj);
+ return (lValueCur > Fi + p->fEpsilon)? SEQ_UPDATE_FAIL : SEQ_UPDATE_NO;
+ }
+ // get the new arrival time of the cut output
+ lValueNew = -ABC_INFINITY;
+ Vec_PtrForEachEntry( vLeaves, pLeaf, i )
+ {
+ SeqEdge = (unsigned)pLeaf;
+ pLeaf = Abc_NtkObj( pObj->pNtk, SeqEdge >> 8 );
+ lValueCur = Seq_NodeGetLValueP(pLeaf) - Fi * (SeqEdge & 255);
+ lValuePin = Abc_Int2Float( (int)Vec_PtrEntry(vDelays, i) );
+ if ( lValueNew < lValuePin + lValueCur )
+ lValueNew = lValuePin + lValueCur;
+ }
+ // compare
+ lValueOld = Seq_NodeGetLValueP( pObj );
+ if ( lValueNew <= lValueOld + p->fEpsilon )
+ return SEQ_UPDATE_NO;
+ // update the values
+ if ( lValueNew > lValueOld + p->fEpsilon )
+ Seq_NodeSetLValueP( pObj, lValueNew );
+ return SEQ_UPDATE_YES;
+}
+
+
+
+/**Function*************************************************************
+
+ Synopsis [Add sequential edges.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Seq_NodeRetimeSetLag_rec( Abc_Obj_t * pNode, char Lag )
+{
+ Abc_Obj_t * pFanin;
+ if ( !Abc_AigNodeIsAnd(pNode) )
+ return;
+ Seq_NodeSetLag( pNode, Lag );
+ // consider the first fanin
+ pFanin = Abc_ObjFanin0(pNode);
+ if ( pFanin->fMarkA == 0 ) // internal node
+ Seq_NodeRetimeSetLag_rec( pFanin, Lag );
+ // consider the second fanin
+ pFanin = Abc_ObjFanin1(pNode);
+ if ( pFanin->fMarkA == 0 ) // internal node
+ Seq_NodeRetimeSetLag_rec( pFanin, Lag );
+}
+
+
+/**Function*************************************************************
+
+ Synopsis [Add sequential edges.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Seq_NodePrintInfo( Abc_Obj_t * pNode )
+{
+ Abc_Seq_t * p = pNode->pNtk->pManFunc;
+ Abc_Obj_t * pFanin, * pObj, * pLeaf;
+ Vec_Ptr_t * vLeaves;
+ unsigned SeqEdge;
+ int i, Number;
+
+ // print the node
+ printf( " Node = %6d. LValue = %7.2f. Lag = %2d.\n",
+ pNode->Id, Seq_NodeGetLValueP(pNode), Seq_NodeGetLag(pNode) );
+
+ // find the number
+ Vec_PtrForEachEntry( p->vMapAnds, pObj, Number )
+ if ( pObj == pNode )
+ break;
+
+ // get the leaves
+ vLeaves = Vec_VecEntry( p->vMapCuts, Number );
+
+ // print the leaves
+ Vec_PtrForEachEntry( vLeaves, pLeaf, i )
+ {
+ SeqEdge = (unsigned)pLeaf;
+ pFanin = Abc_NtkObj( pNode->pNtk, SeqEdge >> 8 );
+ // print the leaf
+ printf( " Fanin%d(%d) = %6d. LValue = %7.2f. Lag = %2d.\n", i, SeqEdge & 255,
+ pFanin->Id, Seq_NodeGetLValueP(pFanin), Seq_NodeGetLag(pFanin) );
+ }
+}
+
+/**Function*************************************************************
+
+ Synopsis [Add sequential edges.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Seq_NodePrintInfoPlus( Abc_Obj_t * pNode )
+{
+ Abc_Obj_t * pFanout;
+ int i;
+ printf( "CENTRAL NODE:\n" );
+ Seq_NodePrintInfo( pNode );
+ Abc_ObjForEachFanout( pNode, pFanout, i )
+ {
+ printf( "FANOUT%d:\n", i );
+ Seq_NodePrintInfo( pFanout );
+ }
+}
+
+////////////////////////////////////////////////////////////////////////
+/// END OF FILE ///
+////////////////////////////////////////////////////////////////////////
+
+
diff --git a/src/base/seq/seqShare.c b/src/base/seq/seqShare.c
new file mode 100644
index 00000000..742de46b
--- /dev/null
+++ b/src/base/seq/seqShare.c
@@ -0,0 +1,388 @@
+/**CFile****************************************************************
+
+ FileName [seqShare.c]
+
+ SystemName [ABC: Logic synthesis and verification system.]
+
+ PackageName [Construction and manipulation of sequential AIGs.]
+
+ Synopsis [Latch sharing at the fanout stems.]
+
+ Author [Alan Mishchenko]
+
+ Affiliation [UC Berkeley]
+
+ Date [Ver. 1.0. Started - June 20, 2005.]
+
+ Revision [$Id: seqShare.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "seqInt.h"
+
+////////////////////////////////////////////////////////////////////////
+/// DECLARATIONS ///
+////////////////////////////////////////////////////////////////////////
+
+static void Seq_NodeShareFanouts( Abc_Obj_t * pNode, Vec_Ptr_t * vNodes );
+static void Seq_NodeShareOne( Abc_Obj_t * pNode, Abc_InitType_t Init, Vec_Ptr_t * vNodes );
+
+////////////////////////////////////////////////////////////////////////
+/// FUNCTION DEFINITIONS ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+ Synopsis [Transforms the sequential AIG to take fanout sharing into account.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Seq_NtkShareFanouts( Abc_Ntk_t * pNtk )
+{
+ Vec_Ptr_t * vNodes;
+ Abc_Obj_t * pObj;
+ int i;
+ vNodes = Vec_PtrAlloc( 10 );
+ // share the PI latches
+ Abc_NtkForEachPi( pNtk, pObj, i )
+ Seq_NodeShareFanouts( pObj, vNodes );
+ // share the node latches
+ Abc_NtkForEachNode( pNtk, pObj, i )
+ Seq_NodeShareFanouts( pObj, vNodes );
+ Vec_PtrFree( vNodes );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Transforms the node to take fanout sharing into account.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Seq_NodeShareFanouts( Abc_Obj_t * pNode, Vec_Ptr_t * vNodes )
+{
+ Abc_Obj_t * pFanout;
+ Abc_InitType_t Type;
+ int nLatches[4], i;
+ // skip the node with only one fanout
+ if ( Abc_ObjFanoutNum(pNode) < 2 )
+ return;
+ // clean the the fanout counters
+ for ( i = 0; i < 4; i++ )
+ nLatches[i] = 0;
+ // find the number of fanouts having latches of each type
+ Abc_ObjForEachFanout( pNode, pFanout, i )
+ {
+ if ( Seq_ObjFanoutL(pNode, pFanout) == 0 )
+ continue;
+ Type = Seq_NodeGetInitLast( pFanout, Abc_ObjFanoutEdgeNum(pNode, pFanout) );
+ nLatches[Type]++;
+ }
+ // decide what to do
+ if ( nLatches[ABC_INIT_ZERO] > 1 && nLatches[ABC_INIT_ONE] > 1 ) // 0-group and 1-group
+ {
+ Seq_NodeShareOne( pNode, ABC_INIT_ZERO, vNodes ); // shares 0 and DC
+ Seq_NodeShareOne( pNode, ABC_INIT_ONE, vNodes ); // shares 1 and DC
+ }
+ else if ( nLatches[ABC_INIT_ZERO] > 1 ) // 0-group
+ Seq_NodeShareOne( pNode, ABC_INIT_ZERO, vNodes ); // shares 0 and DC
+ else if ( nLatches[ABC_INIT_ONE] > 1 ) // 1-group
+ Seq_NodeShareOne( pNode, ABC_INIT_ONE, vNodes ); // shares 1 and DC
+ else if ( nLatches[ABC_INIT_DC] > 1 ) // DC-group
+ {
+ if ( nLatches[ABC_INIT_ZERO] > 0 )
+ Seq_NodeShareOne( pNode, ABC_INIT_ZERO, vNodes ); // shares 0 and DC
+ else
+ Seq_NodeShareOne( pNode, ABC_INIT_ONE, vNodes ); // shares 1 and DC
+ }
+}
+
+/**Function*************************************************************
+
+ Synopsis [Transforms the node to take fanout sharing into account.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Seq_NodeShareOne( Abc_Obj_t * pNode, Abc_InitType_t Init, Vec_Ptr_t * vNodes )
+{
+ Vec_Int_t * vNums = Seq_ObjLNums( pNode );
+ Vec_Ptr_t * vInits = Seq_NodeLats( pNode );
+ Abc_Obj_t * pFanout, * pBuffer;
+ Abc_InitType_t Type, InitNew;
+ int i;
+ // collect the fanouts that satisfy the property (have initial value Init or DC)
+ InitNew = ABC_INIT_DC;
+ Vec_PtrClear( vNodes );
+ Abc_ObjForEachFanout( pNode, pFanout, i )
+ {
+ if ( Seq_ObjFanoutL(pNode, pFanout) == 0 )
+ continue;
+ Type = Seq_NodeGetInitLast( pFanout, Abc_ObjFanoutEdgeNum(pNode, pFanout) );
+ if ( Type == Init )
+ InitNew = Init;
+ if ( Type == Init || Type == ABC_INIT_DC )
+ {
+ Vec_PtrPush( vNodes, pFanout );
+ Seq_NodeDeleteLast( pFanout, Abc_ObjFanoutEdgeNum(pNode, pFanout) );
+ }
+ }
+ // create the new buffer
+ pBuffer = Abc_NtkCreateNode( pNode->pNtk );
+ Abc_ObjAddFanin( pBuffer, pNode );
+
+ // grow storage for initial states
+ Vec_PtrGrow( vInits, 2 * pBuffer->Id + 2 );
+ for ( i = Vec_PtrSize(vInits); i < 2 * (int)pBuffer->Id + 2; i++ )
+ Vec_PtrPush( vInits, NULL );
+ // grow storage for numbers of latches
+ Vec_IntGrow( vNums, 2 * pBuffer->Id + 2 );
+ for ( i = Vec_IntSize(vNums); i < 2 * (int)pBuffer->Id + 2; i++ )
+ Vec_IntPush( vNums, 0 );
+ // insert the new latch
+ Seq_NodeInsertFirst( pBuffer, 0, InitNew );
+
+ // redirect the fanouts
+ Vec_PtrForEachEntry( vNodes, pFanout, i )
+ Abc_ObjPatchFanin( pFanout, pNode, pBuffer );
+}
+
+
+
+
+
+/**Function*************************************************************
+
+ Synopsis [Maps virtual latches into real latches.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+static inline unsigned Seq_NtkShareLatchesKey( Abc_Obj_t * pObj, Abc_InitType_t Init )
+{
+ return (pObj->Id << 2) | Init;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Maps virtual latches into real latches.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Abc_Obj_t * Seq_NtkShareLatches_rec( Abc_Ntk_t * pNtk, Abc_Obj_t * pObj, Seq_Lat_t * pRing, int nLatch, stmm_table * tLatchMap )
+{
+ Abc_Obj_t * pLatch, * pFanin;
+ Abc_InitType_t Init;
+ unsigned Key;
+ if ( nLatch == 0 )
+ return pObj;
+ assert( pRing->pLatch == NULL );
+ // get the latch on the previous level
+ pFanin = Seq_NtkShareLatches_rec( pNtk, pObj, Seq_LatNext(pRing), nLatch - 1, tLatchMap );
+
+ // get the initial state
+ Init = Seq_LatInit( pRing );
+ // check if the latch with this initial state exists
+ Key = Seq_NtkShareLatchesKey( pFanin, Init );
+ if ( stmm_lookup( tLatchMap, (char *)Key, (char **)&pLatch ) )
+ return pRing->pLatch = pLatch;
+
+ // does not exist
+ if ( Init != ABC_INIT_DC )
+ {
+ // check if the don't-care exists
+ Key = Seq_NtkShareLatchesKey( pFanin, ABC_INIT_DC );
+ if ( stmm_lookup( tLatchMap, (char *)Key, (char **)&pLatch ) ) // yes
+ {
+ // update the table
+ stmm_delete( tLatchMap, (char **)&Key, (char **)&pLatch );
+ Key = Seq_NtkShareLatchesKey( pFanin, Init );
+ stmm_insert( tLatchMap, (char *)Key, (char *)pLatch );
+ // change don't-care to the given value
+ pLatch->pData = (void *)Init;
+ return pRing->pLatch = pLatch;
+ }
+
+ // add the latch with this value
+ pLatch = Abc_NtkCreateLatch( pNtk );
+ pLatch->pData = (void *)Init;
+ Abc_ObjAddFanin( pLatch, pFanin );
+ // add it to the table
+ Key = Seq_NtkShareLatchesKey( pFanin, Init );
+ stmm_insert( tLatchMap, (char *)Key, (char *)pLatch );
+ return pRing->pLatch = pLatch;
+ }
+ // the init value is the don't-care
+
+ // check if care values exist
+ Key = Seq_NtkShareLatchesKey( pFanin, ABC_INIT_ZERO );
+ if ( stmm_lookup( tLatchMap, (char *)Key, (char **)&pLatch ) )
+ {
+ Seq_LatSetInit( pRing, ABC_INIT_ZERO );
+ return pRing->pLatch = pLatch;
+ }
+ Key = Seq_NtkShareLatchesKey( pFanin, ABC_INIT_ONE );
+ if ( stmm_lookup( tLatchMap, (char *)Key, (char **)&pLatch ) )
+ {
+ Seq_LatSetInit( pRing, ABC_INIT_ONE );
+ return pRing->pLatch = pLatch;
+ }
+
+ // create the don't-care latch
+ pLatch = Abc_NtkCreateLatch( pNtk );
+ pLatch->pData = (void *)ABC_INIT_DC;
+ Abc_ObjAddFanin( pLatch, pFanin );
+ // add it to the table
+ Key = Seq_NtkShareLatchesKey( pFanin, ABC_INIT_DC );
+ stmm_insert( tLatchMap, (char *)Key, (char *)pLatch );
+ return pRing->pLatch = pLatch;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Maps virtual latches into real latches.]
+
+ Description [Creates new latches and assigns them to virtual latches
+ on the edges of a sequential AIG. The nodes of the new network should
+ be created before this procedure is called.]
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Seq_NtkShareLatches( Abc_Ntk_t * pNtkNew, Abc_Ntk_t * pNtk )
+{
+ Abc_Obj_t * pObj, * pFanin;
+ stmm_table * tLatchMap;
+ int i;
+ assert( Abc_NtkIsSeq( pNtk ) );
+ tLatchMap = stmm_init_table( stmm_ptrcmp, stmm_ptrhash );
+ Abc_AigForEachAnd( pNtk, pObj, i )
+ {
+ pFanin = Abc_ObjFanin0(pObj);
+ Seq_NtkShareLatches_rec( pNtkNew, pFanin->pCopy, Seq_NodeGetRing(pObj,0), Seq_NodeCountLats(pObj,0), tLatchMap );
+ pFanin = Abc_ObjFanin1(pObj);
+ Seq_NtkShareLatches_rec( pNtkNew, pFanin->pCopy, Seq_NodeGetRing(pObj,1), Seq_NodeCountLats(pObj,1), tLatchMap );
+ }
+ Abc_NtkForEachPo( pNtk, pObj, i )
+ Seq_NtkShareLatches_rec( pNtkNew, Abc_ObjFanin0(pObj)->pCopy, Seq_NodeGetRing(pObj,0), Seq_NodeCountLats(pObj,0), tLatchMap );
+ stmm_free_table( tLatchMap );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Maps virtual latches into real latches.]
+
+ Description [Creates new latches and assigns them to virtual latches
+ on the edges of a sequential AIG. The nodes of the new network should
+ be created before this procedure is called.]
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Seq_NtkShareLatchesMapping( Abc_Ntk_t * pNtkNew, Abc_Ntk_t * pNtk, Vec_Ptr_t * vMapAnds, int fFpga )
+{
+ Seq_Match_t * pMatch;
+ Abc_Obj_t * pObj, * pFanout;
+ stmm_table * tLatchMap;
+ Vec_Ptr_t * vNodes;
+ int i, k;
+ assert( Abc_NtkIsSeq( pNtk ) );
+
+ // start the table
+ tLatchMap = stmm_init_table( stmm_ptrcmp, stmm_ptrhash );
+
+ // create the array of all nodes with sharable fanouts
+ vNodes = Vec_PtrAlloc( 100 );
+ Vec_PtrPush( vNodes, Abc_AigConst1(pNtk) );
+ Abc_NtkForEachPi( pNtk, pObj, i )
+ Vec_PtrPush( vNodes, pObj );
+ if ( fFpga )
+ {
+ Vec_PtrForEachEntry( vMapAnds, pObj, i )
+ Vec_PtrPush( vNodes, pObj );
+ }
+ else
+ {
+ Vec_PtrForEachEntry( vMapAnds, pMatch, i )
+ Vec_PtrPush( vNodes, pMatch->pAnd );
+ }
+
+ // process nodes used in the mapping
+ Vec_PtrForEachEntry( vNodes, pObj, i )
+ {
+ // make sure the label is clean
+ Abc_ObjForEachFanout( pObj, pFanout, k )
+ assert( pFanout->fMarkC == 0 );
+ Abc_ObjForEachFanout( pObj, pFanout, k )
+ {
+ if ( pFanout->fMarkC )
+ continue;
+ pFanout->fMarkC = 1;
+ if ( Abc_ObjFaninId0(pFanout) == pObj->Id )
+ Seq_NtkShareLatches_rec( pNtkNew, pObj->pCopy, Seq_NodeGetRing(pFanout,0), Seq_NodeCountLats(pFanout,0), tLatchMap );
+ if ( Abc_ObjFaninId1(pFanout) == pObj->Id )
+ Seq_NtkShareLatches_rec( pNtkNew, pObj->pCopy, Seq_NodeGetRing(pFanout,1), Seq_NodeCountLats(pFanout,1), tLatchMap );
+ }
+ // clean the label
+ Abc_ObjForEachFanout( pObj, pFanout, k )
+ pFanout->fMarkC = 0;
+ }
+ stmm_free_table( tLatchMap );
+ // return to the old array
+ Vec_PtrFree( vNodes );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Clean the latches after sharing them.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Seq_NtkShareLatchesClean( Abc_Ntk_t * pNtk )
+{
+ Abc_Obj_t * pObj;
+ int i;
+ assert( Abc_NtkIsSeq( pNtk ) );
+ Abc_AigForEachAnd( pNtk, pObj, i )
+ {
+ Seq_NodeCleanLats( pObj, 0 );
+ Seq_NodeCleanLats( pObj, 1 );
+ }
+ Abc_NtkForEachPo( pNtk, pObj, i )
+ Seq_NodeCleanLats( pObj, 0 );
+}
+
+////////////////////////////////////////////////////////////////////////
+/// END OF FILE ///
+////////////////////////////////////////////////////////////////////////
diff --git a/src/base/seq/seqUtil.c b/src/base/seq/seqUtil.c
new file mode 100644
index 00000000..55b9df8e
--- /dev/null
+++ b/src/base/seq/seqUtil.c
@@ -0,0 +1,597 @@
+/**CFile****************************************************************
+
+ FileName [seqUtil.c]
+
+ SystemName [ABC: Logic synthesis and verification system.]
+
+ PackageName [Construction and manipulation of sequential AIGs.]
+
+ Synopsis [Various utilities working with sequential AIGs.]
+
+ Author [Alan Mishchenko]
+
+ Affiliation [UC Berkeley]
+
+ Date [Ver. 1.0. Started - June 20, 2005.]
+
+ Revision [$Id: seqUtil.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "seqInt.h"
+
+////////////////////////////////////////////////////////////////////////
+/// DECLARATIONS ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+/// FUNCTION DEFINITIONS ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+ Synopsis [Returns the maximum latch number on any of the fanouts.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Seq_NtkLevelMax( Abc_Ntk_t * pNtk )
+{
+ Abc_Obj_t * pNode;
+ int i, Result;
+ assert( Abc_NtkIsSeq(pNtk) );
+ Result = 0;
+ Abc_NtkForEachPo( pNtk, pNode, i )
+ {
+ pNode = Abc_ObjFanin0(pNode);
+ if ( Result < (int)pNode->Level )
+ Result = pNode->Level;
+ }
+ Abc_SeqForEachCutsetNode( pNtk, pNode, i )
+ {
+ if ( Result < (int)pNode->Level )
+ Result = pNode->Level;
+ }
+ return Result;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Returns the maximum latch number on any of the fanouts.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Seq_ObjFanoutLMax( Abc_Obj_t * pObj )
+{
+ Abc_Obj_t * pFanout;
+ int i, nLatchCur, nLatchRes;
+ if ( Abc_ObjFanoutNum(pObj) == 0 )
+ return 0;
+ nLatchRes = 0;
+ Abc_ObjForEachFanout( pObj, pFanout, i )
+ {
+ nLatchCur = Seq_ObjFanoutL(pObj, pFanout);
+ if ( nLatchRes < nLatchCur )
+ nLatchRes = nLatchCur;
+ }
+ assert( nLatchRes >= 0 );
+ return nLatchRes;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Returns the minimum latch number on any of the fanouts.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Seq_ObjFanoutLMin( Abc_Obj_t * pObj )
+{
+ Abc_Obj_t * pFanout;
+ int i, nLatchCur, nLatchRes;
+ if ( Abc_ObjFanoutNum(pObj) == 0 )
+ return 0;
+ nLatchRes = ABC_INFINITY;
+ Abc_ObjForEachFanout( pObj, pFanout, i )
+ {
+ nLatchCur = Seq_ObjFanoutL(pObj, pFanout);
+ if ( nLatchRes > nLatchCur )
+ nLatchRes = nLatchCur;
+ }
+ assert( nLatchRes < ABC_INFINITY );
+ return nLatchRes;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Returns the sum of latches on the fanout edges.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Seq_ObjFanoutLSum( Abc_Obj_t * pObj )
+{
+ Abc_Obj_t * pFanout;
+ int i, nSum = 0;
+ Abc_ObjForEachFanout( pObj, pFanout, i )
+ nSum += Seq_ObjFanoutL(pObj, pFanout);
+ return nSum;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Returns the sum of latches on the fanin edges.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Seq_ObjFaninLSum( Abc_Obj_t * pObj )
+{
+ Abc_Obj_t * pFanin;
+ int i, nSum = 0;
+ Abc_ObjForEachFanin( pObj, pFanin, i )
+ nSum += Seq_ObjFaninL(pObj, i);
+ return nSum;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Generates the printable edge label with the initial state.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+char * Seq_ObjFaninGetInitPrintable( Abc_Obj_t * pObj, int Edge )
+{
+ static char Buffer[1000];
+ Abc_InitType_t Init;
+ int nLatches, i;
+ nLatches = Seq_ObjFaninL( pObj, Edge );
+ for ( i = 0; i < nLatches; i++ )
+ {
+ Init = Seq_LatInit( Seq_NodeGetLat(pObj, Edge, i) );
+ if ( Init == ABC_INIT_NONE )
+ Buffer[i] = '_';
+ else if ( Init == ABC_INIT_ZERO )
+ Buffer[i] = '0';
+ else if ( Init == ABC_INIT_ONE )
+ Buffer[i] = '1';
+ else if ( Init == ABC_INIT_DC )
+ Buffer[i] = 'x';
+ else assert( 0 );
+ }
+ Buffer[nLatches] = 0;
+ return Buffer;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Sets the given value to all the latches of the edge.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Seq_NodeLatchSetValues( Abc_Obj_t * pObj, int Edge, Abc_InitType_t Init )
+{
+ Seq_Lat_t * pLat, * pRing;
+ int c;
+ pRing = Seq_NodeGetRing(pObj, Edge);
+ if ( pRing == NULL )
+ return;
+ for ( c = 0, pLat = pRing; !c || pLat != pRing; c++, pLat = pLat->pNext )
+ Seq_LatSetInit( pLat, Init );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Sets the given value to all the latches of the edge.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Seq_NtkLatchSetValues( Abc_Ntk_t * pNtk, Abc_InitType_t Init )
+{
+ Abc_Obj_t * pObj;
+ int i;
+ assert( Abc_NtkIsSeq( pNtk ) );
+ Abc_NtkForEachPo( pNtk, pObj, i )
+ Seq_NodeLatchSetValues( pObj, 0, Init );
+ Abc_NtkForEachNode( pNtk, pObj, i )
+ {
+ Seq_NodeLatchSetValues( pObj, 0, Init );
+ Seq_NodeLatchSetValues( pObj, 1, Init );
+ }
+}
+
+
+/**Function*************************************************************
+
+ Synopsis [Counts the number of latches in the sequential AIG.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Seq_NtkLatchNum( Abc_Ntk_t * pNtk )
+{
+ Abc_Obj_t * pObj;
+ int i, Counter;
+ assert( Abc_NtkIsSeq( pNtk ) );
+ Counter = 0;
+ Abc_NtkForEachNode( pNtk, pObj, i )
+ Counter += Seq_ObjFaninLSum( pObj );
+ Abc_NtkForEachPo( pNtk, pObj, i )
+ Counter += Seq_ObjFaninLSum( pObj );
+ return Counter;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Counts the number of latches in the sequential AIG.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Seq_NtkLatchNumMax( Abc_Ntk_t * pNtk )
+{
+ Abc_Obj_t * pObj;
+ int i, Max, Cur;
+ assert( Abc_NtkIsSeq( pNtk ) );
+ Max = 0;
+ Abc_AigForEachAnd( pNtk, pObj, i )
+ {
+ Cur = Seq_ObjFaninLMax( pObj );
+ if ( Max < Cur )
+ Max = Cur;
+ }
+ Abc_NtkForEachPo( pNtk, pObj, i )
+ {
+ Cur = Seq_ObjFaninL0( pObj );
+ if ( Max < Cur )
+ Max = Cur;
+ }
+ return Max;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Counts the number of latches in the sequential AIG.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Seq_NtkLatchNumShared( Abc_Ntk_t * pNtk )
+{
+ Abc_Obj_t * pObj;
+ int i, Counter;
+ assert( Abc_NtkIsSeq( pNtk ) );
+ Counter = 0;
+ Abc_NtkForEachPi( pNtk, pObj, i )
+ Counter += Seq_ObjFanoutLMax( pObj );
+ Abc_NtkForEachNode( pNtk, pObj, i )
+ Counter += Seq_ObjFanoutLMax( pObj );
+ return Counter;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Counts the number of latches in the sequential AIG.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Seq_ObjLatchGetInitNums( Abc_Obj_t * pObj, int Edge, int * pInits )
+{
+ Abc_InitType_t Init;
+ int nLatches, i;
+ nLatches = Seq_ObjFaninL( pObj, Edge );
+ for ( i = 0; i < nLatches; i++ )
+ {
+ Init = Seq_NodeGetInitOne( pObj, Edge, i );
+ pInits[Init]++;
+ }
+}
+
+/**Function*************************************************************
+
+ Synopsis [Counts the number of latches in the sequential AIG.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Seq_NtkLatchGetInitNums( Abc_Ntk_t * pNtk, int * pInits )
+{
+ Abc_Obj_t * pObj;
+ int i;
+ assert( Abc_NtkIsSeq( pNtk ) );
+ for ( i = 0; i < 4; i++ )
+ pInits[i] = 0;
+ Abc_NtkForEachPo( pNtk, pObj, i )
+ Seq_ObjLatchGetInitNums( pObj, 0, pInits );
+ Abc_NtkForEachNode( pNtk, pObj, i )
+ {
+ if ( Abc_ObjFaninNum(pObj) > 0 )
+ Seq_ObjLatchGetInitNums( pObj, 0, pInits );
+ if ( Abc_ObjFaninNum(pObj) > 1 )
+ Seq_ObjLatchGetInitNums( pObj, 1, pInits );
+ }
+}
+
+/**Function*************************************************************
+
+ Synopsis [Report nodes with equal fanins.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Seq_NtkLatchGetEqualFaninNum( Abc_Ntk_t * pNtk )
+{
+ Abc_Obj_t * pObj;
+ int i, Counter;
+ assert( Abc_NtkIsSeq( pNtk ) );
+ Counter = 0;
+ Abc_AigForEachAnd( pNtk, pObj, i )
+ if ( Abc_ObjFaninId0(pObj) == Abc_ObjFaninId1(pObj) )
+ Counter++;
+ if ( Counter )
+ printf( "The number of nodes with equal fanins = %d.\n", Counter );
+ return Counter;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Returns the maximum latch number on any of the fanouts.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Seq_NtkCountNodesAboveLimit( Abc_Ntk_t * pNtk, int Limit )
+{
+ Abc_Obj_t * pNode;
+ int i, Counter;
+ assert( !Abc_NtkIsSeq(pNtk) );
+ Counter = 0;
+ Abc_NtkForEachNode( pNtk, pNode, i )
+ if ( Abc_ObjFaninNum(pNode) > Limit )
+ Counter++;
+ return Counter;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Computes area flows.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Seq_MapComputeAreaFlows( Abc_Ntk_t * pNtk, int fVerbose )
+{
+ Abc_Seq_t * p = pNtk->pManFunc;
+ Abc_Obj_t * pObj;
+ float AFlow;
+ int i, c;
+
+ assert( Abc_NtkIsSeq(pNtk) );
+
+ Vec_IntFill( p->vAFlows, p->nSize, Abc_Float2Int( (float)0.0 ) );
+
+ // update all values iteratively
+ for ( c = 0; c < 7; c++ )
+ {
+ Abc_AigForEachAnd( pNtk, pObj, i )
+ {
+ AFlow = (float)1.0 + Seq_NodeGetFlow( Abc_ObjFanin0(pObj) ) + Seq_NodeGetFlow( Abc_ObjFanin1(pObj) );
+ AFlow /= Abc_ObjFanoutNum(pObj);
+ pObj->pNext = (void *)Abc_Float2Int( AFlow );
+ }
+ Abc_AigForEachAnd( pNtk, pObj, i )
+ {
+ AFlow = Abc_Int2Float( (int)pObj->pNext );
+ pObj->pNext = NULL;
+ Seq_NodeSetFlow( pObj, AFlow );
+
+// printf( "%5d : %6.1f\n", pObj->Id, Seq_NodeGetFlow(pObj) );
+ }
+// printf( "\n" );
+ }
+ return 1;
+}
+
+
+/**Function*************************************************************
+
+ Synopsis [Collects all the internal nodes reachable from POs.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Seq_NtkReachNodesFromPos_rec( Abc_Obj_t * pAnd, Vec_Ptr_t * vNodes )
+{
+ // skip if this is a non-PI node
+ if ( !Abc_AigNodeIsAnd(pAnd) )
+ return;
+ // skip a visited node
+ if ( Abc_NodeIsTravIdCurrent(pAnd) )
+ return;
+ Abc_NodeSetTravIdCurrent(pAnd);
+ // visit the fanin nodes
+ Seq_NtkReachNodesFromPos_rec( Abc_ObjFanin0(pAnd), vNodes );
+ Seq_NtkReachNodesFromPos_rec( Abc_ObjFanin1(pAnd), vNodes );
+ // add this node
+ Vec_PtrPush( vNodes, pAnd );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Collects all the internal nodes reachable from POs.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Seq_NtkReachNodesFromPis_rec( Abc_Obj_t * pAnd, Vec_Ptr_t * vNodes )
+{
+ Abc_Obj_t * pFanout;
+ int k;
+ // skip if this is a non-PI node
+ if ( !Abc_AigNodeIsAnd(pAnd) )
+ return;
+ // skip a visited node
+ if ( Abc_NodeIsTravIdCurrent(pAnd) )
+ return;
+ Abc_NodeSetTravIdCurrent(pAnd);
+ // visit the fanin nodes
+ Abc_ObjForEachFanout( pAnd, pFanout, k )
+ Seq_NtkReachNodesFromPis_rec( pFanout, vNodes );
+ // add this node
+ Vec_PtrPush( vNodes, pAnd );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Collects all the internal nodes reachable from POs.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Vec_Ptr_t * Seq_NtkReachNodes( Abc_Ntk_t * pNtk, int fFromPos )
+{
+ Vec_Ptr_t * vNodes;
+ Abc_Obj_t * pObj, * pFanout;
+ int i, k;
+ assert( Abc_NtkIsSeq(pNtk) );
+ vNodes = Vec_PtrAlloc( 1000 );
+ Abc_NtkIncrementTravId( pNtk );
+ if ( fFromPos )
+ {
+ // traverse the cone of each PO
+ Abc_NtkForEachPo( pNtk, pObj, i )
+ Seq_NtkReachNodesFromPos_rec( Abc_ObjFanin0(pObj), vNodes );
+ }
+ else
+ {
+ // tranvers the reverse cone of the constant node
+ pObj = Abc_AigConst1( pNtk );
+ Abc_ObjForEachFanout( pObj, pFanout, k )
+ Seq_NtkReachNodesFromPis_rec( pFanout, vNodes );
+ // tranvers the reverse cone of the PIs
+ Abc_NtkForEachPi( pNtk, pObj, i )
+ Abc_ObjForEachFanout( pObj, pFanout, k )
+ Seq_NtkReachNodesFromPis_rec( pFanout, vNodes );
+ }
+ return vNodes;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Perform sequential cleanup.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Seq_NtkCleanup( Abc_Ntk_t * pNtk, int fVerbose )
+{
+ Vec_Ptr_t * vNodesPo, * vNodesPi;
+ int Counter = 0;
+ assert( Abc_NtkIsSeq(pNtk) );
+ // collect the nodes reachable from POs and PIs
+ vNodesPo = Seq_NtkReachNodes( pNtk, 1 );
+ vNodesPi = Seq_NtkReachNodes( pNtk, 0 );
+ printf( "Total nodes = %6d. Reachable from POs = %6d. Reachable from PIs = %6d.\n",
+ Abc_NtkNodeNum(pNtk), Vec_PtrSize(vNodesPo), Vec_PtrSize(vNodesPi) );
+ if ( Abc_NtkNodeNum(pNtk) > Vec_PtrSize(vNodesPo) )
+ {
+// Counter = Abc_NtkReduceNodes( pNtk, vNodesPo );
+ Counter = 0;
+ if ( fVerbose )
+ printf( "Cleanup removed %d nodes that are not reachable from the POs.\n", Counter );
+ }
+ Vec_PtrFree( vNodesPo );
+ Vec_PtrFree( vNodesPi );
+ return Counter;
+}
+
+////////////////////////////////////////////////////////////////////////
+/// END OF FILE ///
+////////////////////////////////////////////////////////////////////////
+
+
diff --git a/src/base/temp.c b/src/base/temp.c
new file mode 100644
index 00000000..55709247
--- /dev/null
+++ b/src/base/temp.c
@@ -0,0 +1,83 @@
+
+/**Function*************************************************************
+
+ Synopsis [Command procedure to allow for static BDD variable ordering.]
+
+ Description [This procedure should be integrated in "abc\src\base\abci\abc.c"
+ similar to how procedure Abc_CommandReorder() is currently integrated.]
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Abc_CommandOrder( Abc_Frame_t * pAbc, int argc, char ** argv )
+{
+ FILE * pOut, * pErr, * pFile;
+ Abc_Ntk_t * pNtk;
+ char * pFileName;
+ int c;
+ int fReverse;
+ int fVerbose;
+ extern void Abc_NtkImplementCiOrder( Abc_Ntk_t * pNtk, char * pFileName, int fReverse, int fVerbose );
+ extern void Abc_NtkFindCiOrder( Abc_Ntk_t * pNtk, int fReverse, int fVerbose );
+
+ pNtk = Abc_FrameReadNtk(pAbc);
+ pOut = Abc_FrameReadOut(pAbc);
+ pErr = Abc_FrameReadErr(pAbc);
+
+ // set defaults
+ fReverse = 0;
+ fVerbose = 0;
+ Extra_UtilGetoptReset();
+ while ( ( c = Extra_UtilGetopt( argc, argv, "rvh" ) ) != EOF )
+ {
+ switch ( c )
+ {
+ case 'r':
+ fReverse ^= 1;
+ break;
+ case 'v':
+ fVerbose ^= 1;
+ break;
+ case 'h':
+ goto usage;
+ default:
+ goto usage;
+ }
+ }
+
+ if ( pNtk == NULL )
+ {
+ fprintf( pErr, "Empty network.\n" );
+ return 1;
+ }
+
+ // if the var order file is given, implement this order
+ pFileName = NULL;
+ if ( argc == globalUtilOptind + 1 )
+ {
+ pFileName = argv[globalUtilOptind];
+ pFile = fopen( pFileName, "r" );
+ if ( pFile == NULL )
+ {
+ fprintf( pErr, "Cannot open file \"%s\" with the BDD variable order.\n", pFileName );
+ return 1;
+ }
+ fclose( pFile );
+ }
+ if ( pFileName )
+ Abc_NtkImplementCiOrder( pNtk, pFileName, fReverse, fVerbose );
+ else
+ Abc_NtkFindCiOrder( pNtk, fReverse, fVerbose );
+ return 0;
+
+usage:
+ fprintf( pErr, "usage: order [-rvh] <file>\n" );
+ fprintf( pErr, "\t computes a good static CI variable order\n" );
+ fprintf( pErr, "\t-r : toggle reverse ordering [default = %s]\n", fReverse? "yes": "no" );
+ fprintf( pErr, "\t-v : prints verbose information [default = %s]\n", fVerbose? "yes": "no" );
+ fprintf( pErr, "\t-h : print the command usage\n");
+ fprintf( pErr, "\t<file> : (optional) file with the given variable order\n" );
+ return 1;
+}
diff --git a/src/base/ver/module.make b/src/base/ver/module.make
new file mode 100644
index 00000000..2cc37803
--- /dev/null
+++ b/src/base/ver/module.make
@@ -0,0 +1,4 @@
+SRC += src/base/ver/verCore.c \
+ src/base/ver/verFormula.c \
+ src/base/ver/verParse.c \
+ src/base/ver/verStream.c
diff --git a/src/base/ver/ver.h b/src/base/ver/ver.h
new file mode 100644
index 00000000..9c538ac4
--- /dev/null
+++ b/src/base/ver/ver.h
@@ -0,0 +1,118 @@
+/**CFile****************************************************************
+
+ FileName [ver.h]
+
+ SystemName [ABC: Logic synthesis and verification system.]
+
+ PackageName [Verilog parser.]
+
+ Synopsis [External declarations.]
+
+ Author [Alan Mishchenko]
+
+ Affiliation [UC Berkeley]
+
+ Date [Ver. 1.0. Started - August 19, 2006.]
+
+ Revision [$Id: ver.h,v 1.00 2006/08/19 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#ifndef __VER_H__
+#define __VER_H__
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+////////////////////////////////////////////////////////////////////////
+/// INCLUDES ///
+////////////////////////////////////////////////////////////////////////
+
+#include <stdio.h>
+#include "abc.h"
+
+////////////////////////////////////////////////////////////////////////
+/// PARAMETERS ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+/// BASIC TYPES ///
+////////////////////////////////////////////////////////////////////////
+
+typedef struct Ver_Man_t_ Ver_Man_t;
+typedef struct Ver_Stream_t_ Ver_Stream_t;
+
+struct Ver_Man_t_
+{
+ // internal parameters
+ int fMapped; // mapped verilog
+ int fUseMemMan; // allocate memory manager in the networks
+ int fCheck; // checks network for currectness
+ // input file stream
+ char * pFileName;
+ Ver_Stream_t * pReader;
+ int fNameLast;
+ ProgressBar * pProgress;
+ // current design
+ Abc_Lib_t * pDesign;
+ st_table * tName2Suffix;
+ // error handling
+ FILE * Output;
+ int fTopLevel;
+ int fError;
+ char sError[2000];
+ // intermediate structures
+ Vec_Ptr_t * vNames;
+ Vec_Ptr_t * vStackFn;
+ Vec_Int_t * vStackOp;
+ Vec_Int_t * vPerm;
+};
+
+
+////////////////////////////////////////////////////////////////////////
+/// MACRO DEFINITIONS ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+/// ITERATORS ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+/// FUNCTION DECLARATIONS ///
+////////////////////////////////////////////////////////////////////////
+
+/*=== verCore.c ========================================================*/
+extern Abc_Lib_t * Ver_ParseFile( char * pFileName, Abc_Lib_t * pGateLib, int fCheck, int fUseMemMan );
+extern void Ver_ParsePrintErrorMessage( Ver_Man_t * p );
+/*=== verFormula.c ========================================================*/
+extern void * Ver_FormulaParser( char * pFormula, void * pMan, Vec_Ptr_t * vNames, Vec_Ptr_t * vStackFn, Vec_Int_t * vStackOp, char * pErrorMessage );
+extern void * Ver_FormulaReduction( char * pFormula, void * pMan, Vec_Ptr_t * vNames, char * pErrorMessage );
+/*=== verParse.c ========================================================*/
+extern int Ver_ParseSkipComments( Ver_Man_t * p );
+extern char * Ver_ParseGetName( Ver_Man_t * p );
+/*=== verStream.c ========================================================*/
+extern Ver_Stream_t * Ver_StreamAlloc( char * pFileName );
+extern void Ver_StreamFree( Ver_Stream_t * p );
+extern char * Ver_StreamGetFileName( Ver_Stream_t * p );
+extern int Ver_StreamGetFileSize( Ver_Stream_t * p );
+extern int Ver_StreamGetCurPosition( Ver_Stream_t * p );
+extern int Ver_StreamGetLineNumber( Ver_Stream_t * p );
+
+extern int Ver_StreamIsOkey( Ver_Stream_t * p );
+extern char Ver_StreamScanChar( Ver_Stream_t * p );
+extern char Ver_StreamPopChar( Ver_Stream_t * p );
+extern void Ver_StreamSkipChars( Ver_Stream_t * p, char * pCharsToSkip );
+extern void Ver_StreamSkipToChars( Ver_Stream_t * p, char * pCharsToStop );
+extern char * Ver_StreamGetWord( Ver_Stream_t * p, char * pCharsToStop );
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
+
+////////////////////////////////////////////////////////////////////////
+/// END OF FILE ///
+////////////////////////////////////////////////////////////////////////
+
diff --git a/src/base/ver/verCore.c b/src/base/ver/verCore.c
new file mode 100644
index 00000000..322ce720
--- /dev/null
+++ b/src/base/ver/verCore.c
@@ -0,0 +1,2949 @@
+/**CFile****************************************************************
+
+ FileName [verCore.c]
+
+ SystemName [ABC: Logic synthesis and verification system.]
+
+ PackageName [Verilog parser.]
+
+ Synopsis [Parses several flavors of structural Verilog.]
+
+ Author [Alan Mishchenko]
+
+ Affiliation [UC Berkeley]
+
+ Date [Ver. 1.0. Started - August 19, 2006.]
+
+ Revision [$Id: verCore.c,v 1.00 2006/08/19 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "ver.h"
+#include "mio.h"
+#include "main.h"
+
+////////////////////////////////////////////////////////////////////////
+/// DECLARATIONS ///
+////////////////////////////////////////////////////////////////////////
+
+// types of verilog signals
+typedef enum {
+ VER_SIG_NONE = 0,
+ VER_SIG_INPUT,
+ VER_SIG_OUTPUT,
+ VER_SIG_INOUT,
+ VER_SIG_REG,
+ VER_SIG_WIRE
+} Ver_SignalType_t;
+
+// types of verilog gates
+typedef enum {
+ VER_GATE_AND = 0,
+ VER_GATE_OR,
+ VER_GATE_XOR,
+ VER_GATE_BUF,
+ VER_GATE_NAND,
+ VER_GATE_NOR,
+ VER_GATE_XNOR,
+ VER_GATE_NOT
+} Ver_GateType_t;
+
+static Ver_Man_t * Ver_ParseStart( char * pFileName, Abc_Lib_t * pGateLib );
+static void Ver_ParseStop( Ver_Man_t * p );
+static void Ver_ParseFreeData( Ver_Man_t * p );
+static void Ver_ParseInternal( Ver_Man_t * p );
+static int Ver_ParseModule( Ver_Man_t * p );
+static int Ver_ParseSignal( Ver_Man_t * p, Abc_Ntk_t * pNtk, Ver_SignalType_t SigType );
+static int Ver_ParseAlways( Ver_Man_t * p, Abc_Ntk_t * pNtk );
+static int Ver_ParseInitial( Ver_Man_t * p, Abc_Ntk_t * pNtk );
+static int Ver_ParseAssign( Ver_Man_t * p, Abc_Ntk_t * pNtk );
+static int Ver_ParseGateStandard( Ver_Man_t * pMan, Abc_Ntk_t * pNtk, Ver_GateType_t GateType );
+static int Ver_ParseFlopStandard( Ver_Man_t * pMan, Abc_Ntk_t * pNtk );
+static int Ver_ParseGate( Ver_Man_t * p, Abc_Ntk_t * pNtk, Mio_Gate_t * pGate );
+static int Ver_ParseBox( Ver_Man_t * pMan, Abc_Ntk_t * pNtk, Abc_Ntk_t * pNtkBox );
+static int Ver_ParseConnectBox( Ver_Man_t * pMan, Abc_Obj_t * pBox );
+static int Ver_ParseAttachBoxes( Ver_Man_t * pMan );
+
+static Abc_Obj_t * Ver_ParseCreatePi( Abc_Ntk_t * pNtk, char * pName );
+static Abc_Obj_t * Ver_ParseCreatePo( Abc_Ntk_t * pNtk, char * pName );
+static Abc_Obj_t * Ver_ParseCreateLatch( Abc_Ntk_t * pNtk, Abc_Obj_t * pNetLI, Abc_Obj_t * pNetLO );
+static Abc_Obj_t * Ver_ParseCreateInv( Abc_Ntk_t * pNtk, Abc_Obj_t * pNet );
+
+static void Ver_ParseRemoveSuffixTable( Ver_Man_t * pMan );
+
+static inline int Ver_NtkIsDefined( Abc_Ntk_t * pNtkBox ) { assert( pNtkBox->pName ); return Abc_NtkPiNum(pNtkBox) || Abc_NtkPoNum(pNtkBox); }
+static inline int Ver_ObjIsConnected( Abc_Obj_t * pObj ) { assert( Abc_ObjIsBox(pObj) ); return Abc_ObjFaninNum(pObj) || Abc_ObjFanoutNum(pObj); }
+
+int glo_fMapped = 0; // this is bad!
+
+typedef struct Ver_Bundle_t_ Ver_Bundle_t;
+struct Ver_Bundle_t_
+{
+ char * pNameFormal; // the name of the formal net
+ Vec_Ptr_t * vNetsActual; // the vector of actual nets (MSB to LSB)
+};
+
+////////////////////////////////////////////////////////////////////////
+/// FUNCTION DEFINITIONS ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+ Synopsis [Start parser.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Ver_Man_t * Ver_ParseStart( char * pFileName, Abc_Lib_t * pGateLib )
+{
+ Ver_Man_t * p;
+ p = ALLOC( Ver_Man_t, 1 );
+ memset( p, 0, sizeof(Ver_Man_t) );
+ p->pFileName = pFileName;
+ p->pReader = Ver_StreamAlloc( pFileName );
+ if ( p->pReader == NULL )
+ return NULL;
+ p->Output = stdout;
+ p->vNames = Vec_PtrAlloc( 100 );
+ p->vStackFn = Vec_PtrAlloc( 100 );
+ p->vStackOp = Vec_IntAlloc( 100 );
+ p->vPerm = Vec_IntAlloc( 100 );
+ // create the design library and assign the technology library
+ p->pDesign = Abc_LibCreate( pFileName );
+ p->pDesign->pLibrary = pGateLib;
+ p->pDesign->pGenlib = Abc_FrameReadLibGen();
+ return p;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Stop parser.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Ver_ParseStop( Ver_Man_t * p )
+{
+ if ( p->pProgress )
+ Extra_ProgressBarStop( p->pProgress );
+ Ver_StreamFree( p->pReader );
+ Vec_PtrFree( p->vNames );
+ Vec_PtrFree( p->vStackFn );
+ Vec_IntFree( p->vStackOp );
+ Vec_IntFree( p->vPerm );
+ free( p );
+}
+
+/**Function*************************************************************
+
+ Synopsis [File parser.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Abc_Lib_t * Ver_ParseFile( char * pFileName, Abc_Lib_t * pGateLib, int fCheck, int fUseMemMan )
+{
+ Ver_Man_t * p;
+ Abc_Lib_t * pDesign;
+ // start the parser
+ p = Ver_ParseStart( pFileName, pGateLib );
+ p->fMapped = glo_fMapped;
+ p->fCheck = fCheck;
+ p->fUseMemMan = fUseMemMan;
+ if ( glo_fMapped )
+ {
+ Hop_ManStop(p->pDesign->pManFunc);
+ p->pDesign->pManFunc = NULL;
+ }
+ // parse the file
+ Ver_ParseInternal( p );
+ // save the result
+ pDesign = p->pDesign;
+ p->pDesign = NULL;
+ // stop the parser
+ Ver_ParseStop( p );
+ return pDesign;
+}
+
+/**Function*************************************************************
+
+ Synopsis [File parser.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Ver_ParseInternal( Ver_Man_t * pMan )
+{
+ Abc_Ntk_t * pNtk;
+ char * pToken;
+ int i;
+
+ // preparse the modeles
+ pMan->pProgress = Extra_ProgressBarStart( stdout, Ver_StreamGetFileSize(pMan->pReader) );
+ while ( 1 )
+ {
+ // get the next token
+ pToken = Ver_ParseGetName( pMan );
+ if ( pToken == NULL )
+ break;
+ if ( strcmp( pToken, "module" ) )
+ {
+ sprintf( pMan->sError, "Cannot read \"module\" directive." );
+ Ver_ParsePrintErrorMessage( pMan );
+ return;
+ }
+ // parse the module
+ if ( !Ver_ParseModule(pMan) )
+ return;
+ }
+ Extra_ProgressBarStop( pMan->pProgress );
+ pMan->pProgress = NULL;
+
+ // process defined and undefined boxes
+ if ( !Ver_ParseAttachBoxes( pMan ) )
+ return;
+
+ // connect the boxes and check
+ Vec_PtrForEachEntry( pMan->pDesign->vModules, pNtk, i )
+ {
+ // fix the dangling nets
+ Abc_NtkFinalizeRead( pNtk );
+ // check the network for correctness
+ if ( pMan->fCheck && !Abc_NtkCheckRead( pNtk ) )
+ {
+ pMan->fTopLevel = 1;
+ sprintf( pMan->sError, "The network check has failed for network %s.", pNtk->pName );
+ Ver_ParsePrintErrorMessage( pMan );
+ return;
+ }
+ }
+}
+
+/**Function*************************************************************
+
+ Synopsis [File parser.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Ver_ParseFreeData( Ver_Man_t * p )
+{
+ if ( p->pDesign )
+ {
+ Abc_LibFree( p->pDesign, NULL );
+ p->pDesign = NULL;
+ }
+}
+
+/**Function*************************************************************
+
+ Synopsis [Prints the error message including the file name and line number.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Ver_ParsePrintErrorMessage( Ver_Man_t * p )
+{
+ p->fError = 1;
+ if ( p->fTopLevel ) // the line number is not given
+ fprintf( p->Output, "%s: %s\n", p->pFileName, p->sError );
+ else // print the error message with the line number
+ fprintf( p->Output, "%s (line %d): %s\n",
+ p->pFileName, Ver_StreamGetLineNumber(p->pReader), p->sError );
+ // free the data
+ Ver_ParseFreeData( p );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Finds the network by name or create a new blackbox network.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Abc_Ntk_t * Ver_ParseFindOrCreateNetwork( Ver_Man_t * pMan, char * pName )
+{
+ Abc_Ntk_t * pNtkNew;
+ // check if the network exists
+ if ( pNtkNew = Abc_LibFindModelByName( pMan->pDesign, pName ) )
+ return pNtkNew;
+//printf( "Creating network %s.\n", pName );
+ // create new network
+ pNtkNew = Abc_NtkAlloc( ABC_NTK_NETLIST, ABC_FUNC_BLACKBOX, pMan->fUseMemMan );
+ pNtkNew->pName = Extra_UtilStrsav( pName );
+ pNtkNew->pSpec = NULL;
+ // add module to the design
+ Abc_LibAddModel( pMan->pDesign, pNtkNew );
+ return pNtkNew;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Finds the network by name or create a new blackbox network.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Abc_Obj_t * Ver_ParseFindNet( Abc_Ntk_t * pNtk, char * pName )
+{
+ Abc_Obj_t * pObj;
+ if ( pObj = Abc_NtkFindNet(pNtk, pName) )
+ return pObj;
+ if ( !strcmp( pName, "1\'b0" ) || !strcmp( pName, "1\'bx" ) )
+ return Abc_NtkFindOrCreateNet( pNtk, "1\'b0" );
+ if ( !strcmp( pName, "1\'b1" ) )
+ return Abc_NtkFindOrCreateNet( pNtk, "1\'b1" );
+ return NULL;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Converts the network from the blackbox type into a different one.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Ver_ParseConvertNetwork( Ver_Man_t * pMan, Abc_Ntk_t * pNtk, int fMapped )
+{
+ if ( fMapped )
+ {
+ // convert from the blackbox into the network with local functions representated by AIGs
+ if ( pNtk->ntkFunc == ABC_FUNC_BLACKBOX )
+ {
+ // change network type
+ assert( pNtk->pManFunc == NULL );
+ pNtk->ntkFunc = ABC_FUNC_MAP;
+ pNtk->pManFunc = pMan->pDesign->pGenlib;
+ }
+ else if ( pNtk->ntkFunc != ABC_FUNC_MAP )
+ {
+ sprintf( pMan->sError, "The network %s appears to have both gates and assign statements. Currently such network are not allowed. One way to fix this problem might be to replace assigns by buffers from the library.", pNtk->pName );
+ Ver_ParsePrintErrorMessage( pMan );
+ return 0;
+ }
+ }
+ else
+ {
+ // convert from the blackbox into the network with local functions representated by AIGs
+ if ( pNtk->ntkFunc == ABC_FUNC_BLACKBOX )
+ {
+ // change network type
+ assert( pNtk->pManFunc == NULL );
+ pNtk->ntkFunc = ABC_FUNC_AIG;
+ pNtk->pManFunc = pMan->pDesign->pManFunc;
+ }
+ else if ( pNtk->ntkFunc != ABC_FUNC_AIG )
+ {
+ sprintf( pMan->sError, "The network %s appears to have both gates and assign statements. Currently such network are not allowed. One way to fix this problem might be to replace assigns by buffers from the library.", pNtk->pName );
+ Ver_ParsePrintErrorMessage( pMan );
+ return 0;
+ }
+ }
+ return 1;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Parses one Verilog module.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Ver_ParseModule( Ver_Man_t * pMan )
+{
+ Mio_Gate_t * pGate;
+ Ver_Stream_t * p = pMan->pReader;
+ Abc_Ntk_t * pNtk, * pNtkTemp;
+ char * pWord, Symbol;
+ int RetValue;
+
+ // get the network name
+ pWord = Ver_ParseGetName( pMan );
+
+ // get the network with this name
+ pNtk = Ver_ParseFindOrCreateNetwork( pMan, pWord );
+
+ // make sure we stopped at the opening paranthesis
+ if ( Ver_StreamPopChar(p) != '(' )
+ {
+ sprintf( pMan->sError, "Cannot find \"(\" after \"module\" in network %s.", pNtk->pName );
+ Ver_ParsePrintErrorMessage( pMan );
+ return 0;
+ }
+
+ // skip to the end of parantheses
+ do {
+ if ( Ver_ParseGetName( pMan ) == NULL )
+ return 0;
+ Symbol = Ver_StreamPopChar(p);
+ } while ( Symbol == ',' );
+ assert( Symbol == ')' );
+ if ( !Ver_ParseSkipComments( pMan ) )
+ return 0;
+ Symbol = Ver_StreamPopChar(p);
+ if ( Symbol != ';' )
+ {
+ sprintf( pMan->sError, "Expected closing paranthesis after \"module\"." );
+ Ver_ParsePrintErrorMessage( pMan );
+ return 0;
+ }
+
+ // parse the inputs/outputs/registers/wires/inouts
+ while ( 1 )
+ {
+ Extra_ProgressBarUpdate( pMan->pProgress, Ver_StreamGetCurPosition(p), NULL );
+ pWord = Ver_ParseGetName( pMan );
+ if ( pWord == NULL )
+ return 0;
+ if ( !strcmp( pWord, "input" ) )
+ RetValue = Ver_ParseSignal( pMan, pNtk, VER_SIG_INPUT );
+ else if ( !strcmp( pWord, "output" ) )
+ RetValue = Ver_ParseSignal( pMan, pNtk, VER_SIG_OUTPUT );
+ else if ( !strcmp( pWord, "reg" ) )
+ RetValue = Ver_ParseSignal( pMan, pNtk, VER_SIG_REG );
+ else if ( !strcmp( pWord, "wire" ) )
+ RetValue = Ver_ParseSignal( pMan, pNtk, VER_SIG_WIRE );
+ else if ( !strcmp( pWord, "inout" ) )
+ RetValue = Ver_ParseSignal( pMan, pNtk, VER_SIG_INOUT );
+ else
+ break;
+ if ( RetValue == 0 )
+ return 0;
+ }
+
+ // parse the remaining statements
+ while ( 1 )
+ {
+ Extra_ProgressBarUpdate( pMan->pProgress, Ver_StreamGetCurPosition(p), NULL );
+
+ if ( !strcmp( pWord, "and" ) )
+ RetValue = Ver_ParseGateStandard( pMan, pNtk, VER_GATE_AND );
+ else if ( !strcmp( pWord, "or" ) )
+ RetValue = Ver_ParseGateStandard( pMan, pNtk, VER_GATE_OR );
+ else if ( !strcmp( pWord, "xor" ) )
+ RetValue = Ver_ParseGateStandard( pMan, pNtk, VER_GATE_XOR );
+ else if ( !strcmp( pWord, "buf" ) )
+ RetValue = Ver_ParseGateStandard( pMan, pNtk, VER_GATE_BUF );
+ else if ( !strcmp( pWord, "nand" ) )
+ RetValue = Ver_ParseGateStandard( pMan, pNtk, VER_GATE_NAND );
+ else if ( !strcmp( pWord, "nor" ) )
+ RetValue = Ver_ParseGateStandard( pMan, pNtk, VER_GATE_NOR );
+ else if ( !strcmp( pWord, "xnor" ) )
+ RetValue = Ver_ParseGateStandard( pMan, pNtk, VER_GATE_XNOR );
+ else if ( !strcmp( pWord, "not" ) )
+ RetValue = Ver_ParseGateStandard( pMan, pNtk, VER_GATE_NOT );
+
+ else if ( !strcmp( pWord, "dff" ) )
+ RetValue = Ver_ParseFlopStandard( pMan, pNtk );
+
+ else if ( !strcmp( pWord, "assign" ) )
+ RetValue = Ver_ParseAssign( pMan, pNtk );
+ else if ( !strcmp( pWord, "always" ) )
+ RetValue = Ver_ParseAlways( pMan, pNtk );
+ else if ( !strcmp( pWord, "initial" ) )
+ RetValue = Ver_ParseInitial( pMan, pNtk );
+ else if ( !strcmp( pWord, "endmodule" ) )
+ break;
+ else if ( pMan->pDesign->pGenlib && (pGate = Mio_LibraryReadGateByName(pMan->pDesign->pGenlib, pWord)) ) // current design
+ RetValue = Ver_ParseGate( pMan, pNtk, pGate );
+// else if ( pMan->pDesign->pLibrary && st_lookup(pMan->pDesign->pLibrary->tModules, pWord, (char**)&pNtkTemp) ) // gate library
+// RetValue = Ver_ParseGate( pMan, pNtkTemp );
+ else // assume this is the box used in the current design
+ {
+ pNtkTemp = Ver_ParseFindOrCreateNetwork( pMan, pWord );
+ RetValue = Ver_ParseBox( pMan, pNtk, pNtkTemp );
+ }
+ if ( RetValue == 0 )
+ return 0;
+ // skip the comments
+ if ( !Ver_ParseSkipComments( pMan ) )
+ return 0;
+ // get new word
+ pWord = Ver_ParseGetName( pMan );
+ if ( pWord == NULL )
+ return 0;
+ }
+
+ // convert from the blackbox into the network with local functions representated by AIGs
+ if ( pNtk->ntkFunc == ABC_FUNC_BLACKBOX )
+ {
+ if ( Abc_NtkNodeNum(pNtk) > 0 || Abc_NtkBoxNum(pNtk) > 0 )
+ {
+ if ( !Ver_ParseConvertNetwork( pMan, pNtk, pMan->fMapped ) )
+ return 0;
+ }
+ else
+ {
+ Abc_Obj_t * pObj, * pBox, * pTerm;
+ int i;
+ pBox = Abc_NtkCreateBlackbox(pNtk);
+ Abc_NtkForEachPi( pNtk, pObj, i )
+ {
+ pTerm = Abc_NtkCreateBi(pNtk);
+ Abc_ObjAddFanin( pTerm, Abc_ObjFanout0(pObj) );
+ Abc_ObjAddFanin( pBox, pTerm );
+ }
+ Abc_NtkForEachPo( pNtk, pObj, i )
+ {
+ pTerm = Abc_NtkCreateBo(pNtk);
+ Abc_ObjAddFanin( pTerm, pBox );
+ Abc_ObjAddFanin( Abc_ObjFanin0(pObj), pTerm );
+ }
+ }
+ }
+
+ // remove the table if needed
+ Ver_ParseRemoveSuffixTable( pMan );
+ return 1;
+}
+
+
+/**Function*************************************************************
+
+ Synopsis [Lookups the suffix of the signal of the form [m:n].]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Ver_ParseLookupSuffix( Ver_Man_t * pMan, char * pWord, int * pnMsb, int * pnLsb )
+{
+ unsigned Value;
+ *pnMsb = *pnLsb = -1;
+ if ( pMan->tName2Suffix == NULL )
+ return 1;
+ if ( !st_lookup( pMan->tName2Suffix, (char *)pWord, (char **)&Value ) )
+ return 1;
+ *pnMsb = (Value >> 8) & 0xff;
+ *pnLsb = Value & 0xff;
+ return 1;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Lookups the suffix of the signal of the form [m:n].]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Ver_ParseInsertsSuffix( Ver_Man_t * pMan, char * pWord, int nMsb, int nLsb )
+{
+ unsigned Value;
+ if ( pMan->tName2Suffix == NULL )
+ pMan->tName2Suffix = st_init_table( strcmp, st_strhash );
+ if ( st_is_member( pMan->tName2Suffix, pWord ) )
+ return 1;
+ assert( nMsb >= 0 && nMsb < 128 );
+ assert( nLsb >= 0 && nLsb < 128 );
+ Value = (nMsb << 8) | nLsb;
+ st_insert( pMan->tName2Suffix, Extra_UtilStrsav(pWord), (char *)Value );
+ return 1;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Lookups the suffic of the signal of the form [m:n].]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Ver_ParseRemoveSuffixTable( Ver_Man_t * pMan )
+{
+ st_generator * gen;
+ char * pKey, * pValue;
+ if ( pMan->tName2Suffix == NULL )
+ return;
+ st_foreach_item( pMan->tName2Suffix, gen, (char **)&pKey, (char **)&pValue )
+ free( pKey );
+ st_free_table( pMan->tName2Suffix );
+ pMan->tName2Suffix = NULL;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Determine signal prefix of the form [Beg:End].]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Ver_ParseSignalPrefix( Ver_Man_t * pMan, char ** ppWord, int * pnMsb, int * pnLsb )
+{
+ char * pWord = *ppWord;
+ int nMsb, nLsb;
+ assert( pWord[0] == '[' );
+ // get the beginning
+ nMsb = atoi( pWord + 1 );
+ // find the splitter
+ while ( *pWord && *pWord != ':' && *pWord != ']' )
+ pWord++;
+ if ( *pWord == 0 )
+ {
+ sprintf( pMan->sError, "Cannot find closing bracket in this line." );
+ Ver_ParsePrintErrorMessage( pMan );
+ return 0;
+ }
+ if ( *pWord == ']' )
+ nLsb = nMsb;
+ else
+ {
+ assert( *pWord == ':' );
+ nLsb = atoi( pWord + 1 );
+ // find the closing paranthesis
+ while ( *pWord && *pWord != ']' )
+ pWord++;
+ if ( *pWord == 0 )
+ {
+ sprintf( pMan->sError, "Cannot find closing bracket in this line." );
+ Ver_ParsePrintErrorMessage( pMan );
+ return 0;
+ }
+ assert( *pWord == ']' );
+ pWord++;
+ }
+ assert( nMsb >= 0 && nLsb >= 0 );
+ // return
+ *ppWord = pWord;
+ *pnMsb = nMsb;
+ *pnLsb = nLsb;
+ return 1;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Determine signal suffix of the form [m:n].]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Ver_ParseSignalSuffix( Ver_Man_t * pMan, char * pWord, int * pnMsb, int * pnLsb )
+{
+ char * pCur;
+ int Length;
+ Length = strlen(pWord);
+ assert( pWord[Length-1] == ']' );
+ // walk backward
+ for ( pCur = pWord + Length - 2; pCur != pWord; pCur-- )
+ if ( *pCur == ':' || *pCur == '[' )
+ break;
+ if ( pCur == pWord )
+ {
+ sprintf( pMan->sError, "Cannot find opening bracket in signal name %s.", pWord );
+ Ver_ParsePrintErrorMessage( pMan );
+ return 0;
+ }
+ if ( *pCur == '[' )
+ {
+ *pnMsb = *pnLsb = atoi(pCur+1);
+ *pCur = 0;
+ return 1;
+ }
+ assert( *pCur == ':' );
+ // get the end of the interval
+ *pnLsb = atoi(pCur+1);
+ // find the beginning
+ for ( pCur = pWord + Length - 2; pCur != pWord; pCur-- )
+ if ( *pCur == '[' )
+ break;
+ if ( pCur == pWord )
+ {
+ sprintf( pMan->sError, "Cannot find opening bracket in signal name %s.", pWord );
+ Ver_ParsePrintErrorMessage( pMan );
+ return 0;
+ }
+ assert( *pCur == '[' );
+ // get the beginning of the interval
+ *pnMsb = atoi(pCur+1);
+ // cut the word
+ *pCur = 0;
+ return 1;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Returns the values of constant bits.]
+
+ Description [The resulting bits are in MSB to LSB order.]
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Ver_ParseConstant( Ver_Man_t * pMan, char * pWord )
+{
+ int nBits, i;
+ assert( pWord[0] >= '1' && pWord[1] <= '9' );
+ nBits = atoi(pWord);
+ // find the next symbol \'
+ while ( *pWord && *pWord != '\'' )
+ pWord++;
+ if ( *pWord == 0 )
+ {
+ sprintf( pMan->sError, "Cannot find symbol \' in the constant." );
+ Ver_ParsePrintErrorMessage( pMan );
+ return 0;
+ }
+ assert( *pWord == '\'' );
+ pWord++;
+ if ( *pWord != 'b' )
+ {
+ sprintf( pMan->sError, "Currently can only handle binary constants." );
+ Ver_ParsePrintErrorMessage( pMan );
+ return 0;
+ }
+ pWord++;
+ // scan the bits
+ Vec_PtrClear( pMan->vNames );
+ for ( i = 0; i < nBits; i++ )
+ {
+ if ( pWord[i] != '0' && pWord[i] != '1' && pWord[i] != 'x' )
+ {
+ sprintf( pMan->sError, "Having problem parsing the binary constant." );
+ Ver_ParsePrintErrorMessage( pMan );
+ return 0;
+ }
+ if ( pWord[i] == 'x' )
+ Vec_PtrPush( pMan->vNames, (void *)0 );
+ else
+ Vec_PtrPush( pMan->vNames, (void *)(pWord[i]-'0') );
+ }
+ return 1;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Parses one directive.]
+
+ Description [The signals are added in the order from LSB to MSB.]
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Ver_ParseSignal( Ver_Man_t * pMan, Abc_Ntk_t * pNtk, Ver_SignalType_t SigType )
+{
+ Ver_Stream_t * p = pMan->pReader;
+ char Buffer[1000], Symbol, * pWord;
+ int nMsb, nLsb, Bit, Limit, i;
+ nMsb = nLsb = -1;
+ while ( 1 )
+ {
+ // get the next word
+ pWord = Ver_ParseGetName( pMan );
+ if ( pWord == NULL )
+ return 0;
+
+ // check if the range is specified
+ if ( pWord[0] == '[' && !pMan->fNameLast )
+ {
+ assert( nMsb == -1 && nLsb == -1 );
+ Ver_ParseSignalPrefix( pMan, &pWord, &nMsb, &nLsb );
+ // check the case when there is space between bracket and the next word
+ if ( *pWord == 0 )
+ {
+ // get the signal name
+ pWord = Ver_ParseGetName( pMan );
+ if ( pWord == NULL )
+ return 0;
+ }
+ }
+
+ // create signals
+ if ( nMsb == -1 && nLsb == -1 )
+ {
+ if ( SigType == VER_SIG_INPUT || SigType == VER_SIG_INOUT )
+ Ver_ParseCreatePi( pNtk, pWord );
+ if ( SigType == VER_SIG_OUTPUT || SigType == VER_SIG_INOUT )
+ Ver_ParseCreatePo( pNtk, pWord );
+ if ( SigType == VER_SIG_WIRE || SigType == VER_SIG_REG )
+ Abc_NtkFindOrCreateNet( pNtk, pWord );
+ }
+ else
+ {
+ assert( nMsb >= 0 && nLsb >= 0 );
+ // add to the hash table
+ Ver_ParseInsertsSuffix( pMan, pWord, nMsb, nLsb );
+ // add signals from Lsb to Msb
+ Limit = nMsb > nLsb? nMsb - nLsb + 1: nLsb - nMsb + 1;
+ for ( i = 0, Bit = nLsb; i < Limit; i++, Bit = nMsb > nLsb ? Bit + 1: Bit - 1 )
+ {
+ sprintf( Buffer, "%s[%d]", pWord, Bit );
+ if ( SigType == VER_SIG_INPUT || SigType == VER_SIG_INOUT )
+ Ver_ParseCreatePi( pNtk, Buffer );
+ if ( SigType == VER_SIG_OUTPUT || SigType == VER_SIG_INOUT )
+ Ver_ParseCreatePo( pNtk, Buffer );
+ if ( SigType == VER_SIG_WIRE || SigType == VER_SIG_REG )
+ Abc_NtkFindOrCreateNet( pNtk, Buffer );
+ }
+ }
+
+ Symbol = Ver_StreamPopChar(p);
+ if ( Symbol == ',' )
+ continue;
+ if ( Symbol == ';' )
+ return 1;
+ break;
+ }
+ sprintf( pMan->sError, "Cannot parse signal line (expected , or ;)." );
+ Ver_ParsePrintErrorMessage( pMan );
+ return 0;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Parses one directive.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Ver_ParseAlways( Ver_Man_t * pMan, Abc_Ntk_t * pNtk )
+{
+ Ver_Stream_t * p = pMan->pReader;
+ Abc_Obj_t * pNet, * pNet2;
+ int fStopAfterOne;
+ char * pWord, * pWord2;
+ char Symbol;
+ // parse the directive
+ pWord = Ver_ParseGetName( pMan );
+ if ( pWord == NULL )
+ return 0;
+ if ( pWord[0] == '@' )
+ {
+ Ver_StreamSkipToChars( p, ")" );
+ Ver_StreamPopChar(p);
+ // parse the directive
+ pWord = Ver_ParseGetName( pMan );
+ if ( pWord == NULL )
+ return 0;
+ }
+ // decide how many statements to parse
+ fStopAfterOne = 0;
+ if ( strcmp( pWord, "begin" ) )
+ fStopAfterOne = 1;
+ // iterate over the initial states
+ while ( 1 )
+ {
+ if ( !fStopAfterOne )
+ {
+ // get the name of the output signal
+ pWord = Ver_ParseGetName( pMan );
+ if ( pWord == NULL )
+ return 0;
+ // look for the end of directive
+ if ( !strcmp( pWord, "end" ) )
+ break;
+ }
+ // get the fanout net
+ pNet = Ver_ParseFindNet( pNtk, pWord );
+ if ( pNet == NULL )
+ {
+ sprintf( pMan->sError, "Cannot read the always statement for %s (output wire is not defined).", pWord );
+ Ver_ParsePrintErrorMessage( pMan );
+ return 0;
+ }
+ // get the equality sign
+ Symbol = Ver_StreamPopChar(p);
+ if ( Symbol != '<' && Symbol != '=' )
+ {
+ sprintf( pMan->sError, "Cannot read the assign statement for %s (expected <= or =).", pWord );
+ Ver_ParsePrintErrorMessage( pMan );
+ return 0;
+ }
+ if ( Symbol == '<' )
+ Ver_StreamPopChar(p);
+ // skip the comments
+ if ( !Ver_ParseSkipComments( pMan ) )
+ return 0;
+ // get the second name
+ pWord2 = Ver_ParseGetName( pMan );
+ if ( pWord2 == NULL )
+ return 0;
+ // check if the name is complemented
+ if ( pWord2[0] == '~' )
+ {
+ pNet2 = Ver_ParseFindNet( pNtk, pWord2+1 );
+ pNet2 = Ver_ParseCreateInv( pNtk, pNet2 );
+ }
+ else
+ pNet2 = Ver_ParseFindNet( pNtk, pWord2 );
+ if ( pNet2 == NULL )
+ {
+ sprintf( pMan->sError, "Cannot read the always statement for %s (input wire is not defined).", pWord2 );
+ Ver_ParsePrintErrorMessage( pMan );
+ return 0;
+ }
+ // create the latch
+ Ver_ParseCreateLatch( pNtk, pNet2, pNet );
+ // remove the last symbol
+ Symbol = Ver_StreamPopChar(p);
+ assert( Symbol == ';' );
+ // quit if only one directive
+ if ( fStopAfterOne )
+ break;
+ }
+ return 1;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Parses one directive.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Ver_ParseInitial( Ver_Man_t * pMan, Abc_Ntk_t * pNtk )
+{
+ Ver_Stream_t * p = pMan->pReader;
+ Abc_Obj_t * pNode, * pNet;
+ int fStopAfterOne;
+ char * pWord, * pEquation;
+ char Symbol;
+ // parse the directive
+ pWord = Ver_ParseGetName( pMan );
+ if ( pWord == NULL )
+ return 0;
+ // decide how many statements to parse
+ fStopAfterOne = 0;
+ if ( strcmp( pWord, "begin" ) )
+ fStopAfterOne = 1;
+ // iterate over the initial states
+ while ( 1 )
+ {
+ if ( !fStopAfterOne )
+ {
+ // get the name of the output signal
+ pWord = Ver_ParseGetName( pMan );
+ if ( pWord == NULL )
+ return 0;
+ // look for the end of directive
+ if ( !strcmp( pWord, "end" ) )
+ break;
+ }
+ // get the fanout net
+ pNet = Ver_ParseFindNet( pNtk, pWord );
+ if ( pNet == NULL )
+ {
+ sprintf( pMan->sError, "Cannot read the initial statement for %s (output wire is not defined).", pWord );
+ Ver_ParsePrintErrorMessage( pMan );
+ return 0;
+ }
+ // get the equality sign
+ Symbol = Ver_StreamPopChar(p);
+ if ( Symbol != '<' && Symbol != '=' )
+ {
+ sprintf( pMan->sError, "Cannot read the assign statement for %s (expected <= or =).", pWord );
+ Ver_ParsePrintErrorMessage( pMan );
+ return 0;
+ }
+ if ( Symbol == '<' )
+ Ver_StreamPopChar(p);
+ // skip the comments
+ if ( !Ver_ParseSkipComments( pMan ) )
+ return 0;
+ // get the second name
+ pEquation = Ver_StreamGetWord( p, ";" );
+ if ( pEquation == NULL )
+ return 0;
+ // find the corresponding latch
+ if ( Abc_ObjFaninNum(pNet) == 0 )
+ {
+ sprintf( pMan->sError, "Cannot find the latch to assign the initial value." );
+ Ver_ParsePrintErrorMessage( pMan );
+ return 0;
+ }
+ pNode = Abc_ObjFanin0(Abc_ObjFanin0(pNet));
+ assert( Abc_ObjIsLatch(pNode) );
+ // set the initial state
+ if ( !strcmp(pEquation, "0") || !strcmp(pEquation, "1\'b0") )
+ Abc_LatchSetInit0( pNode );
+ else if ( !strcmp(pEquation, "1") || !strcmp(pEquation, "1\'b1") )
+ Abc_LatchSetInit1( pNode );
+// else if ( !strcmp(pEquation, "2") )
+// Abc_LatchSetInitDc( pNode );
+ else
+ {
+ sprintf( pMan->sError, "Incorrect initial value of the latch %s.", Abc_ObjName(pNet) );
+ Ver_ParsePrintErrorMessage( pMan );
+ return 0;
+ }
+ // remove the last symbol
+ Symbol = Ver_StreamPopChar(p);
+ assert( Symbol == ';' );
+ // quit if only one directive
+ if ( fStopAfterOne )
+ break;
+ }
+ return 1;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Parses one directive.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Ver_ParseAssign( Ver_Man_t * pMan, Abc_Ntk_t * pNtk )
+{
+ char Buffer[1000], Buffer2[1000];
+ Ver_Stream_t * p = pMan->pReader;
+ Abc_Obj_t * pNode, * pNet;
+ char * pWord, * pName, * pEquation;
+ Hop_Obj_t * pFunc;
+ char Symbol;
+ int i, Bit, Limit, Length, fReduction;
+ int nMsb, nLsb;
+
+// if ( Ver_StreamGetLineNumber(p) == 2756 )
+// {
+// int x = 0;
+// }
+
+ // convert from the blackbox into the network with local functions representated by AIGs
+ if ( !Ver_ParseConvertNetwork( pMan, pNtk, pMan->fMapped ) )
+ return 0;
+
+ while ( 1 )
+ {
+ // get the name of the output signal
+ pWord = Ver_ParseGetName( pMan );
+ if ( pWord == NULL )
+ return 0;
+ // check for vector-inputs
+ if ( !Ver_ParseLookupSuffix( pMan, pWord, &nMsb, &nLsb ) )
+ return 0;
+ // handle special case of constant assignment
+ if ( nMsb >= 0 && nLsb >= 0 )
+ {
+ // save the fanout name
+ strcpy( Buffer, pWord );
+ // get the equality sign
+ if ( Ver_StreamPopChar(p) != '=' )
+ {
+ sprintf( pMan->sError, "Cannot read the assign statement for %s (expected equality sign).", pWord );
+ Ver_ParsePrintErrorMessage( pMan );
+ return 0;
+ }
+ // get the constant
+ pWord = Ver_ParseGetName( pMan );
+ if ( pWord == NULL )
+ return 0;
+ // check if it is indeed a constant
+ if ( !(pWord[0] >= '0' && pWord[0] <= '9') )
+ {
+ sprintf( pMan->sError, "Currently can only assign vector-signal \"%s\" to be a constant.", Buffer );
+ Ver_ParsePrintErrorMessage( pMan );
+ return 0;
+ }
+
+ // get individual bits of the constant
+ if ( !Ver_ParseConstant( pMan, pWord ) )
+ return 0;
+ // check that the constant has the same size
+ Limit = nMsb > nLsb? nMsb - nLsb + 1: nLsb - nMsb + 1;
+ if ( Limit != Vec_PtrSize(pMan->vNames) )
+ {
+ sprintf( pMan->sError, "The constant size (%d) is different from the signal\"%s\" size (%d).",
+ Vec_PtrSize(pMan->vNames), Buffer, Limit );
+ Ver_ParsePrintErrorMessage( pMan );
+ return 0;
+ }
+ // iterate through the bits
+ for ( i = 0, Bit = nLsb; i < Limit; i++, Bit = nMsb > nLsb ? Bit + 1: Bit - 1 )
+ {
+ // get the fanin net
+ if ( Vec_PtrEntry( pMan->vNames, Limit-1-i ) )
+ pNet = Ver_ParseFindNet( pNtk, "1\'b1" );
+ else
+ pNet = Ver_ParseFindNet( pNtk, "1\'b0" );
+ assert( pNet != NULL );
+
+ // create the buffer
+ pNode = Abc_NtkCreateNodeBuf( pNtk, pNet );
+
+ // get the fanout net
+ sprintf( Buffer2, "%s[%d]", Buffer, Bit );
+ pNet = Ver_ParseFindNet( pNtk, Buffer2 );
+ if ( pNet == NULL )
+ {
+ sprintf( pMan->sError, "Cannot read the assign statement for %s (output wire is not defined).", pWord );
+ Ver_ParsePrintErrorMessage( pMan );
+ return 0;
+ }
+ Abc_ObjAddFanin( pNet, pNode );
+ }
+ // go to the end of the line
+ Ver_ParseSkipComments( pMan );
+ }
+ else
+ {
+ // consider the case of reduction operations
+ fReduction = 0;
+ if ( pWord[0] == '{' && !pMan->fNameLast )
+ fReduction = 1;
+ if ( fReduction )
+ {
+ pWord++;
+ pWord[strlen(pWord)-1] = 0;
+ assert( pWord[0] != '\\' );
+ }
+ // get the fanout net
+ pNet = Ver_ParseFindNet( pNtk, pWord );
+ if ( pNet == NULL )
+ {
+ sprintf( pMan->sError, "Cannot read the assign statement for %s (output wire is not defined).", pWord );
+ Ver_ParsePrintErrorMessage( pMan );
+ return 0;
+ }
+ // get the equality sign
+ if ( Ver_StreamPopChar(p) != '=' )
+ {
+ sprintf( pMan->sError, "Cannot read the assign statement for %s (expected equality sign).", pWord );
+ Ver_ParsePrintErrorMessage( pMan );
+ return 0;
+ }
+ // skip the comments
+ if ( !Ver_ParseSkipComments( pMan ) )
+ return 0;
+ // get the second name
+ if ( fReduction )
+ pEquation = Ver_StreamGetWord( p, ";" );
+ else
+ pEquation = Ver_StreamGetWord( p, ",;" );
+ if ( pEquation == NULL )
+ {
+ sprintf( pMan->sError, "Cannot read the equation for %s.", Abc_ObjName(pNet) );
+ Ver_ParsePrintErrorMessage( pMan );
+ return 0;
+ }
+
+ // consider the case of mapped network
+ Vec_PtrClear( pMan->vNames );
+ if ( pMan->fMapped )
+ {
+ if ( !strcmp( pEquation, "1\'b0" ) )
+ pFunc = (Hop_Obj_t *)Mio_LibraryReadConst0(Abc_FrameReadLibGen());
+ else if ( !strcmp( pEquation, "1\'b1" ) )
+ pFunc = (Hop_Obj_t *)Mio_LibraryReadConst1(Abc_FrameReadLibGen());
+ else
+ {
+ // "assign foo = \bar ;"
+ if ( *pEquation == '\\' )
+ {
+ pEquation++;
+ pEquation[strlen(pEquation) - 1] = 0;
+ }
+ if ( Ver_ParseFindNet(pNtk, pEquation) == NULL )
+ {
+ sprintf( pMan->sError, "Cannot read Verilog with non-trivial assignments in the mapped netlist." );
+ Ver_ParsePrintErrorMessage( pMan );
+ return 0;
+ }
+ Vec_PtrPush( pMan->vNames, (void *)strlen(pEquation) );
+ Vec_PtrPush( pMan->vNames, pEquation );
+ // get the buffer
+ pFunc = (Hop_Obj_t *)Mio_LibraryReadBuf(Abc_FrameReadLibGen());
+ if ( pFunc == NULL )
+ {
+ sprintf( pMan->sError, "Reading assign statement for node %s has failed because the genlib library has no buffer.", Abc_ObjName(pNet) );
+ Ver_ParsePrintErrorMessage( pMan );
+ return 0;
+ }
+ }
+ }
+ else
+ {
+ if ( !strcmp(pEquation, "0") || !strcmp(pEquation, "1\'b0") || !strcmp(pEquation, "1\'bx") )
+ pFunc = Hop_ManConst0(pNtk->pManFunc);
+ else if ( !strcmp(pEquation, "1") || !strcmp(pEquation, "1\'b1") )
+ pFunc = Hop_ManConst1(pNtk->pManFunc);
+ else if ( fReduction )
+ pFunc = Ver_FormulaReduction( pEquation, pNtk->pManFunc, pMan->vNames, pMan->sError );
+ else
+ pFunc = Ver_FormulaParser( pEquation, pNtk->pManFunc, pMan->vNames, pMan->vStackFn, pMan->vStackOp, pMan->sError );
+ if ( pFunc == NULL )
+ {
+ Ver_ParsePrintErrorMessage( pMan );
+ return 0;
+ }
+ }
+
+ // create the node with the given inputs
+ pNode = Abc_NtkCreateNode( pNtk );
+ pNode->pData = pFunc;
+ Abc_ObjAddFanin( pNet, pNode );
+ // connect to fanin nets
+ for ( i = 0; i < Vec_PtrSize(pMan->vNames)/2; i++ )
+ {
+ // get the name of this signal
+ Length = (int)Vec_PtrEntry( pMan->vNames, 2*i );
+ pName = Vec_PtrEntry( pMan->vNames, 2*i + 1 );
+ pName[Length] = 0;
+ // find the corresponding net
+ pNet = Ver_ParseFindNet( pNtk, pName );
+ if ( pNet == NULL )
+ {
+ sprintf( pMan->sError, "Cannot read the assign statement for %s (input wire %s is not defined).", pWord, pName );
+ Ver_ParsePrintErrorMessage( pMan );
+ return 0;
+ }
+ Abc_ObjAddFanin( pNode, pNet );
+ }
+ }
+
+ Symbol = Ver_StreamPopChar(p);
+ if ( Symbol == ',' )
+ continue;
+ if ( Symbol == ';' )
+ return 1;
+ }
+ return 1;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Parses one directive.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Ver_ParseGateStandard( Ver_Man_t * pMan, Abc_Ntk_t * pNtk, Ver_GateType_t GateType )
+{
+ Ver_Stream_t * p = pMan->pReader;
+ Abc_Obj_t * pNet, * pNode;
+ char * pWord, Symbol;
+
+ // convert from the blackbox into the network with local functions representated by AIGs
+ if ( !Ver_ParseConvertNetwork( pMan, pNtk, pMan->fMapped ) )
+ return 0;
+
+ // this is gate name - throw it away
+ if ( Ver_StreamPopChar(p) != '(' )
+ {
+ sprintf( pMan->sError, "Cannot parse a standard gate (expected opening paranthesis)." );
+ Ver_ParsePrintErrorMessage( pMan );
+ return 0;
+ }
+ Ver_ParseSkipComments( pMan );
+
+ // create the node
+ pNode = Abc_NtkCreateNode( pNtk );
+
+ // parse pairs of formal/actural inputs
+ while ( 1 )
+ {
+ // parse the output name
+ pWord = Ver_ParseGetName( pMan );
+ if ( pWord == NULL )
+ return 0;
+ // get the net corresponding to this output
+ pNet = Ver_ParseFindNet( pNtk, pWord );
+ if ( pNet == NULL )
+ {
+ sprintf( pMan->sError, "Net is missing in gate %s.", pWord );
+ Ver_ParsePrintErrorMessage( pMan );
+ return 0;
+ }
+ // if this is the first net, add it as an output
+ if ( Abc_ObjFanoutNum(pNode) == 0 )
+ Abc_ObjAddFanin( pNet, pNode );
+ else
+ Abc_ObjAddFanin( pNode, pNet );
+ // check if it is the end of gate
+ Ver_ParseSkipComments( pMan );
+ Symbol = Ver_StreamPopChar(p);
+ if ( Symbol == ')' )
+ break;
+ // skip comma
+ if ( Symbol != ',' )
+ {
+ sprintf( pMan->sError, "Cannot parse a standard gate %s (expected closing paranthesis).", Abc_ObjName(Abc_ObjFanout0(pNode)) );
+ Ver_ParsePrintErrorMessage( pMan );
+ return 0;
+ }
+ Ver_ParseSkipComments( pMan );
+ }
+ if ( (GateType == VER_GATE_BUF || GateType == VER_GATE_NOT) && Abc_ObjFaninNum(pNode) != 1 )
+ {
+ sprintf( pMan->sError, "Buffer or interver with multiple fanouts %s (currently not supported).", Abc_ObjName(Abc_ObjFanout0(pNode)) );
+ Ver_ParsePrintErrorMessage( pMan );
+ return 0;
+ }
+
+ // check if it is the end of gate
+ Ver_ParseSkipComments( pMan );
+ if ( Ver_StreamPopChar(p) != ';' )
+ {
+ sprintf( pMan->sError, "Cannot read standard gate %s (expected closing semicolumn).", Abc_ObjName(Abc_ObjFanout0(pNode)) );
+ Ver_ParsePrintErrorMessage( pMan );
+ return 0;
+ }
+ // add logic function
+ if ( GateType == VER_GATE_AND || GateType == VER_GATE_NAND )
+ pNode->pData = Hop_CreateAnd( pNtk->pManFunc, Abc_ObjFaninNum(pNode) );
+ else if ( GateType == VER_GATE_OR || GateType == VER_GATE_NOR )
+ pNode->pData = Hop_CreateOr( pNtk->pManFunc, Abc_ObjFaninNum(pNode) );
+ else if ( GateType == VER_GATE_XOR || GateType == VER_GATE_XNOR )
+ pNode->pData = Hop_CreateExor( pNtk->pManFunc, Abc_ObjFaninNum(pNode) );
+ else if ( GateType == VER_GATE_BUF || GateType == VER_GATE_NOT )
+ pNode->pData = Hop_CreateAnd( pNtk->pManFunc, Abc_ObjFaninNum(pNode) );
+ if ( GateType == VER_GATE_NAND || GateType == VER_GATE_NOR || GateType == VER_GATE_XNOR || GateType == VER_GATE_NOT )
+ pNode->pData = Hop_Not( pNode->pData );
+ return 1;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Parses one directive.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Ver_ParseFlopStandard( Ver_Man_t * pMan, Abc_Ntk_t * pNtk )
+{
+ Ver_Stream_t * p = pMan->pReader;
+ Abc_Obj_t * pNetLi, * pNetLo, * pLatch;
+ char * pWord, Symbol;
+
+ // convert from the blackbox into the network with local functions representated by AIGs
+ if ( !Ver_ParseConvertNetwork( pMan, pNtk, pMan->fMapped ) )
+ return 0;
+
+ // this is gate name - throw it away
+ if ( Ver_StreamPopChar(p) != '(' )
+ {
+ sprintf( pMan->sError, "Cannot parse a standard gate (expected opening paranthesis)." );
+ Ver_ParsePrintErrorMessage( pMan );
+ return 0;
+ }
+ Ver_ParseSkipComments( pMan );
+
+ // parse the output name
+ pWord = Ver_ParseGetName( pMan );
+ if ( pWord == NULL )
+ return 0;
+ // get the net corresponding to this output
+ pNetLo = Ver_ParseFindNet( pNtk, pWord );
+ if ( pNetLo == NULL )
+ {
+ sprintf( pMan->sError, "Net is missing in gate %s.", pWord );
+ Ver_ParsePrintErrorMessage( pMan );
+ return 0;
+ }
+
+ // check if it is the end of gate
+ Ver_ParseSkipComments( pMan );
+ Symbol = Ver_StreamPopChar(p);
+ if ( Symbol == ')' )
+ {
+ sprintf( pMan->sError, "Cannot parse the flop." );
+ Ver_ParsePrintErrorMessage( pMan );
+ return 0;
+ }
+ // skip comma
+ if ( Symbol != ',' )
+ {
+ sprintf( pMan->sError, "Cannot parse the flop." );
+ Ver_ParsePrintErrorMessage( pMan );
+ return 0;
+ }
+ Ver_ParseSkipComments( pMan );
+
+ // parse the output name
+ pWord = Ver_ParseGetName( pMan );
+ if ( pWord == NULL )
+ return 0;
+ // get the net corresponding to this output
+ pNetLi = Ver_ParseFindNet( pNtk, pWord );
+ if ( pNetLi == NULL )
+ {
+ sprintf( pMan->sError, "Net is missing in gate %s.", pWord );
+ Ver_ParsePrintErrorMessage( pMan );
+ return 0;
+ }
+
+ // check if it is the end of gate
+ Ver_ParseSkipComments( pMan );
+ Symbol = Ver_StreamPopChar(p);
+ if ( Symbol != ')' )
+ {
+ sprintf( pMan->sError, "Cannot parse the flop." );
+ Ver_ParsePrintErrorMessage( pMan );
+ return 0;
+ }
+
+ // check if it is the end of gate
+ Ver_ParseSkipComments( pMan );
+ if ( Ver_StreamPopChar(p) != ';' )
+ {
+ sprintf( pMan->sError, "Cannot parse the flop." );
+ Ver_ParsePrintErrorMessage( pMan );
+ return 0;
+ }
+
+ // create the latch
+ pLatch = Ver_ParseCreateLatch( pNtk, pNetLi, pNetLo );
+ Abc_LatchSetInit0( pLatch );
+ return 1;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Returns the index of the given pin the gate.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Ver_FindGateInput( Mio_Gate_t * pGate, char * pName )
+{
+ Mio_Pin_t * pGatePin;
+ int i;
+ for ( i = 0, pGatePin = Mio_GateReadPins(pGate); pGatePin != NULL; pGatePin = Mio_PinReadNext(pGatePin), i++ )
+ if ( strcmp(pName, Mio_PinReadName(pGatePin)) == 0 )
+ return i;
+ if ( strcmp(pName, Mio_GateReadOutName(pGate)) == 0 )
+ return i;
+ return -1;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Parses one directive.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Ver_ParseGate( Ver_Man_t * pMan, Abc_Ntk_t * pNtk, Mio_Gate_t * pGate )
+{
+ Ver_Stream_t * p = pMan->pReader;
+ Abc_Obj_t * pNetActual, * pNode;
+ char * pWord, Symbol;
+ int Input, i, nFanins = Mio_GateReadInputs(pGate);
+
+ // convert from the blackbox into the network with local functions representated by gates
+ if ( 1 != pMan->fMapped )
+ {
+ sprintf( pMan->sError, "The network appears to be mapped. Use \"r -m\" to read mapped Verilog." );
+ Ver_ParsePrintErrorMessage( pMan );
+ return 0;
+ }
+
+ // update the network type if needed
+ if ( !Ver_ParseConvertNetwork( pMan, pNtk, 1 ) )
+ return 0;
+
+ // parse the directive and set the pointers to the PIs/POs of the gate
+ pWord = Ver_ParseGetName( pMan );
+ if ( pWord == NULL )
+ return 0;
+ // this is gate name - throw it away
+ if ( Ver_StreamPopChar(p) != '(' )
+ {
+ sprintf( pMan->sError, "Cannot parse gate %s (expected opening paranthesis).", Mio_GateReadName(pGate) );
+ Ver_ParsePrintErrorMessage( pMan );
+ return 0;
+ }
+ Ver_ParseSkipComments( pMan );
+
+ // start the node
+ pNode = Abc_NtkCreateNode( pNtk );
+ pNode->pData = pGate;
+
+ // parse pairs of formal/actural inputs
+ Vec_IntClear( pMan->vPerm );
+ while ( 1 )
+ {
+ // process one pair of formal/actual parameters
+ if ( Ver_StreamPopChar(p) != '.' )
+ {
+ sprintf( pMan->sError, "Cannot parse gate %s (expected .).", Mio_GateReadName(pGate) );
+ Ver_ParsePrintErrorMessage( pMan );
+ return 0;
+ }
+
+ // parse the formal name
+ pWord = Ver_ParseGetName( pMan );
+ if ( pWord == NULL )
+ return 0;
+
+ // find the corresponding pin of the gate
+ Input = Ver_FindGateInput( pGate, pWord );
+ if ( Input == -1 )
+ {
+ sprintf( pMan->sError, "Formal input name %s cannot be found in the gate %s.", pWord, Mio_GateReadOutName(pGate) );
+ Ver_ParsePrintErrorMessage( pMan );
+ return 0;
+ }
+
+ // open the paranthesis
+ if ( Ver_StreamPopChar(p) != '(' )
+ {
+ sprintf( pMan->sError, "Cannot formal parameter %s of gate %s (expected opening paranthesis).", pWord, Mio_GateReadName(pGate) );
+ Ver_ParsePrintErrorMessage( pMan );
+ return 0;
+ }
+
+ // parse the actual name
+ pWord = Ver_ParseGetName( pMan );
+ if ( pWord == NULL )
+ return 0;
+ // check if the name is complemented
+ assert( pWord[0] != '~' );
+/*
+ fCompl = (pWord[0] == '~');
+ if ( fCompl )
+ {
+ fComplUsed = 1;
+ pWord++;
+ if ( pNtk->pData == NULL )
+ pNtk->pData = Extra_MmFlexStart();
+ }
+*/
+ // get the actual net
+ pNetActual = Ver_ParseFindNet( pNtk, pWord );
+ if ( pNetActual == NULL )
+ {
+ sprintf( pMan->sError, "Actual net %s is missing.", pWord );
+ Ver_ParsePrintErrorMessage( pMan );
+ return 0;
+ }
+
+ // close the paranthesis
+ if ( Ver_StreamPopChar(p) != ')' )
+ {
+ sprintf( pMan->sError, "Cannot formal parameter %s of gate %s (expected closing paranthesis).", pWord, Mio_GateReadName(pGate) );
+ Ver_ParsePrintErrorMessage( pMan );
+ return 0;
+ }
+
+ // add the fanin
+ if ( Input < nFanins )
+ {
+ Vec_IntPush( pMan->vPerm, Input );
+ Abc_ObjAddFanin( pNode, pNetActual ); // fanin
+ }
+ else
+ Abc_ObjAddFanin( pNetActual, pNode ); // fanout
+
+ // check if it is the end of gate
+ Ver_ParseSkipComments( pMan );
+ Symbol = Ver_StreamPopChar(p);
+ if ( Symbol == ')' )
+ break;
+
+ // skip comma
+ if ( Symbol != ',' )
+ {
+ sprintf( pMan->sError, "Cannot formal parameter %s of gate %s (expected closing paranthesis).", pWord, Mio_GateReadName(pGate) );
+ Ver_ParsePrintErrorMessage( pMan );
+ return 0;
+ }
+ Ver_ParseSkipComments( pMan );
+ }
+
+ // check that the gate as the same number of input
+ if ( !(Abc_ObjFaninNum(pNode) == nFanins && Abc_ObjFanoutNum(pNode) == 1) )
+ {
+ sprintf( pMan->sError, "Parsing of gate %s has failed.", Mio_GateReadName(pGate) );
+ Ver_ParsePrintErrorMessage( pMan );
+ return 0;
+ }
+
+ // check if it is the end of gate
+ Ver_ParseSkipComments( pMan );
+ if ( Ver_StreamPopChar(p) != ';' )
+ {
+ sprintf( pMan->sError, "Cannot read gate %s (expected closing semicolumn).", Mio_GateReadName(pGate) );
+ Ver_ParsePrintErrorMessage( pMan );
+ return 0;
+ }
+
+ // check if we need to permute the inputs
+ Vec_IntForEachEntry( pMan->vPerm, Input, i )
+ if ( Input != i )
+ break;
+ if ( i < Vec_IntSize(pMan->vPerm) )
+ {
+ // add the fanin numnbers to the end of the permuation array
+ for ( i = 0; i < nFanins; i++ )
+ Vec_IntPush( pMan->vPerm, Abc_ObjFaninId(pNode, i) );
+ // write the fanin numbers into their corresponding places (according to the gate)
+ for ( i = 0; i < nFanins; i++ )
+ Vec_IntWriteEntry( &pNode->vFanins, Vec_IntEntry(pMan->vPerm, i), Vec_IntEntry(pMan->vPerm, i+nFanins) );
+ }
+ return 1;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Parses one directive.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Ver_ParseBox( Ver_Man_t * pMan, Abc_Ntk_t * pNtk, Abc_Ntk_t * pNtkBox )
+{
+ char Buffer[1000];
+ Ver_Stream_t * p = pMan->pReader;
+ Ver_Bundle_t * pBundle;
+ Vec_Ptr_t * vBundles;
+ Abc_Obj_t * pNetActual;
+ Abc_Obj_t * pNode;
+ char * pWord, Symbol;
+ int fCompl, fFormalIsGiven;
+ int i, k, Bit, Limit, nMsb, nLsb, fQuit, flag;
+
+ // gate the name of the box
+ pWord = Ver_ParseGetName( pMan );
+ if ( pWord == NULL )
+ return 0;
+
+ // create a box with this name
+ pNode = Abc_NtkCreateBlackbox( pNtk );
+ pNode->pData = pNtkBox;
+ Abc_ObjAssignName( pNode, pWord, NULL );
+
+ // continue parsing the box
+ if ( Ver_StreamPopChar(p) != '(' )
+ {
+ sprintf( pMan->sError, "Cannot parse box %s (expected opening paranthesis).", Abc_ObjName(pNode) );
+ Ver_ParsePrintErrorMessage( pMan );
+ return 0;
+ }
+ Ver_ParseSkipComments( pMan );
+
+ // parse pairs of formal/actual inputs
+ vBundles = Vec_PtrAlloc( 16 );
+ pNode->pCopy = (Abc_Obj_t *)vBundles;
+ while ( 1 )
+ {
+/*
+ if ( Ver_StreamGetLineNumber(pMan->pReader) == 5967 )
+ {
+ int x = 0;
+ }
+*/
+ // allocate the bundle (formal name + array of actual nets)
+ pBundle = ALLOC( Ver_Bundle_t, 1 );
+ pBundle->pNameFormal = NULL;
+ pBundle->vNetsActual = Vec_PtrAlloc( 4 );
+ Vec_PtrPush( vBundles, pBundle );
+
+ // process one pair of formal/actual parameters
+ fFormalIsGiven = 0;
+ if ( Ver_StreamScanChar(p) == '.' )
+ {
+ fFormalIsGiven = 1;
+ if ( Ver_StreamPopChar(p) != '.' )
+ {
+ sprintf( pMan->sError, "Cannot parse box %s (expected .).", Abc_ObjName(pNode) );
+ Ver_ParsePrintErrorMessage( pMan );
+ return 0;
+ }
+
+ // parse the formal name
+ pWord = Ver_ParseGetName( pMan );
+ if ( pWord == NULL )
+ return 0;
+
+ // save the name
+ pBundle->pNameFormal = Extra_UtilStrsav( pWord );
+
+ // open the paranthesis
+ if ( Ver_StreamPopChar(p) != '(' )
+ {
+ sprintf( pMan->sError, "Cannot formal parameter %s of box %s (expected opening paranthesis).", pWord, Abc_ObjName(pNode));
+ Ver_ParsePrintErrorMessage( pMan );
+ return 0;
+ }
+ Ver_ParseSkipComments( pMan );
+ }
+
+ // check if this is the beginning of {} expression
+ Symbol = Ver_StreamScanChar(p);
+
+ // consider the case of vector-inputs
+ if ( Symbol == '{' )
+ {
+ // skip this char
+ Ver_StreamPopChar(p);
+
+ // read actual names
+ i = 0;
+ fQuit = 0;
+ while ( 1 )
+ {
+ // parse the formal name
+ Ver_ParseSkipComments( pMan );
+ pWord = Ver_ParseGetName( pMan );
+ if ( pWord == NULL )
+ return 0;
+
+ // check if the last char is a closing brace
+ if ( pWord[strlen(pWord)-1] == '}' )
+ {
+ pWord[strlen(pWord)-1] = 0;
+ fQuit = 1;
+ }
+ if ( pWord[0] == 0 )
+ break;
+
+ // check for constant
+ if ( pWord[0] >= '1' && pWord[0] <= '9' )
+ {
+ if ( !Ver_ParseConstant( pMan, pWord ) )
+ return 0;
+ // add constant MSB to LSB
+ for ( k = 0; k < Vec_PtrSize(pMan->vNames); k++, i++ )
+ {
+ // get the actual net
+ sprintf( Buffer, "1\'b%d", (int)(Vec_PtrEntry(pMan->vNames,k) != NULL) );
+ pNetActual = Ver_ParseFindNet( pNtk, Buffer );
+ if ( pNetActual == NULL )
+ {
+ sprintf( pMan->sError, "Actual net \"%s\" is missing in gate \"%s\".", Buffer, Abc_ObjName(pNode) );
+ Ver_ParsePrintErrorMessage( pMan );
+ return 0;
+ }
+ Vec_PtrPush( pBundle->vNetsActual, pNetActual );
+ }
+ }
+ else
+ {
+ // get the suffix of the form [m:n]
+ if ( pWord[strlen(pWord)-1] == ']' && !pMan->fNameLast )
+ Ver_ParseSignalSuffix( pMan, pWord, &nMsb, &nLsb );
+ else
+ Ver_ParseLookupSuffix( pMan, pWord, &nMsb, &nLsb );
+
+ // generate signals
+ if ( nMsb == -1 && nLsb == -1 )
+ {
+ // get the actual net
+ pNetActual = Ver_ParseFindNet( pNtk, pWord );
+ if ( pNetActual == NULL )
+ {
+ if ( !strncmp(pWord, "Open_", 5) ||
+ !strncmp(pWord, "dct_unconnected", 15) )
+ pNetActual = Abc_NtkCreateNet( pNtk );
+ else
+ {
+ sprintf( pMan->sError, "Actual net \"%s\" is missing in box \"%s\".", pWord, Abc_ObjName(pNode) );
+ Ver_ParsePrintErrorMessage( pMan );
+ return 0;
+ }
+ }
+ Vec_PtrPush( pBundle->vNetsActual, pNetActual );
+ i++;
+ }
+ else
+ {
+ // go from MSB to LSB
+ assert( nMsb >= 0 && nLsb >= 0 );
+ Limit = (nMsb > nLsb) ? nMsb - nLsb + 1: nLsb - nMsb + 1;
+ for ( Bit = nMsb, k = Limit - 1; k >= 0; Bit = (nMsb > nLsb ? Bit - 1: Bit + 1), k--, i++ )
+ {
+ // get the actual net
+ sprintf( Buffer, "%s[%d]", pWord, Bit );
+ pNetActual = Ver_ParseFindNet( pNtk, Buffer );
+ if ( pNetActual == NULL )
+ {
+ if ( !strncmp(pWord, "Open_", 5) ||
+ !strncmp(pWord, "dct_unconnected", 15) )
+ pNetActual = Abc_NtkCreateNet( pNtk );
+ else
+ {
+ sprintf( pMan->sError, "Actual net \"%s\" is missing in box \"%s\".", pWord, Abc_ObjName(pNode) );
+ Ver_ParsePrintErrorMessage( pMan );
+ return 0;
+ }
+ }
+ Vec_PtrPush( pBundle->vNetsActual, pNetActual );
+ }
+ }
+ }
+
+ if ( fQuit )
+ break;
+
+ // skip comma
+ Ver_ParseSkipComments( pMan );
+ Symbol = Ver_StreamPopChar(p);
+ if ( Symbol == '}' )
+ break;
+ if ( Symbol != ',' )
+ {
+ sprintf( pMan->sError, "Cannot parse formal parameter %s of gate %s (expected comma).", pWord, Abc_ObjName(pNode) );
+ Ver_ParsePrintErrorMessage( pMan );
+ return 0;
+ }
+ }
+ }
+ else
+ {
+ // get the next word
+ pWord = Ver_ParseGetName( pMan );
+ if ( pWord == NULL )
+ return 0;
+ // consider the case of empty name
+ fCompl = 0;
+ if ( pWord[0] == 0 )
+ {
+ pNetActual = Abc_NtkCreateNet( pNtk );
+ Vec_PtrPush( pBundle->vNetsActual, Abc_ObjNotCond( pNetActual, fCompl ) );
+ }
+ else
+ {
+ // get the actual net
+ flag=0;
+ pNetActual = Ver_ParseFindNet( pNtk, pWord );
+ if ( pNetActual == NULL )
+ {
+ Ver_ParseLookupSuffix( pMan, pWord, &nMsb, &nLsb );
+ if ( nMsb == -1 && nLsb == -1 )
+ {
+ Ver_ParseSignalSuffix( pMan, pWord, &nMsb, &nLsb );
+ if ( nMsb == -1 && nLsb == -1 )
+ {
+ if ( !strncmp(pWord, "Open_", 5) ||
+ !strncmp(pWord, "dct_unconnected", 15) )
+ {
+ pNetActual = Abc_NtkCreateNet( pNtk );
+ Vec_PtrPush( pBundle->vNetsActual, pNetActual );
+ }
+ else
+ {
+ sprintf( pMan->sError, "Actual net \"%s\" is missing in box \"%s\".", pWord, Abc_ObjName(pNode) );
+ Ver_ParsePrintErrorMessage( pMan );
+ return 0;
+ }
+ }
+ else
+ {
+ flag=1;
+ }
+ }
+ else
+ {
+ flag=1;
+ }
+ if (flag)
+ {
+ Limit = (nMsb > nLsb) ? nMsb - nLsb + 1: nLsb - nMsb + 1;
+ for ( Bit = nMsb, k = Limit - 1; k >= 0; Bit = (nMsb > nLsb ? Bit - 1: Bit + 1), k--)
+ {
+ // get the actual net
+ sprintf( Buffer, "%s[%d]", pWord, Bit );
+ pNetActual = Ver_ParseFindNet( pNtk, Buffer );
+ if ( pNetActual == NULL )
+ {
+ if ( !strncmp(pWord, "Open_", 5) ||
+ !strncmp(pWord, "dct_unconnected", 15))
+ pNetActual = Abc_NtkCreateNet( pNtk );
+ else
+ {
+ sprintf( pMan->sError, "Actual net \"%s\" is missing in box \"%s\".", pWord, Abc_ObjName(pNode) );
+ Ver_ParsePrintErrorMessage( pMan );
+ return 0;
+ }
+ }
+ Vec_PtrPush( pBundle->vNetsActual, pNetActual );
+ }
+ }
+ }
+ else
+ {
+ Vec_PtrPush( pBundle->vNetsActual, Abc_ObjNotCond( pNetActual, fCompl ) );
+ }
+ }
+ }
+
+ if ( fFormalIsGiven )
+ {
+ // close the paranthesis
+ Ver_ParseSkipComments( pMan );
+ if ( Ver_StreamPopChar(p) != ')' )
+ {
+ sprintf( pMan->sError, "Cannot parse formal parameter %s of box %s (expected closing paranthesis).", pWord, Abc_ObjName(pNode) );
+ Ver_ParsePrintErrorMessage( pMan );
+ return 0;
+ }
+ Ver_ParseSkipComments( pMan );
+ }
+
+ // check if it is the end of gate
+ Symbol = Ver_StreamPopChar(p);
+ if ( Symbol == ')' )
+ break;
+ // skip comma
+ if ( Symbol != ',' )
+ {
+ sprintf( pMan->sError, "Cannot parse formal parameter %s of box %s (expected comma).", pWord, Abc_ObjName(pNode) );
+ Ver_ParsePrintErrorMessage( pMan );
+ return 0;
+ }
+ Ver_ParseSkipComments( pMan );
+ }
+
+ // check if it is the end of gate
+ Ver_ParseSkipComments( pMan );
+ if ( Ver_StreamPopChar(p) != ';' )
+ {
+ sprintf( pMan->sError, "Cannot read box %s (expected closing semicolumn).", Abc_ObjName(pNode) );
+ Ver_ParsePrintErrorMessage( pMan );
+ return 0;
+ }
+
+ return 1;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Connects one box to the network]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Ver_ParseFreeBundle( Ver_Bundle_t * pBundle )
+{
+ FREE( pBundle->pNameFormal );
+ Vec_PtrFree( pBundle->vNetsActual );
+ free( pBundle );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Connects one box to the network]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Ver_ParseConnectBox( Ver_Man_t * pMan, Abc_Obj_t * pBox )
+{
+ Vec_Ptr_t * vBundles = (Vec_Ptr_t *)pBox->pCopy;
+ Abc_Ntk_t * pNtk = pBox->pNtk;
+ Abc_Ntk_t * pNtkBox = pBox->pData;
+ Abc_Obj_t * pTerm, * pTermNew, * pNetAct;
+ Ver_Bundle_t * pBundle;
+ char * pNameFormal;
+ int i, k, j, iBundle, Length;
+
+ assert( !Ver_ObjIsConnected(pBox) );
+ assert( Ver_NtkIsDefined(pNtkBox) );
+ assert( !Abc_NtkHasBlackbox(pNtkBox) || Abc_NtkBoxNum(pNtkBox) == 1 );
+/*
+ // clean the PI/PO nets
+ Abc_NtkForEachPi( pNtkBox, pTerm, i )
+ Abc_ObjFanout0(pTerm)->pCopy = NULL;
+ Abc_NtkForEachPo( pNtkBox, pTerm, i )
+ Abc_ObjFanin0(pTerm)->pCopy = NULL;
+*/
+ // check if some of them do not have formal names
+ Vec_PtrForEachEntry( vBundles, pBundle, k )
+ if ( pBundle->pNameFormal == NULL )
+ break;
+ if ( k < Vec_PtrSize(vBundles) )
+ {
+ printf( "Warning: The instance %s of network %s will be connected without using formal names.\n", pNtkBox->pName, Abc_ObjName(pBox) );
+ // add all actual nets in the bundles
+ iBundle = 0;
+ Vec_PtrForEachEntry( vBundles, pBundle, j )
+ iBundle += Vec_PtrSize(pBundle->vNetsActual);
+
+ // check the number of actual nets is the same as the number of formal nets
+ if ( iBundle != Abc_NtkPiNum(pNtkBox) + Abc_NtkPoNum(pNtkBox) )
+ {
+ sprintf( pMan->sError, "The number of actual IOs (%d) is different from the number of formal IOs (%d) when instantiating network %s in box %s.",
+ Vec_PtrSize(vBundles), Abc_NtkPiNum(pNtkBox) + Abc_NtkPoNum(pNtkBox), pNtkBox->pName, Abc_ObjName(pBox) );
+ Ver_ParsePrintErrorMessage( pMan );
+ return 0;
+ }
+ // connect bundles in the natural order
+ iBundle = 0;
+ Abc_NtkForEachPi( pNtkBox, pTerm, i )
+ {
+ pBundle = Vec_PtrEntry( vBundles, iBundle++ );
+ // the bundle is found - add the connections - using order LSB to MSB
+ Vec_PtrForEachEntryReverse( pBundle->vNetsActual, pNetAct, k )
+ {
+ pTermNew = Abc_NtkCreateBi( pNtk );
+ Abc_ObjAddFanin( pBox, pTermNew );
+ Abc_ObjAddFanin( pTermNew, pNetAct );
+ i++;
+ }
+ i--;
+ }
+ // create fanins of the box
+ Abc_NtkForEachPo( pNtkBox, pTerm, i )
+ {
+ pBundle = Vec_PtrEntry( vBundles, iBundle++ );
+ // the bundle is found - add the connections - using order LSB to MSB
+ Vec_PtrForEachEntryReverse( pBundle->vNetsActual, pNetAct, k )
+ {
+ pTermNew = Abc_NtkCreateBo( pNtk );
+ Abc_ObjAddFanin( pTermNew, pBox );
+ Abc_ObjAddFanin( pNetAct, pTermNew );
+ i++;
+ }
+ i--;
+ }
+
+ // free the bundling
+ Vec_PtrForEachEntry( vBundles, pBundle, k )
+ Ver_ParseFreeBundle( pBundle );
+ Vec_PtrFree( vBundles );
+ pBox->pCopy = NULL;
+ return 1;
+ }
+
+ // bundles arrive in any order - but inside each bundle the order is MSB to LSB
+ // make sure every formal PI has a corresponding net
+ Abc_NtkForEachPi( pNtkBox, pTerm, i )
+ {
+ // get the name of this formal net
+ pNameFormal = Abc_ObjName( Abc_ObjFanout0(pTerm) );
+ // try to find the bundle with this formal net
+ pBundle = NULL;
+ Vec_PtrForEachEntry( vBundles, pBundle, k )
+ if ( !strcmp(pBundle->pNameFormal, pNameFormal) )
+ break;
+ assert( pBundle != NULL );
+ // if the bundle is not found, try without parantheses
+ if ( k == Vec_PtrSize(vBundles) )
+ {
+ pBundle = NULL;
+ Length = strlen(pNameFormal);
+ if ( pNameFormal[Length-1] == ']' )
+ {
+ // find the opening brace
+ for ( Length--; Length >= 0; Length-- )
+ if ( pNameFormal[Length] == '[' )
+ break;
+ // compare names before brace
+ if ( Length > 0 )
+ {
+ Vec_PtrForEachEntry( vBundles, pBundle, j )
+ if ( !strncmp(pBundle->pNameFormal, pNameFormal, Length) )
+ break;
+ if ( j == Vec_PtrSize(vBundles) )
+ pBundle = NULL;
+ }
+ }
+ if ( pBundle == NULL )
+ {
+ sprintf( pMan->sError, "Cannot find an actual net for the formal net %s when instantiating network %s in box %s.",
+ pNameFormal, pNtkBox->pName, Abc_ObjName(pBox) );
+ Ver_ParsePrintErrorMessage( pMan );
+ return 0;
+ }
+ }
+ // the bundle is found - add the connections - using order LSB to MSB
+ Vec_PtrForEachEntryReverse( pBundle->vNetsActual, pNetAct, k )
+ {
+ pTermNew = Abc_NtkCreateBi( pNtk );
+ Abc_ObjAddFanin( pBox, pTermNew );
+ Abc_ObjAddFanin( pTermNew, pNetAct );
+ i++;
+ }
+ i--;
+ }
+
+ // connect those formal POs that do have nets
+ Abc_NtkForEachPo( pNtkBox, pTerm, i )
+ {
+ // get the name of this PI
+ pNameFormal = Abc_ObjName( Abc_ObjFanin0(pTerm) );
+ // try to find this formal net in the bundle
+ pBundle = NULL;
+ Vec_PtrForEachEntry( vBundles, pBundle, k )
+ if ( !strcmp(pBundle->pNameFormal, pNameFormal) )
+ break;
+ assert( pBundle != NULL );
+ // if the name is not found, try without parantheses
+ if ( k == Vec_PtrSize(vBundles) )
+ {
+ pBundle = NULL;
+ Length = strlen(pNameFormal);
+ if ( pNameFormal[Length-1] == ']' )
+ {
+ // find the opening brace
+ for ( Length--; Length >= 0; Length-- )
+ if ( pNameFormal[Length] == '[' )
+ break;
+ // compare names before brace
+ if ( Length > 0 )
+ {
+ Vec_PtrForEachEntry( vBundles, pBundle, j )
+ if ( !strncmp(pBundle->pNameFormal, pNameFormal, Length) )
+ break;
+ if ( j == Vec_PtrSize(vBundles) )
+ pBundle = NULL;
+ }
+ }
+ if ( pBundle == NULL )
+ {
+// printf( "Warning: The formal output %s is not driven when instantiating network %s in box %s.",
+// pNameFormal, pNtkBox->pName, Abc_ObjName(pBox) );
+ continue;
+ }
+ }
+ // the bundle is found - add the connections
+ Vec_PtrForEachEntryReverse( pBundle->vNetsActual, pNetAct, k )
+ {
+ if ( !strcmp(Abc_ObjName(pNetAct), "1\'b0") || !strcmp(Abc_ObjName(pNetAct), "1\'b1") )
+ {
+ sprintf( pMan->sError, "It looks like formal output %s is driving a constant net (%s) when instantiating network %s in box %s.",
+ pBundle->pNameFormal, Abc_ObjName(pNetAct), pNtkBox->pName, Abc_ObjName(pBox) );
+ Ver_ParsePrintErrorMessage( pMan );
+ return 0;
+ }
+ pTermNew = Abc_NtkCreateBo( pNtk );
+ Abc_ObjAddFanin( pTermNew, pBox );
+ Abc_ObjAddFanin( pNetAct, pTermNew );
+ i++;
+ }
+ i--;
+ }
+
+ // free the bundling
+ Vec_PtrForEachEntry( vBundles, pBundle, k )
+ Ver_ParseFreeBundle( pBundle );
+ Vec_PtrFree( vBundles );
+ pBox->pCopy = NULL;
+ return 1;
+}
+
+
+/**Function*************************************************************
+
+ Synopsis [Connects the defined boxes.]
+
+ Description [Returns 2 if there are any undef boxes.]
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Ver_ParseConnectDefBoxes( Ver_Man_t * pMan )
+{
+ Abc_Ntk_t * pNtk;
+ Abc_Obj_t * pBox;
+ int i, k, RetValue = 1;
+ // go through all the modules
+ Vec_PtrForEachEntry( pMan->pDesign->vModules, pNtk, i )
+ {
+ // go through all the boxes of this module
+ Abc_NtkForEachBox( pNtk, pBox, k )
+ {
+ if ( Abc_ObjIsLatch(pBox) )
+ continue;
+ // skip internal boxes of the blackboxes
+ if ( pBox->pData == NULL )
+ continue;
+ // if the network is undefined, it will be connected later
+ if ( !Ver_NtkIsDefined(pBox->pData) )
+ {
+ RetValue = 2;
+ continue;
+ }
+ // connect the box
+ if ( !Ver_ParseConnectBox( pMan, pBox ) )
+ return 0;
+ // if the network is a true blackbox, skip
+ if ( Abc_NtkHasBlackbox(pBox->pData) )
+ continue;
+ // convert the box to the whitebox
+ Abc_ObjBlackboxToWhitebox( pBox );
+ }
+ }
+ return RetValue;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Collects the undef boxes and maps them into their instances.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Vec_Ptr_t * Ver_ParseCollectUndefBoxes( Ver_Man_t * pMan )
+{
+ Vec_Ptr_t * vUndefs;
+ Abc_Ntk_t * pNtk, * pNtkBox;
+ Abc_Obj_t * pBox;
+ int i, k;
+ // clear the module structures
+ Vec_PtrForEachEntry( pMan->pDesign->vModules, pNtk, i )
+ pNtk->pData = NULL;
+ // go through all the blackboxes
+ vUndefs = Vec_PtrAlloc( 16 );
+ Vec_PtrForEachEntry( pMan->pDesign->vModules, pNtk, i )
+ {
+ Abc_NtkForEachBlackbox( pNtk, pBox, k )
+ {
+ pNtkBox = pBox->pData;
+ if ( pNtkBox == NULL )
+ continue;
+ if ( Ver_NtkIsDefined(pNtkBox) )
+ continue;
+ if ( pNtkBox->pData == NULL )
+ {
+ // save the box
+ Vec_PtrPush( vUndefs, pNtkBox );
+ pNtkBox->pData = Vec_PtrAlloc( 16 );
+ }
+ // save the instance
+ Vec_PtrPush( pNtkBox->pData, pBox );
+ }
+ }
+ return vUndefs;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Reports how many times each type of undefined box occurs.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Ver_ParseReportUndefBoxes( Ver_Man_t * pMan )
+{
+ Abc_Ntk_t * pNtk;
+ Abc_Obj_t * pBox;
+ int i, k, nBoxes;
+ // clean
+ nBoxes = 0;
+ Vec_PtrForEachEntry( pMan->pDesign->vModules, pNtk, i )
+ {
+ pNtk->fHiePath = 0;
+ if ( !Ver_NtkIsDefined(pNtk) )
+ nBoxes++;
+ }
+ // count
+ Vec_PtrForEachEntry( pMan->pDesign->vModules, pNtk, i )
+ Abc_NtkForEachBlackbox( pNtk, pBox, k )
+ if ( pBox->pData && !Ver_NtkIsDefined(pBox->pData) )
+ ((Abc_Ntk_t *)pBox->pData)->fHiePath++;
+ // print the stats
+ printf( "Warning: The design contains %d undefined objects interpreted as blackboxes:\n", nBoxes );
+ Vec_PtrForEachEntry( pMan->pDesign->vModules, pNtk, i )
+ if ( !Ver_NtkIsDefined(pNtk) )
+ printf( "%s (%d) ", Abc_NtkName(pNtk), pNtk->fHiePath );
+ printf( "\n" );
+ // clean
+ Vec_PtrForEachEntry( pMan->pDesign->vModules, pNtk, i )
+ pNtk->fHiePath = 0;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Returns 1 if there are non-driven nets.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Ver_ParseCheckNondrivenNets( Vec_Ptr_t * vUndefs )
+{
+ Abc_Ntk_t * pNtk;
+ Ver_Bundle_t * pBundle;
+ Abc_Obj_t * pBox, * pNet;
+ int i, k, j, m;
+ // go through undef box types
+ Vec_PtrForEachEntry( vUndefs, pNtk, i )
+ // go through instances of this type
+ Vec_PtrForEachEntry( pNtk->pData, pBox, k )
+ // go through the bundles of this instance
+ Vec_PtrForEachEntryReverse( (Vec_Ptr_t *)pBox->pCopy, pBundle, j )
+ // go through the actual nets of this bundle
+ if ( pBundle )
+ Vec_PtrForEachEntry( pBundle->vNetsActual, pNet, m )
+ {
+ char * pName = Abc_ObjName(pNet);
+ if ( Abc_ObjFaninNum(pNet) == 0 ) // non-driven
+ if ( strcmp(Abc_ObjName(pNet), "1\'b0") && strcmp(Abc_ObjName(pNet), "1\'b1") ) // diff from a const
+ return 1;
+ }
+ return 0;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Checks if formal nets with the given name are driven in any of the instances of undef boxes.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Ver_ParseFormalNetsAreDriven( Abc_Ntk_t * pNtk, char * pNameFormal )
+{
+ Ver_Bundle_t * pBundle;
+ Abc_Obj_t * pBox, * pNet;
+ int k, j, m;
+ // go through instances of this type
+ Vec_PtrForEachEntry( pNtk->pData, pBox, k )
+ {
+ // find a bundle with the given name in this instance
+ Vec_PtrForEachEntryReverse( (Vec_Ptr_t *)pBox->pCopy, pBundle, j )
+ if ( pBundle && !strcmp( pBundle->pNameFormal, pNameFormal ) )
+ break;
+ // skip non-driven bundles
+ if ( j == Vec_PtrSize((Vec_Ptr_t *)pBox->pCopy) )
+ continue;
+ // check if all nets are driven in this bundle
+ Vec_PtrForEachEntry( pBundle->vNetsActual, pNet, m )
+ if ( Abc_ObjFaninNum(pNet) > 0 )
+ return 1;
+ }
+ return 0;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Returns the non-driven bundle that is given distance from the end.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Ver_Bundle_t * Ver_ParseGetNondrivenBundle( Abc_Ntk_t * pNtk, int Counter )
+{
+ Ver_Bundle_t * pBundle;
+ Abc_Obj_t * pBox, * pNet;
+ int k, m;
+ // go through instances of this type
+ Vec_PtrForEachEntry( pNtk->pData, pBox, k )
+ {
+ if ( Counter >= Vec_PtrSize((Vec_Ptr_t *)pBox->pCopy) )
+ continue;
+ // get the bundle given distance away
+ pBundle = Vec_PtrEntry( (Vec_Ptr_t *)pBox->pCopy, Vec_PtrSize((Vec_Ptr_t *)pBox->pCopy) - 1 - Counter );
+ if ( pBundle == NULL )
+ continue;
+ // go through the actual nets of this bundle
+ Vec_PtrForEachEntry( pBundle->vNetsActual, pNet, m )
+ if ( !Abc_ObjFaninNum(pNet) && !Ver_ParseFormalNetsAreDriven(pNtk, pBundle->pNameFormal) ) // non-driven
+ return pBundle;
+ }
+ return NULL;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Drives the bundle in the given undef box.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Ver_ParseDriveFormal( Ver_Man_t * pMan, Abc_Ntk_t * pNtk, Ver_Bundle_t * pBundle0 )
+{
+ char Buffer[200];
+ char * pName;
+ Ver_Bundle_t * pBundle;
+ Abc_Obj_t * pBox, * pTerm, * pTermNew, * pNetAct, * pNetFormal;
+ int k, j, m;
+
+ // drive this net in the undef box
+ Vec_PtrForEachEntry( pBundle0->vNetsActual, pNetAct, m )
+ {
+ // create the formal net
+ if ( Vec_PtrSize(pBundle0->vNetsActual) == 1 )
+ sprintf( Buffer, "%s", pBundle0->pNameFormal );
+ else
+ sprintf( Buffer, "%s[%d]", pBundle0->pNameFormal, m );
+ assert( Abc_NtkFindNet( pNtk, Buffer ) == NULL );
+ pNetFormal = Abc_NtkFindOrCreateNet( pNtk, Buffer );
+ // connect it to the box
+ pTerm = Abc_NtkCreateBo( pNtk );
+ assert( Abc_NtkBoxNum(pNtk) <= 1 );
+ pBox = Abc_NtkBoxNum(pNtk)? Abc_NtkBox(pNtk,0) : Abc_NtkCreateBlackbox(pNtk);
+ Abc_ObjAddFanin( Abc_NtkCreatePo(pNtk), pNetFormal );
+ Abc_ObjAddFanin( pNetFormal, pTerm );
+ Abc_ObjAddFanin( pTerm, pBox );
+ }
+
+ // go through instances of this type
+ pName = Extra_UtilStrsav(pBundle0->pNameFormal);
+ Vec_PtrForEachEntry( pNtk->pData, pBox, k )
+ {
+ // find a bundle with the given name in this instance
+ Vec_PtrForEachEntryReverse( (Vec_Ptr_t *)pBox->pCopy, pBundle, j )
+ if ( pBundle && !strcmp( pBundle->pNameFormal, pName ) )
+ break;
+ // skip non-driven bundles
+ if ( j == Vec_PtrSize((Vec_Ptr_t *)pBox->pCopy) )
+ continue;
+ // check if any nets are driven in this bundle
+ Vec_PtrForEachEntry( pBundle->vNetsActual, pNetAct, m )
+ if ( Abc_ObjFaninNum(pNetAct) > 0 )
+ {
+ sprintf( pMan->sError, "Internal error while trying to connect undefined boxes. It is likely that the algorithm currently used has its limitations." );
+ Ver_ParsePrintErrorMessage( pMan );
+ return 0;
+ }
+ // drive the nets by the undef box
+ Vec_PtrForEachEntryReverse( pBundle->vNetsActual, pNetAct, m )
+ {
+ pTermNew = Abc_NtkCreateBo( pNetAct->pNtk );
+ Abc_ObjAddFanin( pTermNew, pBox );
+ Abc_ObjAddFanin( pNetAct, pTermNew );
+ }
+ // remove the bundle
+ Ver_ParseFreeBundle( pBundle );
+ Vec_PtrWriteEntry( (Vec_Ptr_t *)pBox->pCopy, j, NULL );
+ }
+ free( pName );
+ return 1;
+}
+
+
+/**Function*************************************************************
+
+ Synopsis [Drives the bundle in the given undef box.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Ver_ParseDriveInputs( Ver_Man_t * pMan, Vec_Ptr_t * vUndefs )
+{
+ char Buffer[200];
+ Ver_Bundle_t * pBundle;
+ Abc_Ntk_t * pNtk;
+ Abc_Obj_t * pBox, * pBox2, * pTerm, * pTermNew, * pNetFormal, * pNetAct;
+ int i, k, j, m, CountCur, CountTotal = -1;
+ // iterate through the undef boxes
+ Vec_PtrForEachEntry( vUndefs, pNtk, i )
+ {
+ // count the number of unconnected bundles for instances of this type of box
+ CountTotal = -1;
+ Vec_PtrForEachEntry( pNtk->pData, pBox, k )
+ {
+ CountCur = 0;
+ Vec_PtrForEachEntry( (Vec_Ptr_t *)pBox->pCopy, pBundle, j )
+ CountCur += (pBundle != NULL);
+ if ( CountTotal == -1 )
+ CountTotal = CountCur;
+ else if ( CountTotal != CountCur )
+ {
+ sprintf( pMan->sError, "The number of formal inputs (%d) is different from the expected one (%d) when instantiating network %s in box %s.",
+ CountCur, CountTotal, pNtk->pName, Abc_ObjName(pBox) );
+ Ver_ParsePrintErrorMessage( pMan );
+ return 0;
+ }
+ }
+
+ // create formals
+ pBox = Vec_PtrEntry( pNtk->pData, 0 );
+ Vec_PtrForEachEntry( (Vec_Ptr_t *)pBox->pCopy, pBundle, j )
+ {
+ if ( pBundle == NULL )
+ continue;
+ Vec_PtrForEachEntry( pBundle->vNetsActual, pNetAct, m )
+ {
+ // find create the formal net
+ if ( Vec_PtrSize(pBundle->vNetsActual) == 1 )
+ sprintf( Buffer, "%s", pBundle->pNameFormal );
+ else
+ sprintf( Buffer, "%s[%d]", pBundle->pNameFormal, m );
+ assert( Abc_NtkFindNet( pNtk, Buffer ) == NULL );
+ pNetFormal = Abc_NtkFindOrCreateNet( pNtk, Buffer );
+ // connect
+ pTerm = Abc_NtkCreateBi( pNtk );
+ assert( Abc_NtkBoxNum(pNtk) <= 1 );
+ pBox2 = Abc_NtkBoxNum(pNtk)? Abc_NtkBox(pNtk,0) : Abc_NtkCreateBlackbox(pNtk);
+ Abc_ObjAddFanin( pNetFormal, Abc_NtkCreatePi(pNtk) );
+ Abc_ObjAddFanin( pTerm, pNetFormal );
+ Abc_ObjAddFanin( pBox2, pTerm );
+ }
+ }
+
+ // go through all the boxes
+ Vec_PtrForEachEntry( pNtk->pData, pBox, k )
+ {
+ // go through all the bundles
+ Vec_PtrForEachEntry( (Vec_Ptr_t *)pBox->pCopy, pBundle, j )
+ {
+ if ( pBundle == NULL )
+ continue;
+ // drive the nets by the undef box
+ Vec_PtrForEachEntryReverse( pBundle->vNetsActual, pNetAct, m )
+ {
+ pTermNew = Abc_NtkCreateBi( pNetAct->pNtk );
+ Abc_ObjAddFanin( pBox, pTermNew );
+ Abc_ObjAddFanin( pTermNew, pNetAct );
+ }
+ // remove the bundle
+ Ver_ParseFreeBundle( pBundle );
+ Vec_PtrWriteEntry( (Vec_Ptr_t *)pBox->pCopy, j, NULL );
+ }
+
+ // free the bundles
+ Vec_PtrFree( (Vec_Ptr_t *)pBox->pCopy );
+ pBox->pCopy = NULL;
+ }
+ }
+ return 1;
+}
+
+
+/**Function*************************************************************
+
+ Synopsis [Returns the max size of any undef box.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Ver_ParseMaxBoxSize( Vec_Ptr_t * vUndefs )
+{
+ Abc_Ntk_t * pNtk;
+ Abc_Obj_t * pBox;
+ int i, k, nMaxSize = 0;
+ // go through undef box types
+ Vec_PtrForEachEntry( vUndefs, pNtk, i )
+ // go through instances of this type
+ Vec_PtrForEachEntry( pNtk->pData, pBox, k )
+ // check the number of bundles of this instance
+ if ( nMaxSize < Vec_PtrSize((Vec_Ptr_t *)pBox->pCopy) )
+ nMaxSize = Vec_PtrSize((Vec_Ptr_t *)pBox->pCopy);
+ return nMaxSize;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Prints the comprehensive report into a log file.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Ver_ParsePrintLog( Ver_Man_t * pMan )
+{
+ Abc_Ntk_t * pNtk, * pNtkBox;
+ Abc_Obj_t * pBox;
+ FILE * pFile;
+ char * pNameGeneric;
+ char Buffer[1000];
+ int i, k;
+
+ // open the log file
+ pNameGeneric = Extra_FileNameGeneric( pMan->pFileName );
+ sprintf( Buffer, "%s.log", pNameGeneric );
+ free( pNameGeneric );
+ pFile = fopen( Buffer, "w" );
+
+ // count the total number of instances and how many times they occur
+ Vec_PtrForEachEntry( pMan->pDesign->vModules, pNtk, i )
+ pNtk->fHieVisited = 0;
+ Vec_PtrForEachEntry( pMan->pDesign->vModules, pNtk, i )
+ Abc_NtkForEachBox( pNtk, pBox, k )
+ {
+ if ( Abc_ObjIsLatch(pBox) )
+ continue;
+ pNtkBox = pBox->pData;
+ if ( pNtkBox == NULL )
+ continue;
+ pNtkBox->fHieVisited++;
+ }
+ // print each box and its stats
+ fprintf( pFile, "The hierarhical design %s contains %d modules:\n", pMan->pFileName, Vec_PtrSize(pMan->pDesign->vModules) );
+ Vec_PtrForEachEntry( pMan->pDesign->vModules, pNtk, i )
+ {
+ fprintf( pFile, "%-24s : ", Abc_NtkName(pNtk) );
+ if ( !Ver_NtkIsDefined(pNtk) )
+ fprintf( pFile, "undefbox" );
+ else if ( Abc_NtkHasBlackbox(pNtk) )
+ fprintf( pFile, "blackbox" );
+ else
+ fprintf( pFile, "logicbox" );
+ fprintf( pFile, " instantiated %6d times ", pNtk->fHieVisited );
+// fprintf( pFile, "\n " );
+ fprintf( pFile, " pi = %4d", Abc_NtkPiNum(pNtk) );
+ fprintf( pFile, " po = %4d", Abc_NtkPiNum(pNtk) );
+ fprintf( pFile, " nd = %8d", Abc_NtkNodeNum(pNtk) );
+ fprintf( pFile, " lat = %6d", Abc_NtkLatchNum(pNtk) );
+ fprintf( pFile, " box = %6d", Abc_NtkBoxNum(pNtk)-Abc_NtkLatchNum(pNtk) );
+ fprintf( pFile, "\n" );
+ }
+ Vec_PtrForEachEntry( pMan->pDesign->vModules, pNtk, i )
+ pNtk->fHieVisited = 0;
+
+ // report instances with dangling outputs
+ if ( Vec_PtrSize(pMan->pDesign->vModules) > 1 )
+ {
+ Vec_Ptr_t * vBundles;
+ Ver_Bundle_t * pBundle;
+ int j, nActNets, Counter = 0, CounterBoxes = 0;
+ // count the number of instances with dangling outputs
+ Vec_PtrForEachEntry( pMan->pDesign->vModules, pNtk, i )
+ {
+ Abc_NtkForEachBox( pNtk, pBox, k )
+ {
+ if ( Abc_ObjIsLatch(pBox) )
+ continue;
+ vBundles = (Vec_Ptr_t *)pBox->pCopy;
+ pNtkBox = pBox->pData;
+ if ( pNtkBox == NULL )
+ continue;
+ if ( !Ver_NtkIsDefined(pNtkBox) )
+ continue;
+ // count the number of actual nets
+ nActNets = 0;
+ Vec_PtrForEachEntry( vBundles, pBundle, j )
+ nActNets += Vec_PtrSize(pBundle->vNetsActual);
+ // the box is defined and will be connected
+ if ( nActNets != Abc_NtkPiNum(pNtkBox) + Abc_NtkPoNum(pNtkBox) )
+ Counter++;
+ }
+ }
+ if ( Counter == 0 )
+ fprintf( pFile, "The outputs of all box instances are connected.\n" );
+ else
+ {
+ fprintf( pFile, "\n" );
+ fprintf( pFile, "The outputs of %d box instances are not connected:\n", Counter );
+ // enumerate through the boxes
+ Vec_PtrForEachEntry( pMan->pDesign->vModules, pNtk, i )
+ {
+ Abc_NtkForEachBox( pNtk, pBox, k )
+ {
+ if ( Abc_ObjIsLatch(pBox) )
+ continue;
+ vBundles = (Vec_Ptr_t *)pBox->pCopy;
+ pNtkBox = pBox->pData;
+ if ( pNtkBox == NULL )
+ continue;
+ if ( !Ver_NtkIsDefined(pNtkBox) )
+ continue;
+ // count the number of actual nets
+ nActNets = 0;
+ Vec_PtrForEachEntry( vBundles, pBundle, j )
+ nActNets += Vec_PtrSize(pBundle->vNetsActual);
+ // the box is defined and will be connected
+ if ( nActNets != Abc_NtkPiNum(pNtkBox) + Abc_NtkPoNum(pNtkBox) )
+ fprintf( pFile, "In module \"%s\" instance \"%s\" of box \"%s\" has different numbers of actual/formal nets (%d/%d).\n",
+ Abc_NtkName(pNtk), Abc_ObjName(pBox), Abc_NtkName(pNtkBox), nActNets, Abc_NtkPiNum(pNtkBox) + Abc_NtkPoNum(pNtkBox) );
+ }
+ }
+ }
+ }
+ fclose( pFile );
+ printf( "Hierarchy statistics can be found in log file \"%s\".\n", Buffer );
+}
+
+
+/**Function*************************************************************
+
+ Synopsis [Attaches the boxes to the network.]
+
+ Description [This procedure is called after the design is parsed.
+ At that point, all the defined models have their PIs present.
+ They are connected first. Next undef boxes are processed (if present).
+ Iteratively, one bundle is selected to be driven by the undef boxes in such
+ a way that there is no conflict (if it is driven by an instance of the box,
+ no other net will be driven twice by the same formal net of some other instance
+ of the same box). In the end, all the remaining nets that cannot be driven
+ by the undef boxes are connected to the undef boxes as inputs.]
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Ver_ParseAttachBoxes( Ver_Man_t * pMan )
+{
+ Abc_Ntk_t * pNtk;
+ Ver_Bundle_t * pBundle;
+ Vec_Ptr_t * vUndefs;
+ int i, RetValue, Counter, nMaxBoxSize;
+
+ // print the log file
+ if ( pMan->pDesign->vModules && Vec_PtrSize(pMan->pDesign->vModules) > 1 )
+ Ver_ParsePrintLog( pMan );
+
+ // connect defined boxes
+ RetValue = Ver_ParseConnectDefBoxes( pMan );
+ if ( RetValue < 2 )
+ return RetValue;
+
+ // report the boxes
+ Ver_ParseReportUndefBoxes( pMan );
+
+ // collect undef box types and their actual instances
+ vUndefs = Ver_ParseCollectUndefBoxes( pMan );
+ assert( Vec_PtrSize( vUndefs ) > 0 );
+
+ // go through all undef box types
+ Counter = 0;
+ nMaxBoxSize = Ver_ParseMaxBoxSize( vUndefs );
+ while ( Ver_ParseCheckNondrivenNets(vUndefs) && Counter < nMaxBoxSize )
+ {
+ // go through undef box types
+ pBundle = NULL;
+ Vec_PtrForEachEntry( vUndefs, pNtk, i )
+ if ( pBundle = Ver_ParseGetNondrivenBundle( pNtk, Counter ) )
+ break;
+ if ( pBundle == NULL )
+ {
+ Counter++;
+ continue;
+ }
+ // drive this bundle by this box
+ if ( !Ver_ParseDriveFormal( pMan, pNtk, pBundle ) )
+ return 0;
+ }
+
+ // make all the remaining bundles the drivers of undefs
+ if ( !Ver_ParseDriveInputs( pMan, vUndefs ) )
+ return 0;
+
+ // cleanup
+ Vec_PtrForEachEntry( vUndefs, pNtk, i )
+ {
+ Vec_PtrFree( pNtk->pData );
+ pNtk->pData = NULL;
+ }
+ Vec_PtrFree( vUndefs );
+ return 1;
+}
+
+
+/**Function*************************************************************
+
+ Synopsis [Creates PI terminal and net.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Abc_Obj_t * Ver_ParseCreatePi( Abc_Ntk_t * pNtk, char * pName )
+{
+ Abc_Obj_t * pNet, * pTerm;
+ // get the PI net
+// pNet = Ver_ParseFindNet( pNtk, pName );
+// if ( pNet )
+// printf( "Warning: PI \"%s\" appears twice in the list.\n", pName );
+ pNet = Abc_NtkFindOrCreateNet( pNtk, pName );
+ // add the PI node
+ pTerm = Abc_NtkCreatePi( pNtk );
+ Abc_ObjAddFanin( pNet, pTerm );
+ return pTerm;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Creates PO terminal and net.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Abc_Obj_t * Ver_ParseCreatePo( Abc_Ntk_t * pNtk, char * pName )
+{
+ Abc_Obj_t * pNet, * pTerm;
+ // get the PO net
+// pNet = Ver_ParseFindNet( pNtk, pName );
+// if ( pNet && Abc_ObjFaninNum(pNet) == 0 )
+// printf( "Warning: PO \"%s\" appears twice in the list.\n", pName );
+ pNet = Abc_NtkFindOrCreateNet( pNtk, pName );
+ // add the PO node
+ pTerm = Abc_NtkCreatePo( pNtk );
+ Abc_ObjAddFanin( pTerm, pNet );
+ return pTerm;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Create a latch with the given input/output.]
+
+ Description [By default, the latch value is a don't-care.]
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Abc_Obj_t * Ver_ParseCreateLatch( Abc_Ntk_t * pNtk, Abc_Obj_t * pNetLI, Abc_Obj_t * pNetLO )
+{
+ Abc_Obj_t * pLatch, * pTerm;
+ // add the BO terminal
+ pTerm = Abc_NtkCreateBi( pNtk );
+ Abc_ObjAddFanin( pTerm, pNetLI );
+ // add the latch box
+ pLatch = Abc_NtkCreateLatch( pNtk );
+ Abc_ObjAddFanin( pLatch, pTerm );
+ // add the BI terminal
+ pTerm = Abc_NtkCreateBo( pNtk );
+ Abc_ObjAddFanin( pTerm, pLatch );
+ // get the LO net
+ Abc_ObjAddFanin( pNetLO, pTerm );
+ // set latch name
+ Abc_ObjAssignName( pLatch, Abc_ObjName(pNetLO), "L" );
+ Abc_LatchSetInitDc( pLatch );
+ return pLatch;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Creates inverter and returns its net.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Abc_Obj_t * Ver_ParseCreateInv( Abc_Ntk_t * pNtk, Abc_Obj_t * pNet )
+{
+ Abc_Obj_t * pObj;
+ pObj = Abc_NtkCreateNodeInv( pNtk, pNet );
+ pNet = Abc_NtkCreateNet( pNtk );
+ Abc_ObjAddFanin( pNet, pObj );
+ return pNet;
+}
+
+
+////////////////////////////////////////////////////////////////////////
+/// END OF FILE ///
+////////////////////////////////////////////////////////////////////////
+
+
diff --git a/src/base/ver/verFormula.c b/src/base/ver/verFormula.c
new file mode 100644
index 00000000..19a2c523
--- /dev/null
+++ b/src/base/ver/verFormula.c
@@ -0,0 +1,474 @@
+/**CFile****************************************************************
+
+ FileName [verFormula.c]
+
+ SystemName [ABC: Logic synthesis and verification system.]
+
+ PackageName [Verilog parser.]
+
+ Synopsis [Formula parser to read Verilog assign statements.]
+
+ Author [Alan Mishchenko]
+
+ Affiliation [UC Berkeley]
+
+ Date [Ver. 1.0. Started - August 19, 2006.]
+
+ Revision [$Id: verFormula.c,v 1.00 2006/08/19 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "ver.h"
+
+////////////////////////////////////////////////////////////////////////
+/// DECLARATIONS ///
+////////////////////////////////////////////////////////////////////////
+
+// the list of operation symbols to be used in expressions
+#define VER_PARSE_SYM_OPEN '(' // opening paranthesis
+#define VER_PARSE_SYM_CLOSE ')' // closing paranthesis
+#define VER_PARSE_SYM_CONST0 '0' // constant 0
+#define VER_PARSE_SYM_CONST1 '1' // constant 1
+#define VER_PARSE_SYM_NEGBEF1 '!' // negation before the variable
+#define VER_PARSE_SYM_NEGBEF2 '~' // negation before the variable
+#define VER_PARSE_SYM_AND '&' // logic AND
+#define VER_PARSE_SYM_OR '|' // logic OR
+#define VER_PARSE_SYM_XOR '^' // logic XOR
+#define VER_PARSE_SYM_MUX1 '?' // first symbol of MUX
+#define VER_PARSE_SYM_MUX2 ':' // second symbol of MUX
+
+// the list of opcodes (also specifying operation precedence)
+#define VER_PARSE_OPER_NEG 7 // negation (highest precedence)
+#define VER_PARSE_OPER_AND 6 // logic AND
+#define VER_PARSE_OPER_XOR 5 // logic EXOR (a'b | ab')
+#define VER_PARSE_OPER_OR 4 // logic OR
+#define VER_PARSE_OPER_EQU 3 // equvalence (a'b'| ab )
+#define VER_PARSE_OPER_MUX 2 // MUX(a,b,c) (ab | a'c )
+#define VER_PARSE_OPER_MARK 1 // OpStack token standing for an opening paranthesis
+
+// these are values of the internal Flag
+#define VER_PARSE_FLAG_START 1 // after the opening parenthesis
+#define VER_PARSE_FLAG_VAR 2 // after operation is received
+#define VER_PARSE_FLAG_OPER 3 // after operation symbol is received
+#define VER_PARSE_FLAG_ERROR 4 // when error is detected
+
+static Hop_Obj_t * Ver_FormulaParserTopOper( Hop_Man_t * pMan, Vec_Ptr_t * vStackFn, int Oper );
+static int Ver_FormulaParserFindVar( char * pString, Vec_Ptr_t * vNames );
+
+////////////////////////////////////////////////////////////////////////
+/// FUNCTION DEFINITIONS ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+ Synopsis [Parser of the formula encountered in assign statements.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void * Ver_FormulaParser( char * pFormula, void * pMan, Vec_Ptr_t * vNames, Vec_Ptr_t * vStackFn, Vec_Int_t * vStackOp, char * pErrorMessage )
+{
+ char * pTemp;
+ Hop_Obj_t * bFunc, * bTemp;
+ int nParans, Flag;
+ int Oper, Oper1, Oper2;
+ int v;
+
+ // clear the stacks and the names
+ Vec_PtrClear( vNames );
+ Vec_PtrClear( vStackFn );
+ Vec_IntClear( vStackOp );
+
+ if ( !strcmp(pFormula, "0") || !strcmp(pFormula, "1\'b0") )
+ return Hop_ManConst0(pMan);
+ if ( !strcmp(pFormula, "1") || !strcmp(pFormula, "1\'b1") )
+ return Hop_ManConst1(pMan);
+
+ // make sure that the number of opening and closing parantheses is the same
+ nParans = 0;
+ for ( pTemp = pFormula; *pTemp; pTemp++ )
+ if ( *pTemp == '(' )
+ nParans++;
+ else if ( *pTemp == ')' )
+ nParans--;
+ if ( nParans != 0 )
+ {
+ sprintf( pErrorMessage, "Parse_FormulaParser(): Different number of opening and closing parantheses ()." );
+ return NULL;
+ }
+
+ // add parantheses
+ pTemp = pFormula + strlen(pFormula) + 2;
+ *pTemp-- = 0; *pTemp = ')';
+ while ( --pTemp != pFormula )
+ *pTemp = *(pTemp - 1);
+ *pTemp = '(';
+
+ // perform parsing
+ Flag = VER_PARSE_FLAG_START;
+ for ( pTemp = pFormula; *pTemp; pTemp++ )
+ {
+ switch ( *pTemp )
+ {
+ // skip all spaces, tabs, and end-of-lines
+ case ' ':
+ case '\t':
+ case '\r':
+ case '\n':
+ continue;
+/*
+ // treat Constant 0 as a variable
+ case VER_PARSE_SYM_CONST0:
+ Vec_PtrPush( vStackFn, Hop_ManConst0(pMan) ); // Cudd_Ref( Hop_ManConst0(pMan) );
+ if ( Flag == VER_PARSE_FLAG_VAR )
+ {
+ sprintf( pErrorMessage, "Parse_FormulaParser(): No operation symbol before constant 0." );
+ Flag = VER_PARSE_FLAG_ERROR;
+ break;
+ }
+ Flag = VER_PARSE_FLAG_VAR;
+ break;
+
+ // the same for Constant 1
+ case VER_PARSE_SYM_CONST1:
+ Vec_PtrPush( vStackFn, Hop_ManConst1(pMan) ); // Cudd_Ref( Hop_ManConst1(pMan) );
+ if ( Flag == VER_PARSE_FLAG_VAR )
+ {
+ sprintf( pErrorMessage, "Parse_FormulaParser(): No operation symbol before constant 1." );
+ Flag = VER_PARSE_FLAG_ERROR;
+ break;
+ }
+ Flag = VER_PARSE_FLAG_VAR;
+ break;
+*/
+ case VER_PARSE_SYM_NEGBEF1:
+ case VER_PARSE_SYM_NEGBEF2:
+ if ( Flag == VER_PARSE_FLAG_VAR )
+ {// if NEGBEF follows a variable, AND is assumed
+ sprintf( pErrorMessage, "Parse_FormulaParser(): Variable before negation." );
+ Flag = VER_PARSE_FLAG_ERROR;
+ break;
+ }
+ Vec_IntPush( vStackOp, VER_PARSE_OPER_NEG );
+ break;
+
+ case VER_PARSE_SYM_AND:
+ case VER_PARSE_SYM_OR:
+ case VER_PARSE_SYM_XOR:
+ case VER_PARSE_SYM_MUX1:
+ case VER_PARSE_SYM_MUX2:
+ if ( Flag != VER_PARSE_FLAG_VAR )
+ {
+ sprintf( pErrorMessage, "Parse_FormulaParser(): There is no variable before AND, EXOR, or OR." );
+ Flag = VER_PARSE_FLAG_ERROR;
+ break;
+ }
+ if ( *pTemp == VER_PARSE_SYM_AND )
+ Vec_IntPush( vStackOp, VER_PARSE_OPER_AND );
+ else if ( *pTemp == VER_PARSE_SYM_OR )
+ Vec_IntPush( vStackOp, VER_PARSE_OPER_OR );
+ else if ( *pTemp == VER_PARSE_SYM_XOR )
+ Vec_IntPush( vStackOp, VER_PARSE_OPER_XOR );
+ else if ( *pTemp == VER_PARSE_SYM_MUX1 )
+ Vec_IntPush( vStackOp, VER_PARSE_OPER_MUX );
+// else if ( *pTemp == VER_PARSE_SYM_MUX2 )
+// Vec_IntPush( vStackOp, VER_PARSE_OPER_MUX );
+ Flag = VER_PARSE_FLAG_OPER;
+ break;
+
+ case VER_PARSE_SYM_OPEN:
+ if ( Flag == VER_PARSE_FLAG_VAR )
+ {
+ sprintf( pErrorMessage, "Parse_FormulaParser(): Variable before a paranthesis." );
+ Flag = VER_PARSE_FLAG_ERROR;
+ break;
+ }
+ Vec_IntPush( vStackOp, VER_PARSE_OPER_MARK );
+ // after an opening bracket, it feels like starting over again
+ Flag = VER_PARSE_FLAG_START;
+ break;
+
+ case VER_PARSE_SYM_CLOSE:
+ if ( Vec_IntSize( vStackOp ) )
+ {
+ while ( 1 )
+ {
+ if ( !Vec_IntSize( vStackOp ) )
+ {
+ sprintf( pErrorMessage, "Parse_FormulaParser(): There is no opening paranthesis\n" );
+ Flag = VER_PARSE_FLAG_ERROR;
+ break;
+ }
+ Oper = Vec_IntPop( vStackOp );
+ if ( Oper == VER_PARSE_OPER_MARK )
+ break;
+ // skip the second MUX operation
+// if ( Oper == VER_PARSE_OPER_MUX2 )
+// {
+// Oper = Vec_IntPop( vStackOp );
+// assert( Oper == VER_PARSE_OPER_MUX1 );
+// }
+
+ // perform the given operation
+ if ( Ver_FormulaParserTopOper( pMan, vStackFn, Oper ) == NULL )
+ {
+ sprintf( pErrorMessage, "Parse_FormulaParser(): Unknown operation\n" );
+ return NULL;
+ }
+ }
+ }
+ else
+ {
+ sprintf( pErrorMessage, "Parse_FormulaParser(): There is no opening paranthesis\n" );
+ Flag = VER_PARSE_FLAG_ERROR;
+ break;
+ }
+ if ( Flag != VER_PARSE_FLAG_ERROR )
+ Flag = VER_PARSE_FLAG_VAR;
+ break;
+
+
+ default:
+ // scan the next name
+ v = Ver_FormulaParserFindVar( pTemp, vNames );
+ if ( *pTemp == '\\' )
+ pTemp++;
+ pTemp += (int)Vec_PtrEntry( vNames, 2*v ) - 1;
+
+ // assume operation AND, if vars follow one another
+ if ( Flag == VER_PARSE_FLAG_VAR )
+ {
+ sprintf( pErrorMessage, "Parse_FormulaParser(): Incorrect state." );
+ return NULL;
+ }
+ bTemp = Hop_IthVar( pMan, v );
+ Vec_PtrPush( vStackFn, bTemp ); // Cudd_Ref( bTemp );
+ Flag = VER_PARSE_FLAG_VAR;
+ break;
+ }
+
+ if ( Flag == VER_PARSE_FLAG_ERROR )
+ break; // error exit
+ else if ( Flag == VER_PARSE_FLAG_START )
+ continue; // go on parsing
+ else if ( Flag == VER_PARSE_FLAG_VAR )
+ while ( 1 )
+ { // check if there are negations in the OpStack
+ if ( !Vec_IntSize(vStackOp) )
+ break;
+ Oper = Vec_IntPop( vStackOp );
+ if ( Oper != VER_PARSE_OPER_NEG )
+ {
+ Vec_IntPush( vStackOp, Oper );
+ break;
+ }
+ else
+ {
+// Vec_PtrPush( vStackFn, Cudd_Not(Vec_PtrPop(vStackFn)) );
+ Vec_PtrPush( vStackFn, Hop_Not(Vec_PtrPop(vStackFn)) );
+ }
+ }
+ else // if ( Flag == VER_PARSE_FLAG_OPER )
+ while ( 1 )
+ { // execute all the operations in the OpStack
+ // with precedence higher or equal than the last one
+ Oper1 = Vec_IntPop( vStackOp ); // the last operation
+ if ( !Vec_IntSize(vStackOp) )
+ { // if it is the only operation, push it back
+ Vec_IntPush( vStackOp, Oper1 );
+ break;
+ }
+ Oper2 = Vec_IntPop( vStackOp ); // the operation before the last one
+ if ( Oper2 >= Oper1 && !(Oper1 == Oper2 && Oper1 == VER_PARSE_OPER_MUX) )
+ { // if Oper2 precedence is higher or equal, execute it
+ if ( Ver_FormulaParserTopOper( pMan, vStackFn, Oper2 ) == NULL )
+ {
+ sprintf( pErrorMessage, "Parse_FormulaParser(): Unknown operation\n" );
+ return NULL;
+ }
+ Vec_IntPush( vStackOp, Oper1 ); // push the last operation back
+ }
+ else
+ { // if Oper2 precedence is lower, push them back and done
+ Vec_IntPush( vStackOp, Oper2 );
+ Vec_IntPush( vStackOp, Oper1 );
+ break;
+ }
+ }
+ }
+
+ if ( Flag != VER_PARSE_FLAG_ERROR )
+ {
+ if ( Vec_PtrSize(vStackFn) )
+ {
+ bFunc = Vec_PtrPop(vStackFn);
+ if ( !Vec_PtrSize(vStackFn) )
+ if ( !Vec_IntSize(vStackOp) )
+ {
+// Cudd_Deref( bFunc );
+ return bFunc;
+ }
+ else
+ sprintf( pErrorMessage, "Parse_FormulaParser(): Something is left in the operation stack\n" );
+ else
+ sprintf( pErrorMessage, "Parse_FormulaParser(): Something is left in the function stack\n" );
+ }
+ else
+ sprintf( pErrorMessage, "Parse_FormulaParser(): The input string is empty\n" );
+ }
+// Cudd_Ref( bFunc );
+// Cudd_RecursiveDeref( dd, bFunc );
+ return NULL;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Performs the operation on the top entries in the stack.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Hop_Obj_t * Ver_FormulaParserTopOper( Hop_Man_t * pMan, Vec_Ptr_t * vStackFn, int Oper )
+{
+ Hop_Obj_t * bArg0, * bArg1, * bArg2, * bFunc;
+ // perform the given operation
+ bArg2 = Vec_PtrPop( vStackFn );
+ bArg1 = Vec_PtrPop( vStackFn );
+ if ( Oper == VER_PARSE_OPER_AND )
+ bFunc = Hop_And( pMan, bArg1, bArg2 );
+ else if ( Oper == VER_PARSE_OPER_XOR )
+ bFunc = Hop_Exor( pMan, bArg1, bArg2 );
+ else if ( Oper == VER_PARSE_OPER_OR )
+ bFunc = Hop_Or( pMan, bArg1, bArg2 );
+ else if ( Oper == VER_PARSE_OPER_EQU )
+ bFunc = Hop_Not( Hop_Exor( pMan, bArg1, bArg2 ) );
+ else if ( Oper == VER_PARSE_OPER_MUX )
+ {
+ bArg0 = Vec_PtrPop( vStackFn );
+// bFunc = Cudd_bddIte( dd, bArg0, bArg1, bArg2 ); Cudd_Ref( bFunc );
+ bFunc = Hop_Mux( pMan, bArg0, bArg1, bArg2 );
+// Cudd_RecursiveDeref( dd, bArg0 );
+// Cudd_Deref( bFunc );
+ }
+ else
+ return NULL;
+// Cudd_Ref( bFunc );
+// Cudd_RecursiveDeref( dd, bArg1 );
+// Cudd_RecursiveDeref( dd, bArg2 );
+ Vec_PtrPush( vStackFn, bFunc );
+ return bFunc;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Returns the index of the new variable found.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Ver_FormulaParserFindVar( char * pString, Vec_Ptr_t * vNames )
+{
+ char * pTemp, * pTemp2;
+ int nLength, nLength2, i;
+ // start the string
+ pTemp = pString;
+ // find the end of the string delimited by other characters
+ if ( *pTemp == '\\' )
+ {
+ pString++;
+ while ( *pTemp && *pTemp != ' ' )
+ pTemp++;
+ }
+ else
+ {
+ while ( *pTemp && *pTemp != ' ' && *pTemp != '\t' && *pTemp != '\r' && *pTemp != '\n' && *pTemp != ',' && *pTemp != '}' &&
+ *pTemp != VER_PARSE_SYM_OPEN && *pTemp != VER_PARSE_SYM_CLOSE &&
+ *pTemp != VER_PARSE_SYM_NEGBEF1 && *pTemp != VER_PARSE_SYM_NEGBEF2 &&
+ *pTemp != VER_PARSE_SYM_AND && *pTemp != VER_PARSE_SYM_OR && *pTemp != VER_PARSE_SYM_XOR &&
+ *pTemp != VER_PARSE_SYM_MUX1 && *pTemp != VER_PARSE_SYM_MUX2 )
+ pTemp++;
+ }
+ // look for this string in the array
+ nLength = pTemp - pString;
+ for ( i = 0; i < Vec_PtrSize(vNames)/2; i++ )
+ {
+ nLength2 = (int)Vec_PtrEntry( vNames, 2*i + 0 );
+ if ( nLength2 != nLength )
+ continue;
+ pTemp2 = Vec_PtrEntry( vNames, 2*i + 1 );
+ if ( strncmp( pString, pTemp2, nLength ) )
+ continue;
+ return i;
+ }
+ // could not find - add and return the number
+ Vec_PtrPush( vNames, (void *)nLength );
+ Vec_PtrPush( vNames, pString );
+ return i;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Returns the AIG representation of the reduction formula.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void * Ver_FormulaReduction( char * pFormula, void * pMan, Vec_Ptr_t * vNames, char * pErrorMessage )
+{
+ Hop_Obj_t * pRes;
+ int v, fCompl;
+ char Symbol;
+
+ // get the operation
+ Symbol = *pFormula++;
+ fCompl = ( Symbol == '~' );
+ if ( fCompl )
+ Symbol = *pFormula++;
+ // check the operation
+ if ( Symbol != '&' && Symbol != '|' && Symbol != '^' )
+ {
+ sprintf( pErrorMessage, "Ver_FormulaReduction(): Unknown operation (%c)\n", Symbol );
+ return NULL;
+ }
+ // skip the brace
+ while ( *pFormula++ != '{' );
+ // parse the names
+ Vec_PtrClear( vNames );
+ while ( *pFormula != '}' )
+ {
+ v = Ver_FormulaParserFindVar( pFormula, vNames );
+ pFormula += (int)Vec_PtrEntry( vNames, 2*v );
+ while ( *pFormula == ' ' || *pFormula == ',' )
+ pFormula++;
+ }
+ // compute the function
+ if ( Symbol == '&' )
+ pRes = Hop_CreateAnd( pMan, Vec_PtrSize(vNames)/2 );
+ else if ( Symbol == '|' )
+ pRes = Hop_CreateOr( pMan, Vec_PtrSize(vNames)/2 );
+ else if ( Symbol == '^' )
+ pRes = Hop_CreateExor( pMan, Vec_PtrSize(vNames)/2 );
+ return Hop_NotCond( pRes, fCompl );
+}
+
+////////////////////////////////////////////////////////////////////////
+/// END OF FILE ///
+////////////////////////////////////////////////////////////////////////
+
+
diff --git a/src/base/ver/verParse.c b/src/base/ver/verParse.c
new file mode 100644
index 00000000..9462fc8b
--- /dev/null
+++ b/src/base/ver/verParse.c
@@ -0,0 +1,117 @@
+/**CFile****************************************************************
+
+ FileName [verParse.c]
+
+ SystemName [ABC: Logic synthesis and verification system.]
+
+ PackageName [Verilog parser.]
+
+ Synopsis [Performs some Verilog parsing tasks.]
+
+ Author [Alan Mishchenko]
+
+ Affiliation [UC Berkeley]
+
+ Date [Ver. 1.0. Started - August 19, 2006.]
+
+ Revision [$Id: verParse.c,v 1.00 2006/08/19 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "ver.h"
+
+////////////////////////////////////////////////////////////////////////
+/// DECLARATIONS ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+/// FUNCTION DEFINITIONS ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+ Synopsis [Skips the comments of they are present.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Ver_ParseSkipComments( Ver_Man_t * pMan )
+{
+ Ver_Stream_t * p = pMan->pReader;
+ char Symbol;
+ // skip spaces
+ Ver_StreamSkipChars( p, " \t\n\r" );
+ if ( !Ver_StreamIsOkey(pMan->pReader) )
+ return 1;
+ // read the first symbol
+ Symbol = Ver_StreamScanChar( p );
+ if ( Symbol != '/' )
+ return 1;
+ Ver_StreamPopChar( p );
+ // read the second symbol
+ Symbol = Ver_StreamScanChar( p );
+ if ( Symbol == '/' )
+ { // skip till the end of line
+ Ver_StreamSkipToChars( p, "\n" );
+ return Ver_ParseSkipComments( pMan );
+ }
+ if ( Symbol == '*' )
+ { // skip till the next occurance of */
+ Ver_StreamPopChar( p );
+ do {
+ Ver_StreamSkipToChars( p, "*" );
+ Ver_StreamPopChar( p );
+ } while ( Ver_StreamScanChar( p ) != '/' );
+ Ver_StreamPopChar( p );
+ return Ver_ParseSkipComments( pMan );
+ }
+ sprintf( pMan->sError, "Cannot parse after symbol \"/\"." );
+ Ver_ParsePrintErrorMessage( pMan );
+ return 0;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Parses a Verilog name that can be being with a slash.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+char * Ver_ParseGetName( Ver_Man_t * pMan )
+{
+ Ver_Stream_t * p = pMan->pReader;
+ char Symbol;
+ char * pWord;
+ pMan->fNameLast = 0;
+ if ( !Ver_StreamIsOkey(p) )
+ return NULL;
+ if ( !Ver_ParseSkipComments( pMan ) )
+ return NULL;
+ Symbol = Ver_StreamScanChar( p );
+ if ( Symbol == '\\' )
+ {
+ pMan->fNameLast = 1;
+ Ver_StreamPopChar( p );
+ pWord = Ver_StreamGetWord( p, " \r\n" );
+ }
+ else
+ pWord = Ver_StreamGetWord( p, " \t\n\r(),;" );
+ if ( !Ver_ParseSkipComments( pMan ) )
+ return NULL;
+ return pWord;
+}
+
+
+////////////////////////////////////////////////////////////////////////
+/// END OF FILE ///
+////////////////////////////////////////////////////////////////////////
+
+
diff --git a/src/base/ver/verStream.c b/src/base/ver/verStream.c
new file mode 100644
index 00000000..9b56bb3f
--- /dev/null
+++ b/src/base/ver/verStream.c
@@ -0,0 +1,443 @@
+/**CFile****************************************************************
+
+ FileName [verStream.c]
+
+ SystemName [ABC: Logic synthesis and verification system.]
+
+ PackageName [Verilog parser.]
+
+ Synopsis [Input file stream, which knows nothing about Verilog.]
+
+ Author [Alan Mishchenko]
+
+ Affiliation [UC Berkeley]
+
+ Date [Ver. 1.0. Started - August 19, 2006.]
+
+ Revision [$Id: verStream.c,v 1.00 2006/08/19 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "ver.h"
+
+////////////////////////////////////////////////////////////////////////
+/// DECLARATIONS ///
+////////////////////////////////////////////////////////////////////////
+
+#define VER_BUFFER_SIZE 1048576 // 1M - size of the data chunk stored in memory
+#define VER_OFFSET_SIZE 65536 // 64K - load new data when less than this is left
+#define VER_WORD_SIZE 65536 // 64K - the largest token that can be returned
+
+#define VER_MINIMUM(a,b) (((a) < (b))? (a) : (b))
+
+struct Ver_Stream_t_
+{
+ // the input file
+ char * pFileName; // the input file name
+ FILE * pFile; // the input file pointer
+ int nFileSize; // the total number of bytes in the file
+ int nFileRead; // the number of bytes currently read from file
+ int nLineCounter; // the counter of lines processed
+ // temporary storage for data
+ char * pBuffer; // the buffer
+ int nBufferSize; // the size of the buffer
+ char * pBufferCur; // the current reading position
+ char * pBufferEnd; // the first position not used by currently loaded data
+ char * pBufferStop; // the position where loading new data will be done
+ // tokens given to the user
+ char pChars[VER_WORD_SIZE+5]; // temporary storage for a word (plus end-of-string and two parantheses)
+ int nChars; // the total number of characters in the word
+ // status of the parser
+ int fStop; // this flag goes high when the end of file is reached
+};
+
+static void Ver_StreamReload( Ver_Stream_t * p );
+
+////////////////////////////////////////////////////////////////////////
+/// FUNCTION DEFINITIONS ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+ Synopsis [Starts the file reader for the given file.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Ver_Stream_t * Ver_StreamAlloc( char * pFileName )
+{
+ Ver_Stream_t * p;
+ FILE * pFile;
+ int nCharsToRead;
+ // check if the file can be opened
+ pFile = fopen( pFileName, "rb" );
+ if ( pFile == NULL )
+ {
+ printf( "Ver_StreamAlloc(): Cannot open input file \"%s\".\n", pFileName );
+ return NULL;
+ }
+ // start the file reader
+ p = ALLOC( Ver_Stream_t, 1 );
+ memset( p, 0, sizeof(Ver_Stream_t) );
+ p->pFileName = pFileName;
+ p->pFile = pFile;
+ // get the file size, in bytes
+ fseek( pFile, 0, SEEK_END );
+ p->nFileSize = ftell( pFile );
+ rewind( pFile );
+ // allocate the buffer
+ p->pBuffer = ALLOC( char, VER_BUFFER_SIZE+1 );
+ p->nBufferSize = VER_BUFFER_SIZE;
+ p->pBufferCur = p->pBuffer;
+ // determine how many chars to read
+ nCharsToRead = VER_MINIMUM(p->nFileSize, VER_BUFFER_SIZE);
+ // load the first part into the buffer
+ fread( p->pBuffer, nCharsToRead, 1, p->pFile );
+ p->nFileRead = nCharsToRead;
+ // set the ponters to the end and the stopping point
+ p->pBufferEnd = p->pBuffer + nCharsToRead;
+ p->pBufferStop = (p->nFileRead == p->nFileSize)? p->pBufferEnd : p->pBuffer + VER_BUFFER_SIZE - VER_OFFSET_SIZE;
+ // start the arrays
+ p->nLineCounter = 1; // 1-based line counting
+ return p;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Loads new data into the file reader.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Ver_StreamReload( Ver_Stream_t * p )
+{
+ int nCharsUsed, nCharsToRead;
+ assert( !p->fStop );
+ assert( p->pBufferCur > p->pBufferStop );
+ assert( p->pBufferCur < p->pBufferEnd );
+ // figure out how many chars are still not processed
+ nCharsUsed = p->pBufferEnd - p->pBufferCur;
+ // move the remaining data to the beginning of the buffer
+ memmove( p->pBuffer, p->pBufferCur, nCharsUsed );
+ p->pBufferCur = p->pBuffer;
+ // determine how many chars we will read
+ nCharsToRead = VER_MINIMUM( p->nBufferSize - nCharsUsed, p->nFileSize - p->nFileRead );
+ // read the chars
+ fread( p->pBuffer + nCharsUsed, nCharsToRead, 1, p->pFile );
+ p->nFileRead += nCharsToRead;
+ // set the ponters to the end and the stopping point
+ p->pBufferEnd = p->pBuffer + nCharsUsed + nCharsToRead;
+ p->pBufferStop = (p->nFileRead == p->nFileSize)? p->pBufferEnd : p->pBuffer + VER_BUFFER_SIZE - VER_OFFSET_SIZE;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Stops the file reader.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Ver_StreamFree( Ver_Stream_t * p )
+{
+ if ( p->pFile )
+ fclose( p->pFile );
+ FREE( p->pBuffer );
+ free( p );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Returns the file size.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+char * Ver_StreamGetFileName( Ver_Stream_t * p )
+{
+ return p->pFileName;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Returns the file size.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Ver_StreamGetFileSize( Ver_Stream_t * p )
+{
+ return p->nFileSize;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Returns the current reading position.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Ver_StreamGetCurPosition( Ver_Stream_t * p )
+{
+ return p->nFileRead - (p->pBufferEnd - p->pBufferCur);
+}
+
+/**Function*************************************************************
+
+ Synopsis [Returns the line number for the given token.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Ver_StreamGetLineNumber( Ver_Stream_t * p )
+{
+ return p->nLineCounter;
+}
+
+
+
+/**Function*************************************************************
+
+ Synopsis [Returns current symbol.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Ver_StreamIsOkey( Ver_Stream_t * p )
+{
+ return !p->fStop;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Returns current symbol.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+char Ver_StreamScanChar( Ver_Stream_t * p )
+{
+ assert( !p->fStop );
+ return *p->pBufferCur;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Returns current symbol and moves to the next.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+char Ver_StreamPopChar( Ver_Stream_t * p )
+{
+ assert( !p->fStop );
+ // check if the new data should to be loaded
+ if ( p->pBufferCur > p->pBufferStop )
+ Ver_StreamReload( p );
+ // check if there are symbols left
+ if ( p->pBufferCur == p->pBufferEnd ) // end of file
+ {
+ p->fStop = 1;
+ return -1;
+ }
+ // count the lines
+ if ( *p->pBufferCur == '\n' )
+ p->nLineCounter++;
+ return *p->pBufferCur++;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Skips the current symbol and all symbols from the list.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Ver_StreamSkipChars( Ver_Stream_t * p, char * pCharsToSkip )
+{
+ char * pChar, * pTemp;
+ assert( !p->fStop );
+ assert( pCharsToSkip != NULL );
+ // check if the new data should to be loaded
+ if ( p->pBufferCur > p->pBufferStop )
+ Ver_StreamReload( p );
+ // skip the symbols
+ for ( pChar = p->pBufferCur; pChar < p->pBufferEnd; pChar++ )
+ {
+ // skip symbols as long as they are in the list
+ for ( pTemp = pCharsToSkip; *pTemp; pTemp++ )
+ if ( *pChar == *pTemp )
+ break;
+ if ( *pTemp == 0 ) // pChar is not found in the list
+ {
+ p->pBufferCur = pChar;
+ return;
+ }
+ // count the lines
+ if ( *pChar == '\n' )
+ p->nLineCounter++;
+ }
+ // the file is finished or the last part continued
+ // through VER_OFFSET_SIZE chars till the end of the buffer
+ if ( p->pBufferStop == p->pBufferEnd ) // end of file
+ {
+ p->fStop = 1;
+ return;
+ }
+ printf( "Ver_StreamSkipSymbol() failed to parse the file \"%s\".\n", p->pFileName );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Skips all symbols until encountering one from the list.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Ver_StreamSkipToChars( Ver_Stream_t * p, char * pCharsToStop )
+{
+ char * pChar, * pTemp;
+ assert( !p->fStop );
+ assert( pCharsToStop != NULL );
+ // check if the new data should to be loaded
+ if ( p->pBufferCur > p->pBufferStop )
+ Ver_StreamReload( p );
+ // skip the symbols
+ for ( pChar = p->pBufferCur; pChar < p->pBufferEnd; pChar++ )
+ {
+ // skip symbols as long as they are NOT in the list
+ for ( pTemp = pCharsToStop; *pTemp; pTemp++ )
+ if ( *pChar == *pTemp )
+ break;
+ if ( *pTemp == 0 ) // pChar is not found in the list
+ {
+ // count the lines
+ if ( *pChar == '\n' )
+ p->nLineCounter++;
+ continue;
+ }
+ // the symbol is found - move position and return
+ p->pBufferCur = pChar;
+ return;
+ }
+ // the file is finished or the last part continued
+ // through VER_OFFSET_SIZE chars till the end of the buffer
+ if ( p->pBufferStop == p->pBufferEnd ) // end of file
+ {
+ p->fStop = 1;
+ return;
+ }
+ printf( "Ver_StreamSkipToSymbol() failed to parse the file \"%s\".\n", p->pFileName );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Returns current word delimited by the set of symbols.]
+
+ Description [Modifies the stream by inserting 0 at the first encounter
+ of one of the symbols in the list.]
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+char * Ver_StreamGetWord( Ver_Stream_t * p, char * pCharsToStop )
+{
+ char * pChar, * pTemp;
+ if ( p->fStop )
+ return NULL;
+ assert( pCharsToStop != NULL );
+ // check if the new data should to be loaded
+ if ( p->pBufferCur > p->pBufferStop )
+ Ver_StreamReload( p );
+ // skip the symbols
+ p->nChars = 0;
+ for ( pChar = p->pBufferCur; pChar < p->pBufferEnd; pChar++ )
+ {
+ // skip symbols as long as they are NOT in the list
+ for ( pTemp = pCharsToStop; *pTemp; pTemp++ )
+ if ( *pChar == *pTemp )
+ break;
+ if ( *pTemp == 0 ) // pChar is not found in the list
+ {
+ p->pChars[p->nChars++] = *pChar;
+ if ( p->nChars == VER_WORD_SIZE )
+ {
+ printf( "Ver_StreamGetWord(): The buffer size is exceeded.\n" );
+ return NULL;
+ }
+ // count the lines
+ if ( *pChar == '\n' )
+ p->nLineCounter++;
+ continue;
+ }
+ // the symbol is found - move the position, set the word end, return the word
+ p->pBufferCur = pChar;
+ p->pChars[p->nChars] = 0;
+ return p->pChars;
+ }
+ // the file is finished or the last part continued
+ // through VER_OFFSET_SIZE chars till the end of the buffer
+ if ( p->pBufferStop == p->pBufferEnd ) // end of file
+ {
+ p->fStop = 1;
+ p->pChars[p->nChars] = 0;
+ return p->pChars;
+ }
+ printf( "Ver_StreamGetWord() failed to parse the file \"%s\".\n", p->pFileName );
+ return NULL;
+}
+
+////////////////////////////////////////////////////////////////////////
+/// END OF FILE ///
+////////////////////////////////////////////////////////////////////////
+
+
diff --git a/src/base/ver/verWords.c b/src/base/ver/verWords.c
new file mode 100644
index 00000000..f9d27010
--- /dev/null
+++ b/src/base/ver/verWords.c
@@ -0,0 +1,48 @@
+/**CFile****************************************************************
+
+ FileName [verWords.c]
+
+ SystemName [ABC: Logic synthesis and verification system.]
+
+ PackageName [Verilog parser.]
+
+ Synopsis [Handles keywords that are currently supported.]
+
+ Author [Alan Mishchenko]
+
+ Affiliation [UC Berkeley]
+
+ Date [Ver. 1.0. Started - August 19, 2006.]
+
+ Revision [$Id: verWords.c,v 1.00 2006/08/19 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "ver.h"
+
+////////////////////////////////////////////////////////////////////////
+/// DECLARATIONS ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+/// FUNCTION DEFINITIONS ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+
+
+////////////////////////////////////////////////////////////////////////
+/// END OF FILE ///
+////////////////////////////////////////////////////////////////////////
+
+
diff --git a/src/base/ver/ver_.c b/src/base/ver/ver_.c
new file mode 100644
index 00000000..76599dac
--- /dev/null
+++ b/src/base/ver/ver_.c
@@ -0,0 +1,48 @@
+/**CFile****************************************************************
+
+ FileName [ver_.c]
+
+ SystemName [ABC: Logic synthesis and verification system.]
+
+ PackageName [Verilog parser.]
+
+ Synopsis [Parses several flavors of structural Verilog.]
+
+ Author [Alan Mishchenko]
+
+ Affiliation [UC Berkeley]
+
+ Date [Ver. 1.0. Started - August 19, 2006.]
+
+ Revision [$Id: ver_.c,v 1.00 2006/08/19 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "ver.h"
+
+////////////////////////////////////////////////////////////////////////
+/// DECLARATIONS ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+/// FUNCTION DEFINITIONS ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+
+
+////////////////////////////////////////////////////////////////////////
+/// END OF FILE ///
+////////////////////////////////////////////////////////////////////////
+
+
diff --git a/src/bdd/cas/cas.h b/src/bdd/cas/cas.h
new file mode 100644
index 00000000..fcc9f890
--- /dev/null
+++ b/src/bdd/cas/cas.h
@@ -0,0 +1,62 @@
+/**CFile****************************************************************
+
+ FileName [cas.h]
+
+ SystemName [ABC: Logic synthesis and verification system.]
+
+ PackageName [CASCADE: Decomposition of shared BDDs into a LUT cascade.]
+
+ Synopsis [External declarations.]
+
+ Author [Alan Mishchenko]
+
+ Affiliation [UC Berkeley]
+
+ Date [Ver. 1.0. Started - June 20, 2005.]
+
+ Revision [$Id: cas.h,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#ifndef __CAS_H__
+#define __CAS_H__
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+////////////////////////////////////////////////////////////////////////
+/// INCLUDES ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+/// PARAMETERS ///
+////////////////////////////////////////////////////////////////////////
+
+#define MAXINPUTS 1024
+#define MAXOUTPUTS 1024
+
+////////////////////////////////////////////////////////////////////////
+/// BASIC TYPES ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+/// MACRO DEFINITIONS ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+/// FUNCTION DECLARATIONS ///
+////////////////////////////////////////////////////////////////////////
+
+/*=== zzz.c ==========================================================*/
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
+
+////////////////////////////////////////////////////////////////////////
+/// END OF FILE ///
+////////////////////////////////////////////////////////////////////////
+
diff --git a/src/bdd/cas/casCore.c b/src/bdd/cas/casCore.c
new file mode 100644
index 00000000..579235b1
--- /dev/null
+++ b/src/bdd/cas/casCore.c
@@ -0,0 +1,1263 @@
+/**CFile****************************************************************
+
+ FileName [casCore.c]
+
+ SystemName [ABC: Logic synthesis and verification system.]
+
+ PackageName [CASCADE: Decomposition of shared BDDs into a LUT cascade.]
+
+ Synopsis [Entrance into the implementation.]
+
+ Author [Alan Mishchenko]
+
+ Affiliation [UC Berkeley]
+
+ Date [Ver. 1.0. Started - Spring 2002.]
+
+ Revision [$Id: casCore.c,v 1.0 2002/01/01 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <time.h>
+
+#include "extra.h"
+#include "cas.h"
+
+////////////////////////////////////////////////////////////////////////
+/// static functions ///
+////////////////////////////////////////////////////////////////////////
+
+DdNode * GetSingleOutputFunction( DdManager * dd, DdNode ** pbOuts, int nOuts, DdNode ** pbVarsEnc, int nVarsEnc, int fVerbose );
+DdNode * GetSingleOutputFunctionRemapped( DdManager * dd, DdNode ** pOutputs, int nOuts, DdNode ** pbVarsEnc, int nVarsEnc );
+DdNode * GetSingleOutputFunctionRemappedNewDD( DdManager * dd, DdNode ** pOutputs, int nOuts, DdManager ** DdNew );
+
+extern int CreateDecomposedNetwork( DdManager * dd, DdNode * aFunc, char ** pNames, int nNames, char * FileName, int nLutSize, int fCheck, int fVerbose );
+
+void WriteSingleOutputFunctionBlif( DdManager * dd, DdNode * aFunc, char ** pNames, int nNames, char * FileName );
+
+DdNode * Cudd_bddTransferPermute( DdManager * ddSource, DdManager * ddDestination, DdNode * f, int * Permute );
+
+////////////////////////////////////////////////////////////////////////
+/// static varibles ///
+////////////////////////////////////////////////////////////////////////
+
+//static FILE * pTable = NULL;
+//static long s_RemappingTime = 0;
+
+////////////////////////////////////////////////////////////////////////
+/// debugging macros ///
+////////////////////////////////////////////////////////////////////////
+
+#define PRD(p) printf( "\nDECOMPOSITION TREE:\n\n" ); PrintDecEntry( (p), 0 )
+#define PRB(f) printf( #f " = " ); Cudd_bddPrint(dd,f); printf( "\n" )
+#define PRK(f,n) Cudd_PrintKMap(stdout,dd,(f),Cudd_Not(f),(n),NULL,0); printf( "K-map for function" #f "\n\n" )
+#define PRK2(f,g,n) Cudd_PrintKMap(stdout,dd,(f),(g),(n),NULL,0); printf( "K-map for function <" #f ", " #g ">\n\n" )
+
+
+////////////////////////////////////////////////////////////////////////
+/// EXTERNAL FUNCTIONS ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Abc_CascadeExperiment( char * pFileGeneric, DdManager * dd, DdNode ** pOutputs, int nInputs, int nOutputs, int nLutSize, int fCheck, int fVerbose )
+{
+ int i;
+ int nVars = nInputs;
+ int nOuts = nOutputs;
+ long clk1;
+
+ int nVarsEnc; // the number of additional variables to encode outputs
+ DdNode * pbVarsEnc[MAXOUTPUTS]; // the BDDs of the encoding vars
+
+ int nNames; // the total number of all inputs
+ char * pNames[MAXINPUTS]; // the temporary storage for the input (and output encoding) names
+
+ DdNode * aFunc; // the encoded 0-1 BDD containing all the outputs
+
+ char FileNameIni[100];
+ char FileNameFin[100];
+ char Buffer[100];
+
+
+//pTable = fopen( "stats.txt", "a+" );
+//fprintf( pTable, "%s ", pFileGeneric );
+//fprintf( pTable, "%d ", nVars );
+//fprintf( pTable, "%d ", nOuts );
+
+
+ // assign the file names
+ strcpy( FileNameIni, pFileGeneric );
+ strcat( FileNameIni, "_ENC.blif" );
+
+ strcpy( FileNameFin, pFileGeneric );
+ strcat( FileNameFin, "_LUT.blif" );
+
+
+ // create the variables to encode the outputs
+ nVarsEnc = Extra_Base2Log( nOuts );
+ for ( i = 0; i < nVarsEnc; i++ )
+ pbVarsEnc[i] = Cudd_bddNewVarAtLevel( dd, i );
+
+
+ // store the input names
+ nNames = nVars + nVarsEnc;
+ for ( i = 0; i < nVars; i++ )
+ {
+// pNames[i] = Extra_UtilStrsav( pFunc->pInputNames[i] );
+ sprintf( Buffer, "pi%03d", i );
+ pNames[i] = Extra_UtilStrsav( Buffer );
+ }
+ // set the encoding variable name
+ for ( ; i < nNames; i++ )
+ {
+ sprintf( Buffer, "OutEnc_%02d", i-nVars );
+ pNames[i] = Extra_UtilStrsav( Buffer );
+ }
+
+
+ // print the variable order
+// printf( "\n" );
+// printf( "Variable order is: " );
+// for ( i = 0; i < dd->size; i++ )
+// printf( " %d", dd->invperm[i] );
+// printf( "\n" );
+
+ // derive the single-output function
+ clk1 = clock();
+ aFunc = GetSingleOutputFunction( dd, pOutputs, nOuts, pbVarsEnc, nVarsEnc, fVerbose ); Cudd_Ref( aFunc );
+// aFunc = GetSingleOutputFunctionRemapped( dd, pOutputs, nOuts, pbVarsEnc, nVarsEnc ); Cudd_Ref( aFunc );
+// if ( fVerbose )
+// printf( "Single-output function computation time = %.2f sec\n", (float)(clock() - clk1)/(float)(CLOCKS_PER_SEC) );
+
+//fprintf( pTable, "%d ", Cudd_SharingSize( pOutputs, nOutputs ) );
+//fprintf( pTable, "%d ", Extra_ProfileWidthSharingMax(dd, pOutputs, nOutputs) );
+
+ // dispose of the multiple-output function
+// Extra_Dissolve( pFunc );
+
+ // reorder the single output function
+// if ( fVerbose )
+// printf( "Reordering variables...\n");
+ clk1 = clock();
+// if ( fVerbose )
+// printf( "Node count before = %6d\n", Cudd_DagSize( aFunc ) );
+// Cudd_ReduceHeap(dd, CUDD_REORDER_SIFT,1);
+ Cudd_ReduceHeap(dd, CUDD_REORDER_SYMM_SIFT,1);
+ Cudd_ReduceHeap(dd, CUDD_REORDER_SYMM_SIFT,1);
+// Cudd_ReduceHeap(dd, CUDD_REORDER_SYMM_SIFT,1);
+// Cudd_ReduceHeap(dd, CUDD_REORDER_SYMM_SIFT,1);
+// Cudd_ReduceHeap(dd, CUDD_REORDER_SYMM_SIFT,1);
+// Cudd_ReduceHeap(dd, CUDD_REORDER_SYMM_SIFT,1);
+ if ( fVerbose )
+ printf( "MTBDD reordered = %6d nodes\n", Cudd_DagSize( aFunc ) );
+ if ( fVerbose )
+ printf( "Variable reordering time = %.2f sec\n", (float)(clock() - clk1)/(float)(CLOCKS_PER_SEC) );
+// printf( "\n" );
+// printf( "Variable order is: " );
+// for ( i = 0; i < dd->size; i++ )
+// printf( " %d", dd->invperm[i] );
+// printf( "\n" );
+//fprintf( pTable, "%d ", Cudd_DagSize( aFunc ) );
+//fprintf( pTable, "%d ", Extra_ProfileWidthMax(dd, aFunc) );
+
+ // write the single-output function into BLIF for verification
+ clk1 = clock();
+ if ( fCheck )
+ WriteSingleOutputFunctionBlif( dd, aFunc, pNames, nNames, FileNameIni );
+// if ( fVerbose )
+// printf( "Single-output function writing time = %.2f sec\n", (float)(clock() - clk1)/(float)(CLOCKS_PER_SEC) );
+
+/*
+ ///////////////////////////////////////////////////////////////////
+ // verification of single output function
+ clk1 = clock();
+ {
+ BFunc g_Func;
+ DdNode * aRes;
+
+ g_Func.dd = dd;
+ g_Func.FileInput = Extra_UtilStrsav(FileNameIni);
+
+ if ( Extra_ReadFile( &g_Func ) == 0 )
+ {
+ printf( "\nSomething did not work out while reading the input file for verification\n");
+ Extra_Dissolve( &g_Func );
+ return;
+ }
+
+ aRes = Cudd_BddToAdd( dd, g_Func.pOutputs[0] ); Cudd_Ref( aRes );
+
+ if ( aRes != aFunc )
+ printf( "\nVerification FAILED!\n");
+ else
+ printf( "\nVerification okay!\n");
+
+ Cudd_RecursiveDeref( dd, aRes );
+
+ // delocate
+ Extra_Dissolve( &g_Func );
+ }
+ printf( "Preliminary verification time = %.2f sec\n", (float)(clock() - clk1)/(float)(CLOCKS_PER_SEC) );
+ ///////////////////////////////////////////////////////////////////
+*/
+
+ if ( !CreateDecomposedNetwork( dd, aFunc, pNames, nNames, FileNameFin, nLutSize, fCheck, fVerbose ) )
+ return 0;
+
+/*
+ ///////////////////////////////////////////////////////////////////
+ // verification of the decomposed LUT network
+ clk1 = clock();
+ {
+ BFunc g_Func;
+ DdNode * aRes;
+
+ g_Func.dd = dd;
+ g_Func.FileInput = Extra_UtilStrsav(FileNameFin);
+
+ if ( Extra_ReadFile( &g_Func ) == 0 )
+ {
+ printf( "\nSomething did not work out while reading the input file for verification\n");
+ Extra_Dissolve( &g_Func );
+ return;
+ }
+
+ aRes = Cudd_BddToAdd( dd, g_Func.pOutputs[0] ); Cudd_Ref( aRes );
+
+ if ( aRes != aFunc )
+ printf( "\nFinal verification FAILED!\n");
+ else
+ printf( "\nFinal verification okay!\n");
+
+ Cudd_RecursiveDeref( dd, aRes );
+
+ // delocate
+ Extra_Dissolve( &g_Func );
+ }
+ printf( "Final verification time = %.2f sec\n", (float)(clock() - clk1)/(float)(CLOCKS_PER_SEC) );
+ ///////////////////////////////////////////////////////////////////
+*/
+
+ // verify the results
+ if ( fCheck )
+ {
+ extern int Cmd_CommandExecute( void * pAbc, char * sCommand );
+ extern void * Abc_FrameGetGlobalFrame();
+ char Command[200];
+ sprintf( Command, "cec %s %s", FileNameIni, FileNameFin );
+ Cmd_CommandExecute( Abc_FrameGetGlobalFrame(), Command );
+ }
+
+ Cudd_RecursiveDeref( dd, aFunc );
+
+ // release the names
+ for ( i = 0; i < nNames; i++ )
+ free( pNames[i] );
+
+
+//fprintf( pTable, "\n" );
+//fclose( pTable );
+
+ return 1;
+}
+
+#if 0
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Experiment2( BFunc * pFunc )
+{
+ int i, x, RetValue;
+ int nVars = pFunc->nInputs;
+ int nOuts = pFunc->nOutputs;
+ DdManager * dd = pFunc->dd;
+ long clk1;
+
+// int nVarsEnc; // the number of additional variables to encode outputs
+// DdNode * pbVarsEnc[MAXOUTPUTS]; // the BDDs of the encoding vars
+
+ int nNames; // the total number of all inputs
+ char * pNames[MAXINPUTS]; // the temporary storage for the input (and output encoding) names
+
+ DdNode * aFunc; // the encoded 0-1 BDD containing all the outputs
+
+ char FileNameIni[100];
+ char FileNameFin[100];
+ char Buffer[100];
+
+ DdManager * DdNew;
+
+//pTable = fopen( "stats.txt", "a+" );
+//fprintf( pTable, "%s ", pFunc->FileGeneric );
+//fprintf( pTable, "%d ", nVars );
+//fprintf( pTable, "%d ", nOuts );
+
+
+ // assign the file names
+ strcpy( FileNameIni, pFunc->FileGeneric );
+ strcat( FileNameIni, "_ENC.blif" );
+
+ strcpy( FileNameFin, pFunc->FileGeneric );
+ strcat( FileNameFin, "_LUT.blif" );
+
+ // derive the single-output function IN THE NEW MANAGER
+ clk1 = clock();
+// aFunc = GetSingleOutputFunction( dd, pFunc->pOutputs, nOuts, pbVarsEnc, nVarsEnc ); Cudd_Ref( aFunc );
+ aFunc = GetSingleOutputFunctionRemappedNewDD( dd, pFunc->pOutputs, nOuts, &DdNew ); Cudd_Ref( aFunc );
+ printf( "Single-output function derivation time = %.2f sec\n", (float)(clock() - clk1)/(float)(CLOCKS_PER_SEC) );
+// s_RemappingTime = clock() - clk1;
+
+ // dispose of the multiple-output function
+ Extra_Dissolve( pFunc );
+
+ // reorder the single output function
+ printf( "\nReordering variables in the new manager...\n");
+ clk1 = clock();
+ printf( "Node count before = %d\n", Cudd_DagSize( aFunc ) );
+// Cudd_ReduceHeap(DdNew, CUDD_REORDER_SIFT,1);
+ Cudd_ReduceHeap(DdNew, CUDD_REORDER_SYMM_SIFT,1);
+// Cudd_ReduceHeap(DdNew, CUDD_REORDER_SYMM_SIFT,1);
+ printf( "Node count after = %d\n", Cudd_DagSize( aFunc ) );
+ printf( "Variable reordering time = %.2f sec\n", (float)(clock() - clk1)/(float)(CLOCKS_PER_SEC) );
+ printf( "\n" );
+
+//fprintf( pTable, "%d ", Cudd_DagSize( aFunc ) );
+//fprintf( pTable, "%d ", Extra_ProfileWidthMax(DdNew, aFunc) );
+
+
+ // create the names to be used with the new manager
+ nNames = DdNew->size;
+ for ( x = 0; x < nNames; x++ )
+ {
+ sprintf( Buffer, "v%02d", x );
+ pNames[x] = Extra_UtilStrsav( Buffer );
+ }
+
+
+
+ // write the single-output function into BLIF for verification
+ clk1 = clock();
+ WriteSingleOutputFunctionBlif( DdNew, aFunc, pNames, nNames, FileNameIni );
+ printf( "Single-output function writing time = %.2f sec\n", (float)(clock() - clk1)/(float)(CLOCKS_PER_SEC) );
+
+
+ ///////////////////////////////////////////////////////////////////
+ // verification of single output function
+ clk1 = clock();
+ {
+ BFunc g_Func;
+ DdNode * aRes;
+
+ g_Func.dd = DdNew;
+ g_Func.FileInput = Extra_UtilStrsav(FileNameIni);
+
+ if ( Extra_ReadFile( &g_Func ) == 0 )
+ {
+ printf( "\nSomething did not work out while reading the input file for verification\n");
+ Extra_Dissolve( &g_Func );
+ return;
+ }
+
+ aRes = Cudd_BddToAdd( DdNew, g_Func.pOutputs[0] ); Cudd_Ref( aRes );
+
+ if ( aRes != aFunc )
+ printf( "\nVerification FAILED!\n");
+ else
+ printf( "\nVerification okay!\n");
+
+ Cudd_RecursiveDeref( DdNew, aRes );
+
+ // delocate
+ Extra_Dissolve( &g_Func );
+ }
+ printf( "Preliminary verification time = %.2f sec\n", (float)(clock() - clk1)/(float)(CLOCKS_PER_SEC) );
+ ///////////////////////////////////////////////////////////////////
+
+
+ CreateDecomposedNetwork( DdNew, aFunc, pNames, nNames, FileNameFin, nLutSize, 0 );
+
+/*
+ ///////////////////////////////////////////////////////////////////
+ // verification of the decomposed LUT network
+ clk1 = clock();
+ {
+ BFunc g_Func;
+ DdNode * aRes;
+
+ g_Func.dd = DdNew;
+ g_Func.FileInput = Extra_UtilStrsav(FileNameFin);
+
+ if ( Extra_ReadFile( &g_Func ) == 0 )
+ {
+ printf( "\nSomething did not work out while reading the input file for verification\n");
+ Extra_Dissolve( &g_Func );
+ return;
+ }
+
+ aRes = Cudd_BddToAdd( DdNew, g_Func.pOutputs[0] ); Cudd_Ref( aRes );
+
+ if ( aRes != aFunc )
+ printf( "\nFinal verification FAILED!\n");
+ else
+ printf( "\nFinal verification okay!\n");
+
+ Cudd_RecursiveDeref( DdNew, aRes );
+
+ // delocate
+ Extra_Dissolve( &g_Func );
+ }
+ printf( "Final verification time = %.2f sec\n", (float)(clock() - clk1)/(float)(CLOCKS_PER_SEC) );
+ ///////////////////////////////////////////////////////////////////
+*/
+
+
+ Cudd_RecursiveDeref( DdNew, aFunc );
+
+ // release the names
+ for ( i = 0; i < nNames; i++ )
+ free( pNames[i] );
+
+
+
+ /////////////////////////////////////////////////////////////////////
+ // check for remaining references in the package
+ RetValue = Cudd_CheckZeroRef( DdNew );
+ printf( "\nThe number of referenced nodes in the new manager = %d\n", RetValue );
+ Cudd_Quit( DdNew );
+
+//fprintf( pTable, "\n" );
+//fclose( pTable );
+
+}
+
+#endif
+
+////////////////////////////////////////////////////////////////////////
+/// SINGLE OUTPUT FUNCTION ///
+////////////////////////////////////////////////////////////////////////
+
+// the bit count for the first 256 integer numbers
+static unsigned char BitCount8[256] = {
+ 0,1,1,2,1,2,2,3,1,2,2,3,2,3,3,4,1,2,2,3,2,3,3,4,2,3,3,4,3,4,4,5,
+ 1,2,2,3,2,3,3,4,2,3,3,4,3,4,4,5,2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6,
+ 1,2,2,3,2,3,3,4,2,3,3,4,3,4,4,5,2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6,
+ 2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6,3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7,
+ 1,2,2,3,2,3,3,4,2,3,3,4,3,4,4,5,2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6,
+ 2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6,3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7,
+ 2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6,3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7,
+ 3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7,4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8
+};
+
+/////////////////////////////////////////////////////////////
+static int s_SuppSize[MAXOUTPUTS];
+int CompareSupports( int *ptrX, int *ptrY )
+{
+ return ( s_SuppSize[*ptrY] - s_SuppSize[*ptrX] );
+}
+/////////////////////////////////////////////////////////////
+
+
+/////////////////////////////////////////////////////////////
+static int s_MintOnes[MAXOUTPUTS];
+int CompareMinterms( int *ptrX, int *ptrY )
+{
+ return ( s_MintOnes[*ptrY] - s_MintOnes[*ptrX] );
+}
+/////////////////////////////////////////////////////////////
+
+int GrayCode ( int BinCode )
+{
+ return BinCode ^ ( BinCode >> 1 );
+}
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+DdNode * GetSingleOutputFunction( DdManager * dd, DdNode ** pbOuts, int nOuts, DdNode ** pbVarsEnc, int nVarsEnc, int fVerbose )
+{
+ int i;
+ DdNode * bResult, * aResult;
+ DdNode * bCube, * bTemp, * bProd;
+
+ int Order[MAXOUTPUTS];
+// int OrderMint[MAXOUTPUTS];
+
+ // sort the output according to their support size
+ for ( i = 0; i < nOuts; i++ )
+ {
+ s_SuppSize[i] = Cudd_SupportSize( dd, pbOuts[i] );
+// s_MintOnes[i] = BitCount8[i];
+ Order[i] = i;
+// OrderMint[i] = i;
+ }
+
+ // order the outputs
+ qsort( (void*)Order, nOuts, sizeof(int), (int(*)(const void*, const void*)) CompareSupports );
+ // order the outputs
+// qsort( (void*)OrderMint, nOuts, sizeof(int), (int(*)(const void*, const void*)) CompareMinterms );
+
+
+ bResult = b0; Cudd_Ref( bResult );
+ for ( i = 0; i < nOuts; i++ )
+ {
+// bCube = Cudd_bddBitsToCube( dd, OrderMint[i], nVarsEnc, pbVarsEnc ); Cudd_Ref( bCube );
+// bProd = Cudd_bddAnd( dd, bCube, pbOuts[Order[nOuts-1-i]] ); Cudd_Ref( bProd );
+ bCube = Extra_bddBitsToCube( dd, i, nVarsEnc, pbVarsEnc, 1 ); Cudd_Ref( bCube );
+ bProd = Cudd_bddAnd( dd, bCube, pbOuts[Order[i]] ); Cudd_Ref( bProd );
+ Cudd_RecursiveDeref( dd, bCube );
+
+ bResult = Cudd_bddOr( dd, bProd, bTemp = bResult ); Cudd_Ref( bResult );
+ Cudd_RecursiveDeref( dd, bTemp );
+ Cudd_RecursiveDeref( dd, bProd );
+ }
+
+ // convert to the ADD
+if ( fVerbose )
+printf( "Single BDD size = %6d nodes\n", Cudd_DagSize(bResult) );
+ aResult = Cudd_BddToAdd( dd, bResult ); Cudd_Ref( aResult );
+ Cudd_RecursiveDeref( dd, bResult );
+if ( fVerbose )
+printf( "MTBDD = %6d nodes\n", Cudd_DagSize(aResult) );
+ Cudd_Deref( aResult );
+ return aResult;
+}
+/*
+DdNode * GetSingleOutputFunction( DdManager * dd, DdNode ** pbOuts, int nOuts, DdNode ** pbVarsEnc, int nVarsEnc )
+{
+ int i;
+ DdNode * bResult, * aResult;
+ DdNode * bCube, * bTemp, * bProd;
+
+ bResult = b0; Cudd_Ref( bResult );
+ for ( i = 0; i < nOuts; i++ )
+ {
+// bCube = Extra_bddBitsToCube( dd, i, nVarsEnc, pbVarsEnc ); Cudd_Ref( bCube );
+ bCube = Extra_bddBitsToCube( dd, nOuts-1-i, nVarsEnc, pbVarsEnc ); Cudd_Ref( bCube );
+ bProd = Cudd_bddAnd( dd, bCube, pbOuts[i] ); Cudd_Ref( bProd );
+ Cudd_RecursiveDeref( dd, bCube );
+
+ bResult = Cudd_bddOr( dd, bProd, bTemp = bResult ); Cudd_Ref( bResult );
+ Cudd_RecursiveDeref( dd, bTemp );
+ Cudd_RecursiveDeref( dd, bProd );
+ }
+
+ // conver to the ADD
+ aResult = Cudd_BddToAdd( dd, bResult ); Cudd_Ref( aResult );
+ Cudd_RecursiveDeref( dd, bResult );
+
+ Cudd_Deref( aResult );
+ return aResult;
+}
+*/
+
+
+////////////////////////////////////////////////////////////////////////
+/// INPUT REMAPPING ///
+////////////////////////////////////////////////////////////////////////
+
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+DdNode * GetSingleOutputFunctionRemapped( DdManager * dd, DdNode ** pOutputs, int nOuts, DdNode ** pbVarsEnc, int nVarsEnc )
+// returns the ADD of the remapped function
+{
+ static int Permute[MAXINPUTS];
+ static DdNode * pRemapped[MAXOUTPUTS];
+
+ DdNode * bSupp, * bTemp;
+ int i, Counter;
+ int nSuppPrev = -1;
+ DdNode * bFunc;
+ DdNode * aFunc;
+
+ Cudd_AutodynDisable(dd);
+
+ // perform the remapping
+ for ( i = 0; i < nOuts; i++ )
+ {
+ // get support
+ bSupp = Cudd_Support( dd, pOutputs[i] ); Cudd_Ref( bSupp );
+
+ // create the variable map
+ Counter = 0;
+ for ( bTemp = bSupp; bTemp != dd->one; bTemp = cuddT(bTemp) )
+ Permute[bTemp->index] = Counter++;
+
+ // transfer the BDD and remap it
+ pRemapped[i] = Cudd_bddPermute( dd, pOutputs[i], Permute ); Cudd_Ref( pRemapped[i] );
+
+ // remove support
+ Cudd_RecursiveDeref( dd, bSupp );
+ }
+
+ // perform the encoding
+ bFunc = Extra_bddEncodingBinary( dd, pRemapped, nOuts, pbVarsEnc, nVarsEnc ); Cudd_Ref( bFunc );
+
+ // convert to ADD
+ aFunc = Cudd_BddToAdd( dd, bFunc ); Cudd_Ref( aFunc );
+ Cudd_RecursiveDeref( dd, bFunc );
+
+ // deref the intermediate results
+ for ( i = 0; i < nOuts; i++ )
+ Cudd_RecursiveDeref( dd, pRemapped[i] );
+
+ Cudd_Deref( aFunc );
+ return aFunc;
+}
+
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+DdNode * GetSingleOutputFunctionRemappedNewDD( DdManager * dd, DdNode ** pOutputs, int nOuts, DdManager ** DdNew )
+// returns the ADD of the remapped function
+{
+ static int Permute[MAXINPUTS];
+ static DdNode * pRemapped[MAXOUTPUTS];
+
+ static DdNode * pbVarsEnc[MAXINPUTS];
+ int nVarsEnc;
+
+ DdManager * ddnew;
+
+ DdNode * bSupp, * bTemp;
+ int i, v, Counter;
+ int nSuppPrev = -1;
+ DdNode * bFunc;
+
+ // these are in the new manager
+ DdNode * bFuncNew;
+ DdNode * aFuncNew;
+
+ int nVarsMax = 0;
+
+ // perform the remapping and write the DDs into the new manager
+ for ( i = 0; i < nOuts; i++ )
+ {
+ // get support
+ bSupp = Cudd_Support( dd, pOutputs[i] ); Cudd_Ref( bSupp );
+
+ // create the variable map
+ // to remap the DD into the upper part of the manager
+ Counter = 0;
+ for ( bTemp = bSupp; bTemp != dd->one; bTemp = cuddT(bTemp) )
+ Permute[bTemp->index] = dd->invperm[Counter++];
+
+ // transfer the BDD and remap it
+ pRemapped[i] = Cudd_bddPermute( dd, pOutputs[i], Permute ); Cudd_Ref( pRemapped[i] );
+
+ // remove support
+ Cudd_RecursiveDeref( dd, bSupp );
+
+
+ // determine the largest support size
+ if ( nVarsMax < Counter )
+ nVarsMax = Counter;
+ }
+
+ // select the encoding variables to follow immediately after the original variables
+ nVarsEnc = Extra_Base2Log(nOuts);
+/*
+ for ( v = 0; v < nVarsEnc; v++ )
+ if ( nVarsMax + v < dd->size )
+ pbVarsEnc[v] = dd->var[ dd->invperm[nVarsMax+v] ];
+ else
+ pbVarsEnc[v] = Cudd_bddNewVar( dd );
+*/
+ // create the new variables on top of the manager
+ for ( v = 0; v < nVarsEnc; v++ )
+ pbVarsEnc[v] = Cudd_bddNewVarAtLevel( dd, v );
+
+//fprintf( pTable, "%d ", Cudd_SharingSize( pRemapped, nOuts ) );
+//fprintf( pTable, "%d ", Extra_ProfileWidthSharingMax(dd, pRemapped, nOuts) );
+
+
+ // perform the encoding
+ bFunc = Extra_bddEncodingBinary( dd, pRemapped, nOuts, pbVarsEnc, nVarsEnc ); Cudd_Ref( bFunc );
+
+
+ // find the cross-manager permutation
+ // the variable from the level v in the old manager
+ // should become a variable number v in the new manager
+ for ( v = 0; v < nVarsMax + nVarsEnc; v++ )
+ Permute[dd->invperm[v]] = v;
+
+
+ ///////////////////////////////////////////////////////////////////////////////
+ // start the new manager
+ ddnew = Cudd_Init( nVarsMax + nVarsEnc, 0, CUDD_UNIQUE_SLOTS, CUDD_CACHE_SLOTS, 0);
+// Cudd_AutodynDisable(ddnew);
+ Cudd_AutodynEnable(dd, CUDD_REORDER_SYMM_SIFT);
+
+ // transfer it to the new manager
+ bFuncNew = Cudd_bddTransferPermute( dd, ddnew, bFunc, Permute ); Cudd_Ref( bFuncNew );
+ ///////////////////////////////////////////////////////////////////////////////
+
+
+ // deref the intermediate results in the old manager
+ Cudd_RecursiveDeref( dd, bFunc );
+ for ( i = 0; i < nOuts; i++ )
+ Cudd_RecursiveDeref( dd, pRemapped[i] );
+
+
+ ///////////////////////////////////////////////////////////////////////////////
+ // convert to ADD in the new manager
+ aFuncNew = Cudd_BddToAdd( ddnew, bFuncNew ); Cudd_Ref( aFuncNew );
+ Cudd_RecursiveDeref( ddnew, bFuncNew );
+
+ // return the manager
+ *DdNew = ddnew;
+ ///////////////////////////////////////////////////////////////////////////////
+
+ Cudd_Deref( aFuncNew );
+ return aFuncNew;
+}
+
+////////////////////////////////////////////////////////////////////////
+/// BLIF WRITING FUNCTIONS ///
+////////////////////////////////////////////////////////////////////////
+
+void WriteDDintoBLIFfile( FILE * pFile, DdNode * Func, char * OutputName, char * Prefix, char ** InputNames );
+
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void WriteSingleOutputFunctionBlif( DdManager * dd, DdNode * aFunc, char ** pNames, int nNames, char * FileName )
+{
+ int i;
+ FILE * pFile;
+
+ // start the file
+ pFile = fopen( FileName, "w" );
+ fprintf( pFile, ".model %s\n", FileName );
+
+ fprintf( pFile, ".inputs" );
+ for ( i = 0; i < nNames; i++ )
+ fprintf( pFile, " %s", pNames[i] );
+ fprintf( pFile, "\n" );
+ fprintf( pFile, ".outputs F" );
+ fprintf( pFile, "\n" );
+
+ // write the DD into the file
+ WriteDDintoBLIFfile( pFile, aFunc, "F", "", pNames );
+
+ fprintf( pFile, ".end\n" );
+ fclose( pFile );
+}
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void WriteDDintoBLIFfile( FILE * pFile, DdNode * Func, char * OutputName, char * Prefix, char ** InputNames )
+// writes the main part of the BLIF file
+// Func is a BDD or a 0-1 ADD to be written
+// OutputName is the name of the output
+// Prefix is attached to each intermendiate signal to make it unique
+// InputNames are the names of the input signals
+// (some part of the code is borrowed from Cudd_DumpDot())
+{
+ int i;
+ st_table * visited;
+ st_generator * gen = NULL;
+ long refAddr, diff, mask;
+ DdNode * Node, * Else, * ElseR, * Then;
+
+ /* Initialize symbol table for visited nodes. */
+ visited = st_init_table( st_ptrcmp, st_ptrhash );
+
+ /* Collect all the nodes of this DD in the symbol table. */
+ cuddCollectNodes( Cudd_Regular(Func), visited );
+
+ /* Find how many most significant hex digits are identical
+ ** in the addresses of all the nodes. Build a mask based
+ ** on this knowledge, so that digits that carry no information
+ ** will not be printed. This is done in two steps.
+ ** 1. We scan the symbol table to find the bits that differ
+ ** in at least 2 addresses.
+ ** 2. We choose one of the possible masks. There are 8 possible
+ ** masks for 32-bit integer, and 16 possible masks for 64-bit
+ ** integers.
+ */
+
+ /* Find the bits that are different. */
+ refAddr = ( long )Cudd_Regular(Func);
+ diff = 0;
+ gen = st_init_gen( visited );
+ while ( st_gen( gen, ( char ** ) &Node, NULL ) )
+ {
+ diff |= refAddr ^ ( long ) Node;
+ }
+ st_free_gen( gen );
+ gen = NULL;
+
+ /* Choose the mask. */
+ for ( i = 0; ( unsigned ) i < 8 * sizeof( long ); i += 4 )
+ {
+ mask = ( 1 << i ) - 1;
+ if ( diff <= mask )
+ break;
+ }
+
+
+ // write the buffer for the output
+ fprintf( pFile, ".names %s%lx %s\n", Prefix, ( mask & (long)Cudd_Regular(Func) ) / sizeof(DdNode), OutputName );
+ fprintf( pFile, "%s 1\n", (Cudd_IsComplement(Func))? "0": "1" );
+
+
+ gen = st_init_gen( visited );
+ while ( st_gen( gen, ( char ** ) &Node, NULL ) )
+ {
+ if ( Node->index == CUDD_MAXINDEX )
+ {
+ // write the terminal node
+ fprintf( pFile, ".names %s%lx\n", Prefix, ( mask & (long)Node ) / sizeof(DdNode) );
+ fprintf( pFile, " %s\n", (cuddV(Node) == 0.0)? "0": "1" );
+ continue;
+ }
+
+ Else = cuddE(Node);
+ ElseR = Cudd_Regular(Else);
+ Then = cuddT(Node);
+
+ assert( InputNames[Node->index] );
+ if ( Else == ElseR )
+ { // no inverter
+ fprintf( pFile, ".names %s %s%lx %s%lx %s%lx\n", InputNames[Node->index],
+ Prefix, ( mask & (long)ElseR ) / sizeof(DdNode),
+ Prefix, ( mask & (long)Then ) / sizeof(DdNode),
+ Prefix, ( mask & (long)Node ) / sizeof(DdNode) );
+ fprintf( pFile, "01- 1\n" );
+ fprintf( pFile, "1-1 1\n" );
+ }
+ else
+ { // inverter
+ int * pSlot;
+ fprintf( pFile, ".names %s %s%lx_i %s%lx %s%lx\n", InputNames[Node->index],
+ Prefix, ( mask & (long)ElseR ) / sizeof(DdNode),
+ Prefix, ( mask & (long)Then ) / sizeof(DdNode),
+ Prefix, ( mask & (long)Node ) / sizeof(DdNode) );
+ fprintf( pFile, "01- 1\n" );
+ fprintf( pFile, "1-1 1\n" );
+
+ // if the inverter is written, skip
+ if ( !st_find( visited, (char *)ElseR, (char ***)&pSlot ) )
+ assert( 0 );
+ if ( *pSlot )
+ continue;
+ *pSlot = 1;
+
+ fprintf( pFile, ".names %s%lx %s%lx_i\n",
+ Prefix, ( mask & (long)ElseR ) / sizeof(DdNode),
+ Prefix, ( mask & (long)ElseR ) / sizeof(DdNode) );
+ fprintf( pFile, "0 1\n" );
+ }
+ }
+ st_free_gen( gen );
+ gen = NULL;
+ st_free_table( visited );
+}
+
+
+
+
+static DdManager * s_ddmin;
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void WriteDDintoBLIFfileReorder( DdManager * dd, FILE * pFile, DdNode * Func, char * OutputName, char * Prefix, char ** InputNames )
+// writes the main part of the BLIF file
+// Func is a BDD or a 0-1 ADD to be written
+// OutputName is the name of the output
+// Prefix is attached to each intermendiate signal to make it unique
+// InputNames are the names of the input signals
+// (some part of the code is borrowed from Cudd_DumpDot())
+{
+ int i;
+ st_table * visited;
+ st_generator * gen = NULL;
+ long refAddr, diff, mask;
+ DdNode * Node, * Else, * ElseR, * Then;
+
+
+ ///////////////////////////////////////////////////////////////
+ DdNode * bFmin;
+ int clk1;
+
+ if ( s_ddmin == NULL )
+ s_ddmin = Cudd_Init( dd->size, 0, CUDD_UNIQUE_SLOTS, CUDD_CACHE_SLOTS, 0);
+
+ clk1 = clock();
+ bFmin = Cudd_bddTransfer( dd, s_ddmin, Func ); Cudd_Ref( bFmin );
+
+ // reorder
+ printf( "Nodes before = %d. ", Cudd_DagSize(bFmin) );
+ Cudd_ReduceHeap(s_ddmin,CUDD_REORDER_SYMM_SIFT,1);
+// Cudd_ReduceHeap(s_ddmin,CUDD_REORDER_SYMM_SIFT_CONV,1);
+ printf( "Nodes after = %d. \n", Cudd_DagSize(bFmin) );
+ ///////////////////////////////////////////////////////////////
+
+
+
+ /* Initialize symbol table for visited nodes. */
+ visited = st_init_table( st_ptrcmp, st_ptrhash );
+
+ /* Collect all the nodes of this DD in the symbol table. */
+ cuddCollectNodes( Cudd_Regular(bFmin), visited );
+
+ /* Find how many most significant hex digits are identical
+ ** in the addresses of all the nodes. Build a mask based
+ ** on this knowledge, so that digits that carry no information
+ ** will not be printed. This is done in two steps.
+ ** 1. We scan the symbol table to find the bits that differ
+ ** in at least 2 addresses.
+ ** 2. We choose one of the possible masks. There are 8 possible
+ ** masks for 32-bit integer, and 16 possible masks for 64-bit
+ ** integers.
+ */
+
+ /* Find the bits that are different. */
+ refAddr = ( long )Cudd_Regular(bFmin);
+ diff = 0;
+ gen = st_init_gen( visited );
+ while ( st_gen( gen, ( char ** ) &Node, NULL ) )
+ {
+ diff |= refAddr ^ ( long ) Node;
+ }
+ st_free_gen( gen );
+ gen = NULL;
+
+ /* Choose the mask. */
+ for ( i = 0; ( unsigned ) i < 8 * sizeof( long ); i += 4 )
+ {
+ mask = ( 1 << i ) - 1;
+ if ( diff <= mask )
+ break;
+ }
+
+
+ // write the buffer for the output
+ fprintf( pFile, ".names %s%lx %s\n", Prefix, ( mask & (long)Cudd_Regular(bFmin) ) / sizeof(DdNode), OutputName );
+ fprintf( pFile, "%s 1\n", (Cudd_IsComplement(bFmin))? "0": "1" );
+
+
+ gen = st_init_gen( visited );
+ while ( st_gen( gen, ( char ** ) &Node, NULL ) )
+ {
+ if ( Node->index == CUDD_MAXINDEX )
+ {
+ // write the terminal node
+ fprintf( pFile, ".names %s%lx\n", Prefix, ( mask & (long)Node ) / sizeof(DdNode) );
+ fprintf( pFile, " %s\n", (cuddV(Node) == 0.0)? "0": "1" );
+ continue;
+ }
+
+ Else = cuddE(Node);
+ ElseR = Cudd_Regular(Else);
+ Then = cuddT(Node);
+
+ assert( InputNames[Node->index] );
+ if ( Else == ElseR )
+ { // no inverter
+ fprintf( pFile, ".names %s %s%lx %s%lx %s%lx\n", InputNames[Node->index],
+ Prefix, ( mask & (long)ElseR ) / sizeof(DdNode),
+ Prefix, ( mask & (long)Then ) / sizeof(DdNode),
+ Prefix, ( mask & (long)Node ) / sizeof(DdNode) );
+ fprintf( pFile, "01- 1\n" );
+ fprintf( pFile, "1-1 1\n" );
+ }
+ else
+ { // inverter
+ fprintf( pFile, ".names %s %s%lx_i %s%lx %s%lx\n", InputNames[Node->index],
+ Prefix, ( mask & (long)ElseR ) / sizeof(DdNode),
+ Prefix, ( mask & (long)Then ) / sizeof(DdNode),
+ Prefix, ( mask & (long)Node ) / sizeof(DdNode) );
+ fprintf( pFile, "01- 1\n" );
+ fprintf( pFile, "1-1 1\n" );
+
+ fprintf( pFile, ".names %s%lx %s%lx_i\n",
+ Prefix, ( mask & (long)ElseR ) / sizeof(DdNode),
+ Prefix, ( mask & (long)ElseR ) / sizeof(DdNode) );
+ fprintf( pFile, "0 1\n" );
+ }
+ }
+ st_free_gen( gen );
+ gen = NULL;
+ st_free_table( visited );
+
+
+ //////////////////////////////////////////////////
+ Cudd_RecursiveDeref( s_ddmin, bFmin );
+ //////////////////////////////////////////////////
+}
+
+
+
+
+////////////////////////////////////////////////////////////////////////
+/// TRANSFER WITH MAPPING ///
+////////////////////////////////////////////////////////////////////////
+static DdNode * cuddBddTransferPermuteRecur
+ARGS((DdManager * ddS, DdManager * ddD, DdNode * f, st_table * table, int * Permute ));
+
+static DdNode * cuddBddTransferPermute
+ARGS((DdManager * ddS, DdManager * ddD, DdNode * f, int * Permute));
+
+/**Function********************************************************************
+
+ Synopsis [Convert a BDD from a manager to another one.]
+
+ Description [Convert a BDD from a manager to another one. The orders of the
+ variables in the two managers may be different. Returns a
+ pointer to the BDD in the destination manager if successful; NULL
+ otherwise. The i-th entry in the array Permute tells what is the index
+ of the i-th variable from the old manager in the new manager.]
+
+ SideEffects [None]
+
+ SeeAlso []
+
+******************************************************************************/
+DdNode *
+Cudd_bddTransferPermute( DdManager * ddSource,
+ DdManager * ddDestination, DdNode * f, int * Permute )
+{
+ DdNode *res;
+ do
+ {
+ ddDestination->reordered = 0;
+ res = cuddBddTransferPermute( ddSource, ddDestination, f, Permute );
+ }
+ while ( ddDestination->reordered == 1 );
+ return ( res );
+
+} /* end of Cudd_bddTransferPermute */
+
+
+/*---------------------------------------------------------------------------*/
+/* Definition of internal functions */
+/*---------------------------------------------------------------------------*/
+
+
+/**Function********************************************************************
+
+ Synopsis [Convert a BDD from a manager to another one.]
+
+ Description [Convert a BDD from a manager to another one. Returns a
+ pointer to the BDD in the destination manager if successful; NULL
+ otherwise.]
+
+ SideEffects [None]
+
+ SeeAlso [Cudd_bddTransferPermute]
+
+******************************************************************************/
+DdNode *
+cuddBddTransferPermute( DdManager * ddS, DdManager * ddD, DdNode * f, int * Permute )
+{
+ DdNode *res;
+ st_table *table = NULL;
+ st_generator *gen = NULL;
+ DdNode *key, *value;
+
+ table = st_init_table( st_ptrcmp, st_ptrhash );
+ if ( table == NULL )
+ goto failure;
+ res = cuddBddTransferPermuteRecur( ddS, ddD, f, table, Permute );
+ if ( res != NULL )
+ cuddRef( res );
+
+ /* Dereference all elements in the table and dispose of the table.
+ ** This must be done also if res is NULL to avoid leaks in case of
+ ** reordering. */
+ gen = st_init_gen( table );
+ if ( gen == NULL )
+ goto failure;
+ while ( st_gen( gen, ( char ** ) &key, ( char ** ) &value ) )
+ {
+ Cudd_RecursiveDeref( ddD, value );
+ }
+ st_free_gen( gen );
+ gen = NULL;
+ st_free_table( table );
+ table = NULL;
+
+ if ( res != NULL )
+ cuddDeref( res );
+ return ( res );
+
+ failure:
+ if ( table != NULL )
+ st_free_table( table );
+ if ( gen != NULL )
+ st_free_gen( gen );
+ return ( NULL );
+
+} /* end of cuddBddTransferPermute */
+
+
+/**Function********************************************************************
+
+ Synopsis [Performs the recursive step of Cudd_bddTransferPermute.]
+
+ Description [Performs the recursive step of Cudd_bddTransferPermute.
+ Returns a pointer to the result if successful; NULL otherwise.]
+
+ SideEffects [None]
+
+ SeeAlso [cuddBddTransferPermute]
+
+******************************************************************************/
+static DdNode *
+cuddBddTransferPermuteRecur( DdManager * ddS,
+ DdManager * ddD, DdNode * f, st_table * table, int * Permute )
+{
+ DdNode *ft, *fe, *t, *e, *var, *res;
+ DdNode *one, *zero;
+ int index;
+ int comple = 0;
+
+ statLine( ddD );
+ one = DD_ONE( ddD );
+ comple = Cudd_IsComplement( f );
+
+ /* Trivial cases. */
+ if ( Cudd_IsConstant( f ) )
+ return ( Cudd_NotCond( one, comple ) );
+
+ /* Make canonical to increase the utilization of the cache. */
+ f = Cudd_NotCond( f, comple );
+ /* Now f is a regular pointer to a non-constant node. */
+
+ /* Check the cache. */
+ if ( st_lookup( table, ( char * ) f, ( char ** ) &res ) )
+ return ( Cudd_NotCond( res, comple ) );
+
+ /* Recursive step. */
+ index = Permute[f->index];
+ ft = cuddT( f );
+ fe = cuddE( f );
+
+ t = cuddBddTransferPermuteRecur( ddS, ddD, ft, table, Permute );
+ if ( t == NULL )
+ {
+ return ( NULL );
+ }
+ cuddRef( t );
+
+ e = cuddBddTransferPermuteRecur( ddS, ddD, fe, table, Permute );
+ if ( e == NULL )
+ {
+ Cudd_RecursiveDeref( ddD, t );
+ return ( NULL );
+ }
+ cuddRef( e );
+
+ zero = Cudd_Not( one );
+ var = cuddUniqueInter( ddD, index, one, zero );
+ if ( var == NULL )
+ {
+ Cudd_RecursiveDeref( ddD, t );
+ Cudd_RecursiveDeref( ddD, e );
+ return ( NULL );
+ }
+ res = cuddBddIteRecur( ddD, var, t, e );
+ if ( res == NULL )
+ {
+ Cudd_RecursiveDeref( ddD, t );
+ Cudd_RecursiveDeref( ddD, e );
+ return ( NULL );
+ }
+ cuddRef( res );
+ Cudd_RecursiveDeref( ddD, t );
+ Cudd_RecursiveDeref( ddD, e );
+
+ if ( st_add_direct( table, ( char * ) f, ( char * ) res ) ==
+ ST_OUT_OF_MEM )
+ {
+ Cudd_RecursiveDeref( ddD, res );
+ return ( NULL );
+ }
+ return ( Cudd_NotCond( res, comple ) );
+
+} /* end of cuddBddTransferPermuteRecur */
+
+////////////////////////////////////////////////////////////////////////
+/// END OF FILE ///
+////////////////////////////////////////////////////////////////////////
+
+
+
+
diff --git a/src/bdd/cas/casDec.c b/src/bdd/cas/casDec.c
new file mode 100644
index 00000000..a1eb5f36
--- /dev/null
+++ b/src/bdd/cas/casDec.c
@@ -0,0 +1,508 @@
+/**CFile****************************************************************
+
+ FileName [casDec.c]
+
+ SystemName [ABC: Logic synthesis and verification system.]
+
+ PackageName [CASCADE: Decomposition of shared BDDs into a LUT cascade.]
+
+ Synopsis [BDD-based decomposition with encoding.]
+
+ Author [Alan Mishchenko]
+
+ Affiliation [UC Berkeley]
+
+ Date [Ver. 1.0. Started - Spring 2002.]
+
+ Revision [$Id: casDec.c,v 1.0 2002/01/01 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include <time.h>
+
+#include "extra.h"
+#include "cas.h"
+
+////////////////////////////////////////////////////////////////////////
+/// type definitions ///
+////////////////////////////////////////////////////////////////////////
+
+typedef struct
+{
+ int nIns; // the number of LUT variables
+ int nInsP; // the number of inputs coming from the previous LUT
+ int nCols; // the number of columns in this LUT
+ int nMulti; // the column multiplicity, [log2(nCols)]
+ int nSimple; // the number of outputs implemented as direct connections to inputs of the previous block
+ int Level; // the starting level in the ADD in this LUT
+
+// DdNode ** pbVarsIn[32]; // the BDDs of the elementary input variables
+// DdNode ** pbVarsOut[32]; // the BDDs of the elementary output variables
+
+// char * pNamesIn[32]; // the names of input variables
+// char * pNamesOut[32]; // the names of output variables
+
+ DdNode ** pbCols; // the array of columns represented by BDDs
+ DdNode ** pbCodes; // the array of codes (in terms of pbVarsOut)
+ DdNode ** paNodes; // the array of starting ADD nodes on the next level (also referenced)
+
+ DdNode * bRelation; // the relation after encoding
+
+ // the relation depends on the three groups of variables:
+ // (1) variables on top represent the outputs of the previous cascade
+ // (2) variables in the middle represent the primary inputs
+ // (3) variables below (CVars) represent the codes
+ //
+ // the replacement is done after computing the relation
+} LUT;
+
+
+////////////////////////////////////////////////////////////////////////
+/// static functions ///
+////////////////////////////////////////////////////////////////////////
+
+// the LUT-2-BLIF writing function
+void WriteLUTSintoBLIFfile( FILE * pFile, DdManager * dd, LUT ** pLuts, int nLuts, DdNode ** bCVars, char ** pNames, int nNames, char * FileName );
+
+// the function to write a DD (BDD or ADD) as a network of MUXES
+extern void WriteDDintoBLIFfile( FILE * pFile, DdNode * Func, char * OutputName, char * Prefix, char ** InputNames );
+extern void WriteDDintoBLIFfileReorder( DdManager * dd, FILE * pFile, DdNode * Func, char * OutputName, char * Prefix, char ** InputNames );
+
+////////////////////////////////////////////////////////////////////////
+/// static varibles ///
+////////////////////////////////////////////////////////////////////////
+
+static int s_LutSize = 15;
+static int s_nFuncVars;
+
+long s_EncodingTime;
+
+long s_EncSearchTime;
+long s_EncComputeTime;
+
+////////////////////////////////////
+// temporary output variables
+//FILE * pTable;
+//long s_ReadingTime;
+//long s_RemappingTime;
+////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+/// debugging macros ///
+////////////////////////////////////////////////////////////////////////
+
+#define PRB(f) printf( #f " = " ); Cudd_bddPrint(dd,f); printf( "\n" )
+#define PRK(f,n) Cudd_PrintKMap(stdout,dd,(f),Cudd_Not(f),(n),NULL,0); printf( "K-map for function" #f "\n\n" )
+#define PRK2(f,g,n) Cudd_PrintKMap(stdout,dd,(f),(g),(n),NULL,0); printf( "K-map for function <" #f ", " #g ">\n\n" )
+
+
+////////////////////////////////////////////////////////////////////////
+/// EXTERNAL FUNCTIONS ///
+////////////////////////////////////////////////////////////////////////
+
+int CreateDecomposedNetwork( DdManager * dd, DdNode * aFunc, char ** pNames, int nNames, char * FileName, int nLutSize, int fCheck, int fVerbose )
+// aFunc is a 0-1 ADD for the given function
+// pNames (nNames) are the input variable names
+// FileName is the name of the output file for the LUT network
+// dynamic variable reordering should be disabled when this function is running
+{
+ static LUT * pLuts[MAXINPUTS]; // the LUT cascade
+ static int Profile[MAXINPUTS]; // the profile filled in with the info about the BDD width
+ static int Permute[MAXINPUTS]; // the array to store a temporary permutation of variables
+
+ LUT * p; // the current LUT
+ int i, v;
+
+ DdNode * bCVars[32]; // these are variables for the codes
+
+ int nVarsRem; // the number of remaining variables
+ int PrevMulti; // column multiplicity on the previous level
+ int fLastLut; // flag to signal the last LUT
+ int nLuts;
+ int nLutsTotal = 0;
+ int nLutOutputs = 0;
+ int nLutOutputsOrig = 0;
+
+ long clk1;
+
+ s_LutSize = nLutSize;
+
+ s_nFuncVars = nNames;
+
+ // get the profile
+ clk1 = clock();
+ Extra_ProfileWidth( dd, aFunc, Profile, -1 );
+
+
+// for ( v = 0; v < nNames; v++ )
+// printf( "Level = %2d, Width = %2d\n", v+1, Profile[v] );
+
+
+//printf( "\n" );
+
+ // mark-up the LUTs
+ // assuming that the manager has exactly nNames vars (new vars have not been introduced yet)
+ nVarsRem = nNames; // the number of remaining variables
+ PrevMulti = 0; // column multiplicity on the previous level
+ fLastLut = 0;
+ nLuts = 0;
+ do
+ {
+ p = (LUT*) malloc( sizeof(LUT) );
+ memset( p, 0, sizeof(LUT) );
+
+ if ( nVarsRem + PrevMulti <= s_LutSize ) // this is the last LUT
+ {
+ p->nIns = nVarsRem + PrevMulti;
+ p->nInsP = PrevMulti;
+ p->nCols = 2;
+ p->nMulti = 1;
+ p->Level = nNames-nVarsRem;
+
+ nVarsRem = 0;
+ PrevMulti = 1;
+
+ fLastLut = 1;
+ }
+ else // this is not the last LUT
+ {
+ p->nIns = s_LutSize;
+ p->nInsP = PrevMulti;
+ p->nCols = Profile[nNames-(nVarsRem-(s_LutSize-PrevMulti))];
+ p->nMulti = Extra_Base2Log(p->nCols);
+ p->Level = nNames-nVarsRem;
+
+ nVarsRem = nVarsRem-(s_LutSize-PrevMulti);
+ PrevMulti = p->nMulti;
+ }
+
+ if ( p->nMulti >= s_LutSize )
+ {
+ printf( "The LUT size is too small\n" );
+ return 0;
+ }
+
+ nLutOutputsOrig += p->nMulti;
+
+
+//if ( fVerbose )
+//printf( "Stage %2d: In = %3d, InP = %3d, Cols = %5d, Multi = %2d, Level = %2d\n",
+// nLuts+1, p->nIns, p->nInsP, p->nCols, p->nMulti, p->Level );
+
+
+ // there should be as many columns, codes, and nodes, as there are columns on this level
+ p->pbCols = (DdNode **) malloc( p->nCols * sizeof(DdNode *) );
+ p->pbCodes = (DdNode **) malloc( p->nCols * sizeof(DdNode *) );
+ p->paNodes = (DdNode **) malloc( p->nCols * sizeof(DdNode *) );
+
+ pLuts[nLuts] = p;
+ nLuts++;
+ }
+ while ( !fLastLut );
+
+
+//if ( fVerbose )
+//printf( "The number of cascades = %d\n", nLuts );
+
+
+//fprintf( pTable, "%d ", nLuts );
+
+
+ // add the new variables at the bottom
+ for ( i = 0; i < s_LutSize; i++ )
+ bCVars[i] = Cudd_bddNewVar(dd);
+
+ // for each LUT - assign the LUT and encode the columns
+ s_EncodingTime = 0;
+ for ( i = 0; i < nLuts; i++ )
+ {
+ int RetValue;
+ DdNode * bVars[32];
+ int nVars;
+ DdNode * bVarsInCube;
+ DdNode * bVarsCCube;
+ DdNode * bVarsCube;
+ int CutLevel;
+
+ p = pLuts[i];
+
+ // compute the columns of this LUT starting from the given set of nodes with the given codes
+ // (these codes have been remapped to depend on the topmost variables in the manager)
+ // for the first LUT, start with the constant 1 BDD
+ CutLevel = p->Level + p->nIns - p->nInsP;
+ if ( i == 0 )
+ RetValue = Extra_bddNodePathsUnderCutArray(
+ dd, &aFunc, &(b1), 1,
+ p->paNodes, p->pbCols, CutLevel );
+ else
+ RetValue = Extra_bddNodePathsUnderCutArray(
+ dd, pLuts[i-1]->paNodes, pLuts[i-1]->pbCodes, pLuts[i-1]->nCols,
+ p->paNodes, p->pbCols, CutLevel );
+ assert( RetValue == p->nCols );
+ // at this point, we have filled out p->paNodes[] and p->pbCols[] of this LUT
+ // pLuts[i-1]->paNodes depended on normal vars
+ // pLuts[i-1]->pbCodes depended on the topmost variables
+ // the resulting p->paNodes depend on normal ADD nodes
+ // the resulting p->pbCols depend on normal vars and topmost variables in the manager
+
+ // perform the encoding
+
+ // create the cube of these variables
+ // collect the topmost variables of the manager
+ nVars = p->nInsP;
+ for ( v = 0; v < nVars; v++ )
+ bVars[v] = dd->vars[ dd->invperm[v] ];
+ bVarsCCube = Extra_bddBitsToCube( dd, (1<<nVars)-1, nVars, bVars, 1 ); Cudd_Ref( bVarsCCube );
+
+ // collect the primary input variables involved in this LUT
+ nVars = p->nIns - p->nInsP;
+ for ( v = 0; v < nVars; v++ )
+ bVars[v] = dd->vars[ dd->invperm[p->Level+v] ];
+ bVarsInCube = Extra_bddBitsToCube( dd, (1<<nVars)-1, nVars, bVars, 1 ); Cudd_Ref( bVarsInCube );
+
+ // get the cube
+ bVarsCube = Cudd_bddAnd( dd, bVarsInCube, bVarsCCube ); Cudd_Ref( bVarsCube );
+ Cudd_RecursiveDeref( dd, bVarsInCube );
+ Cudd_RecursiveDeref( dd, bVarsCCube );
+
+ // get the encoding relation
+ if ( i == nLuts -1 )
+ {
+ DdNode * bVar;
+ assert( p->nMulti == 1 );
+ assert( p->nCols == 2 );
+ assert( Cudd_IsConstant( p->paNodes[0] ) );
+ assert( Cudd_IsConstant( p->paNodes[1] ) );
+
+ bVar = ( p->paNodes[0] == a1 )? bCVars[0]: Cudd_Not( bCVars[0] );
+ p->bRelation = Cudd_bddIte( dd, bVar, p->pbCols[0], p->pbCols[1] ); Cudd_Ref( p->bRelation );
+ }
+ else
+ {
+ long clk2 = clock();
+// p->bRelation = PerformTheEncoding( dd, p->pbCols, p->nCols, bVarsCube, bCVars, p->nMulti, &p->nSimple ); Cudd_Ref( p->bRelation );
+ p->bRelation = Extra_bddEncodingNonStrict( dd, p->pbCols, p->nCols, bVarsCube, bCVars, p->nMulti, &p->nSimple ); Cudd_Ref( p->bRelation );
+ s_EncodingTime += clock() - clk2;
+ }
+
+ // update the number of LUT outputs
+ nLutOutputs += (p->nMulti - p->nSimple);
+ nLutsTotal += p->nMulti;
+
+//if ( fVerbose )
+//printf( "Stage %2d: Simple = %d\n", i+1, p->nSimple );
+
+if ( fVerbose )
+printf( "Stage %3d: In = %3d InP = %3d Cols = %5d Multi = %2d Simple = %2d Level = %3d\n",
+ i+1, p->nIns, p->nInsP, p->nCols, p->nMulti, p->nSimple, p->Level );
+
+ // get the codes from the relation (these are not necessarily cubes)
+ {
+ int c;
+ for ( c = 0; c < p->nCols; c++ )
+ {
+ p->pbCodes[c] = Cudd_bddAndAbstract( dd, p->bRelation, p->pbCols[c], bVarsCube ); Cudd_Ref( p->pbCodes[c] );
+ }
+ }
+
+ Cudd_RecursiveDeref( dd, bVarsCube );
+
+ // remap the codes to depend on the topmost varibles of the manager
+ // useful as a preparation for the next step
+ {
+ DdNode ** pbTemp;
+ int k, v;
+
+ pbTemp = (DdNode **) malloc( p->nCols * sizeof(DdNode *) );
+
+ // create the identical permutation
+ for ( v = 0; v < dd->size; v++ )
+ Permute[v] = v;
+
+ // use the topmost variables of the manager
+ // to represent the previous level codes
+ for ( v = 0; v < p->nMulti; v++ )
+ Permute[bCVars[v]->index] = dd->invperm[v];
+
+ Extra_bddPermuteArray( dd, p->pbCodes, pbTemp, p->nCols, Permute );
+ // the array pbTemp comes already referenced
+
+ // deref the old codes and assign the new ones
+ for ( k = 0; k < p->nCols; k++ )
+ {
+ Cudd_RecursiveDeref( dd, p->pbCodes[k] );
+ p->pbCodes[k] = pbTemp[k];
+ }
+ free( pbTemp );
+ }
+ }
+ if ( fVerbose )
+ printf( "LUTs: Total = %5d. Final = %5d. Simple = %5d. (%6.2f %%) ",
+ nLutsTotal, nLutOutputs, nLutsTotal-nLutOutputs, 100.0*(nLutsTotal-nLutOutputs)/nLutsTotal );
+ if ( fVerbose )
+ printf( "Memory = %6.2f Mb\n", 1.0*nLutOutputs*(1<<nLutSize)/(1<<20) );
+// printf( "\n" );
+
+//fprintf( pTable, "%d ", nLutOutputsOrig );
+//fprintf( pTable, "%d ", nLutOutputs );
+
+ if ( fVerbose )
+ {
+ printf( "Pure decomposition time = %.2f sec\n", (float)(clock() - clk1 - s_EncodingTime)/(float)(CLOCKS_PER_SEC) );
+ printf( "Encoding time = %.2f sec\n", (float)(s_EncodingTime)/(float)(CLOCKS_PER_SEC) );
+// printf( "Encoding search time = %.2f sec\n", (float)(s_EncSearchTime)/(float)(CLOCKS_PER_SEC) );
+// printf( "Encoding compute time = %.2f sec\n", (float)(s_EncComputeTime)/(float)(CLOCKS_PER_SEC) );
+ }
+
+
+//fprintf( pTable, "%.2f ", (float)(s_ReadingTime)/(float)(CLOCKS_PER_SEC) );
+//fprintf( pTable, "%.2f ", (float)(clock() - clk1 - s_EncodingTime)/(float)(CLOCKS_PER_SEC) );
+//fprintf( pTable, "%.2f ", (float)(s_EncodingTime)/(float)(CLOCKS_PER_SEC) );
+//fprintf( pTable, "%.2f ", (float)(s_RemappingTime)/(float)(CLOCKS_PER_SEC) );
+
+
+ // write LUTs into the BLIF file
+ clk1 = clock();
+ if ( fCheck )
+ {
+ FILE * pFile;
+ // start the file
+ pFile = fopen( FileName, "w" );
+ fprintf( pFile, ".model %s\n", FileName );
+
+ fprintf( pFile, ".inputs" );
+ for ( i = 0; i < nNames; i++ )
+ fprintf( pFile, " %s", pNames[i] );
+ fprintf( pFile, "\n" );
+ fprintf( pFile, ".outputs F" );
+ fprintf( pFile, "\n" );
+
+ // write the DD into the file
+ WriteLUTSintoBLIFfile( pFile, dd, pLuts, nLuts, bCVars, pNames, nNames, FileName );
+
+ fprintf( pFile, ".end\n" );
+ fclose( pFile );
+ if ( fVerbose )
+ printf( "Output file writing time = %.2f sec\n", (float)(clock() - clk1)/(float)(CLOCKS_PER_SEC) );
+ }
+
+
+ // updo the LUT cascade
+ for ( i = 0; i < nLuts; i++ )
+ {
+ p = pLuts[i];
+ for ( v = 0; v < p->nCols; v++ )
+ {
+ Cudd_RecursiveDeref( dd, p->pbCols[v] );
+ Cudd_RecursiveDeref( dd, p->pbCodes[v] );
+ Cudd_RecursiveDeref( dd, p->paNodes[v] );
+ }
+ Cudd_RecursiveDeref( dd, p->bRelation );
+
+ free( p->pbCols );
+ free( p->pbCodes );
+ free( p->paNodes );
+ free( p );
+ }
+
+ return 1;
+}
+
+void WriteLUTSintoBLIFfile( FILE * pFile, DdManager * dd, LUT ** pLuts, int nLuts, DdNode ** bCVars, char ** pNames, int nNames, char * FileName )
+{
+ int i, v, o;
+ static char * pNamesLocalIn[MAXINPUTS];
+ static char * pNamesLocalOut[MAXINPUTS];
+ static char Buffer[100];
+ DdNode * bCube, * bCof, * bFunc;
+ LUT * p;
+
+ // go through all the LUTs
+ for ( i = 0; i < nLuts; i++ )
+ {
+ // get the pointer to the LUT
+ p = pLuts[i];
+
+ if ( i == nLuts -1 )
+ {
+ assert( p->nMulti == 1 );
+ }
+
+
+ fprintf( pFile, "#----------------- LUT #%d ----------------------\n", i );
+
+
+ // fill in the names for the current LUT
+
+ // write the outputs of the previous LUT
+ if ( i != 0 )
+ for ( v = 0; v < p->nInsP; v++ )
+ {
+ sprintf( Buffer, "LUT%02d_%02d", i-1, v );
+ pNamesLocalIn[dd->invperm[v]] = Extra_UtilStrsav( Buffer );
+ }
+ // write the primary inputs of the current LUT
+ for ( v = 0; v < p->nIns - p->nInsP; v++ )
+ pNamesLocalIn[dd->invperm[p->Level+v]] = Extra_UtilStrsav( pNames[dd->invperm[p->Level+v]] );
+ // write the outputs of the current LUT
+ for ( v = 0; v < p->nMulti; v++ )
+ {
+ sprintf( Buffer, "LUT%02d_%02d", i, v );
+ if ( i != nLuts - 1 )
+ pNamesLocalOut[v] = Extra_UtilStrsav( Buffer );
+ else
+ pNamesLocalOut[v] = Extra_UtilStrsav( "F" );
+ }
+
+
+ // write LUT outputs
+
+ // get the prefix
+ sprintf( Buffer, "L%02d_", i );
+
+ // get the cube of encoding variables
+ bCube = Extra_bddBitsToCube( dd, (1<<p->nMulti)-1, p->nMulti, bCVars, 1 ); Cudd_Ref( bCube );
+
+ // write each output of the LUT
+ for ( o = 0; o < p->nMulti; o++ )
+ {
+ // get the cofactor of this output
+ bCof = Cudd_Cofactor( dd, p->bRelation, bCVars[o] ); Cudd_Ref( bCof );
+ // quantify the remaining variables to get the function
+ bFunc = Cudd_bddExistAbstract( dd, bCof, bCube ); Cudd_Ref( bFunc );
+ Cudd_RecursiveDeref( dd, bCof );
+
+ // write BLIF
+ sprintf( Buffer, "L%02d_%02d_", i, o );
+
+// WriteDDintoBLIFfileReorder( dd, pFile, bFunc, pNamesLocalOut[o], Buffer, pNamesLocalIn );
+ // does not work well; the advantage is marginal (30%), the run time is huge...
+
+ WriteDDintoBLIFfile( pFile, bFunc, pNamesLocalOut[o], Buffer, pNamesLocalIn );
+ Cudd_RecursiveDeref( dd, bFunc );
+ }
+ Cudd_RecursiveDeref( dd, bCube );
+
+ // clean up the previous local names
+ for ( v = 0; v < dd->size; v++ )
+ {
+ if ( pNamesLocalIn[v] )
+ free( pNamesLocalIn[v] );
+ pNamesLocalIn[v] = NULL;
+ }
+ for ( v = 0; v < p->nMulti; v++ )
+ free( pNamesLocalOut[v] );
+ }
+}
+
+
+////////////////////////////////////////////////////////////////////////
+/// END OF FILE ///
+////////////////////////////////////////////////////////////////////////
+
+
+
+
diff --git a/src/bdd/cas/module.make b/src/bdd/cas/module.make
new file mode 100644
index 00000000..7830e47f
--- /dev/null
+++ b/src/bdd/cas/module.make
@@ -0,0 +1,3 @@
+SRC += src/bdd/cas/casCore.c \
+ src/bdd/cas/casDec.c
+
diff --git a/src/bdd/cudd/cuddAPI.c b/src/bdd/cudd/cuddAPI.c
index 2acde7cd..a16b82cf 100644
--- a/src/bdd/cudd/cuddAPI.c
+++ b/src/bdd/cudd/cuddAPI.c
@@ -164,7 +164,7 @@
******************************************************************************/
-#include "util.h"
+#include "util_hack.h"
#include "cuddInt.h"
/*---------------------------------------------------------------------------*/
diff --git a/src/bdd/cudd/cuddAddAbs.c b/src/bdd/cudd/cuddAddAbs.c
index 27039908..b256ad0f 100644
--- a/src/bdd/cudd/cuddAddAbs.c
+++ b/src/bdd/cudd/cuddAddAbs.c
@@ -32,7 +32,7 @@
******************************************************************************/
-#include "util.h"
+#include "util_hack.h"
#include "cuddInt.h"
/*---------------------------------------------------------------------------*/
diff --git a/src/bdd/cudd/cuddAddApply.c b/src/bdd/cudd/cuddAddApply.c
index 67649913..60c06de6 100644
--- a/src/bdd/cudd/cuddAddApply.c
+++ b/src/bdd/cudd/cuddAddApply.c
@@ -42,7 +42,7 @@
******************************************************************************/
-#include "util.h"
+#include "util_hack.h"
#include "cuddInt.h"
/*---------------------------------------------------------------------------*/
diff --git a/src/bdd/cudd/cuddAddFind.c b/src/bdd/cudd/cuddAddFind.c
index 3399527a..0469b014 100644
--- a/src/bdd/cudd/cuddAddFind.c
+++ b/src/bdd/cudd/cuddAddFind.c
@@ -27,7 +27,7 @@
******************************************************************************/
-#include "util.h"
+#include "util_hack.h"
#include "cuddInt.h"
/*---------------------------------------------------------------------------*/
diff --git a/src/bdd/cudd/cuddAddInv.c b/src/bdd/cudd/cuddAddInv.c
index cb6dbfbe..fc4a340b 100644
--- a/src/bdd/cudd/cuddAddInv.c
+++ b/src/bdd/cudd/cuddAddInv.c
@@ -24,7 +24,7 @@
******************************************************************************/
-#include "util.h"
+#include "util_hack.h"
#include "cuddInt.h"
diff --git a/src/bdd/cudd/cuddAddIte.c b/src/bdd/cudd/cuddAddIte.c
index 77c4d18a..71f8070f 100644
--- a/src/bdd/cudd/cuddAddIte.c
+++ b/src/bdd/cudd/cuddAddIte.c
@@ -33,7 +33,7 @@
******************************************************************************/
-#include "util.h"
+#include "util_hack.h"
#include "cuddInt.h"
/*---------------------------------------------------------------------------*/
diff --git a/src/bdd/cudd/cuddAddNeg.c b/src/bdd/cudd/cuddAddNeg.c
index 2420df64..bdb08ddc 100644
--- a/src/bdd/cudd/cuddAddNeg.c
+++ b/src/bdd/cudd/cuddAddNeg.c
@@ -26,7 +26,7 @@
******************************************************************************/
-#include "util.h"
+#include "util_hack.h"
#include "cuddInt.h"
diff --git a/src/bdd/cudd/cuddAddWalsh.c b/src/bdd/cudd/cuddAddWalsh.c
index 980ee215..c6a67e34 100644
--- a/src/bdd/cudd/cuddAddWalsh.c
+++ b/src/bdd/cudd/cuddAddWalsh.c
@@ -26,7 +26,7 @@
******************************************************************************/
-#include "util.h"
+#include "util_hack.h"
#include "cuddInt.h"
diff --git a/src/bdd/cudd/cuddAndAbs.c b/src/bdd/cudd/cuddAndAbs.c
index 3a6ce85f..5ec47beb 100644
--- a/src/bdd/cudd/cuddAndAbs.c
+++ b/src/bdd/cudd/cuddAndAbs.c
@@ -24,7 +24,7 @@
******************************************************************************/
-#include "util.h"
+#include "util_hack.h"
#include "cuddInt.h"
diff --git a/src/bdd/cudd/cuddAnneal.c b/src/bdd/cudd/cuddAnneal.c
index dfc81e86..3d8b56b9 100644
--- a/src/bdd/cudd/cuddAnneal.c
+++ b/src/bdd/cudd/cuddAnneal.c
@@ -35,7 +35,7 @@
******************************************************************************/
-#include "util.h"
+#include "util_hack.h"
#include "cuddInt.h"
/*---------------------------------------------------------------------------*/
diff --git a/src/bdd/cudd/cuddApa.c b/src/bdd/cudd/cuddApa.c
index 805a4dde..47ab51e8 100644
--- a/src/bdd/cudd/cuddApa.c
+++ b/src/bdd/cudd/cuddApa.c
@@ -28,7 +28,7 @@
******************************************************************************/
-#include "util.h"
+#include "util_hack.h"
#include "cuddInt.h"
/*---------------------------------------------------------------------------*/
diff --git a/src/bdd/cudd/cuddApprox.c b/src/bdd/cudd/cuddApprox.c
index eb6813ff..debcf48b 100644
--- a/src/bdd/cudd/cuddApprox.c
+++ b/src/bdd/cudd/cuddApprox.c
@@ -51,7 +51,7 @@
#else
#define DBL_MAX_EXP 1024
#endif
-#include "util.h"
+#include "util_hack.h"
#include "cuddInt.h"
/*---------------------------------------------------------------------------*/
diff --git a/src/bdd/cudd/cuddBddAbs.c b/src/bdd/cudd/cuddBddAbs.c
index 20a8f15a..9552464e 100644
--- a/src/bdd/cudd/cuddBddAbs.c
+++ b/src/bdd/cudd/cuddBddAbs.c
@@ -35,7 +35,7 @@
******************************************************************************/
-#include "util.h"
+#include "util_hack.h"
#include "cuddInt.h"
diff --git a/src/bdd/cudd/cuddBddCorr.c b/src/bdd/cudd/cuddBddCorr.c
index 47395ec7..c99324a8 100644
--- a/src/bdd/cudd/cuddBddCorr.c
+++ b/src/bdd/cudd/cuddBddCorr.c
@@ -30,7 +30,7 @@
******************************************************************************/
-#include "util.h"
+#include "util_hack.h"
#include "cuddInt.h"
diff --git a/src/bdd/cudd/cuddBddIte.c b/src/bdd/cudd/cuddBddIte.c
index fe0c6500..b44e40de 100644
--- a/src/bdd/cudd/cuddBddIte.c
+++ b/src/bdd/cudd/cuddBddIte.c
@@ -44,7 +44,7 @@
******************************************************************************/
-#include "util.h"
+#include "util_hack.h"
#include "cuddInt.h"
diff --git a/src/bdd/cudd/cuddBridge.c b/src/bdd/cudd/cuddBridge.c
index e7e5c89f..ccc0893f 100644
--- a/src/bdd/cudd/cuddBridge.c
+++ b/src/bdd/cudd/cuddBridge.c
@@ -44,7 +44,7 @@
******************************************************************************/
-#include "util.h"
+#include "util_hack.h"
#include "cuddInt.h"
/*---------------------------------------------------------------------------*/
diff --git a/src/bdd/cudd/cuddCache.c b/src/bdd/cudd/cuddCache.c
index 6598948a..d9e40921 100644
--- a/src/bdd/cudd/cuddCache.c
+++ b/src/bdd/cudd/cuddCache.c
@@ -36,7 +36,7 @@
******************************************************************************/
-#include "util.h"
+#include "util_hack.h"
#include "cuddInt.h"
/*---------------------------------------------------------------------------*/
diff --git a/src/bdd/cudd/cuddCheck.c b/src/bdd/cudd/cuddCheck.c
index 3db08dd6..aec8246d 100644
--- a/src/bdd/cudd/cuddCheck.c
+++ b/src/bdd/cudd/cuddCheck.c
@@ -34,7 +34,7 @@
******************************************************************************/
-#include "util.h"
+#include "util_hack.h"
#include "cuddInt.h"
/*---------------------------------------------------------------------------*/
diff --git a/src/bdd/cudd/cuddClip.c b/src/bdd/cudd/cuddClip.c
index 3c728a56..4da296ef 100644
--- a/src/bdd/cudd/cuddClip.c
+++ b/src/bdd/cudd/cuddClip.c
@@ -33,7 +33,7 @@
******************************************************************************/
-#include "util.h"
+#include "util_hack.h"
#include "cuddInt.h"
diff --git a/src/bdd/cudd/cuddCof.c b/src/bdd/cudd/cuddCof.c
index 0dfeff6c..f79e3f91 100644
--- a/src/bdd/cudd/cuddCof.c
+++ b/src/bdd/cudd/cuddCof.c
@@ -29,7 +29,7 @@
******************************************************************************/
-#include "util.h"
+#include "util_hack.h"
#include "cuddInt.h"
/*---------------------------------------------------------------------------*/
diff --git a/src/bdd/cudd/cuddCompose.c b/src/bdd/cudd/cuddCompose.c
index 11c6cb7b..8c858051 100644
--- a/src/bdd/cudd/cuddCompose.c
+++ b/src/bdd/cudd/cuddCompose.c
@@ -55,7 +55,7 @@
******************************************************************************/
-#include "util.h"
+#include "util_hack.h"
#include "cuddInt.h"
diff --git a/src/bdd/cudd/cuddDecomp.c b/src/bdd/cudd/cuddDecomp.c
index d9c28482..4fde7392 100644
--- a/src/bdd/cudd/cuddDecomp.c
+++ b/src/bdd/cudd/cuddDecomp.c
@@ -34,7 +34,7 @@
******************************************************************************/
-#include "util.h"
+#include "util_hack.h"
#include "cuddInt.h"
/*---------------------------------------------------------------------------*/
diff --git a/src/bdd/cudd/cuddEssent.c b/src/bdd/cudd/cuddEssent.c
index 7bd48c5a..db4b8b49 100644
--- a/src/bdd/cudd/cuddEssent.c
+++ b/src/bdd/cudd/cuddEssent.c
@@ -25,7 +25,7 @@
******************************************************************************/
-#include "util.h"
+#include "util_hack.h"
#include "cuddInt.h"
/*---------------------------------------------------------------------------*/
diff --git a/src/bdd/cudd/cuddExact.c b/src/bdd/cudd/cuddExact.c
index 6a81406b..6852be68 100644
--- a/src/bdd/cudd/cuddExact.c
+++ b/src/bdd/cudd/cuddExact.c
@@ -40,7 +40,7 @@
******************************************************************************/
-#include "util.h"
+#include "util_hack.h"
#include "cuddInt.h"
/*---------------------------------------------------------------------------*/
diff --git a/src/bdd/cudd/cuddExport.c b/src/bdd/cudd/cuddExport.c
index d7b9645b..d148be42 100644
--- a/src/bdd/cudd/cuddExport.c
+++ b/src/bdd/cudd/cuddExport.c
@@ -35,7 +35,7 @@
******************************************************************************/
-#include "util.h"
+#include "util_hack.h"
#include "cuddInt.h"
/*---------------------------------------------------------------------------*/
diff --git a/src/bdd/cudd/cuddGenCof.c b/src/bdd/cudd/cuddGenCof.c
index 59ae55d7..142ee27e 100644
--- a/src/bdd/cudd/cuddGenCof.c
+++ b/src/bdd/cudd/cuddGenCof.c
@@ -46,7 +46,7 @@
******************************************************************************/
-#include "util.h"
+#include "util_hack.h"
#include "cuddInt.h"
diff --git a/src/bdd/cudd/cuddGenetic.c b/src/bdd/cudd/cuddGenetic.c
index 8341dcbd..9fe03dad 100644
--- a/src/bdd/cudd/cuddGenetic.c
+++ b/src/bdd/cudd/cuddGenetic.c
@@ -53,7 +53,7 @@
******************************************************************************/
-#include "util.h"
+#include "util_hack.h"
#include "cuddInt.h"
/*---------------------------------------------------------------------------*/
diff --git a/src/bdd/cudd/cuddGroup.c b/src/bdd/cudd/cuddGroup.c
index f84f7881..81c05d2c 100644
--- a/src/bdd/cudd/cuddGroup.c
+++ b/src/bdd/cudd/cuddGroup.c
@@ -49,7 +49,7 @@
******************************************************************************/
-#include "util.h"
+#include "util_hack.h"
#include "cuddInt.h"
/*---------------------------------------------------------------------------*/
diff --git a/src/bdd/cudd/cuddHarwell.c b/src/bdd/cudd/cuddHarwell.c
index 10746186..063f1922 100644
--- a/src/bdd/cudd/cuddHarwell.c
+++ b/src/bdd/cudd/cuddHarwell.c
@@ -21,7 +21,7 @@
******************************************************************************/
-#include "util.h"
+#include "util_hack.h"
#include "cuddInt.h"
/*---------------------------------------------------------------------------*/
diff --git a/src/bdd/cudd/cuddInit.c b/src/bdd/cudd/cuddInit.c
index aec8d286..8e06a425 100644
--- a/src/bdd/cudd/cuddInit.c
+++ b/src/bdd/cudd/cuddInit.c
@@ -29,7 +29,7 @@
******************************************************************************/
-#include "util.h"
+#include "util_hack.h"
#define CUDD_MAIN
#include "cuddInt.h"
#undef CUDD_MAIN
diff --git a/src/bdd/cudd/cuddInteract.c b/src/bdd/cudd/cuddInteract.c
index 5a4ec79a..96613639 100644
--- a/src/bdd/cudd/cuddInteract.c
+++ b/src/bdd/cudd/cuddInteract.c
@@ -47,7 +47,7 @@
******************************************************************************/
-#include "util.h"
+#include "util_hack.h"
#include "cuddInt.h"
/*---------------------------------------------------------------------------*/
diff --git a/src/bdd/cudd/cuddLCache.c b/src/bdd/cudd/cuddLCache.c
index 72fbd48a..8bd37ba0 100644
--- a/src/bdd/cudd/cuddLCache.c
+++ b/src/bdd/cudd/cuddLCache.c
@@ -45,7 +45,7 @@
******************************************************************************/
-#include "util.h"
+#include "util_hack.h"
#include "cuddInt.h"
/*---------------------------------------------------------------------------*/
diff --git a/src/bdd/cudd/cuddLevelQ.c b/src/bdd/cudd/cuddLevelQ.c
index c4c621e7..3cc8e8d8 100644
--- a/src/bdd/cudd/cuddLevelQ.c
+++ b/src/bdd/cudd/cuddLevelQ.c
@@ -50,7 +50,7 @@
******************************************************************************/
-#include "util.h"
+#include "util_hack.h"
#include "cuddInt.h"
/*---------------------------------------------------------------------------*/
diff --git a/src/bdd/cudd/cuddLinear.c b/src/bdd/cudd/cuddLinear.c
index cec7c255..7f6b3678 100644
--- a/src/bdd/cudd/cuddLinear.c
+++ b/src/bdd/cudd/cuddLinear.c
@@ -34,7 +34,7 @@
******************************************************************************/
-#include "util.h"
+#include "util_hack.h"
#include "cuddInt.h"
/*---------------------------------------------------------------------------*/
diff --git a/src/bdd/cudd/cuddLiteral.c b/src/bdd/cudd/cuddLiteral.c
index 69594486..43740690 100644
--- a/src/bdd/cudd/cuddLiteral.c
+++ b/src/bdd/cudd/cuddLiteral.c
@@ -25,7 +25,7 @@
******************************************************************************/
-#include "util.h"
+#include "util_hack.h"
#include "cuddInt.h"
diff --git a/src/bdd/cudd/cuddMatMult.c b/src/bdd/cudd/cuddMatMult.c
index b10975ec..345e7921 100644
--- a/src/bdd/cudd/cuddMatMult.c
+++ b/src/bdd/cudd/cuddMatMult.c
@@ -29,7 +29,7 @@
******************************************************************************/
-#include "util.h"
+#include "util_hack.h"
#include "cuddInt.h"
diff --git a/src/bdd/cudd/cuddPriority.c b/src/bdd/cudd/cuddPriority.c
index bb0b83d3..788fc712 100644
--- a/src/bdd/cudd/cuddPriority.c
+++ b/src/bdd/cudd/cuddPriority.c
@@ -43,7 +43,7 @@
******************************************************************************/
-#include "util.h"
+#include "util_hack.h"
#include "cuddInt.h"
diff --git a/src/bdd/cudd/cuddRead.c b/src/bdd/cudd/cuddRead.c
index eea4c7f3..2c4a86d8 100644
--- a/src/bdd/cudd/cuddRead.c
+++ b/src/bdd/cudd/cuddRead.c
@@ -23,7 +23,7 @@
******************************************************************************/
-#include "util.h"
+#include "util_hack.h"
#include "cuddInt.h"
diff --git a/src/bdd/cudd/cuddRef.c b/src/bdd/cudd/cuddRef.c
index af08d048..a9241f3d 100644
--- a/src/bdd/cudd/cuddRef.c
+++ b/src/bdd/cudd/cuddRef.c
@@ -38,7 +38,7 @@
******************************************************************************/
-#include "util.h"
+#include "util_hack.h"
#include "cuddInt.h"
/*---------------------------------------------------------------------------*/
diff --git a/src/bdd/cudd/cuddReorder.c b/src/bdd/cudd/cuddReorder.c
index e2b3470b..1387196f 100644
--- a/src/bdd/cudd/cuddReorder.c
+++ b/src/bdd/cudd/cuddReorder.c
@@ -45,7 +45,7 @@
******************************************************************************/
-#include "util.h"
+#include "util_hack.h"
#include "cuddInt.h"
/*---------------------------------------------------------------------------*/
diff --git a/src/bdd/cudd/cuddSat.c b/src/bdd/cudd/cuddSat.c
index dde33a5b..1755a1c1 100644
--- a/src/bdd/cudd/cuddSat.c
+++ b/src/bdd/cudd/cuddSat.c
@@ -42,7 +42,7 @@
******************************************************************************/
-#include "util.h"
+#include "util_hack.h"
#include "cuddInt.h"
/*---------------------------------------------------------------------------*/
diff --git a/src/bdd/cudd/cuddSign.c b/src/bdd/cudd/cuddSign.c
index 62477e7f..fcaa65c4 100644
--- a/src/bdd/cudd/cuddSign.c
+++ b/src/bdd/cudd/cuddSign.c
@@ -25,7 +25,7 @@
******************************************************************************/
-#include "util.h"
+#include "util_hack.h"
#include "cuddInt.h"
diff --git a/src/bdd/cudd/cuddSolve.c b/src/bdd/cudd/cuddSolve.c
index 058e0c08..d9c4a2e7 100644
--- a/src/bdd/cudd/cuddSolve.c
+++ b/src/bdd/cudd/cuddSolve.c
@@ -28,7 +28,7 @@
******************************************************************************/
-#include "util.h"
+#include "util_hack.h"
#include "cuddInt.h"
/*---------------------------------------------------------------------------*/
diff --git a/src/bdd/cudd/cuddSplit.c b/src/bdd/cudd/cuddSplit.c
index af7d6372..e21ea7cb 100644
--- a/src/bdd/cudd/cuddSplit.c
+++ b/src/bdd/cudd/cuddSplit.c
@@ -32,7 +32,7 @@
******************************************************************************/
-#include "util.h"
+#include "util_hack.h"
#include "cuddInt.h"
/*---------------------------------------------------------------------------*/
diff --git a/src/bdd/cudd/cuddSubsetHB.c b/src/bdd/cudd/cuddSubsetHB.c
index 43aaf744..24d41ce5 100644
--- a/src/bdd/cudd/cuddSubsetHB.c
+++ b/src/bdd/cudd/cuddSubsetHB.c
@@ -46,7 +46,7 @@
#else
#define DBL_MAX_EXP 1024
#endif
-#include "util.h"
+#include "util_hack.h"
#include "cuddInt.h"
/*---------------------------------------------------------------------------*/
diff --git a/src/bdd/cudd/cuddSubsetSP.c b/src/bdd/cudd/cuddSubsetSP.c
index 0f7209dd..55ee3470 100644
--- a/src/bdd/cudd/cuddSubsetSP.c
+++ b/src/bdd/cudd/cuddSubsetSP.c
@@ -41,7 +41,7 @@
******************************************************************************/
-#include "util.h"
+#include "util_hack.h"
#include "cuddInt.h"
/*---------------------------------------------------------------------------*/
diff --git a/src/bdd/cudd/cuddSymmetry.c b/src/bdd/cudd/cuddSymmetry.c
index 7b2013e4..e5488b17 100644
--- a/src/bdd/cudd/cuddSymmetry.c
+++ b/src/bdd/cudd/cuddSymmetry.c
@@ -38,7 +38,7 @@
******************************************************************************/
-#include "util.h"
+#include "util_hack.h"
#include "cuddInt.h"
/*---------------------------------------------------------------------------*/
diff --git a/src/bdd/cudd/cuddTable.c b/src/bdd/cudd/cuddTable.c
index b118b76a..7f14aed1 100644
--- a/src/bdd/cudd/cuddTable.c
+++ b/src/bdd/cudd/cuddTable.c
@@ -54,7 +54,7 @@
******************************************************************************/
-#include "util.h"
+#include "util_hack.h"
#include "cuddInt.h"
/*---------------------------------------------------------------------------*/
diff --git a/src/bdd/cudd/cuddUtil.c b/src/bdd/cudd/cuddUtil.c
index c366d534..d5fa18e2 100644
--- a/src/bdd/cudd/cuddUtil.c
+++ b/src/bdd/cudd/cuddUtil.c
@@ -76,7 +76,7 @@
******************************************************************************/
-#include "util.h"
+#include "util_hack.h"
#include "cuddInt.h"
/*---------------------------------------------------------------------------*/
diff --git a/src/bdd/cudd/cuddWindow.c b/src/bdd/cudd/cuddWindow.c
index 3e6d5686..9ceb79b2 100644
--- a/src/bdd/cudd/cuddWindow.c
+++ b/src/bdd/cudd/cuddWindow.c
@@ -31,7 +31,7 @@
******************************************************************************/
-#include "util.h"
+#include "util_hack.h"
#include "cuddInt.h"
/*---------------------------------------------------------------------------*/
diff --git a/src/bdd/cudd/cuddZddCount.c b/src/bdd/cudd/cuddZddCount.c
index 29cf0c14..6c6ec1df 100644
--- a/src/bdd/cudd/cuddZddCount.c
+++ b/src/bdd/cudd/cuddZddCount.c
@@ -34,7 +34,7 @@
******************************************************************************/
-#include "util.h"
+#include "util_hack.h"
#include "cuddInt.h"
/*---------------------------------------------------------------------------*/
diff --git a/src/bdd/cudd/cuddZddFuncs.c b/src/bdd/cudd/cuddZddFuncs.c
index f938e1de..9dc27a95 100644
--- a/src/bdd/cudd/cuddZddFuncs.c
+++ b/src/bdd/cudd/cuddZddFuncs.c
@@ -48,7 +48,7 @@
******************************************************************************/
-#include "util.h"
+#include "util_hack.h"
#include "cuddInt.h"
/*---------------------------------------------------------------------------*/
diff --git a/src/bdd/cudd/cuddZddGroup.c b/src/bdd/cudd/cuddZddGroup.c
index 35f28881..621fa43f 100644
--- a/src/bdd/cudd/cuddZddGroup.c
+++ b/src/bdd/cudd/cuddZddGroup.c
@@ -40,7 +40,7 @@
******************************************************************************/
-#include "util.h"
+#include "util_hack.h"
#include "cuddInt.h"
/*---------------------------------------------------------------------------*/
diff --git a/src/bdd/cudd/cuddZddIsop.c b/src/bdd/cudd/cuddZddIsop.c
index 0918461c..f4b057ea 100644
--- a/src/bdd/cudd/cuddZddIsop.c
+++ b/src/bdd/cudd/cuddZddIsop.c
@@ -34,7 +34,7 @@
******************************************************************************/
-#include "util.h"
+#include "util_hack.h"
#include "cuddInt.h"
/*---------------------------------------------------------------------------*/
diff --git a/src/bdd/cudd/cuddZddLin.c b/src/bdd/cudd/cuddZddLin.c
index 9369bb05..ef2cd298 100644
--- a/src/bdd/cudd/cuddZddLin.c
+++ b/src/bdd/cudd/cuddZddLin.c
@@ -32,7 +32,7 @@
******************************************************************************/
-#include "util.h"
+#include "util_hack.h"
#include "cuddInt.h"
/*---------------------------------------------------------------------------*/
diff --git a/src/bdd/cudd/cuddZddMisc.c b/src/bdd/cudd/cuddZddMisc.c
index d55bb768..6a4ddd09 100644
--- a/src/bdd/cudd/cuddZddMisc.c
+++ b/src/bdd/cudd/cuddZddMisc.c
@@ -33,7 +33,7 @@
******************************************************************************/
#include <math.h>
-#include "util.h"
+#include "util_hack.h"
#include "cuddInt.h"
/*---------------------------------------------------------------------------*/
diff --git a/src/bdd/cudd/cuddZddPort.c b/src/bdd/cudd/cuddZddPort.c
index 1700ab2b..6d4a3236 100644
--- a/src/bdd/cudd/cuddZddPort.c
+++ b/src/bdd/cudd/cuddZddPort.c
@@ -32,7 +32,7 @@
******************************************************************************/
-#include "util.h"
+#include "util_hack.h"
#include "cuddInt.h"
/*---------------------------------------------------------------------------*/
diff --git a/src/bdd/cudd/cuddZddReord.c b/src/bdd/cudd/cuddZddReord.c
index e14ae2ad..e2da37f2 100644
--- a/src/bdd/cudd/cuddZddReord.c
+++ b/src/bdd/cudd/cuddZddReord.c
@@ -46,7 +46,7 @@
******************************************************************************/
-#include "util.h"
+#include "util_hack.h"
#include "cuddInt.h"
/*---------------------------------------------------------------------------*/
diff --git a/src/bdd/cudd/cuddZddSetop.c b/src/bdd/cudd/cuddZddSetop.c
index cf05210f..f1bd72f3 100644
--- a/src/bdd/cudd/cuddZddSetop.c
+++ b/src/bdd/cudd/cuddZddSetop.c
@@ -46,7 +46,7 @@
******************************************************************************/
-#include "util.h"
+#include "util_hack.h"
#include "cuddInt.h"
/*---------------------------------------------------------------------------*/
diff --git a/src/bdd/cudd/cuddZddSymm.c b/src/bdd/cudd/cuddZddSymm.c
index c9ffaab4..54019892 100644
--- a/src/bdd/cudd/cuddZddSymm.c
+++ b/src/bdd/cudd/cuddZddSymm.c
@@ -40,7 +40,7 @@
******************************************************************************/
-#include "util.h"
+#include "util_hack.h"
#include "cuddInt.h"
/*---------------------------------------------------------------------------*/
diff --git a/src/bdd/cudd/cuddZddUtil.c b/src/bdd/cudd/cuddZddUtil.c
index 0795f123..616d16d4 100644
--- a/src/bdd/cudd/cuddZddUtil.c
+++ b/src/bdd/cudd/cuddZddUtil.c
@@ -35,7 +35,7 @@
******************************************************************************/
-#include "util.h"
+#include "util_hack.h"
#include "cuddInt.h"
/*---------------------------------------------------------------------------*/
diff --git a/src/bdd/cudd/testcudd.c b/src/bdd/cudd/testcudd.c
index 451bb190..d8affadc 100644
--- a/src/bdd/cudd/testcudd.c
+++ b/src/bdd/cudd/testcudd.c
@@ -23,7 +23,7 @@
******************************************************************************/
-#include "util.h"
+#include "util_hack.h"
#include "cuddInt.h"
diff --git a/src/bdd/dsd/dsd.h b/src/bdd/dsd/dsd.h
index 5396bacd..b73b81ab 100644
--- a/src/bdd/dsd/dsd.h
+++ b/src/bdd/dsd/dsd.h
@@ -28,8 +28,12 @@
#ifndef __DSD_H__
#define __DSD_H__
+#ifdef __cplusplus
+extern "C" {
+#endif
+
////////////////////////////////////////////////////////////////////////
-/// TYPEDEF DEFITIONS ///
+/// TYPEDEF DEFINITIONS ///
////////////////////////////////////////////////////////////////////////
typedef struct Dsd_Manager_t_ Dsd_Manager_t;
@@ -55,14 +59,14 @@ enum Dsd_Type_t_ {
};
////////////////////////////////////////////////////////////////////////
-/// MACRO DEFITIONS ///
+/// MACRO DEFINITIONS ///
////////////////////////////////////////////////////////////////////////
// complementation and testing for pointers for decomposition entries
-#define Dsd_IsComplement(p) (((int)((long) (p) & 01)))
-#define Dsd_Regular(p) ((Dsd_Node_t *)((unsigned)(p) & ~01))
-#define Dsd_Not(p) ((Dsd_Node_t *)((long)(p) ^ 01))
-#define Dsd_NotCond(p,c) ((Dsd_Node_t *)((long)(p) ^ (c)))
+#define Dsd_IsComplement(p) (((int)((unsigned long) (p) & 01)))
+#define Dsd_Regular(p) ((Dsd_Node_t *)((unsigned long)(p) & ~01))
+#define Dsd_Not(p) ((Dsd_Node_t *)((unsigned long)(p) ^ 01))
+#define Dsd_NotCond(p,c) ((Dsd_Node_t *)((unsigned long)(p) ^ (c)))
////////////////////////////////////////////////////////////////////////
/// ITERATORS ///
@@ -76,7 +80,7 @@ enum Dsd_Type_t_ {
Index++ )
////////////////////////////////////////////////////////////////////////
-/// FUNCTION DEFITIONS ///
+/// FUNCTION DEFINITIONS ///
////////////////////////////////////////////////////////////////////////
/*=== dsdApi.c =======================================================*/
@@ -91,6 +95,7 @@ extern void Dsd_NodeSetMark( Dsd_Node_t * p, int Mark );
extern DdManager * Dsd_ManagerReadDd( Dsd_Manager_t * pMan );
extern Dsd_Node_t * Dsd_ManagerReadRoot( Dsd_Manager_t * pMan, int i );
extern Dsd_Node_t * Dsd_ManagerReadInput( Dsd_Manager_t * pMan, int i );
+extern Dsd_Node_t * Dsd_ManagerReadConst1( Dsd_Manager_t * pMan );
/*=== dsdMan.c =======================================================*/
extern Dsd_Manager_t * Dsd_ManagerStart( DdManager * dd, int nSuppMax, int fVerbose );
extern void Dsd_ManagerStop( Dsd_Manager_t * dMan );
@@ -100,6 +105,7 @@ extern Dsd_Node_t * Dsd_DecomposeOne( Dsd_Manager_t * pDsdMan, DdNode * bFunc
/*=== dsdTree.c =======================================================*/
extern void Dsd_TreeNodeGetInfo( Dsd_Manager_t * dMan, int * DepthMax, int * GateSizeMax );
extern void Dsd_TreeNodeGetInfoOne( Dsd_Node_t * pNode, int * DepthMax, int * GateSizeMax );
+extern int Dsd_TreeGetAigCost( Dsd_Node_t * pNode );
extern int Dsd_TreeCountNonTerminalNodes( Dsd_Manager_t * dMan );
extern int Dsd_TreeCountNonTerminalNodesOne( Dsd_Node_t * pRoot );
extern int Dsd_TreeCountPrimeNodes( Dsd_Manager_t * pDsdMan );
@@ -108,11 +114,16 @@ extern int Dsd_TreeCollectDecomposableVars( Dsd_Manager_t * dMan, in
extern Dsd_Node_t ** Dsd_TreeCollectNodesDfs( Dsd_Manager_t * dMan, int * pnNodes );
extern Dsd_Node_t ** Dsd_TreeCollectNodesDfsOne( Dsd_Manager_t * pDsdMan, Dsd_Node_t * pNode, int * pnNodes );
extern void Dsd_TreePrint( FILE * pFile, Dsd_Manager_t * dMan, char * pInputNames[], char * pOutputNames[], int fShortNames, int Output );
+extern void Dsd_NodePrint( FILE * pFile, Dsd_Node_t * pNode );
/*=== dsdLocal.c =======================================================*/
extern DdNode * Dsd_TreeGetPrimeFunction( DdManager * dd, Dsd_Node_t * pNode );
+#ifdef __cplusplus
+}
+#endif
+
+#endif
+
////////////////////////////////////////////////////////////////////////
/// END OF FILE ///
////////////////////////////////////////////////////////////////////////
-
-#endif \ No newline at end of file
diff --git a/src/bdd/dsd/dsdApi.c b/src/bdd/dsd/dsdApi.c
index daf3080f..d1c90e23 100644
--- a/src/bdd/dsd/dsdApi.c
+++ b/src/bdd/dsd/dsdApi.c
@@ -23,7 +23,7 @@
////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////
-/// FUNCTION DEFITIONS ///
+/// FUNCTION DEFINITIONS ///
////////////////////////////////////////////////////////////////////////
/**Function*************************************************************
@@ -89,6 +89,7 @@ void Dsd_NodeSetMark( Dsd_Node_t * p, int Mark ){ p->Mark = Mark; }
***********************************************************************/
Dsd_Node_t * Dsd_ManagerReadRoot( Dsd_Manager_t * pMan, int i ) { return pMan->pRoots[i]; }
Dsd_Node_t * Dsd_ManagerReadInput( Dsd_Manager_t * pMan, int i ) { return pMan->pInputs[i]; }
+Dsd_Node_t * Dsd_ManagerReadConst1( Dsd_Manager_t * pMan ) { return pMan->pConst1; }
DdManager * Dsd_ManagerReadDd( Dsd_Manager_t * pMan ) { return pMan->dd; }
////////////////////////////////////////////////////////////////////////
diff --git a/src/bdd/dsd/dsdCheck.c b/src/bdd/dsd/dsdCheck.c
index 608aa2e3..58b824d2 100644
--- a/src/bdd/dsd/dsdCheck.c
+++ b/src/bdd/dsd/dsdCheck.c
@@ -43,7 +43,7 @@ static Dds_Cache_t * pCache;
static int Dsd_CheckRootFunctionIdentity_rec( DdManager * dd, DdNode * bF1, DdNode * bF2, DdNode * bC1, DdNode * bC2 );
////////////////////////////////////////////////////////////////////////
-/// FUNCTION DEFITIONS ///
+/// FUNCTION DEFINITIONS ///
////////////////////////////////////////////////////////////////////////
/**Function********************************************************************
@@ -82,7 +82,7 @@ void Dsd_CheckCacheAllocate( int nEntries )
/**Function********************************************************************
- Synopsis [Delocates the local cache.]
+ Synopsis [Deallocates the local cache.]
Description []
diff --git a/src/bdd/dsd/dsdInt.h b/src/bdd/dsd/dsdInt.h
index 5008c24e..62ce7e99 100644
--- a/src/bdd/dsd/dsdInt.h
+++ b/src/bdd/dsd/dsdInt.h
@@ -23,7 +23,7 @@
#include "dsd.h"
////////////////////////////////////////////////////////////////////////
-/// TYPEDEF DEFITIONS ///
+/// TYPEDEF DEFINITIONS ///
////////////////////////////////////////////////////////////////////////
typedef unsigned char byte;
@@ -42,6 +42,7 @@ struct Dsd_Manager_t_
int nRootsAlloc;// the number of primary outputs
Dsd_Node_t ** pInputs; // the primary input nodes
Dsd_Node_t ** pRoots; // the primary output nodes
+ Dsd_Node_t * pConst1; // the constant node
int fVerbose; // the verbosity level
};
@@ -58,7 +59,7 @@ struct Dsd_Node_t_
};
////////////////////////////////////////////////////////////////////////
-/// MACRO DEFITIONS ///
+/// MACRO DEFINITIONS ///
////////////////////////////////////////////////////////////////////////
#define MAXINPUTS 1000
@@ -82,9 +83,9 @@ extern void Dsd_TreeNodeDelete( DdManager * dd, Dsd_Node_t * pNode );
extern void Dsd_TreeUnmark( Dsd_Manager_t * dMan );
extern DdNode * Dsd_TreeGetPrimeFunctionOld( DdManager * dd, Dsd_Node_t * pNode, int fRemap );
+#endif
+
////////////////////////////////////////////////////////////////////////
/// END OF FILE ///
////////////////////////////////////////////////////////////////////////
-
-#endif \ No newline at end of file
diff --git a/src/bdd/dsd/dsdMan.c b/src/bdd/dsd/dsdMan.c
index 4529e75a..6e43f0f4 100644
--- a/src/bdd/dsd/dsdMan.c
+++ b/src/bdd/dsd/dsdMan.c
@@ -73,6 +73,7 @@ Dsd_Manager_t * Dsd_ManagerStart( DdManager * dd, int nSuppMax, int fVerbose )
pNode->G = b1; Cudd_Ref( pNode->G );
pNode->S = b1; Cudd_Ref( pNode->S );
st_insert( dMan->Table, (char*)b1, (char*)pNode );
+ dMan->pConst1 = pNode;
Dsd_CheckCacheAllocate( 5000 );
return dMan;
diff --git a/src/bdd/dsd/dsdProc.c b/src/bdd/dsd/dsdProc.c
index 08c029e1..543ad387 100644
--- a/src/bdd/dsd/dsdProc.c
+++ b/src/bdd/dsd/dsdProc.c
@@ -1255,7 +1255,7 @@ EXIT:
s_CacheEntries++;
-#if 0
+/*
if ( dsdKernelVerifyDecomposition(dd, pThis) == 0 )
{
// write the function, for which verification does not work
@@ -1277,7 +1277,7 @@ EXIT:
cuddWriteFunctionSop( stdout, dd, zNewFunc, -1, dd->size, "1", s_pVarMask );
Cudd_RecursiveDerefZdd( dd, zNewFunc );
}
-#endif
+*/
}
diff --git a/src/bdd/dsd/dsdTree.c b/src/bdd/dsd/dsdTree.c
index 7905cbdd..2855d68d 100644
--- a/src/bdd/dsd/dsdTree.c
+++ b/src/bdd/dsd/dsdTree.c
@@ -29,7 +29,7 @@ static int Dsd_TreeCountPrimeNodes_rec( Dsd_Node_t * pNode );
static int Dsd_TreeCollectDecomposableVars_rec( DdManager * dd, Dsd_Node_t * pNode, int * pVars, int * nVars );
static void Dsd_TreeCollectNodesDfs_rec( Dsd_Node_t * pNode, Dsd_Node_t * ppNodes[], int * pnNodes );
static void Dsd_TreePrint_rec( FILE * pFile, Dsd_Node_t * pNode, int fCcmp, char * pInputNames[], char * pOutputName, int nOffset, int * pSigCounter, int fShortNames );
-
+static void Dsd_NodePrint_rec( FILE * pFile, Dsd_Node_t * pNode, int fComp, char * pOutputName, int nOffset, int * pSigCounter );
////////////////////////////////////////////////////////////////////////
/// STATIC VARIABLES ///
@@ -243,6 +243,58 @@ void Dsd_TreeGetInfo_rec( Dsd_Node_t * pNode, int RankCur )
/**Function*************************************************************
+ Synopsis [Counts AIG nodes needed to implement this node.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Dsd_TreeGetAigCost_rec( Dsd_Node_t * pNode )
+{
+ int i, Counter = 0;
+
+ assert( pNode );
+ assert( !Dsd_IsComplement( pNode ) );
+ assert( pNode->nVisits >= 0 );
+
+ if ( pNode->nDecs < 2 )
+ return 0;
+
+ // we don't want the two-input gates to count for non-decomposable blocks
+ if ( pNode->Type == DSD_NODE_OR )
+ Counter += pNode->nDecs - 1;
+ else if ( pNode->Type == DSD_NODE_EXOR )
+ Counter += 3*(pNode->nDecs - 1);
+ else if ( pNode->Type == DSD_NODE_PRIME && pNode->nDecs == 3 )
+ Counter += 3;
+
+ // call recursively
+ for ( i = 0; i < pNode->nDecs; i++ )
+ Counter += Dsd_TreeGetAigCost_rec( Dsd_Regular(pNode->pDecs[i]) );
+ return Counter;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Counts AIG nodes needed to implement this node.]
+
+ Description [Assumes that the only primes of the DSD tree are MUXes.]
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Dsd_TreeGetAigCost( Dsd_Node_t * pNode )
+{
+ return Dsd_TreeGetAigCost_rec( Dsd_Regular(pNode) );
+}
+
+/**Function*************************************************************
+
Synopsis [Counts non-terminal nodes of the DSD tree.]
Description [Nonterminal nodes include all the nodes with the
@@ -631,27 +683,21 @@ void Dsd_TreePrint_rec( FILE * pFile, Dsd_Node_t * pNode, int fComp, char * pInp
pNode->Type == DSD_NODE_PRIME || pNode->Type == DSD_NODE_OR || pNode->Type == DSD_NODE_EXOR );
Extra_PrintSymbols( pFile, ' ', nOffset, 0 );
- fprintf( pFile, "%s: ", pOutputName );
+ if ( !fComp )
+ fprintf( pFile, "%s = ", pOutputName );
+ else
+ fprintf( pFile, "NOT(%s) = ", pOutputName );
pInputNums = ALLOC( int, pNode->nDecs );
if ( pNode->Type == DSD_NODE_CONST1 )
{
- if ( fComp )
- fprintf( pFile, " Constant 0.\n" );
- else
- fprintf( pFile, " Constant 1.\n" );
+ fprintf( pFile, " Constant 1.\n" );
}
else if ( pNode->Type == DSD_NODE_BUF )
{
- if ( fComp )
- fprintf( pFile, " NOT(" );
- else
- fprintf( pFile, " " );
if ( fShortNames )
- fprintf( pFile, "%d", pNode->S->index );
+ fprintf( pFile, "%d", 'a' + pNode->S->index );
else
fprintf( pFile, "%s", pInputNames[pNode->S->index] );
- if ( fComp )
- fprintf( pFile, ")" );
fprintf( pFile, "\n" );
}
else if ( pNode->Type == DSD_NODE_PRIME )
@@ -664,25 +710,25 @@ void Dsd_TreePrint_rec( FILE * pFile, Dsd_Node_t * pNode, int fComp, char * pInp
fCompNew = (int)( pInput != pNode->pDecs[i] );
if ( i )
fprintf( pFile, "," );
+ if ( fCompNew )
+ fprintf( pFile, " NOT(" );
+ else
+ fprintf( pFile, " " );
if ( pInput->Type == DSD_NODE_BUF )
{
pInputNums[i] = 0;
- if ( fCompNew )
- fprintf( pFile, " NOT(" );
- else
- fprintf( pFile, " " );
if ( fShortNames )
fprintf( pFile, "%d", pInput->S->index );
else
fprintf( pFile, "%s", pInputNames[pInput->S->index] );
- if ( fCompNew )
- fprintf( pFile, ")" );
}
else
{
pInputNums[i] = (*pSigCounter)++;
- fprintf( pFile, " <%d>", pInputNums[i] );
+ fprintf( pFile, "<%d>", pInputNums[i] );
}
+ if ( fCompNew )
+ fprintf( pFile, ")" );
}
fprintf( pFile, " )\n" );
// call recursively for the following blocks
@@ -690,43 +736,39 @@ void Dsd_TreePrint_rec( FILE * pFile, Dsd_Node_t * pNode, int fComp, char * pInp
if ( pInputNums[i] )
{
pInput = Dsd_Regular( pNode->pDecs[i] );
- fCompNew = (int)( pInput != pNode->pDecs[i] );
sprintf( Buffer, "<%d>", pInputNums[i] );
- Dsd_TreePrint_rec( pFile, Dsd_Regular( pNode->pDecs[i] ), fCompNew, pInputNames, Buffer, nOffset + 6, pSigCounter, fShortNames );
+ Dsd_TreePrint_rec( pFile, Dsd_Regular( pNode->pDecs[i] ), 0, pInputNames, Buffer, nOffset + 6, pSigCounter, fShortNames );
}
}
else if ( pNode->Type == DSD_NODE_OR )
{
// print the line
- if ( fComp )
- fprintf( pFile, "AND(" );
- else
- fprintf( pFile, "OR(" );
+ fprintf( pFile, "OR(" );
for ( i = 0; i < pNode->nDecs; i++ )
{
pInput = Dsd_Regular( pNode->pDecs[i] );
fCompNew = (int)( pInput != pNode->pDecs[i] );
if ( i )
fprintf( pFile, "," );
+ if ( fCompNew )
+ fprintf( pFile, " NOT(" );
+ else
+ fprintf( pFile, " " );
if ( pInput->Type == DSD_NODE_BUF )
{
pInputNums[i] = 0;
- if ( fCompNew )
- fprintf( pFile, " NOT(" );
- else
- fprintf( pFile, " " );
if ( fShortNames )
- fprintf( pFile, "%d", pInput->S->index );
+ fprintf( pFile, "%c", 'a' + pInput->S->index );
else
fprintf( pFile, "%s", pInputNames[pInput->S->index] );
- if ( fCompNew )
- fprintf( pFile, ")" );
}
else
{
pInputNums[i] = (*pSigCounter)++;
- fprintf( pFile, " <%d>", pInputNums[i] );
+ fprintf( pFile, "<%d>", pInputNums[i] );
}
+ if ( fCompNew )
+ fprintf( pFile, ")" );
}
fprintf( pFile, " )\n" );
// call recursively for the following blocks
@@ -734,43 +776,208 @@ void Dsd_TreePrint_rec( FILE * pFile, Dsd_Node_t * pNode, int fComp, char * pInp
if ( pInputNums[i] )
{
pInput = Dsd_Regular( pNode->pDecs[i] );
- fCompNew = (int)( pInput != pNode->pDecs[i] );
sprintf( Buffer, "<%d>", pInputNums[i] );
- Dsd_TreePrint_rec( pFile, Dsd_Regular( pNode->pDecs[i] ), fComp ^ fCompNew, pInputNames, Buffer, nOffset + 6, pSigCounter, fShortNames );
+ Dsd_TreePrint_rec( pFile, Dsd_Regular( pNode->pDecs[i] ), 0, pInputNames, Buffer, nOffset + 6, pSigCounter, fShortNames );
}
}
else if ( pNode->Type == DSD_NODE_EXOR )
{
// print the line
- if ( fComp )
- fprintf( pFile, "NEXOR(" );
- else
- fprintf( pFile, "EXOR(" );
+ fprintf( pFile, "EXOR(" );
for ( i = 0; i < pNode->nDecs; i++ )
{
pInput = Dsd_Regular( pNode->pDecs[i] );
fCompNew = (int)( pInput != pNode->pDecs[i] );
if ( i )
fprintf( pFile, "," );
+ if ( fCompNew )
+ fprintf( pFile, " NOT(" );
+ else
+ fprintf( pFile, " " );
if ( pInput->Type == DSD_NODE_BUF )
{
pInputNums[i] = 0;
- if ( fCompNew )
- fprintf( pFile, " NOT(" );
- else
- fprintf( pFile, " " );
if ( fShortNames )
- fprintf( pFile, "%d", pInput->S->index );
+ fprintf( pFile, "%c", 'a' + pInput->S->index );
else
fprintf( pFile, "%s", pInputNames[pInput->S->index] );
- if ( fCompNew )
- fprintf( pFile, ")" );
+ }
+ else
+ {
+ pInputNums[i] = (*pSigCounter)++;
+ fprintf( pFile, "<%d>", pInputNums[i] );
+ }
+ if ( fCompNew )
+ fprintf( pFile, ")" );
+ }
+ fprintf( pFile, " )\n" );
+ // call recursively for the following blocks
+ for ( i = 0; i < pNode->nDecs; i++ )
+ if ( pInputNums[i] )
+ {
+ pInput = Dsd_Regular( pNode->pDecs[i] );
+ sprintf( Buffer, "<%d>", pInputNums[i] );
+ Dsd_TreePrint_rec( pFile, Dsd_Regular( pNode->pDecs[i] ), 0, pInputNames, Buffer, nOffset + 6, pSigCounter, fShortNames );
+ }
+ }
+ free( pInputNums );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Prints the decompostion tree into file.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Dsd_NodePrint( FILE * pFile, Dsd_Node_t * pNode )
+{
+ Dsd_Node_t * pNodeR;
+ int SigCounter = 1;
+ pNodeR = Dsd_Regular(pNode);
+ Dsd_NodePrint_rec( pFile, pNodeR, pNodeR != pNode, "F", 0, &SigCounter );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Prints one node of the decomposition tree.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Dsd_NodePrint_rec( FILE * pFile, Dsd_Node_t * pNode, int fComp, char * pOutputName, int nOffset, int * pSigCounter )
+{
+ char Buffer[100];
+ Dsd_Node_t * pInput;
+ int * pInputNums;
+ int fCompNew, i;
+
+ assert( pNode->Type == DSD_NODE_BUF || pNode->Type == DSD_NODE_CONST1 ||
+ pNode->Type == DSD_NODE_PRIME || pNode->Type == DSD_NODE_OR || pNode->Type == DSD_NODE_EXOR );
+
+ Extra_PrintSymbols( pFile, ' ', nOffset, 0 );
+ if ( !fComp )
+ fprintf( pFile, "%s = ", pOutputName );
+ else
+ fprintf( pFile, "NOT(%s) = ", pOutputName );
+ pInputNums = ALLOC( int, pNode->nDecs );
+ if ( pNode->Type == DSD_NODE_CONST1 )
+ {
+ fprintf( pFile, " Constant 1.\n" );
+ }
+ else if ( pNode->Type == DSD_NODE_BUF )
+ {
+ fprintf( pFile, " " );
+ fprintf( pFile, "%c", 'a' + pNode->S->index );
+ fprintf( pFile, "\n" );
+ }
+ else if ( pNode->Type == DSD_NODE_PRIME )
+ {
+ // print the line
+ fprintf( pFile, "PRIME(" );
+ for ( i = 0; i < pNode->nDecs; i++ )
+ {
+ pInput = Dsd_Regular( pNode->pDecs[i] );
+ fCompNew = (int)( pInput != pNode->pDecs[i] );
+ assert( fCompNew == 0 );
+ if ( i )
+ fprintf( pFile, "," );
+ if ( pInput->Type == DSD_NODE_BUF )
+ {
+ pInputNums[i] = 0;
+ fprintf( pFile, " %c", 'a' + pInput->S->index );
+ }
+ else
+ {
+ pInputNums[i] = (*pSigCounter)++;
+ fprintf( pFile, " <%d>", pInputNums[i] );
+ }
+ if ( fCompNew )
+ fprintf( pFile, "\'" );
+ }
+ fprintf( pFile, " )\n" );
+/*
+ fprintf( pFile, " ) " );
+ {
+ DdNode * bLocal;
+ bLocal = Dsd_TreeGetPrimeFunction( dd, pNodeDsd ); Cudd_Ref( bLocal );
+ Extra_bddPrint( dd, bLocal );
+ Cudd_RecursiveDeref( dd, bLocal );
+ }
+*/
+ // call recursively for the following blocks
+ for ( i = 0; i < pNode->nDecs; i++ )
+ if ( pInputNums[i] )
+ {
+ pInput = Dsd_Regular( pNode->pDecs[i] );
+ sprintf( Buffer, "<%d>", pInputNums[i] );
+ Dsd_NodePrint_rec( pFile, Dsd_Regular( pNode->pDecs[i] ), 0, Buffer, nOffset + 6, pSigCounter );
+ }
+ }
+ else if ( pNode->Type == DSD_NODE_OR )
+ {
+ // print the line
+ fprintf( pFile, "OR(" );
+ for ( i = 0; i < pNode->nDecs; i++ )
+ {
+ pInput = Dsd_Regular( pNode->pDecs[i] );
+ fCompNew = (int)( pInput != pNode->pDecs[i] );
+ if ( i )
+ fprintf( pFile, "," );
+ if ( pInput->Type == DSD_NODE_BUF )
+ {
+ pInputNums[i] = 0;
+ fprintf( pFile, " %c", 'a' + pInput->S->index );
+ }
+ else
+ {
+ pInputNums[i] = (*pSigCounter)++;
+ fprintf( pFile, " <%d>", pInputNums[i] );
+ }
+ if ( fCompNew )
+ fprintf( pFile, "\'" );
+ }
+ fprintf( pFile, " )\n" );
+ // call recursively for the following blocks
+ for ( i = 0; i < pNode->nDecs; i++ )
+ if ( pInputNums[i] )
+ {
+ pInput = Dsd_Regular( pNode->pDecs[i] );
+ sprintf( Buffer, "<%d>", pInputNums[i] );
+ Dsd_NodePrint_rec( pFile, Dsd_Regular( pNode->pDecs[i] ), 0, Buffer, nOffset + 6, pSigCounter );
+ }
+ }
+ else if ( pNode->Type == DSD_NODE_EXOR )
+ {
+ // print the line
+ fprintf( pFile, "EXOR(" );
+ for ( i = 0; i < pNode->nDecs; i++ )
+ {
+ pInput = Dsd_Regular( pNode->pDecs[i] );
+ fCompNew = (int)( pInput != pNode->pDecs[i] );
+ assert( fCompNew == 0 );
+ if ( i )
+ fprintf( pFile, "," );
+ if ( pInput->Type == DSD_NODE_BUF )
+ {
+ pInputNums[i] = 0;
+ fprintf( pFile, " %c", 'a' + pInput->S->index );
}
else
{
pInputNums[i] = (*pSigCounter)++;
fprintf( pFile, " <%d>", pInputNums[i] );
}
+ if ( fCompNew )
+ fprintf( pFile, "\'" );
}
fprintf( pFile, " )\n" );
// call recursively for the following blocks
@@ -778,9 +985,8 @@ void Dsd_TreePrint_rec( FILE * pFile, Dsd_Node_t * pNode, int fComp, char * pInp
if ( pInputNums[i] )
{
pInput = Dsd_Regular( pNode->pDecs[i] );
- fCompNew = (int)( pInput != pNode->pDecs[i] );
sprintf( Buffer, "<%d>", pInputNums[i] );
- Dsd_TreePrint_rec( pFile, Dsd_Regular( pNode->pDecs[i] ), fCompNew, pInputNames, Buffer, nOffset + 6, pSigCounter, fShortNames );
+ Dsd_NodePrint_rec( pFile, Dsd_Regular( pNode->pDecs[i] ), 0, Buffer, nOffset + 6, pSigCounter );
}
}
free( pInputNums );
diff --git a/src/bdd/epd/epd.c b/src/bdd/epd/epd.c
index a843b986..a80240bc 100644
--- a/src/bdd/epd/epd.c
+++ b/src/bdd/epd/epd.c
@@ -25,7 +25,7 @@
#include <stdlib.h>
#include <string.h>
#include <math.h>
-#include "util.h"
+#include "util_hack.h"
#include "epd.h"
diff --git a/src/bdd/mtr/mtrBasic.c b/src/bdd/mtr/mtrBasic.c
index 2aec8d6b..94105282 100644
--- a/src/bdd/mtr/mtrBasic.c
+++ b/src/bdd/mtr/mtrBasic.c
@@ -33,7 +33,7 @@
******************************************************************************/
-#include "util.h"
+#include "util_hack.h"
#include "mtrInt.h"
diff --git a/src/bdd/mtr/mtrGroup.c b/src/bdd/mtr/mtrGroup.c
index ae9c5c2f..363b776b 100644
--- a/src/bdd/mtr/mtrGroup.c
+++ b/src/bdd/mtr/mtrGroup.c
@@ -33,7 +33,7 @@
******************************************************************************/
-#include "util.h"
+#include "util_hack.h"
#include "mtrInt.h"
/*---------------------------------------------------------------------------*/
diff --git a/src/bdd/parse/module.make b/src/bdd/parse/module.make
index ea535e6e..4f590f01 100644
--- a/src/bdd/parse/module.make
+++ b/src/bdd/parse/module.make
@@ -1,2 +1,3 @@
SRC += src/bdd/parse/parseCore.c \
+ src/bdd/parse/parseEqn.c \
src/bdd/parse/parseStack.c
diff --git a/src/bdd/parse/parse.h b/src/bdd/parse/parse.h
index 8364e782..4923fbdd 100644
--- a/src/bdd/parse/parse.h
+++ b/src/bdd/parse/parse.h
@@ -36,18 +36,19 @@
////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////
-/// MACRO DEFITIONS ///
+/// MACRO DEFINITIONS ///
////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////
-/// FUNCTION DEFITIONS ///
+/// FUNCTION DEFINITIONS ///
////////////////////////////////////////////////////////////////////////
/*=== parseCore.c =============================================================*/
extern DdNode * Parse_FormulaParser( FILE * pOutput, char * pFormula, int nVars, int nRanks,
char * ppVarNames[], DdManager * dd, DdNode * pbVars[] );
+#endif
+
////////////////////////////////////////////////////////////////////////
/// END OF FILE ///
////////////////////////////////////////////////////////////////////////
-#endif
diff --git a/src/bdd/parse/parseCore.c b/src/bdd/parse/parseCore.c
index d60687a3..21a37070 100644
--- a/src/bdd/parse/parseCore.c
+++ b/src/bdd/parse/parseCore.c
@@ -89,7 +89,7 @@
static DdNode * Parse_ParserPerformTopOp( DdManager * dd, Parse_StackFn_t * pStackFn, int Oper );
////////////////////////////////////////////////////////////////////////
-/// FUNCTION DEFITIONS ///
+/// FUNCTION DEFINITIONS ///
////////////////////////////////////////////////////////////////////////
/**Function*************************************************************
diff --git a/src/bdd/parse/parseEqn.c b/src/bdd/parse/parseEqn.c
new file mode 100644
index 00000000..02d83966
--- /dev/null
+++ b/src/bdd/parse/parseEqn.c
@@ -0,0 +1,349 @@
+/**CFile****************************************************************
+
+ FileNameIn [parseEqn.c]
+
+ PackageName [ABC: Logic synthesis and verification system.]
+
+ Synopsis [Boolean formula parser.]
+
+ Author [Alan Mishchenko]
+
+ Affiliation [UC Berkeley]
+
+ Date [Ver. 1.0. Started - December 18, 2006.]
+
+ Revision [$Id: parseEqn.c,v 1.0 2006/12/18 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+
+////////////////////////////////////////////////////////////////////////
+/// DECLARATIONS ///
+////////////////////////////////////////////////////////////////////////
+
+#include "parseInt.h"
+#include "vec.h"
+#include "hop.h"
+
+// the list of operation symbols to be used in expressions
+#define PARSE_EQN_SYM_OPEN '(' // opening paranthesis
+#define PARSE_EQN_SYM_CLOSE ')' // closing paranthesis
+#define PARSE_EQN_SYM_CONST0 '0' // constant 0
+#define PARSE_EQN_SYM_CONST1 '1' // constant 1
+#define PARSE_EQN_SYM_NEG '!' // negation before the variable
+#define PARSE_EQN_SYM_AND '*' // logic AND
+#define PARSE_EQN_SYM_OR '+' // logic OR
+
+// the list of opcodes (also specifying operation precedence)
+#define PARSE_EQN_OPER_NEG 10 // negation
+#define PARSE_EQN_OPER_AND 9 // logic AND
+#define PARSE_EQN_OPER_OR 7 // logic OR
+#define PARSE_EQN_OPER_MARK 1 // OpStack token standing for an opening paranthesis
+
+// these are values of the internal Flag
+#define PARSE_EQN_FLAG_START 1 // after the opening parenthesis
+#define PARSE_EQN_FLAG_VAR 2 // after operation is received
+#define PARSE_EQN_FLAG_OPER 3 // after operation symbol is received
+#define PARSE_EQN_FLAG_ERROR 4 // when error is detected
+
+#define PARSE_EQN_STACKSIZE 1000
+
+static Hop_Obj_t * Parse_ParserPerformTopOp( Hop_Man_t * pMan, Parse_StackFn_t * pStackFn, int Oper );
+
+////////////////////////////////////////////////////////////////////////
+/// FUNCTION DEFINITIONS ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+ Synopsis [Derives the AIG corresponding to the equation.]
+
+ Description [Takes the stream to output messages, the formula, the vector
+ of variable names and the AIG manager.]
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Hop_Obj_t * Parse_FormulaParserEqn( FILE * pOutput, char * pFormInit, Vec_Ptr_t * vVarNames, Hop_Man_t * pMan )
+{
+ char * pFormula;
+ Parse_StackFn_t * pStackFn;
+ Parse_StackOp_t * pStackOp;
+ Hop_Obj_t * gFunc;
+ char * pTemp, * pName;
+ int nParans, fFound, Flag;
+ int Oper, Oper1, Oper2;
+ int i, v;
+
+ // make sure that the number of opening and closing parantheses is the same
+ nParans = 0;
+ for ( pTemp = pFormInit; *pTemp; pTemp++ )
+ if ( *pTemp == '(' )
+ nParans++;
+ else if ( *pTemp == ')' )
+ nParans--;
+ if ( nParans != 0 )
+ {
+ fprintf( pOutput, "Parse_FormulaParserEqn(): Different number of opening and closing parantheses ().\n" );
+ return NULL;
+ }
+
+ // copy the formula
+ pFormula = ALLOC( char, strlen(pFormInit) + 3 );
+ sprintf( pFormula, "(%s)", pFormInit );
+
+ // start the stacks
+ pStackFn = Parse_StackFnStart( PARSE_EQN_STACKSIZE );
+ pStackOp = Parse_StackOpStart( PARSE_EQN_STACKSIZE );
+
+ Flag = PARSE_EQN_FLAG_START;
+ for ( pTemp = pFormula; *pTemp; pTemp++ )
+ {
+ switch ( *pTemp )
+ {
+ // skip all spaces, tabs, and end-of-lines
+ case ' ':
+ case '\t':
+ case '\r':
+ case '\n':
+ continue;
+ case PARSE_EQN_SYM_CONST0:
+ Parse_StackFnPush( pStackFn, Hop_ManConst0(pMan) ); // Cudd_Ref( b0 );
+ if ( Flag == PARSE_EQN_FLAG_VAR )
+ {
+ fprintf( pOutput, "Parse_FormulaParserEqn(): No operation symbol before constant 0.\n" );
+ Flag = PARSE_EQN_FLAG_ERROR;
+ break;
+ }
+ Flag = PARSE_EQN_FLAG_VAR;
+ break;
+ case PARSE_EQN_SYM_CONST1:
+ Parse_StackFnPush( pStackFn, Hop_ManConst1(pMan) ); // Cudd_Ref( b1 );
+ if ( Flag == PARSE_EQN_FLAG_VAR )
+ {
+ fprintf( pOutput, "Parse_FormulaParserEqn(): No operation symbol before constant 1.\n" );
+ Flag = PARSE_EQN_FLAG_ERROR;
+ break;
+ }
+ Flag = PARSE_EQN_FLAG_VAR;
+ break;
+ case PARSE_EQN_SYM_NEG:
+ if ( Flag == PARSE_EQN_FLAG_VAR )
+ {// if NEGBEF follows a variable, AND is assumed
+ Parse_StackOpPush( pStackOp, PARSE_EQN_OPER_AND );
+ Flag = PARSE_EQN_FLAG_OPER;
+ }
+ Parse_StackOpPush( pStackOp, PARSE_EQN_OPER_NEG );
+ break;
+ case PARSE_EQN_SYM_AND:
+ case PARSE_EQN_SYM_OR:
+ if ( Flag != PARSE_EQN_FLAG_VAR )
+ {
+ fprintf( pOutput, "Parse_FormulaParserEqn(): There is no variable before AND, EXOR, or OR.\n" );
+ Flag = PARSE_EQN_FLAG_ERROR;
+ break;
+ }
+ if ( *pTemp == PARSE_EQN_SYM_AND )
+ Parse_StackOpPush( pStackOp, PARSE_EQN_OPER_AND );
+ else //if ( *pTemp == PARSE_EQN_SYM_OR )
+ Parse_StackOpPush( pStackOp, PARSE_EQN_OPER_OR );
+ Flag = PARSE_EQN_FLAG_OPER;
+ break;
+ case PARSE_EQN_SYM_OPEN:
+ if ( Flag == PARSE_EQN_FLAG_VAR )
+ {
+// Parse_StackOpPush( pStackOp, PARSE_EQN_OPER_AND );
+ fprintf( pOutput, "Parse_FormulaParserEqn(): An opening paranthesis follows a var without operation sign.\n" );
+ Flag = PARSE_EQN_FLAG_ERROR;
+ break;
+ }
+ Parse_StackOpPush( pStackOp, PARSE_EQN_OPER_MARK );
+ // after an opening bracket, it feels like starting over again
+ Flag = PARSE_EQN_FLAG_START;
+ break;
+ case PARSE_EQN_SYM_CLOSE:
+ if ( !Parse_StackOpIsEmpty( pStackOp ) )
+ {
+ while ( 1 )
+ {
+ if ( Parse_StackOpIsEmpty( pStackOp ) )
+ {
+ fprintf( pOutput, "Parse_FormulaParserEqn(): There is no opening paranthesis\n" );
+ Flag = PARSE_EQN_FLAG_ERROR;
+ break;
+ }
+ Oper = Parse_StackOpPop( pStackOp );
+ if ( Oper == PARSE_EQN_OPER_MARK )
+ break;
+
+ // perform the given operation
+ if ( Parse_ParserPerformTopOp( pMan, pStackFn, Oper ) == NULL )
+ {
+ fprintf( pOutput, "Parse_FormulaParserEqn(): Unknown operation\n" );
+ free( pFormula );
+ return NULL;
+ }
+ }
+ }
+ else
+ {
+ fprintf( pOutput, "Parse_FormulaParserEqn(): There is no opening paranthesis\n" );
+ Flag = PARSE_EQN_FLAG_ERROR;
+ break;
+ }
+ if ( Flag != PARSE_EQN_FLAG_ERROR )
+ Flag = PARSE_EQN_FLAG_VAR;
+ break;
+
+
+ default:
+ // scan the next name
+ for ( i = 0; pTemp[i] &&
+ pTemp[i] != ' ' && pTemp[i] != '\t' && pTemp[i] != '\r' && pTemp[i] != '\n' &&
+ pTemp[i] != PARSE_EQN_SYM_AND && pTemp[i] != PARSE_EQN_SYM_OR && pTemp[i] != PARSE_EQN_SYM_CLOSE; i++ )
+ {
+ if ( pTemp[i] == PARSE_EQN_SYM_NEG || pTemp[i] == PARSE_EQN_SYM_OPEN )
+ {
+ fprintf( pOutput, "Parse_FormulaParserEqn(): The negation sign or an opening paranthesis inside the variable name.\n" );
+ Flag = PARSE_EQN_FLAG_ERROR;
+ break;
+ }
+ }
+ // variable name is found
+ fFound = 0;
+ Vec_PtrForEachEntry( vVarNames, pName, v )
+ if ( strncmp(pTemp, pName, i) == 0 && strlen(pName) == (unsigned)i )
+ {
+ pTemp += i-1;
+ fFound = 1;
+ break;
+ }
+ if ( !fFound )
+ {
+ fprintf( pOutput, "Parse_FormulaParserEqn(): The parser cannot find var \"%s\" in the input var list.\n", pTemp );
+ Flag = PARSE_EQN_FLAG_ERROR;
+ break;
+ }
+ if ( Flag == PARSE_EQN_FLAG_VAR )
+ {
+ fprintf( pOutput, "Parse_FormulaParserEqn(): The variable name \"%s\" follows another var without operation sign.\n", pTemp );
+ Flag = PARSE_EQN_FLAG_ERROR;
+ break;
+ }
+ Parse_StackFnPush( pStackFn, Hop_IthVar( pMan, v ) ); // Cudd_Ref( pbVars[v] );
+ Flag = PARSE_EQN_FLAG_VAR;
+ break;
+ }
+
+ if ( Flag == PARSE_EQN_FLAG_ERROR )
+ break; // error exit
+ else if ( Flag == PARSE_EQN_FLAG_START )
+ continue; // go on parsing
+ else if ( Flag == PARSE_EQN_FLAG_VAR )
+ while ( 1 )
+ { // check if there are negations in the OpStack
+ if ( Parse_StackOpIsEmpty(pStackOp) )
+ break;
+ Oper = Parse_StackOpPop( pStackOp );
+ if ( Oper != PARSE_EQN_OPER_NEG )
+ {
+ Parse_StackOpPush( pStackOp, Oper );
+ break;
+ }
+ else
+ {
+ Parse_StackFnPush( pStackFn, Hop_Not(Parse_StackFnPop(pStackFn)) );
+ }
+ }
+ else // if ( Flag == PARSE_EQN_FLAG_OPER )
+ while ( 1 )
+ { // execute all the operations in the OpStack
+ // with precedence higher or equal than the last one
+ Oper1 = Parse_StackOpPop( pStackOp ); // the last operation
+ if ( Parse_StackOpIsEmpty(pStackOp) )
+ { // if it is the only operation, push it back
+ Parse_StackOpPush( pStackOp, Oper1 );
+ break;
+ }
+ Oper2 = Parse_StackOpPop( pStackOp ); // the operation before the last one
+ if ( Oper2 >= Oper1 )
+ { // if Oper2 precedence is higher or equal, execute it
+ if ( Parse_ParserPerformTopOp( pMan, pStackFn, Oper2 ) == NULL )
+ {
+ fprintf( pOutput, "Parse_FormulaParserEqn(): Unknown operation\n" );
+ free( pFormula );
+ return NULL;
+ }
+ Parse_StackOpPush( pStackOp, Oper1 ); // push the last operation back
+ }
+ else
+ { // if Oper2 precedence is lower, push them back and done
+ Parse_StackOpPush( pStackOp, Oper2 );
+ Parse_StackOpPush( pStackOp, Oper1 );
+ break;
+ }
+ }
+ }
+
+ if ( Flag != PARSE_EQN_FLAG_ERROR )
+ {
+ if ( !Parse_StackFnIsEmpty(pStackFn) )
+ {
+ gFunc = Parse_StackFnPop(pStackFn);
+ if ( Parse_StackFnIsEmpty(pStackFn) )
+ if ( Parse_StackOpIsEmpty(pStackOp) )
+ {
+ Parse_StackFnFree(pStackFn);
+ Parse_StackOpFree(pStackOp);
+// Cudd_Deref( gFunc );
+ free( pFormula );
+ return gFunc;
+ }
+ else
+ fprintf( pOutput, "Parse_FormulaParserEqn(): Something is left in the operation stack\n" );
+ else
+ fprintf( pOutput, "Parse_FormulaParserEqn(): Something is left in the function stack\n" );
+ }
+ else
+ fprintf( pOutput, "Parse_FormulaParserEqn(): The input string is empty\n" );
+ }
+ free( pFormula );
+ return NULL;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Performs the operation on the top entries in the stack.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Hop_Obj_t * Parse_ParserPerformTopOp( Hop_Man_t * pMan, Parse_StackFn_t * pStackFn, int Oper )
+{
+ Hop_Obj_t * gArg1, * gArg2, * gFunc;
+ // perform the given operation
+ gArg2 = Parse_StackFnPop( pStackFn );
+ gArg1 = Parse_StackFnPop( pStackFn );
+ if ( Oper == PARSE_EQN_OPER_AND )
+ gFunc = Hop_And( pMan, gArg1, gArg2 );
+ else if ( Oper == PARSE_EQN_OPER_OR )
+ gFunc = Hop_Or( pMan, gArg1, gArg2 );
+ else
+ return NULL;
+// Cudd_Ref( gFunc );
+// Cudd_RecursiveDeref( dd, gArg1 );
+// Cudd_RecursiveDeref( dd, gArg2 );
+ Parse_StackFnPush( pStackFn, gFunc );
+ return gFunc;
+}
+
+
+////////////////////////////////////////////////////////////////////////
+/// END OF FILE ///
+////////////////////////////////////////////////////////////////////////
diff --git a/src/bdd/parse/parseInt.h b/src/bdd/parse/parseInt.h
index 6e6c49b0..17f48375 100644
--- a/src/bdd/parse/parseInt.h
+++ b/src/bdd/parse/parseInt.h
@@ -47,18 +47,18 @@ typedef struct ParseStackOpStruct Parse_StackOp_t; // the operation stack
////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////
-/// MACRO DEFITIONS ///
+/// MACRO DEFINITIONS ///
////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////
-/// FUNCTION DEFITIONS ///
+/// FUNCTION DEFINITIONS ///
////////////////////////////////////////////////////////////////////////
/*=== parseStack.c =============================================================*/
extern Parse_StackFn_t * Parse_StackFnStart ( int nDepth );
extern bool Parse_StackFnIsEmpty( Parse_StackFn_t * p );
-extern void Parse_StackFnPush ( Parse_StackFn_t * p, DdNode * bFunc );
-extern DdNode * Parse_StackFnPop ( Parse_StackFn_t * p );
+extern void Parse_StackFnPush ( Parse_StackFn_t * p, void * bFunc );
+extern void * Parse_StackFnPop ( Parse_StackFn_t * p );
extern void Parse_StackFnFree ( Parse_StackFn_t * p );
extern Parse_StackOp_t * Parse_StackOpStart ( int nDepth );
@@ -67,7 +67,8 @@ extern void Parse_StackOpPush ( Parse_StackOp_t * p, int Oper );
extern int Parse_StackOpPop ( Parse_StackOp_t * p );
extern void Parse_StackOpFree ( Parse_StackOp_t * p );
+#endif
+
////////////////////////////////////////////////////////////////////////
/// END OF FILE ///
////////////////////////////////////////////////////////////////////////
-#endif
diff --git a/src/bdd/parse/parseStack.c b/src/bdd/parse/parseStack.c
index 8329070e..cd7cd7e3 100644
--- a/src/bdd/parse/parseStack.c
+++ b/src/bdd/parse/parseStack.c
@@ -24,7 +24,7 @@
struct ParseStackFnStruct
{
- DdNode ** pData; // the array of elements
+ void ** pData; // the array of elements
int Top; // the index
int Size; // the stack size
};
@@ -37,7 +37,7 @@ struct ParseStackOpStruct
};
////////////////////////////////////////////////////////////////////////
-/// FUNCTION DEFITIONS ///
+/// FUNCTION DEFINITIONS ///
////////////////////////////////////////////////////////////////////////
/**Function*************************************************************
@@ -56,7 +56,7 @@ Parse_StackFn_t * Parse_StackFnStart( int nDepth )
Parse_StackFn_t * p;
p = ALLOC( Parse_StackFn_t, 1 );
memset( p, 0, sizeof(Parse_StackFn_t) );
- p->pData = ALLOC( DdNode *, nDepth );
+ p->pData = ALLOC( void *, nDepth );
p->Size = nDepth;
return p;
}
@@ -88,7 +88,7 @@ bool Parse_StackFnIsEmpty( Parse_StackFn_t * p )
SeeAlso []
***********************************************************************/
-void Parse_StackFnPush( Parse_StackFn_t * p, DdNode * bFunc )
+void Parse_StackFnPush( Parse_StackFn_t * p, void * bFunc )
{
if ( p->Top >= p->Size )
{
@@ -109,7 +109,7 @@ void Parse_StackFnPush( Parse_StackFn_t * p, DdNode * bFunc )
SeeAlso []
***********************************************************************/
-DdNode * Parse_StackFnPop( Parse_StackFn_t * p )
+void * Parse_StackFnPop( Parse_StackFn_t * p )
{
if ( p->Top == 0 )
{
diff --git a/src/bdd/reo/module.make b/src/bdd/reo/module.make
index 7eb41e0e..3a636980 100644
--- a/src/bdd/reo/module.make
+++ b/src/bdd/reo/module.make
@@ -1,6 +1,7 @@
SRC += src/bdd/reo/reoApi.c \
src/bdd/reo/reoCore.c \
src/bdd/reo/reoProfile.c \
+ src/bdd/reo/reoShuffle.c \
src/bdd/reo/reoSift.c \
src/bdd/reo/reoSwap.c \
src/bdd/reo/reoTransfer.c \
diff --git a/src/bdd/reo/reo.h b/src/bdd/reo/reo.h
index 7e4be855..1a31242a 100644
--- a/src/bdd/reo/reo.h
+++ b/src/bdd/reo/reo.h
@@ -19,10 +19,16 @@
#ifndef __REO_H__
#define __REO_H__
+#ifdef __cplusplus
+extern "C" {
+#endif
+
#include <stdio.h>
#include <stdlib.h>
#include "extra.h"
+//#pragma warning( disable : 4514 )
+
////////////////////////////////////////////////////////////////////////
/// MACRO DEFINITIONS ///
////////////////////////////////////////////////////////////////////////
@@ -87,9 +93,9 @@ struct _reo_plane
struct _reo_hash
{
int Sign; // signature of the current cache operation
- unsigned Arg1; // the first argument
- unsigned Arg2; // the second argument
- unsigned Arg3; // the second argument
+ reo_unit * Arg1; // the first argument
+ reo_unit * Arg2; // the second argument
+ reo_unit * Arg3; // the third argument
};
struct _reo_man
@@ -166,8 +172,8 @@ struct _reo_man
// used to manipulate units
#define Unit_Regular(u) ((reo_unit *)((unsigned long)(u) & ~01))
-#define Unit_Not(u) ((reo_unit *)((long)(u) ^ 01))
-#define Unit_NotCond(u,c) ((reo_unit *)((long)(u) ^ (c)))
+#define Unit_Not(u) ((reo_unit *)((unsigned long)(u) ^ 01))
+#define Unit_NotCond(u,c) ((reo_unit *)((unsigned long)(u) ^ (c)))
#define Unit_IsConstant(u) ((int)((u)->lev == REO_CONST_LEVEL))
////////////////////////////////////////////////////////////////////////
@@ -215,8 +221,12 @@ extern DdNode * Extra_ReorderCudd( DdManager * dd, DdNode * aFunc, int pPermut
extern int Extra_bddReorderTest( DdManager * dd, DdNode * bF );
extern int Extra_addReorderTest( DdManager * dd, DdNode * aF );
+#ifdef __cplusplus
+}
+#endif
+
+#endif
+
////////////////////////////////////////////////////////////////////////
/// END OF FILE ///
////////////////////////////////////////////////////////////////////////
-
-#endif
diff --git a/src/bdd/reo/reoProfile.c b/src/bdd/reo/reoProfile.c
index b38575f0..84a0bc19 100644
--- a/src/bdd/reo/reoProfile.c
+++ b/src/bdd/reo/reoProfile.c
@@ -330,7 +330,7 @@ void reoProfileWidthPrint( reo_man * p )
WidthMax = p->pPlanes[i].statsWidth;
TotalWidth += p->pPlanes[i].statsWidth;
}
- assert( p->nWidthCur = TotalWidth );
+ assert( p->nWidthCur == TotalWidth );
printf( "WIDTH: " );
printf( "Maximum = %5d. ", WidthMax );
printf( "Total = %7d. ", p->nWidthCur );
diff --git a/src/bdd/reo/reoShuffle.c b/src/bdd/reo/reoShuffle.c
new file mode 100644
index 00000000..8dab67a4
--- /dev/null
+++ b/src/bdd/reo/reoShuffle.c
@@ -0,0 +1,224 @@
+/**CFile****************************************************************
+
+ FileName [reoShuffle.c]
+
+ PackageName [REO: A specialized DD reordering engine.]
+
+ Synopsis [Implementation of the two-variable swap.]
+
+ Author [Alan Mishchenko]
+
+ Affiliation [UC Berkeley]
+
+ Date [Ver. 1.0. Started - October 15, 2002.]
+
+ Revision [$Id: reoShuffle.c,v 1.0 2002/15/10 03:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "reo.h"
+
+////////////////////////////////////////////////////////////////////////
+/// DECLARATIONS ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+/// FUNCTION DEFINITIONS ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+ Synopsis [This procedure is similar to Cudd_ShuffleHeap() and Cudd_bddPermute().]
+
+ Description [The first argument is the REO manager. The 2nd/3d
+ arguments are the function and its CUDD manager. The last argument
+ is the permutation to be implemented. The i-th entry of the permutation
+ array contains the index of the variable that should be brought to the
+ i-th level. The size of the array should be equal or greater to
+ the number of variables currently in use (that is, the size of CUDD
+ manager and the size of REO manager).]
+
+ SideEffects [Note that the resulting BDD is not referenced.]
+
+ SeeAlso []
+
+***********************************************************************/
+DdNode * reoShuffle( reo_man * p, DdManager * dd, DdNode * bFunc, int * pPerm, int * pPermInv )
+{
+ DdNode * bFuncRes = NULL;
+ int i, k, v;
+
+ if ( Cudd_IsConstant(bFunc) )
+ return bFunc;
+
+ // set the initial parameters
+ p->dd = dd;
+ p->nSupp = Cudd_SupportSize( dd, bFunc );
+ p->nTops = 1;
+// p->nNodesBeg = Cudd_DagSize( bFunc );
+
+ // set the starting permutation
+ for ( i = 0; i < p->nSupp; i++ )
+ {
+ p->pOrderInt[i] = i;
+ p->pMapToPlanes[ dd->invperm[i] ] = i;
+ p->pMapToDdVarsFinal[i] = dd->invperm[i];
+ }
+
+ // set the initial parameters
+ p->nUnitsUsed = 0;
+ p->nNodesCur = 0;
+ p->fThisIsAdd = 0;
+ p->Signature++;
+
+ // transfer the function from the CUDD package into REO's internal data structure
+ p->pTops[0] = reoTransferNodesToUnits_rec( p, bFunc );
+// assert( p->nNodesBeg == p->nNodesCur );
+
+ // reorder one variable at a time
+ for ( i = 0; i < p->nSupp; i++ )
+ {
+ if ( p->pOrderInt[i] == pPerm[i] )
+ continue;
+ // find where is variable number pPerm[i]
+ for ( k = i + 1; k < p->nSupp; k++ )
+ if ( pPerm[i] == p->pOrderInt[k] )
+ break;
+ if ( k == p->nSupp )
+ {
+ printf( "reoShuffle() Error: Cannot find a variable.\n" );
+ goto finish;
+ }
+ // move the variable up
+ for ( v = k - 1; v >= i; v-- )
+ {
+ reoReorderSwapAdjacentVars( p, v, 1 );
+ // check if the number of nodes is not too large
+ if ( p->nNodesCur > 10000 )
+ {
+ printf( "reoShuffle() Error: BDD size is too large.\n" );
+ goto finish;
+ }
+ }
+ assert( p->pOrderInt[i] == pPerm[i] );
+ }
+
+ // set the initial parameters
+ p->nRefNodes = 0;
+ p->nNodesCur = 0;
+ p->Signature++;
+ // transfer the BDDs from REO's internal data structure to CUDD
+ bFuncRes = reoTransferUnitsToNodes_rec( p, p->pTops[0] ); Cudd_Ref( bFuncRes );
+ // undo the DDs referenced for storing in the cache
+ for ( i = 0; i < p->nRefNodes; i++ )
+ Cudd_RecursiveDeref( dd, p->pRefNodes[i] );
+
+ // verify zero refs of the terminal nodes
+// assert( reoRecursiveDeref( p->pTops[0] ) );
+// assert( reoCheckZeroRefs( &(p->pPlanes[p->nSupp]) ) );
+
+ // perform verification
+ if ( p->fVerify )
+ {
+ DdNode * bFuncPerm;
+ bFuncPerm = Cudd_bddPermute( dd, bFunc, pPermInv ); Cudd_Ref( bFuncPerm );
+ if ( bFuncPerm != bFuncRes )
+ {
+ printf( "REO: Internal verification has failed!\n" );
+ fflush( stdout );
+ }
+ Cudd_RecursiveDeref( dd, bFuncPerm );
+ }
+
+ // recycle the data structure
+ for ( i = 0; i <= p->nSupp; i++ )
+ reoUnitsRecycleUnitList( p, p->pPlanes + i );
+
+finish :
+ if ( bFuncRes )
+ Cudd_Deref( bFuncRes );
+ return bFuncRes;
+}
+
+
+
+/**Function*************************************************************
+
+ Synopsis [Reorders the DD using REO and CUDD.]
+
+ Description [This function can be used to test the performance of the reordering package.]
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Extra_ShuffleTest( reo_man * pReo, DdManager * dd, DdNode * Func )
+{
+// extern int runtime1, runtime2;
+
+ DdNode * Temp, * bRemap;
+ int nSuppSize, OffSet, Num, i, clk;
+ int pOrder[1000], pOrderInv[1000];
+ assert( dd->size < 1000 );
+
+ srand( 0x12341234 );
+ nSuppSize = Cudd_SupportSize( dd, Func );
+ if ( nSuppSize < 2 )
+ return;
+
+ for ( i = 0; i < nSuppSize; i++ )
+ pOrder[i] = i;
+ for ( i = 0; i < 120; i++ )
+ {
+ OffSet = rand() % (nSuppSize - 1);
+ Num = pOrder[OffSet];
+ pOrder[OffSet] = pOrder[OffSet+1];
+ pOrder[OffSet+1] = Num;
+ }
+ for ( i = 0; i < nSuppSize; i++ )
+ pOrderInv[pOrder[i]] = i;
+
+/*
+ printf( "Permutation: " );
+ for ( i = 0; i < nSuppSize; i++ )
+ printf( "%d ", pOrder[i] );
+ printf( "\n" );
+ printf( "Inverse permutation: " );
+ for ( i = 0; i < nSuppSize; i++ )
+ printf( "%d ", pOrderInv[i] );
+ printf( "\n" );
+*/
+
+ // create permutation
+// Extra_ReorderSetVerification( pReo, 1 );
+ bRemap = Extra_bddRemapUp( dd, Func ); Cudd_Ref( bRemap );
+
+clk = clock();
+ Temp = reoShuffle( pReo, dd, bRemap, pOrder, pOrderInv ); Cudd_Ref( Temp );
+//runtime1 += clock() - clk;
+
+//printf( "Initial = %d. Final = %d.\n", Cudd_DagSize(bRemap), Cudd_DagSize(Temp) );
+
+ {
+ DdNode * bFuncPerm;
+clk = clock();
+ bFuncPerm = Cudd_bddPermute( dd, bRemap, pOrderInv ); Cudd_Ref( bFuncPerm );
+//runtime2 += clock() - clk;
+ if ( bFuncPerm != Temp )
+ {
+ printf( "REO: Internal verification has failed!\n" );
+ fflush( stdout );
+ }
+ Cudd_RecursiveDeref( dd, bFuncPerm );
+ }
+
+ Cudd_RecursiveDeref( dd, Temp );
+ Cudd_RecursiveDeref( dd, bRemap );
+}
+
+
+////////////////////////////////////////////////////////////////////////
+/// END OF FILE ///
+////////////////////////////////////////////////////////////////////////
+
diff --git a/src/bdd/reo/reoSwap.c b/src/bdd/reo/reoSwap.c
index cb730d8e..4afa650c 100644
--- a/src/bdd/reo/reoSwap.c
+++ b/src/bdd/reo/reoSwap.c
@@ -271,9 +271,9 @@ double reoReorderSwapAdjacentVars( reo_man * p, int lev0, int fMovingUp )
HKey = (HKey+1) % p->nTableSize );
assert( p->HTable[HKey].Sign != p->Signature );
p->HTable[HKey].Sign = p->Signature;
- p->HTable[HKey].Arg1 = (unsigned)pUnitE;
- p->HTable[HKey].Arg2 = (unsigned)pUnitT;
- p->HTable[HKey].Arg3 = (unsigned)pUnit;
+ p->HTable[HKey].Arg1 = pUnitE;
+ p->HTable[HKey].Arg2 = pUnitT;
+ p->HTable[HKey].Arg3 = pUnit;
nNodesUpMovedDown++;
@@ -512,10 +512,10 @@ double reoReorderSwapAdjacentVars( reo_man * p, int lev0, int fMovingUp )
for ( HKey = hashKey3(p->Signature, pNew1E, pNew1T, p->nTableSize);
p->HTable[HKey].Sign == p->Signature;
HKey = (HKey+1) % p->nTableSize )
- if ( p->HTable[HKey].Arg1 == (unsigned)pNew1E && p->HTable[HKey].Arg2 == (unsigned)pNew1T )
+ if ( p->HTable[HKey].Arg1 == pNew1E && p->HTable[HKey].Arg2 == pNew1T )
{ // the entry is present
// assign this entry
- pNewPlane20 = (reo_unit *)p->HTable[HKey].Arg3;
+ pNewPlane20 = p->HTable[HKey].Arg3;
assert( pNewPlane20->lev == lev1 );
fFound = 1;
p->HashSuccess++;
@@ -549,9 +549,9 @@ double reoReorderSwapAdjacentVars( reo_man * p, int lev0, int fMovingUp )
// add this entry to cache
assert( p->HTable[HKey].Sign != p->Signature );
p->HTable[HKey].Sign = p->Signature;
- p->HTable[HKey].Arg1 = (unsigned)pNew1E;
- p->HTable[HKey].Arg2 = (unsigned)pNew1T;
- p->HTable[HKey].Arg3 = (unsigned)pNewPlane20;
+ p->HTable[HKey].Arg1 = pNew1E;
+ p->HTable[HKey].Arg2 = pNew1T;
+ p->HTable[HKey].Arg3 = pNewPlane20;
nNodesUnrefAdded++;
@@ -637,10 +637,10 @@ double reoReorderSwapAdjacentVars( reo_man * p, int lev0, int fMovingUp )
for ( HKey = hashKey3(p->Signature, pNew2E, pNew2T, p->nTableSize);
p->HTable[HKey].Sign == p->Signature;
HKey = (HKey+1) % p->nTableSize )
- if ( p->HTable[HKey].Arg1 == (unsigned)pNew2E && p->HTable[HKey].Arg2 == (unsigned)pNew2T )
+ if ( p->HTable[HKey].Arg1 == pNew2E && p->HTable[HKey].Arg2 == pNew2T )
{ // the entry is present
// assign this entry
- pNewPlane21 = (reo_unit *)p->HTable[HKey].Arg3;
+ pNewPlane21 = p->HTable[HKey].Arg3;
assert( pNewPlane21->lev == lev1 );
fFound = 1;
p->HashSuccess++;
@@ -675,9 +675,9 @@ double reoReorderSwapAdjacentVars( reo_man * p, int lev0, int fMovingUp )
// add this entry to cache
assert( p->HTable[HKey].Sign != p->Signature );
p->HTable[HKey].Sign = p->Signature;
- p->HTable[HKey].Arg1 = (unsigned)pNew2E;
- p->HTable[HKey].Arg2 = (unsigned)pNew2T;
- p->HTable[HKey].Arg3 = (unsigned)pNewPlane21;
+ p->HTable[HKey].Arg1 = pNew2E;
+ p->HTable[HKey].Arg2 = pNew2T;
+ p->HTable[HKey].Arg3 = pNewPlane21;
nNodesUnrefAdded++;
diff --git a/src/bdd/reo/reoTransfer.c b/src/bdd/reo/reoTransfer.c
index 752cd3d7..65d31d01 100644
--- a/src/bdd/reo/reoTransfer.c
+++ b/src/bdd/reo/reoTransfer.c
@@ -51,9 +51,9 @@ reo_unit * reoTransferNodesToUnits_rec( reo_man * p, DdNode * F )
{
// search cache - use linear probing
for ( HKey = hashKey2(p->Signature,F,p->nTableSize); p->HTable[HKey].Sign == p->Signature; HKey = (HKey+1) % p->nTableSize )
- if ( p->HTable[HKey].Arg1 == (unsigned)F )
+ if ( p->HTable[HKey].Arg1 == (reo_unit *)F )
{
- pUnit = (reo_unit*) p->HTable[HKey].Arg2;
+ pUnit = p->HTable[HKey].Arg2;
assert( pUnit );
// increment the edge counter
pUnit->n++;
@@ -93,8 +93,8 @@ reo_unit * reoTransferNodesToUnits_rec( reo_man * p, DdNode * F )
// might have been used. Make sure that its signature is different.
for ( ; p->HTable[HKey].Sign == p->Signature; HKey = (HKey+1) % p->nTableSize );
p->HTable[HKey].Sign = p->Signature;
- p->HTable[HKey].Arg1 = (unsigned)F;
- p->HTable[HKey].Arg2 = (unsigned)pUnit;
+ p->HTable[HKey].Arg1 = (reo_unit *)F;
+ p->HTable[HKey].Arg2 = pUnit;
}
// increment the counter of nodes
@@ -126,7 +126,7 @@ DdNode * reoTransferUnitsToNodes_rec( reo_man * p, reo_unit * pUnit )
if ( pUnit->n != 1 )
{
for ( HKey = hashKey2(p->Signature,pUnit,p->nTableSize); p->HTable[HKey].Sign == p->Signature; HKey = (HKey+1) % p->nTableSize )
- if ( p->HTable[HKey].Arg1 == (unsigned)pUnit )
+ if ( p->HTable[HKey].Arg1 == pUnit )
{
bRes = (DdNode*) p->HTable[HKey].Arg2;
assert( bRes );
@@ -179,8 +179,8 @@ DdNode * reoTransferUnitsToNodes_rec( reo_man * p, reo_unit * pUnit )
// might have been used. Make sure that its signature is different.
for ( ; p->HTable[HKey].Sign == p->Signature; HKey = (HKey+1) % p->nTableSize );
p->HTable[HKey].Sign = p->Signature;
- p->HTable[HKey].Arg1 = (unsigned)pUnit;
- p->HTable[HKey].Arg2 = (unsigned)bRes;
+ p->HTable[HKey].Arg1 = pUnit;
+ p->HTable[HKey].Arg2 = (reo_unit *)bRes;
// add the DD to the referenced DD list in order to be able to store it in cache
p->pRefNodes[p->nRefNodes++] = bRes; Cudd_Ref( bRes );
diff --git a/src/generic.c b/src/generic.c
index 43dd32d8..f94c50e6 100644
--- a/src/generic.c
+++ b/src/generic.c
@@ -25,7 +25,7 @@
////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////
-/// FUNCTION DEFITIONS ///
+/// FUNCTION DEFINITIONS ///
////////////////////////////////////////////////////////////////////////
/**Function*************************************************************
diff --git a/src/generic.h b/src/generic.h
index 860f2465..e17d2edf 100644
--- a/src/generic.h
+++ b/src/generic.h
@@ -21,6 +21,10 @@
#ifndef __zzz_H__
#define __zzz_H__
+#ifdef __cplusplus
+extern "C" {
+#endif
+
////////////////////////////////////////////////////////////////////////
/// INCLUDES ///
////////////////////////////////////////////////////////////////////////
@@ -34,7 +38,7 @@
////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////
-/// MACRO DEFITIONS ///
+/// MACRO DEFINITIONS ///
////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////
@@ -42,10 +46,14 @@
////////////////////////////////////////////////////////////////////////
/*=== zzz.c ==========================================================*/
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
////////////////////////////////////////////////////////////////////////
/// END OF FILE ///
////////////////////////////////////////////////////////////////////////
-#endif
-
diff --git a/src/map/fpga/fpga.c b/src/map/fpga/fpga.c
index 3d2ca913..40423f4f 100644
--- a/src/map/fpga/fpga.c
+++ b/src/map/fpga/fpga.c
@@ -39,7 +39,7 @@ static int Fpga_CommandPrintLibrary( Abc_Frame_t * pAbc, int argc, char **argv )
*/
////////////////////////////////////////////////////////////////////////
-/// FUNCTION DEFITIONS ///
+/// FUNCTION DEFINITIONS ///
////////////////////////////////////////////////////////////////////////
/**Function*************************************************************
@@ -56,8 +56,11 @@ static int Fpga_CommandPrintLibrary( Abc_Frame_t * pAbc, int argc, char **argv )
void Fpga_Init( Abc_Frame_t * pAbc )
{
// set the default library
- //Fpga_LutLib_t s_LutLib = { "lutlib", 6, {0,1,2,4,8,16,32}, {0,1,2,3,4,5,6} };
- Fpga_LutLib_t s_LutLib = { "lutlib", 5, {0,1,1,1,1,1}, {0,1,1,1,1,1} };
+ //Fpga_LutLib_t s_LutLib = { "lutlib", 6, 0, {0,1,2,4,8,16,32}, {{0},{1},{2},{3},{4},{5},{6}} };
+// Fpga_LutLib_t s_LutLib = { "lutlib", 5, 0, {0,1,1,1,1,1}, {{0},{1},{1},{1},{1},{1}} };
+ Fpga_LutLib_t s_LutLib = { "lutlib", 4, 0, {0,1,1,1,1}, {{0},{1},{1},{1},{1}} };
+ //Fpga_LutLib_t s_LutLib = { "lutlib", 3, 0, {0,1,1,1}, {{0},{1},{1},{1}} };
+
Abc_FrameSetLibLut( Fpga_LutLibDup(&s_LutLib) );
Cmd_CommandAdd( pAbc, "FPGA mapping", "read_lut", Fpga_CommandReadLibrary, 0 );
@@ -77,7 +80,7 @@ void Fpga_Init( Abc_Frame_t * pAbc )
***********************************************************************/
void Fpga_End()
{
- Fpga_LutLibFree( Abc_FrameReadLibLut(Abc_FrameGetGlobalFrame()) );
+ Fpga_LutLibFree( Abc_FrameReadLibLut() );
}
@@ -102,14 +105,14 @@ int Fpga_CommandReadLibrary( Abc_Frame_t * pAbc, int argc, char **argv )
int fVerbose;
int c;
- pNet = Abc_FrameReadNet(pAbc);
+ pNet = Abc_FrameReadNtk(pAbc);
pOut = Abc_FrameReadOut(pAbc);
pErr = Abc_FrameReadErr(pAbc);
// set the defaults
fVerbose = 1;
- util_getopt_reset();
- while ( (c = util_getopt(argc, argv, "vh")) != EOF )
+ Extra_UtilGetoptReset();
+ while ( (c = Extra_UtilGetopt(argc, argv, "vh")) != EOF )
{
switch (c)
{
@@ -125,13 +128,13 @@ int Fpga_CommandReadLibrary( Abc_Frame_t * pAbc, int argc, char **argv )
}
- if ( argc != util_optind + 1 )
+ if ( argc != globalUtilOptind + 1 )
{
goto usage;
}
// get the input file name
- FileName = argv[util_optind];
+ FileName = argv[globalUtilOptind];
if ( (pFile = fopen( FileName, "r" )) == NULL )
{
fprintf( pErr, "Cannot open input file \"%s\". ", FileName );
@@ -192,14 +195,14 @@ int Fpga_CommandPrintLibrary( Abc_Frame_t * pAbc, int argc, char **argv )
int fVerbose;
int c;
- pNet = Abc_FrameReadNet(pAbc);
+ pNet = Abc_FrameReadNtk(pAbc);
pOut = Abc_FrameReadOut(pAbc);
pErr = Abc_FrameReadErr(pAbc);
// set the defaults
fVerbose = 1;
- util_getopt_reset();
- while ( (c = util_getopt(argc, argv, "vh")) != EOF )
+ Extra_UtilGetoptReset();
+ while ( (c = Extra_UtilGetopt(argc, argv, "vh")) != EOF )
{
switch (c)
{
@@ -215,13 +218,13 @@ int Fpga_CommandPrintLibrary( Abc_Frame_t * pAbc, int argc, char **argv )
}
- if ( argc != util_optind )
+ if ( argc != globalUtilOptind )
{
goto usage;
}
// set the new network
- Fpga_LutLibPrint( Abc_FrameReadLibLut(Abc_FrameGetGlobalFrame()) );
+ Fpga_LutLibPrint( Abc_FrameReadLibLut() );
return 0;
usage:
@@ -232,6 +235,47 @@ usage:
return 1; /* error exit */
}
+/**Function*************************************************************
+
+ Synopsis [Sets simple LUT library.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Fpga_SetSimpleLutLib( int nLutSize )
+{
+ Fpga_LutLib_t s_LutLib10= { "lutlib",10, 0, {0,1,1,1,1,1,1,1,1,1,1}, {{0},{1},{1},{1},{1},{1},{1},{1},{1},{1},{1}} };
+ Fpga_LutLib_t s_LutLib9 = { "lutlib", 9, 0, {0,1,1,1,1,1,1,1,1,1}, {{0},{1},{1},{1},{1},{1},{1},{1},{1},{1}} };
+ Fpga_LutLib_t s_LutLib8 = { "lutlib", 8, 0, {0,1,1,1,1,1,1,1,1}, {{0},{1},{1},{1},{1},{1},{1},{1},{1}} };
+ Fpga_LutLib_t s_LutLib7 = { "lutlib", 7, 0, {0,1,1,1,1,1,1,1}, {{0},{1},{1},{1},{1},{1},{1},{1}} };
+ Fpga_LutLib_t s_LutLib6 = { "lutlib", 6, 0, {0,1,1,1,1,1,1}, {{0},{1},{1},{1},{1},{1},{1}} };
+ Fpga_LutLib_t s_LutLib5 = { "lutlib", 5, 0, {0,1,1,1,1,1}, {{0},{1},{1},{1},{1},{1}} };
+ Fpga_LutLib_t s_LutLib4 = { "lutlib", 4, 0, {0,1,1,1,1}, {{0},{1},{1},{1},{1}} };
+ Fpga_LutLib_t s_LutLib3 = { "lutlib", 3, 0, {0,1,1,1}, {{0},{1},{1},{1}} };
+ Fpga_LutLib_t * pLutLib;
+ assert( nLutSize >= 3 && nLutSize <= 10 );
+ switch ( nLutSize )
+ {
+ case 3: pLutLib = &s_LutLib3; break;
+ case 4: pLutLib = &s_LutLib4; break;
+ case 5: pLutLib = &s_LutLib5; break;
+ case 6: pLutLib = &s_LutLib6; break;
+ case 7: pLutLib = &s_LutLib7; break;
+ case 8: pLutLib = &s_LutLib8; break;
+ case 9: pLutLib = &s_LutLib9; break;
+ case 10: pLutLib = &s_LutLib10; break;
+ default: pLutLib = NULL; break;
+ }
+ if ( pLutLib == NULL )
+ return;
+ Fpga_LutLibFree( Abc_FrameReadLibLut() );
+ Abc_FrameSetLibLut( Fpga_LutLibDup(pLutLib) );
+}
+
////////////////////////////////////////////////////////////////////////
/// END OF FILE ///
////////////////////////////////////////////////////////////////////////
diff --git a/src/map/fpga/fpga.h b/src/map/fpga/fpga.h
index 19241a74..708cf385 100644
--- a/src/map/fpga/fpga.h
+++ b/src/map/fpga/fpga.h
@@ -19,6 +19,10 @@
#ifndef __FPGA_H__
#define __FPGA_H__
+#ifdef __cplusplus
+extern "C" {
+#endif
+
////////////////////////////////////////////////////////////////////////
/// INCLUDES ///
////////////////////////////////////////////////////////////////////////
@@ -28,7 +32,7 @@
////////////////////////////////////////////////////////////////////////
// the maximum size of LUTs used for mapping
-#define FPGA_MAX_LUTSIZE 10
+#define FPGA_MAX_LUTSIZE 32
////////////////////////////////////////////////////////////////////////
/// STRUCTURE DEFINITIONS ///
@@ -45,20 +49,20 @@ typedef struct Fpga_LutLibStruct_t_ Fpga_LutLib_t;
////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////
-/// MACRO DEFITIONS ///
+/// MACRO DEFINITIONS ///
////////////////////////////////////////////////////////////////////////
-#define Fpga_IsComplement(p) (((int)((long) (p) & 01)))
-#define Fpga_Regular(p) ((Fpga_Node_t *)((unsigned)(p) & ~01))
-#define Fpga_Not(p) ((Fpga_Node_t *)((long)(p) ^ 01))
-#define Fpga_NotCond(p,c) ((Fpga_Node_t *)((long)(p) ^ (c)))
+#define Fpga_IsComplement(p) (((int)((unsigned long) (p) & 01)))
+#define Fpga_Regular(p) ((Fpga_Node_t *)((unsigned long)(p) & ~01))
+#define Fpga_Not(p) ((Fpga_Node_t *)((unsigned long)(p) ^ 01))
+#define Fpga_NotCond(p,c) ((Fpga_Node_t *)((unsigned long)(p) ^ (c)))
#define Fpga_Ref(p)
#define Fpga_Deref(p)
#define Fpga_RecursiveDeref(p,c)
////////////////////////////////////////////////////////////////////////
-/// FUNCTION DEFITIONS ///
+/// FUNCTION DEFINITIONS ///
////////////////////////////////////////////////////////////////////////
/*=== fpgaCreate.c =============================================================*/
@@ -74,7 +78,9 @@ extern Fpga_Node_t ** Fpga_ManReadOutputs( Fpga_Man_t * p );
extern Fpga_Node_t * Fpga_ManReadConst1 ( Fpga_Man_t * p );
extern float * Fpga_ManReadInputArrivals( Fpga_Man_t * p );
extern int Fpga_ManReadVerbose( Fpga_Man_t * p );
+extern int Fpga_ManReadVarMax( Fpga_Man_t * p );
extern float * Fpga_ManReadLutAreas( Fpga_Man_t * p );
+extern Fpga_NodeVec_t* Fpga_ManReadMapping( Fpga_Man_t * p );
extern void Fpga_ManSetTimeToMap( Fpga_Man_t * p, int Time );
extern void Fpga_ManSetTimeToNet( Fpga_Man_t * p, int Time );
extern void Fpga_ManSetTimeTotal( Fpga_Man_t * p, int Time );
@@ -92,13 +98,16 @@ extern void Fpga_ManSetChoiceNodeNum( Fpga_Man_t * p, int nChoiceNode
extern void Fpga_ManSetChoiceNum( Fpga_Man_t * p, int nChoices );
extern void Fpga_ManSetVerbose( Fpga_Man_t * p, int fVerbose );
extern void Fpga_ManSetSwitching( Fpga_Man_t * p, int fSwitching );
+extern void Fpga_ManSetLatchPaths( Fpga_Man_t * p, int fLatchPaths );
extern void Fpga_ManSetLatchNum( Fpga_Man_t * p, int nLatches );
+extern void Fpga_ManSetDelayTarget( Fpga_Man_t * p, float DelayTarget );
extern void Fpga_ManSetName( Fpga_Man_t * p, char * pFileName );
extern int Fpga_LibReadLutMax( Fpga_LutLib_t * pLib );
extern char * Fpga_NodeReadData0( Fpga_Node_t * p );
extern Fpga_Node_t * Fpga_NodeReadData1( Fpga_Node_t * p );
+extern int Fpga_NodeReadRefs( Fpga_Node_t * p );
extern int Fpga_NodeReadNum( Fpga_Node_t * p );
extern int Fpga_NodeReadLevel( Fpga_Node_t * p );
extern Fpga_Cut_t * Fpga_NodeReadCuts( Fpga_Node_t * p );
@@ -134,23 +143,33 @@ extern int Fpga_Mapping( Fpga_Man_t * p );
/*=== fpgaCut.c ===============================================================*/
extern void Fpga_MappingCreatePiCuts( Fpga_Man_t * p );
extern void Fpga_CutsCleanSign( Fpga_Man_t * pMan );
+extern void Fpga_CutsCleanRoot( Fpga_Man_t * pMan );
/*=== fpgaCutUtils.c =============================================================*/
extern void Fpga_CutCreateFromNode( Fpga_Man_t * p, int iRoot, int * pLeaves, int nLeaves );
extern void Fpga_MappingSetUsedCuts( Fpga_Man_t * p );
-/*=== fpgaFraig.c =============================================================*/
-extern Fpga_Man_t * Fpga_ManDupFraig( Fraig_Man_t * pManFraig );
-extern Fpga_Man_t * Fpga_ManBalanceFraig( Fraig_Man_t * pManFraig, int * pInputArrivals );
/*=== fpgaLib.c =============================================================*/
extern Fpga_LutLib_t * Fpga_LutLibDup( Fpga_LutLib_t * p );
+extern int Fpga_LutLibReadVarMax( Fpga_LutLib_t * p );
+extern float * Fpga_LutLibReadLutAreas( Fpga_LutLib_t * p );
+extern float * Fpga_LutLibReadLutDelays( Fpga_LutLib_t * p );
+extern float Fpga_LutLibReadLutArea( Fpga_LutLib_t * p, int Size );
+extern float Fpga_LutLibReadLutDelay( Fpga_LutLib_t * p, int Size );
/*=== fpgaTruth.c =============================================================*/
extern void * Fpga_TruthsCutBdd( void * dd, Fpga_Cut_t * pCut );
+extern int Fpga_CutVolume( Fpga_Cut_t * pCut );
/*=== fpgaUtil.c =============================================================*/
extern int Fpga_ManCheckConsistency( Fpga_Man_t * p );
extern void Fpga_ManCleanData0( Fpga_Man_t * pMan );
extern Fpga_NodeVec_t * Fpga_CollectNodeTfo( Fpga_Man_t * pMan, Fpga_Node_t * pNode );
+/*=== fpga.c =============================================================*/
+extern void Fpga_SetSimpleLutLib( int nLutSize );
+
+#ifdef __cplusplus
+}
+#endif
+#endif
////////////////////////////////////////////////////////////////////////
/// END OF FILE ///
////////////////////////////////////////////////////////////////////////
-#endif
diff --git a/src/map/fpga/fpgaCore.c b/src/map/fpga/fpgaCore.c
index 9ca65379..634a8eb1 100644
--- a/src/map/fpga/fpgaCore.c
+++ b/src/map/fpga/fpgaCore.c
@@ -24,8 +24,12 @@
static int Fpga_MappingPostProcess( Fpga_Man_t * p );
+extern int s_MappingTime;
+extern int s_MappingMem;
+
+
////////////////////////////////////////////////////////////////////////
-/// FUNCTION DEFITIONS ///
+/// FUNCTION DEFINITIONS ///
////////////////////////////////////////////////////////////////////////
/**Function*************************************************************
@@ -46,7 +50,7 @@ static int Fpga_MappingPostProcess( Fpga_Man_t * p );
int Fpga_Mapping( Fpga_Man_t * p )
{
int clk, clkTotal = clock();
-
+
// collect the nodes reachable from POs in the DFS order (including the choices)
p->vAnds = Fpga_MappingDfs( p, 1 );
Fpga_ManReportChoices( p ); // recomputes levels
@@ -64,19 +68,23 @@ int Fpga_Mapping( Fpga_Man_t * p )
p->timeMatch = clock() - clk;
// perform area recovery
- if ( p->fAreaRecovery )
- {
- clk = clock();
- if ( !Fpga_MappingPostProcess( p ) )
- return 0;
- p->timeRecover = clock() - clk;
- }
+ clk = clock();
+ if ( !Fpga_MappingPostProcess( p ) )
+ return 0;
+ p->timeRecover = clock() - clk;
//PRT( "Total mapping time", clock() - clkTotal );
+ s_MappingTime = clock() - clkTotal;
+ s_MappingMem = Fpga_CutCountAll(p) * (sizeof(Fpga_Cut_t) - sizeof(int) * (FPGA_MAX_LEAVES - p->nVarsMax));
+
// print the AI-graph used for mapping
//Fpga_ManShow( p, "test" );
+// if ( p->fVerbose )
+// Fpga_MappingPrintOutputArrivals( p );
if ( p->fVerbose )
- Fpga_MappingPrintOutputArrivals( p );
+ {
+ PRT( "Total time", clock() - clkTotal );
+ }
return 1;
}
@@ -88,7 +96,7 @@ int Fpga_Mapping( Fpga_Man_t * p )
It iterates the loop, in which the required times are computed and
the mapping is updated. It is conceptually similar to the paper:
V. Manohararajah, S. D. Brown, Z. G. Vranesic, Heuristics for area
- minimization in LUT-based FGPA technology mapping. Proc. IWLS '04.]
+ minimization in LUT-based FPGA technology mapping. Proc. IWLS '04.]
SideEffects []
@@ -97,12 +105,15 @@ int Fpga_Mapping( Fpga_Man_t * p )
***********************************************************************/
int Fpga_MappingPostProcess( Fpga_Man_t * p )
{
- int fShowSwitching = 1;
+ int fShowSwitching = 0;
int fRecoverAreaFlow = 1;
int fRecoverArea = 1;
float aAreaTotalCur, aAreaTotalCur2;
int Iter, clk;
+//if ( p->fVerbose )
+// printf( "Best clock period = %5.2f\n", Fpga_TimeComputeArrivalMax(p) );
+
// compute area, set references, and collect nodes used in the mapping
Iter = 1;
aAreaTotalCur = Fpga_MappingSetRefsAndArea( p );
@@ -111,14 +122,20 @@ if ( p->fVerbose )
printf( "Iteration %dD : Area = %8.1f ", Iter++, aAreaTotalCur );
if ( fShowSwitching )
printf( "Switch = %8.1f ", Fpga_MappingGetSwitching(p,p->vMapping) );
+else
+printf( "Delay = %5.2f ", Fpga_TimeComputeArrivalMax(p) );
+
PRT( "Time", p->timeMatch );
}
+ if ( !p->fAreaRecovery )
+ return 1;
+
if ( fRecoverAreaFlow )
{
clk = clock();
// compute the required times and the fanouts
- Fpga_TimeComputeRequiredGlobal( p );
+ Fpga_TimeComputeRequiredGlobal( p, 1 );
// remap topologically
Fpga_MappingMatches( p, 0 );
// get the resulting area
@@ -131,6 +148,8 @@ if ( p->fVerbose )
printf( "Iteration %dF : Area = %8.1f ", Iter++, aAreaTotalCur );
if ( fShowSwitching )
printf( "Switch = %8.1f ", Fpga_MappingGetSwitching(p,p->vMapping) );
+else
+printf( "Delay = %5.2f ", Fpga_TimeComputeArrivalMax(p) );
PRT( "Time", clock() - clk );
}
}
@@ -143,7 +162,7 @@ PRT( "Time", clock() - clk );
{
clk = clock();
// compute the required times and the fanouts
- Fpga_TimeComputeRequiredGlobal( p );
+ Fpga_TimeComputeRequiredGlobal( p, 0 );
// remap topologically
if ( p->fSwitching )
Fpga_MappingMatchesSwitch( p );
@@ -156,6 +175,8 @@ if ( p->fVerbose )
printf( "Iteration %d%s : Area = %8.1f ", Iter++, (p->fSwitching?"S":"A"), aAreaTotalCur );
if ( fShowSwitching )
printf( "Switch = %8.1f ", Fpga_MappingGetSwitching(p,p->vMapping) );
+else
+printf( "Delay = %5.2f ", Fpga_TimeComputeArrivalMax(p) );
PRT( "Time", clock() - clk );
}
}
diff --git a/src/map/fpga/fpgaCreate.c b/src/map/fpga/fpgaCreate.c
index b7bfa3c5..be71d74e 100644
--- a/src/map/fpga/fpgaCreate.c
+++ b/src/map/fpga/fpgaCreate.c
@@ -31,7 +31,7 @@ static Fpga_Node_t * Fpga_TableLookup( Fpga_Man_t * p, Fpga_Node_t * p1, Fpga_
static inline unsigned Fpga_HashKey2( Fpga_Node_t * p0, Fpga_Node_t * p1, int TableSize ) { return ((unsigned)(p0) + (unsigned)(p1) * 12582917) % TableSize; }
////////////////////////////////////////////////////////////////////////
-/// FUNCTION DEFITIONS ///
+/// FUNCTION DEFINITIONS ///
////////////////////////////////////////////////////////////////////////
/**Function*************************************************************
@@ -52,7 +52,9 @@ Fpga_Node_t ** Fpga_ManReadOutputs( Fpga_Man_t * p ) { retu
Fpga_Node_t * Fpga_ManReadConst1 ( Fpga_Man_t * p ) { return p->pConst1; }
float * Fpga_ManReadInputArrivals( Fpga_Man_t * p ) { return p->pInputArrivals;}
int Fpga_ManReadVerbose( Fpga_Man_t * p ) { return p->fVerbose; }
+int Fpga_ManReadVarMax( Fpga_Man_t * p ) { return p->pLutLib->LutMax; }
float * Fpga_ManReadLutAreas( Fpga_Man_t * p ) { return p->pLutLib->pLutAreas; }
+Fpga_NodeVec_t* Fpga_ManReadMapping( Fpga_Man_t * p ) { return p->vMapping; }
void Fpga_ManSetTimeToMap( Fpga_Man_t * p, int Time ) { p->timeToMap = Time; }
void Fpga_ManSetTimeToNet( Fpga_Man_t * p, int Time ) { p->timeToNet = Time; }
void Fpga_ManSetTimeTotal( Fpga_Man_t * p, int Time ) { p->timeTotal = Time; }
@@ -66,7 +68,9 @@ void Fpga_ManSetChoiceNodeNum( Fpga_Man_t * p, int nChoiceNodes ) { p
void Fpga_ManSetChoiceNum( Fpga_Man_t * p, int nChoices ) { p->nChoices = nChoices; }
void Fpga_ManSetVerbose( Fpga_Man_t * p, int fVerbose ) { p->fVerbose = fVerbose; }
void Fpga_ManSetSwitching( Fpga_Man_t * p, int fSwitching ) { p->fSwitching = fSwitching; }
+void Fpga_ManSetLatchPaths( Fpga_Man_t * p, int fLatchPaths ) { p->fLatchPaths = fLatchPaths; }
void Fpga_ManSetLatchNum( Fpga_Man_t * p, int nLatches ) { p->nLatches = nLatches; }
+void Fpga_ManSetDelayTarget( Fpga_Man_t * p, float DelayTarget ) { p->DelayTarget = DelayTarget; }
void Fpga_ManSetName( Fpga_Man_t * p, char * pFileName ) { p->pFileName = pFileName; }
/**Function*************************************************************
@@ -95,6 +99,7 @@ int Fpga_LibReadLutMax( Fpga_LutLib_t * pLib ) { return pLib->LutMa
***********************************************************************/
char * Fpga_NodeReadData0( Fpga_Node_t * p ) { return p->pData0; }
Fpga_Node_t * Fpga_NodeReadData1( Fpga_Node_t * p ) { return p->pLevel; }
+int Fpga_NodeReadRefs( Fpga_Node_t * p ) { return p->nRefs; }
int Fpga_NodeReadNum( Fpga_Node_t * p ) { return p->Num; }
int Fpga_NodeReadLevel( Fpga_Node_t * p ) { return Fpga_Regular(p)->Level; }
Fpga_Cut_t * Fpga_NodeReadCuts( Fpga_Node_t * p ) { return p->pCuts; }
@@ -164,7 +169,7 @@ Fpga_Man_t * Fpga_ManCreate( int nInputs, int nOutputs, int fVerbose )
// start the manager
p = ALLOC( Fpga_Man_t, 1 );
memset( p, 0, sizeof(Fpga_Man_t) );
- p->pLutLib = Abc_FrameReadLibLut(Abc_FrameGetGlobalFrame());
+ p->pLutLib = Abc_FrameReadLibLut();
p->nVarsMax = p->pLutLib->LutMax;
p->fVerbose = fVerbose;
p->fAreaRecovery = 1;
@@ -223,8 +228,8 @@ void Fpga_ManFree( Fpga_Man_t * p )
Fpga_NodeVecFree( p->vAnds );
if ( p->vNodesAll )
Fpga_NodeVecFree( p->vNodesAll );
- Extra_MmFixedStop( p->mmNodes, 0 );
- Extra_MmFixedStop( p->mmCuts, 0 );
+ Extra_MmFixedStop( p->mmNodes );
+ Extra_MmFixedStop( p->mmCuts );
FREE( p->ppOutputNames );
FREE( p->pInputArrivals );
FREE( p->pInputs );
diff --git a/src/map/fpga/fpgaCut.c b/src/map/fpga/fpgaCut.c
index 5b5fbe69..ce688179 100644
--- a/src/map/fpga/fpgaCut.c
+++ b/src/map/fpga/fpgaCut.c
@@ -35,9 +35,11 @@ struct Fpga_CutTableStrutct_t
};
// the largest number of cuts considered
-#define FPGA_CUTS_MAX_COMPUTE 500
+//#define FPGA_CUTS_MAX_COMPUTE 500
+#define FPGA_CUTS_MAX_COMPUTE 2000
// the largest number of cuts used
-#define FPGA_CUTS_MAX_USE 200
+//#define FPGA_CUTS_MAX_USE 200
+#define FPGA_CUTS_MAX_USE 1000
// primes used to compute the hash key
static int s_HashPrimes[10] = { 109, 499, 557, 619, 631, 709, 797, 881, 907, 991 };
@@ -95,7 +97,7 @@ static Fpga_Cut_t * Fpga_CutArray2List( Fpga_Cut_t ** pArray, int nCuts );
////////////////////////////////////////////////////////////////////////
-/// FUNCTION DEFITIONS ///
+/// FUNCTION DEFINITIONS ///
////////////////////////////////////////////////////////////////////////
/**Function*************************************************************
@@ -128,9 +130,10 @@ void Fpga_MappingCuts( Fpga_Man_t * p )
Fpga_CutTable_t * pTable;
Fpga_Node_t * pNode;
int nCuts, nNodes, i;
+ int clk = clock();
// set the elementary cuts for the PI variables
- assert( p->nVarsMax > 1 && p->nVarsMax < 7 );
+ assert( p->nVarsMax > 1 && p->nVarsMax < 11 );
Fpga_MappingCreatePiCuts( p );
// compute the cuts for the internal nodes
@@ -152,8 +155,9 @@ void Fpga_MappingCuts( Fpga_Man_t * p )
if ( p->fVerbose )
{
nCuts = Fpga_CutCountAll(p);
- printf( "Nodes = %6d. Total %d-feasible cuts = %d. Cuts per node = %.1f.\n",
+ printf( "Nodes = %6d. Total %d-cuts = %d. Cuts per node = %.1f. ",
p->nNodes, p->nVarsMax, nCuts, ((float)nCuts)/p->nNodes );
+ PRT( "Time", clock() - clk );
}
// print the cuts for the first primary output
@@ -245,7 +249,7 @@ Fpga_Cut_t * Fpga_CutCompute( Fpga_Man_t * p, Fpga_CutTable_t * pTable, Fpga_Nod
// set at the node
pNode->pCuts = pCut;
// remove the dominated cuts
- Fpga_CutFilter( p, pNode );
+// Fpga_CutFilter( p, pNode );
// set the phase correctly
if ( pNode->pRepr && Fpga_NodeComparePhase(pNode, pNode->pRepr) )
{
@@ -347,8 +351,8 @@ void Fpga_CutFilter( Fpga_Man_t * p, Fpga_Node_t * pNode )
Fpga_Cut_t * Fpga_CutMergeLists( Fpga_Man_t * p, Fpga_CutTable_t * pTable,
Fpga_Cut_t * pList1, Fpga_Cut_t * pList2, int fComp1, int fComp2, int fPivot1, int fPivot2 )
{
- Fpga_Node_t * ppNodes[6];
- Fpga_Cut_t * pListNew, ** ppListNew, * pLists[7] = { NULL };
+ Fpga_Node_t * ppNodes[FPGA_MAX_LEAVES];
+ Fpga_Cut_t * pListNew, ** ppListNew, * pLists[FPGA_MAX_LEAVES+1] = { NULL };
Fpga_Cut_t * pCut, * pPrev, * pTemp1, * pTemp2;
int nNodes, Counter, i;
Fpga_Cut_t ** ppArray1, ** ppArray2, ** ppArray3;
@@ -532,8 +536,8 @@ QUITS :
Fpga_Cut_t * Fpga_CutMergeLists2( Fpga_Man_t * p, Fpga_CutTable_t * pTable,
Fpga_Cut_t * pList1, Fpga_Cut_t * pList2, int fComp1, int fComp2, int fPivot1, int fPivot2 )
{
- Fpga_Node_t * ppNodes[6];
- Fpga_Cut_t * pListNew, ** ppListNew, * pLists[7] = { NULL };
+ Fpga_Node_t * ppNodes[FPGA_MAX_LEAVES];
+ Fpga_Cut_t * pListNew, ** ppListNew, * pLists[FPGA_MAX_LEAVES+1] = { NULL };
Fpga_Cut_t * pCut, * pPrev, * pTemp1, * pTemp2;
int nNodes, Counter, i;
@@ -682,7 +686,8 @@ int Fpga_CutMergeTwo( Fpga_Cut_t * pCut1, Fpga_Cut_t * pCut2, Fpga_Node_t * ppNo
{
min = i;
for ( k = i+1; k < nTotal; k++ )
- if ( ppNodes[k] < ppNodes[min] )
+// if ( ppNodes[k] < ppNodes[min] ) // reported bug fix (non-determinism!)
+ if ( ppNodes[k]->Num < ppNodes[min]->Num )
min = k;
pNodeTemp = ppNodes[i];
ppNodes[i] = ppNodes[min];
@@ -767,7 +772,10 @@ int Fpga_CutCountAll( Fpga_Man_t * pMan )
for ( pNode = pMan->pBins[i]; pNode; pNode = pNode->pNext )
for ( pCut = pNode->pCuts; pCut; pCut = pCut->pNext )
if ( pCut->nLeaves > 1 ) // skip the elementary cuts
+ {
+// Fpga_CutVolume( pCut );
nCuts++;
+ }
return nCuts;
}
@@ -794,6 +802,28 @@ void Fpga_CutsCleanSign( Fpga_Man_t * pMan )
pCut->uSign = 0;
}
+/**Function*************************************************************
+
+ Synopsis [Clean the signatures.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Fpga_CutsCleanRoot( Fpga_Man_t * pMan )
+{
+ Fpga_Node_t * pNode;
+ Fpga_Cut_t * pCut;
+ int i;
+ for ( i = 0; i < pMan->nBins; i++ )
+ for ( pNode = pMan->pBins[i]; pNode; pNode = pNode->pNext )
+ for ( pCut = pNode->pCuts; pCut; pCut = pCut->pNext )
+ pCut->pRoot = NULL;
+}
+
/**Function*************************************************************
@@ -1079,7 +1109,7 @@ Fpga_Cut_t * Fpga_CutSortCuts( Fpga_Man_t * pMan, Fpga_CutTable_t * p, Fpga_Cut_
nCuts = Fpga_CutList2Array( p->pCuts1, pList );
assert( nCuts <= FPGA_CUTS_MAX_COMPUTE );
// sort the cuts
- qsort( (void *)p->pCuts1, nCuts, sizeof(Fpga_Cut_t *),
+ qsort( (void *)p->pCuts1, nCuts, sizeof(void *),
(int (*)(const void *, const void *)) Fpga_CutSortCutsCompare );
// move them back into the list
if ( nCuts > FPGA_CUTS_MAX_USE - 1 )
diff --git a/src/map/fpga/fpgaCutUtils.c b/src/map/fpga/fpgaCutUtils.c
index 2419cac4..e60a1dee 100644
--- a/src/map/fpga/fpgaCutUtils.c
+++ b/src/map/fpga/fpgaCutUtils.c
@@ -23,7 +23,7 @@
////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////
-/// FUNCTION DEFITIONS ///
+/// FUNCTION DEFINITIONS ///
////////////////////////////////////////////////////////////////////////
/**Function*************************************************************
@@ -290,7 +290,9 @@ void Fpga_CutGetParameters( Fpga_Man_t * pMan, Fpga_Cut_t * pCut )
// pCut->aFlow += pFaninCut->aFlow / pCut->ppLeaves[i]->nRefs;
pCut->aFlow += pFaninCut->aFlow / pCut->ppLeaves[i]->aEstFanouts;
}
- pCut->tArrival += pMan->pLutLib->pLutDelays[pCut->nLeaves];
+ // use the first pin to compute the delay of the LUT
+ // (this mapper does not support the variable pin delay model)
+ pCut->tArrival += pMan->pLutLib->pLutDelays[pCut->nLeaves][0];
}
@@ -338,7 +340,7 @@ float Fpga_CutGetAreaRefed( Fpga_Man_t * pMan, Fpga_Cut_t * pCut )
return 0;
aResult = Fpga_CutDeref( pMan, NULL, pCut, 0 );
aResult2 = Fpga_CutRef( pMan, NULL, pCut, 0 );
- assert( aResult == aResult2 );
+ assert( Fpga_FloatEqual( pMan, aResult, aResult2 ) );
return aResult;
}
@@ -360,7 +362,7 @@ float Fpga_CutGetAreaDerefed( Fpga_Man_t * pMan, Fpga_Cut_t * pCut )
return 0;
aResult2 = Fpga_CutRef( pMan, NULL, pCut, 0 );
aResult = Fpga_CutDeref( pMan, NULL, pCut, 0 );
- assert( aResult == aResult2 );
+ assert( Fpga_FloatEqual( pMan, aResult, aResult2 ) );
return aResult;
}
diff --git a/src/map/fpga/fpgaFanout.c b/src/map/fpga/fpgaFanout.c
index 0a34ff43..c28a8799 100644
--- a/src/map/fpga/fpgaFanout.c
+++ b/src/map/fpga/fpgaFanout.c
@@ -25,7 +25,7 @@
////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////
-/// FUNCTION DEFITIONS ///
+/// FUNCTION DEFINITIONS ///
////////////////////////////////////////////////////////////////////////
/**Function*************************************************************
diff --git a/src/map/fpga/fpgaGENERIC.c b/src/map/fpga/fpgaGENERIC.c
index f272c1b8..4483c215 100644
--- a/src/map/fpga/fpgaGENERIC.c
+++ b/src/map/fpga/fpgaGENERIC.c
@@ -23,7 +23,7 @@
////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////
-/// FUNCTION DEFITIONS ///
+/// FUNCTION DEFINITIONS ///
////////////////////////////////////////////////////////////////////////
/**Function*************************************************************
diff --git a/src/map/fpga/fpgaInt.h b/src/map/fpga/fpgaInt.h
index ec6057a7..c01d1e3d 100644
--- a/src/map/fpga/fpgaInt.h
+++ b/src/map/fpga/fpgaInt.h
@@ -28,7 +28,6 @@
#include <stdlib.h>
#include <string.h>
#include "extra.h"
-#include "fraig.h"
#include "fpga.h"
////////////////////////////////////////////////////////////////////////
@@ -39,7 +38,7 @@
//#define FPGA_ALLOCATE_FANOUT 1
////////////////////////////////////////////////////////////////////////
-/// MACRO DEFITIONS ///
+/// MACRO DEFINITIONS ///
////////////////////////////////////////////////////////////////////////
#ifdef _WIN32
@@ -68,16 +67,16 @@
#define FPGA_SEQ_SIGN(p) (1 << (((unsigned)p)%31));
// internal macros to work with cuts
-#define Fpga_CutIsComplement(p) (((int)((long) (p) & 01)))
-#define Fpga_CutRegular(p) ((Fpga_Cut_t *)((unsigned)(p) & ~01))
-#define Fpga_CutNot(p) ((Fpga_Cut_t *)((long)(p) ^ 01))
-#define Fpga_CutNotCond(p,c) ((Fpga_Cut_t *)((long)(p) ^ (c)))
+#define Fpga_CutIsComplement(p) (((int)((unsigned long) (p) & 01)))
+#define Fpga_CutRegular(p) ((Fpga_Cut_t *)((unsigned long)(p) & ~01))
+#define Fpga_CutNot(p) ((Fpga_Cut_t *)((unsigned long)(p) ^ 01))
+#define Fpga_CutNotCond(p,c) ((Fpga_Cut_t *)((unsigned long)(p) ^ (c)))
// the cut nodes
-#define Fpga_SeqIsComplement( p ) (((int)((long) (p) & 01)))
-#define Fpga_SeqRegular( p ) ((Fpga_Node_t *)((unsigned)(p) & ~015))
-#define Fpga_SeqIndex( p ) ((((unsigned)(p)) >> 1) & 07)
-#define Fpga_SeqIndexCreate( p, Ind ) (((unsigned)(p)) | (1 << (((unsigned)(Ind)) & 07)))
+#define Fpga_SeqIsComplement( p ) (((int)((unsigned long) (p) & 01)))
+#define Fpga_SeqRegular( p ) ((Fpga_Node_t *)((unsigned long)(p) & ~015))
+#define Fpga_SeqIndex( p ) ((((unsigned long)(p)) >> 1) & 07)
+#define Fpga_SeqIndexCreate( p, Ind ) (((unsigned long)(p)) | (1 << (((unsigned)(Ind)) & 07)))
// internal macros for referencing of nodes
#define Fpga_NodeReadRef(p) ((Fpga_Regular(p))->nRefs)
@@ -123,7 +122,9 @@ struct Fpga_ManStruct_t_
int fAreaRecovery; // the flag to use area flow as the first parameter
int fVerbose; // the verbosiness flag
int fSwitching; // minimize the switching activity (instead of area)
- int nTravIds;
+ int fLatchPaths; // optimize latch paths for delay, other paths for area
+ int nTravIds; // the counter of traversal IDs
+ float DelayTarget; // the target required times
// support of choice nodes
int nChoiceNodes; // the number of choice nodes
@@ -170,8 +171,9 @@ struct Fpga_LutLibStruct_t_
{
char * pName; // the name of the LUT library
int LutMax; // the maximum LUT size
+ int fVarPinDelays; // set to 1 if variable pin delays are specified
float pLutAreas[FPGA_MAX_LUTSIZE+1]; // the areas of LUTs
- float pLutDelays[FPGA_MAX_LUTSIZE+1];// the delays of LUTs
+ float pLutDelays[FPGA_MAX_LUTSIZE+1][FPGA_MAX_LUTSIZE+1];// the delays of LUTs
};
// the mapping node
@@ -182,8 +184,8 @@ struct Fpga_NodeStruct_t_
Fpga_Node_t * pLevel; // the next node in the linked list by level
int Num; // the unique number of this node
int NumA; // the unique number of this node
- short Num2; // the temporary number of this node
- short nRefs; // the number of references (fanouts) of the given node
+ int Num2; // the temporary number of this node
+ int nRefs; // the number of references (fanouts) of the given node
unsigned fMark0 : 1; // the mark used for traversals
unsigned fMark1 : 1; // the mark used for traversals
unsigned fInv : 1; // the complemented attribute for the equivalent nodes
@@ -276,12 +278,16 @@ struct Fpga_NodeVecStruct_t_
pFanout = pFanout2, \
pFanout2 = Fpga_NodeReadNextFanout(pNode, pFanout) )
+static inline Fpga_FloatMoreThan( Fpga_Man_t * p, float Arg1, float Arg2 ) { return Arg1 > Arg2 + p->fEpsilon; }
+static inline Fpga_FloatLessThan( Fpga_Man_t * p, float Arg1, float Arg2 ) { return Arg1 < Arg2 - p->fEpsilon; }
+static inline Fpga_FloatEqual( Fpga_Man_t * p, float Arg1, float Arg2 ) { return Arg1 > Arg2 - p->fEpsilon && Arg1 < Arg2 + p->fEpsilon; }
+
////////////////////////////////////////////////////////////////////////
/// GLOBAL VARIABLES ///
////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////
-/// FUNCTION DEFITIONS ///
+/// FUNCTION DEFINITIONS ///
////////////////////////////////////////////////////////////////////////
/*=== fpgaCut.c ===============================================================*/
@@ -331,7 +337,7 @@ extern float Fpga_MappingGetSwitching( Fpga_Man_t * pMan, Fpga_NodeV
extern float Fpga_TimeCutComputeArrival( Fpga_Man_t * pMan, Fpga_Cut_t * pCut );
extern float Fpga_TimeCutComputeArrival_rec( Fpga_Man_t * pMan, Fpga_Cut_t * pCut );
extern float Fpga_TimeComputeArrivalMax( Fpga_Man_t * p );
-extern void Fpga_TimeComputeRequiredGlobal( Fpga_Man_t * p );
+extern void Fpga_TimeComputeRequiredGlobal( Fpga_Man_t * p, int fFirstTime );
extern void Fpga_TimeComputeRequired( Fpga_Man_t * p, float fRequired );
extern void Fpga_TimePropagateRequired( Fpga_Man_t * p, Fpga_NodeVec_t * vNodes );
extern void Fpga_TimePropagateArrival( Fpga_Man_t * p );
@@ -375,8 +381,8 @@ extern void Fpga_MappingSetChoiceLevels( Fpga_Man_t * pMan );
/*=== CUDD package.c ===============================================================*/
extern unsigned int Cudd_Prime( unsigned int p );
+#endif
+
////////////////////////////////////////////////////////////////////////
/// END OF FILE ///
////////////////////////////////////////////////////////////////////////
-
-#endif
diff --git a/src/map/fpga/fpgaLib.c b/src/map/fpga/fpgaLib.c
index 9fd8e281..b1bb4cdc 100644
--- a/src/map/fpga/fpgaLib.c
+++ b/src/map/fpga/fpgaLib.c
@@ -23,11 +23,26 @@
////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////
-/// FUNCTION DEFITIONS ///
+/// FUNCTION DEFINITIONS ///
////////////////////////////////////////////////////////////////////////
/**Function*************************************************************
+ Synopsis [APIs to access LUT library.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Fpga_LutLibReadVarMax( Fpga_LutLib_t * p ) { return p->LutMax; }
+float * Fpga_LutLibReadLutAreas( Fpga_LutLib_t * p ) { return p->pLutAreas; }
+float Fpga_LutLibReadLutArea( Fpga_LutLib_t * p, int Size ) { assert( Size <= p->LutMax ); return p->pLutAreas[Size]; }
+
+/**Function*************************************************************
+
Synopsis [Reads the description of LUTs from the LUT library file.]
Description []
@@ -42,7 +57,7 @@ Fpga_LutLib_t * Fpga_LutLibCreate( char * FileName, int fVerbose )
char pBuffer[1000], * pToken;
Fpga_LutLib_t * p;
FILE * pFile;
- int i;
+ int i, k;
pFile = fopen( FileName, "r" );
if ( pFile == NULL )
@@ -53,7 +68,7 @@ Fpga_LutLib_t * Fpga_LutLibCreate( char * FileName, int fVerbose )
p = ALLOC( Fpga_LutLib_t, 1 );
memset( p, 0, sizeof(Fpga_LutLib_t) );
- p->pName = util_strsav( FileName );
+ p->pName = Extra_UtilStrsav( FileName );
i = 1;
while ( fgets( pBuffer, 1000, pFile ) != NULL )
@@ -70,25 +85,66 @@ Fpga_LutLib_t * Fpga_LutLibCreate( char * FileName, int fVerbose )
return NULL;
}
+ // read area
pToken = strtok( NULL, " \t\n" );
p->pLutAreas[i] = (float)atof(pToken);
- pToken = strtok( NULL, " \t\n" );
- p->pLutDelays[i] = (float)atof(pToken);
+ // read delays
+ k = 0;
+ while ( pToken = strtok( NULL, " \t\n" ) )
+ p->pLutDelays[i][k++] = (float)atof(pToken);
+
+ // check for out-of-bound
+ if ( k > i )
+ {
+ printf( "LUT %d has too many pins (%d). Max allowed is %d.\n", i, k, i );
+ return NULL;
+ }
+
+ // check if var delays are specifies
+ if ( k > 1 )
+ p->fVarPinDelays = 1;
if ( i == FPGA_MAX_LUTSIZE )
{
printf( "Skipping LUTs of size more than %d.\n", i );
- break;
+ return NULL;
}
i++;
}
p->LutMax = i-1;
+
if ( p->LutMax > FPGA_MAX_LEAVES )
{
p->LutMax = FPGA_MAX_LEAVES;
- printf( "Warning: LUTs with more than %d input will not be used.\n", FPGA_MAX_LEAVES );
+ printf( "Warning: LUTs with more than %d inputs will not be used.\n", FPGA_MAX_LEAVES );
}
+
+ // check the library
+ if ( p->fVarPinDelays )
+ {
+ for ( i = 1; i <= p->LutMax; i++ )
+ for ( k = 0; k < i; k++ )
+ {
+ if ( p->pLutDelays[i][k] <= 0.0 )
+ printf( "Warning: Pin %d of LUT %d has delay %f. Pin delays should be non-negative numbers. Technology mapping may not work correctly.\n",
+ k, i, p->pLutDelays[i][k] );
+ if ( k && p->pLutDelays[i][k-1] > p->pLutDelays[i][k] )
+ printf( "Warning: Pin %d of LUT %d has delay %f. Pin %d of LUT %d has delay %f. Pin delays should be in non-decreasing order. Technology mapping may not work correctly.\n",
+ k-1, i, p->pLutDelays[i][k-1],
+ k, i, p->pLutDelays[i][k] );
+ }
+ }
+ else
+ {
+ for ( i = 1; i <= p->LutMax; i++ )
+ {
+ if ( p->pLutDelays[i][0] <= 0.0 )
+ printf( "Warning: LUT %d has delay %f. Pin delays should be non-negative numbers. Technology mapping may not work correctly.\n",
+ k, i, p->pLutDelays[i][0] );
+ }
+ }
+
return p;
}
@@ -108,7 +164,7 @@ Fpga_LutLib_t * Fpga_LutLibDup( Fpga_LutLib_t * p )
Fpga_LutLib_t * pNew;
pNew = ALLOC( Fpga_LutLib_t, 1 );
*pNew = *p;
- pNew->pName = util_strsav( pNew->pName );
+ pNew->pName = Extra_UtilStrsav( pNew->pName );
return pNew;
}
@@ -145,11 +201,22 @@ void Fpga_LutLibFree( Fpga_LutLib_t * pLutLib )
***********************************************************************/
void Fpga_LutLibPrint( Fpga_LutLib_t * pLutLib )
{
- int i;
+ int i, k;
printf( "# The area/delay of k-variable LUTs:\n" );
printf( "# k area delay\n" );
- for ( i = 1; i <= pLutLib->LutMax; i++ )
- printf( "%d %7.2f %7.2f\n", i, pLutLib->pLutAreas[i], pLutLib->pLutDelays[i] );
+ if ( pLutLib->fVarPinDelays )
+ {
+ for ( i = 1; i <= pLutLib->LutMax; i++ )
+ {
+ printf( "%d %7.2f ", i, pLutLib->pLutAreas[i] );
+ for ( k = 0; k < i; k++ )
+ printf( " %7.2f", pLutLib->pLutDelays[i][k] );
+ printf( "\n" );
+ }
+ }
+ else
+ for ( i = 1; i <= pLutLib->LutMax; i++ )
+ printf( "%d %7.2f %7.2f\n", i, pLutLib->pLutAreas[i], pLutLib->pLutDelays[i][0] );
}
/**Function*************************************************************
@@ -169,7 +236,7 @@ int Fpga_LutLibDelaysAreDiscrete( Fpga_LutLib_t * pLutLib )
int i;
for ( i = 1; i <= pLutLib->LutMax; i++ )
{
- Delay = pLutLib->pLutDelays[i];
+ Delay = pLutLib->pLutDelays[i][0];
if ( ((float)((int)Delay)) != Delay )
return 0;
}
diff --git a/src/map/fpga/fpgaMatch.c b/src/map/fpga/fpgaMatch.c
index 20444209..73fa1258 100644
--- a/src/map/fpga/fpgaMatch.c
+++ b/src/map/fpga/fpgaMatch.c
@@ -30,7 +30,7 @@ static Fpga_Cut_t * Fpga_MappingAreaWithoutNode( Fpga_Man_t * p, Fpga_Node_t * p
static int Fpga_MappingMatchesAreaArray( Fpga_Man_t * p, Fpga_NodeVec_t * vNodes );
////////////////////////////////////////////////////////////////////////
-/// FUNCTION DEFITIONS ///
+/// FUNCTION DEFINITIONS ///
////////////////////////////////////////////////////////////////////////
/**Function*************************************************************
@@ -87,6 +87,18 @@ int Fpga_MappingMatches( Fpga_Man_t * p, int fDelayOriented )
Extra_ProgressBarUpdate( pProgress, i, "Matches ..." );
}
Extra_ProgressBarStop( pProgress );
+/*
+ if ( !fDelayOriented )
+ {
+ float Area = 0.0;
+ for ( i = 0; i < p->nOutputs; i++ )
+ {
+ printf( "%5.2f ", Fpga_Regular(p->pOutputs[i])->pCutBest->aFlow );
+ Area += Fpga_Regular(p->pOutputs[i])->pCutBest->aFlow;
+ }
+ printf( "\nTotal = %5.2f\n", Area );
+ }
+*/
return 1;
}
@@ -128,7 +140,7 @@ clk = clock();
Fpga_CutGetParameters( p, pCut );
//p->time2 += clock() - clk;
// drop the cut if it does not meet the required times
- if ( pCut->tArrival > pNode->tRequired )
+ if ( Fpga_FloatMoreThan(p, pCut->tArrival, pNode->tRequired) )
continue;
// if no cut is assigned, use the current one
if ( pNode->pCutBest == NULL )
@@ -140,11 +152,11 @@ clk = clock();
// (1) delay oriented mapping (first traversal), delay first, area-flow as a tie-breaker
// (2) area recovery (subsequent traversals), area-flow first, delay as a tie-breaker
if ( (fDelayOriented &&
- (pNode->pCutBest->tArrival > pCut->tArrival ||
- pNode->pCutBest->tArrival == pCut->tArrival && pNode->pCutBest->aFlow > pCut->aFlow)) ||
+ (Fpga_FloatMoreThan(p, pNode->pCutBest->tArrival, pCut->tArrival) ||
+ Fpga_FloatEqual(p, pNode->pCutBest->tArrival, pCut->tArrival) && Fpga_FloatMoreThan(p, pNode->pCutBest->aFlow, pCut->aFlow) )) ||
(!fDelayOriented &&
- (pNode->pCutBest->aFlow > pCut->aFlow ||
- pNode->pCutBest->aFlow == pCut->aFlow && pNode->pCutBest->tArrival > pCut->tArrival)) )
+ (Fpga_FloatMoreThan(p, pNode->pCutBest->aFlow, pCut->aFlow) ||
+ Fpga_FloatEqual(p, pNode->pCutBest->aFlow, pCut->aFlow) && Fpga_FloatMoreThan(p, pNode->pCutBest->tArrival, pCut->tArrival))) )
{
pNode->pCutBest = pCut;
}
@@ -277,7 +289,7 @@ clk = clock();
pCut->tArrival = Fpga_TimeCutComputeArrival( p, pCut );
//p->time2 += clock() - clk;
// drop the cut if it does not meet the required times
- if ( pCut->tArrival > pNode->tRequired )
+ if ( Fpga_FloatMoreThan( p, pCut->tArrival, pNode->tRequired ) )
continue;
// get the area of this cut
pCut->aFlow = Fpga_CutGetAreaDerefed( p, pCut );
@@ -288,8 +300,8 @@ clk = clock();
continue;
}
// choose the best cut as follows: exact area first, delay as a tie-breaker
- if ( pNode->pCutBest->aFlow > pCut->aFlow ||
- pNode->pCutBest->aFlow == pCut->aFlow && pNode->pCutBest->tArrival > pCut->tArrival )
+ if ( Fpga_FloatMoreThan(p, pNode->pCutBest->aFlow, pCut->aFlow) ||
+ Fpga_FloatEqual(p, pNode->pCutBest->aFlow, pCut->aFlow) && Fpga_FloatMoreThan(p, pNode->pCutBest->tArrival, pCut->tArrival) )
{
pNode->pCutBest = pCut;
}
@@ -311,7 +323,7 @@ clk = clock();
if ( pNode->nRefs )
{
pNode->pCutBest->aFlow = Fpga_CutRef( p, pNode, pNode->pCutBest, 0 );
- assert( pNode->pCutBest->aFlow <= aAreaCutBest );
+// assert( pNode->pCutBest->aFlow <= aAreaCutBest );
// assert( pNode->tRequired < FPGA_FLOAT_LARGE );
}
return 1;
@@ -398,7 +410,7 @@ clk = clock();
pCut->tArrival = Fpga_TimeCutComputeArrival( p, pCut );
//p->time2 += clock() - clk;
// drop the cut if it does not meet the required times
- if ( pCut->tArrival > pNode->tRequired )
+ if ( Fpga_FloatMoreThan( p, pCut->tArrival, pNode->tRequired ) )
continue;
// get the area of this cut
pCut->aFlow = Fpga_CutGetSwitchDerefed( p, pNode, pCut );
@@ -409,8 +421,8 @@ clk = clock();
continue;
}
// choose the best cut as follows: exact area first, delay as a tie-breaker
- if ( pNode->pCutBest->aFlow > pCut->aFlow ||
- pNode->pCutBest->aFlow == pCut->aFlow && pNode->pCutBest->tArrival > pCut->tArrival )
+ if ( Fpga_FloatMoreThan(p, pNode->pCutBest->aFlow, pCut->aFlow) ||
+ Fpga_FloatEqual(p, pNode->pCutBest->aFlow, pCut->aFlow) && Fpga_FloatMoreThan(p, pNode->pCutBest->tArrival, pCut->tArrival) )
{
pNode->pCutBest = pCut;
}
@@ -501,7 +513,7 @@ void Fpga_Experiment( Fpga_Man_t * p )
AreaBefore = pNode->pCutBest->aFlow;
pNode->pCutBest->aFlow = FPGA_FLOAT_LARGE;
- Fpga_TimeComputeRequiredGlobal( p );
+ Fpga_TimeComputeRequiredGlobal( p, 0 );
vNodesTfo = Fpga_CollectNodeTfo( p, pNode );
if ( Fpga_MappingMatchesAreaArray( p, vNodesTfo ) == 0 )
diff --git a/src/map/fpga/fpgaSwitch.c b/src/map/fpga/fpgaSwitch.c
index 8cc77990..5e881959 100644
--- a/src/map/fpga/fpgaSwitch.c
+++ b/src/map/fpga/fpgaSwitch.c
@@ -23,7 +23,7 @@
////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////
-/// FUNCTION DEFITIONS ///
+/// FUNCTION DEFINITIONS ///
////////////////////////////////////////////////////////////////////////
/**function*************************************************************
@@ -139,8 +139,8 @@ float Fpga_MappingGetSwitching( Fpga_Man_t * pMan, Fpga_NodeVec_t * vMapping )
}
// add buffer for each CO driven by a CI
for ( i = 0; i < pMan->nOutputs; i++ )
- if ( Fpga_NodeIsVar(pMan->pOutputs[i]) && !Fpga_IsComplement(pMan->pOutputs[i]) )
- Switch += pMan->pOutputs[i]->Switching;
+ if ( Fpga_NodeIsVar(Fpga_Regular(pMan->pOutputs[i])) && !Fpga_IsComplement(pMan->pOutputs[i]) )
+ Switch += Fpga_Regular(pMan->pOutputs[i])->Switching;
return Switch;
}
diff --git a/src/map/fpga/fpgaTime.c b/src/map/fpga/fpgaTime.c
index 6cbe16f9..879cad4d 100644
--- a/src/map/fpga/fpgaTime.c
+++ b/src/map/fpga/fpgaTime.c
@@ -23,7 +23,7 @@
////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////
-/// FUNCTION DEFITIONS ///
+/// FUNCTION DEFINITIONS ///
////////////////////////////////////////////////////////////////////////
/**Function*************************************************************
@@ -46,7 +46,7 @@ float Fpga_TimeCutComputeArrival( Fpga_Man_t * pMan, Fpga_Cut_t * pCut )
for ( i = 0; i < pCut->nLeaves; i++ )
if ( tArrival < pCut->ppLeaves[i]->pCutBest->tArrival )
tArrival = pCut->ppLeaves[i]->pCutBest->tArrival;
- tArrival += pMan->pLutLib->pLutDelays[pCut->nLeaves];
+ tArrival += pMan->pLutLib->pLutDelays[pCut->nLeaves][0];
return tArrival;
}
@@ -87,13 +87,34 @@ float Fpga_TimeComputeArrivalMax( Fpga_Man_t * p )
{
float fRequired;
int i;
+ if ( p->fLatchPaths && p->nLatches == 0 )
+ {
+ printf( "Delay optimization of latch path is not performed because there is no latches.\n" );
+ p->fLatchPaths = 0;
+ }
// get the critical PO arrival time
fRequired = -FPGA_FLOAT_LARGE;
- for ( i = 0; i < p->nOutputs; i++ )
+ if ( p->fLatchPaths )
{
- if ( Fpga_NodeIsConst(p->pOutputs[i]) )
- continue;
- fRequired = FPGA_MAX( fRequired, Fpga_Regular(p->pOutputs[i])->pCutBest->tArrival );
+ for ( i = p->nOutputs - p->nLatches; i < p->nOutputs; i++ )
+ {
+ if ( Fpga_NodeIsConst(p->pOutputs[i]) )
+ continue;
+ fRequired = FPGA_MAX( fRequired, Fpga_Regular(p->pOutputs[i])->pCutBest->tArrival );
+// printf( " %5.1f", Fpga_Regular(p->pOutputs[i])->pCutBest->tArrival );
+ }
+// printf( "Required latches = %5.1f\n", fRequired );
+ }
+ else
+ {
+ for ( i = 0; i < p->nOutputs; i++ )
+ {
+ if ( Fpga_NodeIsConst(p->pOutputs[i]) )
+ continue;
+ fRequired = FPGA_MAX( fRequired, Fpga_Regular(p->pOutputs[i])->pCutBest->tArrival );
+// printf( " %5.1f", Fpga_Regular(p->pOutputs[i])->pCutBest->tArrival );
+ }
+// printf( "Required outputs = %5.1f\n", fRequired );
}
return fRequired;
}
@@ -109,9 +130,24 @@ float Fpga_TimeComputeArrivalMax( Fpga_Man_t * p )
SeeAlso []
***********************************************************************/
-void Fpga_TimeComputeRequiredGlobal( Fpga_Man_t * p )
+void Fpga_TimeComputeRequiredGlobal( Fpga_Man_t * p, int fFirstTime )
{
p->fRequiredGlo = Fpga_TimeComputeArrivalMax( p );
+ // update the required times according to the target
+ if ( p->DelayTarget != -1 )
+ {
+ if ( p->fRequiredGlo > p->DelayTarget + p->fEpsilon )
+ {
+ if ( fFirstTime )
+ printf( "Cannot meet the target required times (%4.2f). Mapping continues anyway.\n", p->DelayTarget );
+ }
+ else if ( p->fRequiredGlo < p->DelayTarget - p->fEpsilon )
+ {
+ if ( fFirstTime )
+ printf( "Relaxing the required times from (%4.2f) to the target (%4.2f).\n", p->fRequiredGlo, p->DelayTarget );
+ p->fRequiredGlo = p->DelayTarget;
+ }
+ }
Fpga_TimeComputeRequired( p, p->fRequiredGlo );
}
@@ -133,10 +169,23 @@ void Fpga_TimeComputeRequired( Fpga_Man_t * p, float fRequired )
for ( i = 0; i < p->vAnds->nSize; i++ )
p->vAnds->pArray[i]->tRequired = FPGA_FLOAT_LARGE;
// set the required times for the POs
- for ( i = 0; i < p->nOutputs; i++ )
- Fpga_Regular(p->pOutputs[i])->tRequired = fRequired;
+ if ( p->fLatchPaths )
+ for ( i = p->nOutputs - p->nLatches; i < p->nOutputs; i++ )
+ Fpga_Regular(p->pOutputs[i])->tRequired = fRequired;
+ else
+ for ( i = 0; i < p->nOutputs; i++ )
+ Fpga_Regular(p->pOutputs[i])->tRequired = fRequired;
// collect nodes reachable from POs in the DFS order through the best cuts
Fpga_TimePropagateRequired( p, p->vMapping );
+/*
+ {
+ int Counter = 0;
+ for ( i = 0; i < p->vAnds->nSize; i++ )
+ if ( p->vAnds->pArray[i]->tRequired > FPGA_FLOAT_LARGE - 100 )
+ Counter++;
+ printf( "The number of nodes with large required times = %d.\n", Counter );
+ }
+*/
}
/**Function*************************************************************
@@ -167,7 +216,7 @@ void Fpga_TimePropagateRequired( Fpga_Man_t * p, Fpga_NodeVec_t * vNodes )
if ( !Fpga_NodeIsAnd(pNode) )
continue;
// get the required time for children
- fRequired = pNode->tRequired - p->pLutLib->pLutDelays[pNode->pCutBest->nLeaves];
+ fRequired = pNode->tRequired - p->pLutLib->pLutDelays[pNode->pCutBest->nLeaves][0];
// update the required time of the children
for ( i = 0; i < pNode->pCutBest->nLeaves; i++ )
{
diff --git a/src/map/fpga/fpgaTruth.c b/src/map/fpga/fpgaTruth.c
index 17c6385c..e3eb487f 100644
--- a/src/map/fpga/fpgaTruth.c
+++ b/src/map/fpga/fpgaTruth.c
@@ -24,7 +24,7 @@
////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////
-/// FUNCTION DEFITIONS ///
+/// FUNCTION DEFINITIONS ///
////////////////////////////////////////////////////////////////////////
/**Function*************************************************************
@@ -94,12 +94,71 @@ void * Fpga_TruthsCutBdd( void * dd, Fpga_Cut_t * pCut )
Cudd_RecursiveDeref( dd, (DdNode*)pCut->uSign );
pCut->uSign = 0;
}
+// printf( "%d ", vVisited->nSize );
Fpga_NodeVecFree( vVisited );
Cudd_Deref( bFunc );
return bFunc;
}
+/**Function*************************************************************
+
+ Synopsis [Recursively derives the truth table for the cut.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Fpga_CutVolume_rec( Fpga_Cut_t * pCut, Fpga_NodeVec_t * vVisited )
+{
+ assert( !Fpga_IsComplement(pCut) );
+ if ( pCut->fMark )
+ return;
+ pCut->fMark = 1;
+ Fpga_CutVolume_rec( Fpga_CutRegular(pCut->pOne), vVisited );
+ Fpga_CutVolume_rec( Fpga_CutRegular(pCut->pTwo), vVisited );
+ Fpga_NodeVecPush( vVisited, (Fpga_Node_t *)pCut );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Derives the truth table for one cut.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Fpga_CutVolume( Fpga_Cut_t * pCut )
+{
+ Fpga_NodeVec_t * vVisited;
+ int Volume, i;
+ assert( pCut->nLeaves > 1 );
+ // set the leaf variables
+ for ( i = 0; i < pCut->nLeaves; i++ )
+ pCut->ppLeaves[i]->pCuts->fMark = 1;
+ // recursively compute the function
+ vVisited = Fpga_NodeVecAlloc( 10 );
+ Fpga_CutVolume_rec( pCut, vVisited );
+ // clean the marks
+ for ( i = 0; i < pCut->nLeaves; i++ )
+ pCut->ppLeaves[i]->pCuts->fMark = 0;
+ for ( i = 0; i < vVisited->nSize; i++ )
+ {
+ pCut = (Fpga_Cut_t *)vVisited->pArray[i];
+ pCut->fMark = 0;
+ }
+ Volume = vVisited->nSize;
+ printf( "%d ", Volume );
+ Fpga_NodeVecFree( vVisited );
+ return Volume;
+}
+
////////////////////////////////////////////////////////////////////////
/// END OF FILE ///
////////////////////////////////////////////////////////////////////////
diff --git a/src/map/fpga/fpgaUtils.c b/src/map/fpga/fpgaUtils.c
index db0f9623..b951fd8f 100644
--- a/src/map/fpga/fpgaUtils.c
+++ b/src/map/fpga/fpgaUtils.c
@@ -30,10 +30,11 @@ static int Fpga_MappingCompareOutputDelay( Fpga_Node_t ** ppNode1, Fpga_Node_t
static void Fpga_MappingFindLatest( Fpga_Man_t * p, int * pNodes, int nNodesMax );
static void Fpga_DfsLim_rec( Fpga_Node_t * pNode, int Level, Fpga_NodeVec_t * vNodes );
static int Fpga_CollectNodeTfo_rec( Fpga_Node_t * pNode, Fpga_Node_t * pPivot, Fpga_NodeVec_t * vVisited, Fpga_NodeVec_t * vTfo );
+static Fpga_NodeVec_t * Fpga_MappingOrderCosByLevel( Fpga_Man_t * pMan );
static Fpga_Man_t * s_pMan = NULL;
////////////////////////////////////////////////////////////////////////
-/// FUNCTION DEFITIONS ///
+/// FUNCTION DEFINITIONS ///
////////////////////////////////////////////////////////////////////////
@@ -50,9 +51,11 @@ static Fpga_Man_t * s_pMan = NULL;
***********************************************************************/
Fpga_NodeVec_t * Fpga_MappingDfs( Fpga_Man_t * pMan, int fCollectEquiv )
{
- Fpga_NodeVec_t * vNodes;
+ Fpga_NodeVec_t * vNodes;//, * vNodesCo;
Fpga_Node_t * pNode;
int i;
+ // collect the CO nodes by level
+// vNodesCo = Fpga_MappingOrderCosByLevel( pMan );
// start the array
vNodes = Fpga_NodeVecAlloc( 100 );
// collect the PIs
@@ -65,10 +68,15 @@ Fpga_NodeVec_t * Fpga_MappingDfs( Fpga_Man_t * pMan, int fCollectEquiv )
// perform the traversal
for ( i = 0; i < pMan->nOutputs; i++ )
Fpga_MappingDfs_rec( Fpga_Regular(pMan->pOutputs[i]), vNodes, fCollectEquiv );
+// for ( i = vNodesCo->nSize - 1; i >= 0 ; i-- )
+// for ( pNode = vNodesCo->pArray[i]; pNode; pNode = (Fpga_Node_t *)pNode->pData0 )
+// Fpga_MappingDfs_rec( pNode, vNodes, fCollectEquiv );
+ // clean the node marks
for ( i = 0; i < vNodes->nSize; i++ )
vNodes->pArray[i]->fMark0 = 0;
// for ( i = 0; i < pMan->nOutputs; i++ )
// Fpga_MappingUnmark_rec( Fpga_Regular(pMan->pOutputs[i]) );
+// Fpga_NodeVecFree( vNodesCo );
return vNodes;
}
@@ -930,6 +938,47 @@ void Fpga_ManReportChoices( Fpga_Man_t * pMan )
*/
}
+/**Function*************************************************************
+
+ Synopsis [Returns the array of CO nodes sorted by level.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Fpga_NodeVec_t * Fpga_MappingOrderCosByLevel( Fpga_Man_t * pMan )
+{
+ Fpga_Node_t * pNode;
+ Fpga_NodeVec_t * vNodes;
+ int i, nLevels;
+ // get the largest level of a CO
+ nLevels = Fpga_MappingMaxLevel( pMan );
+ // allocate the array of nodes
+ vNodes = Fpga_NodeVecAlloc( nLevels + 1 );
+ for ( i = 0; i <= nLevels; i++ )
+ Fpga_NodeVecPush( vNodes, NULL );
+ // clean the marks
+ for ( i = 0; i < pMan->nOutputs; i++ )
+ Fpga_Regular(pMan->pOutputs[i])->fMark0 = 0;
+ // put the nodes into the structure
+ for ( i = 0; i < pMan->nOutputs; i++ )
+ {
+ pNode = Fpga_Regular(pMan->pOutputs[i]);
+ if ( pNode->fMark0 )
+ continue;
+ pNode->fMark0 = 1;
+ pNode->pData0 = (char *)Fpga_NodeVecReadEntry( vNodes, pNode->Level );
+ Fpga_NodeVecWriteEntry( vNodes, pNode->Level, pNode );
+ }
+ for ( i = 0; i < pMan->nOutputs; i++ )
+ Fpga_Regular(pMan->pOutputs[i])->fMark0 = 0;
+ return vNodes;
+
+}
+
////////////////////////////////////////////////////////////////////////
/// END OF FILE ///
////////////////////////////////////////////////////////////////////////
diff --git a/src/map/fpga/fpgaVec.c b/src/map/fpga/fpgaVec.c
index a8c6b983..70a4a7ac 100644
--- a/src/map/fpga/fpgaVec.c
+++ b/src/map/fpga/fpgaVec.c
@@ -25,7 +25,7 @@
static int Fpga_NodeVecCompareLevels( Fpga_Node_t ** pp1, Fpga_Node_t ** pp2 );
////////////////////////////////////////////////////////////////////////
-/// FUNCTION DEFITIONS ///
+/// FUNCTION DEFINITIONS ///
////////////////////////////////////////////////////////////////////////
/**Function*************************************************************
diff --git a/src/map/if/if.h b/src/map/if/if.h
new file mode 100644
index 00000000..b3d2d745
--- /dev/null
+++ b/src/map/if/if.h
@@ -0,0 +1,410 @@
+/**CFile****************************************************************
+
+ FileName [if.h]
+
+ SystemName [ABC: Logic synthesis and verification system.]
+
+ PackageName [FPGA mapping based on priority cuts.]
+
+ Synopsis [External declarations.]
+
+ Author [Alan Mishchenko]
+
+ Affiliation [UC Berkeley]
+
+ Date [Ver. 1.0. Started - November 21, 2006.]
+
+ Revision [$Id: if.h,v 1.00 2006/11/21 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#ifndef __IF_H__
+#define __IF_H__
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+////////////////////////////////////////////////////////////////////////
+/// INCLUDES ///
+////////////////////////////////////////////////////////////////////////
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <assert.h>
+#include <time.h>
+#include "vec.h"
+#include "mem.h"
+#include "tim.h"
+
+////////////////////////////////////////////////////////////////////////
+/// PARAMETERS ///
+////////////////////////////////////////////////////////////////////////
+
+// the maximum size of LUTs used for mapping (should be the same as FPGA_MAX_LUTSIZE defined in "fpga.h"!!!)
+#define IF_MAX_LUTSIZE 32
+// the largest possible number of LUT inputs when funtionality of the LUTs are computed
+#define IF_MAX_FUNC_LUTSIZE 15
+// a very large number
+#define IF_INFINITY 100000000
+// the largest possible user cut cost
+#define IF_COST_MAX ((1<<14)-1)
+
+// object types
+typedef enum {
+ IF_NONE, // 0: non-existent object
+ IF_CONST1, // 1: constant 1
+ IF_CI, // 2: combinational input
+ IF_CO, // 3: combinational output
+ IF_AND, // 4: AND node
+ IF_VOID // 5: unused object
+} If_Type_t;
+
+////////////////////////////////////////////////////////////////////////
+/// BASIC TYPES ///
+////////////////////////////////////////////////////////////////////////
+
+typedef struct If_Man_t_ If_Man_t;
+typedef struct If_Par_t_ If_Par_t;
+typedef struct If_Lib_t_ If_Lib_t;
+typedef struct If_Obj_t_ If_Obj_t;
+typedef struct If_Cut_t_ If_Cut_t;
+typedef struct If_Set_t_ If_Set_t;
+
+// parameters
+struct If_Par_t_
+{
+ // user-controlable parameters
+ int nLutSize; // the LUT size
+ int nCutsMax; // the max number of cuts
+ int nFlowIters; // the number of iterations of area recovery
+ int nAreaIters; // the number of iterations of area recovery
+ float DelayTarget; // delay target
+ int fPreprocess; // preprossing
+ int fArea; // area-oriented mapping
+ int fFancy; // a fancy feature
+ int fExpRed; // expand/reduce of the best cuts
+ int fLatchPaths; // reset timing on latch paths
+ int fEdge; // uses edge-based cut selection heuristics
+ int fCutMin; // performs cut minimization by removing functionally reducdant variables
+ int fSeqMap; // sequential mapping
+ int fVerbose; // the verbosity flag
+ // internal parameters
+ int fAreaOnly; // area only mode
+ int fTruth; // truth table computation enabled
+ int fUsePerm; // use permutation (delay info)
+ int fUseBdds; // use local BDDs as a cost function
+ int fUseSops; // use local SOPs as a cost function
+ int fUseCnfs; // use local CNFs as a cost function
+ int fUseMv; // use local MV-SOPs as a cost function
+ int nLatches; // the number of latches in seq mapping
+ int fLiftLeaves; // shift the leaves for seq mapping
+ If_Lib_t * pLutLib; // the LUT library
+ float * pTimesArr; // arrival times
+ float * pTimesReq; // required times
+ int (* pFuncCost) (If_Cut_t *); // procedure to compute the user's cost of a cut
+ int (* pFuncUser) (If_Man_t *, If_Obj_t *, If_Cut_t *); // procedure called for each cut when cut computation is finished
+ void * pReoMan; // reordering manager
+};
+
+// the LUT library
+struct If_Lib_t_
+{
+ char * pName; // the name of the LUT library
+ int LutMax; // the maximum LUT size
+ int fVarPinDelays; // set to 1 if variable pin delays are specified
+ float pLutAreas[IF_MAX_LUTSIZE+1]; // the areas of LUTs
+ float pLutDelays[IF_MAX_LUTSIZE+1][IF_MAX_LUTSIZE+1];// the delays of LUTs
+};
+
+// manager
+struct If_Man_t_
+{
+ // mapping parameters
+ If_Par_t * pPars;
+ // mapping nodes
+ If_Obj_t * pConst1; // the constant 1 node
+ Vec_Ptr_t * vCis; // the primary inputs
+ Vec_Ptr_t * vCos; // the primary outputs
+ Vec_Ptr_t * vObjs; // all objects
+ Vec_Ptr_t * vObjsRev; // reverse topological order of objects
+// Vec_Ptr_t * vMapped; // objects used in the mapping
+ Vec_Ptr_t * vTemp; // temporary array
+ int nObjs[IF_VOID];// the number of objects by type
+ // various data
+ int nLevelMax; // the max number of AIG levels
+ float fEpsilon; // epsilon used for comparison
+ float RequiredGlo; // global required times
+ float RequiredGlo2; // global required times
+ float AreaGlo; // global area
+ int nNets; // the sum total of fanins of all LUTs in the mapping
+ int nCutsUsed; // the number of cuts currently used
+ int nCutsMerged; // the total number of cuts merged
+ unsigned * puTemp[4]; // used for the truth table computation
+ int SortMode; // one of the three sorting modes
+ int fNextRound; // set to 1 after the first round
+ int nChoices; // the number of choice nodes
+ // sequential mapping
+ Vec_Ptr_t * vLatchOrder; // topological ordering of latches
+ Vec_Int_t * vLags; // sequentail lags of all nodes
+ int nAttempts; // the number of attempts in binary search
+ int nMaxIters; // the maximum number of iterations
+ int Period; // the current value of the clock period (for seq mapping)
+ // memory management
+ int nTruthWords; // the size of the truth table if allocated
+ int nPermWords; // the size of the permutation array (in words)
+ int nObjBytes; // the size of the object
+ int nCutBytes; // the size of the cut
+ int nSetBytes; // the size of the cut set
+ Mem_Fixed_t * pMemObj; // memory manager for objects (entrysize = nEntrySize)
+ Mem_Fixed_t * pMemSet; // memory manager for sets of cuts (entrysize = nCutSize*(nCutsMax+1))
+ If_Set_t * pMemCi; // memory for CI cutsets
+ If_Set_t * pMemAnd; // memory for AND cutsets
+ If_Set_t * pFreeList; // the list of free cutsets
+ int nSmallSupp; // the small support
+ // timing manager
+ Tim_Man_t * pManTim;
+};
+
+// priority cut
+struct If_Cut_t_
+{
+ float Delay; // delay of the cut
+ float Area; // area (or area-flow) of the cut
+ float AveRefs; // the average number of leaf references
+ float Edge; // the edge flow
+ unsigned uSign; // cut signature
+ unsigned Cost : 14; // the user's cost of the cut
+ unsigned fCompl : 1; // the complemented attribute
+ unsigned fUser : 1; // using the user's area and delay
+ unsigned nLimit : 8; // the maximum number of leaves
+ unsigned nLeaves : 8; // the number of leaves
+ int * pLeaves; // array of fanins
+ char * pPerm; // permutation
+ unsigned * pTruth; // the truth table
+};
+
+// set of priority cut
+struct If_Set_t_
+{
+ short nCutsMax; // the max number of cuts
+ short nCuts; // the current number of cuts
+ If_Set_t * pNext; // next cutset in the free list
+ If_Cut_t ** ppCuts; // the array of pointers to the cuts
+};
+
+// node extension
+struct If_Obj_t_
+{
+ unsigned Type : 4; // object
+ unsigned fCompl0 : 1; // complemented attribute
+ unsigned fCompl1 : 1; // complemented attribute
+ unsigned fPhase : 1; // phase of the node
+ unsigned fRepr : 1; // representative of the equivalence class
+ unsigned fMark : 1; // multipurpose mark
+ unsigned fVisit : 1; // multipurpose mark
+ unsigned Level : 22; // logic level of the node
+ int Id; // integer ID
+ int IdPio; // integer ID of PIs/POs
+ int nRefs; // the number of references
+ int nVisits; // the number of visits to this node
+ int nVisitsCopy; // the number of visits to this node
+ If_Obj_t * pFanin0; // the first fanin
+ If_Obj_t * pFanin1; // the second fanin
+ If_Obj_t * pEquiv; // the choice node
+ float EstRefs; // estimated reference counter
+ float Required; // required time of the onde
+ float LValue; // sequential arrival time of the node
+ void * pCopy; // used for object duplication
+ If_Set_t * pCutSet; // the pointer to the cutset
+ If_Cut_t CutBest; // the best cut selected
+};
+
+static inline If_Obj_t * If_Regular( If_Obj_t * p ) { return (If_Obj_t *)((unsigned long)(p) & ~01); }
+static inline If_Obj_t * If_Not( If_Obj_t * p ) { return (If_Obj_t *)((unsigned long)(p) ^ 01); }
+static inline If_Obj_t * If_NotCond( If_Obj_t * p, int c ) { return (If_Obj_t *)((unsigned long)(p) ^ (c)); }
+static inline int If_IsComplement( If_Obj_t * p ) { return (int )(((unsigned long)p) & 01); }
+
+static inline int If_ManCiNum( If_Man_t * p ) { return p->nObjs[IF_CI]; }
+static inline int If_ManCoNum( If_Man_t * p ) { return p->nObjs[IF_CO]; }
+static inline int If_ManAndNum( If_Man_t * p ) { return p->nObjs[IF_AND]; }
+static inline int If_ManObjNum( If_Man_t * p ) { return Vec_PtrSize(p->vObjs); }
+
+static inline If_Obj_t * If_ManConst1( If_Man_t * p ) { return p->pConst1; }
+static inline If_Obj_t * If_ManCi( If_Man_t * p, int i ) { return (If_Obj_t *)Vec_PtrEntry( p->vCis, i ); }
+static inline If_Obj_t * If_ManCo( If_Man_t * p, int i ) { return (If_Obj_t *)Vec_PtrEntry( p->vCos, i ); }
+static inline If_Obj_t * If_ManLi( If_Man_t * p, int i ) { return (If_Obj_t *)Vec_PtrEntry( p->vCos, If_ManCoNum(p) - p->pPars->nLatches + i ); }
+static inline If_Obj_t * If_ManLo( If_Man_t * p, int i ) { return (If_Obj_t *)Vec_PtrEntry( p->vCis, If_ManCiNum(p) - p->pPars->nLatches + i ); }
+static inline If_Obj_t * If_ManObj( If_Man_t * p, int i ) { return (If_Obj_t *)Vec_PtrEntry( p->vObjs, i ); }
+
+static inline int If_ObjIsConst1( If_Obj_t * pObj ) { return pObj->Type == IF_CONST1; }
+static inline int If_ObjIsCi( If_Obj_t * pObj ) { return pObj->Type == IF_CI; }
+static inline int If_ObjIsCo( If_Obj_t * pObj ) { return pObj->Type == IF_CO; }
+//static inline int If_ObjIsPi( If_Obj_t * pObj ) { return If_ObjIsCi(pObj) && pObj->pFanin0 == NULL; }
+static inline int If_ObjIsLatch( If_Obj_t * pObj ) { return If_ObjIsCi(pObj) && pObj->pFanin0 != NULL; }
+static inline int If_ObjIsAnd( If_Obj_t * pObj ) { return pObj->Type == IF_AND; }
+
+static inline If_Obj_t * If_ObjFanin0( If_Obj_t * pObj ) { return pObj->pFanin0; }
+static inline If_Obj_t * If_ObjFanin1( If_Obj_t * pObj ) { return pObj->pFanin1; }
+static inline int If_ObjFaninC0( If_Obj_t * pObj ) { return pObj->fCompl0; }
+static inline int If_ObjFaninC1( If_Obj_t * pObj ) { return pObj->fCompl1; }
+static inline void * If_ObjCopy( If_Obj_t * pObj ) { return pObj->pCopy; }
+static inline void If_ObjSetCopy( If_Obj_t * pObj, void * pCopy ) { pObj->pCopy = pCopy; }
+static inline void If_ObjSetChoice( If_Obj_t * pObj, If_Obj_t * pEqu ) { pObj->pEquiv = pEqu; }
+
+static inline If_Cut_t * If_ObjCutBest( If_Obj_t * pObj ) { return &pObj->CutBest; }
+static inline unsigned If_ObjCutSign( unsigned ObjId ) { return (1 << (ObjId % 31)); }
+
+static inline float If_ObjArrTime( If_Obj_t * pObj ) { return If_ObjCutBest(pObj)->Delay; }
+static inline void If_ObjSetArrTime( If_Obj_t * pObj, float ArrTime ) { If_ObjCutBest(pObj)->Delay = ArrTime; }
+
+static inline float If_ObjLValue( If_Obj_t * pObj ) { return pObj->LValue; }
+static inline void If_ObjSetLValue( If_Obj_t * pObj, float LValue ) { pObj->LValue = LValue; }
+
+static inline void * If_CutData( If_Cut_t * pCut ) { return *(void **)pCut; }
+static inline void If_CutSetData( If_Cut_t * pCut, void * pData ) { *(void **)pCut = pData; }
+
+static inline int If_CutLeaveNum( If_Cut_t * pCut ) { return pCut->nLeaves; }
+static inline int * If_CutLeaves( If_Cut_t * pCut ) { return pCut->pLeaves; }
+static inline unsigned * If_CutTruth( If_Cut_t * pCut ) { return pCut->pTruth; }
+static inline unsigned If_CutSuppMask( If_Cut_t * pCut ) { return (~(unsigned)0) >> (32-pCut->nLeaves); }
+static inline int If_CutTruthWords( int nVarsMax ) { return nVarsMax <= 5 ? 1 : (1 << (nVarsMax - 5)); }
+static inline int If_CutPermWords( int nVarsMax ) { return nVarsMax / sizeof(int) + ((nVarsMax % sizeof(int)) > 0); }
+
+static inline float If_CutLutArea( If_Man_t * p, If_Cut_t * pCut ) { return pCut->fUser? (float)pCut->Cost : (p->pPars->pLutLib? p->pPars->pLutLib->pLutAreas[pCut->nLeaves] : (float)1.0); }
+
+////////////////////////////////////////////////////////////////////////
+/// MACRO DEFINITIONS ///
+////////////////////////////////////////////////////////////////////////
+
+#define IF_MIN(a,b) (((a) < (b))? (a) : (b))
+#define IF_MAX(a,b) (((a) > (b))? (a) : (b))
+
+// the small and large numbers (min/max float are 1.17e-38/3.40e+38)
+#define IF_FLOAT_LARGE ((float)1.0e+20)
+#define IF_FLOAT_SMALL ((float)1.0e-20)
+#define IF_INT_LARGE (10000000)
+
+// iterator over the primary inputs
+#define If_ManForEachCi( p, pObj, i ) \
+ Vec_PtrForEachEntry( p->vCis, pObj, i )
+// iterator over the primary outputs
+#define If_ManForEachCo( p, pObj, i ) \
+ Vec_PtrForEachEntry( p->vCos, pObj, i )
+// iterator over the primary inputs
+#define If_ManForEachPi( p, pObj, i ) \
+ Vec_PtrForEachEntryStop( p->vCis, pObj, i, If_ManCiNum(p) - p->pPars->nLatches )
+// iterator over the primary outputs
+#define If_ManForEachPo( p, pObj, i ) \
+ Vec_PtrForEachEntryStop( p->vCos, pObj, i, If_ManCoNum(p) - p->pPars->nLatches )
+// iterator over the latches
+#define If_ManForEachLatchInput( p, pObj, i ) \
+ Vec_PtrForEachEntryStart( p->vCos, pObj, i, If_ManCoNum(p) - p->pPars->nLatches )
+#define If_ManForEachLatchOutput( p, pObj, i ) \
+ Vec_PtrForEachEntryStart( p->vCis, pObj, i, If_ManCiNum(p) - p->pPars->nLatches )
+// iterator over all objects in topological order
+#define If_ManForEachObj( p, pObj, i ) \
+ Vec_PtrForEachEntry( p->vObjs, pObj, i )
+// iterator over all objects in reverse topological order
+#define If_ManForEachObjReverse( p, pObj, i ) \
+ Vec_PtrForEachEntry( p->vObjsRev, pObj, i )
+// iterator over logic nodes
+#define If_ManForEachNode( p, pObj, i ) \
+ If_ManForEachObj( p, pObj, i ) if ( pObj->Type != IF_AND ) {} else
+// iterator over cuts of the node
+#define If_ObjForEachCut( pObj, pCut, i ) \
+ for ( i = 0; (i < (pObj)->pCutSet->nCuts) && ((pCut) = (pObj)->pCutSet->ppCuts[i]); i++ )
+// iterator over the leaves of the cut
+#define If_CutForEachLeaf( p, pCut, pLeaf, i ) \
+ for ( i = 0; (i < (int)(pCut)->nLeaves) && ((pLeaf) = If_ManObj(p, (pCut)->pLeaves[i])); i++ )
+#define If_CutForEachLeafReverse( p, pCut, pLeaf, i ) \
+ for ( i = (int)(pCut)->nLeaves - 1; (i >= 0) && ((pLeaf) = If_ManObj(p, (pCut)->pLeaves[i])); i-- )
+//#define If_CutForEachLeaf( p, pCut, pLeaf, i ) \
+// for ( i = 0; (i < (int)(pCut)->nLeaves) && ((pLeaf) = If_ManObj(p, p->pPars->fLiftLeaves? (pCut)->pLeaves[i] >> 8 : (pCut)->pLeaves[i])); i++ )
+// iterator over the leaves of the sequential cut
+#define If_CutForEachLeafSeq( p, pCut, pLeaf, Shift, i ) \
+ for ( i = 0; (i < (int)(pCut)->nLeaves) && ((pLeaf) = If_ManObj(p, (pCut)->pLeaves[i] >> 8)) && (((Shift) = ((pCut)->pLeaves[i] & 255)) >= 0); i++ )
+
+////////////////////////////////////////////////////////////////////////
+/// FUNCTION DECLARATIONS ///
+////////////////////////////////////////////////////////////////////////
+
+/*=== ifCore.c ===========================================================*/
+extern int If_ManPerformMapping( If_Man_t * p );
+extern int If_ManPerformMappingComb( If_Man_t * p );
+/*=== ifCut.c ============================================================*/
+extern int If_CutFilter( If_Set_t * pCutSet, If_Cut_t * pCut );
+extern void If_CutSort( If_Man_t * p, If_Set_t * pCutSet, If_Cut_t * pCut );
+extern int If_CutMerge( If_Cut_t * pCut0, If_Cut_t * pCut1, If_Cut_t * pCut );
+extern void If_CutPrint( If_Man_t * p, If_Cut_t * pCut );
+extern void If_CutPrintTiming( If_Man_t * p, If_Cut_t * pCut );
+extern void If_CutLift( If_Cut_t * pCut );
+extern void If_CutCopy( If_Man_t * p, If_Cut_t * pCutDest, If_Cut_t * pCutSrc );
+extern float If_CutAreaFlow( If_Man_t * p, If_Cut_t * pCut );
+extern float If_CutEdgeFlow( If_Man_t * p, If_Cut_t * pCut );
+extern float If_CutAverageRefs( If_Man_t * p, If_Cut_t * pCut );
+extern float If_CutAreaDeref( If_Man_t * p, If_Cut_t * pCut );
+extern float If_CutAreaRef( If_Man_t * p, If_Cut_t * pCut );
+extern float If_CutAreaDerefed( If_Man_t * p, If_Cut_t * pCut );
+extern float If_CutAreaRefed( If_Man_t * p, If_Cut_t * pCut );
+extern float If_CutEdgeDeref( If_Man_t * p, If_Cut_t * pCut );
+extern float If_CutEdgeRef( If_Man_t * p, If_Cut_t * pCut );
+extern float If_CutEdgeDerefed( If_Man_t * p, If_Cut_t * pCut );
+extern float If_CutEdgeRefed( If_Man_t * p, If_Cut_t * pCut );
+/*=== ifMan.c =============================================================*/
+extern If_Man_t * If_ManStart( If_Par_t * pPars );
+extern void If_ManRestart( If_Man_t * p );
+extern void If_ManStop( If_Man_t * p );
+extern If_Obj_t * If_ManCreateCi( If_Man_t * p );
+extern If_Obj_t * If_ManCreateCo( If_Man_t * p, If_Obj_t * pDriver );
+extern If_Obj_t * If_ManCreateAnd( If_Man_t * p, If_Obj_t * pFan0, If_Obj_t * pFan1 );
+extern If_Obj_t * If_ManCreateXor( If_Man_t * p, If_Obj_t * pFan0, If_Obj_t * pFan1 );
+extern If_Obj_t * If_ManCreateMux( If_Man_t * p, If_Obj_t * pFan0, If_Obj_t * pFan1, If_Obj_t * pCtrl );
+extern void If_ManCreateChoice( If_Man_t * p, If_Obj_t * pRepr );
+extern void If_ManSetupCutTriv( If_Man_t * p, If_Cut_t * pCut, int ObjId );
+extern void If_ManSetupCiCutSets( If_Man_t * p );
+extern If_Set_t * If_ManSetupNodeCutSet( If_Man_t * p, If_Obj_t * pObj );
+extern void If_ManDerefNodeCutSet( If_Man_t * p, If_Obj_t * pObj );
+extern void If_ManDerefChoiceCutSet( If_Man_t * p, If_Obj_t * pObj );
+extern void If_ManSetupSetAll( If_Man_t * p, int nCrossCut );
+/*=== ifMap.c =============================================================*/
+extern void If_ObjPerformMappingAnd( If_Man_t * p, If_Obj_t * pObj, int Mode, int fPreprocess );
+extern void If_ObjPerformMappingChoice( If_Man_t * p, If_Obj_t * pObj, int Mode, int fPreprocess );
+extern int If_ManPerformMappingRound( If_Man_t * p, int nCutsUsed, int Mode, int fPreprocess, char * pLabel );
+/*=== ifReduce.c ==========================================================*/
+extern void If_ManImproveMapping( If_Man_t * p );
+/*=== ifSeq.c =============================================================*/
+extern int If_ManPerformMappingSeq( If_Man_t * p );
+/*=== ifTime.c ============================================================*/
+extern float If_CutDelay( If_Man_t * p, If_Cut_t * pCut );
+extern void If_CutPropagateRequired( If_Man_t * p, If_Cut_t * pCut, float Required );
+/*=== ifTruth.c ===========================================================*/
+extern void If_CutComputeTruth( If_Man_t * p, If_Cut_t * pCut, If_Cut_t * pCut0, If_Cut_t * pCut1, int fCompl0, int fCompl1 );
+/*=== ifUtil.c ============================================================*/
+extern void If_ManCleanNodeCopy( If_Man_t * p );
+extern void If_ManCleanCutData( If_Man_t * p );
+extern void If_ManCleanMarkV( If_Man_t * p );
+extern float If_ManDelayMax( If_Man_t * p, int fSeq );
+extern void If_ManComputeRequired( If_Man_t * p );
+extern float If_ManScanMapping( If_Man_t * p );
+extern float If_ManScanMappingDirect( If_Man_t * p );
+extern float If_ManScanMappingSeq( If_Man_t * p );
+extern void If_ManResetOriginalRefs( If_Man_t * p );
+extern int If_ManCrossCut( If_Man_t * p );
+
+extern Vec_Ptr_t * If_ManReverseOrder( If_Man_t * p );
+extern void If_ManMarkMapping( If_Man_t * p );
+extern Vec_Ptr_t * If_ManCollectMappingDirect( If_Man_t * p );
+
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
+
+////////////////////////////////////////////////////////////////////////
+/// END OF FILE ///
+////////////////////////////////////////////////////////////////////////
+
diff --git a/src/map/if/ifCore.c b/src/map/if/ifCore.c
new file mode 100644
index 00000000..f7124703
--- /dev/null
+++ b/src/map/if/ifCore.c
@@ -0,0 +1,148 @@
+/**CFile****************************************************************
+
+ FileName [ifCore.c]
+
+ SystemName [ABC: Logic synthesis and verification system.]
+
+ PackageName [FPGA mapping based on priority cuts.]
+
+ Synopsis [The central part of the mapper.]
+
+ Author [Alan Mishchenko]
+
+ Affiliation [UC Berkeley]
+
+ Date [Ver. 1.0. Started - November 21, 2006.]
+
+ Revision [$Id: ifCore.c,v 1.00 2006/11/21 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "if.h"
+
+////////////////////////////////////////////////////////////////////////
+/// DECLARATIONS ///
+////////////////////////////////////////////////////////////////////////
+
+extern int s_MappingTime;
+
+////////////////////////////////////////////////////////////////////////
+/// FUNCTION DEFINITIONS ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int If_ManPerformMapping( If_Man_t * p )
+{
+ p->pPars->fAreaOnly = p->pPars->fArea; // temporary
+
+ // create the CI cutsets
+ If_ManSetupCiCutSets( p );
+ // allocate memory for other cutsets
+ If_ManSetupSetAll( p, If_ManCrossCut(p) );
+ // derive reverse top order
+ p->vObjsRev = If_ManReverseOrder( p );
+
+ // try sequential mapping
+ if ( p->pPars->fSeqMap )
+ {
+ int RetValue = 1;
+ printf( "Currently sequential mapping is not performed.\n" );
+// RetValue = If_ManPerformMappingSeq( p );
+ return RetValue;
+// return 1;
+ }
+
+ return If_ManPerformMappingComb( p );
+}
+
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int If_ManPerformMappingComb( If_Man_t * p )
+{
+ If_Obj_t * pObj;
+ int clkTotal = clock();
+ int i;
+
+ // set arrival times and fanout estimates
+ If_ManForEachCi( p, pObj, i )
+ {
+ If_ObjSetArrTime( pObj, p->pPars->pTimesArr[i] );
+ pObj->EstRefs = (float)1.0;
+ }
+
+ // delay oriented mapping
+ if ( p->pPars->fPreprocess && !p->pPars->fArea )
+ {
+ // map for delay
+ If_ManPerformMappingRound( p, p->pPars->nCutsMax, 0, 1, "Delay" );
+ // map for delay second option
+ p->pPars->fFancy = 1;
+ If_ManResetOriginalRefs( p );
+ If_ManPerformMappingRound( p, p->pPars->nCutsMax, 0, 1, "Delay-2" );
+ p->pPars->fFancy = 0;
+ // map for area
+ p->pPars->fArea = 1;
+ If_ManResetOriginalRefs( p );
+ If_ManPerformMappingRound( p, p->pPars->nCutsMax, 0, 1, "Area" );
+ p->pPars->fArea = 0;
+ }
+ else
+ If_ManPerformMappingRound( p, p->pPars->nCutsMax, 0, 0, "Delay" );
+
+ // try to improve area by expanding and reducing the cuts
+ if ( p->pPars->fExpRed && !p->pPars->fTruth )
+ If_ManImproveMapping( p );
+
+ // area flow oriented mapping
+ for ( i = 0; i < p->pPars->nFlowIters; i++ )
+ {
+ If_ManPerformMappingRound( p, p->pPars->nCutsMax, 1, 0, "Flow" );
+ if ( p->pPars->fExpRed && !p->pPars->fTruth )
+ If_ManImproveMapping( p );
+ }
+
+ // area oriented mapping
+ for ( i = 0; i < p->pPars->nAreaIters; i++ )
+ {
+ If_ManPerformMappingRound( p, p->pPars->nCutsMax, 2, 0, "Area" );
+ if ( p->pPars->fExpRed && !p->pPars->fTruth )
+ If_ManImproveMapping( p );
+ }
+
+ if ( p->pPars->fVerbose )
+ {
+// printf( "Total memory = %7.2f Mb. Peak cut memory = %7.2f Mb. ",
+// 1.0 * (p->nObjBytes + 2*sizeof(void *)) * If_ManObjNum(p) / (1<<20),
+// 1.0 * p->nSetBytes * Mem_FixedReadMaxEntriesUsed(p->pMemSet) / (1<<20) );
+ PRT( "Total time", clock() - clkTotal );
+ }
+// printf( "Cross cut memory = %d.\n", Mem_FixedReadMaxEntriesUsed(p->pMemSet) );
+ s_MappingTime = clock() - clkTotal;
+ return 1;
+}
+
+////////////////////////////////////////////////////////////////////////
+/// END OF FILE ///
+////////////////////////////////////////////////////////////////////////
+
+
diff --git a/src/map/if/ifCut.c b/src/map/if/ifCut.c
new file mode 100644
index 00000000..cc842c19
--- /dev/null
+++ b/src/map/if/ifCut.c
@@ -0,0 +1,988 @@
+/**CFile****************************************************************
+
+ FileName [ifCut.c]
+
+ SystemName [ABC: Logic synthesis and verification system.]
+
+ PackageName [FPGA mapping based on priority cuts.]
+
+ Synopsis [Cut computation.]
+
+ Author [Alan Mishchenko]
+
+ Affiliation [UC Berkeley]
+
+ Date [Ver. 1.0. Started - November 21, 2006.]
+
+ Revision [$Id: ifCut.c,v 1.00 2006/11/21 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "if.h"
+
+////////////////////////////////////////////////////////////////////////
+/// DECLARATIONS ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+/// FUNCTION DEFINITIONS ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+ Synopsis [Returns 1 if pDom is contained in pCut.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+static inline int If_CutCheckDominance( If_Cut_t * pDom, If_Cut_t * pCut )
+{
+ int i, k;
+ for ( i = 0; i < (int)pDom->nLeaves; i++ )
+ {
+ for ( k = 0; k < (int)pCut->nLeaves; k++ )
+ if ( pDom->pLeaves[i] == pCut->pLeaves[k] )
+ break;
+ if ( k == (int)pCut->nLeaves ) // node i in pDom is not contained in pCut
+ return 0;
+ }
+ // every node in pDom is contained in pCut
+ return 1;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Returns 1 if pDom is equal to pCut.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+static inline int If_CutCheckEquality( If_Cut_t * pDom, If_Cut_t * pCut )
+{
+ int i;
+ if ( (int)pDom->nLeaves != (int)pCut->nLeaves )
+ return 0;
+ for ( i = 0; i < (int)pDom->nLeaves; i++ )
+ if ( pDom->pLeaves[i] != pCut->pLeaves[i] )
+ return 0;
+ return 1;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Returns 1 if the cut is contained.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int If_CutFilter( If_Set_t * pCutSet, If_Cut_t * pCut )
+{
+ If_Cut_t * pTemp;
+ int i, k;
+ assert( pCutSet->ppCuts[pCutSet->nCuts] == pCut );
+ for ( i = 0; i < pCutSet->nCuts; i++ )
+ {
+ pTemp = pCutSet->ppCuts[i];
+ if ( pTemp->nLeaves > pCut->nLeaves )
+ {
+ // do not fiter the first cut
+ if ( i == 0 )
+ continue;
+ // skip the non-contained cuts
+ if ( (pTemp->uSign & pCut->uSign) != pCut->uSign )
+ continue;
+ // check containment seriously
+ if ( If_CutCheckDominance( pCut, pTemp ) )
+ {
+// p->ppCuts[i] = p->ppCuts[p->nCuts-1];
+// p->ppCuts[p->nCuts-1] = pTemp;
+// p->nCuts--;
+// i--;
+ // remove contained cut
+ for ( k = i; k < pCutSet->nCuts; k++ )
+ pCutSet->ppCuts[k] = pCutSet->ppCuts[k+1];
+ pCutSet->ppCuts[pCutSet->nCuts] = pTemp;
+ pCutSet->nCuts--;
+ i--;
+ }
+ }
+ else
+ {
+ // skip the non-contained cuts
+ if ( (pTemp->uSign & pCut->uSign) != pTemp->uSign )
+ continue;
+ // check containment seriously
+ if ( If_CutCheckDominance( pTemp, pCut ) )
+ return 1;
+ }
+ }
+ return 0;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Merges two cuts.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+static inline int If_CutMergeOrdered( If_Cut_t * pC0, If_Cut_t * pC1, If_Cut_t * pC )
+{
+ int i, k, c;
+ assert( pC0->nLeaves >= pC1->nLeaves );
+ // the case of the largest cut sizes
+ if ( pC0->nLeaves == pC->nLimit && pC1->nLeaves == pC->nLimit )
+ {
+ for ( i = 0; i < (int)pC0->nLeaves; i++ )
+ if ( pC0->pLeaves[i] != pC1->pLeaves[i] )
+ return 0;
+ for ( i = 0; i < (int)pC0->nLeaves; i++ )
+ pC->pLeaves[i] = pC0->pLeaves[i];
+ pC->nLeaves = pC0->nLeaves;
+ return 1;
+ }
+ // the case when one of the cuts is the largest
+ if ( pC0->nLeaves == pC->nLimit )
+ {
+ for ( i = 0; i < (int)pC1->nLeaves; i++ )
+ {
+ for ( k = (int)pC0->nLeaves - 1; k >= 0; k-- )
+ if ( pC0->pLeaves[k] == pC1->pLeaves[i] )
+ break;
+ if ( k == -1 ) // did not find
+ return 0;
+ }
+ for ( i = 0; i < (int)pC0->nLeaves; i++ )
+ pC->pLeaves[i] = pC0->pLeaves[i];
+ pC->nLeaves = pC0->nLeaves;
+ return 1;
+ }
+
+ // compare two cuts with different numbers
+ i = k = 0;
+ for ( c = 0; c < (int)pC->nLimit; c++ )
+ {
+ if ( k == (int)pC1->nLeaves )
+ {
+ if ( i == (int)pC0->nLeaves )
+ {
+ pC->nLeaves = c;
+ return 1;
+ }
+ pC->pLeaves[c] = pC0->pLeaves[i++];
+ continue;
+ }
+ if ( i == (int)pC0->nLeaves )
+ {
+ if ( k == (int)pC1->nLeaves )
+ {
+ pC->nLeaves = c;
+ return 1;
+ }
+ pC->pLeaves[c] = pC1->pLeaves[k++];
+ continue;
+ }
+ if ( pC0->pLeaves[i] < pC1->pLeaves[k] )
+ {
+ pC->pLeaves[c] = pC0->pLeaves[i++];
+ continue;
+ }
+ if ( pC0->pLeaves[i] > pC1->pLeaves[k] )
+ {
+ pC->pLeaves[c] = pC1->pLeaves[k++];
+ continue;
+ }
+ pC->pLeaves[c] = pC0->pLeaves[i++];
+ k++;
+ }
+ if ( i < (int)pC0->nLeaves || k < (int)pC1->nLeaves )
+ return 0;
+ pC->nLeaves = c;
+ return 1;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Merges two cuts.]
+
+ Description [Special case when the cut is known to exist.]
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+static inline int If_CutMergeOrdered2( If_Cut_t * pC0, If_Cut_t * pC1, If_Cut_t * pC )
+{
+ int i, k, c;
+ assert( pC0->nLeaves >= pC1->nLeaves );
+ // copy the first cut
+ for ( i = 0; i < (int)pC0->nLeaves; i++ )
+ pC->pLeaves[i] = pC0->pLeaves[i];
+ pC->nLeaves = pC0->nLeaves;
+ // the case when one of the cuts is the largest
+ if ( pC0->nLeaves == pC->nLimit )
+ return 1;
+ // add nodes of the second cut
+ k = 0;
+ for ( i = 0; i < (int)pC1->nLeaves; i++ )
+ {
+ // find k-th node before which i-th node should be added
+ for ( ; k < (int)pC->nLeaves; k++ )
+ if ( pC->pLeaves[k] >= pC1->pLeaves[i] )
+ break;
+ // check the case when this should be the last node
+ if ( k == (int)pC->nLeaves )
+ {
+ pC->pLeaves[k++] = pC1->pLeaves[i];
+ pC->nLeaves++;
+ continue;
+ }
+ // check the case when equal node is found
+ if ( pC1->pLeaves[i] == pC->pLeaves[k] )
+ continue;
+ // add the node
+ for ( c = (int)pC->nLeaves; c > k; c-- )
+ pC->pLeaves[c] = pC->pLeaves[c-1];
+ pC->pLeaves[k++] = pC1->pLeaves[i];
+ pC->nLeaves++;
+ }
+/*
+ assert( pC->nLeaves <= pC->nLimit );
+ for ( i = 1; i < (int)pC->nLeaves; i++ )
+ assert( pC->pLeaves[i-1] < pC->pLeaves[i] );
+*/
+ return 1;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Prepares the object for FPGA mapping.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int If_CutMerge( If_Cut_t * pCut0, If_Cut_t * pCut1, If_Cut_t * pCut )
+{
+ assert( pCut->nLimit > 0 );
+ // merge the nodes
+ if ( pCut0->nLeaves < pCut1->nLeaves )
+ {
+ if ( !If_CutMergeOrdered( pCut1, pCut0, pCut ) )
+ return 0;
+ }
+ else
+ {
+ if ( !If_CutMergeOrdered( pCut0, pCut1, pCut ) )
+ return 0;
+ }
+ pCut->uSign = pCut0->uSign | pCut1->uSign;
+ return 1;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Prepares the object for FPGA mapping.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int If_CutCompareDelay( If_Man_t * p, If_Cut_t ** ppC0, If_Cut_t ** ppC1 )
+{
+ If_Cut_t * pC0 = *ppC0;
+ If_Cut_t * pC1 = *ppC1;
+ if ( pC0->Delay < pC1->Delay - p->fEpsilon )
+ return -1;
+ if ( pC0->Delay > pC1->Delay + p->fEpsilon )
+ return 1;
+ if ( pC0->nLeaves < pC1->nLeaves )
+ return -1;
+ if ( pC0->nLeaves > pC1->nLeaves )
+ return 1;
+ if ( pC0->Area < pC1->Area - p->fEpsilon )
+ return -1;
+ if ( pC0->Area > pC1->Area + p->fEpsilon )
+ return 1;
+ return 0;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Prepares the object for FPGA mapping.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int If_CutCompareDelayOld( If_Man_t * p, If_Cut_t ** ppC0, If_Cut_t ** ppC1 )
+{
+ If_Cut_t * pC0 = *ppC0;
+ If_Cut_t * pC1 = *ppC1;
+ if ( pC0->Delay < pC1->Delay - p->fEpsilon )
+ return -1;
+ if ( pC0->Delay > pC1->Delay + p->fEpsilon )
+ return 1;
+ if ( pC0->Area < pC1->Area - p->fEpsilon )
+ return -1;
+ if ( pC0->Area > pC1->Area + p->fEpsilon )
+ return 1;
+ if ( pC0->nLeaves < pC1->nLeaves )
+ return -1;
+ if ( pC0->nLeaves > pC1->nLeaves )
+ return 1;
+ return 0;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Prepares the object for FPGA mapping.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int If_CutCompareArea( If_Man_t * p, If_Cut_t ** ppC0, If_Cut_t ** ppC1 )
+{
+ If_Cut_t * pC0 = *ppC0;
+ If_Cut_t * pC1 = *ppC1;
+ if ( pC0->Area < pC1->Area - p->fEpsilon )
+ return -1;
+ if ( pC0->Area > pC1->Area + p->fEpsilon )
+ return 1;
+ if ( pC0->AveRefs > pC1->AveRefs )
+ return -1;
+ if ( pC0->AveRefs < pC1->AveRefs )
+ return 1;
+ if ( pC0->nLeaves < pC1->nLeaves )
+ return -1;
+ if ( pC0->nLeaves > pC1->nLeaves )
+ return 1;
+ if ( pC0->Delay < pC1->Delay - p->fEpsilon )
+ return -1;
+ if ( pC0->Delay > pC1->Delay + p->fEpsilon )
+ return 1;
+ return 0;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Sorts the cuts.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void If_ManSortCuts( If_Man_t * p, int Mode )
+{
+/*
+ // sort the cuts
+ if ( Mode || p->pPars->fArea ) // area
+ qsort( p->ppCuts, p->nCuts, sizeof(If_Cut_t *), (int (*)(const void *, const void *))If_CutCompareArea );
+ else if ( p->pPars->fFancy )
+ qsort( p->ppCuts, p->nCuts, sizeof(If_Cut_t *), (int (*)(const void *, const void *))If_CutCompareDelayOld );
+ else
+ qsort( p->ppCuts, p->nCuts, sizeof(If_Cut_t *), (int (*)(const void *, const void *))If_CutCompareDelay );
+*/
+}
+
+/**Function*************************************************************
+
+ Synopsis [Comparison function for two cuts.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+static inline int If_ManSortCompare( If_Man_t * p, If_Cut_t * pC0, If_Cut_t * pC1 )
+{
+ if ( p->SortMode == 1 ) // area
+ {
+ if ( pC0->Area < pC1->Area - p->fEpsilon )
+ return -1;
+ if ( pC0->Area > pC1->Area + p->fEpsilon )
+ return 1;
+ if ( pC0->Edge < pC1->Edge - p->fEpsilon )
+ return -1;
+ if ( pC0->Edge > pC1->Edge + p->fEpsilon )
+ return 1;
+ if ( pC0->AveRefs > pC1->AveRefs )
+ return -1;
+ if ( pC0->AveRefs < pC1->AveRefs )
+ return 1;
+ if ( pC0->nLeaves < pC1->nLeaves )
+ return -1;
+ if ( pC0->nLeaves > pC1->nLeaves )
+ return 1;
+ if ( pC0->Delay < pC1->Delay - p->fEpsilon )
+ return -1;
+ if ( pC0->Delay > pC1->Delay + p->fEpsilon )
+ return 1;
+ return 0;
+ }
+ if ( p->SortMode == 0 ) // delay
+ {
+ if ( pC0->Delay < pC1->Delay - p->fEpsilon )
+ return -1;
+ if ( pC0->Delay > pC1->Delay + p->fEpsilon )
+ return 1;
+ if ( pC0->nLeaves < pC1->nLeaves )
+ return -1;
+ if ( pC0->nLeaves > pC1->nLeaves )
+ return 1;
+ if ( pC0->Area < pC1->Area - p->fEpsilon )
+ return -1;
+ if ( pC0->Area > pC1->Area + p->fEpsilon )
+ return 1;
+ if ( pC0->Edge < pC1->Edge - p->fEpsilon )
+ return -1;
+ if ( pC0->Edge > pC1->Edge + p->fEpsilon )
+ return 1;
+ return 0;
+ }
+ assert( p->SortMode == 2 ); // delay old
+ if ( pC0->Delay < pC1->Delay - p->fEpsilon )
+ return -1;
+ if ( pC0->Delay > pC1->Delay + p->fEpsilon )
+ return 1;
+ if ( pC0->Area < pC1->Area - p->fEpsilon )
+ return -1;
+ if ( pC0->Area > pC1->Area + p->fEpsilon )
+ return 1;
+ if ( pC0->Edge < pC1->Edge - p->fEpsilon )
+ return -1;
+ if ( pC0->Edge > pC1->Edge + p->fEpsilon )
+ return 1;
+ if ( pC0->nLeaves < pC1->nLeaves )
+ return -1;
+ if ( pC0->nLeaves > pC1->nLeaves )
+ return 1;
+ return 0;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Comparison function for two cuts.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+static inline int If_ManSortCompare_old( If_Man_t * p, If_Cut_t * pC0, If_Cut_t * pC1 )
+{
+ if ( p->SortMode == 1 ) // area
+ {
+ if ( pC0->Area < pC1->Area - p->fEpsilon )
+ return -1;
+ if ( pC0->Area > pC1->Area + p->fEpsilon )
+ return 1;
+ if ( pC0->AveRefs > pC1->AveRefs )
+ return -1;
+ if ( pC0->AveRefs < pC1->AveRefs )
+ return 1;
+ if ( pC0->nLeaves < pC1->nLeaves )
+ return -1;
+ if ( pC0->nLeaves > pC1->nLeaves )
+ return 1;
+ if ( pC0->Delay < pC1->Delay - p->fEpsilon )
+ return -1;
+ if ( pC0->Delay > pC1->Delay + p->fEpsilon )
+ return 1;
+ return 0;
+ }
+ if ( p->SortMode == 0 ) // delay
+ {
+ if ( pC0->Delay < pC1->Delay - p->fEpsilon )
+ return -1;
+ if ( pC0->Delay > pC1->Delay + p->fEpsilon )
+ return 1;
+ if ( pC0->nLeaves < pC1->nLeaves )
+ return -1;
+ if ( pC0->nLeaves > pC1->nLeaves )
+ return 1;
+ if ( pC0->Area < pC1->Area - p->fEpsilon )
+ return -1;
+ if ( pC0->Area > pC1->Area + p->fEpsilon )
+ return 1;
+ return 0;
+ }
+ assert( p->SortMode == 2 ); // delay old
+ if ( pC0->Delay < pC1->Delay - p->fEpsilon )
+ return -1;
+ if ( pC0->Delay > pC1->Delay + p->fEpsilon )
+ return 1;
+ if ( pC0->Area < pC1->Area - p->fEpsilon )
+ return -1;
+ if ( pC0->Area > pC1->Area + p->fEpsilon )
+ return 1;
+ if ( pC0->nLeaves < pC1->nLeaves )
+ return -1;
+ if ( pC0->nLeaves > pC1->nLeaves )
+ return 1;
+ return 0;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Performs incremental sorting of cuts.]
+
+ Description [Currently only the trivial sorting is implemented.]
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void If_CutSort( If_Man_t * p, If_Set_t * pCutSet, If_Cut_t * pCut )
+{
+// int Counter = 0;
+ int i;
+
+ // the new cut is the last one
+ assert( pCutSet->ppCuts[pCutSet->nCuts] == pCut );
+ assert( pCutSet->nCuts <= pCutSet->nCutsMax );
+
+ // cut structure is empty
+ if ( pCutSet->nCuts == 0 )
+ {
+ pCutSet->nCuts++;
+ return;
+ }
+
+ // the cut will be added - find its place
+ for ( i = pCutSet->nCuts-1; i >= 0; i-- )
+ {
+// Counter++;
+ if ( If_ManSortCompare( p, pCutSet->ppCuts[i], pCut ) <= 0 )
+ break;
+ pCutSet->ppCuts[i+1] = pCutSet->ppCuts[i];
+ pCutSet->ppCuts[i] = pCut;
+ }
+// printf( "%d ", Counter );
+
+ // update the number of cuts
+ if ( pCutSet->nCuts < pCutSet->nCutsMax )
+ pCutSet->nCuts++;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Prints one cut.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void If_CutPrint( If_Man_t * p, If_Cut_t * pCut )
+{
+ unsigned i;
+ printf( "{" );
+ for ( i = 0; i < pCut->nLeaves; i++ )
+ printf( " %d", pCut->pLeaves[i] );
+ printf( " }\n" );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Prints one cut.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void If_CutPrintTiming( If_Man_t * p, If_Cut_t * pCut )
+{
+ If_Obj_t * pLeaf;
+ unsigned i;
+ printf( "{" );
+ If_CutForEachLeaf( p, pCut, pLeaf, i )
+ printf( " %d(%.2f/%.2f)", pLeaf->Id, If_ObjCutBest(pLeaf)->Delay, pLeaf->Required );
+ printf( " }\n" );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Moves the cut over the latch.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void If_CutLift( If_Cut_t * pCut )
+{
+ unsigned i;
+ for ( i = 0; i < pCut->nLeaves; i++ )
+ {
+ assert( (pCut->pLeaves[i] & 255) < 255 );
+ pCut->pLeaves[i]++;
+ }
+}
+
+/**Function*************************************************************
+
+ Synopsis [Computes area of the first level.]
+
+ Description [The cut need to be derefed.]
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void If_CutCopy( If_Man_t * p, If_Cut_t * pCutDest, If_Cut_t * pCutSrc )
+{
+ int * pLeaves;
+ char * pPerm;
+ unsigned * pTruth;
+ // save old arrays
+ pLeaves = pCutDest->pLeaves;
+ pPerm = pCutDest->pPerm;
+ pTruth = pCutDest->pTruth;
+ // copy the cut info
+ memcpy( pCutDest, pCutSrc, p->nCutBytes );
+ // restore the arrays
+ pCutDest->pLeaves = pLeaves;
+ pCutDest->pPerm = pPerm;
+ pCutDest->pTruth = pTruth;
+}
+
+
+/**Function*************************************************************
+
+ Synopsis [Computes area flow.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+float If_CutAreaFlow( If_Man_t * p, If_Cut_t * pCut )
+{
+ If_Obj_t * pLeaf;
+ float Flow;
+ int i;
+ assert( p->pPars->fSeqMap || pCut->nLeaves > 1 );
+ Flow = If_CutLutArea(p, pCut);
+ If_CutForEachLeaf( p, pCut, pLeaf, i )
+ {
+ if ( pLeaf->nRefs == 0 )
+ Flow += If_ObjCutBest(pLeaf)->Area;
+ else if ( p->pPars->fSeqMap ) // seq
+ Flow += If_ObjCutBest(pLeaf)->Area / pLeaf->nRefs;
+ else
+ {
+ assert( pLeaf->EstRefs > p->fEpsilon );
+ Flow += If_ObjCutBest(pLeaf)->Area / pLeaf->EstRefs;
+ }
+ }
+ return Flow;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Computes area flow.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+float If_CutEdgeFlow( If_Man_t * p, If_Cut_t * pCut )
+{
+ If_Obj_t * pLeaf;
+ float Flow;
+ int i;
+ assert( p->pPars->fSeqMap || pCut->nLeaves > 1 );
+ Flow = pCut->nLeaves;
+ If_CutForEachLeaf( p, pCut, pLeaf, i )
+ {
+ if ( pLeaf->nRefs == 0 )
+ Flow += If_ObjCutBest(pLeaf)->Edge;
+ else if ( p->pPars->fSeqMap ) // seq
+ Flow += If_ObjCutBest(pLeaf)->Edge / pLeaf->nRefs;
+ else
+ {
+ assert( pLeaf->EstRefs > p->fEpsilon );
+ Flow += If_ObjCutBest(pLeaf)->Edge / pLeaf->EstRefs;
+ }
+ }
+ return Flow;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Average number of references of the leaves.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+float If_CutAverageRefs( If_Man_t * p, If_Cut_t * pCut )
+{
+ If_Obj_t * pLeaf;
+ int nRefsTotal, i;
+ assert( p->pPars->fSeqMap || pCut->nLeaves > 1 );
+ nRefsTotal = 0;
+ If_CutForEachLeaf( p, pCut, pLeaf, i )
+ nRefsTotal += pLeaf->nRefs;
+ return ((float)nRefsTotal)/pCut->nLeaves;
+}
+
+
+/**Function*************************************************************
+
+ Synopsis [Computes area of the first level.]
+
+ Description [The cut need to be derefed.]
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+float If_CutAreaDeref( If_Man_t * p, If_Cut_t * pCut )
+{
+ If_Obj_t * pLeaf;
+ float Area;
+ int i;
+ Area = If_CutLutArea(p, pCut);
+ If_CutForEachLeaf( p, pCut, pLeaf, i )
+ {
+ assert( pLeaf->nRefs > 0 );
+ if ( --pLeaf->nRefs > 0 || !If_ObjIsAnd(pLeaf) )
+ continue;
+ Area += If_CutAreaDeref( p, If_ObjCutBest(pLeaf) );
+ }
+ return Area;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Computes area of the first level.]
+
+ Description [The cut need to be derefed.]
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+float If_CutAreaRef( If_Man_t * p, If_Cut_t * pCut )
+{
+ If_Obj_t * pLeaf;
+ float Area;
+ int i;
+ Area = If_CutLutArea(p, pCut);
+ If_CutForEachLeaf( p, pCut, pLeaf, i )
+ {
+ assert( pLeaf->nRefs >= 0 );
+ if ( pLeaf->nRefs++ > 0 || !If_ObjIsAnd(pLeaf) )
+ continue;
+ Area += If_CutAreaRef( p, If_ObjCutBest(pLeaf) );
+ }
+ return Area;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Computes area of the first level.]
+
+ Description [The cut need to be derefed.]
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+float If_CutAreaDerefed( If_Man_t * p, If_Cut_t * pCut )
+{
+ float aResult, aResult2;
+ assert( p->pPars->fSeqMap || pCut->nLeaves > 1 );
+ aResult2 = If_CutAreaRef( p, pCut );
+ aResult = If_CutAreaDeref( p, pCut );
+ assert( aResult > aResult2 - p->fEpsilon );
+ assert( aResult < aResult2 + p->fEpsilon );
+ return aResult;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Computes area of the first level.]
+
+ Description [The cut need to be derefed.]
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+float If_CutAreaRefed( If_Man_t * p, If_Cut_t * pCut )
+{
+ float aResult, aResult2;
+ assert( p->pPars->fSeqMap || pCut->nLeaves > 1 );
+ aResult2 = If_CutAreaDeref( p, pCut );
+ aResult = If_CutAreaRef( p, pCut );
+ assert( aResult > aResult2 - p->fEpsilon );
+ assert( aResult < aResult2 + p->fEpsilon );
+ return aResult;
+}
+
+
+/**Function*************************************************************
+
+ Synopsis [Computes area of the first level.]
+
+ Description [The cut need to be derefed.]
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+float If_CutEdgeDeref( If_Man_t * p, If_Cut_t * pCut )
+{
+ If_Obj_t * pLeaf;
+ float Edge;
+ int i;
+ Edge = pCut->nLeaves;
+ If_CutForEachLeaf( p, pCut, pLeaf, i )
+ {
+ assert( pLeaf->nRefs > 0 );
+ if ( --pLeaf->nRefs > 0 || !If_ObjIsAnd(pLeaf) )
+ continue;
+ Edge += If_CutEdgeDeref( p, If_ObjCutBest(pLeaf) );
+ }
+ return Edge;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Computes area of the first level.]
+
+ Description [The cut need to be derefed.]
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+float If_CutEdgeRef( If_Man_t * p, If_Cut_t * pCut )
+{
+ If_Obj_t * pLeaf;
+ float Edge;
+ int i;
+ Edge = pCut->nLeaves;
+ If_CutForEachLeaf( p, pCut, pLeaf, i )
+ {
+ assert( pLeaf->nRefs >= 0 );
+ if ( pLeaf->nRefs++ > 0 || !If_ObjIsAnd(pLeaf) )
+ continue;
+ Edge += If_CutEdgeRef( p, If_ObjCutBest(pLeaf) );
+ }
+ return Edge;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Computes edge of the first level.]
+
+ Description [The cut need to be derefed.]
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+float If_CutEdgeDerefed( If_Man_t * p, If_Cut_t * pCut )
+{
+ float aResult, aResult2;
+ assert( p->pPars->fSeqMap || pCut->nLeaves > 1 );
+ aResult2 = If_CutEdgeRef( p, pCut );
+ aResult = If_CutEdgeDeref( p, pCut );
+ assert( aResult > aResult2 - p->fEpsilon );
+ assert( aResult < aResult2 + p->fEpsilon );
+ return aResult;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Computes area of the first level.]
+
+ Description [The cut need to be derefed.]
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+float If_CutEdgeRefed( If_Man_t * p, If_Cut_t * pCut )
+{
+ float aResult, aResult2;
+ assert( p->pPars->fSeqMap || pCut->nLeaves > 1 );
+ aResult2 = If_CutEdgeDeref( p, pCut );
+ aResult = If_CutEdgeRef( p, pCut );
+ assert( aResult > aResult2 - p->fEpsilon );
+ assert( aResult < aResult2 + p->fEpsilon );
+ return aResult;
+}
+
+
+////////////////////////////////////////////////////////////////////////
+/// END OF FILE ///
+////////////////////////////////////////////////////////////////////////
+
+
diff --git a/src/map/if/ifMan.c b/src/map/if/ifMan.c
new file mode 100644
index 00000000..6b21919b
--- /dev/null
+++ b/src/map/if/ifMan.c
@@ -0,0 +1,577 @@
+/**CFile****************************************************************
+
+ FileName [ifMan.c]
+
+ SystemName [ABC: Logic synthesis and verification system.]
+
+ PackageName [FPGA mapping based on priority cuts.]
+
+ Synopsis [Mapping manager.]
+
+ Author [Alan Mishchenko]
+
+ Affiliation [UC Berkeley]
+
+ Date [Ver. 1.0. Started - November 21, 2006.]
+
+ Revision [$Id: ifMan.c,v 1.00 2006/11/21 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "if.h"
+
+////////////////////////////////////////////////////////////////////////
+/// DECLARATIONS ///
+////////////////////////////////////////////////////////////////////////
+
+static If_Obj_t * If_ManSetupObj( If_Man_t * p );
+
+static void If_ManCutSetRecycle( If_Man_t * p, If_Set_t * pSet ) { pSet->pNext = p->pFreeList; p->pFreeList = pSet; }
+static If_Set_t * If_ManCutSetFetch( If_Man_t * p ) { If_Set_t * pTemp = p->pFreeList; p->pFreeList = p->pFreeList->pNext; return pTemp; }
+
+////////////////////////////////////////////////////////////////////////
+/// FUNCTION DEFINITIONS ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+ Synopsis [Starts the AIG manager.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+If_Man_t * If_ManStart( If_Par_t * pPars )
+{
+ If_Man_t * p;
+ // start the manager
+ p = ALLOC( If_Man_t, 1 );
+ memset( p, 0, sizeof(If_Man_t) );
+ p->pPars = pPars;
+ p->fEpsilon = (float)0.001;
+ // allocate arrays for nodes
+ p->vCis = Vec_PtrAlloc( 100 );
+ p->vCos = Vec_PtrAlloc( 100 );
+ p->vObjs = Vec_PtrAlloc( 100 );
+// p->vMapped = Vec_PtrAlloc( 100 );
+ p->vTemp = Vec_PtrAlloc( 100 );
+ // prepare the memory manager
+ p->nTruthWords = p->pPars->fTruth? If_CutTruthWords( p->pPars->nLutSize ) : 0;
+ p->nPermWords = p->pPars->fUsePerm? If_CutPermWords( p->pPars->nLutSize ) : 0;
+ p->nObjBytes = sizeof(If_Obj_t) + sizeof(int) * (p->pPars->nLutSize + p->nPermWords + p->nTruthWords);
+ p->nCutBytes = sizeof(If_Cut_t) + sizeof(int) * (p->pPars->nLutSize + p->nPermWords + p->nTruthWords);
+ p->nSetBytes = sizeof(If_Set_t) + (sizeof(If_Cut_t *) + p->nCutBytes) * (p->pPars->nCutsMax + 1);
+ p->pMemObj = Mem_FixedStart( p->nObjBytes );
+// p->pMemSet = Mem_FixedStart( p->nSetBytes );
+ // report expected memory usage
+ if ( p->pPars->fVerbose )
+ printf( "K = %d. Memory (bytes): Truth = %4d. Cut = %4d. Obj = %4d. Set = %4d.\n",
+ p->pPars->nLutSize, 4 * p->nTruthWords, p->nCutBytes, p->nObjBytes, p->nSetBytes );
+ // room for temporary truth tables
+ p->puTemp[0] = p->pPars->fTruth? ALLOC( unsigned, 4 * p->nTruthWords ) : NULL;
+ p->puTemp[1] = p->puTemp[0] + p->nTruthWords;
+ p->puTemp[2] = p->puTemp[1] + p->nTruthWords;
+ p->puTemp[3] = p->puTemp[2] + p->nTruthWords;
+ // create the constant node
+ p->pConst1 = If_ManSetupObj( p );
+ p->pConst1->Type = IF_CONST1;
+ p->pConst1->fPhase = 1;
+ p->nObjs[IF_CONST1]++;
+ return p;
+}
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void If_ManRestart( If_Man_t * p )
+{
+ FREE( p->pMemCi );
+ Vec_PtrClear( p->vCis );
+ Vec_PtrClear( p->vCos );
+ Vec_PtrClear( p->vObjs );
+// Vec_PtrClear( p->vMapped );
+ Vec_PtrClear( p->vTemp );
+ Mem_FixedRestart( p->pMemObj );
+ // create the constant node
+ p->pConst1 = If_ManSetupObj( p );
+ p->pConst1->Type = IF_CONST1;
+ p->pConst1->fPhase = 1;
+ // reset the counter of other nodes
+ p->nObjs[IF_CI] = p->nObjs[IF_CO] = p->nObjs[IF_AND] = 0;
+}
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void If_ManStop( If_Man_t * p )
+{
+// printf( "Small support = %d.\n", p->nSmallSupp );
+ Vec_PtrFree( p->vCis );
+ Vec_PtrFree( p->vCos );
+ Vec_PtrFree( p->vObjs );
+// Vec_PtrFree( p->vMapped );
+ Vec_PtrFree( p->vTemp );
+ if ( p->vObjsRev ) Vec_PtrFree( p->vObjsRev );
+ if ( p->vLatchOrder ) Vec_PtrFree( p->vLatchOrder );
+ if ( p->vLags ) Vec_IntFree( p->vLags );
+ Mem_FixedStop( p->pMemObj, 0 );
+ FREE( p->pMemCi );
+ FREE( p->pMemAnd );
+ FREE( p->puTemp[0] );
+ // free pars memory
+ if ( p->pPars->pTimesArr )
+ FREE( p->pPars->pTimesArr );
+ if ( p->pPars->pTimesReq )
+ FREE( p->pPars->pTimesReq );
+ if ( p->pManTim )
+ Tim_ManStop( p->pManTim );
+ free( p );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Creates primary input.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+If_Obj_t * If_ManCreateCi( If_Man_t * p )
+{
+ If_Obj_t * pObj;
+ pObj = If_ManSetupObj( p );
+ pObj->Type = IF_CI;
+ pObj->IdPio = Vec_PtrSize( p->vCis );
+ Vec_PtrPush( p->vCis, pObj );
+ p->nObjs[IF_CI]++;
+ return pObj;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Creates primary output with the given driver.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+If_Obj_t * If_ManCreateCo( If_Man_t * p, If_Obj_t * pDriver )
+{
+ If_Obj_t * pObj;
+ pObj = If_ManSetupObj( p );
+ pObj->IdPio = Vec_PtrSize( p->vCos );
+ Vec_PtrPush( p->vCos, pObj );
+ pObj->Type = IF_CO;
+ pObj->fCompl0 = If_IsComplement(pDriver); pDriver = If_Regular(pDriver);
+ pObj->pFanin0 = pDriver; pDriver->nRefs++;
+ pObj->Level = pDriver->Level;
+ p->nObjs[IF_CO]++;
+ return pObj;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Create the new node assuming it does not exist.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+If_Obj_t * If_ManCreateAnd( If_Man_t * p, If_Obj_t * pFan0, If_Obj_t * pFan1 )
+{
+ If_Obj_t * pObj;
+ // perform constant propagation
+ if ( pFan0 == pFan1 )
+ return pFan0;
+ if ( pFan0 == If_Not(pFan1) )
+ return If_Not(p->pConst1);
+ if ( If_Regular(pFan0) == p->pConst1 )
+ return pFan0 == p->pConst1 ? pFan1 : If_Not(p->pConst1);
+ if ( If_Regular(pFan1) == p->pConst1 )
+ return pFan1 == p->pConst1 ? pFan0 : If_Not(p->pConst1);
+ // get memory for the new object
+ pObj = If_ManSetupObj( p );
+ pObj->Type = IF_AND;
+ pObj->fCompl0 = If_IsComplement(pFan0); pFan0 = If_Regular(pFan0);
+ pObj->fCompl1 = If_IsComplement(pFan1); pFan1 = If_Regular(pFan1);
+ pObj->pFanin0 = pFan0; pFan0->nRefs++; pFan0->nVisits++; pFan0->nVisitsCopy++;
+ pObj->pFanin1 = pFan1; pFan1->nRefs++; pFan1->nVisits++; pFan1->nVisitsCopy++;
+ pObj->fPhase = (pObj->fCompl0 ^ pFan0->fPhase) & (pObj->fCompl1 ^ pFan1->fPhase);
+ pObj->Level = 1 + IF_MAX( pFan0->Level, pFan1->Level );
+ if ( p->nLevelMax < (int)pObj->Level )
+ p->nLevelMax = (int)pObj->Level;
+ p->nObjs[IF_AND]++;
+ return pObj;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Create the new node assuming it does not exist.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+If_Obj_t * If_ManCreateXor( If_Man_t * p, If_Obj_t * pFan0, If_Obj_t * pFan1 )
+{
+ If_Obj_t * pRes1, * pRes2;
+ pRes1 = If_ManCreateAnd( p, If_Not(pFan0), pFan1 );
+ pRes2 = If_ManCreateAnd( p, pFan0, If_Not(pFan1) );
+ return If_Not( If_ManCreateAnd( p, If_Not(pRes1), If_Not(pRes2) ) );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Create the new node assuming it does not exist.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+If_Obj_t * If_ManCreateMux( If_Man_t * p, If_Obj_t * pFan0, If_Obj_t * pFan1, If_Obj_t * pCtrl )
+{
+ If_Obj_t * pRes1, * pRes2;
+ pRes1 = If_ManCreateAnd( p, pFan0, If_Not(pCtrl) );
+ pRes2 = If_ManCreateAnd( p, pFan1, pCtrl );
+ return If_Not( If_ManCreateAnd( p, If_Not(pRes1), If_Not(pRes2) ) );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Creates the choice node.]
+
+ Description [Should be called after the equivalence class nodes are linked.]
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void If_ManCreateChoice( If_Man_t * p, If_Obj_t * pObj )
+{
+ If_Obj_t * pTemp;
+ // mark the node as a representative if its class
+ assert( pObj->fRepr == 0 );
+ pObj->fRepr = 1;
+ // update the level of this node (needed for correct required time computation)
+ for ( pTemp = pObj; pTemp; pTemp = pTemp->pEquiv )
+ {
+ pObj->Level = IF_MAX( pObj->Level, pTemp->Level );
+ pTemp->nVisits++; pTemp->nVisitsCopy++;
+ }
+ // mark the largest level
+ if ( p->nLevelMax < (int)pObj->Level )
+ p->nLevelMax = (int)pObj->Level;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Prepares memory for one cut.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void If_ManSetupCut( If_Man_t * p, If_Cut_t * pCut )
+{
+ memset( pCut, 0, sizeof(If_Cut_t) );
+ pCut->nLimit = p->pPars->nLutSize;
+ pCut->pLeaves = (int *)(pCut + 1);
+ if ( p->pPars->fUsePerm )
+ pCut->pPerm = (char *)(pCut->pLeaves + p->pPars->nLutSize);
+ if ( p->pPars->fTruth )
+ pCut->pTruth = pCut->pLeaves + p->pPars->nLutSize + p->nPermWords;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Prepares memory for one cutset.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void If_ManSetupSet( If_Man_t * p, If_Set_t * pSet )
+{
+ char * pArray;
+ int i;
+ pSet->nCuts = 0;
+ pSet->nCutsMax = p->pPars->nCutsMax;
+ pSet->ppCuts = (If_Cut_t **)(pSet + 1);
+ pArray = (char *)pSet->ppCuts + sizeof(If_Cut_t *) * (pSet->nCutsMax+1);
+ for ( i = 0; i <= pSet->nCutsMax; i++ )
+ {
+ pSet->ppCuts[i] = (If_Cut_t *)(pArray + i * p->nCutBytes);
+ If_ManSetupCut( p, pSet->ppCuts[i] );
+ }
+// pArray += (pSet->nCutsMax + 1) * p->nCutBytes;
+// assert( ((char *)pArray) - ((char *)pSet) == p->nSetBytes );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Prepares memory for one cut.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void If_ManSetupCutTriv( If_Man_t * p, If_Cut_t * pCut, int ObjId )
+{
+ pCut->fCompl = 0;
+ pCut->nLimit = p->pPars->nLutSize;
+ pCut->nLeaves = 1;
+ pCut->pLeaves[0] = p->pPars->fLiftLeaves? (ObjId << 8) : ObjId;
+ pCut->uSign = If_ObjCutSign( pCut->pLeaves[0] );
+ // set up elementary truth table of the unit cut
+ if ( p->pPars->fTruth )
+ {
+ int i, nTruthWords;
+ nTruthWords = pCut->nLimit <= 5 ? 1 : (1 << (pCut->nLimit - 5));
+ for ( i = 0; i < nTruthWords; i++ )
+ If_CutTruth(pCut)[i] = 0xAAAAAAAA;
+ }
+}
+
+/**Function*************************************************************
+
+ Synopsis [Prepares memory for the node with cuts.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+If_Obj_t * If_ManSetupObj( If_Man_t * p )
+{
+ If_Obj_t * pObj;
+ // get memory for the object
+ pObj = (If_Obj_t *)Mem_FixedEntryFetch( p->pMemObj );
+ memset( pObj, 0, sizeof(If_Obj_t) );
+ If_ManSetupCut( p, &pObj->CutBest );
+ // assign ID and save
+ pObj->Id = Vec_PtrSize(p->vObjs);
+ Vec_PtrPush( p->vObjs, pObj );
+ // set the required times
+ pObj->Required = IF_FLOAT_LARGE;
+ return pObj;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Prepares memory for one cut.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void If_ManSetupCiCutSets( If_Man_t * p )
+{
+ If_Obj_t * pObj;
+ int i;
+ assert( p->pMemCi == NULL );
+ // create elementary cuts for the CIs
+ If_ManForEachCi( p, pObj, i )
+ If_ManSetupCutTriv( p, &pObj->CutBest, pObj->Id );
+ // create elementary cutsets for the CIs
+ p->pMemCi = (If_Set_t *)malloc( If_ManCiNum(p) * (sizeof(If_Set_t) + sizeof(void *)) );
+ If_ManForEachCi( p, pObj, i )
+ {
+ pObj->pCutSet = (If_Set_t *)((char *)p->pMemCi + i * (sizeof(If_Set_t) + sizeof(void *)));
+ pObj->pCutSet->nCuts = 1;
+ pObj->pCutSet->nCutsMax = p->pPars->nCutsMax;
+ pObj->pCutSet->ppCuts = (If_Cut_t **)(pObj->pCutSet + 1);
+ pObj->pCutSet->ppCuts[0] = &pObj->CutBest;
+ }
+}
+
+/**Function*************************************************************
+
+ Synopsis [Prepares cutset of the node.]
+
+ Description [Elementary cutset will be added last.]
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+If_Set_t * If_ManSetupNodeCutSet( If_Man_t * p, If_Obj_t * pObj )
+{
+ assert( If_ObjIsAnd(pObj) );
+ assert( pObj->pCutSet == NULL );
+// pObj->pCutSet = (If_Set_t *)Mem_FixedEntryFetch( p->pMemSet );
+// If_ManSetupSet( p, pObj->pCutSet );
+
+ pObj->pCutSet = If_ManCutSetFetch( p );
+ pObj->pCutSet->nCuts = 0;
+ pObj->pCutSet->nCutsMax = p->pPars->nCutsMax;
+
+ return pObj->pCutSet;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Dereferences cutset of the node.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void If_ManDerefNodeCutSet( If_Man_t * p, If_Obj_t * pObj )
+{
+ If_Obj_t * pFanin;
+ assert( If_ObjIsAnd(pObj) );
+ // consider the node
+ assert( pObj->nVisits >= 0 );
+ if ( pObj->nVisits == 0 )
+ {
+// Mem_FixedEntryRecycle( p->pMemSet, (char *)pObj->pCutSet );
+ If_ManCutSetRecycle( p, pObj->pCutSet );
+ pObj->pCutSet = NULL;
+ }
+ // consider the first fanin
+ pFanin = If_ObjFanin0(pObj);
+ assert( pFanin->nVisits > 0 );
+ if ( !If_ObjIsCi(pFanin) && --pFanin->nVisits == 0 )
+ {
+// Mem_FixedEntryRecycle( p->pMemSet, (char *)pFanin->pCutSet );
+ If_ManCutSetRecycle( p, pFanin->pCutSet );
+ pFanin->pCutSet = NULL;
+ }
+ // consider the second fanin
+ pFanin = If_ObjFanin1(pObj);
+ assert( pFanin->nVisits > 0 );
+ if ( !If_ObjIsCi(pFanin) && --pFanin->nVisits == 0 )
+ {
+// Mem_FixedEntryRecycle( p->pMemSet, (char *)pFanin->pCutSet );
+ If_ManCutSetRecycle( p, pFanin->pCutSet );
+ pFanin->pCutSet = NULL;
+ }
+}
+
+/**Function*************************************************************
+
+ Synopsis [Dereferences cutset of the node.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void If_ManDerefChoiceCutSet( If_Man_t * p, If_Obj_t * pObj )
+{
+ If_Obj_t * pTemp;
+ assert( If_ObjIsAnd(pObj) );
+ assert( pObj->fRepr );
+ assert( pObj->nVisits > 0 );
+ // consider the nodes in the choice class
+ for ( pTemp = pObj; pTemp; pTemp = pTemp->pEquiv )
+ {
+ assert( pTemp == pObj || pTemp->nVisits == 1 );
+ if ( --pTemp->nVisits == 0 )
+ {
+// Mem_FixedEntryRecycle( p->pMemSet, (char *)pTemp->pCutSet );
+ If_ManCutSetRecycle( p, pTemp->pCutSet );
+ pTemp->pCutSet = NULL;
+ }
+ }
+}
+
+/**Function*************************************************************
+
+ Synopsis [Dereferences cutset of the node.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void If_ManSetupSetAll( If_Man_t * p, int nCrossCut )
+{
+ If_Set_t * pCutSet;
+ int i, nCutSets;
+ nCutSets = 128 + nCrossCut;
+ p->pFreeList = p->pMemAnd = pCutSet = (If_Set_t *)malloc( nCutSets * p->nSetBytes );
+ for ( i = 0; i < nCutSets; i++ )
+ {
+ If_ManSetupSet( p, pCutSet );
+ if ( i == nCutSets - 1 )
+ pCutSet->pNext = NULL;
+ else
+ pCutSet->pNext = (If_Set_t *)( (char *)pCutSet + p->nSetBytes );
+ pCutSet = pCutSet->pNext;
+ }
+ assert( pCutSet == NULL );
+
+ if ( p->pPars->fVerbose )
+ {
+ printf( "Node = %7d. Ch = %5d. Total mem = %7.2f Mb. Peak cut mem = %7.2f Mb.\n",
+ If_ManAndNum(p), p->nChoices,
+ 1.0 * (p->nObjBytes + 2*sizeof(void *)) * If_ManObjNum(p) / (1<<20),
+ 1.0 * p->nSetBytes * nCrossCut / (1<<20) );
+ }
+// printf( "Cross cut = %d.\n", nCrossCut );
+
+}
+
+////////////////////////////////////////////////////////////////////////
+/// END OF FILE ///
+////////////////////////////////////////////////////////////////////////
+
+
diff --git a/src/map/if/ifMap.c b/src/map/if/ifMap.c
new file mode 100644
index 00000000..1ac5ef21
--- /dev/null
+++ b/src/map/if/ifMap.c
@@ -0,0 +1,350 @@
+/**CFile****************************************************************
+
+ FileName [ifMap.c]
+
+ SystemName [ABC: Logic synthesis and verification system.]
+
+ PackageName [FPGA mapping based on priority cuts.]
+
+ Synopsis [Mapping procedures.]
+
+ Author [Alan Mishchenko]
+
+ Affiliation [UC Berkeley]
+
+ Date [Ver. 1.0. Started - November 21, 2006.]
+
+ Revision [$Id: ifMap.c,v 1.00 2006/11/21 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "if.h"
+
+////////////////////////////////////////////////////////////////////////
+/// DECLARATIONS ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+/// FUNCTION DEFINITIONS ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+ Synopsis [Counts the number of 1s in the signature.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+static inline int If_WordCountOnes( unsigned uWord )
+{
+ uWord = (uWord & 0x55555555) + ((uWord>>1) & 0x55555555);
+ uWord = (uWord & 0x33333333) + ((uWord>>2) & 0x33333333);
+ uWord = (uWord & 0x0F0F0F0F) + ((uWord>>4) & 0x0F0F0F0F);
+ uWord = (uWord & 0x00FF00FF) + ((uWord>>8) & 0x00FF00FF);
+ return (uWord & 0x0000FFFF) + (uWord>>16);
+}
+
+/**Function*************************************************************
+
+ Synopsis [Finds the best cut for the given node.]
+
+ Description [Mapping modes: delay (0), area flow (1), area (2).]
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void If_ObjPerformMappingAnd( If_Man_t * p, If_Obj_t * pObj, int Mode, int fPreprocess )
+{
+ If_Set_t * pCutSet;
+ If_Cut_t * pCut0, * pCut1, * pCut;
+ int i, k;
+
+ assert( p->pPars->fSeqMap || !If_ObjIsAnd(pObj->pFanin0) || pObj->pFanin0->pCutSet->nCuts > 1 );
+ assert( p->pPars->fSeqMap || !If_ObjIsAnd(pObj->pFanin1) || pObj->pFanin1->pCutSet->nCuts > 1 );
+
+ // prepare
+ if ( !p->pPars->fSeqMap )
+ {
+ if ( Mode == 0 )
+ pObj->EstRefs = (float)pObj->nRefs;
+ else if ( Mode == 1 )
+ pObj->EstRefs = (float)((2.0 * pObj->EstRefs + pObj->nRefs) / 3.0);
+ }
+ if ( Mode && pObj->nRefs > 0 )
+ If_CutAreaDeref( p, If_ObjCutBest(pObj) );
+
+ // prepare the cutset
+ pCutSet = If_ManSetupNodeCutSet( p, pObj );
+
+ // get the current assigned best cut
+ pCut = If_ObjCutBest(pObj);
+ if ( pCut->nLeaves > 0 )
+ {
+ // recompute the parameters of the best cut
+ pCut->Delay = If_CutDelay( p, pCut );
+ assert( pCut->Delay <= pObj->Required + p->fEpsilon );
+ pCut->Area = (Mode == 2)? If_CutAreaDerefed( p, pCut ) : If_CutAreaFlow( p, pCut );
+ if ( p->pPars->fEdge )
+ pCut->Edge = (Mode == 2)? If_CutEdgeDerefed( p, pCut ) : If_CutEdgeFlow( p, pCut );
+ // save the best cut from the previous iteration
+ if ( !fPreprocess )
+ If_CutCopy( p, pCutSet->ppCuts[pCutSet->nCuts++], pCut );
+ }
+
+ // generate cuts
+ If_ObjForEachCut( pObj->pFanin0, pCut0, i )
+ If_ObjForEachCut( pObj->pFanin1, pCut1, k )
+ {
+ // get the next free cut
+ assert( pCutSet->nCuts <= pCutSet->nCutsMax );
+ pCut = pCutSet->ppCuts[pCutSet->nCuts];
+ // make sure K-feasible cut exists
+ if ( If_WordCountOnes(pCut0->uSign | pCut1->uSign) > p->pPars->nLutSize )
+ continue;
+ // merge the nodes
+ if ( !If_CutMerge( pCut0, pCut1, pCut ) )
+ continue;
+ assert( p->pPars->fSeqMap || pCut->nLeaves > 1 );
+ p->nCutsMerged++;
+ // check if this cut is contained in any of the available cuts
+// if ( p->pPars->pFuncCost == NULL && If_CutFilter( p, pCut ) ) // do not filter functionality cuts
+ if ( If_CutFilter( pCutSet, pCut ) )
+ continue;
+ // compute the truth table
+ pCut->fCompl = 0;
+ if ( p->pPars->fTruth )
+ If_CutComputeTruth( p, pCut, pCut0, pCut1, pObj->fCompl0, pObj->fCompl1 );
+ // compute the application-specific cost and depth
+ pCut->fUser = (p->pPars->pFuncCost != NULL);
+ pCut->Cost = p->pPars->pFuncCost? p->pPars->pFuncCost(pCut) : 0;
+ if ( pCut->Cost == IF_COST_MAX )
+ continue;
+ // check if the cut satisfies the required times
+ pCut->Delay = If_CutDelay( p, pCut );
+// printf( "%.2f ", pCut->Delay );
+ if ( Mode && pCut->Delay > pObj->Required + p->fEpsilon )
+ continue;
+ // compute area of the cut (this area may depend on the application specific cost)
+ pCut->Area = (Mode == 2)? If_CutAreaDerefed( p, pCut ) : If_CutAreaFlow( p, pCut );
+ if ( p->pPars->fEdge )
+ pCut->Edge = (Mode == 2)? If_CutEdgeDerefed( p, pCut ) : If_CutEdgeFlow( p, pCut );
+ pCut->AveRefs = (Mode == 0)? (float)0.0 : If_CutAverageRefs( p, pCut );
+ // insert the cut into storage
+ If_CutSort( p, pCutSet, pCut );
+ }
+ assert( pCutSet->nCuts > 0 );
+
+ // add the trivial cut to the set
+ If_ManSetupCutTriv( p, pCutSet->ppCuts[pCutSet->nCuts++], pObj->Id );
+ assert( pCutSet->nCuts <= pCutSet->nCutsMax+1 );
+
+ // update the best cut
+ if ( !fPreprocess || pCutSet->ppCuts[0]->Delay <= pObj->Required + p->fEpsilon )
+ If_CutCopy( p, If_ObjCutBest(pObj), pCutSet->ppCuts[0] );
+ assert( p->pPars->fSeqMap || If_ObjCutBest(pObj)->nLeaves > 1 );
+
+ // ref the selected cut
+ if ( Mode && pObj->nRefs > 0 )
+ If_CutAreaRef( p, If_ObjCutBest(pObj) );
+
+ // call the user specified function for each cut
+ if ( p->pPars->pFuncUser )
+ If_ObjForEachCut( pObj, pCut, i )
+ p->pPars->pFuncUser( p, pObj, pCut );
+
+ // free the cuts
+ If_ManDerefNodeCutSet( p, pObj );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Finds the best cut for the choice node.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void If_ObjPerformMappingChoice( If_Man_t * p, If_Obj_t * pObj, int Mode, int fPreprocess )
+{
+ If_Set_t * pCutSet;
+ If_Obj_t * pTemp;
+ If_Cut_t * pCutTemp, * pCut;
+ int i;
+ assert( pObj->pEquiv != NULL );
+
+ // prepare
+ if ( Mode && pObj->nRefs > 0 )
+ If_CutAreaDeref( p, If_ObjCutBest(pObj) );
+
+ // remove elementary cuts
+ for ( pTemp = pObj; pTemp; pTemp = pTemp->pEquiv )
+ pTemp->pCutSet->nCuts--;
+
+ // update the cutset of the node
+ pCutSet = pObj->pCutSet;
+
+ // generate cuts
+ for ( pTemp = pObj->pEquiv; pTemp; pTemp = pTemp->pEquiv )
+ {
+ assert( pTemp->nRefs == 0 );
+ assert( p->pPars->fSeqMap || pTemp->pCutSet->nCuts > 0 );
+ // go through the cuts of this node
+ If_ObjForEachCut( pTemp, pCutTemp, i )
+ {
+ assert( p->pPars->fSeqMap || pCutTemp->nLeaves > 1 );
+ // get the next free cut
+ assert( pCutSet->nCuts <= pCutSet->nCutsMax );
+ pCut = pCutSet->ppCuts[pCutSet->nCuts];
+ // copy the cut into storage
+ If_CutCopy( p, pCut, pCutTemp );
+ // check if this cut is contained in any of the available cuts
+ if ( If_CutFilter( pCutSet, pCut ) )
+ continue;
+ // check if the cut satisfies the required times
+ assert( pCut->Delay == If_CutDelay( p, pCut ) );
+ if ( Mode && pCut->Delay > pObj->Required + p->fEpsilon )
+ continue;
+ // set the phase attribute
+ assert( pCut->fCompl == 0 );
+ pCut->fCompl ^= (pObj->fPhase ^ pTemp->fPhase); // why ^= ?
+ // compute area of the cut (this area may depend on the application specific cost)
+ pCut->Area = (Mode == 2)? If_CutAreaDerefed( p, pCut ) : If_CutAreaFlow( p, pCut );
+ if ( p->pPars->fEdge )
+ pCut->Edge = (Mode == 2)? If_CutEdgeDerefed( p, pCut ) : If_CutEdgeFlow( p, pCut );
+ pCut->AveRefs = (Mode == 0)? (float)0.0 : If_CutAverageRefs( p, pCut );
+ // insert the cut into storage
+ If_CutSort( p, pCutSet, pCut );
+ }
+ }
+ assert( pCutSet->nCuts > 0 );
+
+ // add the trivial cut to the set
+ If_ManSetupCutTriv( p, pCutSet->ppCuts[pCutSet->nCuts++], pObj->Id );
+ assert( pCutSet->nCuts <= pCutSet->nCutsMax+1 );
+
+ // update the best cut
+ if ( !fPreprocess || pCutSet->ppCuts[0]->Delay <= pObj->Required + p->fEpsilon )
+ If_CutCopy( p, If_ObjCutBest(pObj), pCutSet->ppCuts[0] );
+ assert( p->pPars->fSeqMap || If_ObjCutBest(pObj)->nLeaves > 1 );
+
+ // ref the selected cut
+ if ( Mode && pObj->nRefs > 0 )
+ If_CutAreaRef( p, If_ObjCutBest(pObj) );
+
+ // free the cuts
+ If_ManDerefChoiceCutSet( p, pObj );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Performs one mapping pass over all nodes.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int If_ManPerformMappingRound( If_Man_t * p, int nCutsUsed, int Mode, int fPreprocess, char * pLabel )
+{
+// ProgressBar * pProgress;
+ If_Obj_t * pObj;
+ int i, clk = clock();
+ float arrTime;
+ assert( Mode >= 0 && Mode <= 2 );
+ // set the sorting function
+ if ( Mode || p->pPars->fArea ) // area
+ p->SortMode = 1;
+ else if ( p->pPars->fFancy )
+ p->SortMode = 2;
+ else
+ p->SortMode = 0;
+ // set the cut number
+ p->nCutsUsed = nCutsUsed;
+ p->nCutsMerged = 0;
+ // make sure the visit counters are all zero
+ If_ManForEachNode( p, pObj, i )
+ assert( pObj->nVisits == pObj->nVisitsCopy );
+ // map the internal nodes
+ if ( p->pManTim != NULL )
+ {
+ Tim_ManIncrementTravId( p->pManTim );
+ If_ManForEachObj( p, pObj, i )
+ {
+ if ( If_ObjIsAnd(pObj) )
+ {
+ If_ObjPerformMappingAnd( p, pObj, Mode, fPreprocess );
+ if ( pObj->fRepr )
+ If_ObjPerformMappingChoice( p, pObj, Mode, fPreprocess );
+ }
+ else if ( If_ObjIsCi(pObj) )
+ {
+ arrTime = Tim_ManGetPiArrival( p->pManTim, pObj->IdPio );
+ If_ObjSetArrTime( pObj, arrTime );
+/*
+ if ( pObj->IdPio >= 2000 )
+ {
+ int x = 0;
+ printf( "+%d %6.3f ", pObj->IdPio, arrTime );
+ }
+*/
+ }
+ else if ( If_ObjIsCo(pObj) )
+ {
+ arrTime = If_ObjArrTime( If_ObjFanin0(pObj) );
+ Tim_ManSetPoArrival( p->pManTim, pObj->IdPio, arrTime );
+ }
+ else if ( If_ObjIsConst1(pObj) )
+ {
+ }
+ else
+ assert( 0 );
+ }
+// Tim_ManPrint( p->pManTim );
+ }
+ else
+ {
+ // pProgress = Extra_ProgressBarStart( stdout, If_ManObjNum(p) );
+ If_ManForEachNode( p, pObj, i )
+ {
+ // Extra_ProgressBarUpdate( pProgress, i, pLabel );
+ If_ObjPerformMappingAnd( p, pObj, Mode, fPreprocess );
+ if ( pObj->fRepr )
+ If_ObjPerformMappingChoice( p, pObj, Mode, fPreprocess );
+ }
+ }
+// Extra_ProgressBarStop( pProgress );
+ // make sure the visit counters are all zero
+ If_ManForEachNode( p, pObj, i )
+ assert( pObj->nVisits == 0 );
+ // compute required times and stats
+ If_ManComputeRequired( p );
+// Tim_ManPrint( p->pManTim );
+ if ( p->pPars->fVerbose )
+ {
+ char Symb = fPreprocess? 'P' : ((Mode == 0)? 'D' : ((Mode == 1)? 'F' : 'A'));
+ printf( "%c: Del = %7.2f. Ar = %9.1f. Edge = %8d. Cut = %8d. ",
+ Symb, p->RequiredGlo, p->AreaGlo, p->nNets, p->nCutsMerged );
+ PRT( "T", clock() - clk );
+// printf( "Max number of cuts = %d. Average number of cuts = %5.2f.\n",
+// p->nCutsMax, 1.0 * p->nCutsMerged / If_ManAndNum(p) );
+ }
+ return 1;
+}
+
+
+////////////////////////////////////////////////////////////////////////
+/// END OF FILE ///
+////////////////////////////////////////////////////////////////////////
+
+
diff --git a/src/map/if/ifReduce.c b/src/map/if/ifReduce.c
new file mode 100644
index 00000000..0912a965
--- /dev/null
+++ b/src/map/if/ifReduce.c
@@ -0,0 +1,575 @@
+/**CFile****************************************************************
+
+ FileName [ifExpand.c]
+
+ SystemName [ABC: Logic synthesis and verification system.]
+
+ PackageName [FPGA mapping based on priority cuts.]
+
+ Synopsis [Incremental improvement of current mapping.]
+
+ Author [Alan Mishchenko]
+
+ Affiliation [UC Berkeley]
+
+ Date [Ver. 1.0. Started - November 21, 2006.]
+
+ Revision [$Id: ifExpand.c,v 1.00 2006/11/21 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "if.h"
+
+////////////////////////////////////////////////////////////////////////
+/// DECLARATIONS ///
+////////////////////////////////////////////////////////////////////////
+
+static void If_ManImproveReduce( If_Man_t * p, int nLimit );
+static void If_ManImproveExpand( If_Man_t * p, int nLimit );
+static void If_ManImproveNodeExpand( If_Man_t * p, If_Obj_t * pObj, int nLimit, Vec_Ptr_t * vFront, Vec_Ptr_t * vFrontOld, Vec_Ptr_t * vVisited );
+static void If_ManImproveNodePrepare( If_Man_t * p, If_Obj_t * pObj, int nLimit, Vec_Ptr_t * vFront, Vec_Ptr_t * vFrontOld, Vec_Ptr_t * vVisited );
+static void If_ManImproveNodeUpdate( If_Man_t * p, If_Obj_t * pObj, Vec_Ptr_t * vFront );
+static void If_ManImproveNodeFaninCompact( If_Man_t * p, If_Obj_t * pObj, int nLimit, Vec_Ptr_t * vFront, Vec_Ptr_t * vVisited );
+
+////////////////////////////////////////////////////////////////////////
+/// FUNCTION DEFINITIONS ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+ Synopsis [Improves current mapping using expand/Expand of one cut.]
+
+ Description [Assumes current mapping assigned and required times computed.]
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void If_ManImproveMapping( If_Man_t * p )
+{
+ int clk;
+
+ clk = clock();
+ If_ManImproveExpand( p, p->pPars->nLutSize );
+ If_ManComputeRequired( p );
+ if ( p->pPars->fVerbose )
+ {
+ printf( "E: Del = %7.2f. Ar = %9.1f. Edge = %8d. Cut = %8d. ",
+ p->RequiredGlo, p->AreaGlo, p->nNets, p->nCutsMerged );
+ PRT( "T", clock() - clk );
+ }
+
+/*
+ clk = clock();
+ If_ManImproveReduce( p, p->pPars->nLutSize );
+ If_ManComputeRequired( p, 0 );
+ if ( p->pPars->fVerbose )
+ {
+ printf( "R: Del = %6.2f. Area = %8.2f. Nets = %6d. Cuts = %8d. Lim = %2d. Ave = %5.2f. ",
+ p->RequiredGlo, p->AreaGlo, p->nNets, p->nCutsMerged, p->nCutsUsed, 1.0 * p->nCutsMerged / If_ManAndNum(p) );
+ PRT( "T", clock() - clk );
+ }
+*/
+/*
+ clk = clock();
+ If_ManImproveExpand( p, p->pPars->nLutSize );
+ If_ManComputeRequired( p, 0 );
+ if ( p->pPars->fVerbose )
+ {
+ printf( "E: Del = %6.2f. Area = %8.2f. Nets = %6d. Cuts = %8d. Lim = %2d. Ave = %5.2f. ",
+ p->RequiredGlo, p->AreaGlo, p->nNets, p->nCutsMerged, p->nCutsUsed, 1.0 * p->nCutsMerged / If_ManAndNum(p) );
+ PRT( "T", clock() - clk );
+ }
+*/
+}
+
+/**Function*************************************************************
+
+ Synopsis [Performs area recovery for each node.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void If_ManImproveExpand( If_Man_t * p, int nLimit )
+{
+ Vec_Ptr_t * vFront, * vFrontOld, * vVisited;
+ If_Obj_t * pObj;
+ int i;
+ vFront = Vec_PtrAlloc( nLimit );
+ vFrontOld = Vec_PtrAlloc( nLimit );
+ vVisited = Vec_PtrAlloc( 100 );
+ // iterate through all nodes in the topological order
+ If_ManForEachNode( p, pObj, i )
+ If_ManImproveNodeExpand( p, pObj, nLimit, vFront, vFrontOld, vVisited );
+ Vec_PtrFree( vFront );
+ Vec_PtrFree( vFrontOld );
+ Vec_PtrFree( vVisited );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Counts the number of nodes with no external fanout.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int If_ManImproveCutCost( If_Man_t * p, Vec_Ptr_t * vFront )
+{
+ If_Obj_t * pFanin;
+ int i, Counter = 0;
+ Vec_PtrForEachEntry( vFront, pFanin, i )
+ if ( pFanin->nRefs == 0 )
+ Counter++;
+ return Counter;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Performs area recovery for each node.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void If_ManImproveNodeExpand( If_Man_t * p, If_Obj_t * pObj, int nLimit, Vec_Ptr_t * vFront, Vec_Ptr_t * vFrontOld, Vec_Ptr_t * vVisited )
+{
+ If_Obj_t * pFanin;
+ If_Cut_t * pCut;
+ int CostBef, CostAft, i;
+ float DelayOld, AreaBef, AreaAft;
+ pCut = If_ObjCutBest(pObj);
+ pCut->Delay = If_CutDelay( p, pCut );
+ assert( pCut->Delay <= pObj->Required + p->fEpsilon );
+ if ( pObj->nRefs == 0 )
+ return;
+ // get the delay
+ DelayOld = pCut->Delay;
+ // get the area
+ AreaBef = If_CutAreaRefed( p, pCut );
+// if ( AreaBef == 1 )
+// return;
+ // the cut is non-trivial
+ If_ManImproveNodePrepare( p, pObj, nLimit, vFront, vFrontOld, vVisited );
+ // iteratively modify the cut
+ If_CutAreaDeref( p, pCut );
+ CostBef = If_ManImproveCutCost( p, vFront );
+ If_ManImproveNodeFaninCompact( p, pObj, nLimit, vFront, vVisited );
+ CostAft = If_ManImproveCutCost( p, vFront );
+ If_CutAreaRef( p, pCut );
+ assert( CostBef >= CostAft );
+ // clean up
+ Vec_PtrForEachEntry( vVisited, pFanin, i )
+ pFanin->fMark = 0;
+ // update the node
+ If_ManImproveNodeUpdate( p, pObj, vFront );
+ pCut->Delay = If_CutDelay( p, pCut );
+ // get the new area
+ AreaAft = If_CutAreaRefed( p, pCut );
+ if ( AreaAft > AreaBef || pCut->Delay > pObj->Required + p->fEpsilon )
+ {
+ If_ManImproveNodeUpdate( p, pObj, vFrontOld );
+ AreaAft = If_CutAreaRefed( p, pCut );
+ assert( AreaAft == AreaBef );
+ pCut->Delay = DelayOld;
+ }
+}
+
+/**Function*************************************************************
+
+ Synopsis [Performs area recovery for each node.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void If_ManImproveMark_rec( If_Man_t * p, If_Obj_t * pObj, Vec_Ptr_t * vVisited )
+{
+ if ( pObj->fMark )
+ return;
+ assert( If_ObjIsAnd(pObj) );
+ If_ManImproveMark_rec( p, If_ObjFanin0(pObj), vVisited );
+ If_ManImproveMark_rec( p, If_ObjFanin1(pObj), vVisited );
+ Vec_PtrPush( vVisited, pObj );
+ pObj->fMark = 1;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Prepares node mapping.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void If_ManImproveNodePrepare( If_Man_t * p, If_Obj_t * pObj, int nLimit, Vec_Ptr_t * vFront, Vec_Ptr_t * vFrontOld, Vec_Ptr_t * vVisited )
+{
+ If_Cut_t * pCut;
+ If_Obj_t * pLeaf;
+ int i;
+ Vec_PtrClear( vFront );
+ Vec_PtrClear( vFrontOld );
+ Vec_PtrClear( vVisited );
+ // expand the cut downwards from the given place
+ pCut = If_ObjCutBest(pObj);
+ If_CutForEachLeaf( p, pCut, pLeaf, i )
+ {
+ Vec_PtrPush( vFront, pLeaf );
+ Vec_PtrPush( vFrontOld, pLeaf );
+ Vec_PtrPush( vVisited, pLeaf );
+ pLeaf->fMark = 1;
+ }
+ // mark the nodes in the cone
+ If_ManImproveMark_rec( p, pObj, vVisited );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Updates the frontier.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void If_ManImproveNodeUpdate( If_Man_t * p, If_Obj_t * pObj, Vec_Ptr_t * vFront )
+{
+ If_Cut_t * pCut;
+ If_Obj_t * pFanin;
+ int i;
+ pCut = If_ObjCutBest(pObj);
+ // deref node's cut
+ If_CutAreaDeref( p, pCut );
+ // update the node's cut
+ pCut->nLeaves = Vec_PtrSize(vFront);
+ Vec_PtrForEachEntry( vFront, pFanin, i )
+ pCut->pLeaves[i] = pFanin->Id;
+ // ref the new cut
+ If_CutAreaRef( p, pCut );
+}
+
+
+/**Function*************************************************************
+
+ Synopsis [Returns 1 if the number of fanins will grow.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int If_ManImproveNodeWillGrow( If_Man_t * p, If_Obj_t * pObj )
+{
+ If_Obj_t * pFanin0, * pFanin1;
+ assert( If_ObjIsAnd(pObj) );
+ pFanin0 = If_ObjFanin0(pObj);
+ pFanin1 = If_ObjFanin1(pObj);
+ return !pFanin0->fMark && !pFanin1->fMark;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Returns the increase in the number of fanins with no external refs.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int If_ManImproveNodeFaninCost( If_Man_t * p, If_Obj_t * pObj )
+{
+ int Counter = 0;
+ assert( If_ObjIsAnd(pObj) );
+ // check if the node has external refs
+ if ( pObj->nRefs == 0 )
+ Counter--;
+ // increment the number of fanins without external refs
+ if ( !If_ObjFanin0(pObj)->fMark && If_ObjFanin0(pObj)->nRefs == 0 )
+ Counter++;
+ // increment the number of fanins without external refs
+ if ( !If_ObjFanin1(pObj)->fMark && If_ObjFanin1(pObj)->nRefs == 0 )
+ Counter++;
+ return Counter;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Updates the frontier.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void If_ManImproveNodeFaninUpdate( If_Man_t * p, If_Obj_t * pObj, Vec_Ptr_t * vFront, Vec_Ptr_t * vVisited )
+{
+ If_Obj_t * pFanin;
+ assert( If_ObjIsAnd(pObj) );
+ Vec_PtrRemove( vFront, pObj );
+ pFanin = If_ObjFanin0(pObj);
+ if ( !pFanin->fMark )
+ {
+ Vec_PtrPush( vFront, pFanin );
+ Vec_PtrPush( vVisited, pFanin );
+ pFanin->fMark = 1;
+ }
+ pFanin = If_ObjFanin1(pObj);
+ if ( !pFanin->fMark )
+ {
+ Vec_PtrPush( vFront, pFanin );
+ Vec_PtrPush( vVisited, pFanin );
+ pFanin->fMark = 1;
+ }
+}
+
+/**Function*************************************************************
+
+ Synopsis [Compacts the number of external refs.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int If_ManImproveNodeFaninCompact0( If_Man_t * p, If_Obj_t * pObj, int nLimit, Vec_Ptr_t * vFront, Vec_Ptr_t * vVisited )
+{
+ If_Obj_t * pFanin;
+ int i;
+ Vec_PtrForEachEntry( vFront, pFanin, i )
+ {
+ if ( If_ObjIsCi(pFanin) )
+ continue;
+ if ( If_ManImproveNodeWillGrow(p, pFanin) )
+ continue;
+ if ( If_ManImproveNodeFaninCost(p, pFanin) <= 0 )
+ {
+ If_ManImproveNodeFaninUpdate( p, pFanin, vFront, vVisited );
+ return 1;
+ }
+ }
+ return 0;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Compacts the number of external refs.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int If_ManImproveNodeFaninCompact1( If_Man_t * p, If_Obj_t * pObj, int nLimit, Vec_Ptr_t * vFront, Vec_Ptr_t * vVisited )
+{
+ If_Obj_t * pFanin;
+ int i;
+ Vec_PtrForEachEntry( vFront, pFanin, i )
+ {
+ if ( If_ObjIsCi(pFanin) )
+ continue;
+ if ( If_ManImproveNodeFaninCost(p, pFanin) < 0 )
+ {
+ If_ManImproveNodeFaninUpdate( p, pFanin, vFront, vVisited );
+ return 1;
+ }
+ }
+ return 0;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Compacts the number of external refs.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int If_ManImproveNodeFaninCompact2( If_Man_t * p, If_Obj_t * pObj, int nLimit, Vec_Ptr_t * vFront, Vec_Ptr_t * vVisited )
+{
+ If_Obj_t * pFanin;
+ int i;
+ Vec_PtrForEachEntry( vFront, pFanin, i )
+ {
+ if ( If_ObjIsCi(pFanin) )
+ continue;
+ if ( If_ManImproveNodeFaninCost(p, pFanin) <= 0 )
+ {
+ If_ManImproveNodeFaninUpdate( p, pFanin, vFront, vVisited );
+ return 1;
+ }
+ }
+ return 0;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Compacts the number of external refs.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int If_ManImproveNodeFaninCompact_int( If_Man_t * p, If_Obj_t * pObj, int nLimit, Vec_Ptr_t * vFront, Vec_Ptr_t * vVisited )
+{
+ if ( If_ManImproveNodeFaninCompact0(p, pObj, nLimit, vFront, vVisited) )
+ return 1;
+ if ( Vec_PtrSize(vFront) < nLimit && If_ManImproveNodeFaninCompact1(p, pObj, nLimit, vFront, vVisited) )
+ return 1;
+// if ( Vec_PtrSize(vFront) < nLimit && If_ManImproveNodeFaninCompact2(p, pObj, nLimit, vFront, vVisited) )
+// return 1;
+ assert( Vec_PtrSize(vFront) <= nLimit );
+ return 0;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Compacts the number of external refs.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void If_ManImproveNodeFaninCompact( If_Man_t * p, If_Obj_t * pObj, int nLimit, Vec_Ptr_t * vFront, Vec_Ptr_t * vVisited )
+{
+ while ( If_ManImproveNodeFaninCompact_int( p, pObj, nLimit, vFront, vVisited ) );
+}
+
+
+
+
+
+/**Function*************************************************************
+
+ Synopsis [Performs fast mapping for one node.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void If_ManImproveNodeReduce( If_Man_t * p, If_Obj_t * pObj, int nLimit )
+{
+/*
+ If_Cut_t * pCut, * pCut0, * pCut1, * pCutR;
+ If_Obj_t * pFanin0, * pFanin1;
+ float AreaBef, AreaAft;
+ int RetValue;
+
+ assert( nLimit <= 32 );
+ assert( If_ObjIsAnd(pObj) );
+ // get the fanins
+ pFanin0 = If_ObjFanin0(pObj);
+ pFanin1 = If_ObjFanin1(pObj);
+ // get the cuts
+ pCut = If_ObjCutBest(pObj);
+ pCut0 = If_ObjIsCi(pFanin0) ? If_ObjCutTriv(pFanin0) : If_ObjCutBest(pFanin0);
+ pCut1 = If_ObjIsCi(pFanin1) ? If_ObjCutTriv(pFanin1) : If_ObjCutBest(pFanin1);
+ assert( pCut->Delay <= pObj->Required + p->fEpsilon );
+
+ // deref the cut if the node is refed
+ if ( pObj->nRefs > 0 )
+ If_CutAreaDeref( p, pCut );
+ // get the area
+ AreaBef = If_CutAreaDerefed( p, pCut );
+ // get the fanin support
+ if ( pFanin0->nRefs > 2 && pCut0->Delay < pObj->Required + p->fEpsilon )
+// if ( pSupp0->nRefs > 0 && pSupp0->Delay < pSupp->DelayR ) // this leads to 2% worse results
+ {
+ pCut0 = If_ObjCutTriv(pFanin0);
+ }
+ // get the fanin support
+ if ( pFanin1->nRefs > 2 && pCut1->Delay < pObj->Required + p->fEpsilon )
+// if ( pSupp1->nRefs > 0 && pSupp1->Delay < pSupp->DelayR )
+ {
+ pCut1 = If_ObjCutTriv(pFanin1);
+ }
+
+ // merge the cuts
+ pCutR = p->ppCuts[0];
+ RetValue = If_CutMerge( pCut0, pCut1, pCutR );
+ // try very simple cut
+ if ( !RetValue )
+ {
+ RetValue = If_CutMerge( If_ObjCutTriv(pFanin0), If_ObjCutTriv(pFanin1), pCutR );
+ assert( RetValue == 1 );
+ }
+ if ( RetValue )
+ {
+ pCutR->Delay = If_CutDelay( p, pCutR );
+ AreaAft = If_CutAreaDerefed( p, pCutR );
+ // update the best cut
+ if ( AreaAft < AreaBef - p->fEpsilon && pCutR->Delay < pObj->Required + p->fEpsilon )
+ If_CutCopy( p, pCut, pCutR );
+ }
+ // recompute the delay of the best cut
+ pCut->Delay = If_CutDelay( p, pCut );
+ // ref the cut if the node is refed
+ if ( pObj->nRefs > 0 )
+ If_CutRef( p, pCut );
+*/
+}
+
+/**Function*************************************************************
+
+ Synopsis [Performs area recovery for each node.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void If_ManImproveReduce( If_Man_t * p, int nLimit )
+{
+ If_Obj_t * pObj;
+ int i;
+ If_ManForEachNode( p, pObj, i )
+ If_ManImproveNodeReduce( p, pObj, nLimit );
+}
+
+////////////////////////////////////////////////////////////////////////
+/// END OF FILE ///
+////////////////////////////////////////////////////////////////////////
+
+
diff --git a/src/map/if/ifSeq.c b/src/map/if/ifSeq.c
new file mode 100644
index 00000000..8d1de8c1
--- /dev/null
+++ b/src/map/if/ifSeq.c
@@ -0,0 +1,405 @@
+/**CFile****************************************************************
+
+ FileName [ifSeq.c]
+
+ SystemName [ABC: Logic synthesis and verification system.]
+
+ PackageName [FPGA mapping based on priority cuts.]
+
+ Synopsis [Sequential mapping.]
+
+ Author [Alan Mishchenko]
+
+ Affiliation [UC Berkeley]
+
+ Date [Ver. 1.0. Started - November 21, 2006.]
+
+ Revision [$Id: ifSeq.c,v 1.00 2006/11/21 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "if.h"
+
+////////////////////////////////////////////////////////////////////////
+/// DECLARATIONS ///
+////////////////////////////////////////////////////////////////////////
+
+extern int s_MappingTime;
+
+////////////////////////////////////////////////////////////////////////
+/// FUNCTION DEFINITIONS ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+ Synopsis [Prepares for sequential mapping by linking the latches.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void If_ManPrepareMappingSeq( If_Man_t * p )
+{
+ If_Obj_t * pObjLi, * pObjLo;
+ int i;
+
+ // link the latch outputs (CIs) directly to the drivers of latch inputs (COs)
+ for ( i = 0; i < p->pPars->nLatches; i++ )
+ {
+ pObjLi = If_ManLi( p, i );
+ pObjLo = If_ManLo( p, i );
+ pObjLo->pFanin0 = If_ObjFanin0( pObjLi );
+ pObjLo->fCompl0 = If_ObjFaninC0( pObjLi );
+ }
+}
+
+/**Function*************************************************************
+
+ Synopsis [Collects latches in the topological order.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void If_ManCollectLatches_rec( If_Obj_t * pObj, Vec_Ptr_t * vLatches )
+{
+ if ( !If_ObjIsLatch(pObj) )
+ return;
+ if ( pObj->fMark )
+ return;
+ pObj->fMark = 1;
+ If_ManCollectLatches_rec( pObj->pFanin0, vLatches );
+ Vec_PtrPush( vLatches, pObj );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Collects latches in the topological order.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Vec_Ptr_t * If_ManCollectLatches( If_Man_t * p )
+{
+ Vec_Ptr_t * vLatches;
+ If_Obj_t * pObj;
+ int i;
+ // collect latches
+ vLatches = Vec_PtrAlloc( p->pPars->nLatches );
+ If_ManForEachLatchOutput( p, pObj, i )
+ If_ManCollectLatches_rec( pObj, vLatches );
+ // clean marks
+ Vec_PtrForEachEntry( vLatches, pObj, i )
+ pObj->fMark = 0;
+ assert( Vec_PtrSize(vLatches) == p->pPars->nLatches );
+ return vLatches;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Performs one pass of l-value computation over all nodes.]
+
+ Description [Experimentally it was found that checking POs changes
+ is not enough to detect the convergence of l-values in the network.]
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int If_ManPerformMappingRoundSeq( If_Man_t * p, int nIter )
+{
+ If_Obj_t * pObj;
+ int i, clk = clock();
+ int fVeryVerbose = 0;
+ int fChange = 0;
+
+ // map the internal nodes
+ p->nCutsMerged = 0;
+ If_ManForEachNode( p, pObj, i )
+ {
+ If_ObjPerformMappingAnd( p, pObj, 0, 0 );
+ if ( pObj->fRepr )
+ If_ObjPerformMappingChoice( p, pObj, 0, 0 );
+ }
+
+ // postprocess the mapping
+//printf( "Itereation %d: \n", nIter );
+ If_ManForEachNode( p, pObj, i )
+ {
+ // update the LValues stored separately
+ if ( If_ObjLValue(pObj) < If_ObjCutBest(pObj)->Delay - p->fEpsilon )
+ {
+ If_ObjSetLValue( pObj, If_ObjCutBest(pObj)->Delay );
+ fChange = 1;
+ }
+//printf( "%d ", (int)If_ObjLValue(pObj) );
+ // reset the visit counters
+ assert( pObj->nVisits == 0 );
+ pObj->nVisits = pObj->nVisitsCopy;
+ }
+//printf( "\n" );
+
+ // propagate LValues over the registers
+ Vec_PtrForEachEntry( p->vLatchOrder, pObj, i )
+ {
+ If_ObjSetLValue( pObj, If_ObjLValue(If_ObjFanin0(pObj)) - p->Period );
+ If_ObjSetArrTime( pObj, If_ObjLValue(pObj) );
+ }
+
+ // compute area and delay
+ if ( fVeryVerbose )
+ {
+ p->RequiredGlo = If_ManDelayMax( p, 1 );
+ p->AreaGlo = If_ManScanMapping(p);
+ printf( "S%d: Fi = %6.2f. Del = %6.2f. Area = %8.2f. Cuts = %8d. ",
+ nIter, (float)p->Period, p->RequiredGlo, p->AreaGlo, p->nCutsMerged );
+ PRT( "T", clock() - clk );
+ }
+ return fChange;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Returns 1 if retiming with this clock period is feasible.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int If_ManBinarySearchPeriod( If_Man_t * p )
+{
+ If_Obj_t * pObj;
+ int i, c, fConverged;
+ int fResetRefs = 0;
+
+ p->nAttempts++;
+
+ // reset initial LValues (PIs to 0; others to -inf)
+ If_ManForEachObj( p, pObj, i )
+ {
+ if ( If_ObjIsPi(pObj) || If_ObjIsConst1(pObj) )
+ {
+ If_ObjSetLValue( pObj, (float)0.0 );
+ If_ObjSetArrTime( pObj, (float)0.0 );
+ }
+ else
+ {
+ If_ObjSetLValue( pObj, (float)-IF_INFINITY );
+ If_ObjSetArrTime( pObj, (float)-IF_INFINITY );
+ }
+ // undo any previous mapping, except for CIs
+ if ( If_ObjIsAnd(pObj) )
+ If_ObjCutBest(pObj)->nLeaves = 0;
+ }
+
+ // update all values iteratively
+ fConverged = 0;
+ for ( c = 1; c <= p->nMaxIters; c++ )
+ {
+ if ( !If_ManPerformMappingRoundSeq( p, c ) )
+ {
+ p->RequiredGlo = If_ManDelayMax( p, 1 );
+ fConverged = 1;
+ break;
+ }
+ p->RequiredGlo = If_ManDelayMax( p, 1 );
+//printf( "Global = %d \n", (int)p->RequiredGlo );
+ if ( p->RequiredGlo > p->Period + p->fEpsilon )
+ break;
+ }
+
+ // report the results
+ if ( p->pPars->fVerbose )
+ {
+ p->AreaGlo = If_ManScanMapping(p);
+ printf( "Attempt = %2d. Iters = %3d. Area = %10.2f. Fi = %6.2f. ", p->nAttempts, c, p->AreaGlo, (float)p->Period );
+ if ( fConverged )
+ printf( " Feasible" );
+ else if ( c > p->nMaxIters )
+ printf( "Infeasible (timeout)" );
+ else
+ printf( "Infeasible" );
+ printf( "\n" );
+ }
+ return fConverged;
+}
+
+
+/**Function*************************************************************
+
+ Synopsis [Performs binary search for the optimal clock period.]
+
+ Description [Assumes that FiMin is infeasible while FiMax is feasible.]
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int If_ManBinarySearch_rec( If_Man_t * p, int FiMin, int FiMax )
+{
+ assert( FiMin < FiMax );
+ if ( FiMin + 1 == FiMax )
+ return FiMax;
+ // compute the median
+ p->Period = FiMin + (FiMax - FiMin)/2;
+ if ( If_ManBinarySearchPeriod( p ) )
+ return If_ManBinarySearch_rec( p, FiMin, p->Period ); // Median is feasible
+ else
+ return If_ManBinarySearch_rec( p, p->Period, FiMax ); // Median is infeasible
+}
+
+/**Function*************************************************************
+
+ Synopsis [Performs sequential mapping.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void If_ManPerformMappingSeqPost( If_Man_t * p )
+{
+ If_Obj_t * pObjLi, * pObjLo, * pObj;
+ int i;
+
+ // link the latch outputs (CIs) directly to the drivers of latch inputs (COs)
+ for ( i = 0; i < p->pPars->nLatches; i++ )
+ {
+ pObjLi = If_ManLi( p, i );
+ pObjLo = If_ManLo( p, i );
+// printf( "%3d : %2d -> %2d \n", i,
+// (int)If_ObjLValue(If_ObjFanin0(pObjLo)), (int)If_ObjLValue(pObjLo) );
+ }
+
+ // set arrival times
+ assert( p->pPars->pTimesArr != NULL );
+ If_ManForEachLatchOutput( p, pObjLo, i )
+ p->pPars->pTimesArr[i] = If_ObjLValue(pObjLo);
+
+ // set the required times
+ assert( p->pPars->pTimesReq == NULL );
+ p->pPars->pTimesReq = ALLOC( float, If_ManCoNum(p) );
+ If_ManForEachPo( p, pObj, i )
+ {
+ p->pPars->pTimesReq[i] = p->RequiredGlo2;
+// printf( "Out %3d : %2d \n", i, (int)p->pPars->pTimesReq[i] );
+ }
+ If_ManForEachLatchInput( p, pObjLi, i )
+ {
+ p->pPars->pTimesReq[i] = If_ObjLValue(If_ObjFanin0(pObjLi));
+// printf( "Out %3d : %2d \n", i, (int)p->pPars->pTimesReq[i] );
+ }
+
+ // undo previous mapping
+ If_ManForEachObj( p, pObj, i )
+ if ( If_ObjIsAnd(pObj) )
+ If_ObjCutBest(pObj)->nLeaves = 0;
+
+ // map again combinationally
+ p->pPars->fSeqMap = 0;
+ If_ManPerformMappingComb( p );
+ p->pPars->fSeqMap = 1;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Performs sequential mapping.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int If_ManPerformMappingSeq( If_Man_t * p )
+{
+ int clkTotal = clock();
+ int PeriodBest;
+
+ p->SortMode = 0;
+
+ // perform combinational mapping to get the upper bound on the clock period
+ If_ManPerformMappingRound( p, 1, 0, 0, NULL );
+ p->RequiredGlo = If_ManDelayMax( p, 0 );
+ p->RequiredGlo2 = p->RequiredGlo;
+
+ // set direct linking of latches with their inputs
+ If_ManPrepareMappingSeq( p );
+
+ // collect latches
+ p->vLatchOrder = If_ManCollectLatches( p );
+
+ // set parameters
+ p->nCutsUsed = p->pPars->nCutsMax;
+ p->nAttempts = 0;
+ p->nMaxIters = 50;
+ p->Period = (int)p->RequiredGlo;
+
+ // make sure the clock period works
+ if ( !If_ManBinarySearchPeriod( p ) )
+ {
+ printf( "If_ManPerformMappingSeq(): The upper bound on the clock period cannot be computed.\n" );
+ return 0;
+ }
+
+ // perform binary search
+ PeriodBest = If_ManBinarySearch_rec( p, 0, p->Period );
+
+ // recompute the best l-values
+ if ( p->Period != PeriodBest )
+ {
+ p->Period = PeriodBest;
+ if ( !If_ManBinarySearchPeriod( p ) )
+ {
+ printf( "If_ManPerformMappingSeq(): The final clock period cannot be confirmed.\n" );
+ return 0;
+ }
+ }
+ if ( p->pPars->fVerbose )
+ {
+/*
+ {
+ FILE * pTable;
+ pTable = fopen( "iscas/stats_new.txt", "a+" );
+// fprintf( pTable, "%s ", pNtk->pName );
+ fprintf( pTable, "%d ", p->Period );
+ // fprintf( pTable, "%.2f ", (float)(s_MappingMem)/(float)(1<<20) );
+// fprintf( pTable, "%.2f", (float)(s_MappingTime)/(float)(CLOCKS_PER_SEC) );
+// fprintf( pTable, "\n" );
+ fclose( pTable );
+ }
+*/
+ printf( "The best clock period is %3d. ", p->Period );
+ PRT( "Sequential time", clock() - clkTotal );
+ }
+ p->RequiredGlo = (float)PeriodBest;
+
+ // postprocess it using combinational mapping
+ If_ManPerformMappingSeqPost( p );
+ s_MappingTime = clock() - clkTotal;
+ return 1;
+}
+
+////////////////////////////////////////////////////////////////////////
+/// END OF FILE ///
+////////////////////////////////////////////////////////////////////////
+
+
diff --git a/src/map/if/ifTime.c b/src/map/if/ifTime.c
new file mode 100644
index 00000000..3d1dab1b
--- /dev/null
+++ b/src/map/if/ifTime.c
@@ -0,0 +1,228 @@
+/**CFile****************************************************************
+
+ FileName [ifTime.c]
+
+ SystemName [ABC: Logic synthesis and verification system.]
+
+ PackageName [FPGA mapping based on priority cuts.]
+
+ Synopsis [Computation of delay paramters depending on the library.]
+
+ Author [Alan Mishchenko]
+
+ Affiliation [UC Berkeley]
+
+ Date [Ver. 1.0. Started - November 21, 2006.]
+
+ Revision [$Id: ifTime.c,v 1.00 2006/11/21 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "if.h"
+
+////////////////////////////////////////////////////////////////////////
+/// DECLARATIONS ///
+////////////////////////////////////////////////////////////////////////
+
+static void If_CutSortInputPins( If_Man_t * p, If_Cut_t * pCut, int * pPinPerm, float * pPinDelays );
+
+////////////////////////////////////////////////////////////////////////
+/// FUNCTION DEFINITIONS ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+ Synopsis [Computes delay.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+float If_CutDelay( If_Man_t * p, If_Cut_t * pCut )
+{
+ static int pPinPerm[IF_MAX_LUTSIZE];
+ static float pPinDelays[IF_MAX_LUTSIZE];
+ If_Obj_t * pLeaf;
+ float Delay, DelayCur;
+ float * pLutDelays;
+ int i, Shift;
+ assert( p->pPars->fSeqMap || pCut->nLeaves > 1 );
+ Delay = -IF_FLOAT_LARGE;
+ if ( p->pPars->pLutLib )
+ {
+ assert( !p->pPars->fLiftLeaves );
+ pLutDelays = p->pPars->pLutLib->pLutDelays[pCut->nLeaves];
+ if ( p->pPars->pLutLib->fVarPinDelays )
+ {
+ // compute the delay using sorted pins
+ If_CutSortInputPins( p, pCut, pPinPerm, pPinDelays );
+ for ( i = 0; i < (int)pCut->nLeaves; i++ )
+ {
+ DelayCur = pPinDelays[pPinPerm[i]] + pLutDelays[i];
+ Delay = IF_MAX( Delay, DelayCur );
+ }
+ }
+ else
+ {
+ If_CutForEachLeaf( p, pCut, pLeaf, i )
+ {
+ DelayCur = If_ObjCutBest(pLeaf)->Delay + pLutDelays[0];
+ Delay = IF_MAX( Delay, DelayCur );
+ }
+ }
+ }
+ else
+ {
+ if ( pCut->fUser )
+ {
+ assert( !p->pPars->fLiftLeaves );
+ If_CutForEachLeaf( p, pCut, pLeaf, i )
+ {
+ DelayCur = If_ObjCutBest(pLeaf)->Delay + (float)pCut->pPerm[i];
+ Delay = IF_MAX( Delay, DelayCur );
+ }
+ }
+ else
+ {
+ if ( p->pPars->fLiftLeaves )
+ {
+ If_CutForEachLeafSeq( p, pCut, pLeaf, Shift, i )
+ {
+ DelayCur = If_ObjCutBest(pLeaf)->Delay - Shift * p->Period;
+ Delay = IF_MAX( Delay, DelayCur );
+ }
+ }
+ else
+ {
+ If_CutForEachLeaf( p, pCut, pLeaf, i )
+ {
+/*
+ if ( pLeaf->IdPio > 2000 )
+ {
+ int x = 0;
+ printf( "-%d %6.3f ", pLeaf->IdPio, If_ObjCutBest(pLeaf)->Delay );
+ }
+*/
+ DelayCur = If_ObjCutBest(pLeaf)->Delay;
+ Delay = IF_MAX( Delay, DelayCur );
+ }
+ }
+ Delay += 1.0;
+ }
+ }
+ return Delay;
+}
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void If_CutPropagateRequired( If_Man_t * p, If_Cut_t * pCut, float ObjRequired )
+{
+ static int pPinPerm[IF_MAX_LUTSIZE];
+ static float pPinDelays[IF_MAX_LUTSIZE];
+ If_Obj_t * pLeaf;
+ float * pLutDelays;
+ float Required;
+ int i;
+ assert( !p->pPars->fLiftLeaves );
+ // compute the pins
+ if ( p->pPars->pLutLib )
+ {
+ pLutDelays = p->pPars->pLutLib->pLutDelays[pCut->nLeaves];
+ if ( p->pPars->pLutLib->fVarPinDelays )
+ {
+ // compute the delay using sorted pins
+ If_CutSortInputPins( p, pCut, pPinPerm, pPinDelays );
+ for ( i = 0; i < (int)pCut->nLeaves; i++ )
+ {
+ Required = ObjRequired - pLutDelays[i];
+ pLeaf = If_ManObj( p, pCut->pLeaves[pPinPerm[i]] );
+ pLeaf->Required = IF_MIN( pLeaf->Required, Required );
+ }
+ }
+ else
+ {
+ Required = ObjRequired - pLutDelays[0];
+ If_CutForEachLeaf( p, pCut, pLeaf, i )
+ pLeaf->Required = IF_MIN( pLeaf->Required, Required );
+ }
+ }
+ else
+ {
+ if ( pCut->fUser )
+ {
+ If_CutForEachLeaf( p, pCut, pLeaf, i )
+ {
+ Required = ObjRequired - (float)pCut->pPerm[i];
+ pLeaf->Required = IF_MIN( pLeaf->Required, Required );
+ }
+ }
+ else
+ {
+ Required = ObjRequired - (float)1.0;
+ If_CutForEachLeaf( p, pCut, pLeaf, i )
+ pLeaf->Required = IF_MIN( pLeaf->Required, Required );
+ }
+ }
+}
+
+/**Function*************************************************************
+
+ Synopsis [Sorts the pins in the decreasing order of delays.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void If_CutSortInputPins( If_Man_t * p, If_Cut_t * pCut, int * pPinPerm, float * pPinDelays )
+{
+ If_Obj_t * pLeaf;
+ int i, j, best_i, temp;
+ // start the trivial permutation and collect pin delays
+ If_CutForEachLeaf( p, pCut, pLeaf, i )
+ {
+ pPinPerm[i] = i;
+ pPinDelays[i] = If_ObjCutBest(pLeaf)->Delay;
+ }
+ // selection sort the pins in the decreasible order of delays
+ // this order will match the increasing order of LUT input pins
+ for ( i = 0; i < (int)pCut->nLeaves-1; i++ )
+ {
+ best_i = i;
+ for ( j = i+1; j < (int)pCut->nLeaves; j++ )
+ if ( pPinDelays[pPinPerm[j]] > pPinDelays[pPinPerm[best_i]] )
+ best_i = j;
+ if ( best_i == i )
+ continue;
+ temp = pPinPerm[i];
+ pPinPerm[i] = pPinPerm[best_i];
+ pPinPerm[best_i] = temp;
+ }
+ // verify
+ assert( pPinPerm[0] < (int)pCut->nLeaves );
+ for ( i = 1; i < (int)pCut->nLeaves; i++ )
+ {
+ assert( pPinPerm[i] < (int)pCut->nLeaves );
+ assert( pPinDelays[pPinPerm[i-1]] >= pPinDelays[pPinPerm[i]] );
+ }
+}
+
+////////////////////////////////////////////////////////////////////////
+/// END OF FILE ///
+////////////////////////////////////////////////////////////////////////
+
+
diff --git a/src/map/if/ifTruth.c b/src/map/if/ifTruth.c
new file mode 100644
index 00000000..f18d8308
--- /dev/null
+++ b/src/map/if/ifTruth.c
@@ -0,0 +1,404 @@
+/**CFile****************************************************************
+
+ FileName [ifTruth.c]
+
+ SystemName [ABC: Logic synthesis and verification system.]
+
+ PackageName [FPGA mapping based on priority cuts.]
+
+ Synopsis [Computation of truth tables of the cuts.]
+
+ Author [Alan Mishchenko]
+
+ Affiliation [UC Berkeley]
+
+ Date [Ver. 1.0. Started - November 21, 2006.]
+
+ Revision [$Id: ifTruth.c,v 1.00 2006/11/21 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "if.h"
+
+////////////////////////////////////////////////////////////////////////
+/// DECLARATIONS ///
+////////////////////////////////////////////////////////////////////////
+
+static int If_CutTruthMinimize( If_Man_t * p, If_Cut_t * pCut );
+
+////////////////////////////////////////////////////////////////////////
+/// FUNCTION DEFINITIONS ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+ Synopsis [Several simple procedures working with truth tables.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+static inline int If_TruthWordNum( int nVars ) { return nVars <= 5 ? 1 : (1 << (nVars - 5)); }
+static inline void If_TruthNot( unsigned * pOut, unsigned * pIn, int nVars )
+{
+ int w;
+ for ( w = If_TruthWordNum(nVars)-1; w >= 0; w-- )
+ pOut[w] = ~pIn[w];
+}
+static inline void If_TruthCopy( unsigned * pOut, unsigned * pIn, int nVars )
+{
+ int w;
+ for ( w = If_TruthWordNum(nVars)-1; w >= 0; w-- )
+ pOut[w] = pIn[w];
+}
+static inline void If_TruthNand( unsigned * pOut, unsigned * pIn0, unsigned * pIn1, int nVars )
+{
+ int w;
+ for ( w = If_TruthWordNum(nVars)-1; w >= 0; w-- )
+ pOut[w] = ~(pIn0[w] & pIn1[w]);
+}
+static inline void If_TruthAnd( unsigned * pOut, unsigned * pIn0, unsigned * pIn1, int nVars )
+{
+ int w;
+ for ( w = If_TruthWordNum(nVars)-1; w >= 0; w-- )
+ pOut[w] = pIn0[w] & pIn1[w];
+}
+
+/**Function*************************************************************
+
+ Synopsis [Swaps two adjacent variables in the truth table.]
+
+ Description [Swaps var number Start and var number Start+1 (0-based numbers).
+ The input truth table is pIn. The output truth table is pOut.]
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void If_TruthSwapAdjacentVars( unsigned * pOut, unsigned * pIn, int nVars, int iVar )
+{
+ static unsigned PMasks[4][3] = {
+ { 0x99999999, 0x22222222, 0x44444444 },
+ { 0xC3C3C3C3, 0x0C0C0C0C, 0x30303030 },
+ { 0xF00FF00F, 0x00F000F0, 0x0F000F00 },
+ { 0xFF0000FF, 0x0000FF00, 0x00FF0000 }
+ };
+ int nWords = If_TruthWordNum( nVars );
+ int i, k, Step, Shift;
+
+ assert( iVar < nVars - 1 );
+ if ( iVar < 4 )
+ {
+ Shift = (1 << iVar);
+ for ( i = 0; i < nWords; i++ )
+ pOut[i] = (pIn[i] & PMasks[iVar][0]) | ((pIn[i] & PMasks[iVar][1]) << Shift) | ((pIn[i] & PMasks[iVar][2]) >> Shift);
+ }
+ else if ( iVar > 4 )
+ {
+ Step = (1 << (iVar - 5));
+ for ( k = 0; k < nWords; k += 4*Step )
+ {
+ for ( i = 0; i < Step; i++ )
+ pOut[i] = pIn[i];
+ for ( i = 0; i < Step; i++ )
+ pOut[Step+i] = pIn[2*Step+i];
+ for ( i = 0; i < Step; i++ )
+ pOut[2*Step+i] = pIn[Step+i];
+ for ( i = 0; i < Step; i++ )
+ pOut[3*Step+i] = pIn[3*Step+i];
+ pIn += 4*Step;
+ pOut += 4*Step;
+ }
+ }
+ else // if ( iVar == 4 )
+ {
+ for ( i = 0; i < nWords; i += 2 )
+ {
+ pOut[i] = (pIn[i] & 0x0000FFFF) | ((pIn[i+1] & 0x0000FFFF) << 16);
+ pOut[i+1] = (pIn[i+1] & 0xFFFF0000) | ((pIn[i] & 0xFFFF0000) >> 16);
+ }
+ }
+}
+
+/**Function*************************************************************
+
+ Synopsis [Expands the truth table according to the phase.]
+
+ Description [The input and output truth tables are in pIn/pOut. The current number
+ of variables is nVars. The total number of variables in nVarsAll. The last argument
+ (Phase) contains shows where the variables should go.]
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void If_TruthStretch( unsigned * pOut, unsigned * pIn, int nVars, int nVarsAll, unsigned Phase )
+{
+ unsigned * pTemp;
+ int i, k, Var = nVars - 1, Counter = 0;
+ for ( i = nVarsAll - 1; i >= 0; i-- )
+ if ( Phase & (1 << i) )
+ {
+ for ( k = Var; k < i; k++ )
+ {
+ If_TruthSwapAdjacentVars( pOut, pIn, nVarsAll, k );
+ pTemp = pIn; pIn = pOut; pOut = pTemp;
+ Counter++;
+ }
+ Var--;
+ }
+ assert( Var == -1 );
+ // swap if it was moved an even number of times
+ if ( !(Counter & 1) )
+ If_TruthCopy( pOut, pIn, nVarsAll );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Shrinks the truth table according to the phase.]
+
+ Description [The input and output truth tables are in pIn/pOut. The current number
+ of variables is nVars. The total number of variables in nVarsAll. The last argument
+ (Phase) contains shows what variables should remain.]
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void If_TruthShrink( unsigned * pOut, unsigned * pIn, int nVars, int nVarsAll, unsigned Phase, int fReturnIn )
+{
+ unsigned * pTemp;
+ int i, k, Var = 0, Counter = 0;
+ for ( i = 0; i < nVarsAll; i++ )
+ if ( Phase & (1 << i) )
+ {
+ for ( k = i-1; k >= Var; k-- )
+ {
+ If_TruthSwapAdjacentVars( pOut, pIn, nVarsAll, k );
+ pTemp = pIn; pIn = pOut; pOut = pTemp;
+ Counter++;
+ }
+ Var++;
+ }
+ assert( Var == nVars );
+ // swap if it was moved an even number of times
+ if ( fReturnIn ^ !(Counter & 1) )
+ If_TruthCopy( pOut, pIn, nVarsAll );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Returns 1 if TT depends on the given variable.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int If_CutTruthVarInSupport( unsigned * pTruth, int nVars, int iVar )
+{
+ int nWords = If_TruthWordNum( nVars );
+ int i, k, Step;
+
+ assert( iVar < nVars );
+ switch ( iVar )
+ {
+ case 0:
+ for ( i = 0; i < nWords; i++ )
+ if ( (pTruth[i] & 0x55555555) != ((pTruth[i] & 0xAAAAAAAA) >> 1) )
+ return 1;
+ return 0;
+ case 1:
+ for ( i = 0; i < nWords; i++ )
+ if ( (pTruth[i] & 0x33333333) != ((pTruth[i] & 0xCCCCCCCC) >> 2) )
+ return 1;
+ return 0;
+ case 2:
+ for ( i = 0; i < nWords; i++ )
+ if ( (pTruth[i] & 0x0F0F0F0F) != ((pTruth[i] & 0xF0F0F0F0) >> 4) )
+ return 1;
+ return 0;
+ case 3:
+ for ( i = 0; i < nWords; i++ )
+ if ( (pTruth[i] & 0x00FF00FF) != ((pTruth[i] & 0xFF00FF00) >> 8) )
+ return 1;
+ return 0;
+ case 4:
+ for ( i = 0; i < nWords; i++ )
+ if ( (pTruth[i] & 0x0000FFFF) != ((pTruth[i] & 0xFFFF0000) >> 16) )
+ return 1;
+ return 0;
+ default:
+ Step = (1 << (iVar - 5));
+ for ( k = 0; k < nWords; k += 2*Step )
+ {
+ for ( i = 0; i < Step; i++ )
+ if ( pTruth[i] != pTruth[Step+i] )
+ return 1;
+ pTruth += 2*Step;
+ }
+ return 0;
+ }
+}
+
+/**Function*************************************************************
+
+ Synopsis [Returns support of the function.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+unsigned If_CutTruthSupport( unsigned * pTruth, int nVars, int * pnSuppSize )
+{
+ int i, Support = 0;
+ int nSuppSize = 0;
+ for ( i = 0; i < nVars; i++ )
+ if ( If_CutTruthVarInSupport( pTruth, nVars, i ) )
+ {
+ Support |= (1 << i);
+ nSuppSize++;
+ }
+ *pnSuppSize = nSuppSize;
+ return Support;
+}
+
+
+/**Function*************************************************************
+
+ Synopsis [Computes the stretching phase of the cut w.r.t. the merged cut.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+static inline unsigned If_CutTruthPhase( If_Cut_t * pCut, If_Cut_t * pCut1 )
+{
+ unsigned uPhase = 0;
+ int i, k;
+ for ( i = k = 0; i < (int)pCut->nLeaves; i++ )
+ {
+ if ( k == (int)pCut1->nLeaves )
+ break;
+ if ( pCut->pLeaves[i] < pCut1->pLeaves[k] )
+ continue;
+ assert( pCut->pLeaves[i] == pCut1->pLeaves[k] );
+ uPhase |= (1 << i);
+ k++;
+ }
+ return uPhase;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Performs truth table computation.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void If_CutComputeTruth( If_Man_t * p, If_Cut_t * pCut, If_Cut_t * pCut0, If_Cut_t * pCut1, int fCompl0, int fCompl1 )
+{
+ extern void If_CutFactorTest( unsigned * pTruth, int nVars );
+
+ // permute the first table
+ if ( fCompl0 ^ pCut0->fCompl )
+ If_TruthNot( p->puTemp[0], If_CutTruth(pCut0), pCut->nLimit );
+ else
+ If_TruthCopy( p->puTemp[0], If_CutTruth(pCut0), pCut->nLimit );
+ If_TruthStretch( p->puTemp[2], p->puTemp[0], pCut0->nLeaves, pCut->nLimit, If_CutTruthPhase(pCut, pCut0) );
+ // permute the second table
+ if ( fCompl1 ^ pCut1->fCompl )
+ If_TruthNot( p->puTemp[1], If_CutTruth(pCut1), pCut->nLimit );
+ else
+ If_TruthCopy( p->puTemp[1], If_CutTruth(pCut1), pCut->nLimit );
+ If_TruthStretch( p->puTemp[3], p->puTemp[1], pCut1->nLeaves, pCut->nLimit, If_CutTruthPhase(pCut, pCut1) );
+ // produce the resulting table
+ assert( pCut->fCompl == 0 );
+ if ( pCut->fCompl )
+ If_TruthNand( If_CutTruth(pCut), p->puTemp[2], p->puTemp[3], pCut->nLimit );
+ else
+ If_TruthAnd( If_CutTruth(pCut), p->puTemp[2], p->puTemp[3], pCut->nLimit );
+
+ // minimize the support of the cut
+ if ( p->pPars->fCutMin )
+ If_CutTruthMinimize( p, pCut );
+
+ // perform
+// If_CutFactorTest( If_CutTruth(pCut), pCut->nLimit );
+// printf( "%d ", If_CutLeaveNum(pCut) - If_CutTruthSupportSize(If_CutTruth(pCut), If_CutLeaveNum(pCut)) );
+}
+
+
+/**Function*************************************************************
+
+ Synopsis [Minimize support of the cut.]
+
+ Description [Returns 1 if the node's support has changed]
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int If_CutTruthMinimize( If_Man_t * p, If_Cut_t * pCut )
+{
+ unsigned uSupport;
+ int nSuppSize, i, k;
+ // compute the support of the cut's function
+ uSupport = If_CutTruthSupport( If_CutTruth(pCut), If_CutLeaveNum(pCut), &nSuppSize );
+ if ( nSuppSize == If_CutLeaveNum(pCut) )
+ return 0;
+
+// TEMPORARY
+ if ( nSuppSize < 2 )
+ {
+ p->nSmallSupp++;
+ return 0;
+ }
+// if ( If_CutLeaveNum(pCut) - nSuppSize > 1 )
+// return 0;
+//printf( "%d %d ", If_CutLeaveNum(pCut), nSuppSize );
+
+ // shrink the truth table
+ If_TruthShrink( p->puTemp[0], If_CutTruth(pCut), nSuppSize, pCut->nLimit, uSupport, 1 );
+ // update leaves and signature
+ pCut->uSign = 0;
+ for ( i = k = 0; i < If_CutLeaveNum(pCut); i++ )
+ {
+ if ( !(uSupport & (1 << i)) )
+ continue;
+ pCut->pLeaves[k++] = pCut->pLeaves[i];
+ pCut->uSign |= If_ObjCutSign( pCut->pLeaves[i] );
+ }
+ assert( k == nSuppSize );
+ pCut->nLeaves = nSuppSize;
+ // verify the result
+// uSupport = If_CutTruthSupport( If_CutTruth(pCut), If_CutLeaveNum(pCut), &nSuppSize );
+// assert( nSuppSize == If_CutLeaveNum(pCut) );
+ return 1;
+}
+
+
+////////////////////////////////////////////////////////////////////////
+/// END OF FILE ///
+////////////////////////////////////////////////////////////////////////
+
+
diff --git a/src/map/if/ifUtil.c b/src/map/if/ifUtil.c
new file mode 100644
index 00000000..2624efd0
--- /dev/null
+++ b/src/map/if/ifUtil.c
@@ -0,0 +1,658 @@
+/**CFile****************************************************************
+
+ FileName [ifUtil.c]
+
+ SystemName [ABC: Logic synthesis and verification system.]
+
+ PackageName [FPGA mapping based on priority cuts.]
+
+ Synopsis [Various utilities.]
+
+ Author [Alan Mishchenko]
+
+ Affiliation [UC Berkeley]
+
+ Date [Ver. 1.0. Started - November 21, 2006.]
+
+ Revision [$Id: ifUtil.c,v 1.00 2006/11/21 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "if.h"
+
+////////////////////////////////////////////////////////////////////////
+/// DECLARATIONS ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+/// FUNCTION DEFINITIONS ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+ Synopsis [Sets all the node copy to NULL.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void If_ManCleanNodeCopy( If_Man_t * p )
+{
+ If_Obj_t * pObj;
+ int i;
+ If_ManForEachObj( p, pObj, i )
+ If_ObjSetCopy( pObj, NULL );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Sets all the cut data to NULL.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void If_ManCleanCutData( If_Man_t * p )
+{
+ If_Obj_t * pObj;
+ int i;
+ If_ManForEachObj( p, pObj, i )
+ If_CutSetData( If_ObjCutBest(pObj), NULL );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Sets all visited marks to 0.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void If_ManCleanMarkV( If_Man_t * p )
+{
+ If_Obj_t * pObj;
+ int i;
+ If_ManForEachObj( p, pObj, i )
+ pObj->fVisit = 0;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Returns the max delay of the POs.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+float If_ManDelayMax( If_Man_t * p, int fSeq )
+{
+ If_Obj_t * pObj;
+ float DelayBest;
+ int i;
+ if ( p->pPars->fLatchPaths && p->pPars->nLatches == 0 )
+ {
+ printf( "Delay optimization of latch path is not performed because there is no latches.\n" );
+ p->pPars->fLatchPaths = 0;
+ }
+ DelayBest = -IF_FLOAT_LARGE;
+ if ( fSeq )
+ {
+ assert( p->pPars->nLatches > 0 );
+ If_ManForEachPo( p, pObj, i )
+ if ( DelayBest < If_ObjArrTime(If_ObjFanin0(pObj)) )
+ DelayBest = If_ObjArrTime(If_ObjFanin0(pObj));
+ }
+ else if ( p->pPars->fLatchPaths )
+ {
+ If_ManForEachLatchInput( p, pObj, i )
+ if ( DelayBest < If_ObjArrTime(If_ObjFanin0(pObj)) )
+ DelayBest = If_ObjArrTime(If_ObjFanin0(pObj));
+ }
+ else
+ {
+ If_ManForEachCo( p, pObj, i )
+ if ( DelayBest < If_ObjArrTime(If_ObjFanin0(pObj)) )
+ DelayBest = If_ObjArrTime(If_ObjFanin0(pObj));
+ }
+ return DelayBest;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Computes the required times of all nodes.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void If_ManComputeRequired( If_Man_t * p )
+{
+ If_Obj_t * pObj;
+ int i, Counter;
+ float reqTime;
+
+ // compute area, clean required times, collect nodes used in the mapping
+// p->AreaGlo = If_ManScanMapping( p );
+ If_ManMarkMapping( p );
+
+ if ( p->pManTim == NULL )
+ {
+ // consider the case when the required times are given
+ if ( p->pPars->pTimesReq )
+ {
+ assert( !p->pPars->fAreaOnly );
+ // make sure that the required time hold
+ Counter = 0;
+ If_ManForEachCo( p, pObj, i )
+ {
+ if ( If_ObjArrTime(If_ObjFanin0(pObj)) > p->pPars->pTimesReq[i] + p->fEpsilon )
+ {
+ Counter++;
+ // printf( "Required times are violated for output %d (arr = %d; req = %d).\n",
+ // i, (int)If_ObjArrTime(If_ObjFanin0(pObj)), (int)p->pPars->pTimesReq[i] );
+ }
+ If_ObjFanin0(pObj)->Required = p->pPars->pTimesReq[i];
+ }
+ if ( Counter )
+ printf( "Required times are violated for %d outputs.\n", Counter );
+ }
+ else
+ {
+ // get the global required times
+ p->RequiredGlo = If_ManDelayMax( p, 0 );
+ // update the required times according to the target
+ if ( p->pPars->DelayTarget != -1 )
+ {
+ if ( p->RequiredGlo > p->pPars->DelayTarget + p->fEpsilon )
+ {
+ if ( p->fNextRound == 0 )
+ {
+ p->fNextRound = 1;
+ printf( "Cannot meet the target required times (%4.2f). Mapping continues anyway.\n", p->pPars->DelayTarget );
+ }
+ }
+ else if ( p->RequiredGlo < p->pPars->DelayTarget - p->fEpsilon )
+ {
+ if ( p->fNextRound == 0 )
+ {
+ p->fNextRound = 1;
+ printf( "Relaxing the required times from (%4.2f) to the target (%4.2f).\n", p->RequiredGlo, p->pPars->DelayTarget );
+ }
+ p->RequiredGlo = p->pPars->DelayTarget;
+ }
+ }
+ // do not propagate required times if area minimization is requested
+ if ( p->pPars->fAreaOnly )
+ return;
+ // set the required times for the POs
+ if ( p->pPars->fLatchPaths )
+ {
+ If_ManForEachLatchInput( p, pObj, i )
+ If_ObjFanin0(pObj)->Required = p->RequiredGlo;
+ }
+ else
+ {
+ If_ManForEachCo( p, pObj, i )
+ If_ObjFanin0(pObj)->Required = p->RequiredGlo;
+ }
+ }
+ // go through the nodes in the reverse topological order
+ // Vec_PtrForEachEntry( p->vMapped, pObj, i )
+ // If_CutPropagateRequired( p, If_ObjCutBest(pObj), pObj->Required );
+ If_ManForEachObjReverse( p, pObj, i )
+ {
+ if ( pObj->nRefs == 0 )
+ continue;
+ If_CutPropagateRequired( p, If_ObjCutBest(pObj), pObj->Required );
+ }
+ }
+ else
+ {
+ // get the global required times
+ p->RequiredGlo = If_ManDelayMax( p, 0 );
+ // do not propagate required times if area minimization is requested
+ if ( p->pPars->fAreaOnly )
+ return;
+ // set the required times for the POs
+ Tim_ManIncrementTravId( p->pManTim );
+ if ( p->pPars->fLatchPaths )
+ {
+ assert( 0 );
+ If_ManForEachPo( p, pObj, i )
+ Tim_ManSetPoRequired( p->pManTim, pObj->IdPio, IF_FLOAT_LARGE );
+ If_ManForEachLatchInput( p, pObj, i )
+ Tim_ManSetPoRequired( p->pManTim, pObj->IdPio, p->RequiredGlo );
+ }
+ else
+ {
+ Tim_ManSetPoRequiredAll( p->pManTim, p->RequiredGlo );
+// If_ManForEachCo( p, pObj, i )
+// Tim_ManSetPoRequired( p->pManTim, pObj->IdPio, p->RequiredGlo );
+ }
+ // go through the nodes in the reverse topological order
+ If_ManForEachObjReverse( p, pObj, i )
+ {
+ if ( If_ObjIsAnd(pObj) )
+ {
+ if ( pObj->nRefs == 0 )
+ continue;
+ If_CutPropagateRequired( p, If_ObjCutBest(pObj), pObj->Required );
+ }
+ else if ( If_ObjIsCi(pObj) )
+ {
+ reqTime = pObj->Required;
+ Tim_ManSetPiRequired( p->pManTim, pObj->IdPio, reqTime );
+ }
+ else if ( If_ObjIsCo(pObj) )
+ {
+ reqTime = Tim_ManGetPoRequired( p->pManTim, pObj->IdPio );
+ If_ObjFanin0(pObj)->Required = IF_MIN( reqTime, If_ObjFanin0(pObj)->Required );
+ }
+ else if ( If_ObjIsConst1(pObj) )
+ {
+ }
+ else // add the node to the mapper
+ assert( 0 );
+ }
+ }
+}
+
+#if 0
+
+/**Function*************************************************************
+
+ Synopsis [Computes area, references, and nodes used in the mapping.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+float If_ManScanMapping_rec( If_Man_t * p, If_Obj_t * pObj, If_Obj_t ** ppStore )
+{
+ If_Obj_t * pLeaf;
+ If_Cut_t * pCutBest;
+ float aArea;
+ int i;
+ if ( pObj->nRefs++ || If_ObjIsCi(pObj) || If_ObjIsConst1(pObj) )
+ return 0.0;
+ // store the node in the structure by level
+ assert( If_ObjIsAnd(pObj) );
+ pObj->pCopy = (char *)ppStore[pObj->Level];
+ ppStore[pObj->Level] = pObj;
+ // visit the transitive fanin of the selected cut
+ pCutBest = If_ObjCutBest(pObj);
+ p->nNets += pCutBest->nLeaves;
+ aArea = If_CutLutArea( p, pCutBest );
+ If_CutForEachLeaf( p, pCutBest, pLeaf, i )
+ aArea += If_ManScanMapping_rec( p, pLeaf, ppStore );
+ return aArea;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Computes area, references, and nodes used in the mapping.]
+
+ Description [Collects the nodes in reverse topological order in array
+ p->vMapping.]
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+float If_ManScanMapping( If_Man_t * p )
+{
+ If_Obj_t * pObj, ** ppStore;
+ float aArea;
+ int i;
+ assert( !p->pPars->fLiftLeaves );
+ // clean all references
+ p->nNets = 0;
+ If_ManForEachObj( p, pObj, i )
+ {
+ pObj->Required = IF_FLOAT_LARGE;
+ pObj->nVisits = pObj->nVisitsCopy;
+ pObj->nRefs = 0;
+ }
+ // allocate place to store the nodes
+ ppStore = ALLOC( If_Obj_t *, p->nLevelMax + 1 );
+ memset( ppStore, 0, sizeof(If_Obj_t *) * (p->nLevelMax + 1) );
+ // collect nodes reachable from POs in the DFS order through the best cuts
+ aArea = 0;
+ If_ManForEachCo( p, pObj, i )
+ aArea += If_ManScanMapping_rec( p, If_ObjFanin0(pObj), ppStore );
+ // reconnect the nodes in reverse topological order
+ Vec_PtrClear( p->vMapped );
+ for ( i = p->nLevelMax; i >= 0; i-- )
+ for ( pObj = ppStore[i]; pObj; pObj = pObj->pCopy )
+ Vec_PtrPush( p->vMapped, pObj );
+ free( ppStore );
+ return aArea;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Computes area, references, and nodes used in the mapping.]
+
+ Description [Collects the nodes in reverse topological order in array
+ p->vMapping.]
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+float If_ManScanMappingDirect( If_Man_t * p )
+{
+ If_Obj_t * pObj, ** ppStore;
+ float aArea;
+ int i;
+ assert( !p->pPars->fLiftLeaves );
+ // clean all references
+ If_ManForEachObj( p, pObj, i )
+ {
+ pObj->Required = IF_FLOAT_LARGE;
+ pObj->nVisits = pObj->nVisitsCopy;
+ pObj->nRefs = 0;
+ }
+ // allocate place to store the nodes
+ ppStore = ALLOC( If_Obj_t *, p->nLevelMax + 1 );
+ memset( ppStore, 0, sizeof(If_Obj_t *) * (p->nLevelMax + 1) );
+ // collect nodes reachable from POs in the DFS order through the best cuts
+ aArea = 0;
+ If_ManForEachCo( p, pObj, i )
+ aArea += If_ManScanMapping_rec( p, If_ObjFanin0(pObj), ppStore );
+ // reconnect the nodes in reverse topological order
+ Vec_PtrClear( p->vMapped );
+// for ( i = p->nLevelMax; i >= 0; i-- )
+ for ( i = 0; i <= p->nLevelMax; i++ )
+ for ( pObj = ppStore[i]; pObj; pObj = pObj->pCopy )
+ Vec_PtrPush( p->vMapped, pObj );
+ free( ppStore );
+ return aArea;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Computes area, references, and nodes used in the mapping.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+float If_ManScanMappingSeq_rec( If_Man_t * p, If_Obj_t * pObj, Vec_Ptr_t * vMapped )
+{
+ If_Obj_t * pLeaf;
+ If_Cut_t * pCutBest;
+ float aArea;
+ int i, Shift;
+ // treat latches transparently
+ if ( If_ObjIsLatch(pObj) )
+ return If_ManScanMappingSeq_rec( p, If_ObjFanin0(pObj), vMapped );
+ // consider trivial cases
+ if ( pObj->nRefs++ || If_ObjIsPi(pObj) || If_ObjIsConst1(pObj) )
+ return 0.0;
+ // store the node in the structure by level
+ assert( If_ObjIsAnd(pObj) );
+ // visit the transitive fanin of the selected cut
+ pCutBest = If_ObjCutBest(pObj);
+ aArea = If_ObjIsAnd(pObj)? If_CutLutArea(p, pCutBest) : (float)0.0;
+ If_CutForEachLeafSeq( p, pCutBest, pLeaf, Shift, i )
+ aArea += If_ManScanMappingSeq_rec( p, pLeaf, vMapped );
+ // add the node
+ Vec_PtrPush( vMapped, pObj );
+ return aArea;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Computes area, references, and nodes used in the mapping.]
+
+ Description [Collects the nodes in reverse topological order in array
+ p->vMapping.]
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+float If_ManScanMappingSeq( If_Man_t * p )
+{
+ If_Obj_t * pObj;
+ float aArea;
+ int i;
+ assert( p->pPars->fLiftLeaves );
+ // clean all references
+ If_ManForEachObj( p, pObj, i )
+ pObj->nRefs = 0;
+ // collect nodes reachable from POs in the DFS order through the best cuts
+ aArea = 0;
+ Vec_PtrClear( p->vMapped );
+ If_ManForEachPo( p, pObj, i )
+ aArea += If_ManScanMappingSeq_rec( p, If_ObjFanin0(pObj), p->vMapped );
+ return aArea;
+}
+
+#endif
+
+/**Function*************************************************************
+
+ Synopsis [Computes area, references, and nodes used in the mapping.]
+
+ Description [Collects the nodes in reverse topological order in array
+ p->vMapping.]
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void If_ManResetOriginalRefs( If_Man_t * p )
+{
+ If_Obj_t * pObj;
+ int i;
+ If_ManForEachObj( p, pObj, i )
+ pObj->nRefs = 0;
+ If_ManForEachObj( p, pObj, i )
+ {
+ if ( If_ObjIsAnd(pObj) )
+ {
+ pObj->pFanin0->nRefs++;
+ pObj->pFanin1->nRefs++;
+ }
+ else if ( If_ObjIsCo(pObj) )
+ pObj->pFanin0->nRefs++;
+ }
+}
+
+/**Function*************************************************************
+
+ Synopsis [Computes cross-cut of the circuit.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int If_ManCrossCut( If_Man_t * p )
+{
+ If_Obj_t * pObj, * pFanin;
+ int i, nCutSize = 0, nCutSizeMax = 0;
+ If_ManForEachObj( p, pObj, i )
+ {
+ if ( !If_ObjIsAnd(pObj) )
+ continue;
+ // consider the node
+ if ( nCutSizeMax < ++nCutSize )
+ nCutSizeMax = nCutSize;
+ if ( pObj->nVisits == 0 )
+ nCutSize--;
+ // consider the fanins
+ pFanin = If_ObjFanin0(pObj);
+ if ( !If_ObjIsCi(pFanin) && --pFanin->nVisits == 0 )
+ nCutSize--;
+ pFanin = If_ObjFanin1(pObj);
+ if ( !If_ObjIsCi(pFanin) && --pFanin->nVisits == 0 )
+ nCutSize--;
+ // consider the choice class
+ if ( pObj->fRepr )
+ for ( pFanin = pObj; pFanin; pFanin = pFanin->pEquiv )
+ if ( !If_ObjIsCi(pFanin) && --pFanin->nVisits == 0 )
+ nCutSize--;
+ }
+ If_ManForEachObj( p, pObj, i )
+ {
+ assert( If_ObjIsCi(pObj) || pObj->fVisit == 0 );
+ pObj->nVisits = pObj->nVisitsCopy;
+ }
+ assert( nCutSize == 0 );
+// printf( "Max cross cut size = %6d.\n", nCutSizeMax );
+ return nCutSizeMax;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Computes the reverse topological order of nodes.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Vec_Ptr_t * If_ManReverseOrder( If_Man_t * p )
+{
+ Vec_Ptr_t * vOrder;
+ If_Obj_t * pObj, ** ppStore;
+ int i;
+ // allocate place to store the nodes
+ ppStore = ALLOC( If_Obj_t *, p->nLevelMax + 1 );
+ memset( ppStore, 0, sizeof(If_Obj_t *) * (p->nLevelMax + 1) );
+ // add the nodes
+ If_ManForEachObj( p, pObj, i )
+ {
+ assert( pObj->Level >= 0 && pObj->Level <= (unsigned)p->nLevelMax );
+ pObj->pCopy = (char *)ppStore[pObj->Level];
+ ppStore[pObj->Level] = pObj;
+ }
+ vOrder = Vec_PtrAlloc( If_ManObjNum(p) );
+ for ( i = p->nLevelMax; i >= 0; i-- )
+ for ( pObj = ppStore[i]; pObj; pObj = pObj->pCopy )
+ Vec_PtrPush( vOrder, pObj );
+ free( ppStore );
+ // print the order
+// Vec_PtrForEachEntry( vOrder, pObj, i )
+// printf( "Obj %2d Type %d Level = %d\n", pObj->Id, pObj->Type, pObj->Level );
+ return vOrder;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Computes area, references, and nodes used in the mapping.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+float If_ManMarkMapping_rec( If_Man_t * p, If_Obj_t * pObj )
+{
+ If_Obj_t * pLeaf;
+ If_Cut_t * pCutBest;
+ float aArea;
+ int i;
+ if ( pObj->nRefs++ || If_ObjIsCi(pObj) || If_ObjIsConst1(pObj) )
+ return 0.0;
+ // store the node in the structure by level
+ assert( If_ObjIsAnd(pObj) );
+ // visit the transitive fanin of the selected cut
+ pCutBest = If_ObjCutBest(pObj);
+ p->nNets += pCutBest->nLeaves;
+ aArea = If_CutLutArea( p, pCutBest );
+ If_CutForEachLeaf( p, pCutBest, pLeaf, i )
+ aArea += If_ManMarkMapping_rec( p, pLeaf );
+ return aArea;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Computes area, references, and nodes used in the mapping.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void If_ManMarkMapping( If_Man_t * p )
+{
+ If_Obj_t * pObj;
+ int i;
+ If_ManForEachObj( p, pObj, i )
+ {
+ pObj->Required = IF_FLOAT_LARGE;
+ pObj->nVisits = pObj->nVisitsCopy;
+ pObj->nRefs = 0;
+ }
+ p->nNets = 0;
+ p->AreaGlo = 0.0;
+ If_ManForEachCo( p, pObj, i )
+ p->AreaGlo += If_ManMarkMapping_rec( p, If_ObjFanin0(pObj) );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Collects nodes used in the mapping in the topological order.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Vec_Ptr_t * If_ManCollectMappingDirect( If_Man_t * p )
+{
+ Vec_Ptr_t * vOrder;
+ If_Obj_t * pObj;
+ int i;
+ If_ManMarkMapping( p );
+ vOrder = Vec_PtrAlloc( If_ManObjNum(p) );
+ If_ManForEachObj( p, pObj, i )
+ if ( If_ObjIsAnd(pObj) && pObj->nRefs )
+ Vec_PtrPush( vOrder, pObj );
+ return vOrder;
+}
+
+////////////////////////////////////////////////////////////////////////
+/// END OF FILE ///
+////////////////////////////////////////////////////////////////////////
+
+
diff --git a/src/map/if/if_.c b/src/map/if/if_.c
new file mode 100644
index 00000000..d2960077
--- /dev/null
+++ b/src/map/if/if_.c
@@ -0,0 +1,47 @@
+/**CFile****************************************************************
+
+ FileName [if_.c]
+
+ SystemName [ABC: Logic synthesis and verification system.]
+
+ PackageName [FPGA mapping based on priority cuts.]
+
+ Synopsis []
+
+ Author [Alan Mishchenko]
+
+ Affiliation [UC Berkeley]
+
+ Date [Ver. 1.0. Started - November 21, 2006.]
+
+ Revision [$Id: if_.c,v 1.00 2006/11/21 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "if.h"
+
+////////////////////////////////////////////////////////////////////////
+/// DECLARATIONS ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+/// FUNCTION DEFINITIONS ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+
+////////////////////////////////////////////////////////////////////////
+/// END OF FILE ///
+////////////////////////////////////////////////////////////////////////
+
+
diff --git a/src/map/if/module.make b/src/map/if/module.make
new file mode 100644
index 00000000..c14428da
--- /dev/null
+++ b/src/map/if/module.make
@@ -0,0 +1,8 @@
+SRC += src/map/if/ifCore.c \
+ src/map/if/ifCut.c \
+ src/map/if/ifMan.c \
+ src/map/if/ifMap.c \
+ src/map/if/ifReduce.c \
+ src/map/if/ifTime.c \
+ src/map/if/ifTruth.c \
+ src/map/if/ifUtil.c
diff --git a/src/map/mapper/mapper.c b/src/map/mapper/mapper.c
index e59fa4a3..b18b68c0 100644
--- a/src/map/mapper/mapper.c
+++ b/src/map/mapper/mapper.c
@@ -28,7 +28,7 @@
static int Map_CommandReadLibrary ( Abc_Frame_t * pAbc, int argc, char **argv );
////////////////////////////////////////////////////////////////////////
-/// FUNCTION DEFITIONS ///
+/// FUNCTION DEFINITIONS ///
////////////////////////////////////////////////////////////////////////
/**Function*************************************************************
@@ -61,7 +61,7 @@ void Map_Init( Abc_Frame_t * pAbc )
void Map_End()
{
// Map_SuperLibFree( s_pSuperLib );
- Map_SuperLibFree( Abc_FrameReadLibSuper(Abc_FrameGetGlobalFrame()) );
+ Map_SuperLibFree( Abc_FrameReadLibSuper() );
}
@@ -87,7 +87,7 @@ int Map_CommandReadLibrary( Abc_Frame_t * pAbc, int argc, char **argv )
int fAlgorithm;
int c;
- pNet = Abc_FrameReadNet(pAbc);
+ pNet = Abc_FrameReadNtk(pAbc);
pOut = Abc_FrameReadOut(pAbc);
pErr = Abc_FrameReadErr(pAbc);
@@ -95,16 +95,16 @@ int Map_CommandReadLibrary( Abc_Frame_t * pAbc, int argc, char **argv )
fVerbose = 1;
fAlgorithm = 1;
ExcludeFile = 0;
- util_getopt_reset();
- while ( (c = util_getopt(argc, argv, "eovh")) != EOF )
+ Extra_UtilGetoptReset();
+ while ( (c = Extra_UtilGetopt(argc, argv, "eovh")) != EOF )
{
switch (c)
{
case 'e':
- ExcludeFile = argv[util_optind];
+ ExcludeFile = argv[globalUtilOptind];
if ( ExcludeFile == 0 )
goto usage;
- util_optind++;
+ globalUtilOptind++;
break;
case 'o':
fAlgorithm ^= 1;
@@ -121,15 +121,15 @@ int Map_CommandReadLibrary( Abc_Frame_t * pAbc, int argc, char **argv )
}
- if ( argc != util_optind + 1 )
+ if ( argc != globalUtilOptind + 1 )
{
goto usage;
}
// get the input file name
- FileName = argv[util_optind];
-// if ( (pFile = Io_FileOpen( FileName, "open_path", "r" )) == NULL )
- if ( (pFile = fopen( FileName, "r" )) == NULL )
+ FileName = argv[globalUtilOptind];
+ if ( (pFile = Io_FileOpen( FileName, "open_path", "r", 0 )) == NULL )
+// if ( (pFile = fopen( FileName, "r" )) == NULL )
{
fprintf( pErr, "Cannot open input file \"%s\". ", FileName );
if ( FileName = Extra_FileGetSimilarName( FileName, ".genlib", ".lib", ".gen", ".g", NULL ) )
diff --git a/src/map/mapper/mapper.h b/src/map/mapper/mapper.h
index c3f1ce81..8eade761 100644
--- a/src/map/mapper/mapper.h
+++ b/src/map/mapper/mapper.h
@@ -19,6 +19,10 @@
#ifndef __MAPPER_H__
#define __MAPPER_H__
+#ifdef __cplusplus
+extern "C" {
+#endif
+
////////////////////////////////////////////////////////////////////////
/// INCLUDES ///
////////////////////////////////////////////////////////////////////////
@@ -56,16 +60,16 @@ struct Map_TimeStruct_t_
////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////
-/// MACRO DEFITIONS ///
+/// MACRO DEFINITIONS ///
////////////////////////////////////////////////////////////////////////
-#define Map_IsComplement(p) (((int)((long) (p) & 01)))
-#define Map_Regular(p) ((Map_Node_t *)((unsigned)(p) & ~01))
-#define Map_Not(p) ((Map_Node_t *)((long)(p) ^ 01))
-#define Map_NotCond(p,c) ((Map_Node_t *)((long)(p) ^ (c)))
+#define Map_IsComplement(p) (((int)((unsigned long) (p) & 01)))
+#define Map_Regular(p) ((Map_Node_t *)((unsigned long)(p) & ~01))
+#define Map_Not(p) ((Map_Node_t *)((unsigned long)(p) ^ 01))
+#define Map_NotCond(p,c) ((Map_Node_t *)((unsigned long)(p) ^ (c)))
////////////////////////////////////////////////////////////////////////
-/// FUNCTION DEFITIONS ///
+/// FUNCTION DEFINITIONS ///
////////////////////////////////////////////////////////////////////////
/*=== mapperCreate.c =============================================================*/
@@ -180,7 +184,12 @@ extern void Map_ManCleanData( Map_Man_t * p );
extern void Map_MappingSetupTruthTables( unsigned uTruths[][2] );
extern void Map_MappingSetupTruthTablesLarge( unsigned uTruths[][32] );
+#ifdef __cplusplus
+}
+#endif
+
+#endif
+
////////////////////////////////////////////////////////////////////////
/// END OF FILE ///
////////////////////////////////////////////////////////////////////////
-#endif
diff --git a/src/map/mapper/mapperCanon.c b/src/map/mapper/mapperCanon.c
index 2b0f261f..203c9142 100644
--- a/src/map/mapper/mapperCanon.c
+++ b/src/map/mapper/mapperCanon.c
@@ -26,7 +26,7 @@ static unsigned Map_CanonComputePhase( unsigned uTruths[][2], int nVars, unsigne
static void Map_CanonComputePhase6( unsigned uTruths[][2], int nVars, unsigned uTruth[], unsigned uPhase, unsigned uTruthRes[] );
////////////////////////////////////////////////////////////////////////
-/// FUNCTION DEFITIONS ///
+/// FUNCTION DEFINITIONS ///
////////////////////////////////////////////////////////////////////////
/**Function*************************************************************
@@ -218,7 +218,7 @@ int Map_CanonComputeFast( Map_Man_t * p, int nVarsMax, int nVarsReal, unsigned u
if ( uCanon0 >= uCanon1 ) // using nCanon1 as the main one
{
assert( p->pCounters[uTruth1] > 0 );
- uCanonBest = 0xFFFF;
+ uCanonBest = 0xFFFFFFFF;
for ( i = 0; i < p->pCounters[uTruth1]; i++ )
{
uCanon0 = Extra_TruthPolarize( uTruth0, p->uPhases[uTruth1][i], 4 );
@@ -226,6 +226,7 @@ int Map_CanonComputeFast( Map_Man_t * p, int nVarsMax, int nVarsReal, unsigned u
{
uCanonBest = uCanon0;
uPhaseBest = p->uPhases[uTruth1][i];
+ assert( uPhaseBest < 16 );
}
}
uTruthRes[0] = (uCanon1 << 16) | uCanonBest;
@@ -236,7 +237,7 @@ int Map_CanonComputeFast( Map_Man_t * p, int nVarsMax, int nVarsReal, unsigned u
else if ( uCanon0 < uCanon1 )
{
assert( p->pCounters[uTruth0] > 0 );
- uCanonBest = 0xFFFF;
+ uCanonBest = 0xFFFFFFFF;
for ( i = 0; i < p->pCounters[uTruth0]; i++ )
{
uCanon1 = Extra_TruthPolarize( uTruth1, p->uPhases[uTruth0][i], 4 );
@@ -244,6 +245,7 @@ int Map_CanonComputeFast( Map_Man_t * p, int nVarsMax, int nVarsReal, unsigned u
{
uCanonBest = uCanon1;
uPhaseBest = p->uPhases[uTruth0][i];
+ assert( uPhaseBest < 16 );
}
}
uTruthRes[0] = (uCanon0 << 16) | uCanonBest;
diff --git a/src/map/mapper/mapperCore.c b/src/map/mapper/mapperCore.c
index 629ba59d..5d4854e6 100644
--- a/src/map/mapper/mapperCore.c
+++ b/src/map/mapper/mapperCore.c
@@ -24,7 +24,7 @@
////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////
-/// FUNCTION DEFITIONS ///
+/// FUNCTION DEFINITIONS ///
////////////////////////////////////////////////////////////////////////
/**Function*************************************************************
@@ -46,7 +46,7 @@
***********************************************************************/
int Map_Mapping( Map_Man_t * p )
{
- int fShowSwitching = 0;
+ int fShowSwitching = 1;
int fUseAreaFlow = 1;
int fUseExactArea = !p->fSwitching;
int fUseExactAreaWithPhase = !p->fSwitching;
@@ -93,7 +93,11 @@ PRT( "Time", p->timeMatch );
//////////////////////////////////////////////////////////////////////
if ( !p->fAreaRecovery )
+ {
+ if ( p->fVerbose )
+ Map_MappingPrintOutputArrivals( p );
return 1;
+ }
//////////////////////////////////////////////////////////////////////
// perform area recovery using area flow
diff --git a/src/map/mapper/mapperCreate.c b/src/map/mapper/mapperCreate.c
index 31fbf0ea..157d467b 100644
--- a/src/map/mapper/mapperCreate.c
+++ b/src/map/mapper/mapperCreate.c
@@ -30,7 +30,7 @@ static Map_Node_t * Map_TableLookup( Map_Man_t * p, Map_Node_t * p1, Map_Node
static inline unsigned Map_HashKey2( Map_Node_t * p0, Map_Node_t * p1, int TableSize ) { return ((unsigned)(p0) + (unsigned)(p1) * 12582917) % TableSize; }
////////////////////////////////////////////////////////////////////////
-/// FUNCTION DEFITIONS ///
+/// FUNCTION DEFINITIONS ///
////////////////////////////////////////////////////////////////////////
/**Function*************************************************************
@@ -183,7 +183,7 @@ Map_Man_t * Map_ManCreate( int nInputs, int nOutputs, int fVerbose )
int i;
// derive the supergate library
- if ( Abc_FrameReadLibSuper(Abc_FrameGetGlobalFrame()) == NULL )
+ if ( Abc_FrameReadLibSuper() == NULL )
{
printf( "The supergate library is not specified. Use \"read_library\" or \"read_super\".\n" );
return NULL;
@@ -192,7 +192,7 @@ Map_Man_t * Map_ManCreate( int nInputs, int nOutputs, int fVerbose )
// start the manager
p = ALLOC( Map_Man_t, 1 );
memset( p, 0, sizeof(Map_Man_t) );
- p->pSuperLib = Abc_FrameReadLibSuper(Abc_FrameGetGlobalFrame());
+ p->pSuperLib = Abc_FrameReadLibSuper();
p->nVarsMax = p->pSuperLib->nVarsMax;
p->fVerbose = fVerbose;
p->fEpsilon = (float)0.001;
@@ -261,8 +261,8 @@ void Map_ManFree( Map_Man_t * p )
if ( p->uCanons ) free( p->uCanons );
if ( p->uPhases ) free( p->uPhases );
if ( p->pCounters ) free( p->pCounters );
- Extra_MmFixedStop( p->mmNodes, 0 );
- Extra_MmFixedStop( p->mmCuts, 0 );
+ Extra_MmFixedStop( p->mmNodes );
+ Extra_MmFixedStop( p->mmCuts );
FREE( p->pInputArrivals );
FREE( p->pInputs );
FREE( p->pOutputs );
@@ -314,7 +314,7 @@ void Map_ManPrintTimeStats( Map_Man_t * p )
void Map_ManPrintStatsToFile( char * pName, float Area, float Delay, int Time )
{
FILE * pTable;
- pTable = fopen( "stats.txt", "a+" );
+ pTable = fopen( "map_stats.txt", "a+" );
fprintf( pTable, "%s ", pName );
fprintf( pTable, "%4.2f ", Area );
fprintf( pTable, "%4.2f ", Delay );
diff --git a/src/map/mapper/mapperCut.c b/src/map/mapper/mapperCut.c
index b5ce4018..b05e9d0c 100644
--- a/src/map/mapper/mapperCut.c
+++ b/src/map/mapper/mapperCut.c
@@ -80,7 +80,7 @@ static unsigned Map_CutComputeTruth( Map_Man_t * p, Map_Cut_t * pCut, Ma
pCut2 = pCut? pCut->pNext: NULL )
////////////////////////////////////////////////////////////////////////
-/// FUNCTION DEFITIONS ///
+/// FUNCTION DEFINITIONS ///
////////////////////////////////////////////////////////////////////////
/**Function*************************************************************
@@ -149,7 +149,7 @@ void Map_MappingCuts( Map_Man_t * p )
if ( p->fVerbose )
{
nCuts = Map_MappingCountAllCuts(p);
- printf( "Nodes = %6d. Total %d-feasible cuts = %d. Per node = %.1f. ",
+ printf( "Nodes = %6d. Total %d-feasible cuts = %10d. Per node = %.1f. ",
p->nNodes, p->nVarsMax, nCuts, ((float)nCuts)/p->nNodes );
PRT( "Time", clock() - clk );
}
@@ -208,7 +208,7 @@ Map_Cut_t * Map_CutCompute( Map_Man_t * p, Map_CutTable_t * pTable, Map_Node_t *
// set at the node
pNode->pCuts = pCut;
// remove the dominated cuts
-// Map_CutFilter( p, pNode );
+ Map_CutFilter( p, pNode );
// set the phase correctly
if ( pNode->pRepr && Map_NodeComparePhase(pNode, pNode->pRepr) )
{
@@ -612,7 +612,8 @@ int Map_CutMergeTwo( Map_Cut_t * pCut1, Map_Cut_t * pCut2, Map_Node_t * ppNodes[
{
min = i;
for ( k = i+1; k < nTotal; k++ )
- if ( ppNodes[k] < ppNodes[min] )
+// if ( ppNodes[k] < ppNodes[min] ) // reported bug fix (non-determinism!)
+ if ( ppNodes[k]->Num < ppNodes[min]->Num )
min = k;
pNodeTemp = ppNodes[i];
ppNodes[i] = ppNodes[min];
diff --git a/src/map/mapper/mapperCutUtils.c b/src/map/mapper/mapperCutUtils.c
index 9f572e75..4450cb04 100644
--- a/src/map/mapper/mapperCutUtils.c
+++ b/src/map/mapper/mapperCutUtils.c
@@ -23,7 +23,7 @@
////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////
-/// FUNCTION DEFITIONS ///
+/// FUNCTION DEFINITIONS ///
////////////////////////////////////////////////////////////////////////
/**Function*************************************************************
diff --git a/src/map/mapper/mapperFanout.c b/src/map/mapper/mapperFanout.c
index aca29918..63cdbd2a 100644
--- a/src/map/mapper/mapperFanout.c
+++ b/src/map/mapper/mapperFanout.c
@@ -25,7 +25,7 @@
////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////
-/// FUNCTION DEFITIONS ///
+/// FUNCTION DEFINITIONS ///
////////////////////////////////////////////////////////////////////////
/**Function*************************************************************
diff --git a/src/map/mapper/mapperGENERIC.c b/src/map/mapper/mapperGENERIC.c
index 4df5ee51..823eb4f2 100644
--- a/src/map/mapper/mapperGENERIC.c
+++ b/src/map/mapper/mapperGENERIC.c
@@ -23,7 +23,7 @@
////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////
-/// FUNCTION DEFITIONS ///
+/// FUNCTION DEFINITIONS ///
////////////////////////////////////////////////////////////////////////
/**Function*************************************************************
diff --git a/src/map/mapper/mapperInt.h b/src/map/mapper/mapperInt.h
index 0acca56c..37cca3d3 100644
--- a/src/map/mapper/mapperInt.h
+++ b/src/map/mapper/mapperInt.h
@@ -41,7 +41,7 @@
//#define MAP_ALLOCATE_FANOUT 1
////////////////////////////////////////////////////////////////////////
-/// MACRO DEFITIONS ///
+/// MACRO DEFINITIONS ///
////////////////////////////////////////////////////////////////////////
// the bit masks
@@ -61,10 +61,10 @@
#define MAP_RANDOM_UNSIGNED ((((unsigned)rand()) << 24) ^ (((unsigned)rand()) << 12) ^ ((unsigned)rand()))
// internal macros to work with cuts
-#define Map_CutIsComplement(p) (((int)((long) (p) & 01)))
-#define Map_CutRegular(p) ((Map_Cut_t *)((unsigned)(p) & ~01))
-#define Map_CutNot(p) ((Map_Cut_t *)((long)(p) ^ 01))
-#define Map_CutNotCond(p,c) ((Map_Cut_t *)((long)(p) ^ (c)))
+#define Map_CutIsComplement(p) (((int)((unsigned long) (p) & 01)))
+#define Map_CutRegular(p) ((Map_Cut_t *)((unsigned long)(p) & ~01))
+#define Map_CutNot(p) ((Map_Cut_t *)((unsigned long)(p) ^ 01))
+#define Map_CutNotCond(p,c) ((Map_Cut_t *)((unsigned long)(p) ^ (c)))
// internal macros for referencing of nodes
#define Map_NodeReadRef(p) ((Map_Regular(p))->nRefs)
@@ -347,7 +347,7 @@ struct Map_HashEntryStruct_t_
////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////
-/// FUNCTION DEFITIONS ///
+/// FUNCTION DEFINITIONS ///
////////////////////////////////////////////////////////////////////////
/*=== mapperCanon.c =============================================================*/
@@ -470,8 +470,8 @@ extern void Map_NodeVecWriteEntry( Map_NodeVec_t * p, int i, Map_No
extern Map_Node_t * Map_NodeVecReadEntry( Map_NodeVec_t * p, int i );
extern void Map_NodeVecSortByLevel( Map_NodeVec_t * p );
+#endif
+
////////////////////////////////////////////////////////////////////////
/// END OF FILE ///
////////////////////////////////////////////////////////////////////////
-
-#endif
diff --git a/src/map/mapper/mapperLib.c b/src/map/mapper/mapperLib.c
index a9e9e29b..d916487e 100644
--- a/src/map/mapper/mapperLib.c
+++ b/src/map/mapper/mapperLib.c
@@ -23,7 +23,7 @@
////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////
-/// FUNCTION DEFITIONS ///
+/// FUNCTION DEFINITIONS ///
////////////////////////////////////////////////////////////////////////
/**Function*************************************************************
@@ -147,9 +147,9 @@ void Map_SuperLibFree( Map_SuperLib_t * p )
Map_SuperTableFree( p->tTableC );
if ( p->tTable )
Map_SuperTableFree( p->tTable );
- Extra_MmFixedStop( p->mmSupers, 0 );
- Extra_MmFixedStop( p->mmEntries, 0 );
- Extra_MmFlexStop( p->mmForms, 0 );
+ Extra_MmFixedStop( p->mmSupers );
+ Extra_MmFixedStop( p->mmEntries );
+ Extra_MmFlexStop( p->mmForms );
FREE( p->ppSupers );
FREE( p );
}
@@ -179,7 +179,7 @@ int Map_SuperLibDeriveFromGenlib( Mio_Library_t * pLib )
return 0;
// write the current library into the file
- strcpy( FileNameGenlib, Mio_LibraryReadName(pLib) );
+ sprintf( FileNameGenlib, "%s_temp", Mio_LibraryReadName(pLib) );
pFile = fopen( FileNameGenlib, "w" );
Mio_WriteLibrary( pFile, pLib, 0 );
fclose( pFile );
diff --git a/src/map/mapper/mapperMatch.c b/src/map/mapper/mapperMatch.c
index ddb9ebb7..bfa72601 100644
--- a/src/map/mapper/mapperMatch.c
+++ b/src/map/mapper/mapperMatch.c
@@ -41,7 +41,7 @@ static void Map_NodeTryDroppingOnePhase( Map_Man_t * p, Map_Node_t * pNode );
static void Map_NodeTransferArrivalTimes( Map_Man_t * p, Map_Node_t * pNode );
////////////////////////////////////////////////////////////////////////
-/// FUNCTION DEFITIONS ///
+/// FUNCTION DEFINITIONS ///
////////////////////////////////////////////////////////////////////////
/**Function*************************************************************
diff --git a/src/map/mapper/mapperRefs.c b/src/map/mapper/mapperRefs.c
index baaebfa1..a50b134a 100644
--- a/src/map/mapper/mapperRefs.c
+++ b/src/map/mapper/mapperRefs.c
@@ -28,7 +28,7 @@ static float Map_CutRefDeref( Map_Cut_t * pCut, int fPhase, int fReference );
static void Map_MappingSetRefs_rec( Map_Man_t * pMan, Map_Node_t * pNode, Map_Node_t ** ppStore );
////////////////////////////////////////////////////////////////////////
-/// FUNCTION DEFITIONS ///
+/// FUNCTION DEFINITIONS ///
////////////////////////////////////////////////////////////////////////
/**Function*************************************************************
@@ -237,7 +237,7 @@ float Map_CutGetAreaRefed( Map_Cut_t * pCut, int fPhase )
float aResult, aResult2;
aResult2 = Map_CutRefDeref( pCut, fPhase, 0 ); // dereference
aResult = Map_CutRefDeref( pCut, fPhase, 1 ); // reference
- assert( aResult == aResult2 );
+// assert( aResult == aResult2 );
return aResult;
}
@@ -257,7 +257,7 @@ float Map_CutGetAreaDerefed( Map_Cut_t * pCut, int fPhase )
float aResult, aResult2;
aResult2 = Map_CutRefDeref( pCut, fPhase, 1 ); // reference
aResult = Map_CutRefDeref( pCut, fPhase, 0 ); // dereference
- assert( aResult == aResult2 );
+// assert( aResult == aResult2 );
return aResult;
}
diff --git a/src/map/mapper/mapperSuper.c b/src/map/mapper/mapperSuper.c
index 34b1d8e6..ce6a780f 100644
--- a/src/map/mapper/mapperSuper.c
+++ b/src/map/mapper/mapperSuper.c
@@ -30,7 +30,7 @@ static void Map_LibraryComputeTruth_rec( Map_SuperLib_t * pLib, char *
static void Map_LibraryPrintClasses( Map_SuperLib_t * p );
////////////////////////////////////////////////////////////////////////
-/// FUNCTION DEFITIONS ///
+/// FUNCTION DEFINITIONS ///
////////////////////////////////////////////////////////////////////////
/**Function*************************************************************
diff --git a/src/map/mapper/mapperSwitch.c b/src/map/mapper/mapperSwitch.c
index 13168b47..9dd6e42b 100644
--- a/src/map/mapper/mapperSwitch.c
+++ b/src/map/mapper/mapperSwitch.c
@@ -25,7 +25,7 @@
static float Map_SwitchCutRefDeref( Map_Node_t * pNode, Map_Cut_t * pCut, int fPhase, int fReference );
////////////////////////////////////////////////////////////////////////
-/// FUNCTION DEFITIONS ///
+/// FUNCTION DEFINITIONS ///
////////////////////////////////////////////////////////////////////////
/**function*************************************************************
diff --git a/src/map/mapper/mapperTable.c b/src/map/mapper/mapperTable.c
index 747fe1c8..d0cb7a01 100644
--- a/src/map/mapper/mapperTable.c
+++ b/src/map/mapper/mapperTable.c
@@ -28,7 +28,7 @@
static void Map_SuperTableResize( Map_HashTable_t * pLib );
////////////////////////////////////////////////////////////////////////
-/// FUNCTION DEFITIONS ///
+/// FUNCTION DEFINITIONS ///
////////////////////////////////////////////////////////////////////////
/**Function*************************************************************
@@ -325,7 +325,7 @@ void Map_SuperTableSortSupergates( Map_HashTable_t * p, int nSupersMax )
ppSupers[nSupers++] = pSuper;
// sort by usage
- qsort( (void *)ppSupers, nSupers, sizeof(int),
+ qsort( (void *)ppSupers, nSupers, sizeof(Map_Super_t *),
(int (*)(const void *, const void *)) Map_SuperTableCompareSupergates );
assert( Map_SuperTableCompareSupergates( ppSupers, ppSupers + nSupers - 1 ) <= 0 );
@@ -380,7 +380,7 @@ void Map_SuperTableSortSupergatesByDelay( Map_HashTable_t * p, int nSupersMax )
if ( nSupers == 0 )
continue;
// sort the gates by delay
- qsort( (void *)ppSupers, nSupers, sizeof(int),
+ qsort( (void *)ppSupers, nSupers, sizeof(Map_Super_t *),
(int (*)(const void *, const void *)) Map_SuperTableCompareGatesInList );
assert( Map_SuperTableCompareGatesInList( ppSupers, ppSupers + nSupers - 1 ) <= 0 );
// link them in the reverse order
diff --git a/src/map/mapper/mapperTime.c b/src/map/mapper/mapperTime.c
index f1cafae7..cc4173cf 100644
--- a/src/map/mapper/mapperTime.c
+++ b/src/map/mapper/mapperTime.c
@@ -27,7 +27,7 @@ static void Map_TimePropagateRequiredPhase( Map_Man_t * p, Map_Node_t * pNode,
static float Map_MatchComputeReqTimes( Map_Cut_t * pCut, int fPhase, Map_Time_t * ptArrRes );
////////////////////////////////////////////////////////////////////////
-/// FUNCTION DEFITIONS ///
+/// FUNCTION DEFINITIONS ///
////////////////////////////////////////////////////////////////////////
/**function*************************************************************
diff --git a/src/map/mapper/mapperTree.c b/src/map/mapper/mapperTree.c
index 04576045..ef66082d 100644
--- a/src/map/mapper/mapperTree.c
+++ b/src/map/mapper/mapperTree.c
@@ -37,7 +37,7 @@ static unsigned Map_LibraryGetGateSupp_rec( Map_Super_t * pGate );
extern const int s_MapFanoutLimits[10] = { 1/*0*/, 10/*1*/, 5/*2*/, 2/*3*/, 1/*4*/, 1/*5*/, 1/*6*/ };
////////////////////////////////////////////////////////////////////////
-/// FUNCTION DEFITIONS ///
+/// FUNCTION DEFINITIONS ///
////////////////////////////////////////////////////////////////////////
/**Function*************************************************************
@@ -60,8 +60,8 @@ int Map_LibraryReadTree( Map_SuperLib_t * pLib, char * pFileName, char * pExclud
// read the beginning of the file
assert( pLib->pGenlib == NULL );
-// pFile = Io_FileOpen( pFileName, "open_path", "r" );
- pFile = fopen( pFileName, "r" );
+ pFile = Io_FileOpen( pFileName, "open_path", "r", 1 );
+// pFile = fopen( pFileName, "r" );
if ( pFile == NULL )
{
printf( "Cannot open input file \"%s\".\n", pFileName );
@@ -149,8 +149,8 @@ int Map_LibraryReadFileTree( Map_SuperLib_t * pLib, FILE * pFile, char *pFileNam
}
#endif
-// pFileGen = Io_FileOpen( pLibFile, "open_path", "r" );
- pFileGen = fopen( pLibFile, "r" );
+ pFileGen = Io_FileOpen( pLibFile, "open_path", "r", 1 );
+// pFileGen = fopen( pLibFile, "r" );
if ( pFileGen == NULL )
{
printf( "Cannot open the GENLIB file \"%s\".\n", pLibFile );
@@ -439,6 +439,9 @@ int Map_LibraryDeriveGateInfo( Map_SuperLib_t * pLib, st_table * tExcludeGate )
pGate->tDelayMax.Fall = pGate->tDelaysF[k].Rise;
if ( pGate->tDelayMax.Fall < pGate->tDelaysF[k].Fall )
pGate->tDelayMax.Fall = pGate->tDelaysF[k].Fall;
+
+ pGate->tDelaysF[k].Worst = MAP_MAX( pGate->tDelaysF[k].Fall, pGate->tDelaysF[k].Rise );
+ pGate->tDelaysR[k].Worst = MAP_MAX( pGate->tDelaysR[k].Fall, pGate->tDelaysR[k].Rise );
}
// count gates and area of the supergate
diff --git a/src/map/mapper/mapperTruth.c b/src/map/mapper/mapperTruth.c
index 7eabf4df..388b6dd3 100644
--- a/src/map/mapper/mapperTruth.c
+++ b/src/map/mapper/mapperTruth.c
@@ -27,7 +27,7 @@ extern void Map_TruthsCutOne( Map_Man_t * p, Map_Cut_t * pCut, unsigned uTruth[]
static void Map_CutsCollect_rec( Map_Cut_t * pCut, Map_NodeVec_t * vVisited );
////////////////////////////////////////////////////////////////////////
-/// FUNCTION DEFITIONS ///
+/// FUNCTION DEFINITIONS ///
////////////////////////////////////////////////////////////////////////
/**Function*************************************************************
@@ -89,14 +89,15 @@ void Map_MappingTruths( Map_Man_t * pMan )
***********************************************************************/
void Map_TruthsCut( Map_Man_t * p, Map_Cut_t * pCut )
-{
+{
// unsigned uCanon1, uCanon2;
unsigned uTruth[2], uCanon[2];
unsigned char uPhases[16];
unsigned * uCanon2;
char * pPhases2;
- int fUseFast = 0;
- int fUseRec = 1;
+ int fUseFast = 1;
+ int fUseSlow = 0;
+ int fUseRec = 0; // this does not work for Solaris
extern int Map_CanonCompute( int nVarsMax, int nVarsReal, unsigned * pt, unsigned ** pptRes, char ** ppfRes );
@@ -117,6 +118,8 @@ void Map_TruthsCut( Map_Man_t * p, Map_Cut_t * pCut )
// compute the canonical form for the positive phase
if ( fUseFast )
Map_CanonComputeFast( p, p->nVarsMax, pCut->nLeaves, uTruth, uPhases, uCanon );
+ else if ( fUseSlow )
+ Map_CanonComputeSlow( p->uTruths, p->nVarsMax, pCut->nLeaves, uTruth, uPhases, uCanon );
else if ( fUseRec )
{
// Map_CanonComputeSlow( p->uTruths, p->nVarsMax, pCut->nLeaves, uTruth, uPhases, uCanon );
@@ -145,6 +148,8 @@ void Map_TruthsCut( Map_Man_t * p, Map_Cut_t * pCut )
uTruth[1] = ~uTruth[1];
if ( fUseFast )
Map_CanonComputeFast( p, p->nVarsMax, pCut->nLeaves, uTruth, uPhases, uCanon );
+ else if ( fUseSlow )
+ Map_CanonComputeSlow( p->uTruths, p->nVarsMax, pCut->nLeaves, uTruth, uPhases, uCanon );
else if ( fUseRec )
{
// Map_CanonComputeSlow( p->uTruths, p->nVarsMax, pCut->nLeaves, uTruth, uPhases, uCanon );
diff --git a/src/map/mapper/mapperUtils.c b/src/map/mapper/mapperUtils.c
index 00f1b85b..11a3a683 100644
--- a/src/map/mapper/mapperUtils.c
+++ b/src/map/mapper/mapperUtils.c
@@ -40,7 +40,7 @@ static int Map_MappingCountUsedNodes( Map_Man_t * pMan, int fChoices );
static Map_Man_t * s_pMan = NULL;
////////////////////////////////////////////////////////////////////////
-/// FUNCTION DEFITIONS ///
+/// FUNCTION DEFINITIONS ///
////////////////////////////////////////////////////////////////////////
diff --git a/src/map/mapper/mapperVec.c b/src/map/mapper/mapperVec.c
index e3ab4b7f..f75138fb 100644
--- a/src/map/mapper/mapperVec.c
+++ b/src/map/mapper/mapperVec.c
@@ -25,7 +25,7 @@
static int Map_NodeVecCompareLevels( Map_Node_t ** pp1, Map_Node_t ** pp2 );
////////////////////////////////////////////////////////////////////////
-/// FUNCTION DEFITIONS ///
+/// FUNCTION DEFINITIONS ///
////////////////////////////////////////////////////////////////////////
/**Function*************************************************************
diff --git a/src/map/mio/mio.c b/src/map/mio/mio.c
index bb6dbba1..10a5af9d 100644
--- a/src/map/mio/mio.c
+++ b/src/map/mio/mio.c
@@ -55,7 +55,7 @@ static char * pMcncGenlib[25] = {
};
////////////////////////////////////////////////////////////////////////
-/// FUNCTION DEFITIONS ///
+/// FUNCTION DEFINITIONS ///
////////////////////////////////////////////////////////////////////////
/**Function*************************************************************
@@ -108,7 +108,7 @@ void Mio_Init( Abc_Frame_t * pAbc )
void Mio_End()
{
// Mio_LibraryDelete( s_pLib );
- Mio_LibraryDelete( Abc_FrameReadLibGen(Abc_FrameGetGlobalFrame()) );
+ Mio_LibraryDelete( Abc_FrameReadLibGen() );
}
@@ -133,14 +133,14 @@ int Mio_CommandReadLibrary( Abc_Frame_t * pAbc, int argc, char **argv )
int fVerbose;
int c;
- pNet = Abc_FrameReadNet(pAbc);
+ pNet = Abc_FrameReadNtk(pAbc);
pOut = Abc_FrameReadOut(pAbc);
pErr = Abc_FrameReadErr(pAbc);
// set the defaults
fVerbose = 1;
- util_getopt_reset();
- while ( (c = util_getopt(argc, argv, "vh")) != EOF )
+ Extra_UtilGetoptReset();
+ while ( (c = Extra_UtilGetopt(argc, argv, "vh")) != EOF )
{
switch (c)
{
@@ -156,14 +156,14 @@ int Mio_CommandReadLibrary( Abc_Frame_t * pAbc, int argc, char **argv )
}
- if ( argc != util_optind + 1 )
+ if ( argc != globalUtilOptind + 1 )
{
goto usage;
}
// get the input file name
- FileName = argv[util_optind];
- if ( (pFile = fopen( FileName, "r" )) == NULL )
+ FileName = argv[globalUtilOptind];
+ if ( (pFile = Io_FileOpen( FileName, "open_path", "r", 0 )) == NULL )
{
fprintf( pErr, "Cannot open input file \"%s\". ", FileName );
if ( (FileName = Extra_FileGetSimilarName( FileName, ".genlib", ".lib", ".gen", ".g", NULL )) )
@@ -181,7 +181,7 @@ int Mio_CommandReadLibrary( Abc_Frame_t * pAbc, int argc, char **argv )
return 1;
}
// free the current superlib because it depends on the old Mio library
- if ( Abc_FrameReadLibSuper(Abc_FrameGetGlobalFrame()) )
+ if ( Abc_FrameReadLibSuper() )
{
extern void Map_SuperLibFree( Map_SuperLib_t * p );
// Map_SuperLibFree( s_pSuperLib );
@@ -223,14 +223,14 @@ int Mio_CommandPrintLibrary( Abc_Frame_t * pAbc, int argc, char **argv )
int fVerbose;
int c;
- pNet = Abc_FrameReadNet(pAbc);
+ pNet = Abc_FrameReadNtk(pAbc);
pOut = Abc_FrameReadOut(pAbc);
pErr = Abc_FrameReadErr(pAbc);
// set the defaults
fVerbose = 1;
- util_getopt_reset();
- while ( (c = util_getopt(argc, argv, "vh")) != EOF )
+ Extra_UtilGetoptReset();
+ while ( (c = Extra_UtilGetopt(argc, argv, "vh")) != EOF )
{
switch (c)
{
@@ -246,13 +246,13 @@ int Mio_CommandPrintLibrary( Abc_Frame_t * pAbc, int argc, char **argv )
}
- if ( argc != util_optind )
+ if ( argc != globalUtilOptind )
{
goto usage;
}
// set the new network
- Mio_WriteLibrary( stdout, Abc_FrameReadLibGen(Abc_FrameGetGlobalFrame()), 0 );
+ Mio_WriteLibrary( stdout, Abc_FrameReadLibGen(), 0 );
return 0;
usage:
diff --git a/src/map/mio/mio.h b/src/map/mio/mio.h
index f9f4973d..dbe2420b 100644
--- a/src/map/mio/mio.h
+++ b/src/map/mio/mio.h
@@ -19,6 +19,10 @@
#ifndef __MIO_H__
#define __MIO_H__
+#ifdef __cplusplus
+extern "C" {
+#endif
+
////////////////////////////////////////////////////////////////////////
/// INCLUDES ///
////////////////////////////////////////////////////////////////////////
@@ -42,7 +46,7 @@ typedef struct Mio_PinStruct_t_ Mio_Pin_t;
////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////
-/// MACRO DEFITIONS ///
+/// MACRO DEFINITIONS ///
////////////////////////////////////////////////////////////////////////
#define Mio_LibraryForEachGate( Lib, Gate ) \
@@ -68,7 +72,7 @@ typedef struct Mio_PinStruct_t_ Mio_Pin_t;
Pin2 = (Pin? Mio_PinReadNext(Pin): NULL) )
////////////////////////////////////////////////////////////////////////
-/// FUNCTION DEFITIONS ///
+/// FUNCTION DEFINITIONS ///
////////////////////////////////////////////////////////////////////////
/*=== mioApi.c =============================================================*/
@@ -81,6 +85,7 @@ extern char * Mio_LibraryReadSopByName ( Mio_Library_t * pLib, char
extern Mio_Gate_t * Mio_LibraryReadConst0 ( Mio_Library_t * pLib );
extern Mio_Gate_t * Mio_LibraryReadConst1 ( Mio_Library_t * pLib );
extern Mio_Gate_t * Mio_LibraryReadNand2 ( Mio_Library_t * pLib );
+extern Mio_Gate_t * Mio_LibraryReadAnd2 ( Mio_Library_t * pLib );
extern Mio_Gate_t * Mio_LibraryReadBuf ( Mio_Library_t * pLib );
extern Mio_Gate_t * Mio_LibraryReadInv ( Mio_Library_t * pLib );
extern float Mio_LibraryReadDelayInvRise( Mio_Library_t * pLib );
@@ -89,9 +94,11 @@ extern float Mio_LibraryReadDelayInvMax( Mio_Library_t * pLib );
extern float Mio_LibraryReadDelayNand2Rise( Mio_Library_t * pLib );
extern float Mio_LibraryReadDelayNand2Fall( Mio_Library_t * pLib );
extern float Mio_LibraryReadDelayNand2Max( Mio_Library_t * pLib );
+extern float Mio_LibraryReadDelayAnd2Max( Mio_Library_t * pLib );
extern float Mio_LibraryReadAreaInv ( Mio_Library_t * pLib );
extern float Mio_LibraryReadAreaBuf ( Mio_Library_t * pLib );
extern float Mio_LibraryReadAreaNand2 ( Mio_Library_t * pLib );
+extern int Mio_LibraryReadGateNameMax( Mio_Library_t * pLib );
extern char * Mio_GateReadName ( Mio_Gate_t * pGate );
extern char * Mio_GateReadOutName ( Mio_Gate_t * pGate );
extern double Mio_GateReadArea ( Mio_Gate_t * pGate );
@@ -114,8 +121,8 @@ extern double Mio_PinReadDelayFanoutFall( Mio_Pin_t * pPin );
extern double Mio_PinReadDelayBlockMax ( Mio_Pin_t * pPin );
extern Mio_Pin_t * Mio_PinReadNext ( Mio_Pin_t * pPin );
/*=== mioRead.c =============================================================*/
-extern Mio_Library_t * Mio_LibraryRead( Abc_Frame_t * pAbc, char * FileName, char * ExcludeFile, int fVerbose );
-extern int Mio_LibraryReadExclude( Abc_Frame_t * pAbc, char * ExcludeFile, st_table * tExcludeGate );
+extern Mio_Library_t * Mio_LibraryRead( void * pAbc, char * FileName, char * ExcludeFile, int fVerbose );
+extern int Mio_LibraryReadExclude( void * pAbc, char * ExcludeFile, st_table * tExcludeGate );
/*=== mioFunc.c =============================================================*/
extern int Mio_LibraryParseFormulas( Mio_Library_t * pLib );
/*=== mioUtils.c =============================================================*/
@@ -131,7 +138,13 @@ extern void Mio_DeriveGateDelays( Mio_Gate_t * pGate,
float * ptDelaysRes, float * ptPinDelayMax );
extern Mio_Gate_t * Mio_GateCreatePseudo( int nInputs );
+#ifdef __cplusplus
+}
+#endif
+
+#endif
+
////////////////////////////////////////////////////////////////////////
/// END OF FILE ///
////////////////////////////////////////////////////////////////////////
-#endif
+
diff --git a/src/map/mio/mioApi.c b/src/map/mio/mioApi.c
index a39c6288..73473f8b 100644
--- a/src/map/mio/mioApi.c
+++ b/src/map/mio/mioApi.c
@@ -23,7 +23,7 @@
////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////
-/// FUNCTION DEFITIONS ///
+/// FUNCTION DEFINITIONS ///
////////////////////////////////////////////////////////////////////////
/**Function*************************************************************
@@ -43,21 +43,47 @@ Mio_Gate_t * Mio_LibraryReadGates ( Mio_Library_t * pLib ) { retur
DdManager * Mio_LibraryReadDd ( Mio_Library_t * pLib ) { return pLib->dd; }
Mio_Gate_t * Mio_LibraryReadBuf ( Mio_Library_t * pLib ) { return pLib->pGateBuf; }
Mio_Gate_t * Mio_LibraryReadInv ( Mio_Library_t * pLib ) { return pLib->pGateInv; }
-Mio_Gate_t * Mio_LibraryReadConst0 ( Mio_Library_t * pLib ) { return pLib->pGate0; }
-Mio_Gate_t * Mio_LibraryReadConst1 ( Mio_Library_t * pLib ) { return pLib->pGate1; }
+Mio_Gate_t * Mio_LibraryReadConst0 ( Mio_Library_t * pLib ) { return pLib->pGate0; }
+Mio_Gate_t * Mio_LibraryReadConst1 ( Mio_Library_t * pLib ) { return pLib->pGate1; }
Mio_Gate_t * Mio_LibraryReadNand2 ( Mio_Library_t * pLib ) { return pLib->pGateNand2; }
+Mio_Gate_t * Mio_LibraryReadAnd2 ( Mio_Library_t * pLib ) { return pLib->pGateAnd2; }
float Mio_LibraryReadDelayInvRise ( Mio_Library_t * pLib ) { return (float)(pLib->pGateInv? pLib->pGateInv->pPins->dDelayBlockRise : 0.0); }
float Mio_LibraryReadDelayInvFall ( Mio_Library_t * pLib ) { return (float)(pLib->pGateInv? pLib->pGateInv->pPins->dDelayBlockFall : 0.0); }
float Mio_LibraryReadDelayInvMax ( Mio_Library_t * pLib ) { return (float)(pLib->pGateInv? pLib->pGateInv->pPins->dDelayBlockMax : 0.0); }
float Mio_LibraryReadDelayNand2Rise( Mio_Library_t * pLib ) { return (float)(pLib->pGateNand2? pLib->pGateNand2->pPins->dDelayBlockRise : 0.0); }
float Mio_LibraryReadDelayNand2Fall( Mio_Library_t * pLib ) { return (float)(pLib->pGateNand2? pLib->pGateNand2->pPins->dDelayBlockFall : 0.0); }
float Mio_LibraryReadDelayNand2Max ( Mio_Library_t * pLib ) { return (float)(pLib->pGateNand2? pLib->pGateNand2->pPins->dDelayBlockMax : 0.0); }
+float Mio_LibraryReadDelayAnd2Max ( Mio_Library_t * pLib ) { return (float)(pLib->pGateAnd2? pLib->pGateAnd2->pPins->dDelayBlockMax : 0.0); }
float Mio_LibraryReadAreaInv ( Mio_Library_t * pLib ) { return (float)(pLib->pGateInv? pLib->pGateInv->dArea : 0.0); }
float Mio_LibraryReadAreaBuf ( Mio_Library_t * pLib ) { return (float)(pLib->pGateBuf? pLib->pGateBuf->dArea : 0.0); }
float Mio_LibraryReadAreaNand2 ( Mio_Library_t * pLib ) { return (float)(pLib->pGateNand2? pLib->pGateNand2->dArea : 0.0); }
/**Function*************************************************************
+ Synopsis [Returns the longest gate name.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Mio_LibraryReadGateNameMax( Mio_Library_t * pLib )
+{
+ Mio_Gate_t * pGate;
+ int LenMax = 0, LenCur;
+ Mio_LibraryForEachGate( pLib, pGate )
+ {
+ LenCur = strlen( Mio_GateReadName(pGate) );
+ if ( LenMax < LenCur )
+ LenMax = LenCur;
+ }
+ return LenMax;
+}
+
+/**Function*************************************************************
+
Synopsis [Read Mvc of the gate by name.]
Description []
diff --git a/src/map/mio/mioFunc.c b/src/map/mio/mioFunc.c
index 24b2fecb..21a078f9 100644
--- a/src/map/mio/mioFunc.c
+++ b/src/map/mio/mioFunc.c
@@ -35,7 +35,7 @@ static int Mio_GateParseFormula( Mio_Gate_t * pGate );
static int Mio_GateCollectNames( char * pFormula, char * pPinNames[] );
////////////////////////////////////////////////////////////////////////
-/// FUNCTION DEFITIONS ///
+/// FUNCTION DEFINITIONS ///
////////////////////////////////////////////////////////////////////////
/**Function*************************************************************
@@ -213,7 +213,7 @@ int Mio_GateParseFormula( Mio_Gate_t * pGate )
Cudd_Ref( pGate->bFunc );
// derive the cover (SOP)
- pGate->pSop = Abc_ConvertBddToSop( pGate->pLib->pMmFlex, dd, pGate->bFunc, pGate->bFunc, nPins, pGate->pLib->vCube, -1 );
+ pGate->pSop = Abc_ConvertBddToSop( pGate->pLib->pMmFlex, dd, pGate->bFunc, pGate->bFunc, nPins, 0, pGate->pLib->vCube, -1 );
return 0;
}
@@ -253,7 +253,7 @@ int Mio_GateCollectNames( char * pFormula, char * pPinNames[] )
break;
if ( i == nPins )
{ // cannot find this name; save it
- pPinNames[nPins++] = util_strsav(pTemp);
+ pPinNames[nPins++] = Extra_UtilStrsav(pTemp);
}
// get the next name
pTemp = strtok( NULL, " " );
diff --git a/src/map/mio/mioGENERIC.c b/src/map/mio/mioGENERIC.c
index 6a40bc52..972c4ffc 100644
--- a/src/map/mio/mioGENERIC.c
+++ b/src/map/mio/mioGENERIC.c
@@ -23,7 +23,7 @@
////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////
-/// FUNCTION DEFITIONS ///
+/// FUNCTION DEFINITIONS ///
////////////////////////////////////////////////////////////////////////
/**Function*************************************************************
diff --git a/src/map/mio/mioInt.h b/src/map/mio/mioInt.h
index 105e3d8d..3f90b625 100644
--- a/src/map/mio/mioInt.h
+++ b/src/map/mio/mioInt.h
@@ -60,6 +60,7 @@ struct Mio_LibraryStruct_t_
Mio_Gate_t * pGateBuf; // the buffer
Mio_Gate_t * pGateInv; // the inverter
Mio_Gate_t * pGateNand2; // the NAND2 gate
+ Mio_Gate_t * pGateAnd2; // the AND2 gate
st_table * tName2Gate; // the mapping of gate names into their pointer
DdManager * dd; // the nanager storing functions of gates
Extra_MmFlex_t * pMmFlex; // the memory manaqer for SOPs
@@ -106,19 +107,19 @@ struct Mio_PinStruct_t_
////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////
-/// MACRO DEFITIONS ///
+/// MACRO DEFINITIONS ///
////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////
-/// FUNCTION DEFITIONS ///
+/// FUNCTION DEFINITIONS ///
////////////////////////////////////////////////////////////////////////
/*=== mio.c =============================================================*/
/*=== mioRead.c =============================================================*/
/*=== mioUtils.c =============================================================*/
+#endif
+
////////////////////////////////////////////////////////////////////////
/// END OF FILE ///
////////////////////////////////////////////////////////////////////////
-
-#endif
diff --git a/src/map/mio/mioRead.c b/src/map/mio/mioRead.c
index f2778ca4..13c2cdcd 100644
--- a/src/map/mio/mioRead.c
+++ b/src/map/mio/mioRead.c
@@ -23,7 +23,7 @@
////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////
-/// FUNCTION DEFITIONS ///
+/// FUNCTION DEFINITIONS ///
////////////////////////////////////////////////////////////////////////
static Mio_Library_t * Mio_LibraryReadOne( Abc_Frame_t * pAbc, char * FileName, bool fExtendedFormat, st_table * tExcludeGate, int fVerbose );
@@ -49,7 +49,7 @@ extern int isspace( int c ); // to silence the warning in VS
SeeAlso []
***********************************************************************/
-Mio_Library_t * Mio_LibraryRead( Abc_Frame_t * pAbc, char * FileName, char * ExcludeFile, int fVerbose )
+Mio_Library_t * Mio_LibraryRead( void * pAbc, char * FileName, char * ExcludeFile, int fVerbose )
{
Mio_Library_t * pLib;
int num;
@@ -99,7 +99,7 @@ Mio_Library_t * Mio_LibraryReadOne( Abc_Frame_t * pAbc, char * FileName, bool fE
// allocate the genlib structure
pLib = ALLOC( Mio_Library_t, 1 );
memset( pLib, 0, sizeof(Mio_Library_t) );
- pLib->pName = util_strsav( FileName );
+ pLib->pName = Extra_UtilStrsav( FileName );
pLib->tName2Gate = st_init_table(strcmp, st_strhash);
pLib->pMmFlex = Extra_MmFlexStart();
pLib->vCube = Vec_StrAlloc( 100 );
@@ -114,8 +114,8 @@ Mio_Library_t * Mio_LibraryReadOne( Abc_Frame_t * pAbc, char * FileName, bool fE
int nFileSize;
// open the BLIF file for binary reading
-// pFile = Io_FileOpen( FileName, "open_path", "rb" );
- pFile = fopen( FileName, "rb" );
+ pFile = Io_FileOpen( FileName, "open_path", "rb", 1 );
+// pFile = fopen( FileName, "rb" );
// if we got this far, file should be okay otherwise would
// have been detected by caller
assert ( pFile != NULL );
@@ -251,7 +251,7 @@ Mio_Gate_t * Mio_LibraryReadGate( char ** ppToken, bool fExtendedFormat )
// read the name
pToken = strtok( NULL, " \t\r\n" );
- pGate->pName = util_strsav( pToken );
+ pGate->pName = Extra_UtilStrsav( pToken );
// read the area
pToken = strtok( NULL, " \t\r\n" );
@@ -265,7 +265,7 @@ Mio_Gate_t * Mio_LibraryReadGate( char ** ppToken, bool fExtendedFormat )
// then rest of the expression
pToken = strtok( NULL, ";" );
- pGate->pForm = util_strsav( pToken );
+ pGate->pForm = Extra_UtilStrsav( pToken );
// read the pin info
// start the linked list of pins
@@ -319,7 +319,7 @@ Mio_Pin_t * Mio_LibraryReadPin( char ** ppToken, bool fExtendedFormat )
// read the name
pToken = strtok( NULL, " \t\r\n" );
- pPin->pName = util_strsav( pToken );
+ pPin->pName = Extra_UtilStrsav( pToken );
// read the pin phase
pToken = strtok( NULL, " \t\r\n" );
@@ -418,12 +418,14 @@ char *chomp( char *s )
void Mio_LibraryDetectSpecialGates( Mio_Library_t * pLib )
{
Mio_Gate_t * pGate;
- DdNode * bFuncBuf, * bFuncInv, * bFuncNand2;
+ DdNode * bFuncBuf, * bFuncInv, * bFuncNand2, * bFuncAnd2;
bFuncBuf = pLib->dd->vars[0]; Cudd_Ref( bFuncBuf );
bFuncInv = Cudd_Not( pLib->dd->vars[0] ); Cudd_Ref( bFuncInv );
bFuncNand2 = Cudd_bddNand( pLib->dd, pLib->dd->vars[0], pLib->dd->vars[1] ); Cudd_Ref( bFuncNand2 );
+ bFuncAnd2 = Cudd_bddAnd( pLib->dd, pLib->dd->vars[0], pLib->dd->vars[1] ); Cudd_Ref( bFuncAnd2 );
+ // get buffer
Mio_LibraryForEachGate( pLib, pGate )
if ( pLib->pGateBuf == NULL && pGate->bFunc == bFuncBuf )
{
@@ -435,7 +437,8 @@ void Mio_LibraryDetectSpecialGates( Mio_Library_t * pLib )
printf( "Warnings: GENLIB library reader cannot detect the buffer gate.\n" );
printf( "Some parts of the supergate-based technology mapper may not work correctly.\n" );
}
-
+
+ // get inverter
Mio_LibraryForEachGate( pLib, pGate )
if ( pLib->pGateInv == NULL && pGate->bFunc == bFuncInv )
{
@@ -448,20 +451,28 @@ void Mio_LibraryDetectSpecialGates( Mio_Library_t * pLib )
printf( "Some parts of the supergate-based technology mapper may not work correctly.\n" );
}
+ // get the NAND2 and AND2 gates
Mio_LibraryForEachGate( pLib, pGate )
if ( pLib->pGateNand2 == NULL && pGate->bFunc == bFuncNand2 )
{
pLib->pGateNand2 = pGate;
break;
}
- if ( pLib->pGateNand2 == NULL )
+ Mio_LibraryForEachGate( pLib, pGate )
+ if ( pLib->pGateAnd2 == NULL && pGate->bFunc == bFuncAnd2 )
+ {
+ pLib->pGateAnd2 = pGate;
+ break;
+ }
+ if ( pLib->pGateAnd2 == NULL && pLib->pGateNand2 == NULL )
{
- printf( "Warnings: GENLIB library reader cannot detect the NAND2 gate.\n" );
+ printf( "Warnings: GENLIB library reader cannot detect the AND2 or NAND2 gate.\n" );
printf( "Some parts of the supergate-based technology mapper may not work correctly.\n" );
}
Cudd_RecursiveDeref( pLib->dd, bFuncInv );
Cudd_RecursiveDeref( pLib->dd, bFuncNand2 );
+ Cudd_RecursiveDeref( pLib->dd, bFuncAnd2 );
}
/**Function*************************************************************
@@ -475,7 +486,7 @@ void Mio_LibraryDetectSpecialGates( Mio_Library_t * pLib )
SeeAlso []
***********************************************************************/
-int Mio_LibraryReadExclude( Abc_Frame_t * pAbc, char * ExcludeFile, st_table * tExcludeGate )
+int Mio_LibraryReadExclude( void * pAbc, char * ExcludeFile, st_table * tExcludeGate )
{
int nDel = 0;
FILE *pEx;
@@ -496,7 +507,7 @@ int Mio_LibraryReadExclude( Abc_Frame_t * pAbc, char * ExcludeFile, st_table * t
while (1 == fscanf( pEx, "%127s", buffer ))
{
//printf ("Read: '%s'\n", buffer );
- st_insert( tExcludeGate, util_strsav( buffer ), (char *)0 );
+ st_insert( tExcludeGate, Extra_UtilStrsav( buffer ), (char *)0 );
nDel++;
}
diff --git a/src/map/mio/mioUtils.c b/src/map/mio/mioUtils.c
index 15f32890..bd3d01f7 100644
--- a/src/map/mio/mioUtils.c
+++ b/src/map/mio/mioUtils.c
@@ -28,7 +28,7 @@ static int Mio_DelayCompare( Mio_Gate_t ** ppG1, Mio_Gate_t ** ppG2 );
static void Mio_DeriveTruthTable_rec( DdNode * bFunc, unsigned uTruthsIn[][2], unsigned uTruthRes[] );
////////////////////////////////////////////////////////////////////////
-/// FUNCTION DEFITIONS ///
+/// FUNCTION DEFINITIONS ///
////////////////////////////////////////////////////////////////////////
/**Function*************************************************************
@@ -53,7 +53,7 @@ void Mio_LibraryDelete( Mio_Library_t * pLib )
FREE( pLib->pName );
Mio_LibraryForEachGateSafe( pLib, pGate, pGate2 )
Mio_GateDelete( pGate );
- Extra_MmFlexStop( pLib->pMmFlex, 0 );
+ Extra_MmFlexStop( pLib->pMmFlex );
Vec_StrFree( pLib->vCube );
if ( pLib->tName2Gate )
st_free_table( pLib->tName2Gate );
@@ -120,7 +120,7 @@ Mio_Pin_t * Mio_PinDup( Mio_Pin_t * pPin )
pPinNew = ALLOC( Mio_Pin_t, 1 );
*pPinNew = *pPin;
- pPinNew->pName = (pPinNew->pName ? util_strsav(pPinNew->pName) : NULL);
+ pPinNew->pName = (pPinNew->pName ? Extra_UtilStrsav(pPinNew->pName) : NULL);
pPinNew->pNext = NULL;
return pPinNew;
@@ -165,9 +165,9 @@ void Mio_WriteGate( FILE * pFile, Mio_Gate_t * pGate, int fPrintSops )
Mio_Pin_t * pPin;
fprintf( pFile, "GATE " );
- fprintf( pFile, "%12s ", pGate->pName );
+ fprintf( pFile, "%12s ", pGate->pName );
fprintf( pFile, "%10.2f ", pGate->dArea );
- fprintf( pFile, "O=%s;\n", pGate->pForm );
+ fprintf( pFile, "%s=%s;\n", pGate->pOutName, pGate->pForm );
// print the pins
if ( fPrintSops )
fprintf( pFile, "%s", pGate->pSop? pGate->pSop : "unspecified\n" );
diff --git a/src/map/super/super.c b/src/map/super/super.c
index ffb432d5..97420c5c 100644
--- a/src/map/super/super.c
+++ b/src/map/super/super.c
@@ -28,7 +28,7 @@ static int Super_CommandSupergates ( Abc_Frame_t * pAbc, int argc, char **argv
static int Super_CommandSupergatesAnd( Abc_Frame_t * pAbc, int argc, char **argv );
////////////////////////////////////////////////////////////////////////
-/// FUNCTION DEFITIONS ///
+/// FUNCTION DEFINITIONS ///
////////////////////////////////////////////////////////////////////////
/**Function*************************************************************
@@ -90,20 +90,20 @@ int Super_CommandSupergatesAnd( Abc_Frame_t * pAbc, int argc, char **argv )
nVarsMax = 4;
nLevels = 3;
fVerbose = 0;
- util_getopt_reset();
- while ( (c = util_getopt(argc, argv, "ilvh")) != EOF )
+ Extra_UtilGetoptReset();
+ while ( (c = Extra_UtilGetopt(argc, argv, "ilvh")) != EOF )
{
switch (c)
{
case 'i':
- nVarsMax = atoi(argv[util_optind]);
- util_optind++;
+ nVarsMax = atoi(argv[globalUtilOptind]);
+ globalUtilOptind++;
if ( nVarsMax < 0 )
goto usage;
break;
case 'l':
- nLevels = atoi(argv[util_optind]);
- util_optind++;
+ nLevels = atoi(argv[globalUtilOptind]);
+ globalUtilOptind++;
if ( nLevels < 0 )
goto usage;
break;
@@ -172,44 +172,44 @@ int Super_CommandSupergates( Abc_Frame_t * pAbc, int argc, char **argv )
fWriteOldFormat = 0;
ExcludeFile = 0;
- util_getopt_reset();
- while ( (c = util_getopt(argc, argv, "eiltdasovh")) != EOF )
+ Extra_UtilGetoptReset();
+ while ( (c = Extra_UtilGetopt(argc, argv, "eiltdasovh")) != EOF )
{
switch (c)
{
case 'e':
- ExcludeFile = argv[util_optind];
+ ExcludeFile = argv[globalUtilOptind];
if ( ExcludeFile == 0 )
goto usage;
- util_optind++;
+ globalUtilOptind++;
break;
case 'i':
- nVarsMax = atoi(argv[util_optind]);
- util_optind++;
+ nVarsMax = atoi(argv[globalUtilOptind]);
+ globalUtilOptind++;
if ( nVarsMax < 0 )
goto usage;
break;
case 'l':
- nLevels = atoi(argv[util_optind]);
- util_optind++;
+ nLevels = atoi(argv[globalUtilOptind]);
+ globalUtilOptind++;
if ( nLevels < 0 )
goto usage;
break;
case 't':
- TimeLimit = atoi(argv[util_optind]);
- util_optind++;
+ TimeLimit = atoi(argv[globalUtilOptind]);
+ globalUtilOptind++;
if ( TimeLimit < 0 )
goto usage;
break;
case 'd':
- DelayLimit = (float)atof(argv[util_optind]);
- util_optind++;
+ DelayLimit = (float)atof(argv[globalUtilOptind]);
+ globalUtilOptind++;
if ( DelayLimit <= 0.0 )
goto usage;
break;
case 'a':
- AreaLimit = (float)atof(argv[util_optind]);
- util_optind++;
+ AreaLimit = (float)atof(argv[globalUtilOptind]);
+ globalUtilOptind++;
if ( AreaLimit <= 0.0 )
goto usage;
break;
@@ -231,7 +231,7 @@ int Super_CommandSupergates( Abc_Frame_t * pAbc, int argc, char **argv )
}
- if ( argc != util_optind + 1 )
+ if ( argc != globalUtilOptind + 1 )
{
fprintf( pErr, "The GENLIB library file should be given on the command line.\n" );
goto usage;
@@ -244,9 +244,9 @@ int Super_CommandSupergates( Abc_Frame_t * pAbc, int argc, char **argv )
}
// get the input file name
- FileName = argv[util_optind];
-// if ( (pFile = Io_FileOpen( FileName, "open_path", "r" )) == NULL )
- if ( (pFile = fopen( FileName, "r" )) == NULL )
+ FileName = argv[globalUtilOptind];
+ if ( (pFile = Io_FileOpen( FileName, "open_path", "r", 0 )) == NULL )
+// if ( (pFile = fopen( FileName, "r" )) == NULL )
{
fprintf( pErr, "Cannot open input file \"%s\". ", FileName );
if (( FileName = Extra_FileGetSimilarName( FileName, ".genlib", ".lib", ".gen", ".g", NULL ) ))
diff --git a/src/map/super/super.h b/src/map/super/super.h
index ce2b7433..a7169924 100644
--- a/src/map/super/super.h
+++ b/src/map/super/super.h
@@ -19,6 +19,10 @@
#ifndef __SUPER_H__
#define __SUPER_H__
+#ifdef __cplusplus
+extern "C" {
+#endif
+
////////////////////////////////////////////////////////////////////////
/// INCLUDES ///
////////////////////////////////////////////////////////////////////////
@@ -36,16 +40,21 @@
////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////
-/// MACRO DEFITIONS ///
+/// MACRO DEFINITIONS ///
////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////
-/// FUNCTION DEFITIONS ///
+/// FUNCTION DEFINITIONS ///
////////////////////////////////////////////////////////////////////////
/*=== superCore.c =============================================================*/
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
////////////////////////////////////////////////////////////////////////
/// END OF FILE ///
////////////////////////////////////////////////////////////////////////
-#endif
diff --git a/src/map/super/superAnd.c b/src/map/super/superAnd.c
index e90fc76d..52473fba 100644
--- a/src/map/super/superAnd.c
+++ b/src/map/super/superAnd.c
@@ -61,10 +61,10 @@ struct Super2_GateStruct_t_
// manipulation of complemented attributes
-#define Super2_IsComplement(p) (((int)((long) (p) & 01)))
-#define Super2_Regular(p) ((Super2_Gate_t *)((unsigned)(p) & ~01))
-#define Super2_Not(p) ((Super2_Gate_t *)((long)(p) ^ 01))
-#define Super2_NotCond(p,c) ((Super2_Gate_t *)((long)(p) ^ (c)))
+#define Super2_IsComplement(p) (((int)((unsigned long) (p) & 01)))
+#define Super2_Regular(p) ((Super2_Gate_t *)((unsigned long)(p) & ~01))
+#define Super2_Not(p) ((Super2_Gate_t *)((unsigned long)(p) ^ 01))
+#define Super2_NotCond(p,c) ((Super2_Gate_t *)((unsigned long)(p) ^ (c)))
// iterating through the gates in the library
#define Super2_LibForEachGate( Lib, Gate ) \
@@ -93,7 +93,7 @@ static int Super2_LibWriteCompare( char * pStr1, char * pStr2 );
static int Super2_LibCompareGates( Super2_Gate_t ** ppG1, Super2_Gate_t ** ppG2 );
////////////////////////////////////////////////////////////////////////
-/// FUNCTION DEFITIONS ///
+/// FUNCTION DEFINITIONS ///
////////////////////////////////////////////////////////////////////////
/**Function*************************************************************
@@ -183,7 +183,7 @@ Super2_Man_t * Super2_ManStart()
***********************************************************************/
void Super2_ManStop( Super2_Man_t * pMan )
{
- Extra_MmFixedStop( pMan->pMem, 0 );
+ Extra_MmFixedStop( pMan->pMem );
stmm_free_table( pMan->tTable );
free( pMan );
}
diff --git a/src/map/super/superGENERIC.c b/src/map/super/superGENERIC.c
index 4c7b67ca..1f2b7651 100644
--- a/src/map/super/superGENERIC.c
+++ b/src/map/super/superGENERIC.c
@@ -23,7 +23,7 @@
////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////
-/// FUNCTION DEFITIONS ///
+/// FUNCTION DEFINITIONS ///
////////////////////////////////////////////////////////////////////////
/**Function*************************************************************
diff --git a/src/map/super/superGate.c b/src/map/super/superGate.c
index d0cd0ad7..91a1e513 100644
--- a/src/map/super/superGate.c
+++ b/src/map/super/superGate.c
@@ -120,7 +120,7 @@ static void Super_WriteLibraryTree( Super_Man_t * pMan );
static void Super_WriteLibraryTree_rec( FILE * pFile, Super_Man_t * pMan, Super_Gate_t * pSuper, int * pCounter );
////////////////////////////////////////////////////////////////////////
-/// FUNCTION DEFITIONS ///
+/// FUNCTION DEFINITIONS ///
////////////////////////////////////////////////////////////////////////
/**Function*************************************************************
@@ -886,7 +886,7 @@ Super_Man_t * Super_ManStart()
***********************************************************************/
void Super_ManStop( Super_Man_t * pMan )
{
- Extra_MmFixedStop( pMan->pMem, 0 );
+ Extra_MmFixedStop( pMan->pMem );
if ( pMan->tTable ) stmm_free_table( pMan->tTable );
FREE( pMan->pGates );
free( pMan );
diff --git a/src/map/super/superInt.h b/src/map/super/superInt.h
index 686c8739..ec6d0a38 100644
--- a/src/map/super/superInt.h
+++ b/src/map/super/superInt.h
@@ -43,11 +43,11 @@
////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////
-/// MACRO DEFITIONS ///
+/// MACRO DEFINITIONS ///
////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////
-/// FUNCTION DEFITIONS ///
+/// FUNCTION DEFINITIONS ///
////////////////////////////////////////////////////////////////////////
/*=== superAnd.c =============================================================*/
@@ -55,8 +55,8 @@ extern void Super2_Precompute( int nInputs, int nLevels, int fVerbose );
/*=== superGate.c =============================================================*/
extern void Super_Precompute( Mio_Library_t * pLibGen, int nInputs, int nLevels, float tDelayMax, float tAreaMax, int TimeLimit, bool fSkipInv, bool fWriteOldFormat, int fVerbose );
+#endif
+
////////////////////////////////////////////////////////////////////////
/// END OF FILE ///
////////////////////////////////////////////////////////////////////////
-
-#endif
diff --git a/src/map/super/superWrite.c b/src/map/super/superWrite.c
index a0e85604..395ef145 100644
--- a/src/map/super/superWrite.c
+++ b/src/map/super/superWrite.c
@@ -53,7 +53,7 @@
////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////
-/// FUNCTION DEFITIONS ///
+/// FUNCTION DEFINITIONS ///
////////////////////////////////////////////////////////////////////////
/**Function*************************************************************
diff --git a/src/misc/espresso/cofactor.c b/src/misc/espresso/cofactor.c
new file mode 100644
index 00000000..b851a639
--- /dev/null
+++ b/src/misc/espresso/cofactor.c
@@ -0,0 +1,382 @@
+/*
+ * Revision Control Information
+ *
+ * $Source$
+ * $Author$
+ * $Revision$
+ * $Date$
+ *
+ */
+#include "espresso.h"
+
+/*
+ The cofactor of a cover against a cube "c" is a cover formed by the
+ cofactor of each cube in the cover against c. The cofactor of two
+ cubes is null if they are distance 1 or more apart. If they are
+ distance zero apart, the cofactor is the restriction of the cube
+ to the minterms of c.
+
+ The cube list contains the following information:
+
+ T[0] = pointer to a cube identifying the variables that have
+ been cofactored against
+ T[1] = pointer to just beyond the sentinel (i.e., T[n] in this case)
+ T[2]
+ .
+ . = pointers to cubes
+ .
+ T[n-2]
+ T[n-1] = NULL pointer (sentinel)
+
+
+ Cofactoring involves repeated application of "cdist0" to check if a
+ cube of the cover intersects the cofactored cube. This can be
+ slow, especially for the recursive descent of the espresso
+ routines. Therefore, a special cofactor routine "scofactor" is
+ provided which assumes the cofactor is only in a single variable.
+*/
+
+
+/* cofactor -- compute the cofactor of a cover with respect to a cube */
+pcube *cofactor(T, c)
+IN pcube *T;
+IN register pcube c;
+{
+ pcube temp = cube.temp[0], *Tc_save, *Tc, *T1;
+ register pcube p;
+ int listlen;
+
+ listlen = CUBELISTSIZE(T) + 5;
+
+ /* Allocate a new list of cube pointers (max size is previous size) */
+ Tc_save = Tc = ALLOC(pcube, listlen);
+
+ /* pass on which variables have been cofactored against */
+ *Tc++ = set_or(new_cube(), T[0], set_diff(temp, cube.fullset, c));
+ Tc++;
+
+ /* Loop for each cube in the list, determine suitability, and save */
+ for(T1 = T+2; (p = *T1++) != NULL; ) {
+ if (p != c) {
+
+#ifdef NO_INLINE
+ if (! cdist0(p, c)) goto false;
+#else
+ {register int w,last;register unsigned int x;if((last=cube.inword)!=-1)
+ {x=p[last]&c[last];if(~(x|x>>1)&cube.inmask)goto false;for(w=1;w<last;w++)
+ {x=p[w]&c[w];if(~(x|x>>1)&DISJOINT)goto false;}}}{register int w,var,last;
+ register pcube mask;for(var=cube.num_binary_vars;var<cube.num_vars;var++){
+ mask=cube.var_mask[var];last=cube.last_word[var];for(w=cube.first_word[var
+ ];w<=last;w++)if(p[w]&c[w]&mask[w])goto nextvar;goto false;nextvar:;}}
+#endif
+
+ *Tc++ = p;
+ false: ;
+ }
+ }
+
+ *Tc++ = (pcube) NULL; /* sentinel */
+ Tc_save[1] = (pcube) Tc; /* save pointer to last */
+ return Tc_save;
+}
+
+/*
+ scofactor -- compute the cofactor of a cover with respect to a cube,
+ where the cube is "active" in only a single variable.
+
+ This routine has been optimized for speed.
+*/
+
+pcube *scofactor(T, c, var)
+IN pcube *T, c;
+IN int var;
+{
+ pcube *Tc, *Tc_save;
+ register pcube p, mask = cube.temp[1], *T1;
+ register int first = cube.first_word[var], last = cube.last_word[var];
+ int listlen;
+
+ listlen = CUBELISTSIZE(T) + 5;
+
+ /* Allocate a new list of cube pointers (max size is previous size) */
+ Tc_save = Tc = ALLOC(pcube, listlen);
+
+ /* pass on which variables have been cofactored against */
+ *Tc++ = set_or(new_cube(), T[0], set_diff(mask, cube.fullset, c));
+ Tc++;
+
+ /* Setup for the quick distance check */
+ (void) set_and(mask, cube.var_mask[var], c);
+
+ /* Loop for each cube in the list, determine suitability, and save */
+ for(T1 = T+2; (p = *T1++) != NULL; )
+ if (p != c) {
+ register int i = first;
+ do
+ if (p[i] & mask[i]) {
+ *Tc++ = p;
+ break;
+ }
+ while (++i <= last);
+ }
+
+ *Tc++ = (pcube) NULL; /* sentinel */
+ Tc_save[1] = (pcube) Tc; /* save pointer to last */
+ return Tc_save;
+}
+
+void massive_count(T)
+IN pcube *T;
+{
+ int *count = cdata.part_zeros;
+ pcube *T1;
+
+ /* Clear the column counts (count of # zeros in each column) */
+ { register int i;
+ for(i = cube.size - 1; i >= 0; i--)
+ count[i] = 0;
+ }
+
+ /* Count the number of zeros in each column */
+ { register int i, *cnt;
+ register unsigned int val;
+ register pcube p, cof = T[0], full = cube.fullset;
+ for(T1 = T+2; (p = *T1++) != NULL; )
+ for(i = LOOP(p); i > 0; i--)
+ if (val = full[i] & ~ (p[i] | cof[i])) {
+ cnt = count + ((i-1) << LOGBPI);
+#if BPI == 32
+ if (val & 0xFF000000) {
+ if (val & 0x80000000) cnt[31]++;
+ if (val & 0x40000000) cnt[30]++;
+ if (val & 0x20000000) cnt[29]++;
+ if (val & 0x10000000) cnt[28]++;
+ if (val & 0x08000000) cnt[27]++;
+ if (val & 0x04000000) cnt[26]++;
+ if (val & 0x02000000) cnt[25]++;
+ if (val & 0x01000000) cnt[24]++;
+ }
+ if (val & 0x00FF0000) {
+ if (val & 0x00800000) cnt[23]++;
+ if (val & 0x00400000) cnt[22]++;
+ if (val & 0x00200000) cnt[21]++;
+ if (val & 0x00100000) cnt[20]++;
+ if (val & 0x00080000) cnt[19]++;
+ if (val & 0x00040000) cnt[18]++;
+ if (val & 0x00020000) cnt[17]++;
+ if (val & 0x00010000) cnt[16]++;
+ }
+#endif
+ if (val & 0xFF00) {
+ if (val & 0x8000) cnt[15]++;
+ if (val & 0x4000) cnt[14]++;
+ if (val & 0x2000) cnt[13]++;
+ if (val & 0x1000) cnt[12]++;
+ if (val & 0x0800) cnt[11]++;
+ if (val & 0x0400) cnt[10]++;
+ if (val & 0x0200) cnt[ 9]++;
+ if (val & 0x0100) cnt[ 8]++;
+ }
+ if (val & 0x00FF) {
+ if (val & 0x0080) cnt[ 7]++;
+ if (val & 0x0040) cnt[ 6]++;
+ if (val & 0x0020) cnt[ 5]++;
+ if (val & 0x0010) cnt[ 4]++;
+ if (val & 0x0008) cnt[ 3]++;
+ if (val & 0x0004) cnt[ 2]++;
+ if (val & 0x0002) cnt[ 1]++;
+ if (val & 0x0001) cnt[ 0]++;
+ }
+ }
+ }
+
+ /*
+ * Perform counts for each variable:
+ * cdata.var_zeros[var] = number of zeros in the variable
+ * cdata.parts_active[var] = number of active parts for each variable
+ * cdata.vars_active = number of variables which are active
+ * cdata.vars_unate = number of variables which are active and unate
+ *
+ * best -- the variable which is best for splitting based on:
+ * mostactive -- most # active parts in any variable
+ * mostzero -- most # zeros in any variable
+ * mostbalanced -- minimum over the maximum # zeros / part / variable
+ */
+
+ { register int var, i, lastbit, active, maxactive;
+ int best = -1, mostactive = 0, mostzero = 0, mostbalanced = 32000;
+ cdata.vars_unate = cdata.vars_active = 0;
+
+ for(var = 0; var < cube.num_vars; var++) {
+ if (var < cube.num_binary_vars) { /* special hack for binary vars */
+ i = count[var*2];
+ lastbit = count[var*2 + 1];
+ active = (i > 0) + (lastbit > 0);
+ cdata.var_zeros[var] = i + lastbit;
+ maxactive = MAX(i, lastbit);
+ } else {
+ maxactive = active = cdata.var_zeros[var] = 0;
+ lastbit = cube.last_part[var];
+ for(i = cube.first_part[var]; i <= lastbit; i++) {
+ cdata.var_zeros[var] += count[i];
+ active += (count[i] > 0);
+ if (active > maxactive) maxactive = active;
+ }
+ }
+
+ /* first priority is to maximize the number of active parts */
+ /* for binary case, this will usually select the output first */
+ if (active > mostactive)
+ best = var, mostactive = active, mostzero = cdata.var_zeros[best],
+ mostbalanced = maxactive;
+ else if (active == mostactive)
+ /* secondary condition is to maximize the number zeros */
+ /* for binary variables, this is the same as minimum # of 2's */
+ if (cdata.var_zeros[var] > mostzero)
+ best = var, mostzero = cdata.var_zeros[best],
+ mostbalanced = maxactive;
+ else if (cdata.var_zeros[var] == mostzero)
+ /* third condition is to pick a balanced variable */
+ /* for binary vars, this means roughly equal # 0's and 1's */
+ if (maxactive < mostbalanced)
+ best = var, mostbalanced = maxactive;
+
+ cdata.parts_active[var] = active;
+ cdata.is_unate[var] = (active == 1);
+ cdata.vars_active += (active > 0);
+ cdata.vars_unate += (active == 1);
+ }
+ cdata.best = best;
+ }
+}
+
+int binate_split_select(T, cleft, cright, debug_flag)
+IN pcube *T;
+IN register pcube cleft, cright;
+IN int debug_flag;
+{
+ int best = cdata.best;
+ register int i, lastbit = cube.last_part[best], halfbit = 0;
+ register pcube cof=T[0];
+
+ /* Create the cubes to cofactor against */
+ (void) set_diff(cleft, cube.fullset, cube.var_mask[best]);
+ (void) set_diff(cright, cube.fullset, cube.var_mask[best]);
+ for(i = cube.first_part[best]; i <= lastbit; i++)
+ if (! is_in_set(cof,i))
+ halfbit++;
+ for(i = cube.first_part[best], halfbit = halfbit/2; halfbit > 0; i++)
+ if (! is_in_set(cof,i))
+ halfbit--, set_insert(cleft, i);
+ for(; i <= lastbit; i++)
+ if (! is_in_set(cof,i))
+ set_insert(cright, i);
+
+ if (debug & debug_flag) {
+ (void) printf("BINATE_SPLIT_SELECT: split against %d\n", best);
+ if (verbose_debug)
+ (void) printf("cl=%s\ncr=%s\n", pc1(cleft), pc2(cright));
+ }
+ return best;
+}
+
+
+pcube *cube1list(A)
+pcover A;
+{
+ register pcube last, p, *plist, *list;
+
+ list = plist = ALLOC(pcube, A->count + 3);
+ *plist++ = new_cube();
+ plist++;
+ foreach_set(A, last, p) {
+ *plist++ = p;
+ }
+ *plist++ = NULL; /* sentinel */
+ list[1] = (pcube) plist;
+ return list;
+}
+
+
+pcube *cube2list(A, B)
+pcover A, B;
+{
+ register pcube last, p, *plist, *list;
+
+ list = plist = ALLOC(pcube, A->count + B->count + 3);
+ *plist++ = new_cube();
+ plist++;
+ foreach_set(A, last, p) {
+ *plist++ = p;
+ }
+ foreach_set(B, last, p) {
+ *plist++ = p;
+ }
+ *plist++ = NULL;
+ list[1] = (pcube) plist;
+ return list;
+}
+
+
+pcube *cube3list(A, B, C)
+pcover A, B, C;
+{
+ register pcube last, p, *plist, *list;
+
+ plist = ALLOC(pcube, A->count + B->count + C->count + 3);
+ list = plist;
+ *plist++ = new_cube();
+ plist++;
+ foreach_set(A, last, p) {
+ *plist++ = p;
+ }
+ foreach_set(B, last, p) {
+ *plist++ = p;
+ }
+ foreach_set(C, last, p) {
+ *plist++ = p;
+ }
+ *plist++ = NULL;
+ list[1] = (pcube) plist;
+ return list;
+}
+
+
+pcover cubeunlist(A1)
+pcube *A1;
+{
+ register int i;
+ register pcube p, pdest, cof = A1[0];
+ register pcover A;
+
+ A = new_cover(CUBELISTSIZE(A1));
+ for(i = 2; (p = A1[i]) != NULL; i++) {
+ pdest = GETSET(A, i-2);
+ INLINEset_or(pdest, p, cof);
+ }
+ A->count = CUBELISTSIZE(A1);
+ return A;
+}
+
+simplify_cubelist(T)
+pcube *T;
+{
+ register pcube *Tdest;
+ register int i, ncubes;
+
+ (void) set_copy(cube.temp[0], T[0]); /* retrieve cofactor */
+
+ ncubes = CUBELISTSIZE(T);
+ qsort((char *) (T+2), ncubes, sizeof(pset), (int (*)()) d1_order);
+
+ Tdest = T+2;
+ /* *Tdest++ = T[2]; */
+ for(i = 3; i < ncubes; i++) {
+ if (d1_order(&T[i-1], &T[i]) != 0) {
+ *Tdest++ = T[i];
+ }
+ }
+
+ *Tdest++ = NULL; /* sentinel */
+ Tdest[1] = (pcube) Tdest; /* save pointer to last */
+}
diff --git a/src/misc/espresso/cols.c b/src/misc/espresso/cols.c
new file mode 100644
index 00000000..ec3797e6
--- /dev/null
+++ b/src/misc/espresso/cols.c
@@ -0,0 +1,314 @@
+/*
+ * Revision Control Information
+ *
+ * $Source$
+ * $Author$
+ * $Revision$
+ * $Date$
+ *
+ */
+//#include "port.h"
+#include "sparse_int.h"
+
+
+/*
+ * allocate a new col vector
+ */
+sm_col *
+sm_col_alloc()
+{
+ register sm_col *pcol;
+
+#ifdef FAST_AND_LOOSE
+ if (sm_col_freelist == NIL(sm_col)) {
+ pcol = ALLOC(sm_col, 1);
+ } else {
+ pcol = sm_col_freelist;
+ sm_col_freelist = pcol->next_col;
+ }
+#else
+ pcol = ALLOC(sm_col, 1);
+#endif
+
+ pcol->col_num = 0;
+ pcol->length = 0;
+ pcol->first_row = pcol->last_row = NIL(sm_element);
+ pcol->next_col = pcol->prev_col = NIL(sm_col);
+ pcol->flag = 0;
+ pcol->user_word = NIL(char); /* for our user ... */
+ return pcol;
+}
+
+
+/*
+ * free a col vector -- for FAST_AND_LOOSE, this is real cheap for cols;
+ * however, freeing a rowumn must still walk down the rowumn discarding
+ * the elements one-by-one; that is the only use for the extra '-DCOLS'
+ * compile flag ...
+ */
+void
+sm_col_free(pcol)
+register sm_col *pcol;
+{
+#if defined(FAST_AND_LOOSE) && ! defined(COLS)
+ if (pcol->first_row != NIL(sm_element)) {
+ /* Add the linked list of col items to the free list */
+ pcol->last_row->next_row = sm_element_freelist;
+ sm_element_freelist = pcol->first_row;
+ }
+
+ /* Add the col to the free list of cols */
+ pcol->next_col = sm_col_freelist;
+ sm_col_freelist = pcol;
+#else
+ register sm_element *p, *pnext;
+
+ for(p = pcol->first_row; p != 0; p = pnext) {
+ pnext = p->next_row;
+ sm_element_free(p);
+ }
+ FREE(pcol);
+#endif
+}
+
+
+/*
+ * duplicate an existing col
+ */
+sm_col *
+sm_col_dup(pcol)
+register sm_col *pcol;
+{
+ register sm_col *pnew;
+ register sm_element *p;
+
+ pnew = sm_col_alloc();
+ for(p = pcol->first_row; p != 0; p = p->next_row) {
+ (void) sm_col_insert(pnew, p->row_num);
+ }
+ return pnew;
+}
+
+
+/*
+ * insert an element into a col vector
+ */
+sm_element *
+sm_col_insert(pcol, row)
+register sm_col *pcol;
+register int row;
+{
+ register sm_element *test, *element;
+
+ /* get a new item, save its address */
+ sm_element_alloc(element);
+ test = element;
+ sorted_insert(sm_element, pcol->first_row, pcol->last_row, pcol->length,
+ next_row, prev_row, row_num, row, test);
+
+ /* if item was not used, free it */
+ if (element != test) {
+ sm_element_free(element);
+ }
+
+ /* either way, return the current new value */
+ return test;
+}
+
+
+/*
+ * remove an element from a col vector
+ */
+void
+sm_col_remove(pcol, row)
+register sm_col *pcol;
+register int row;
+{
+ register sm_element *p;
+
+ for(p = pcol->first_row; p != 0 && p->row_num < row; p = p->next_row)
+ ;
+ if (p != 0 && p->row_num == row) {
+ dll_unlink(p, pcol->first_row, pcol->last_row,
+ next_row, prev_row, pcol->length);
+ sm_element_free(p);
+ }
+}
+
+
+/*
+ * find an element (if it is in the col vector)
+ */
+sm_element *
+sm_col_find(pcol, row)
+sm_col *pcol;
+int row;
+{
+ register sm_element *p;
+
+ for(p = pcol->first_row; p != 0 && p->row_num < row; p = p->next_row)
+ ;
+ if (p != 0 && p->row_num == row) {
+ return p;
+ } else {
+ return NIL(sm_element);
+ }
+}
+
+/*
+ * return 1 if col p2 contains col p1; 0 otherwise
+ */
+int
+sm_col_contains(p1, p2)
+sm_col *p1, *p2;
+{
+ register sm_element *q1, *q2;
+
+ q1 = p1->first_row;
+ q2 = p2->first_row;
+ while (q1 != 0) {
+ if (q2 == 0 || q1->row_num < q2->row_num) {
+ return 0;
+ } else if (q1->row_num == q2->row_num) {
+ q1 = q1->next_row;
+ q2 = q2->next_row;
+ } else {
+ q2 = q2->next_row;
+ }
+ }
+ return 1;
+}
+
+
+/*
+ * return 1 if col p1 and col p2 share an element in common
+ */
+int
+sm_col_intersects(p1, p2)
+sm_col *p1, *p2;
+{
+ register sm_element *q1, *q2;
+
+ q1 = p1->first_row;
+ q2 = p2->first_row;
+ if (q1 == 0 || q2 == 0) return 0;
+ for(;;) {
+ if (q1->row_num < q2->row_num) {
+ if ((q1 = q1->next_row) == 0) {
+ return 0;
+ }
+ } else if (q1->row_num > q2->row_num) {
+ if ((q2 = q2->next_row) == 0) {
+ return 0;
+ }
+ } else {
+ return 1;
+ }
+ }
+}
+
+
+/*
+ * compare two cols, lexical ordering
+ */
+int
+sm_col_compare(p1, p2)
+sm_col *p1, *p2;
+{
+ register sm_element *q1, *q2;
+
+ q1 = p1->first_row;
+ q2 = p2->first_row;
+ while(q1 != 0 && q2 != 0) {
+ if (q1->row_num != q2->row_num) {
+ return q1->row_num - q2->row_num;
+ }
+ q1 = q1->next_row;
+ q2 = q2->next_row;
+ }
+
+ if (q1 != 0) {
+ return 1;
+ } else if (q2 != 0) {
+ return -1;
+ } else {
+ return 0;
+ }
+}
+
+
+/*
+ * return the intersection
+ */
+sm_col *
+sm_col_and(p1, p2)
+sm_col *p1, *p2;
+{
+ register sm_element *q1, *q2;
+ register sm_col *result;
+
+ result = sm_col_alloc();
+ q1 = p1->first_row;
+ q2 = p2->first_row;
+ if (q1 == 0 || q2 == 0) return result;
+ for(;;) {
+ if (q1->row_num < q2->row_num) {
+ if ((q1 = q1->next_row) == 0) {
+ return result;
+ }
+ } else if (q1->row_num > q2->row_num) {
+ if ((q2 = q2->next_row) == 0) {
+ return result;
+ }
+ } else {
+ (void) sm_col_insert(result, q1->row_num);
+ if ((q1 = q1->next_row) == 0) {
+ return result;
+ }
+ if ((q2 = q2->next_row) == 0) {
+ return result;
+ }
+ }
+ }
+}
+
+int
+sm_col_hash(pcol, modulus)
+sm_col *pcol;
+int modulus;
+{
+ register int sum;
+ register sm_element *p;
+
+ sum = 0;
+ for(p = pcol->first_row; p != 0; p = p->next_row) {
+ sum = (sum*17 + p->row_num) % modulus;
+ }
+ return sum;
+}
+
+/*
+ * remove an element from a col vector (given a pointer to the element)
+ */
+void
+sm_col_remove_element(pcol, p)
+register sm_col *pcol;
+register sm_element *p;
+{
+ dll_unlink(p, pcol->first_row, pcol->last_row,
+ next_row, prev_row, pcol->length);
+ sm_element_free(p);
+}
+
+
+void
+sm_col_print(fp, pcol)
+FILE *fp;
+sm_col *pcol;
+{
+ sm_element *p;
+
+ for(p = pcol->first_row; p != 0; p = p->next_row) {
+ (void) fprintf(fp, " %d", p->row_num);
+ }
+}
diff --git a/src/misc/espresso/compl.c b/src/misc/espresso/compl.c
new file mode 100644
index 00000000..8f1c6606
--- /dev/null
+++ b/src/misc/espresso/compl.c
@@ -0,0 +1,680 @@
+/*
+ * Revision Control Information
+ *
+ * $Source$
+ * $Author$
+ * $Revision$
+ * $Date$
+ *
+ */
+/*
+ * module: compl.c
+ * purpose: compute the complement of a multiple-valued function
+ *
+ * The "unate recursive paradigm" is used. After a set of special
+ * cases are examined, the function is split on the "most active
+ * variable". These two halves are complemented recursively, and then
+ * the results are merged.
+ *
+ * Changes (from Version 2.1 to Version 2.2)
+ * 1. Minor bug in compl_lifting -- cubes in the left half were
+ * not marked as active, so that when merging a leaf from the left
+ * hand side, the active flags were essentially random. This led
+ * to minor impredictability problem, but never affected the
+ * accuracy of the results.
+ */
+
+#include "espresso.h"
+
+#define USE_COMPL_LIFT 0
+#define USE_COMPL_LIFT_ONSET 1
+#define USE_COMPL_LIFT_ONSET_COMPLEX 2
+#define NO_LIFTING 3
+
+static bool compl_special_cases();
+static pcover compl_merge();
+static void compl_d1merge();
+static pcover compl_cube();
+static void compl_lift();
+static void compl_lift_onset();
+static void compl_lift_onset_complex();
+static bool simp_comp_special_cases();
+static bool simplify_special_cases();
+
+
+/* complement -- compute the complement of T */
+pcover complement(T)
+pcube *T; /* T will be disposed of */
+{
+ register pcube cl, cr;
+ register int best;
+ pcover Tbar, Tl, Tr;
+ int lifting;
+ static int compl_level = 0;
+
+ if (debug & COMPL)
+ debug_print(T, "COMPLEMENT", compl_level++);
+
+ if (compl_special_cases(T, &Tbar) == MAYBE) {
+
+ /* Allocate space for the partition cubes */
+ cl = new_cube();
+ cr = new_cube();
+ best = binate_split_select(T, cl, cr, COMPL);
+
+ /* Complement the left and right halves */
+ Tl = complement(scofactor(T, cl, best));
+ Tr = complement(scofactor(T, cr, best));
+
+ if (Tr->count*Tl->count > (Tr->count+Tl->count)*CUBELISTSIZE(T)) {
+ lifting = USE_COMPL_LIFT_ONSET;
+ } else {
+ lifting = USE_COMPL_LIFT;
+ }
+ Tbar = compl_merge(T, Tl, Tr, cl, cr, best, lifting);
+
+ free_cube(cl);
+ free_cube(cr);
+ free_cubelist(T);
+ }
+
+ if (debug & COMPL)
+ debug1_print(Tbar, "exit COMPLEMENT", --compl_level);
+ return Tbar;
+}
+
+static bool compl_special_cases(T, Tbar)
+pcube *T; /* will be disposed if answer is determined */
+pcover *Tbar; /* returned only if answer determined */
+{
+ register pcube *T1, p, ceil, cof=T[0];
+ pcover A, ceil_compl;
+
+ /* Check for no cubes in the cover */
+ if (T[2] == NULL) {
+ *Tbar = sf_addset(new_cover(1), cube.fullset);
+ free_cubelist(T);
+ return TRUE;
+ }
+
+ /* Check for only a single cube in the cover */
+ if (T[3] == NULL) {
+ *Tbar = compl_cube(set_or(cof, cof, T[2]));
+ free_cubelist(T);
+ return TRUE;
+ }
+
+ /* Check for a row of all 1's (implies complement is null) */
+ for(T1 = T+2; (p = *T1++) != NULL; ) {
+ if (full_row(p, cof)) {
+ *Tbar = new_cover(0);
+ free_cubelist(T);
+ return TRUE;
+ }
+ }
+
+ /* Check for a column of all 0's which can be factored out */
+ ceil = set_save(cof);
+ for(T1 = T+2; (p = *T1++) != NULL; ) {
+ INLINEset_or(ceil, ceil, p);
+ }
+ if (! setp_equal(ceil, cube.fullset)) {
+ ceil_compl = compl_cube(ceil);
+ (void) set_or(cof, cof, set_diff(ceil, cube.fullset, ceil));
+ set_free(ceil);
+ *Tbar = sf_append(complement(T), ceil_compl);
+ return TRUE;
+ }
+ set_free(ceil);
+
+ /* Collect column counts, determine unate variables, etc. */
+ massive_count(T);
+
+ /* If single active variable not factored out above, then tautology ! */
+ if (cdata.vars_active == 1) {
+ *Tbar = new_cover(0);
+ free_cubelist(T);
+ return TRUE;
+
+ /* Check for unate cover */
+ } else if (cdata.vars_unate == cdata.vars_active) {
+ A = map_cover_to_unate(T);
+ free_cubelist(T);
+ A = unate_compl(A);
+ *Tbar = map_unate_to_cover(A);
+ sf_free(A);
+ return TRUE;
+
+ /* Not much we can do about it */
+ } else {
+ return MAYBE;
+ }
+}
+
+/*
+ * compl_merge -- merge the two cofactors around the splitting
+ * variable
+ *
+ * The merge operation involves intersecting each cube of the left
+ * cofactor with cl, and intersecting each cube of the right cofactor
+ * with cr. The union of these two covers is the merged result.
+ *
+ * In order to reduce the number of cubes, a distance-1 merge is
+ * performed (note that two cubes can only combine distance-1 in the
+ * splitting variable). Also, a simple expand is performed in the
+ * splitting variable (simple implies the covering check for the
+ * expansion is not full containment, but single-cube containment).
+ */
+
+static pcover compl_merge(T1, L, R, cl, cr, var, lifting)
+pcube *T1; /* Original ON-set */
+pcover L, R; /* Complement from each recursion branch */
+register pcube cl, cr; /* cubes used for cofactoring */
+int var; /* splitting variable */
+int lifting; /* whether to perform lifting or not */
+{
+ register pcube p, last, pt;
+ pcover T, Tbar;
+ pcube *L1, *R1;
+
+ if (debug & COMPL) {
+ (void) printf("compl_merge: left %d, right %d\n", L->count, R->count);
+ (void) printf("%s (cl)\n%s (cr)\nLeft is\n", pc1(cl), pc2(cr));
+ cprint(L);
+ (void) printf("Right is\n");
+ cprint(R);
+ }
+
+ /* Intersect each cube with the cofactored cube */
+ foreach_set(L, last, p) {
+ INLINEset_and(p, p, cl);
+ SET(p, ACTIVE);
+ }
+ foreach_set(R, last, p) {
+ INLINEset_and(p, p, cr);
+ SET(p, ACTIVE);
+ }
+
+ /* Sort the arrays for a distance-1 merge */
+ (void) set_copy(cube.temp[0], cube.var_mask[var]);
+ qsort((char *) (L1 = sf_list(L)), L->count, sizeof(pset), (int (*)()) d1_order);
+ qsort((char *) (R1 = sf_list(R)), R->count, sizeof(pset), (int (*)()) d1_order);
+
+ /* Perform distance-1 merge */
+ compl_d1merge(L1, R1);
+
+ /* Perform lifting */
+ switch(lifting) {
+ case USE_COMPL_LIFT_ONSET:
+ T = cubeunlist(T1);
+ compl_lift_onset(L1, T, cr, var);
+ compl_lift_onset(R1, T, cl, var);
+ free_cover(T);
+ break;
+ case USE_COMPL_LIFT_ONSET_COMPLEX:
+ T = cubeunlist(T1);
+ compl_lift_onset_complex(L1, T, var);
+ compl_lift_onset_complex(R1, T, var);
+ free_cover(T);
+ break;
+ case USE_COMPL_LIFT:
+ compl_lift(L1, R1, cr, var);
+ compl_lift(R1, L1, cl, var);
+ break;
+ case NO_LIFTING:
+ break;
+ default:
+ ;
+ }
+ FREE(L1);
+ FREE(R1);
+
+ /* Re-create the merged cover */
+ Tbar = new_cover(L->count + R->count);
+ pt = Tbar->data;
+ foreach_set(L, last, p) {
+ INLINEset_copy(pt, p);
+ Tbar->count++;
+ pt += Tbar->wsize;
+ }
+ foreach_active_set(R, last, p) {
+ INLINEset_copy(pt, p);
+ Tbar->count++;
+ pt += Tbar->wsize;
+ }
+
+ if (debug & COMPL) {
+ (void) printf("Result %d\n", Tbar->count);
+ if (verbose_debug)
+ cprint(Tbar);
+ }
+
+ free_cover(L);
+ free_cover(R);
+ return Tbar;
+}
+
+/*
+ * compl_lift_simple -- expand in the splitting variable using single
+ * cube containment against the other recursion branch to check
+ * validity of the expansion, and expanding all (or none) of the
+ * splitting variable.
+ */
+static void compl_lift(A1, B1, bcube, var)
+pcube *A1, *B1, bcube;
+int var;
+{
+ register pcube a, b, *B2, lift=cube.temp[4], liftor=cube.temp[5];
+ pcube mask = cube.var_mask[var];
+
+ (void) set_and(liftor, bcube, mask);
+
+ /* for each cube in the first array ... */
+ for(; (a = *A1++) != NULL; ) {
+ if (TESTP(a, ACTIVE)) {
+
+ /* create a lift of this cube in the merging coord */
+ (void) set_merge(lift, bcube, a, mask);
+
+ /* for each cube in the second array */
+ for(B2 = B1; (b = *B2++) != NULL; ) {
+ INLINEsetp_implies(lift, b, /* when_false => */ continue);
+ /* when_true => fall through to next statement */
+
+ /* cube of A1 was contained by some cube of B1, so raise */
+ INLINEset_or(a, a, liftor);
+ break;
+ }
+ }
+ }
+}
+
+
+
+/*
+ * compl_lift_onset -- expand in the splitting variable using a
+ * distance-1 check against the original on-set; expand all (or
+ * none) of the splitting variable. Each cube of A1 is expanded
+ * against the original on-set T.
+ */
+static void compl_lift_onset(A1, T, bcube, var)
+pcube *A1;
+pcover T;
+pcube bcube;
+int var;
+{
+ register pcube a, last, p, lift=cube.temp[4], mask=cube.var_mask[var];
+
+ /* for each active cube from one branch of the complement */
+ for(; (a = *A1++) != NULL; ) {
+ if (TESTP(a, ACTIVE)) {
+
+ /* create a lift of this cube in the merging coord */
+ INLINEset_and(lift, bcube, mask); /* isolate parts to raise */
+ INLINEset_or(lift, a, lift); /* raise these parts in a */
+
+ /* for each cube in the ON-set, check for intersection */
+ foreach_set(T, last, p) {
+ if (cdist0(p, lift)) {
+ goto nolift;
+ }
+ }
+ INLINEset_copy(a, lift); /* save the raising */
+ SET(a, ACTIVE);
+nolift : ;
+ }
+ }
+}
+
+/*
+ * compl_lift_complex -- expand in the splitting variable, but expand all
+ * parts which can possibly expand.
+ * T is the original ON-set
+ * A1 is either the left or right cofactor
+ */
+static void compl_lift_onset_complex(A1, T, var)
+pcube *A1; /* array of pointers to new result */
+pcover T; /* original ON-set */
+int var; /* which variable we split on */
+{
+ register int dist;
+ register pcube last, p, a, xlower;
+
+ /* for each cube in the complement */
+ xlower = new_cube();
+ for(; (a = *A1++) != NULL; ) {
+
+ if (TESTP(a, ACTIVE)) {
+
+ /* Find which parts of the splitting variable are forced low */
+ INLINEset_clear(xlower, cube.size);
+ foreach_set(T, last, p) {
+ if ((dist = cdist01(p, a)) < 2) {
+ if (dist == 0) {
+ fatal("compl: ON-set and OFF-set are not orthogonal");
+ } else {
+ (void) force_lower(xlower, p, a);
+ }
+ }
+ }
+
+ (void) set_diff(xlower, cube.var_mask[var], xlower);
+ (void) set_or(a, a, xlower);
+ free_cube(xlower);
+ }
+ }
+}
+
+
+
+/*
+ * compl_d1merge -- distance-1 merge in the splitting variable
+ */
+static void compl_d1merge(L1, R1)
+register pcube *L1, *R1;
+{
+ register pcube pl, pr;
+
+ /* Find equal cubes between the two cofactors */
+ for(pl = *L1, pr = *R1; (pl != NULL) && (pr != NULL); )
+ switch (d1_order(L1, R1)) {
+ case 1:
+ pr = *(++R1); break; /* advance right pointer */
+ case -1:
+ pl = *(++L1); break; /* advance left pointer */
+ case 0:
+ RESET(pr, ACTIVE);
+ INLINEset_or(pl, pl, pr);
+ pr = *(++R1);
+ default:
+ ;
+ }
+}
+
+
+
+/* compl_cube -- return the complement of a single cube (De Morgan's law) */
+static pcover compl_cube(p)
+register pcube p;
+{
+ register pcube diff=cube.temp[7], pdest, mask, full=cube.fullset;
+ int var;
+ pcover R;
+
+ /* Allocate worst-case size cover (to avoid checking overflow) */
+ R = new_cover(cube.num_vars);
+
+ /* Compute bit-wise complement of the cube */
+ INLINEset_diff(diff, full, p);
+
+ for(var = 0; var < cube.num_vars; var++) {
+ mask = cube.var_mask[var];
+ /* If the bit-wise complement is not empty in var ... */
+ if (! setp_disjoint(diff, mask)) {
+ pdest = GETSET(R, R->count++);
+ INLINEset_merge(pdest, diff, full, mask);
+ }
+ }
+ return R;
+}
+
+/* simp_comp -- quick simplification of T */
+void simp_comp(T, Tnew, Tbar)
+pcube *T; /* T will be disposed of */
+pcover *Tnew;
+pcover *Tbar;
+{
+ register pcube cl, cr;
+ register int best;
+ pcover Tl, Tr, Tlbar, Trbar;
+ int lifting;
+ static int simplify_level = 0;
+
+ if (debug & COMPL)
+ debug_print(T, "SIMPCOMP", simplify_level++);
+
+ if (simp_comp_special_cases(T, Tnew, Tbar) == MAYBE) {
+
+ /* Allocate space for the partition cubes */
+ cl = new_cube();
+ cr = new_cube();
+ best = binate_split_select(T, cl, cr, COMPL);
+
+ /* Complement the left and right halves */
+ simp_comp(scofactor(T, cl, best), &Tl, &Tlbar);
+ simp_comp(scofactor(T, cr, best), &Tr, &Trbar);
+
+ lifting = USE_COMPL_LIFT;
+ *Tnew = compl_merge(T, Tl, Tr, cl, cr, best, lifting);
+
+ lifting = USE_COMPL_LIFT;
+ *Tbar = compl_merge(T, Tlbar, Trbar, cl, cr, best, lifting);
+
+ /* All of this work for nothing ? Let's hope not ... */
+ if ((*Tnew)->count > CUBELISTSIZE(T)) {
+ sf_free(*Tnew);
+ *Tnew = cubeunlist(T);
+ }
+
+ free_cube(cl);
+ free_cube(cr);
+ free_cubelist(T);
+ }
+
+ if (debug & COMPL) {
+ debug1_print(*Tnew, "exit SIMPCOMP (new)", simplify_level);
+ debug1_print(*Tbar, "exit SIMPCOMP (compl)", simplify_level);
+ simplify_level--;
+ }
+}
+
+static bool simp_comp_special_cases(T, Tnew, Tbar)
+pcube *T; /* will be disposed if answer is determined */
+pcover *Tnew; /* returned only if answer determined */
+pcover *Tbar; /* returned only if answer determined */
+{
+ register pcube *T1, p, ceil, cof=T[0];
+ pcube last;
+ pcover A;
+
+ /* Check for no cubes in the cover (function is empty) */
+ if (T[2] == NULL) {
+ *Tnew = new_cover(1);
+ *Tbar = sf_addset(new_cover(1), cube.fullset);
+ free_cubelist(T);
+ return TRUE;
+ }
+
+ /* Check for only a single cube in the cover */
+ if (T[3] == NULL) {
+ (void) set_or(cof, cof, T[2]);
+ *Tnew = sf_addset(new_cover(1), cof);
+ *Tbar = compl_cube(cof);
+ free_cubelist(T);
+ return TRUE;
+ }
+
+ /* Check for a row of all 1's (function is a tautology) */
+ for(T1 = T+2; (p = *T1++) != NULL; ) {
+ if (full_row(p, cof)) {
+ *Tnew = sf_addset(new_cover(1), cube.fullset);
+ *Tbar = new_cover(1);
+ free_cubelist(T);
+ return TRUE;
+ }
+ }
+
+ /* Check for a column of all 0's which can be factored out */
+ ceil = set_save(cof);
+ for(T1 = T+2; (p = *T1++) != NULL; ) {
+ INLINEset_or(ceil, ceil, p);
+ }
+ if (! setp_equal(ceil, cube.fullset)) {
+ p = new_cube();
+ (void) set_diff(p, cube.fullset, ceil);
+ (void) set_or(cof, cof, p);
+ set_free(p);
+ simp_comp(T, Tnew, Tbar);
+
+ /* Adjust the ON-set */
+ A = *Tnew;
+ foreach_set(A, last, p) {
+ INLINEset_and(p, p, ceil);
+ }
+
+ /* Compute the new complement */
+ *Tbar = sf_append(*Tbar, compl_cube(ceil));
+ set_free(ceil);
+ return TRUE;
+ }
+ set_free(ceil);
+
+ /* Collect column counts, determine unate variables, etc. */
+ massive_count(T);
+
+ /* If single active variable not factored out above, then tautology ! */
+ if (cdata.vars_active == 1) {
+ *Tnew = sf_addset(new_cover(1), cube.fullset);
+ *Tbar = new_cover(1);
+ free_cubelist(T);
+ return TRUE;
+
+ /* Check for unate cover */
+ } else if (cdata.vars_unate == cdata.vars_active) {
+ /* Make the cover minimum by single-cube containment */
+ A = cubeunlist(T);
+ *Tnew = sf_contain(A);
+
+ /* Now form a minimum representation of the complement */
+ A = map_cover_to_unate(T);
+ A = unate_compl(A);
+ *Tbar = map_unate_to_cover(A);
+ sf_free(A);
+ free_cubelist(T);
+ return TRUE;
+
+ /* Not much we can do about it */
+ } else {
+ return MAYBE;
+ }
+}
+
+/* simplify -- quick simplification of T */
+pcover simplify(T)
+pcube *T; /* T will be disposed of */
+{
+ register pcube cl, cr;
+ register int best;
+ pcover Tbar, Tl, Tr;
+ int lifting;
+ static int simplify_level = 0;
+
+ if (debug & COMPL) {
+ debug_print(T, "SIMPLIFY", simplify_level++);
+ }
+
+ if (simplify_special_cases(T, &Tbar) == MAYBE) {
+
+ /* Allocate space for the partition cubes */
+ cl = new_cube();
+ cr = new_cube();
+
+ best = binate_split_select(T, cl, cr, COMPL);
+
+ /* Complement the left and right halves */
+ Tl = simplify(scofactor(T, cl, best));
+ Tr = simplify(scofactor(T, cr, best));
+
+ lifting = USE_COMPL_LIFT;
+ Tbar = compl_merge(T, Tl, Tr, cl, cr, best, lifting);
+
+ /* All of this work for nothing ? Let's hope not ... */
+ if (Tbar->count > CUBELISTSIZE(T)) {
+ sf_free(Tbar);
+ Tbar = cubeunlist(T);
+ }
+
+ free_cube(cl);
+ free_cube(cr);
+ free_cubelist(T);
+ }
+
+ if (debug & COMPL) {
+ debug1_print(Tbar, "exit SIMPLIFY", --simplify_level);
+ }
+ return Tbar;
+}
+
+static bool simplify_special_cases(T, Tnew)
+pcube *T; /* will be disposed if answer is determined */
+pcover *Tnew; /* returned only if answer determined */
+{
+ register pcube *T1, p, ceil, cof=T[0];
+ pcube last;
+ pcover A;
+
+ /* Check for no cubes in the cover */
+ if (T[2] == NULL) {
+ *Tnew = new_cover(0);
+ free_cubelist(T);
+ return TRUE;
+ }
+
+ /* Check for only a single cube in the cover */
+ if (T[3] == NULL) {
+ *Tnew = sf_addset(new_cover(1), set_or(cof, cof, T[2]));
+ free_cubelist(T);
+ return TRUE;
+ }
+
+ /* Check for a row of all 1's (implies function is a tautology) */
+ for(T1 = T+2; (p = *T1++) != NULL; ) {
+ if (full_row(p, cof)) {
+ *Tnew = sf_addset(new_cover(1), cube.fullset);
+ free_cubelist(T);
+ return TRUE;
+ }
+ }
+
+ /* Check for a column of all 0's which can be factored out */
+ ceil = set_save(cof);
+ for(T1 = T+2; (p = *T1++) != NULL; ) {
+ INLINEset_or(ceil, ceil, p);
+ }
+ if (! setp_equal(ceil, cube.fullset)) {
+ p = new_cube();
+ (void) set_diff(p, cube.fullset, ceil);
+ (void) set_or(cof, cof, p);
+ free_cube(p);
+
+ A = simplify(T);
+ foreach_set(A, last, p) {
+ INLINEset_and(p, p, ceil);
+ }
+ *Tnew = A;
+ set_free(ceil);
+ return TRUE;
+ }
+ set_free(ceil);
+
+ /* Collect column counts, determine unate variables, etc. */
+ massive_count(T);
+
+ /* If single active variable not factored out above, then tautology ! */
+ if (cdata.vars_active == 1) {
+ *Tnew = sf_addset(new_cover(1), cube.fullset);
+ free_cubelist(T);
+ return TRUE;
+
+ /* Check for unate cover */
+ } else if (cdata.vars_unate == cdata.vars_active) {
+ A = cubeunlist(T);
+ *Tnew = sf_contain(A);
+ free_cubelist(T);
+ return TRUE;
+
+ /* Not much we can do about it */
+ } else {
+ return MAYBE;
+ }
+}
diff --git a/src/misc/espresso/contain.c b/src/misc/espresso/contain.c
new file mode 100644
index 00000000..180dceb6
--- /dev/null
+++ b/src/misc/espresso/contain.c
@@ -0,0 +1,441 @@
+/*
+ * Revision Control Information
+ *
+ * $Source$
+ * $Author$
+ * $Revision$
+ * $Date$
+ *
+ */
+/*
+ contain.c -- set containment routines
+
+ These are complex routines for performing containment over a
+ family of sets, but they have the advantage of being much faster
+ than a straightforward n*n routine.
+
+ First the cubes are sorted by size, and as a secondary key they are
+ sorted so that if two cubes are equal they end up adjacent. We can
+ than quickly remove equal cubes from further consideration by
+ comparing each cube to its neighbor. Finally, because the cubes
+ are sorted by size, we need only check cubes which are larger (or
+ smaller) than a given cube for containment.
+*/
+
+#include "espresso.h"
+
+
+/*
+ sf_contain -- perform containment on a set family (delete sets which
+ are contained by some larger set in the family). No assumptions are
+ made about A, and the result will be returned in decreasing order of
+ set size.
+*/
+pset_family sf_contain(A)
+INOUT pset_family A; /* disposes of A */
+{
+ int cnt;
+ pset *A1;
+ pset_family R;
+
+ A1 = sf_sort(A, descend); /* sort into descending order */
+ cnt = rm_equal(A1, descend); /* remove duplicates */
+ cnt = rm_contain(A1); /* remove contained sets */
+ R = sf_unlist(A1, cnt, A->sf_size); /* recreate the set family */
+ sf_free(A);
+ return R;
+}
+
+
+/*
+ sf_rev_contain -- perform containment on a set family (delete sets which
+ contain some smaller set in the family). No assumptions are made about
+ A, and the result will be returned in increasing order of set size
+*/
+pset_family sf_rev_contain(A)
+INOUT pset_family A; /* disposes of A */
+{
+ int cnt;
+ pset *A1;
+ pset_family R;
+
+ A1 = sf_sort(A, ascend); /* sort into ascending order */
+ cnt = rm_equal(A1, ascend); /* remove duplicates */
+ cnt = rm_rev_contain(A1); /* remove containing sets */
+ R = sf_unlist(A1, cnt, A->sf_size); /* recreate the set family */
+ sf_free(A);
+ return R;
+}
+
+
+/*
+ sf_ind_contain -- perform containment on a set family (delete sets which
+ are contained by some larger set in the family). No assumptions are
+ made about A, and the result will be returned in decreasing order of
+ set size. Also maintains a set of row_indices to track which rows
+ disappear and how the rows end up permuted.
+*/
+pset_family sf_ind_contain(A, row_indices)
+INOUT pset_family A; /* disposes of A */
+INOUT int *row_indices; /* updated with the new values */
+{
+ int cnt;
+ pset *A1;
+ pset_family R;
+
+ A1 = sf_sort(A, descend); /* sort into descending order */
+ cnt = rm_equal(A1, descend); /* remove duplicates */
+ cnt = rm_contain(A1); /* remove contained sets */
+ R = sf_ind_unlist(A1, cnt, A->sf_size, row_indices, A->data);
+ sf_free(A);
+ return R;
+}
+
+
+/* sf_dupl -- delete duplicate sets in a set family */
+pset_family sf_dupl(A)
+INOUT pset_family A; /* disposes of A */
+{
+ register int cnt;
+ register pset *A1;
+ pset_family R;
+
+ A1 = sf_sort(A, descend); /* sort the set family */
+ cnt = rm_equal(A1, descend); /* remove duplicates */
+ R = sf_unlist(A1, cnt, A->sf_size); /* recreate the set family */
+ sf_free(A);
+ return R;
+}
+
+
+/*
+ sf_union -- form the contained union of two set families (delete
+ sets which are contained by some larger set in the family). A and
+ B are assumed already sorted in decreasing order of set size (and
+ the SIZE field is assumed to contain the set size), and the result
+ will be returned sorted likewise.
+*/
+pset_family sf_union(A, B)
+INOUT pset_family A, B; /* disposes of A and B */
+{
+ int cnt;
+ pset_family R;
+ pset *A1 = sf_list(A), *B1 = sf_list(B), *E1;
+
+ E1 = ALLOC(pset, MAX(A->count, B->count) + 1);
+ cnt = rm2_equal(A1, B1, E1, descend);
+ cnt += rm2_contain(A1, B1) + rm2_contain(B1, A1);
+ R = sf_merge(A1, B1, E1, cnt, A->sf_size);
+ sf_free(A); sf_free(B);
+ return R;
+}
+
+
+/*
+ dist_merge -- consider all sets to be "or"-ed with "mask" and then
+ delete duplicates from the set family.
+*/
+pset_family dist_merge(A, mask)
+INOUT pset_family A; /* disposes of A */
+IN pset mask; /* defines variables to mask out */
+{
+ pset *A1;
+ int cnt;
+ pset_family R;
+
+ (void) set_copy(cube.temp[0], mask);
+ A1 = sf_sort(A, d1_order);
+ cnt = d1_rm_equal(A1, d1_order);
+ R = sf_unlist(A1, cnt, A->sf_size);
+ sf_free(A);
+ return R;
+}
+
+
+/*
+ d1merge -- perform an efficient distance-1 merge of cubes of A
+*/
+pset_family d1merge(A, var)
+INOUT pset_family A; /* disposes of A */
+IN int var;
+{
+ return dist_merge(A, cube.var_mask[var]);
+}
+
+
+
+/* d1_rm_equal -- distance-1 merge (merge cubes which are equal under a mask) */
+int d1_rm_equal(A1, compare)
+register pset *A1; /* array of set pointers */
+int (*compare)(); /* comparison function */
+{
+ register int i, j, dest;
+
+ dest = 0;
+ if (A1[0] != (pcube) NULL) {
+ for(i = 0, j = 1; A1[j] != (pcube) NULL; j++)
+ if ( (*compare)(&A1[i], &A1[j]) == 0) {
+ /* if sets are equal (under the mask) merge them */
+ (void) set_or(A1[i], A1[i], A1[j]);
+ } else {
+ /* sets are unequal, so save the set i */
+ A1[dest++] = A1[i];
+ i = j;
+ }
+ A1[dest++] = A1[i];
+ }
+ A1[dest] = (pcube) NULL;
+ return dest;
+}
+
+
+/* rm_equal -- scan a sorted array of set pointers for duplicate sets */
+int rm_equal(A1, compare)
+INOUT pset *A1; /* updated in place */
+IN int (*compare)();
+{
+ register pset *p, *pdest = A1;
+
+ if (*A1 != NULL) { /* If more than one set */
+ for(p = A1+1; *p != NULL; p++)
+ if ((*compare)(p, p-1) != 0)
+ *pdest++ = *(p-1);
+ *pdest++ = *(p-1);
+ *pdest = NULL;
+ }
+ return pdest - A1;
+}
+
+
+/* rm_contain -- perform containment over a sorted array of set pointers */
+int rm_contain(A1)
+INOUT pset *A1; /* updated in place */
+{
+ register pset *pa, *pb, *pcheck, a, b;
+ pset *pdest = A1;
+ int last_size = -1;
+
+ /* Loop for all cubes of A1 */
+ for(pa = A1; (a = *pa++) != NULL; ) {
+ /* Update the check pointer if the size has changed */
+ if (SIZE(a) != last_size)
+ last_size = SIZE(a), pcheck = pdest;
+ for(pb = A1; pb != pcheck; ) {
+ b = *pb++;
+ INLINEsetp_implies(a, b, /* when_false => */ continue);
+ goto lnext1;
+ }
+ /* set a was not contained by some larger set, so save it */
+ *pdest++ = a;
+ lnext1: ;
+ }
+
+ *pdest = NULL;
+ return pdest - A1;
+}
+
+
+/* rm_rev_contain -- perform rcontainment over a sorted array of set pointers */
+int rm_rev_contain(A1)
+INOUT pset *A1; /* updated in place */
+{
+ register pset *pa, *pb, *pcheck, a, b;
+ pset *pdest = A1;
+ int last_size = -1;
+
+ /* Loop for all cubes of A1 */
+ for(pa = A1; (a = *pa++) != NULL; ) {
+ /* Update the check pointer if the size has changed */
+ if (SIZE(a) != last_size)
+ last_size = SIZE(a), pcheck = pdest;
+ for(pb = A1; pb != pcheck; ) {
+ b = *pb++;
+ INLINEsetp_implies(b, a, /* when_false => */ continue);
+ goto lnext1;
+ }
+ /* the set a did not contain some smaller set, so save it */
+ *pdest++ = a;
+ lnext1: ;
+ }
+
+ *pdest = NULL;
+ return pdest - A1;
+}
+
+
+/* rm2_equal -- check two sorted arrays of set pointers for equal cubes */
+int rm2_equal(A1, B1, E1, compare)
+INOUT register pset *A1, *B1; /* updated in place */
+OUT pset *E1;
+IN int (*compare)();
+{
+ register pset *pda = A1, *pdb = B1, *pde = E1;
+
+ /* Walk through the arrays advancing pointer to larger cube */
+ for(; *A1 != NULL && *B1 != NULL; )
+ switch((*compare)(A1, B1)) {
+ case -1: /* "a" comes before "b" */
+ *pda++ = *A1++; break;
+ case 0: /* equal cubes */
+ *pde++ = *A1++; B1++; break;
+ case 1: /* "a" is to follow "b" */
+ *pdb++ = *B1++; break;
+ }
+
+ /* Finish moving down the pointers of A and B */
+ while (*A1 != NULL)
+ *pda++ = *A1++;
+ while (*B1 != NULL)
+ *pdb++ = *B1++;
+ *pda = *pdb = *pde = NULL;
+
+ return pde - E1;
+}
+
+
+/* rm2_contain -- perform containment between two arrays of set pointers */
+int rm2_contain(A1, B1)
+INOUT pset *A1; /* updated in place */
+IN pset *B1; /* unchanged */
+{
+ register pset *pa, *pb, a, b, *pdest = A1;
+
+ /* for each set in the first array ... */
+ for(pa = A1; (a = *pa++) != NULL; ) {
+ /* for each set in the second array which is larger ... */
+ for(pb = B1; (b = *pb++) != NULL && SIZE(b) > SIZE(a); ) {
+ INLINEsetp_implies(a, b, /* when_false => */ continue);
+ /* set was contained in some set of B, so don't save pointer */
+ goto lnext1;
+ }
+ /* set wasn't contained in any set of B, so save the pointer */
+ *pdest++ = a;
+ lnext1: ;
+ }
+
+ *pdest = NULL; /* sentinel */
+ return pdest - A1; /* # elements in A1 */
+}
+
+
+
+/* sf_sort -- sort the sets of A */
+pset *sf_sort(A, compare)
+IN pset_family A;
+IN int (*compare)();
+{
+ register pset p, last, *pdest, *A1;
+
+ /* Create a single array pointing to each cube of A */
+ pdest = A1 = ALLOC(pset, A->count + 1);
+ foreach_set(A, last, p) {
+ PUTSIZE(p, set_ord(p)); /* compute the set size */
+ *pdest++ = p; /* save the pointer */
+ }
+ *pdest = NULL; /* Sentinel -- never seen by sort */
+
+ /* Sort cubes by size */
+ qsort((char *) A1, A->count, sizeof(pset), compare);
+ return A1;
+}
+
+
+/* sf_list -- make a list of pointers to the sets in a set family */
+pset *sf_list(A)
+IN register pset_family A;
+{
+ register pset p, last, *pdest, *A1;
+
+ /* Create a single array pointing to each cube of A */
+ pdest = A1 = ALLOC(pset, A->count + 1);
+ foreach_set(A, last, p)
+ *pdest++ = p; /* save the pointer */
+ *pdest = NULL; /* Sentinel */
+ return A1;
+}
+
+
+/* sf_unlist -- make a set family out of a list of pointers to sets */
+pset_family sf_unlist(A1, totcnt, size)
+IN pset *A1;
+IN int totcnt, size;
+{
+ register pset pr, p, *pa;
+ pset_family R = sf_new(totcnt, size);
+
+ R->count = totcnt;
+ for(pr = R->data, pa = A1; (p = *pa++) != NULL; pr += R->wsize)
+ INLINEset_copy(pr, p);
+ FREE(A1);
+ return R;
+}
+
+
+/* sf_ind_unlist -- make a set family out of a list of pointers to sets */
+pset_family sf_ind_unlist(A1, totcnt, size, row_indices, pfirst)
+IN pset *A1;
+IN int totcnt, size;
+INOUT int *row_indices;
+IN register pset pfirst;
+{
+ register pset pr, p, *pa;
+ register int i, *new_row_indices;
+ pset_family R = sf_new(totcnt, size);
+
+ R->count = totcnt;
+ new_row_indices = ALLOC(int, totcnt);
+ for(pr = R->data, pa = A1, i=0; (p = *pa++) != NULL; pr += R->wsize, i++) {
+ INLINEset_copy(pr, p);
+ new_row_indices[i] = row_indices[(p - pfirst)/R->wsize];
+ }
+ for(i = 0; i < totcnt; i++)
+ row_indices[i] = new_row_indices[i];
+ FREE(new_row_indices);
+ FREE(A1);
+ return R;
+}
+
+
+/* sf_merge -- merge three sorted lists of set pointers */
+pset_family sf_merge(A1, B1, E1, totcnt, size)
+INOUT pset *A1, *B1, *E1; /* will be disposed of */
+IN int totcnt, size;
+{
+ register pset pr, ps, *pmin, *pmid, *pmax;
+ pset_family R;
+ pset *temp[3], *swap;
+ int i, j, n;
+
+ /* Allocate the result set_family */
+ R = sf_new(totcnt, size);
+ R->count = totcnt;
+ pr = R->data;
+
+ /* Quick bubble sort to order the top member of the three arrays */
+ n = 3; temp[0] = A1; temp[1] = B1; temp[2] = E1;
+ for(i = 0; i < n-1; i++)
+ for(j = i+1; j < n; j++)
+ if (desc1(*temp[i], *temp[j]) > 0) {
+ swap = temp[j];
+ temp[j] = temp[i];
+ temp[i] = swap;
+ }
+ pmin = temp[0]; pmid = temp[1]; pmax = temp[2];
+
+ /* Save the minimum element, then update pmin, pmid, pmax */
+ while (*pmin != (pset) NULL) {
+ ps = *pmin++;
+ INLINEset_copy(pr, ps);
+ pr += R->wsize;
+ if (desc1(*pmin, *pmax) > 0) {
+ swap = pmax; pmax = pmin; pmin = pmid; pmid = swap;
+ } else if (desc1(*pmin, *pmid) > 0) {
+ swap = pmin; pmin = pmid; pmid = swap;
+ }
+ }
+
+ FREE(A1);
+ FREE(B1);
+ FREE(E1);
+ return R;
+}
diff --git a/src/misc/espresso/cubehack.c b/src/misc/espresso/cubehack.c
new file mode 100644
index 00000000..8e1724fc
--- /dev/null
+++ b/src/misc/espresso/cubehack.c
@@ -0,0 +1,138 @@
+/*
+ * Revision Control Information
+ *
+ * $Source: /vol/opua/opua2/sis/sis-1.1/common/src/sis/node/RCS/cubehack.c,v $
+ * $Author: sis $
+ * $Revision: 1.2 $
+ * $Date: 1992/05/06 18:57:41 $
+ *
+ */
+/*
+#include "sis.h"
+#include "node_int.h"
+
+#ifdef lint
+struct cube_struct cube;
+bool summary;
+bool trace;
+bool remove_essential;
+bool force_irredundant;
+bool unwrap_onset;
+bool single_expand;
+bool pos;
+bool recompute_onset;
+bool use_super_gasp;
+bool use_random_order;
+#endif
+*/
+#include "espresso.h"
+
+
+void
+cautious_define_cube_size(n)
+int n;
+{
+ if (cube.fullset != 0 && cube.num_binary_vars == n)
+ return;
+ if (cube.fullset != 0) {
+ setdown_cube();
+ FREE(cube.part_size);
+ }
+ cube.num_binary_vars = cube.num_vars = n;
+ cube.part_size = ALLOC(int, n);
+ cube_setup();
+}
+
+
+void
+define_cube_size(n)
+int n;
+{
+ register int q, i;
+ static int called_before = 0;
+
+ /* check if the cube is already just the right size */
+ if (cube.fullset != 0 && cube.num_binary_vars == n && cube.num_vars == n)
+ return;
+
+ /* We can't handle more than 100 inputs */
+ if (n > 100) {
+ cautious_define_cube_size(n);
+ called_before = 0;
+ return;
+ }
+
+ if (cube.fullset == 0 || ! called_before) {
+ cautious_define_cube_size(100);
+ called_before = 1;
+ }
+
+ cube.num_vars = n;
+ cube.num_binary_vars = n;
+ cube.num_mv_vars = 0;
+ cube.output = -1;
+ cube.size = n * 2;
+
+ /* first_part, last_part, first_word, last_word, part_size OKAY */
+ /* cube.sparse is OKAY */
+
+ /* need to completely re-make cube.fullset and cube.binary_mask */
+ (void) set_fill(cube.fullset, n*2);
+ (void) set_fill(cube.binary_mask, n*2);
+
+ /* need to resize each set in cube.var_mask and cube.temp */
+ q = cube.fullset[0];
+ for(i = 0; i < cube.num_vars; i++)
+ cube.var_mask[i][0] = q;
+ for(i = 0; i < CUBE_TEMP; i++)
+ cube.temp[i][0] = q;
+
+ /* need to resize cube.emptyset and cube.mv_mask */
+ cube.emptyset[0] = q;
+ cube.mv_mask[0] = q;
+
+ /* need to reset the inword and inmask */
+ if (cube.num_binary_vars != 0) {
+ cube.inword = cube.last_word[cube.num_binary_vars - 1];
+ cube.inmask = cube.binary_mask[cube.inword] & DISJOINT;
+ } else {
+ cube.inword = -1;
+ cube.inmask = 0;
+ }
+
+ /* cdata (entire structure) is OKAY */
+}
+
+
+void
+undefine_cube_size()
+{
+ if (cube.num_binary_vars > 100) {
+ if (cube.fullset != 0) {
+ setdown_cube();
+ FREE(cube.part_size);
+ }
+ } else {
+ cube.num_vars = cube.num_binary_vars = 100;
+ if (cube.fullset != 0) {
+ setdown_cube();
+ FREE(cube.part_size);
+ }
+ }
+}
+
+
+void
+set_espresso_flags()
+{
+ summary = FALSE;
+ trace = FALSE;
+ remove_essential = TRUE;
+ force_irredundant = TRUE;
+ unwrap_onset = TRUE;
+ single_expand = FALSE;
+ pos = FALSE;
+ recompute_onset = FALSE;
+ use_super_gasp = FALSE;
+ use_random_order = FALSE;
+}
diff --git a/src/misc/espresso/cubestr.c b/src/misc/espresso/cubestr.c
new file mode 100644
index 00000000..77389e73
--- /dev/null
+++ b/src/misc/espresso/cubestr.c
@@ -0,0 +1,152 @@
+/*
+ * Revision Control Information
+ *
+ * $Source$
+ * $Author$
+ * $Revision$
+ * $Date$
+ *
+ */
+/*
+ Module: cubestr.c -- routines for managing the global cube structure
+*/
+
+#include "espresso.h"
+
+/*
+ cube_setup -- assume that the fields "num_vars", "num_binary_vars", and
+ part_size[num_binary_vars .. num_vars-1] are setup, and initialize the
+ rest of cube and cdata.
+
+ If a part_size is < 0, then the field size is abs(part_size) and the
+ field read from the input is symbolic.
+*/
+void cube_setup()
+{
+ register int i, var;
+ register pcube p;
+
+ if (cube.num_binary_vars < 0 || cube.num_vars < cube.num_binary_vars)
+ fatal("cube size is silly, error in .i/.o or .mv");
+
+ cube.num_mv_vars = cube.num_vars - cube.num_binary_vars;
+ cube.output = cube.num_mv_vars > 0 ? cube.num_vars - 1 : -1;
+
+ cube.size = 0;
+ cube.first_part = ALLOC(int, cube.num_vars);
+ cube.last_part = ALLOC(int, cube.num_vars);
+ cube.first_word = ALLOC(int, cube.num_vars);
+ cube.last_word = ALLOC(int, cube.num_vars);
+ for(var = 0; var < cube.num_vars; var++) {
+ if (var < cube.num_binary_vars)
+ cube.part_size[var] = 2;
+ cube.first_part[var] = cube.size;
+ cube.first_word[var] = WHICH_WORD(cube.size);
+ cube.size += ABS(cube.part_size[var]);
+ cube.last_part[var] = cube.size - 1;
+ cube.last_word[var] = WHICH_WORD(cube.size - 1);
+ }
+
+ cube.var_mask = ALLOC(pset, cube.num_vars);
+ cube.sparse = ALLOC(int, cube.num_vars);
+ cube.binary_mask = new_cube();
+ cube.mv_mask = new_cube();
+ for(var = 0; var < cube.num_vars; var++) {
+ p = cube.var_mask[var] = new_cube();
+ for(i = cube.first_part[var]; i <= cube.last_part[var]; i++)
+ set_insert(p, i);
+ if (var < cube.num_binary_vars) {
+ INLINEset_or(cube.binary_mask, cube.binary_mask, p);
+ cube.sparse[var] = 0;
+ } else {
+ INLINEset_or(cube.mv_mask, cube.mv_mask, p);
+ cube.sparse[var] = 1;
+ }
+ }
+ if (cube.num_binary_vars == 0)
+ cube.inword = -1;
+ else {
+ cube.inword = cube.last_word[cube.num_binary_vars - 1];
+ cube.inmask = cube.binary_mask[cube.inword] & DISJOINT;
+ }
+
+ cube.temp = ALLOC(pset, CUBE_TEMP);
+ for(i = 0; i < CUBE_TEMP; i++)
+ cube.temp[i] = new_cube();
+ cube.fullset = set_fill(new_cube(), cube.size);
+ cube.emptyset = new_cube();
+
+ cdata.part_zeros = ALLOC(int, cube.size);
+ cdata.var_zeros = ALLOC(int, cube.num_vars);
+ cdata.parts_active = ALLOC(int, cube.num_vars);
+ cdata.is_unate = ALLOC(int, cube.num_vars);
+}
+
+/*
+ setdown_cube -- free memory allocated for the cube/cdata structs
+ (free's all but the part_size array)
+
+ (I wanted to call this cube_setdown, but that violates the 8-character
+ external routine limit on the IBM !)
+*/
+void setdown_cube()
+{
+ register int i, var;
+
+ FREE(cube.first_part);
+ FREE(cube.last_part);
+ FREE(cube.first_word);
+ FREE(cube.last_word);
+ FREE(cube.sparse);
+
+ free_cube(cube.binary_mask);
+ free_cube(cube.mv_mask);
+ free_cube(cube.fullset);
+ free_cube(cube.emptyset);
+ for(var = 0; var < cube.num_vars; var++)
+ free_cube(cube.var_mask[var]);
+ FREE(cube.var_mask);
+
+ for(i = 0; i < CUBE_TEMP; i++)
+ free_cube(cube.temp[i]);
+ FREE(cube.temp);
+
+ FREE(cdata.part_zeros);
+ FREE(cdata.var_zeros);
+ FREE(cdata.parts_active);
+ FREE(cdata.is_unate);
+
+ cube.first_part = cube.last_part = (int *) NULL;
+ cube.first_word = cube.last_word = (int *) NULL;
+ cube.sparse = (int *) NULL;
+ cube.binary_mask = cube.mv_mask = (pcube) NULL;
+ cube.fullset = cube.emptyset = (pcube) NULL;
+ cube.var_mask = cube.temp = (pcube *) NULL;
+
+ cdata.part_zeros = cdata.var_zeros = cdata.parts_active = (int *) NULL;
+ cdata.is_unate = (bool *) NULL;
+}
+
+
+void save_cube_struct()
+{
+ temp_cube_save = cube; /* structure copy ! */
+ temp_cdata_save = cdata; /* "" */
+
+ cube.first_part = cube.last_part = (int *) NULL;
+ cube.first_word = cube.last_word = (int *) NULL;
+ cube.part_size = (int *) NULL;
+ cube.binary_mask = cube.mv_mask = (pcube) NULL;
+ cube.fullset = cube.emptyset = (pcube) NULL;
+ cube.var_mask = cube.temp = (pcube *) NULL;
+
+ cdata.part_zeros = cdata.var_zeros = cdata.parts_active = (int *) NULL;
+ cdata.is_unate = (bool *) NULL;
+}
+
+
+void restore_cube_struct()
+{
+ cube = temp_cube_save; /* structure copy ! */
+ cdata = temp_cdata_save; /* "" */
+}
diff --git a/src/misc/espresso/cvrin.c b/src/misc/espresso/cvrin.c
new file mode 100644
index 00000000..7790b38b
--- /dev/null
+++ b/src/misc/espresso/cvrin.c
@@ -0,0 +1,810 @@
+/*
+ * Revision Control Information
+ *
+ * $Source$
+ * $Author$
+ * $Revision$
+ * $Date$
+ *
+ */
+/*
+ module: cvrin.c
+ purpose: cube and cover input routines
+*/
+
+#include "espresso.h"
+
+static bool line_length_error;
+static int lineno;
+
+void skip_line(fpin, fpout, echo)
+register FILE *fpin, *fpout;
+register bool echo;
+{
+ register int ch;
+ while ((ch=getc(fpin)) != EOF && ch != '\n')
+ if (echo)
+ putc(ch, fpout);
+ if (echo)
+ putc('\n', fpout);
+ lineno++;
+}
+
+char *get_word(fp, word)
+register FILE *fp;
+register char *word;
+{
+ register int ch, i = 0;
+ while ((ch = getc(fp)) != EOF && isspace(ch))
+ ;
+ word[i++] = ch;
+ while ((ch = getc(fp)) != EOF && ! isspace(ch))
+ word[i++] = ch;
+ word[i++] = '\0';
+ return word;
+}
+
+/*
+ * Yes, I know this routine is a mess
+ */
+void read_cube(fp, PLA)
+register FILE *fp;
+pPLA PLA;
+{
+ register int var, i;
+ pcube cf = cube.temp[0], cr = cube.temp[1], cd = cube.temp[2];
+ bool savef = FALSE, saved = FALSE, saver = FALSE;
+ char token[256]; /* for kiss read hack */
+ int varx, first, last, offset; /* for kiss read hack */
+
+ set_clear(cf, cube.size);
+
+ /* Loop and read binary variables */
+ for(var = 0; var < cube.num_binary_vars; var++)
+ switch(getc(fp)) {
+ case EOF:
+ goto bad_char;
+ case '\n':
+ if (! line_length_error)
+ (void) fprintf(stderr, "product term(s) %s\n",
+ "span more than one line (warning only)");
+ line_length_error = TRUE;
+ lineno++;
+ var--;
+ break;
+ case ' ': case '|': case '\t':
+ var--;
+ break;
+ case '2': case '-':
+ set_insert(cf, var*2+1);
+ case '0':
+ set_insert(cf, var*2);
+ break;
+ case '1':
+ set_insert(cf, var*2+1);
+ break;
+ case '?':
+ break;
+ default:
+ goto bad_char;
+ }
+
+
+ /* Loop for the all but one of the multiple-valued variables */
+ for(var = cube.num_binary_vars; var < cube.num_vars-1; var++)
+
+ /* Read a symbolic multiple-valued variable */
+ if (cube.part_size[var] < 0) {
+ (void) fscanf(fp, "%s", token);
+ if (equal(token, "-") || equal(token, "ANY")) {
+ if (kiss && var == cube.num_vars - 2) {
+ /* leave it empty */
+ } else {
+ /* make it full */
+ set_or(cf, cf, cube.var_mask[var]);
+ }
+ } else if (equal(token, "~")) {
+ ;
+ /* leave it empty ... (?) */
+ } else {
+ if (kiss && var == cube.num_vars - 2)
+ varx = var - 1, offset = ABS(cube.part_size[var-1]);
+ else
+ varx = var, offset = 0;
+ /* Find the symbolic label in the label table */
+ first = cube.first_part[varx];
+ last = cube.last_part[varx];
+ for(i = first; i <= last; i++)
+ if (PLA->label[i] == (char *) NULL) {
+ PLA->label[i] = util_strsav(token); /* add new label */
+ set_insert(cf, i+offset);
+ break;
+ } else if (equal(PLA->label[i], token)) {
+ set_insert(cf, i+offset); /* use column i */
+ break;
+ }
+ if (i > last) {
+ (void) fprintf(stderr,
+"declared size of variable %d (counting from variable 0) is too small\n", var);
+ exit(-1);
+ }
+ }
+
+ } else for(i = cube.first_part[var]; i <= cube.last_part[var]; i++)
+ switch (getc(fp)) {
+ case EOF:
+ goto bad_char;
+ case '\n':
+ if (! line_length_error)
+ (void) fprintf(stderr, "product term(s) %s\n",
+ "span more than one line (warning only)");
+ line_length_error = TRUE;
+ lineno++;
+ i--;
+ break;
+ case ' ': case '|': case '\t':
+ i--;
+ break;
+ case '1':
+ set_insert(cf, i);
+ case '0':
+ break;
+ default:
+ goto bad_char;
+ }
+
+ /* Loop for last multiple-valued variable */
+ if (kiss) {
+ saver = savef = TRUE;
+ (void) set_xor(cr, cf, cube.var_mask[cube.num_vars - 2]);
+ } else
+ set_copy(cr, cf);
+ set_copy(cd, cf);
+ for(i = cube.first_part[var]; i <= cube.last_part[var]; i++)
+ switch (getc(fp)) {
+ case EOF:
+ goto bad_char;
+ case '\n':
+ if (! line_length_error)
+ (void) fprintf(stderr, "product term(s) %s\n",
+ "span more than one line (warning only)");
+ line_length_error = TRUE;
+ lineno++;
+ i--;
+ break;
+ case ' ': case '|': case '\t':
+ i--;
+ break;
+ case '4': case '1':
+ if (PLA->pla_type & F_type)
+ set_insert(cf, i), savef = TRUE;
+ break;
+ case '3': case '0':
+ if (PLA->pla_type & R_type)
+ set_insert(cr, i), saver = TRUE;
+ break;
+ case '2': case '-':
+ if (PLA->pla_type & D_type)
+ set_insert(cd, i), saved = TRUE;
+ case '~':
+ break;
+ default:
+ goto bad_char;
+ }
+ if (savef) PLA->F = sf_addset(PLA->F, cf);
+ if (saved) PLA->D = sf_addset(PLA->D, cd);
+ if (saver) PLA->R = sf_addset(PLA->R, cr);
+ return;
+
+bad_char:
+ (void) fprintf(stderr, "(warning): input line #%d ignored\n", lineno);
+ skip_line(fp, stdout, TRUE);
+ return;
+}
+void parse_pla(fp, PLA)
+IN FILE *fp;
+INOUT pPLA PLA;
+{
+ int i, var, ch, np, last;
+ char word[256];
+
+ lineno = 1;
+ line_length_error = FALSE;
+
+loop:
+ switch(ch = getc(fp)) {
+ case EOF:
+ return;
+
+ case '\n':
+ lineno++;
+
+ case ' ': case '\t': case '\f': case '\r':
+ break;
+
+ case '#':
+ (void) ungetc(ch, fp);
+ skip_line(fp, stdout, echo_comments);
+ break;
+
+ case '.':
+ /* .i gives the cube input size (binary-functions only) */
+ if (equal(get_word(fp, word), "i")) {
+ if (cube.fullset != NULL) {
+ (void) fprintf(stderr, "extra .i ignored\n");
+ skip_line(fp, stdout, /* echo */ FALSE);
+ } else {
+ if (fscanf(fp, "%d", &cube.num_binary_vars) != 1)
+ fatal("error reading .i");
+ cube.num_vars = cube.num_binary_vars + 1;
+ cube.part_size = ALLOC(int, cube.num_vars);
+ }
+
+ /* .o gives the cube output size (binary-functions only) */
+ } else if (equal(word, "o")) {
+ if (cube.fullset != NULL) {
+ (void) fprintf(stderr, "extra .o ignored\n");
+ skip_line(fp, stdout, /* echo */ FALSE);
+ } else {
+ if (cube.part_size == NULL)
+ fatal(".o cannot appear before .i");
+ if (fscanf(fp, "%d", &(cube.part_size[cube.num_vars-1]))!=1)
+ fatal("error reading .o");
+ cube_setup();
+ PLA_labels(PLA);
+ }
+
+ /* .mv gives the cube size for a multiple-valued function */
+ } else if (equal(word, "mv")) {
+ if (cube.fullset != NULL) {
+ (void) fprintf(stderr, "extra .mv ignored\n");
+ skip_line(fp, stdout, /* echo */ FALSE);
+ } else {
+ if (cube.part_size != NULL)
+ fatal("cannot mix .i and .mv");
+ if (fscanf(fp,"%d %d",
+ &cube.num_vars,&cube.num_binary_vars) != 2)
+ fatal("error reading .mv");
+ if (cube.num_binary_vars < 0)
+fatal("num_binary_vars (second field of .mv) cannot be negative");
+ if (cube.num_vars < cube.num_binary_vars)
+ fatal(
+"num_vars (1st field of .mv) must exceed num_binary_vars (2nd field of .mv)");
+ cube.part_size = ALLOC(int, cube.num_vars);
+ for(var=cube.num_binary_vars; var < cube.num_vars; var++)
+ if (fscanf(fp, "%d", &(cube.part_size[var])) != 1)
+ fatal("error reading .mv");
+ cube_setup();
+ PLA_labels(PLA);
+ }
+
+ /* .p gives the number of product terms -- we ignore it */
+ } else if (equal(word, "p"))
+ (void) fscanf(fp, "%d", &np);
+ /* .e and .end specify the end of the file */
+ else if (equal(word, "e") || equal(word,"end")) {
+ if (cube.fullset == NULL) {
+ /* fatal("unknown PLA size, need .i/.o or .mv");*/
+ } else if (PLA->F == NULL) {
+ PLA->F = new_cover(10);
+ PLA->D = new_cover(10);
+ PLA->R = new_cover(10);
+ }
+ return;
+ }
+ /* .kiss turns on the kiss-hack option */
+ else if (equal(word, "kiss"))
+ kiss = TRUE;
+
+ /* .type specifies a logical type for the PLA */
+ else if (equal(word, "type")) {
+ (void) get_word(fp, word);
+ for(i = 0; pla_types[i].key != 0; i++)
+ if (equal(pla_types[i].key + 1, word)) {
+ PLA->pla_type = pla_types[i].value;
+ break;
+ }
+ if (pla_types[i].key == 0)
+ fatal("unknown type in .type command");
+
+ /* parse the labels */
+ } else if (equal(word, "ilb")) {
+ if (cube.fullset == NULL)
+ fatal("PLA size must be declared before .ilb or .ob");
+ if (PLA->label == NULL)
+ PLA_labels(PLA);
+ for(var = 0; var < cube.num_binary_vars; var++) {
+ (void) get_word(fp, word);
+ i = cube.first_part[var];
+ PLA->label[i+1] = util_strsav(word);
+ PLA->label[i] = ALLOC(char, strlen(word) + 6);
+ (void) sprintf(PLA->label[i], "%s.bar", word);
+ }
+ } else if (equal(word, "ob")) {
+ if (cube.fullset == NULL)
+ fatal("PLA size must be declared before .ilb or .ob");
+ if (PLA->label == NULL)
+ PLA_labels(PLA);
+ var = cube.num_vars - 1;
+ for(i = cube.first_part[var]; i <= cube.last_part[var]; i++) {
+ (void) get_word(fp, word);
+ PLA->label[i] = util_strsav(word);
+ }
+ /* .label assigns labels to multiple-valued variables */
+ } else if (equal(word, "label")) {
+ if (cube.fullset == NULL)
+ fatal("PLA size must be declared before .label");
+ if (PLA->label == NULL)
+ PLA_labels(PLA);
+ if (fscanf(fp, "var=%d", &var) != 1)
+ fatal("Error reading labels");
+ for(i = cube.first_part[var]; i <= cube.last_part[var]; i++) {
+ (void) get_word(fp, word);
+ PLA->label[i] = util_strsav(word);
+ }
+
+ } else if (equal(word, "symbolic")) {
+ symbolic_t *newlist, *p1;
+ if (read_symbolic(fp, PLA, word, &newlist)) {
+ if (PLA->symbolic == NIL(symbolic_t)) {
+ PLA->symbolic = newlist;
+ } else {
+ for(p1=PLA->symbolic;p1->next!=NIL(symbolic_t);
+ p1=p1->next){
+ }
+ p1->next = newlist;
+ }
+ } else {
+ fatal("error reading .symbolic");
+ }
+
+ } else if (equal(word, "symbolic-output")) {
+ symbolic_t *newlist, *p1;
+ if (read_symbolic(fp, PLA, word, &newlist)) {
+ if (PLA->symbolic_output == NIL(symbolic_t)) {
+ PLA->symbolic_output = newlist;
+ } else {
+ for(p1=PLA->symbolic_output;p1->next!=NIL(symbolic_t);
+ p1=p1->next){
+ }
+ p1->next = newlist;
+ }
+ } else {
+ fatal("error reading .symbolic-output");
+ }
+
+ /* .phase allows a choice of output phases */
+ } else if (equal(word, "phase")) {
+ if (cube.fullset == NULL)
+ fatal("PLA size must be declared before .phase");
+ if (PLA->phase != NULL) {
+ (void) fprintf(stderr, "extra .phase ignored\n");
+ skip_line(fp, stdout, /* echo */ FALSE);
+ } else {
+ do ch = getc(fp); while (ch == ' ' || ch == '\t');
+ (void) ungetc(ch, fp);
+ PLA->phase = set_save(cube.fullset);
+ last = cube.last_part[cube.num_vars - 1];
+ for(i=cube.first_part[cube.num_vars - 1]; i <= last; i++)
+ if ((ch = getc(fp)) == '0')
+ set_remove(PLA->phase, i);
+ else if (ch != '1')
+ fatal("only 0 or 1 allowed in phase description");
+ }
+
+ /* .pair allows for bit-pairing input variables */
+ } else if (equal(word, "pair")) {
+ int j;
+ if (PLA->pair != NULL) {
+ (void) fprintf(stderr, "extra .pair ignored\n");
+ } else {
+ ppair pair;
+ PLA->pair = pair = ALLOC(pair_t, 1);
+ if (fscanf(fp, "%d", &(pair->cnt)) != 1)
+ fatal("syntax error in .pair");
+ pair->var1 = ALLOC(int, pair->cnt);
+ pair->var2 = ALLOC(int, pair->cnt);
+ for(i = 0; i < pair->cnt; i++) {
+ (void) get_word(fp, word);
+ if (word[0] == '(') (void) strcpy(word, word+1);
+ if (label_index(PLA, word, &var, &j)) {
+ pair->var1[i] = var+1;
+ } else {
+ fatal("syntax error in .pair");
+ }
+
+ (void) get_word(fp, word);
+ if (word[strlen(word)-1] == ')') {
+ word[strlen(word)-1]='\0';
+ }
+ if (label_index(PLA, word, &var, &j)) {
+ pair->var2[i] = var+1;
+ } else {
+ fatal("syntax error in .pair");
+ }
+ }
+ }
+
+ } else {
+ if (echo_unknown_commands)
+ printf("%c%s ", ch, word);
+ skip_line(fp, stdout, echo_unknown_commands);
+ }
+ break;
+ default:
+ (void) ungetc(ch, fp);
+ if (cube.fullset == NULL) {
+/* fatal("unknown PLA size, need .i/.o or .mv");*/
+ if (echo_comments)
+ putchar('#');
+ skip_line(fp, stdout, echo_comments);
+ break;
+ }
+ if (PLA->F == NULL) {
+ PLA->F = new_cover(10);
+ PLA->D = new_cover(10);
+ PLA->R = new_cover(10);
+ }
+ read_cube(fp, PLA);
+ }
+ goto loop;
+}
+/*
+ read_pla -- read a PLA from a file
+
+ Input stops when ".e" is encountered in the input file, or upon reaching
+ end of file.
+
+ Returns the PLA in the variable PLA after massaging the "symbolic"
+ representation into a positional cube notation of the ON-set, OFF-set,
+ and the DC-set.
+
+ needs_dcset and needs_offset control the computation of the OFF-set
+ and DC-set (i.e., if either needs to be computed, then it will be
+ computed via complement only if the corresponding option is TRUE.)
+ pla_type specifies the interpretation to be used when reading the
+ PLA.
+
+ The phase of the output functions is adjusted according to the
+ global option "pos" or according to an imbedded .phase option in
+ the input file. Note that either phase option implies that the
+ OFF-set be computed regardless of whether the caller needs it
+ explicitly or not.
+
+ Bit pairing of the binary variables is performed according to an
+ imbedded .pair option in the input file.
+
+ The global cube structure also reflects the sizes of the PLA which
+ was just read. If these fields have already been set, then any
+ subsequent PLA must conform to these sizes.
+
+ The global flags trace and summary control the output produced
+ during the read.
+
+ Returns a status code as a result:
+ EOF (-1) : End of file reached before any data was read
+ > 0 : Operation successful
+*/
+
+int read_pla(fp, needs_dcset, needs_offset, pla_type, PLA_return)
+IN FILE *fp;
+IN bool needs_dcset, needs_offset;
+IN int pla_type;
+OUT pPLA *PLA_return;
+{
+ pPLA PLA;
+ int i, second, third;
+ long time;
+ cost_t cost;
+
+ /* Allocate and initialize the PLA structure */
+ PLA = *PLA_return = new_PLA();
+ PLA->pla_type = pla_type;
+
+ /* Read the pla */
+ time = ptime();
+ parse_pla(fp, PLA);
+
+ /* Check for nothing on the file -- implies reached EOF */
+ if (PLA->F == NULL) {
+ return EOF;
+ }
+
+ /* This hack merges the next-state field with the outputs */
+ for(i = 0; i < cube.num_vars; i++) {
+ cube.part_size[i] = ABS(cube.part_size[i]);
+ }
+ if (kiss) {
+ third = cube.num_vars - 3;
+ second = cube.num_vars - 2;
+ if (cube.part_size[third] != cube.part_size[second]) {
+ (void) fprintf(stderr," with .kiss option, third to last and second\n");
+ (void) fprintf(stderr, "to last variables must be the same size.\n");
+ return EOF;
+ }
+ for(i = 0; i < cube.part_size[second]; i++) {
+ PLA->label[i + cube.first_part[second]] =
+ util_strsav(PLA->label[i + cube.first_part[third]]);
+ }
+ cube.part_size[second] += cube.part_size[cube.num_vars-1];
+ cube.num_vars--;
+ setdown_cube();
+ cube_setup();
+ }
+
+ if (trace) {
+ totals(time, READ_TIME, PLA->F, &cost);
+ }
+
+ /* Decide how to break PLA into ON-set, OFF-set and DC-set */
+ time = ptime();
+ if (pos || PLA->phase != NULL || PLA->symbolic_output != NIL(symbolic_t)) {
+ needs_offset = TRUE;
+ }
+ if (needs_offset && (PLA->pla_type==F_type || PLA->pla_type==FD_type)) {
+ free_cover(PLA->R);
+ PLA->R = complement(cube2list(PLA->F, PLA->D));
+ } else if (needs_dcset && PLA->pla_type == FR_type) {
+ pcover X;
+ free_cover(PLA->D);
+ /* hack, why not? */
+ X = d1merge(sf_join(PLA->F, PLA->R), cube.num_vars - 1);
+ PLA->D = complement(cube1list(X));
+ free_cover(X);
+ } else if (PLA->pla_type == R_type || PLA->pla_type == DR_type) {
+ free_cover(PLA->F);
+ PLA->F = complement(cube2list(PLA->D, PLA->R));
+ }
+
+ if (trace) {
+ totals(time, COMPL_TIME, PLA->R, &cost);
+ }
+
+ /* Check for phase rearrangement of the functions */
+ if (pos) {
+ pcover onset = PLA->F;
+ PLA->F = PLA->R;
+ PLA->R = onset;
+ PLA->phase = new_cube();
+ set_diff(PLA->phase, cube.fullset, cube.var_mask[cube.num_vars-1]);
+ } else if (PLA->phase != NULL) {
+ (void) set_phase(PLA);
+ }
+
+ /* Setup minimization for two-bit decoders */
+ if (PLA->pair != (ppair) NULL) {
+ set_pair(PLA);
+ }
+
+ if (PLA->symbolic != NIL(symbolic_t)) {
+ EXEC(map_symbolic(PLA), "MAP-INPUT ", PLA->F);
+ }
+ if (PLA->symbolic_output != NIL(symbolic_t)) {
+ EXEC(map_output_symbolic(PLA), "MAP-OUTPUT ", PLA->F);
+ if (needs_offset) {
+ free_cover(PLA->R);
+EXECUTE(PLA->R=complement(cube2list(PLA->F,PLA->D)), COMPL_TIME, PLA->R, cost);
+ }
+ }
+
+ return 1;
+}
+
+void PLA_summary(PLA)
+pPLA PLA;
+{
+ int var, i;
+ symbolic_list_t *p2;
+ symbolic_t *p1;
+
+ printf("# PLA is %s", PLA->filename);
+ if (cube.num_binary_vars == cube.num_vars - 1)
+ printf(" with %d inputs and %d outputs\n",
+ cube.num_binary_vars, cube.part_size[cube.num_vars - 1]);
+ else {
+ printf(" with %d variables (%d binary, mv sizes",
+ cube.num_vars, cube.num_binary_vars);
+ for(var = cube.num_binary_vars; var < cube.num_vars; var++)
+ printf(" %d", cube.part_size[var]);
+ printf(")\n");
+ }
+ printf("# ON-set cost is %s\n", print_cost(PLA->F));
+ printf("# OFF-set cost is %s\n", print_cost(PLA->R));
+ printf("# DC-set cost is %s\n", print_cost(PLA->D));
+ if (PLA->phase != NULL)
+ printf("# phase is %s\n", pc1(PLA->phase));
+ if (PLA->pair != NULL) {
+ printf("# two-bit decoders:");
+ for(i = 0; i < PLA->pair->cnt; i++)
+ printf(" (%d %d)", PLA->pair->var1[i], PLA->pair->var2[i]);
+ printf("\n");
+ }
+ if (PLA->symbolic != NIL(symbolic_t)) {
+ for(p1 = PLA->symbolic; p1 != NIL(symbolic_t); p1 = p1->next) {
+ printf("# symbolic: ");
+ for(p2=p1->symbolic_list; p2!=NIL(symbolic_list_t); p2=p2->next) {
+ printf(" %d", p2->variable);
+ }
+ printf("\n");
+ }
+ }
+ if (PLA->symbolic_output != NIL(symbolic_t)) {
+ for(p1 = PLA->symbolic_output; p1 != NIL(symbolic_t); p1 = p1->next) {
+ printf("# output symbolic: ");
+ for(p2=p1->symbolic_list; p2!=NIL(symbolic_list_t); p2=p2->next) {
+ printf(" %d", p2->pos);
+ }
+ printf("\n");
+ }
+ }
+ (void) fflush(stdout);
+}
+
+
+pPLA new_PLA()
+{
+ pPLA PLA;
+
+ PLA = ALLOC(PLA_t, 1);
+ PLA->F = PLA->D = PLA->R = (pcover) NULL;
+ PLA->phase = (pcube) NULL;
+ PLA->pair = (ppair) NULL;
+ PLA->label = (char **) NULL;
+ PLA->filename = (char *) NULL;
+ PLA->pla_type = 0;
+ PLA->symbolic = NIL(symbolic_t);
+ PLA->symbolic_output = NIL(symbolic_t);
+ return PLA;
+}
+
+
+PLA_labels(PLA)
+pPLA PLA;
+{
+ int i;
+
+ PLA->label = ALLOC(char *, cube.size);
+ for(i = 0; i < cube.size; i++)
+ PLA->label[i] = (char *) NULL;
+}
+
+
+void free_PLA(PLA)
+pPLA PLA;
+{
+ symbolic_list_t *p2, *p2next;
+ symbolic_t *p1, *p1next;
+ int i;
+
+ if (PLA->F != (pcover) NULL)
+ free_cover(PLA->F);
+ if (PLA->R != (pcover) NULL)
+ free_cover(PLA->R);
+ if (PLA->D != (pcover) NULL)
+ free_cover(PLA->D);
+ if (PLA->phase != (pcube) NULL)
+ free_cube(PLA->phase);
+ if (PLA->pair != (ppair) NULL) {
+ FREE(PLA->pair->var1);
+ FREE(PLA->pair->var2);
+ FREE(PLA->pair);
+ }
+ if (PLA->label != NULL) {
+ for(i = 0; i < cube.size; i++)
+ if (PLA->label[i] != NULL)
+ FREE(PLA->label[i]);
+ FREE(PLA->label);
+ }
+ if (PLA->filename != NULL) {
+ FREE(PLA->filename);
+ }
+ for(p1 = PLA->symbolic; p1 != NIL(symbolic_t); p1 = p1next) {
+ for(p2 = p1->symbolic_list; p2 != NIL(symbolic_list_t); p2 = p2next) {
+ p2next = p2->next;
+ FREE(p2);
+ }
+ p1next = p1->next;
+ FREE(p1);
+ }
+ PLA->symbolic = NIL(symbolic_t);
+ for(p1 = PLA->symbolic_output; p1 != NIL(symbolic_t); p1 = p1next) {
+ for(p2 = p1->symbolic_list; p2 != NIL(symbolic_list_t); p2 = p2next) {
+ p2next = p2->next;
+ FREE(p2);
+ }
+ p1next = p1->next;
+ FREE(p1);
+ }
+ PLA->symbolic_output = NIL(symbolic_t);
+ FREE(PLA);
+}
+
+
+int read_symbolic(fp, PLA, word, retval)
+FILE *fp;
+pPLA PLA;
+char *word; /* scratch string for words */
+symbolic_t **retval;
+{
+ symbolic_list_t *listp, *prev_listp;
+ symbolic_label_t *labelp, *prev_labelp;
+ symbolic_t *newlist;
+ int i, var;
+
+ newlist = ALLOC(symbolic_t, 1);
+ newlist->next = NIL(symbolic_t);
+ newlist->symbolic_list = NIL(symbolic_list_t);
+ newlist->symbolic_list_length = 0;
+ newlist->symbolic_label = NIL(symbolic_label_t);
+ newlist->symbolic_label_length = 0;
+ prev_listp = NIL(symbolic_list_t);
+ prev_labelp = NIL(symbolic_label_t);
+
+ for(;;) {
+ (void) get_word(fp, word);
+ if (equal(word, ";"))
+ break;
+ if (label_index(PLA, word, &var, &i)) {
+ listp = ALLOC(symbolic_list_t, 1);
+ listp->variable = var;
+ listp->pos = i;
+ listp->next = NIL(symbolic_list_t);
+ if (prev_listp == NIL(symbolic_list_t)) {
+ newlist->symbolic_list = listp;
+ } else {
+ prev_listp->next = listp;
+ }
+ prev_listp = listp;
+ newlist->symbolic_list_length++;
+ } else {
+ return FALSE;
+ }
+ }
+
+ for(;;) {
+ (void) get_word(fp, word);
+ if (equal(word, ";"))
+ break;
+ labelp = ALLOC(symbolic_label_t, 1);
+ labelp->label = util_strsav(word);
+ labelp->next = NIL(symbolic_label_t);
+ if (prev_labelp == NIL(symbolic_label_t)) {
+ newlist->symbolic_label = labelp;
+ } else {
+ prev_labelp->next = labelp;
+ }
+ prev_labelp = labelp;
+ newlist->symbolic_label_length++;
+ }
+
+ *retval = newlist;
+ return TRUE;
+}
+
+
+int label_index(PLA, word, varp, ip)
+pPLA PLA;
+char *word;
+int *varp;
+int *ip;
+{
+ int var, i;
+
+ if (PLA->label == NIL(char *) || PLA->label[0] == NIL(char)) {
+ if (sscanf(word, "%d", varp) == 1) {
+ *ip = *varp;
+ return TRUE;
+ }
+ } else {
+ for(var = 0; var < cube.num_vars; var++) {
+ for(i = 0; i < cube.part_size[var]; i++) {
+ if (equal(PLA->label[cube.first_part[var]+i], word)) {
+ *varp = var;
+ *ip = i;
+ return TRUE;
+ }
+ }
+ }
+ }
+ return FALSE;
+}
diff --git a/src/misc/espresso/cvrm.c b/src/misc/espresso/cvrm.c
new file mode 100644
index 00000000..7d42d6e3
--- /dev/null
+++ b/src/misc/espresso/cvrm.c
@@ -0,0 +1,539 @@
+/*
+ * Revision Control Information
+ *
+ * $Source$
+ * $Author$
+ * $Revision$
+ * $Date$
+ *
+ */
+/*
+ module: cvrm.c
+ Purpose: miscellaneous cover manipulation
+ a) verify two covers are equal, check consistency of a cover
+ b) unravel a multiple-valued cover into minterms
+ c) sort covers
+*/
+
+#include "espresso.h"
+
+
+static void cb_unravel(c, start, end, startbase, B1)
+IN register pcube c;
+IN int start, end;
+IN pcube startbase;
+INOUT pcover B1;
+{
+ pcube base = cube.temp[0], p, last;
+ int expansion, place, skip, var, size, offset;
+ register int i, j, k, n;
+
+ /* Determine how many cubes it will blow up into, and create a mask
+ for those parts that have only a single coordinate
+ */
+ expansion = 1;
+ (void) set_copy(base, startbase);
+ for(var = start; var <= end; var++) {
+ if ((size = set_dist(c, cube.var_mask[var])) < 2) {
+ (void) set_or(base, base, cube.var_mask[var]);
+ } else {
+ expansion *= size;
+ }
+ }
+ (void) set_and(base, c, base);
+
+ /* Add the unravelled sets starting at the last element of B1 */
+ offset = B1->count;
+ B1->count += expansion;
+ foreach_remaining_set(B1, last, GETSET(B1, offset-1), p) {
+ INLINEset_copy(p, base);
+ }
+
+ place = expansion;
+ for(var = start; var <= end; var++) {
+ if ((size = set_dist(c, cube.var_mask[var])) > 1) {
+ skip = place;
+ place = place / size;
+ n = 0;
+ for(i = cube.first_part[var]; i <= cube.last_part[var]; i++) {
+ if (is_in_set(c, i)) {
+ for(j = n; j < expansion; j += skip) {
+ for(k = 0; k < place; k++) {
+ p = GETSET(B1, j+k+offset);
+ (void) set_insert(p, i);
+ }
+ }
+ n += place;
+ }
+ }
+ }
+ }
+}
+
+
+pcover unravel_range(B, start, end)
+IN pcover B;
+IN int start, end;
+{
+ pcover B1;
+ int var, total_size, expansion, size;
+ register pcube p, last, startbase = cube.temp[1];
+
+ /* Create the starting base for those variables not being unravelled */
+ (void) set_copy(startbase, cube.emptyset);
+ for(var = 0; var < start; var++)
+ (void) set_or(startbase, startbase, cube.var_mask[var]);
+ for(var = end+1; var < cube.num_vars; var++)
+ (void) set_or(startbase, startbase, cube.var_mask[var]);
+
+ /* Determine how many cubes it will blow up into */
+ total_size = 0;
+ foreach_set(B, last, p) {
+ expansion = 1;
+ for(var = start; var <= end; var++)
+ if ((size = set_dist(p, cube.var_mask[var])) >= 2)
+ if ((expansion *= size) > 1000000)
+ fatal("unreasonable expansion in unravel");
+ total_size += expansion;
+ }
+
+ /* We can now allocate a cover of exactly the correct size */
+ B1 = new_cover(total_size);
+ foreach_set(B, last, p) {
+ cb_unravel(p, start, end, startbase, B1);
+ }
+ free_cover(B);
+ return B1;
+}
+
+
+pcover unravel(B, start)
+IN pcover B;
+IN int start;
+{
+ return unravel_range(B, start, cube.num_vars-1);
+}
+
+/* lex_sort -- sort cubes in a standard lexical fashion */
+pcover lex_sort(T)
+pcover T;
+{
+ pcover T1 = sf_unlist(sf_sort(T, lex_order), T->count, T->sf_size);
+ free_cover(T);
+ return T1;
+}
+
+
+/* size_sort -- sort cubes by their size */
+pcover size_sort(T)
+pcover T;
+{
+ pcover T1 = sf_unlist(sf_sort(T, descend), T->count, T->sf_size);
+ free_cover(T);
+ return T1;
+}
+
+
+/* mini_sort -- sort cubes according to the heuristics of mini */
+pcover mini_sort(F, compare)
+pcover F;
+int (*compare)();
+{
+ register int *count, cnt, n = cube.size, i;
+ register pcube p, last;
+ pcover F_sorted;
+ pcube *F1;
+
+ /* Perform a column sum over the set family */
+ count = sf_count(F);
+
+ /* weight is "inner product of the cube and the column sums" */
+ foreach_set(F, last, p) {
+ cnt = 0;
+ for(i = 0; i < n; i++)
+ if (is_in_set(p, i))
+ cnt += count[i];
+ PUTSIZE(p, cnt);
+ }
+ FREE(count);
+
+ /* use qsort to sort the array */
+ qsort((char *) (F1 = sf_list(F)), F->count, sizeof(pcube), compare);
+ F_sorted = sf_unlist(F1, F->count, F->sf_size);
+ free_cover(F);
+
+ return F_sorted;
+}
+
+
+/* sort_reduce -- Espresso strategy for ordering the cubes before reduction */
+pcover sort_reduce(T)
+IN pcover T;
+{
+ register pcube p, last, largest = NULL;
+ register int bestsize = -1, size, n = cube.num_vars;
+ pcover T_sorted;
+ pcube *T1;
+
+ if (T->count == 0)
+ return T;
+
+ /* find largest cube */
+ foreach_set(T, last, p)
+ if ((size = set_ord(p)) > bestsize)
+ largest = p, bestsize = size;
+
+ foreach_set(T, last, p)
+ PUTSIZE(p, ((n - cdist(largest,p)) << 7) + MIN(set_ord(p),127));
+
+ qsort((char *) (T1 = sf_list(T)), T->count, sizeof(pcube), (int (*)()) descend);
+ T_sorted = sf_unlist(T1, T->count, T->sf_size);
+ free_cover(T);
+
+ return T_sorted;
+}
+
+pcover random_order(F)
+register pcover F;
+{
+ pset temp;
+ register int i, k;
+#ifdef RANDOM
+ long random();
+#endif
+
+ temp = set_new(F->sf_size);
+ for(i = F->count - 1; i > 0; i--) {
+ /* Choose a random number between 0 and i */
+#ifdef RANDOM
+ k = random() % i;
+#else
+ /* this is not meant to be really used; just provides an easy
+ "out" if random() and srandom() aren't around
+ */
+ k = (i*23 + 997) % i;
+#endif
+ /* swap sets i and k */
+ (void) set_copy(temp, GETSET(F, k));
+ (void) set_copy(GETSET(F, k), GETSET(F, i));
+ (void) set_copy(GETSET(F, i), temp);
+ }
+ set_free(temp);
+ return F;
+}
+
+/*
+ * cubelist_partition -- take a cubelist T and see if it has any components;
+ * if so, return cubelist's of the two partitions A and B; the return value
+ * is the size of the partition; if not, A and B
+ * are undefined and the return value is 0
+ */
+int cubelist_partition(T, A, B, comp_debug)
+pcube *T; /* a list of cubes */
+pcube **A, **B; /* cubelist of partition and remainder */
+unsigned int comp_debug;
+{
+ register pcube *T1, p, seed, cof;
+ pcube *A1, *B1;
+ bool change;
+ int count, numcube;
+
+ numcube = CUBELISTSIZE(T);
+
+ /* Mark all cubes -- covered cubes belong to the partition */
+ for(T1 = T+2; (p = *T1++) != NULL; ) {
+ RESET(p, COVERED);
+ }
+
+ /*
+ * Extract a partition from the cubelist T; start with the first cube as a
+ * seed, and then pull in all cubes which share a variable with the seed;
+ * iterate until no new cubes are brought into the partition.
+ */
+ seed = set_save(T[2]);
+ cof = T[0];
+ SET(T[2], COVERED);
+ count = 1;
+
+ do {
+ change = FALSE;
+ for(T1 = T+2; (p = *T1++) != NULL; ) {
+ if (! TESTP(p, COVERED) && ccommon(p, seed, cof)) {
+ INLINEset_and(seed, seed, p);
+ SET(p, COVERED);
+ change = TRUE;
+ count++;
+ }
+
+ }
+ } while (change);
+
+ set_free(seed);
+
+ if (comp_debug) {
+ (void) printf("COMPONENT_REDUCTION: split into %d %d\n",
+ count, numcube - count);
+ }
+
+ if (count != numcube) {
+ /* Allocate and setup the cubelist's for the two partitions */
+ *A = A1 = ALLOC(pcube, numcube+3);
+ *B = B1 = ALLOC(pcube, numcube+3);
+ (*A)[0] = set_save(T[0]);
+ (*B)[0] = set_save(T[0]);
+ A1 = *A + 2;
+ B1 = *B + 2;
+
+ /* Loop over the cubes in T and distribute to A and B */
+ for(T1 = T+2; (p = *T1++) != NULL; ) {
+ if (TESTP(p, COVERED)) {
+ *A1++ = p;
+ } else {
+ *B1++ = p;
+ }
+ }
+
+ /* Stuff needed at the end of the cubelist's */
+ *A1++ = NULL;
+ (*A)[1] = (pcube) A1;
+ *B1++ = NULL;
+ (*B)[1] = (pcube) B1;
+ }
+
+ return numcube - count;
+}
+
+/*
+ * quick cofactor against a single output function
+ */
+pcover cof_output(T, i)
+pcover T;
+register int i;
+{
+ pcover T1;
+ register pcube p, last, pdest, mask;
+
+ mask = cube.var_mask[cube.output];
+ T1 = new_cover(T->count);
+ foreach_set(T, last, p) {
+ if (is_in_set(p, i)) {
+ pdest = GETSET(T1, T1->count++);
+ INLINEset_or(pdest, p, mask);
+ RESET(pdest, PRIME);
+ }
+ }
+ return T1;
+}
+
+
+/*
+ * quick intersection against a single output function
+ */
+pcover uncof_output(T, i)
+pcover T;
+int i;
+{
+ register pcube p, last, mask;
+
+ if (T == NULL) {
+ return T;
+ }
+
+ mask = cube.var_mask[cube.output];
+ foreach_set(T, last, p) {
+ INLINEset_diff(p, p, mask);
+ set_insert(p, i);
+ }
+ return T;
+}
+
+
+/*
+ * A generic routine to perform an operation for each output function
+ *
+ * func() is called with a PLA for each output function (with the output
+ * part effectively removed).
+ * func1() is called after reforming the equivalent output function
+ *
+ * Each function returns TRUE if process is to continue
+ */
+foreach_output_function(PLA, func, func1)
+pPLA PLA;
+int (*func)();
+int (*func1)();
+{
+ pPLA PLA1;
+ int i;
+
+ /* Loop for each output function */
+ for(i = 0; i < cube.part_size[cube.output]; i++) {
+
+ /* cofactor on the output part */
+ PLA1 = new_PLA();
+ PLA1->F = cof_output(PLA->F, i + cube.first_part[cube.output]);
+ PLA1->R = cof_output(PLA->R, i + cube.first_part[cube.output]);
+ PLA1->D = cof_output(PLA->D, i + cube.first_part[cube.output]);
+
+ /* Call a routine to do something with the cover */
+ if ((*func)(PLA1, i) == 0) {
+ free_PLA(PLA1);
+ return;
+ }
+
+ /* intersect with the particular output part again */
+ PLA1->F = uncof_output(PLA1->F, i + cube.first_part[cube.output]);
+ PLA1->R = uncof_output(PLA1->R, i + cube.first_part[cube.output]);
+ PLA1->D = uncof_output(PLA1->D, i + cube.first_part[cube.output]);
+
+ /* Call a routine to do something with the final result */
+ if ((*func1)(PLA1, i) == 0) {
+ free_PLA(PLA1);
+ return;
+ }
+
+ /* Cleanup for next go-around */
+ free_PLA(PLA1);
+
+
+ }
+}
+
+static pcover Fmin;
+static pcube phase;
+
+/*
+ * minimize each output function individually
+ */
+void so_espresso(PLA, strategy)
+pPLA PLA;
+int strategy;
+{
+ Fmin = new_cover(PLA->F->count);
+ if (strategy == 0) {
+ foreach_output_function(PLA, so_do_espresso, so_save);
+ } else {
+ foreach_output_function(PLA, so_do_exact, so_save);
+ }
+ sf_free(PLA->F);
+ PLA->F = Fmin;
+}
+
+
+/*
+ * minimize each output function, choose function or complement based on the
+ * one with the fewer number of terms
+ */
+void so_both_espresso(PLA, strategy)
+pPLA PLA;
+int strategy;
+{
+ phase = set_save(cube.fullset);
+ Fmin = new_cover(PLA->F->count);
+ if (strategy == 0) {
+ foreach_output_function(PLA, so_both_do_espresso, so_both_save);
+ } else {
+ foreach_output_function(PLA, so_both_do_exact, so_both_save);
+ }
+ sf_free(PLA->F);
+ PLA->F = Fmin;
+ PLA->phase = phase;
+}
+
+
+int so_do_espresso(PLA, i)
+pPLA PLA;
+int i;
+{
+ char word[32];
+
+ /* minimize the single-output function (on-set) */
+ skip_make_sparse = 1;
+ (void) sprintf(word, "ESPRESSO-POS(%d)", i);
+ EXEC_S(PLA->F = espresso(PLA->F, PLA->D, PLA->R), word, PLA->F);
+ return 1;
+}
+
+
+int so_do_exact(PLA, i)
+pPLA PLA;
+int i;
+{
+ char word[32];
+
+ /* minimize the single-output function (on-set) */
+ skip_make_sparse = 1;
+ (void) sprintf(word, "EXACT-POS(%d)", i);
+ EXEC_S(PLA->F = minimize_exact(PLA->F, PLA->D, PLA->R, 1), word, PLA->F);
+ return 1;
+}
+
+
+/*ARGSUSED*/
+int so_save(PLA, i)
+pPLA PLA;
+int i;
+{
+ Fmin = sf_append(Fmin, PLA->F); /* disposes of PLA->F */
+ PLA->F = NULL;
+ return 1;
+}
+
+
+int so_both_do_espresso(PLA, i)
+pPLA PLA;
+int i;
+{
+ char word[32];
+
+ /* minimize the single-output function (on-set) */
+ (void) sprintf(word, "ESPRESSO-POS(%d)", i);
+ skip_make_sparse = 1;
+ EXEC_S(PLA->F = espresso(PLA->F, PLA->D, PLA->R), word, PLA->F);
+
+ /* minimize the single-output function (off-set) */
+ (void) sprintf(word, "ESPRESSO-NEG(%d)", i);
+ skip_make_sparse = 1;
+ EXEC_S(PLA->R = espresso(PLA->R, PLA->D, PLA->F), word, PLA->R);
+
+ return 1;
+}
+
+
+int so_both_do_exact(PLA, i)
+pPLA PLA;
+int i;
+{
+ char word[32];
+
+ /* minimize the single-output function (on-set) */
+ (void) sprintf(word, "EXACT-POS(%d)", i);
+ skip_make_sparse = 1;
+ EXEC_S(PLA->F = minimize_exact(PLA->F, PLA->D, PLA->R, 1), word, PLA->F);
+
+ /* minimize the single-output function (off-set) */
+ (void) sprintf(word, "EXACT-NEG(%d)", i);
+ skip_make_sparse = 1;
+ EXEC_S(PLA->R = minimize_exact(PLA->R, PLA->D, PLA->F, 1), word, PLA->R);
+
+ return 1;
+}
+
+
+int so_both_save(PLA, i)
+pPLA PLA;
+int i;
+{
+ if (PLA->F->count > PLA->R->count) {
+ sf_free(PLA->F);
+ PLA->F = PLA->R;
+ PLA->R = NULL;
+ i += cube.first_part[cube.output];
+ set_remove(phase, i);
+ } else {
+ sf_free(PLA->R);
+ PLA->R = NULL;
+ }
+ Fmin = sf_append(Fmin, PLA->F);
+ PLA->F = NULL;
+ return 1;
+}
diff --git a/src/misc/espresso/cvrmisc.c b/src/misc/espresso/cvrmisc.c
new file mode 100644
index 00000000..0f3de195
--- /dev/null
+++ b/src/misc/espresso/cvrmisc.c
@@ -0,0 +1,142 @@
+/*
+ * Revision Control Information
+ *
+ * $Source$
+ * $Author$
+ * $Revision$
+ * $Date$
+ *
+ */
+#include "espresso.h"
+
+
+/* cost -- compute the cost of a cover */
+void cover_cost(F, cost)
+IN pcover F;
+INOUT pcost cost;
+{
+ register pcube p, last;
+ pcube *T;
+ int var;
+
+ /* use the routine used by cofactor to decide splitting variables */
+ massive_count(T = cube1list(F));
+ free_cubelist(T);
+
+ cost->cubes = F->count;
+ cost->total = cost->in = cost->out = cost->mv = cost->primes = 0;
+
+ /* Count transistors (zeros) for each binary variable (inputs) */
+ for(var = 0; var < cube.num_binary_vars; var++)
+ cost->in += cdata.var_zeros[var];
+
+ /* Count transistors for each mv variable based on sparse/dense */
+ for(var = cube.num_binary_vars; var < cube.num_vars - 1; var++)
+ if (cube.sparse[var])
+ cost->mv += F->count * cube.part_size[var] - cdata.var_zeros[var];
+ else
+ cost->mv += cdata.var_zeros[var];
+
+ /* Count the transistors (ones) for the output variable */
+ if (cube.num_binary_vars != cube.num_vars) {
+ var = cube.num_vars - 1;
+ cost->out = F->count * cube.part_size[var] - cdata.var_zeros[var];
+ }
+
+ /* Count the number of nonprime cubes */
+ foreach_set(F, last, p)
+ cost->primes += TESTP(p, PRIME) != 0;
+
+ /* Count the total number of literals */
+ cost->total = cost->in + cost->out + cost->mv;
+}
+
+
+/* fmt_cost -- return a string which reports the "cost" of a cover */
+char *fmt_cost(cost)
+IN pcost cost;
+{
+ static char s[200];
+
+ if (cube.num_binary_vars == cube.num_vars - 1)
+ (void) sprintf(s, "c=%d(%d) in=%d out=%d tot=%d",
+ cost->cubes, cost->cubes - cost->primes, cost->in,
+ cost->out, cost->total);
+ else
+ (void) sprintf(s, "c=%d(%d) in=%d mv=%d out=%d",
+ cost->cubes, cost->cubes - cost->primes, cost->in,
+ cost->mv, cost->out);
+ return s;
+}
+
+
+char *print_cost(F)
+IN pcover F;
+{
+ cost_t cost;
+ cover_cost(F, &cost);
+ return fmt_cost(&cost);
+}
+
+
+/* copy_cost -- copy a cost function from s to d */
+void copy_cost(s, d)
+pcost s, d;
+{
+ d->cubes = s->cubes;
+ d->in = s->in;
+ d->out = s->out;
+ d->mv = s->mv;
+ d->total = s->total;
+ d->primes = s->primes;
+}
+
+
+/* size_stamp -- print single line giving the size of a cover */
+void size_stamp(T, name)
+IN pcover T;
+IN char *name;
+{
+ (void) printf("# %s\tCost is %s\n", name, print_cost(T));
+ (void) fflush(stdout);
+}
+
+
+/* print_trace -- print a line reporting size and time after a function */
+void print_trace(T, name, time)
+pcover T;
+char *name;
+long time;
+{
+ (void) printf("# %s\tTime was %s, cost is %s\n",
+ name, print_time(time), print_cost(T));
+ (void) fflush(stdout);
+}
+
+
+/* totals -- add time spent in the function into the totals */
+void totals(time, i, T, cost)
+long time;
+int i;
+pcover T;
+pcost cost;
+{
+ time = ptime() - time;
+ total_time[i] += time;
+ total_calls[i]++;
+ cover_cost(T, cost);
+ if (trace) {
+ (void) printf("# %s\tTime was %s, cost is %s\n",
+ total_name[i], print_time(time), fmt_cost(cost));
+ (void) fflush(stdout);
+ }
+}
+
+
+/* fatal -- report fatal error message and take a dive */
+void fatal(s)
+char *s;
+{
+ (void) fprintf(stderr, "espresso: %s\n", s);
+ exit(1);
+}
diff --git a/src/misc/espresso/cvrout.c b/src/misc/espresso/cvrout.c
new file mode 100644
index 00000000..4bd1c53b
--- /dev/null
+++ b/src/misc/espresso/cvrout.c
@@ -0,0 +1,609 @@
+/*
+ * Revision Control Information
+ *
+ * $Source$
+ * $Author$
+ * $Revision$
+ * $Date$
+ *
+ */
+/*
+ module: cvrout.c
+ purpose: cube and cover output routines
+*/
+
+#include "espresso.h"
+
+void fprint_pla(fp, PLA, output_type)
+INOUT FILE *fp;
+IN pPLA PLA;
+IN int output_type;
+{
+ int num;
+ register pcube last, p;
+
+ if ((output_type & CONSTRAINTS_type) != 0) {
+ output_symbolic_constraints(fp, PLA, 0);
+ output_type &= ~ CONSTRAINTS_type;
+ if (output_type == 0) {
+ return;
+ }
+ }
+
+ if ((output_type & SYMBOLIC_CONSTRAINTS_type) != 0) {
+ output_symbolic_constraints(fp, PLA, 1);
+ output_type &= ~ SYMBOLIC_CONSTRAINTS_type;
+ if (output_type == 0) {
+ return;
+ }
+ }
+
+ if (output_type == PLEASURE_type) {
+ pls_output(PLA);
+ } else if (output_type == EQNTOTT_type) {
+ eqn_output(PLA);
+ } else if (output_type == KISS_type) {
+ kiss_output(fp, PLA);
+ } else {
+ fpr_header(fp, PLA, output_type);
+
+ num = 0;
+ if (output_type & F_type) num += (PLA->F)->count;
+ if (output_type & D_type) num += (PLA->D)->count;
+ if (output_type & R_type) num += (PLA->R)->count;
+ (void) fprintf(fp, ".p %d\n", num);
+
+ /* quick patch 01/17/85 to support TPLA ! */
+ if (output_type == F_type) {
+ foreach_set(PLA->F, last, p) {
+ print_cube(fp, p, "01");
+ }
+ (void) fprintf(fp, ".e\n");
+ } else {
+ if (output_type & F_type) {
+ foreach_set(PLA->F, last, p) {
+ print_cube(fp, p, "~1");
+ }
+ }
+ if (output_type & D_type) {
+ foreach_set(PLA->D, last, p) {
+ print_cube(fp, p, "~2");
+ }
+ }
+ if (output_type & R_type) {
+ foreach_set(PLA->R, last, p) {
+ print_cube(fp, p, "~0");
+ }
+ }
+ (void) fprintf(fp, ".end\n");
+ }
+ }
+}
+
+void fpr_header(fp, PLA, output_type)
+FILE *fp;
+pPLA PLA;
+int output_type;
+{
+ register int i, var;
+ int first, last;
+
+ /* .type keyword gives logical type */
+ if (output_type != F_type) {
+ (void) fprintf(fp, ".type ");
+ if (output_type & F_type) putc('f', fp);
+ if (output_type & D_type) putc('d', fp);
+ if (output_type & R_type) putc('r', fp);
+ putc('\n', fp);
+ }
+
+ /* Check for binary or multiple-valued labels */
+ if (cube.num_mv_vars <= 1) {
+ (void) fprintf(fp, ".i %d\n", cube.num_binary_vars);
+ if (cube.output != -1)
+ (void) fprintf(fp, ".o %d\n", cube.part_size[cube.output]);
+ } else {
+ (void) fprintf(fp, ".mv %d %d", cube.num_vars, cube.num_binary_vars);
+ for(var = cube.num_binary_vars; var < cube.num_vars; var++)
+ (void) fprintf(fp, " %d", cube.part_size[var]);
+ (void) fprintf(fp, "\n");
+ }
+
+ /* binary valued labels */
+ if (PLA->label != NIL(char *) && PLA->label[1] != NIL(char)
+ && cube.num_binary_vars > 0) {
+ (void) fprintf(fp, ".ilb");
+ for(var = 0; var < cube.num_binary_vars; var++)
+ /* see (NIL) OUTLABELS comment below */
+ if(INLABEL(var) == NIL(char)){
+ (void) fprintf(fp, " (null)");
+ }
+ else{
+ (void) fprintf(fp, " %s", INLABEL(var));
+ }
+ putc('\n', fp);
+ }
+
+ /* output-part (last multiple-valued variable) labels */
+ if (PLA->label != NIL(char *) &&
+ PLA->label[cube.first_part[cube.output]] != NIL(char)
+ && cube.output != -1) {
+ (void) fprintf(fp, ".ob");
+ for(i = 0; i < cube.part_size[cube.output]; i++)
+ /* (NIL) OUTLABELS caused espresso to segfault under solaris */
+ if(OUTLABEL(i) == NIL(char)){
+ (void) fprintf(fp, " (null)");
+ }
+ else{
+ (void) fprintf(fp, " %s", OUTLABEL(i));
+ }
+ putc('\n', fp);
+ }
+
+ /* multiple-valued labels */
+ for(var = cube.num_binary_vars; var < cube.num_vars-1; var++) {
+ first = cube.first_part[var];
+ last = cube.last_part[var];
+ if (PLA->label != NULL && PLA->label[first] != NULL) {
+ (void) fprintf(fp, ".label var=%d", var);
+ for(i = first; i <= last; i++) {
+ (void) fprintf(fp, " %s", PLA->label[i]);
+ }
+ putc('\n', fp);
+ }
+ }
+
+ if (PLA->phase != (pcube) NULL) {
+ first = cube.first_part[cube.output];
+ last = cube.last_part[cube.output];
+ (void) fprintf(fp, "#.phase ");
+ for(i = first; i <= last; i++)
+ putc(is_in_set(PLA->phase,i) ? '1' : '0', fp);
+ (void) fprintf(fp, "\n");
+ }
+}
+
+void pls_output(PLA)
+IN pPLA PLA;
+{
+ register pcube last, p;
+
+ (void) printf(".option unmerged\n");
+ makeup_labels(PLA);
+ pls_label(PLA, stdout);
+ pls_group(PLA, stdout);
+ (void) printf(".p %d\n", PLA->F->count);
+ foreach_set(PLA->F, last, p) {
+ print_expanded_cube(stdout, p, PLA->phase);
+ }
+ (void) printf(".end\n");
+}
+
+
+void pls_group(PLA, fp)
+pPLA PLA;
+FILE *fp;
+{
+ int var, i, col, len;
+
+ (void) fprintf(fp, "\n.group");
+ col = 6;
+ for(var = 0; var < cube.num_vars-1; var++) {
+ (void) fprintf(fp, " ("), col += 2;
+ for(i = cube.first_part[var]; i <= cube.last_part[var]; i++) {
+ len = strlen(PLA->label[i]);
+ if (col + len > 75)
+ (void) fprintf(fp, " \\\n"), col = 0;
+ else if (i != 0)
+ putc(' ', fp), col += 1;
+ (void) fprintf(fp, "%s", PLA->label[i]), col += len;
+ }
+ (void) fprintf(fp, ")"), col += 1;
+ }
+ (void) fprintf(fp, "\n");
+}
+
+
+void pls_label(PLA, fp)
+pPLA PLA;
+FILE *fp;
+{
+ int var, i, col, len;
+
+ (void) fprintf(fp, ".label");
+ col = 6;
+ for(var = 0; var < cube.num_vars; var++)
+ for(i = cube.first_part[var]; i <= cube.last_part[var]; i++) {
+ len = strlen(PLA->label[i]);
+ if (col + len > 75)
+ (void) fprintf(fp, " \\\n"), col = 0;
+ else
+ putc(' ', fp), col += 1;
+ (void) fprintf(fp, "%s", PLA->label[i]), col += len;
+ }
+}
+
+
+
+/*
+ eqntott output mode -- output algebraic equations
+*/
+void eqn_output(PLA)
+pPLA PLA;
+{
+ register pcube p, last;
+ register int i, var, col, len;
+ int x;
+ bool firstand, firstor;
+
+ if (cube.output == -1)
+ fatal("Cannot have no-output function for EQNTOTT output mode");
+ if (cube.num_mv_vars != 1)
+ fatal("Must have binary-valued function for EQNTOTT output mode");
+ makeup_labels(PLA);
+
+ /* Write a single equation for each output */
+ for(i = 0; i < cube.part_size[cube.output]; i++) {
+ (void) printf("%s = ", OUTLABEL(i));
+ col = strlen(OUTLABEL(i)) + 3;
+ firstor = TRUE;
+
+ /* Write product terms for each cube in this output */
+ foreach_set(PLA->F, last, p)
+ if (is_in_set(p, i + cube.first_part[cube.output])) {
+ if (firstor)
+ (void) printf("("), col += 1;
+ else
+ (void) printf(" | ("), col += 4;
+ firstor = FALSE;
+ firstand = TRUE;
+
+ /* print out a product term */
+ for(var = 0; var < cube.num_binary_vars; var++)
+ if ((x=GETINPUT(p, var)) != DASH) {
+ len = strlen(INLABEL(var));
+ if (col+len > 72)
+ (void) printf("\n "), col = 4;
+ if (! firstand)
+ (void) printf("&"), col += 1;
+ firstand = FALSE;
+ if (x == ZERO)
+ (void) printf("!"), col += 1;
+ (void) printf("%s", INLABEL(var)), col += len;
+ }
+ (void) printf(")"), col += 1;
+ }
+ (void) printf(";\n\n");
+ }
+}
+
+
+char *fmt_cube(c, out_map, s)
+register pcube c;
+register char *out_map, *s;
+{
+ register int i, var, last, len = 0;
+
+ for(var = 0; var < cube.num_binary_vars; var++) {
+ s[len++] = "?01-" [GETINPUT(c, var)];
+ }
+ for(var = cube.num_binary_vars; var < cube.num_vars - 1; var++) {
+ s[len++] = ' ';
+ for(i = cube.first_part[var]; i <= cube.last_part[var]; i++) {
+ s[len++] = "01" [is_in_set(c, i) != 0];
+ }
+ }
+ if (cube.output != -1) {
+ last = cube.last_part[cube.output];
+ s[len++] = ' ';
+ for(i = cube.first_part[cube.output]; i <= last; i++) {
+ s[len++] = out_map [is_in_set(c, i) != 0];
+ }
+ }
+ s[len] = '\0';
+ return s;
+}
+
+
+void print_cube(fp, c, out_map)
+register FILE *fp;
+register pcube c;
+register char *out_map;
+{
+ register int i, var, ch;
+ int last;
+
+ for(var = 0; var < cube.num_binary_vars; var++) {
+ ch = "?01-" [GETINPUT(c, var)];
+ putc(ch, fp);
+ }
+ for(var = cube.num_binary_vars; var < cube.num_vars - 1; var++) {
+ putc(' ', fp);
+ for(i = cube.first_part[var]; i <= cube.last_part[var]; i++) {
+ ch = "01" [is_in_set(c, i) != 0];
+ putc(ch, fp);
+ }
+ }
+ if (cube.output != -1) {
+ last = cube.last_part[cube.output];
+ putc(' ', fp);
+ for(i = cube.first_part[cube.output]; i <= last; i++) {
+ ch = out_map [is_in_set(c, i) != 0];
+ putc(ch, fp);
+ }
+ }
+ putc('\n', fp);
+}
+
+
+void print_expanded_cube(fp, c, phase)
+register FILE *fp;
+register pcube c;
+pcube phase;
+{
+ register int i, var, ch;
+ char *out_map;
+
+ for(var = 0; var < cube.num_binary_vars; var++) {
+ for(i = cube.first_part[var]; i <= cube.last_part[var]; i++) {
+ ch = "~1" [is_in_set(c, i) != 0];
+ putc(ch, fp);
+ }
+ }
+ for(var = cube.num_binary_vars; var < cube.num_vars - 1; var++) {
+ for(i = cube.first_part[var]; i <= cube.last_part[var]; i++) {
+ ch = "1~" [is_in_set(c, i) != 0];
+ putc(ch, fp);
+ }
+ }
+ if (cube.output != -1) {
+ var = cube.num_vars - 1;
+ putc(' ', fp);
+ for(i = cube.first_part[var]; i <= cube.last_part[var]; i++) {
+ if (phase == (pcube) NULL || is_in_set(phase, i)) {
+ out_map = "~1";
+ } else {
+ out_map = "~0";
+ }
+ ch = out_map[is_in_set(c, i) != 0];
+ putc(ch, fp);
+ }
+ }
+ putc('\n', fp);
+}
+
+
+char *pc1(c) pcube c;
+{static char s1[256];return fmt_cube(c, "01", s1);}
+char *pc2(c) pcube c;
+{static char s2[256];return fmt_cube(c, "01", s2);}
+
+
+void debug_print(T, name, level)
+pcube *T;
+char *name;
+int level;
+{
+ register pcube *T1, p, temp;
+ register int cnt;
+
+ cnt = CUBELISTSIZE(T);
+ temp = new_cube();
+ if (verbose_debug && level == 0)
+ (void) printf("\n");
+ (void) printf("%s[%d]: ord(T)=%d\n", name, level, cnt);
+ if (verbose_debug) {
+ (void) printf("cofactor=%s\n", pc1(T[0]));
+ for(T1 = T+2, cnt = 1; (p = *T1++) != (pcube) NULL; cnt++)
+ (void) printf("%4d. %s\n", cnt, pc1(set_or(temp, p, T[0])));
+ }
+ free_cube(temp);
+}
+
+
+void debug1_print(T, name, num)
+pcover T;
+char *name;
+int num;
+{
+ register int cnt = 1;
+ register pcube p, last;
+
+ if (verbose_debug && num == 0)
+ (void) printf("\n");
+ (void) printf("%s[%d]: ord(T)=%d\n", name, num, T->count);
+ if (verbose_debug)
+ foreach_set(T, last, p)
+ (void) printf("%4d. %s\n", cnt++, pc1(p));
+}
+
+
+void cprint(T)
+pcover T;
+{
+ register pcube p, last;
+
+ foreach_set(T, last, p)
+ (void) printf("%s\n", pc1(p));
+}
+
+
+int makeup_labels(PLA)
+pPLA PLA;
+{
+ int var, i, ind;
+
+ if (PLA->label == (char **) NULL)
+ PLA_labels(PLA);
+
+ for(var = 0; var < cube.num_vars; var++)
+ for(i = 0; i < cube.part_size[var]; i++) {
+ ind = cube.first_part[var] + i;
+ if (PLA->label[ind] == (char *) NULL) {
+ PLA->label[ind] = ALLOC(char, 15);
+ if (var < cube.num_binary_vars)
+ if ((i % 2) == 0)
+ (void) sprintf(PLA->label[ind], "v%d.bar", var);
+ else
+ (void) sprintf(PLA->label[ind], "v%d", var);
+ else
+ (void) sprintf(PLA->label[ind], "v%d.%d", var, i);
+ }
+ }
+}
+
+
+kiss_output(fp, PLA)
+FILE *fp;
+pPLA PLA;
+{
+ register pset last, p;
+
+ foreach_set(PLA->F, last, p) {
+ kiss_print_cube(fp, PLA, p, "~1");
+ }
+ foreach_set(PLA->D, last, p) {
+ kiss_print_cube(fp, PLA, p, "~2");
+ }
+}
+
+
+kiss_print_cube(fp, PLA, p, out_string)
+FILE *fp;
+pPLA PLA;
+pcube p;
+char *out_string;
+{
+ register int i, var;
+ int part, x;
+
+ for(var = 0; var < cube.num_binary_vars; var++) {
+ x = "?01-" [GETINPUT(p, var)];
+ putc(x, fp);
+ }
+
+ for(var = cube.num_binary_vars; var < cube.num_vars - 1; var++) {
+ putc(' ', fp);
+ if (setp_implies(cube.var_mask[var], p)) {
+ putc('-', fp);
+ } else {
+ part = -1;
+ for(i = cube.first_part[var]; i <= cube.last_part[var]; i++) {
+ if (is_in_set(p, i)) {
+ if (part != -1) {
+ fatal("more than 1 part in a symbolic variable\n");
+ }
+ part = i;
+ }
+ }
+ if (part == -1) {
+ putc('~', fp); /* no parts, hope its an output ... */
+ } else {
+ (void) fputs(PLA->label[part], fp);
+ }
+ }
+ }
+
+ if ((var = cube.output) != -1) {
+ putc(' ', fp);
+ for(i = cube.first_part[var]; i <= cube.last_part[var]; i++) {
+ x = out_string [is_in_set(p, i) != 0];
+ putc(x, fp);
+ }
+ }
+
+ putc('\n', fp);
+}
+
+output_symbolic_constraints(fp, PLA, output_symbolic)
+FILE *fp;
+pPLA PLA;
+int output_symbolic;
+{
+ pset_family A;
+ register int i, j;
+ int size, var, npermute, *permute, *weight, noweight;
+
+ if ((cube.num_vars - cube.num_binary_vars) <= 1) {
+ return;
+ }
+ makeup_labels(PLA);
+
+ for(var=cube.num_binary_vars; var < cube.num_vars-1; var++) {
+
+ /* pull out the columns for variable "var" */
+ npermute = cube.part_size[var];
+ permute = ALLOC(int, npermute);
+ for(i=0; i < npermute; i++) {
+ permute[i] = cube.first_part[var] + i;
+ }
+ A = sf_permute(sf_save(PLA->F), permute, npermute);
+ FREE(permute);
+
+
+ /* Delete the singletons and the full sets */
+ noweight = 0;
+ for(i = 0; i < A->count; i++) {
+ size = set_ord(GETSET(A,i));
+ if (size == 1 || size == A->sf_size) {
+ sf_delset(A, i--);
+ noweight++;
+ }
+ }
+
+
+ /* Count how many times each is duplicated */
+ weight = ALLOC(int, A->count);
+ for(i = 0; i < A->count; i++) {
+ RESET(GETSET(A, i), COVERED);
+ }
+ for(i = 0; i < A->count; i++) {
+ weight[i] = 0;
+ if (! TESTP(GETSET(A,i), COVERED)) {
+ weight[i] = 1;
+ for(j = i+1; j < A->count; j++) {
+ if (setp_equal(GETSET(A,i), GETSET(A,j))) {
+ weight[i]++;
+ SET(GETSET(A,j), COVERED);
+ }
+ }
+ }
+ }
+
+
+ /* Print out the contraints */
+ if (! output_symbolic) {
+ (void) fprintf(fp,
+ "# Symbolic constraints for variable %d (Numeric form)\n", var);
+ (void) fprintf(fp, "# unconstrained weight = %d\n", noweight);
+ (void) fprintf(fp, "num_codes=%d\n", cube.part_size[var]);
+ for(i = 0; i < A->count; i++) {
+ if (weight[i] > 0) {
+ (void) fprintf(fp, "weight=%d: ", weight[i]);
+ for(j = 0; j < A->sf_size; j++) {
+ if (is_in_set(GETSET(A,i), j)) {
+ (void) fprintf(fp, " %d", j);
+ }
+ }
+ (void) fprintf(fp, "\n");
+ }
+ }
+ } else {
+ (void) fprintf(fp,
+ "# Symbolic constraints for variable %d (Symbolic form)\n", var);
+ for(i = 0; i < A->count; i++) {
+ if (weight[i] > 0) {
+ (void) fprintf(fp, "# w=%d: (", weight[i]);
+ for(j = 0; j < A->sf_size; j++) {
+ if (is_in_set(GETSET(A,i), j)) {
+ (void) fprintf(fp, " %s",
+ PLA->label[cube.first_part[var]+j]);
+ }
+ }
+ (void) fprintf(fp, " )\n");
+ }
+ }
+ FREE(weight);
+ }
+ }
+}
diff --git a/src/misc/espresso/dominate.c b/src/misc/espresso/dominate.c
new file mode 100644
index 00000000..a930d453
--- /dev/null
+++ b/src/misc/espresso/dominate.c
@@ -0,0 +1,98 @@
+/*
+ * Revision Control Information
+ *
+ * $Source$
+ * $Author$
+ * $Revision$
+ * $Date$
+ *
+ */
+#include "mincov_int.h"
+
+
+int
+sm_row_dominance(A)
+sm_matrix *A;
+{
+ register sm_row *prow, *prow1;
+ register sm_col *pcol, *least_col;
+ register sm_element *p, *pnext;
+ int rowcnt;
+
+ rowcnt = A->nrows;
+
+ /* Check each row against all other rows */
+ for(prow = A->first_row; prow != 0; prow = prow->next_row) {
+
+ /* Among all columns with a 1 in this row, choose smallest */
+ least_col = sm_get_col(A, prow->first_col->col_num);
+ for(p = prow->first_col->next_col; p != 0; p = p->next_col) {
+ pcol = sm_get_col(A, p->col_num);
+ if (pcol->length < least_col->length) {
+ least_col = pcol;
+ }
+ }
+
+ /* Only check for containment against rows in this column */
+ for(p = least_col->first_row; p != 0; p = pnext) {
+ pnext = p->next_row;
+
+ prow1 = sm_get_row(A, p->row_num);
+ if ((prow1->length > prow->length) ||
+ (prow1->length == prow->length &&
+ prow1->row_num > prow->row_num)) {
+ if (sm_row_contains(prow, prow1)) {
+ sm_delrow(A, prow1->row_num);
+ }
+ }
+ }
+ }
+
+ return rowcnt - A->nrows;
+}
+
+int
+sm_col_dominance(A, weight)
+sm_matrix *A;
+int *weight;
+{
+ register sm_row *prow;
+ register sm_col *pcol, *pcol1;
+ register sm_element *p;
+ sm_row *least_row;
+ sm_col *next_col;
+ int colcnt;
+
+ colcnt = A->ncols;
+
+ /* Check each column against all other columns */
+ for(pcol = A->first_col; pcol != 0; pcol = next_col) {
+ next_col = pcol->next_col;
+
+ /* Check all rows to find the one with fewest elements */
+ least_row = sm_get_row(A, pcol->first_row->row_num);
+ for(p = pcol->first_row->next_row; p != 0; p = p->next_row) {
+ prow = sm_get_row(A, p->row_num);
+ if (prow->length < least_row->length) {
+ least_row = prow;
+ }
+ }
+
+ /* Only check for containment against columns in this row */
+ for(p = least_row->first_col; p != 0; p = p->next_col) {
+ pcol1 = sm_get_col(A, p->col_num);
+ if (weight != 0 && weight[pcol1->col_num] > weight[pcol->col_num])
+ continue;
+ if ((pcol1->length > pcol->length) ||
+ (pcol1->length == pcol->length &&
+ pcol1->col_num > pcol->col_num)) {
+ if (sm_col_contains(pcol, pcol1)) {
+ sm_delcol(A, pcol->col_num);
+ break;
+ }
+ }
+ }
+ }
+
+ return colcnt - A->ncols;
+}
diff --git a/src/misc/espresso/equiv.c b/src/misc/espresso/equiv.c
new file mode 100644
index 00000000..ba898a70
--- /dev/null
+++ b/src/misc/espresso/equiv.c
@@ -0,0 +1,94 @@
+/*
+ * Revision Control Information
+ *
+ * $Source$
+ * $Author$
+ * $Revision$
+ * $Date$
+ *
+ */
+#include "espresso.h"
+
+
+find_equiv_outputs(PLA)
+pPLA PLA;
+{
+ int i, j, ipart, jpart, some_equiv;
+ pcover *R, *F;
+
+ some_equiv = FALSE;
+
+ makeup_labels(PLA);
+
+ F = ALLOC(pcover, cube.part_size[cube.output]);
+ R = ALLOC(pcover, cube.part_size[cube.output]);
+
+ for(i = 0; i < cube.part_size[cube.output]; i++) {
+ ipart = cube.first_part[cube.output] + i;
+ R[i] = cof_output(PLA->R, ipart);
+ F[i] = complement(cube1list(R[i]));
+ }
+
+ for(i = 0; i < cube.part_size[cube.output]-1; i++) {
+ for(j = i+1; j < cube.part_size[cube.output]; j++) {
+ ipart = cube.first_part[cube.output] + i;
+ jpart = cube.first_part[cube.output] + j;
+
+ if (check_equiv(F[i], F[j])) {
+ (void) printf("# Outputs %d and %d (%s and %s) are equivalent\n",
+ i, j, PLA->label[ipart], PLA->label[jpart]);
+ some_equiv = TRUE;
+ } else if (check_equiv(F[i], R[j])) {
+ (void) printf("# Outputs %d and NOT %d (%s and %s) are equivalent\n",
+ i, j, PLA->label[ipart], PLA->label[jpart]);
+ some_equiv = TRUE;
+ } else if (check_equiv(R[i], F[j])) {
+ (void) printf("# Outputs NOT %d and %d (%s and %s) are equivalent\n",
+ i, j, PLA->label[ipart], PLA->label[jpart]);
+ some_equiv = TRUE;
+ } else if (check_equiv(R[i], R[j])) {
+ (void) printf("# Outputs NOT %d and NOT %d (%s and %s) are equivalent\n",
+ i, j, PLA->label[ipart], PLA->label[jpart]);
+ some_equiv = TRUE;
+ }
+ }
+ }
+
+ if (! some_equiv) {
+ (void) printf("# No outputs are equivalent\n");
+ }
+
+ for(i = 0; i < cube.part_size[cube.output]; i++) {
+ free_cover(F[i]);
+ free_cover(R[i]);
+ }
+ FREE(F);
+ FREE(R);
+}
+
+
+
+int check_equiv(f1, f2)
+pcover f1, f2;
+{
+ register pcube *f1list, *f2list;
+ register pcube p, last;
+
+ f1list = cube1list(f1);
+ foreach_set(f2, last, p) {
+ if (! cube_is_covered(f1list, p)) {
+ return FALSE;
+ }
+ }
+ free_cubelist(f1list);
+
+ f2list = cube1list(f2);
+ foreach_set(f1, last, p) {
+ if (! cube_is_covered(f2list, p)) {
+ return FALSE;
+ }
+ }
+ free_cubelist(f2list);
+
+ return TRUE;
+}
diff --git a/src/misc/espresso/espresso.c b/src/misc/espresso/espresso.c
new file mode 100644
index 00000000..8f05d43f
--- /dev/null
+++ b/src/misc/espresso/espresso.c
@@ -0,0 +1,139 @@
+/*
+ * Revision Control Information
+ *
+ * $Source$
+ * $Author$
+ * $Revision$
+ * $Date$
+ *
+ */
+/*
+ * Module: espresso.c
+ * Purpose: The main espresso algorithm
+ *
+ * Returns a minimized version of the ON-set of a function
+ *
+ * The following global variables affect the operation of Espresso:
+ *
+ * MISCELLANEOUS:
+ * trace
+ * print trace information as the minimization progresses
+ *
+ * remove_essential
+ * remove essential primes
+ *
+ * single_expand
+ * if true, stop after first expand/irredundant
+ *
+ * LAST_GASP or SUPER_GASP strategy:
+ * use_super_gasp
+ * uses the super_gasp strategy rather than last_gasp
+ *
+ * SETUP strategy:
+ * recompute_onset
+ * recompute onset using the complement before starting
+ *
+ * unwrap_onset
+ * unwrap the function output part before first expand
+ *
+ * MAKE_SPARSE strategy:
+ * force_irredundant
+ * iterates make_sparse to force a minimal solution (used
+ * indirectly by make_sparse)
+ *
+ * skip_make_sparse
+ * skip the make_sparse step (used by opo only)
+ */
+
+#include "espresso.h"
+
+pcover espresso(F, D1, R)
+pcover F, D1, R;
+{
+ pcover E, D, Fsave;
+ pset last, p;
+ cost_t cost, best_cost;
+
+begin:
+ Fsave = sf_save(F); /* save original function */
+ D = sf_save(D1); /* make a scratch copy of D */
+
+ /* Setup has always been a problem */
+ if (recompute_onset) {
+ EXEC(E = simplify(cube1list(F)), "SIMPLIFY ", E);
+ free_cover(F);
+ F = E;
+ }
+ cover_cost(F, &cost);
+ if (unwrap_onset && (cube.part_size[cube.num_vars - 1] > 1)
+ && (cost.out != cost.cubes*cube.part_size[cube.num_vars-1])
+ && (cost.out < 5000))
+ EXEC(F = sf_contain(unravel(F, cube.num_vars - 1)), "SETUP ", F);
+
+ /* Initial expand and irredundant */
+ foreach_set(F, last, p) {
+ RESET(p, PRIME);
+ }
+ EXECUTE(F = expand(F, R, FALSE), EXPAND_TIME, F, cost);
+ EXECUTE(F = irredundant(F, D), IRRED_TIME, F, cost);
+
+ if (! single_expand) {
+ if (remove_essential) {
+ EXECUTE(E = essential(&F, &D), ESSEN_TIME, E, cost);
+ } else {
+ E = new_cover(0);
+ }
+
+ cover_cost(F, &cost);
+ do {
+
+ /* Repeat inner loop until solution becomes "stable" */
+ do {
+ copy_cost(&cost, &best_cost);
+ EXECUTE(F = reduce(F, D), REDUCE_TIME, F, cost);
+ EXECUTE(F = expand(F, R, FALSE), EXPAND_TIME, F, cost);
+ EXECUTE(F = irredundant(F, D), IRRED_TIME, F, cost);
+ } while (cost.cubes < best_cost.cubes);
+
+ /* Perturb solution to see if we can continue to iterate */
+ copy_cost(&cost, &best_cost);
+ if (use_super_gasp) {
+ F = super_gasp(F, D, R, &cost);
+ if (cost.cubes >= best_cost.cubes)
+ break;
+ } else {
+ F = last_gasp(F, D, R, &cost);
+ }
+
+ } while (cost.cubes < best_cost.cubes ||
+ (cost.cubes == best_cost.cubes && cost.total < best_cost.total));
+
+ /* Append the essential cubes to F */
+ F = sf_append(F, E); /* disposes of E */
+ if (trace) size_stamp(F, "ADJUST ");
+ }
+
+ /* Free the D which we used */
+ free_cover(D);
+
+ /* Attempt to make the PLA matrix sparse */
+ if (! skip_make_sparse) {
+ F = make_sparse(F, D1, R);
+ }
+
+ /*
+ * Check to make sure function is actually smaller !!
+ * This can only happen because of the initial unravel. If we fail,
+ * then run the whole thing again without the unravel.
+ */
+ if (Fsave->count < F->count) {
+ free_cover(F);
+ F = Fsave;
+ unwrap_onset = FALSE;
+ goto begin;
+ } else {
+ free_cover(Fsave);
+ }
+
+ return F;
+}
diff --git a/src/misc/espresso/espresso.h b/src/misc/espresso/espresso.h
new file mode 100644
index 00000000..1c7a8646
--- /dev/null
+++ b/src/misc/espresso/espresso.h
@@ -0,0 +1,782 @@
+/*
+ * Revision Control Information
+ *
+ * $Source$
+ * $Author$
+ * $Revision$
+ * $Date$
+ *
+ */
+/*
+ * espresso.h -- header file for Espresso-mv
+ */
+
+//#include "port.h"
+//#include "utility.h"
+#include "sparse.h"
+#include "mincov.h"
+
+#include "util_hack.h" // added
+
+#define ptime() util_cpu_time()
+#define print_time(t) util_print_time(t)
+
+#ifdef IBM_WATC
+#define void int
+#include "short.h"
+#endif
+
+#ifdef IBMPC /* set default options for IBM/PC */
+#define NO_INLINE
+#define BPI 16
+#endif
+
+/*-----THIS USED TO BE set.h----- */
+
+/*
+ * set.h -- definitions for packed arrays of bits
+ *
+ * This header file describes the data structures which comprise a
+ * facility for efficiently implementing packed arrays of bits
+ * (otherwise known as sets, cf. Pascal).
+ *
+ * A set is a vector of bits and is implemented here as an array of
+ * unsigned integers. The low order bits of set[0] give the index of
+ * the last word of set data. The higher order bits of set[0] are
+ * used to store data associated with the set. The set data is
+ * contained in elements set[1] ... set[LOOP(set)] as a packed bit
+ * array.
+ *
+ * A family of sets is a two-dimensional matrix of bits and is
+ * implemented with the data type "set_family".
+ *
+ * BPI == 32 and BPI == 16 have been tested and work.
+ */
+
+
+/* Define host machine characteristics of "unsigned int" */
+#ifndef BPI
+#define BPI 32 /* # bits per integer */
+#endif
+
+#if BPI == 32
+#define LOGBPI 5 /* log(BPI)/log(2) */
+#else
+#define LOGBPI 4 /* log(BPI)/log(2) */
+#endif
+
+/* Define the set type */
+typedef unsigned int *pset;
+
+/* Define the set family type -- an array of sets */
+typedef struct set_family {
+ int wsize; /* Size of each set in 'ints' */
+ int sf_size; /* User declared set size */
+ int capacity; /* Number of sets allocated */
+ int count; /* The number of sets in the family */
+ int active_count; /* Number of "active" sets */
+ pset data; /* Pointer to the set data */
+ struct set_family *next; /* For garbage collection */
+} set_family_t, *pset_family;
+
+/* Macros to set and test single elements */
+#define WHICH_WORD(element) (((element) >> LOGBPI) + 1)
+#define WHICH_BIT(element) ((element) & (BPI-1))
+
+/* # of ints needed to allocate a set with "size" elements */
+#if BPI == 32
+#define SET_SIZE(size) ((size) <= BPI ? 2 : (WHICH_WORD((size)-1) + 1))
+#else
+#define SET_SIZE(size) ((size) <= BPI ? 3 : (WHICH_WORD((size)-1) + 2))
+#endif
+
+/*
+ * Three fields are maintained in the first word of the set
+ * LOOP is the index of the last word used for set data
+ * LOOPCOPY is the index of the last word in the set
+ * SIZE is available for general use (e.g., recording # elements in set)
+ * NELEM retrieves the number of elements in the set
+ */
+#define LOOP(set) (set[0] & 0x03ff)
+#define PUTLOOP(set, i) (set[0] &= ~0x03ff, set[0] |= (i))
+#if BPI == 32
+#define LOOPCOPY(set) LOOP(set)
+#define SIZE(set) (set[0] >> 16)
+#define PUTSIZE(set, size) (set[0] &= 0xffff, set[0] |= ((size) << 16))
+#else
+#define LOOPCOPY(set) (LOOP(set) + 1)
+#define SIZE(set) (set[LOOP(set)+1])
+#define PUTSIZE(set, size) ((set[LOOP(set)+1]) = (size))
+#endif
+
+#define NELEM(set) (BPI * LOOP(set))
+#define LOOPINIT(size) ((size <= BPI) ? 1 : WHICH_WORD((size)-1))
+
+/*
+ * FLAGS store general information about the set
+ */
+#define SET(set, flag) (set[0] |= (flag))
+#define RESET(set, flag) (set[0] &= ~ (flag))
+#define TESTP(set, flag) (set[0] & (flag))
+
+/* Flag definitions are ... */
+#define PRIME 0x8000 /* cube is prime */
+#define NONESSEN 0x4000 /* cube cannot be essential prime */
+#define ACTIVE 0x2000 /* cube is still active */
+#define REDUND 0x1000 /* cube is redundant(at this point) */
+#define COVERED 0x0800 /* cube has been covered */
+#define RELESSEN 0x0400 /* cube is relatively essential */
+
+/* Most efficient way to look at all members of a set family */
+#define foreach_set(R, last, p)\
+ for(p=R->data,last=p+R->count*R->wsize;p<last;p+=R->wsize)
+#define foreach_remaining_set(R, last, pfirst, p)\
+ for(p=pfirst+R->wsize,last=R->data+R->count*R->wsize;p<last;p+=R->wsize)
+#define foreach_active_set(R, last, p)\
+ foreach_set(R,last,p) if (TESTP(p, ACTIVE))
+
+/* Another way that also keeps the index of the current set member in i */
+#define foreachi_set(R, i, p)\
+ for(p=R->data,i=0;i<R->count;p+=R->wsize,i++)
+#define foreachi_active_set(R, i, p)\
+ foreachi_set(R,i,p) if (TESTP(p, ACTIVE))
+
+/* Looping over all elements in a set:
+ * foreach_set_element(pset p, int i, unsigned val, int base) {
+ * .
+ * .
+ * .
+ * }
+ */
+#define foreach_set_element(p, i, val, base) \
+ for(i = LOOP(p); i > 0; ) \
+ for(val = p[i], base = --i << LOGBPI; val != 0; base++, val >>= 1) \
+ if (val & 1)
+
+/* Return a pointer to a given member of a set family */
+#define GETSET(family, index) ((family)->data + (family)->wsize * (index))
+
+/* Allocate and deallocate sets */
+#define set_new(size) set_clear(ALLOC(unsigned int, SET_SIZE(size)), size)
+#define set_full(size) set_fill(ALLOC(unsigned int, SET_SIZE(size)), size)
+#define set_save(r) set_copy(ALLOC(unsigned int, SET_SIZE(NELEM(r))), r)
+#define set_free(r) FREE(r)
+
+/* Check for set membership, remove set element and insert set element */
+#define is_in_set(set, e) (set[WHICH_WORD(e)] & (1 << WHICH_BIT(e)))
+#define set_remove(set, e) (set[WHICH_WORD(e)] &= ~ (1 << WHICH_BIT(e)))
+#define set_insert(set, e) (set[WHICH_WORD(e)] |= 1 << WHICH_BIT(e))
+
+/* Inline code substitution for those places that REALLY need it on a VAX */
+#ifdef NO_INLINE
+#define INLINEset_copy(r, a) (void) set_copy(r,a)
+#define INLINEset_clear(r, size) (void) set_clear(r, size)
+#define INLINEset_fill(r, size) (void) set_fill(r, size)
+#define INLINEset_and(r, a, b) (void) set_and(r, a, b)
+#define INLINEset_or(r, a, b) (void) set_or(r, a, b)
+#define INLINEset_diff(r, a, b) (void) set_diff(r, a, b)
+#define INLINEset_ndiff(r, a, b, f) (void) set_ndiff(r, a, b, f)
+#define INLINEset_xor(r, a, b) (void) set_xor(r, a, b)
+#define INLINEset_xnor(r, a, b, f) (void) set_xnor(r, a, b, f)
+#define INLINEset_merge(r, a, b, mask) (void) set_merge(r, a, b, mask)
+#define INLINEsetp_implies(a, b, when_false) \
+ if (! setp_implies(a,b)) when_false
+#define INLINEsetp_disjoint(a, b, when_false) \
+ if (! setp_disjoint(a,b)) when_false
+#define INLINEsetp_equal(a, b, when_false) \
+ if (! setp_equal(a,b)) when_false
+
+#else
+
+#define INLINEset_copy(r, a)\
+ {register int i_=LOOPCOPY(a); do r[i_]=a[i_]; while (--i_>=0);}
+#define INLINEset_clear(r, size)\
+ {register int i_=LOOPINIT(size); *r=i_; do r[i_] = 0; while (--i_ > 0);}
+#define INLINEset_fill(r, size)\
+ {register int i_=LOOPINIT(size); *r=i_; \
+ r[i_]=((unsigned int)(~0))>>(i_*BPI-size); while(--i_>0) r[i_]=~0;}
+#define INLINEset_and(r, a, b)\
+ {register int i_=LOOP(a); PUTLOOP(r,i_);\
+ do r[i_] = a[i_] & b[i_]; while (--i_>0);}
+#define INLINEset_or(r, a, b)\
+ {register int i_=LOOP(a); PUTLOOP(r,i_);\
+ do r[i_] = a[i_] | b[i_]; while (--i_>0);}
+#define INLINEset_diff(r, a, b)\
+ {register int i_=LOOP(a); PUTLOOP(r,i_);\
+ do r[i_] = a[i_] & ~ b[i_]; while (--i_>0);}
+#define INLINEset_ndiff(r, a, b, fullset)\
+ {register int i_=LOOP(a); PUTLOOP(r,i_);\
+ do r[i_] = fullset[i_] & (a[i_] | ~ b[i_]); while (--i_>0);}
+#ifdef IBM_WATC
+#define INLINEset_xor(r, a, b) (void) set_xor(r, a, b)
+#define INLINEset_xnor(r, a, b, f) (void) set_xnor(r, a, b, f)
+#else
+#define INLINEset_xor(r, a, b)\
+ {register int i_=LOOP(a); PUTLOOP(r,i_);\
+ do r[i_] = a[i_] ^ b[i_]; while (--i_>0);}
+#define INLINEset_xnor(r, a, b, fullset)\
+ {register int i_=LOOP(a); PUTLOOP(r,i_);\
+ do r[i_] = fullset[i_] & ~ (a[i_] ^ b[i_]); while (--i_>0);}
+#endif
+#define INLINEset_merge(r, a, b, mask)\
+ {register int i_=LOOP(a); PUTLOOP(r,i_);\
+ do r[i_] = (a[i_]&mask[i_]) | (b[i_]&~mask[i_]); while (--i_>0);}
+#define INLINEsetp_implies(a, b, when_false)\
+ {register int i_=LOOP(a); do if (a[i_]&~b[i_]) break; while (--i_>0);\
+ if (i_ != 0) when_false;}
+#define INLINEsetp_disjoint(a, b, when_false)\
+ {register int i_=LOOP(a); do if (a[i_]&b[i_]) break; while (--i_>0);\
+ if (i_ != 0) when_false;}
+#define INLINEsetp_equal(a, b, when_false)\
+ {register int i_=LOOP(a); do if (a[i_]!=b[i_]) break; while (--i_>0);\
+ if (i_ != 0) when_false;}
+
+#endif
+
+#if BPI == 32
+#define count_ones(v)\
+ (bit_count[v & 255] + bit_count[(v >> 8) & 255]\
+ + bit_count[(v >> 16) & 255] + bit_count[(v >> 24) & 255])
+#else
+#define count_ones(v) (bit_count[v & 255] + bit_count[(v >> 8) & 255])
+#endif
+
+/* Table for efficient bit counting */
+extern int bit_count[256];
+/*----- END OF set.h ----- */
+
+
+/* Define a boolean type */
+#define bool int
+#define FALSE 0
+#define TRUE 1
+#define MAYBE 2
+#define print_bool(x) ((x) == 0 ? "FALSE" : ((x) == 1 ? "TRUE" : "MAYBE"))
+
+/* Map many cube/cover types/routines into equivalent set types/routines */
+#define pcube pset
+#define new_cube() set_new(cube.size)
+#define free_cube(r) set_free(r)
+#define pcover pset_family
+#define new_cover(i) sf_new(i, cube.size)
+#define free_cover(r) sf_free(r)
+#define free_cubelist(T) FREE(T[0]); FREE(T);
+
+
+/* cost_t describes the cost of a cover */
+typedef struct cost_struct {
+ int cubes; /* number of cubes in the cover */
+ int in; /* transistor count, binary-valued variables */
+ int out; /* transistor count, output part */
+ int mv; /* transistor count, multiple-valued vars */
+ int total; /* total number of transistors */
+ int primes; /* number of prime cubes */
+} cost_t, *pcost;
+
+
+/* pair_t describes bit-paired variables */
+typedef struct pair_struct {
+ int cnt;
+ int *var1;
+ int *var2;
+} pair_t, *ppair;
+
+
+/* symbolic_list_t describes a single ".symbolic" line */
+typedef struct symbolic_list_struct {
+ int variable;
+ int pos;
+ struct symbolic_list_struct *next;
+} symbolic_list_t;
+
+
+/* symbolic_list_t describes a single ".symbolic" line */
+typedef struct symbolic_label_struct {
+ char *label;
+ struct symbolic_label_struct *next;
+} symbolic_label_t;
+
+
+/* symbolic_t describes a linked list of ".symbolic" lines */
+typedef struct symbolic_struct {
+ symbolic_list_t *symbolic_list; /* linked list of items */
+ int symbolic_list_length; /* length of symbolic_list list */
+ symbolic_label_t *symbolic_label; /* linked list of new names */
+ int symbolic_label_length; /* length of symbolic_label list */
+ struct symbolic_struct *next;
+} symbolic_t;
+
+
+/* PLA_t stores the logical representation of a PLA */
+typedef struct {
+ pcover F, D, R; /* on-set, off-set and dc-set */
+ char *filename; /* filename */
+ int pla_type; /* logical PLA format */
+ pcube phase; /* phase to split into on-set and off-set */
+ ppair pair; /* how to pair variables */
+ char **label; /* labels for the columns */
+ symbolic_t *symbolic; /* allow binary->symbolic mapping */
+ symbolic_t *symbolic_output;/* allow symbolic output mapping */
+} PLA_t, *pPLA;
+
+#define equal(a,b) (strcmp(a,b) == 0)
+
+/* This is a hack which I wish I hadn't done, but too painful to change */
+#define CUBELISTSIZE(T) (((pcube *) T[1] - T) - 3)
+
+/* For documentation purposes */
+#define IN
+#define OUT
+#define INOUT
+
+/* The pla_type field describes the input and output format of the PLA */
+#define F_type 1
+#define D_type 2
+#define R_type 4
+#define PLEASURE_type 8 /* output format */
+#define EQNTOTT_type 16 /* output format algebraic eqns */
+#define KISS_type 128 /* output format kiss */
+#define CONSTRAINTS_type 256 /* output the constraints (numeric) */
+#define SYMBOLIC_CONSTRAINTS_type 512 /* output the constraints (symbolic) */
+#define FD_type (F_type | D_type)
+#define FR_type (F_type | R_type)
+#define DR_type (D_type | R_type)
+#define FDR_type (F_type | D_type | R_type)
+
+/* Definitions for the debug variable */
+#define COMPL 0x0001
+#define ESSEN 0x0002
+#define EXPAND 0x0004
+#define EXPAND1 0x0008
+#define GASP 0x0010
+#define IRRED 0x0020
+#define REDUCE 0x0040
+#define REDUCE1 0x0080
+#define SPARSE 0x0100
+#define TAUT 0x0200
+#define EXACT 0x0400
+#define MINCOV 0x0800
+#define MINCOV1 0x1000
+#define SHARP 0x2000
+#define IRRED1 0x4000
+
+#define VERSION\
+ "UC Berkeley, Espresso Version #2.3, Release date 01/31/88"
+
+/* Define constants used for recording program statistics */
+#define TIME_COUNT 16
+#define READ_TIME 0
+#define COMPL_TIME 1
+#define ONSET_TIME 2
+#define ESSEN_TIME 3
+#define EXPAND_TIME 4
+#define IRRED_TIME 5
+#define REDUCE_TIME 6
+#define GEXPAND_TIME 7
+#define GIRRED_TIME 8
+#define GREDUCE_TIME 9
+#define PRIMES_TIME 10
+#define MINCOV_TIME 11
+#define MV_REDUCE_TIME 12
+#define RAISE_IN_TIME 13
+#define VERIFY_TIME 14
+#define WRITE_TIME 15
+
+
+/* For those who like to think about PLAs, macros to get at inputs/outputs */
+#define NUMINPUTS cube.num_binary_vars
+#define NUMOUTPUTS cube.part_size[cube.num_vars - 1]
+
+#define POSITIVE_PHASE(pos)\
+ (is_in_set(PLA->phase, cube.first_part[cube.output]+pos) != 0)
+
+#define INLABEL(var) PLA->label[cube.first_part[var] + 1]
+#define OUTLABEL(pos) PLA->label[cube.first_part[cube.output] + pos]
+
+#define GETINPUT(c, pos)\
+ ((c[WHICH_WORD(2*pos)] >> WHICH_BIT(2*pos)) & 3)
+#define GETOUTPUT(c, pos)\
+ (is_in_set(c, cube.first_part[cube.output] + pos) != 0)
+
+#define PUTINPUT(c, pos, value)\
+ c[WHICH_WORD(2*pos)] = (c[WHICH_WORD(2*pos)] & ~(3 << WHICH_BIT(2*pos)))\
+ | (value << WHICH_BIT(2*pos))
+#define PUTOUTPUT(c, pos, value)\
+ c[WHICH_WORD(pos)] = (c[WHICH_WORD(pos)] & ~(1 << WHICH_BIT(pos)))\
+ | (value << WHICH_BIT(pos))
+
+#define TWO 3
+#define DASH 3
+#define ONE 2
+#define ZERO 1
+
+
+#define EXEC(fct, name, S)\
+ {long t=ptime();fct;if(trace)print_trace(S,name,ptime()-t);}
+#define EXEC_S(fct, name, S)\
+ {long t=ptime();fct;if(summary)print_trace(S,name,ptime()-t);}
+#define EXECUTE(fct,i,S,cost)\
+ {long t=ptime();fct;totals(t,i,S,&(cost));}
+
+/*
+ * Global Variable Declarations
+ */
+
+extern unsigned int debug; /* debug parameter */
+extern bool verbose_debug; /* -v: whether to print a lot */
+extern char *total_name[TIME_COUNT]; /* basic function names */
+extern long total_time[TIME_COUNT]; /* time spent in basic fcts */
+extern int total_calls[TIME_COUNT]; /* # calls to each fct */
+
+extern bool echo_comments; /* turned off by -eat option */
+extern bool echo_unknown_commands; /* always true ?? */
+extern bool force_irredundant; /* -nirr command line option */
+extern bool skip_make_sparse;
+extern bool kiss; /* -kiss command line option */
+extern bool pos; /* -pos command line option */
+extern bool print_solution; /* -x command line option */
+extern bool recompute_onset; /* -onset command line option */
+extern bool remove_essential; /* -ness command line option */
+extern bool single_expand; /* -fast command line option */
+extern bool summary; /* -s command line option */
+extern bool trace; /* -t command line option */
+extern bool unwrap_onset; /* -nunwrap command line option */
+extern bool use_random_order; /* -random command line option */
+extern bool use_super_gasp; /* -strong command line option */
+extern char *filename; /* filename PLA was read from */
+extern bool debug_exact_minimization; /* dumps info for -do exact */
+
+
+/*
+ * pla_types are the input and output types for reading/writing a PLA
+ */
+struct pla_types_struct {
+ char *key;
+ int value;
+};
+
+
+/*
+ * The cube structure is a global structure which contains information
+ * on how a set maps into a cube -- i.e., number of parts per variable,
+ * number of variables, etc. Also, many fields are pre-computed to
+ * speed up various primitive operations.
+ */
+#define CUBE_TEMP 10
+
+struct cube_struct {
+ int size; /* set size of a cube */
+ int num_vars; /* number of variables in a cube */
+ int num_binary_vars; /* number of binary variables */
+ int *first_part; /* first element of each variable */
+ int *last_part; /* first element of each variable */
+ int *part_size; /* number of elements in each variable */
+ int *first_word; /* first word for each variable */
+ int *last_word; /* last word for each variable */
+ pset binary_mask; /* Mask to extract binary variables */
+ pset mv_mask; /* mask to get mv parts */
+ pset *var_mask; /* mask to extract a variable */
+ pset *temp; /* an array of temporary sets */
+ pset fullset; /* a full cube */
+ pset emptyset; /* an empty cube */
+ unsigned int inmask; /* mask to get odd word of binary part */
+ int inword; /* which word number for above */
+ int *sparse; /* should this variable be sparse? */
+ int num_mv_vars; /* number of multiple-valued variables */
+ int output; /* which variable is "output" (-1 if none) */
+};
+
+struct cdata_struct {
+ int *part_zeros; /* count of zeros for each element */
+ int *var_zeros; /* count of zeros for each variable */
+ int *parts_active; /* number of "active" parts for each var */
+ bool *is_unate; /* indicates given var is unate */
+ int vars_active; /* number of "active" variables */
+ int vars_unate; /* number of unate variables */
+ int best; /* best "binate" variable */
+};
+
+
+extern struct pla_types_struct pla_types[];
+extern struct cube_struct cube, temp_cube_save;
+extern struct cdata_struct cdata, temp_cdata_save;
+
+#ifdef lint
+#define DISJOINT 0x5555
+#else
+#if BPI == 32
+#define DISJOINT 0x55555555
+#else
+#define DISJOINT 0x5555
+#endif
+#endif
+
+/* function declarations */
+
+/* cofactor.c */ extern int binate_split_select();
+/* cofactor.c */ extern pcover cubeunlist();
+/* cofactor.c */ extern pcube *cofactor();
+/* cofactor.c */ extern pcube *cube1list();
+/* cofactor.c */ extern pcube *cube2list();
+/* cofactor.c */ extern pcube *cube3list();
+/* cofactor.c */ extern pcube *scofactor();
+/* cofactor.c */ extern void massive_count();
+/* compl.c */ extern pcover complement();
+/* compl.c */ extern pcover simplify();
+/* compl.c */ extern void simp_comp();
+/* contain.c */ extern int d1_rm_equal();
+/* contain.c */ extern int rm2_contain();
+/* contain.c */ extern int rm2_equal();
+/* contain.c */ extern int rm_contain();
+/* contain.c */ extern int rm_equal();
+/* contain.c */ extern int rm_rev_contain();
+/* contain.c */ extern pset *sf_list();
+/* contain.c */ extern pset *sf_sort();
+/* contain.c */ extern pset_family d1merge();
+/* contain.c */ extern pset_family dist_merge();
+/* contain.c */ extern pset_family sf_contain();
+/* contain.c */ extern pset_family sf_dupl();
+/* contain.c */ extern pset_family sf_ind_contain();
+/* contain.c */ extern pset_family sf_ind_unlist();
+/* contain.c */ extern pset_family sf_merge();
+/* contain.c */ extern pset_family sf_rev_contain();
+/* contain.c */ extern pset_family sf_union();
+/* contain.c */ extern pset_family sf_unlist();
+/* cubestr.c */ extern void cube_setup();
+/* cubestr.c */ extern void restore_cube_struct();
+/* cubestr.c */ extern void save_cube_struct();
+/* cubestr.c */ extern void setdown_cube();
+/* cvrin.c */ extern PLA_labels();
+/* cvrin.c */ extern char *get_word();
+/* cvrin.c */ extern int label_index();
+/* cvrin.c */ extern int read_pla();
+/* cvrin.c */ extern int read_symbolic();
+/* cvrin.c */ extern pPLA new_PLA();
+/* cvrin.c */ extern void PLA_summary();
+/* cvrin.c */ extern void free_PLA();
+/* cvrin.c */ extern void parse_pla();
+/* cvrin.c */ extern void read_cube();
+/* cvrin.c */ extern void skip_line();
+/* cvrm.c */ extern foreach_output_function();
+/* cvrm.c */ extern int cubelist_partition();
+/* cvrm.c */ extern int so_both_do_espresso();
+/* cvrm.c */ extern int so_both_do_exact();
+/* cvrm.c */ extern int so_both_save();
+/* cvrm.c */ extern int so_do_espresso();
+/* cvrm.c */ extern int so_do_exact();
+/* cvrm.c */ extern int so_save();
+/* cvrm.c */ extern pcover cof_output();
+/* cvrm.c */ extern pcover lex_sort();
+/* cvrm.c */ extern pcover mini_sort();
+/* cvrm.c */ extern pcover random_order();
+/* cvrm.c */ extern pcover size_sort();
+/* cvrm.c */ extern pcover sort_reduce();
+/* cvrm.c */ extern pcover uncof_output();
+/* cvrm.c */ extern pcover unravel();
+/* cvrm.c */ extern pcover unravel_range();
+/* cvrm.c */ extern void so_both_espresso();
+/* cvrm.c */ extern void so_espresso();
+/* cvrmisc.c */ extern char *fmt_cost();
+/* cvrmisc.c */ extern char *print_cost();
+/* cvrmisc.c */ extern char *strsav();
+/* cvrmisc.c */ extern void copy_cost();
+/* cvrmisc.c */ extern void cover_cost();
+/* cvrmisc.c */ extern void fatal();
+/* cvrmisc.c */ extern void print_trace();
+/* cvrmisc.c */ extern void size_stamp();
+/* cvrmisc.c */ extern void totals();
+/* cvrout.c */ extern char *fmt_cube();
+/* cvrout.c */ extern char *fmt_expanded_cube();
+/* cvrout.c */ extern char *pc1();
+/* cvrout.c */ extern char *pc2();
+/* cvrout.c */ extern char *pc3();
+/* cvrout.c */ extern int makeup_labels();
+/* cvrout.c */ extern kiss_output();
+/* cvrout.c */ extern kiss_print_cube();
+/* cvrout.c */ extern output_symbolic_constraints();
+/* cvrout.c */ extern void cprint();
+/* cvrout.c */ extern void debug1_print();
+/* cvrout.c */ extern void debug_print();
+/* cvrout.c */ extern void eqn_output();
+/* cvrout.c */ extern void fpr_header();
+/* cvrout.c */ extern void fprint_pla();
+/* cvrout.c */ extern void pls_group();
+/* cvrout.c */ extern void pls_label();
+/* cvrout.c */ extern void pls_output();
+/* cvrout.c */ extern void print_cube();
+/* cvrout.c */ extern void print_expanded_cube();
+/* cvrout.c */ extern void sf_debug_print();
+/* equiv.c */ extern find_equiv_outputs();
+/* equiv.c */ extern int check_equiv();
+/* espresso.c */ extern pcover espresso();
+/* essen.c */ extern bool essen_cube();
+/* essen.c */ extern pcover cb_consensus();
+/* essen.c */ extern pcover cb_consensus_dist0();
+/* essen.c */ extern pcover essential();
+/* exact.c */ extern pcover minimize_exact();
+/* exact.c */ extern pcover minimize_exact_literals();
+/* expand.c */ extern bool feasibly_covered();
+/* expand.c */ extern int most_frequent();
+/* expand.c */ extern pcover all_primes();
+/* expand.c */ extern pcover expand();
+/* expand.c */ extern pcover find_all_primes();
+/* expand.c */ extern void elim_lowering();
+/* expand.c */ extern void essen_parts();
+/* expand.c */ extern void essen_raising();
+/* expand.c */ extern void expand1();
+/* expand.c */ extern void mincov();
+/* expand.c */ extern void select_feasible();
+/* expand.c */ extern void setup_BB_CC();
+/* gasp.c */ extern pcover expand_gasp();
+/* gasp.c */ extern pcover irred_gasp();
+/* gasp.c */ extern pcover last_gasp();
+/* gasp.c */ extern pcover super_gasp();
+/* gasp.c */ extern void expand1_gasp();
+/* getopt.c */ extern int util_getopt();
+/* hack.c */ extern find_dc_inputs();
+/* hack.c */ extern find_inputs();
+/* hack.c */ extern form_bitvector();
+/* hack.c */ extern map_dcset();
+/* hack.c */ extern map_output_symbolic();
+/* hack.c */ extern map_symbolic();
+/* hack.c */ extern pcover map_symbolic_cover();
+/* hack.c */ extern symbolic_hack_labels();
+/* irred.c */ extern bool cube_is_covered();
+/* irred.c */ extern bool taut_special_cases();
+/* irred.c */ extern bool tautology();
+/* irred.c */ extern pcover irredundant();
+/* irred.c */ extern void mark_irredundant();
+/* irred.c */ extern void irred_split_cover();
+/* irred.c */ extern sm_matrix *irred_derive_table();
+/* map.c */ extern pset minterms();
+/* map.c */ extern void explode();
+/* map.c */ extern void map();
+/* opo.c */ extern output_phase_setup();
+/* opo.c */ extern pPLA set_phase();
+/* opo.c */ extern pcover opo();
+/* opo.c */ extern pcube find_phase();
+/* opo.c */ extern pset_family find_covers();
+/* opo.c */ extern pset_family form_cover_table();
+/* opo.c */ extern pset_family opo_leaf();
+/* opo.c */ extern pset_family opo_recur();
+/* opo.c */ extern void opoall();
+/* opo.c */ extern void phase_assignment();
+/* opo.c */ extern void repeated_phase_assignment();
+/* pair.c */ extern generate_all_pairs();
+/* pair.c */ extern int **find_pairing_cost();
+/* pair.c */ extern int find_best_cost();
+/* pair.c */ extern int greedy_best_cost();
+/* pair.c */ extern int minimize_pair();
+/* pair.c */ extern int pair_free();
+/* pair.c */ extern pair_all();
+/* pair.c */ extern pcover delvar();
+/* pair.c */ extern pcover pairvar();
+/* pair.c */ extern ppair pair_best_cost();
+/* pair.c */ extern ppair pair_new();
+/* pair.c */ extern ppair pair_save();
+/* pair.c */ extern print_pair();
+/* pair.c */ extern void find_optimal_pairing();
+/* pair.c */ extern void set_pair();
+/* pair.c */ extern void set_pair1();
+/* primes.c */ extern pcover primes_consensus();
+/* reduce.c */ extern bool sccc_special_cases();
+/* reduce.c */ extern pcover reduce();
+/* reduce.c */ extern pcube reduce_cube();
+/* reduce.c */ extern pcube sccc();
+/* reduce.c */ extern pcube sccc_cube();
+/* reduce.c */ extern pcube sccc_merge();
+/* set.c */ extern bool set_andp();
+/* set.c */ extern bool set_orp();
+/* set.c */ extern bool setp_disjoint();
+/* set.c */ extern bool setp_empty();
+/* set.c */ extern bool setp_equal();
+/* set.c */ extern bool setp_full();
+/* set.c */ extern bool setp_implies();
+/* set.c */ extern char *pbv1();
+/* set.c */ extern char *ps1();
+/* set.c */ extern int *sf_count();
+/* set.c */ extern int *sf_count_restricted();
+/* set.c */ extern int bit_index();
+/* set.c */ extern int set_dist();
+/* set.c */ extern int set_ord();
+/* set.c */ extern void set_adjcnt();
+/* set.c */ extern pset set_and();
+/* set.c */ extern pset set_clear();
+/* set.c */ extern pset set_copy();
+/* set.c */ extern pset set_diff();
+/* set.c */ extern pset set_fill();
+/* set.c */ extern pset set_merge();
+/* set.c */ extern pset set_or();
+/* set.c */ extern pset set_xor();
+/* set.c */ extern pset sf_and();
+/* set.c */ extern pset sf_or();
+/* set.c */ extern pset_family sf_active();
+/* set.c */ extern pset_family sf_addcol();
+/* set.c */ extern pset_family sf_addset();
+/* set.c */ extern pset_family sf_append();
+/* set.c */ extern pset_family sf_bm_read();
+/* set.c */ extern pset_family sf_compress();
+/* set.c */ extern pset_family sf_copy();
+/* set.c */ extern pset_family sf_copy_col();
+/* set.c */ extern pset_family sf_delc();
+/* set.c */ extern pset_family sf_delcol();
+/* set.c */ extern pset_family sf_inactive();
+/* set.c */ extern pset_family sf_join();
+/* set.c */ extern pset_family sf_new();
+/* set.c */ extern pset_family sf_permute();
+/* set.c */ extern pset_family sf_read();
+/* set.c */ extern pset_family sf_save();
+/* set.c */ extern pset_family sf_transpose();
+/* set.c */ extern void set_write();
+/* set.c */ extern void sf_bm_print();
+/* set.c */ extern void sf_cleanup();
+/* set.c */ extern void sf_delset();
+/* set.c */ extern void sf_free();
+/* set.c */ extern void sf_print();
+/* set.c */ extern void sf_write();
+/* setc.c */ extern bool ccommon();
+/* setc.c */ extern bool cdist0();
+/* setc.c */ extern bool full_row();
+/* setc.c */ extern int ascend();
+/* setc.c */ extern int cactive();
+/* setc.c */ extern int cdist();
+/* setc.c */ extern int cdist01();
+/* setc.c */ extern int cvolume();
+/* setc.c */ extern int d1_order();
+/* setc.c */ extern int d1_order_size();
+/* setc.c */ extern int desc1();
+/* setc.c */ extern int descend();
+/* setc.c */ extern int lex_order();
+/* setc.c */ extern int lex_order1();
+/* setc.c */ extern pset force_lower();
+/* setc.c */ extern void consensus();
+/* sharp.c */ extern pcover cb1_dsharp();
+/* sharp.c */ extern pcover cb_dsharp();
+/* sharp.c */ extern pcover cb_recur_dsharp();
+/* sharp.c */ extern pcover cb_recur_sharp();
+/* sharp.c */ extern pcover cb_sharp();
+/* sharp.c */ extern pcover cv_dsharp();
+/* sharp.c */ extern pcover cv_intersect();
+/* sharp.c */ extern pcover cv_sharp();
+/* sharp.c */ extern pcover dsharp();
+/* sharp.c */ extern pcover make_disjoint();
+/* sharp.c */ extern pcover sharp();
+/* sminterf.c */pset do_sm_minimum_cover();
+/* sparse.c */ extern pcover make_sparse();
+/* sparse.c */ extern pcover mv_reduce();
+#if !defined(__osf__) && !defined(__STDC__) && !defined(__hpux)
+/* ucbqsort.c */ extern qsort();
+#endif
+/* ucbqsort.c */ extern qst();
+/* unate.c */ extern pcover find_all_minimal_covers_petrick();
+/* unate.c */ extern pcover map_cover_to_unate();
+/* unate.c */ extern pcover map_unate_to_cover();
+/* unate.c */ extern pset_family exact_minimum_cover();
+/* unate.c */ extern pset_family gen_primes();
+/* unate.c */ extern pset_family unate_compl();
+/* unate.c */ extern pset_family unate_complement();
+/* unate.c */ extern pset_family unate_intersect();
+/* verify.c */ extern PLA_permute();
+/* verify.c */ extern bool PLA_verify();
+/* verify.c */ extern bool check_consistency();
+/* verify.c */ extern bool verify();
diff --git a/src/misc/espresso/essen.c b/src/misc/espresso/essen.c
new file mode 100644
index 00000000..6a46295d
--- /dev/null
+++ b/src/misc/espresso/essen.c
@@ -0,0 +1,179 @@
+/*
+ * Revision Control Information
+ *
+ * $Source$
+ * $Author$
+ * $Revision$
+ * $Date$
+ *
+ */
+/*
+ module: essen.c
+ purpose: Find essential primes in a multiple-valued function
+*/
+
+#include "espresso.h"
+
+/*
+ essential -- return a cover consisting of the cubes of F which are
+ essential prime implicants (with respect to F u D); Further, remove
+ these cubes from the ON-set F, and add them to the OFF-set D.
+
+ Sometimes EXPAND can determine that a cube is not an essential prime.
+ If so, it will set the "NONESSEN" flag in the cube.
+
+ We count on IRREDUNDANT to have set the flag RELESSEN to indicate
+ that a prime was relatively essential (i.e., covers some minterm
+ not contained in any other prime in the current cover), or to have
+ reset the flag to indicate that a prime was relatively redundant
+ (i.e., all minterms covered by other primes in the current cover).
+ Of course, after executing irredundant, all of the primes in the
+ cover are relatively essential, but we can mark the primes which
+ were redundant at the start of irredundant and avoid an extra check
+ on these primes for essentiality.
+*/
+
+pcover essential(Fp, Dp)
+IN pcover *Fp, *Dp;
+{
+ register pcube last, p;
+ pcover E, F = *Fp, D = *Dp;
+
+ /* set all cubes in F active */
+ (void) sf_active(F);
+
+ /* Might as well start out with some cubes in E */
+ E = new_cover(10);
+
+ foreach_set(F, last, p) {
+ /* don't test a prime which EXPAND says is nonessential */
+ if (! TESTP(p, NONESSEN)) {
+ /* only test a prime which was relatively essential */
+ if (TESTP(p, RELESSEN)) {
+ /* Check essentiality */
+ if (essen_cube(F, D, p)) {
+ if (debug & ESSEN)
+ printf("ESSENTIAL: %s\n", pc1(p));
+ E = sf_addset(E, p);
+ RESET(p, ACTIVE);
+ F->active_count--;
+ }
+ }
+ }
+ }
+
+ *Fp = sf_inactive(F); /* delete the inactive cubes from F */
+ *Dp = sf_join(D, E); /* add the essentials to D */
+ sf_free(D);
+ return E;
+}
+
+/*
+ essen_cube -- check if a single cube is essential or not
+
+ The prime c is essential iff
+
+ consensus((F u D) # c, c) u D
+
+ does not contain c.
+*/
+bool essen_cube(F, D, c)
+IN pcover F, D;
+IN pcube c;
+{
+ pcover H, FD;
+ pcube *H1;
+ bool essen;
+
+ /* Append F and D together, and take the sharp-consensus with c */
+ FD = sf_join(F, D);
+ H = cb_consensus(FD, c);
+ free_cover(FD);
+
+ /* Add the don't care set, and see if this covers c */
+ H1 = cube2list(H, D);
+ essen = ! cube_is_covered(H1, c);
+ free_cubelist(H1);
+
+ free_cover(H);
+ return essen;
+}
+
+
+/*
+ * cb_consensus -- compute consensus(T # c, c)
+ */
+pcover cb_consensus(T, c)
+register pcover T;
+register pcube c;
+{
+ register pcube temp, last, p;
+ register pcover R;
+
+ R = new_cover(T->count*2);
+ temp = new_cube();
+ foreach_set(T, last, p) {
+ if (p != c) {
+ switch (cdist01(p, c)) {
+ case 0:
+ /* distance-0 needs special care */
+ R = cb_consensus_dist0(R, p, c);
+ break;
+
+ case 1:
+ /* distance-1 is easy because no sharping required */
+ consensus(temp, p, c);
+ R = sf_addset(R, temp);
+ break;
+ }
+ }
+ }
+ set_free(temp);
+ return R;
+}
+
+
+/*
+ * form the sharp-consensus for p and c when they intersect
+ * What we are forming is consensus(p # c, c).
+ */
+pcover cb_consensus_dist0(R, p, c)
+pcover R;
+register pcube p, c;
+{
+ int var;
+ bool got_one;
+ register pcube temp, mask;
+ register pcube p_diff_c=cube.temp[0], p_and_c=cube.temp[1];
+
+ /* If c contains p, then this gives us no information for essential test */
+ if (setp_implies(p, c)) {
+ return R;
+ }
+
+ /* For the multiple-valued variables */
+ temp = new_cube();
+ got_one = FALSE;
+ INLINEset_diff(p_diff_c, p, c);
+ INLINEset_and(p_and_c, p, c);
+
+ for(var = cube.num_binary_vars; var < cube.num_vars; var++) {
+ /* Check if c(var) is contained in p(var) -- if so, no news */
+ mask = cube.var_mask[var];
+ if (! setp_disjoint(p_diff_c, mask)) {
+ INLINEset_merge(temp, c, p_and_c, mask);
+ R = sf_addset(R, temp);
+ got_one = TRUE;
+ }
+ }
+
+ /* if no cube so far, add one for the intersection */
+ if (! got_one && cube.num_binary_vars > 0) {
+ /* Add a single cube for the intersection of p and c */
+ INLINEset_and(temp, p, c);
+ R = sf_addset(R, temp);
+ }
+
+ set_free(temp);
+ return R;
+}
diff --git a/src/misc/espresso/exact.c b/src/misc/espresso/exact.c
new file mode 100644
index 00000000..b1943636
--- /dev/null
+++ b/src/misc/espresso/exact.c
@@ -0,0 +1,181 @@
+/*
+ * Revision Control Information
+ *
+ * $Source$
+ * $Author$
+ * $Revision$
+ * $Date$
+ *
+ */
+#include "espresso.h"
+
+
+static void dump_irredundant();
+static pcover do_minimize();
+
+
+/*
+ * minimize_exact -- main entry point for exact minimization
+ *
+ * Global flags which affect this routine are:
+ *
+ * debug
+ * skip_make_sparse
+ */
+
+pcover
+minimize_exact(F, D, R, exact_cover)
+pcover F, D, R;
+int exact_cover;
+{
+ return do_minimize(F, D, R, exact_cover, /*weighted*/ 0);
+}
+
+
+pcover
+minimize_exact_literals(F, D, R, exact_cover)
+pcover F, D, R;
+int exact_cover;
+{
+ return do_minimize(F, D, R, exact_cover, /*weighted*/ 1);
+}
+
+
+
+static pcover
+do_minimize(F, D, R, exact_cover, weighted)
+pcover F, D, R;
+int exact_cover;
+int weighted;
+{
+ pcover newF, E, Rt, Rp;
+ pset p, last;
+ int heur, level, *weights, i;
+ sm_matrix *table;
+ sm_row *cover;
+ sm_element *pe;
+ int debug_save = debug;
+
+ if (debug & EXACT) {
+ debug |= (IRRED | MINCOV);
+ }
+#if defined(sun) || defined(bsd4_2) /* hack ... */
+ if (debug & MINCOV) {
+ setlinebuf(stdout);
+ }
+#endif
+ level = (debug & MINCOV) ? 4 : 0;
+ heur = ! exact_cover;
+
+ /* Generate all prime implicants */
+ EXEC(F = primes_consensus(cube2list(F, D)), "PRIMES ", F);
+
+ /* Setup the prime implicant table */
+ EXEC(irred_split_cover(F, D, &E, &Rt, &Rp), "ESSENTIALS ", E);
+ EXEC(table = irred_derive_table(D, E, Rp), "PI-TABLE ", Rp);
+
+ /* Solve either a weighted or nonweighted covering problem */
+ if (weighted) {
+ /* correct only for all 2-valued variables */
+ weights = ALLOC(int, F->count);
+ foreach_set(Rp, last, p) {
+ weights[SIZE(p)] = cube.size - set_ord(p);
+ /* We have added the 0's in the output part instead of the 1's.
+ This loop corrects the literal count. */
+ for (i = cube.first_part[cube.output];
+ i <= cube.last_part[cube.output]; i++) {
+ is_in_set(p, i) ? weights[SIZE(p)]++ : weights[SIZE(p)]--;
+ }
+ }
+ } else {
+ weights = NIL(int);
+ }
+ EXEC(cover=sm_minimum_cover(table,weights,heur,level), "MINCOV ", F);
+ if (weights != 0) {
+ FREE(weights);
+ }
+
+ if (debug & EXACT) {
+ dump_irredundant(E, Rt, Rp, table);
+ }
+
+ /* Form the result cover */
+ newF = new_cover(100);
+ foreach_set(E, last, p) {
+ newF = sf_addset(newF, p);
+ }
+ sm_foreach_row_element(cover, pe) {
+ newF = sf_addset(newF, GETSET(F, pe->col_num));
+ }
+
+ free_cover(E);
+ free_cover(Rt);
+ free_cover(Rp);
+ sm_free(table);
+ sm_row_free(cover);
+ free_cover(F);
+
+ /* Attempt to make the results more sparse */
+ debug &= ~ (IRRED | SHARP | MINCOV);
+ if (! skip_make_sparse && R != 0) {
+ newF = make_sparse(newF, D, R);
+ }
+
+ debug = debug_save;
+ return newF;
+}
+
+static void
+dump_irredundant(E, Rt, Rp, table)
+pcover E, Rt, Rp;
+sm_matrix *table;
+{
+ FILE *fp_pi_table, *fp_primes;
+ pPLA PLA;
+ pset last, p;
+ char *file;
+
+ if (filename == 0 || strcmp(filename, "(stdin)") == 0) {
+ fp_pi_table = fp_primes = stdout;
+ } else {
+ file = ALLOC(char, strlen(filename)+20);
+ (void) sprintf(file, "%s.primes", filename);
+ if ((fp_primes = fopen(file, "w")) == NULL) {
+ (void) fprintf(stderr, "espresso: Unable to open %s\n", file);
+ fp_primes = stdout;
+ }
+ (void) sprintf(file, "%s.pi", filename);
+ if ((fp_pi_table = fopen(file, "w")) == NULL) {
+ (void) fprintf(stderr, "espresso: Unable to open %s\n", file);
+ fp_pi_table = stdout;
+ }
+ FREE(file);
+ }
+
+ PLA = new_PLA();
+ PLA_labels(PLA);
+
+ fpr_header(fp_primes, PLA, F_type);
+ free_PLA(PLA);
+
+ (void) fprintf(fp_primes, "# Essential primes are\n");
+ foreach_set(E, last, p) {
+ (void) fprintf(fp_primes, "%s\n", pc1(p));
+ }
+ (void) fprintf(fp_primes, "# Totally redundant primes are\n");
+ foreach_set(Rt, last, p) {
+ (void) fprintf(fp_primes, "%s\n", pc1(p));
+ }
+ (void) fprintf(fp_primes, "# Partially redundant primes are\n");
+ foreach_set(Rp, last, p) {
+ (void) fprintf(fp_primes, "%s\n", pc1(p));
+ }
+ if (fp_primes != stdout) {
+ (void) fclose(fp_primes);
+ }
+
+ sm_write(fp_pi_table, table);
+ if (fp_pi_table != stdout) {
+ (void) fclose(fp_pi_table);
+ }
+}
diff --git a/src/misc/espresso/expand.c b/src/misc/espresso/expand.c
new file mode 100644
index 00000000..2765d71c
--- /dev/null
+++ b/src/misc/espresso/expand.c
@@ -0,0 +1,693 @@
+/*
+ * Revision Control Information
+ *
+ * $Source$
+ * $Author$
+ * $Revision$
+ * $Date$
+ *
+ */
+/*
+ module: expand.c
+ purpose: Perform the Espresso-II Expansion Step
+
+ The idea is to take each nonprime cube of the on-set and expand it
+ into a prime implicant such that we can cover as many other cubes
+ of the on-set. If no cube of the on-set can be covered, then we
+ expand each cube into a large prime implicant by transforming the
+ problem into a minimum covering problem which is solved by the
+ heuristics of minimum_cover.
+
+ These routines revolve around having a representation of the
+ OFF-set. (In contrast to the Espresso-II manuscript, we do NOT
+ require an "unwrapped" version of the OFF-set).
+
+ Some conventions on variable names:
+
+ SUPER_CUBE is the supercube of all cubes which can be covered
+ by an expansion of the cube being expanded
+
+ OVEREXPANDED_CUBE is the cube which would result from expanding
+ all parts which can expand individually of the cube being expanded
+
+ RAISE is the current expansion of the current cube
+
+ FREESET is the set of parts which haven't been raised or lowered yet.
+
+ INIT_LOWER is a set of parts to be removed from the free parts before
+ starting the expansion
+*/
+
+#include "espresso.h"
+
+/*
+ expand -- expand each nonprime cube of F into a prime implicant
+
+ If nonsparse is true, only the non-sparse variables will be expanded;
+ this is done by forcing all of the sparse variables out of the free set.
+*/
+
+pcover expand(F, R, nonsparse)
+INOUT pcover F;
+IN pcover R;
+IN bool nonsparse; /* expand non-sparse variables only */
+{
+ register pcube last, p;
+ pcube RAISE, FREESET, INIT_LOWER, SUPER_CUBE, OVEREXPANDED_CUBE;
+ int var, num_covered;
+ bool change;
+
+ /* Order the cubes according to "chewing-away from the edges" of mini */
+ if (use_random_order)
+ F = random_order(F);
+ else
+ F = mini_sort(F, ascend);
+
+ /* Allocate memory for variables needed by expand1() */
+ RAISE = new_cube();
+ FREESET = new_cube();
+ INIT_LOWER = new_cube();
+ SUPER_CUBE = new_cube();
+ OVEREXPANDED_CUBE = new_cube();
+
+ /* Setup the initial lowering set (differs only for nonsparse) */
+ if (nonsparse)
+ for(var = 0; var < cube.num_vars; var++)
+ if (cube.sparse[var])
+ (void) set_or(INIT_LOWER, INIT_LOWER, cube.var_mask[var]);
+
+ /* Mark all cubes as not covered, and maybe essential */
+ foreach_set(F, last, p) {
+ RESET(p, COVERED);
+ RESET(p, NONESSEN);
+ }
+
+ /* Try to expand each nonprime and noncovered cube */
+ foreach_set(F, last, p) {
+ /* do not expand if PRIME or if covered by previous expansion */
+ if (! TESTP(p, PRIME) && ! TESTP(p, COVERED)) {
+
+ /* expand the cube p, result is RAISE */
+ expand1(R, F, RAISE, FREESET, OVEREXPANDED_CUBE, SUPER_CUBE,
+ INIT_LOWER, &num_covered, p);
+ if (debug & EXPAND)
+ printf("EXPAND: %s (covered %d)\n", pc1(p), num_covered);
+ (void) set_copy(p, RAISE);
+ SET(p, PRIME);
+ RESET(p, COVERED); /* not really necessary */
+
+ /* See if we generated an inessential prime */
+ if (num_covered == 0 && ! setp_equal(p, OVEREXPANDED_CUBE)) {
+ SET(p, NONESSEN);
+ }
+ }
+ }
+
+ /* Delete any cubes of F which became covered during the expansion */
+ F->active_count = 0;
+ change = FALSE;
+ foreach_set(F, last, p) {
+ if (TESTP(p, COVERED)) {
+ RESET(p, ACTIVE);
+ change = TRUE;
+ } else {
+ SET(p, ACTIVE);
+ F->active_count++;
+ }
+ }
+ if (change)
+ F = sf_inactive(F);
+
+ free_cube(RAISE);
+ free_cube(FREESET);
+ free_cube(INIT_LOWER);
+ free_cube(SUPER_CUBE);
+ free_cube(OVEREXPANDED_CUBE);
+ return F;
+}
+
+/*
+ expand1 -- Expand a single cube against the OFF-set
+*/
+void expand1(BB, CC, RAISE, FREESET, OVEREXPANDED_CUBE, SUPER_CUBE,
+ INIT_LOWER, num_covered, c)
+pcover BB; /* Blocking matrix (OFF-set) */
+pcover CC; /* Covering matrix (ON-set) */
+pcube RAISE; /* The current parts which have been raised */
+pcube FREESET; /* The current parts which are free */
+pcube OVEREXPANDED_CUBE; /* Overexpanded cube of c */
+pcube SUPER_CUBE; /* Supercube of all cubes of CC we cover */
+pcube INIT_LOWER; /* Parts to initially remove from FREESET */
+int *num_covered; /* Number of cubes of CC which are covered */
+pcube c; /* The cube to be expanded */
+{
+ int bestindex;
+
+ if (debug & EXPAND1)
+ printf("\nEXPAND1: \t%s\n", pc1(c));
+
+ /* initialize BB and CC */
+ SET(c, PRIME); /* don't try to cover ourself */
+ setup_BB_CC(BB, CC);
+
+ /* initialize count of # cubes covered, and the supercube of them */
+ *num_covered = 0;
+ (void) set_copy(SUPER_CUBE, c);
+
+ /* Initialize the lowering, raising and unassigned sets */
+ (void) set_copy(RAISE, c);
+ (void) set_diff(FREESET, cube.fullset, RAISE);
+
+ /* If some parts are forced into lowering set, remove them */
+ if (! setp_empty(INIT_LOWER)) {
+ (void) set_diff(FREESET, FREESET, INIT_LOWER);
+ elim_lowering(BB, CC, RAISE, FREESET);
+ }
+
+ /* Determine what can be raised, and return the over-expanded cube */
+ essen_parts(BB, CC, RAISE, FREESET);
+ (void) set_or(OVEREXPANDED_CUBE, RAISE, FREESET);
+
+ /* While there are still cubes which can be covered, cover them ! */
+ if (CC->active_count > 0) {
+ select_feasible(BB, CC, RAISE, FREESET, SUPER_CUBE, num_covered);
+ }
+
+ /* While there are still cubes covered by the overexpanded cube ... */
+ while (CC->active_count > 0) {
+ bestindex = most_frequent(CC, FREESET);
+ set_insert(RAISE, bestindex);
+ set_remove(FREESET, bestindex);
+ essen_parts(BB, CC, RAISE, FREESET);
+ }
+
+ /* Finally, when all else fails, choose the largest possible prime */
+ /* We will loop only if we decide unravelling OFF-set is too expensive */
+ while (BB->active_count > 0) {
+ mincov(BB, RAISE, FREESET);
+ }
+
+ /* Raise any remaining free coordinates */
+ (void) set_or(RAISE, RAISE, FREESET);
+}
+
+/*
+ essen_parts -- determine which parts are forced into the lowering
+ set to insure that the cube be orthognal to the OFF-set.
+
+ If any cube of the OFF-set is distance 1 from the raising cube,
+ then we must lower all parts of the conflicting variable. (If the
+ cube is distance 0, we detect this error here.)
+
+ If there are essentially lowered parts, we can remove from consideration
+ any cubes of the OFF-set which are more than distance 1 from the
+ overexpanded cube of RAISE.
+*/
+
+void essen_parts(BB, CC, RAISE, FREESET)
+pcover BB, CC;
+pcube RAISE, FREESET;
+{
+ register pcube p, r = RAISE;
+ pcube lastp, xlower = cube.temp[0];
+ int dist;
+
+ (void) set_copy(xlower, cube.emptyset);
+
+ foreach_active_set(BB, lastp, p) {
+#ifdef NO_INLINE
+ if ((dist = cdist01(p, r)) > 1) goto exit_if;
+#else
+ {register int w,last;register unsigned int x;dist=0;if((last=cube.inword)!=-1)
+{x=p[last]&r[last];if(x=~(x|x>>1)&cube.inmask)if((dist=count_ones(x))>1)goto
+exit_if;for(w=1;w<last;w++){x=p[w]&r[w];if(x=~(x|x>>1)&DISJOINT)if(dist==1||(
+dist+=count_ones(x))>1)goto exit_if;}}}{register int w,var,last;register pcube
+mask;for(var=cube.num_binary_vars;var<cube.num_vars;var++){mask=cube.var_mask[
+var];last=cube.last_word[var];for(w=cube.first_word[var];w<=last;w++)if(p[w]&r[
+w]&mask[w])goto nextvar;if(++dist>1)goto exit_if;nextvar:;}}
+#endif
+ if (dist == 0) {
+ fatal("ON-set and OFF-set are not orthogonal");
+ } else {
+ (void) force_lower(xlower, p, r);
+ BB->active_count--;
+ RESET(p, ACTIVE);
+ }
+exit_if: ;
+ }
+
+ if (! setp_empty(xlower)) {
+ (void) set_diff(FREESET, FREESET, xlower);/* remove from free set */
+ elim_lowering(BB, CC, RAISE, FREESET);
+ }
+
+ if (debug & EXPAND1)
+ printf("ESSEN_PARTS:\tRAISE=%s FREESET=%s\n", pc1(RAISE), pc2(FREESET));
+}
+
+/*
+ essen_raising -- determine which parts may always be added to
+ the raising set without restricting further expansions
+
+ General rule: if some part is not blocked by any cube of BB, then
+ this part can always be raised.
+*/
+
+void essen_raising(BB, RAISE, FREESET)
+register pcover BB;
+pcube RAISE, FREESET;
+{
+ register pcube last, p, xraise = cube.temp[0];
+
+ /* Form union of all cubes of BB, and then take complement wrt FREESET */
+ (void) set_copy(xraise, cube.emptyset);
+ foreach_active_set(BB, last, p)
+ INLINEset_or(xraise, xraise, p);
+ (void) set_diff(xraise, FREESET, xraise);
+
+ (void) set_or(RAISE, RAISE, xraise); /* add to raising set */
+ (void) set_diff(FREESET, FREESET, xraise); /* remove from free set */
+
+ if (debug & EXPAND1)
+ printf("ESSEN_RAISING:\tRAISE=%s FREESET=%s\n",
+ pc1(RAISE), pc2(FREESET));
+}
+
+/*
+ elim_lowering -- after removing parts from FREESET, we can reduce the
+ size of both BB and CC.
+
+ We mark as inactive any cube of BB which does not intersect the
+ overexpanded cube (i.e., RAISE + FREESET). Likewise, we remove
+ from CC any cube which is not covered by the overexpanded cube.
+*/
+
+void elim_lowering(BB, CC, RAISE, FREESET)
+pcover BB, CC;
+pcube RAISE, FREESET;
+{
+ register pcube p, r = set_or(cube.temp[0], RAISE, FREESET);
+ pcube last;
+
+ /*
+ * Remove sets of BB which are orthogonal to future expansions
+ */
+ foreach_active_set(BB, last, p) {
+#ifdef NO_INLINE
+ if (! cdist0(p, r))
+#else
+ {register int w,lastw;register unsigned int x;if((lastw=cube.inword)!=-1){x=p[
+lastw]&r[lastw];if(~(x|x>>1)&cube.inmask)goto false;for(w=1;w<lastw;w++){x=p[w]
+&r[w];if(~(x|x>>1)&DISJOINT)goto false;}}}{register int w,var,lastw;register
+pcube mask;for(var=cube.num_binary_vars;var<cube.num_vars;var++){mask=cube.
+var_mask[var];lastw=cube.last_word[var];for(w=cube.first_word[var];w<=lastw;w++)
+if(p[w]&r[w]&mask[w])goto nextvar;goto false;nextvar:;}}continue;false:
+#endif
+ BB->active_count--, RESET(p, ACTIVE);
+ }
+
+
+ /*
+ * Remove sets of CC which cannot be covered by future expansions
+ */
+ if (CC != (pcover) NULL) {
+ foreach_active_set(CC, last, p) {
+#ifdef NO_INLINE
+ if (! setp_implies(p, r))
+#else
+ INLINEsetp_implies(p, r, /* when false => */ goto false1);
+ /* when true => go to end of loop */ continue;
+ false1:
+#endif
+ CC->active_count--, RESET(p, ACTIVE);
+ }
+ }
+}
+
+/*
+ most_frequent -- When all else fails, select a reasonable part to raise
+ The active cubes of CC are the cubes which are covered by the
+ overexpanded cube of the original cube (however, we know that none
+ of them can actually be covered by a feasible expansion of the
+ original cube). We resort to the MINI strategy of selecting to
+ raise the part which will cover the same part in the most cubes of CC.
+*/
+int most_frequent(CC, FREESET)
+pcover CC;
+pcube FREESET;
+{
+ register int i, best_part, best_count, *count;
+ register pset p, last;
+
+ /* Count occurences of each variable */
+ count = ALLOC(int, cube.size);
+ for(i = 0; i < cube.size; i++)
+ count[i] = 0;
+ if (CC != (pcover) NULL)
+ foreach_active_set(CC, last, p)
+ set_adjcnt(p, count, 1);
+
+ /* Now find which free part occurs most often */
+ best_count = best_part = -1;
+ for(i = 0; i < cube.size; i++)
+ if (is_in_set(FREESET,i) && count[i] > best_count) {
+ best_part = i;
+ best_count = count[i];
+ }
+ FREE(count);
+
+ if (debug & EXPAND1)
+ printf("MOST_FREQUENT:\tbest=%d FREESET=%s\n", best_part, pc2(FREESET));
+ return best_part;
+}
+
+/*
+ setup_BB_CC -- set up the blocking and covering set families;
+
+ Note that the blocking family is merely the set of cubes of R, and
+ that CC is the set of cubes of F which might possibly be covered
+ (i.e., nonprime cubes, and cubes not already covered)
+*/
+
+void setup_BB_CC(BB, CC)
+register pcover BB, CC;
+{
+ register pcube p, last;
+
+ /* Create the block and cover set families */
+ BB->active_count = BB->count;
+ foreach_set(BB, last, p)
+ SET(p, ACTIVE);
+
+ if (CC != (pcover) NULL) {
+ CC->active_count = CC->count;
+ foreach_set(CC, last, p)
+ if (TESTP(p, COVERED) || TESTP(p, PRIME))
+ CC->active_count--, RESET(p, ACTIVE);
+ else
+ SET(p, ACTIVE);
+ }
+}
+
+/*
+ select_feasible -- Determine if there are cubes which can be covered,
+ and if so, raise those parts necessary to cover as many as possible.
+
+ We really don't check to maximize the number that can be covered;
+ instead, we check, for each fcc, how many other fcc remain fcc
+ after expanding to cover the fcc. (Essentially one-level lookahead).
+*/
+
+void select_feasible(BB, CC, RAISE, FREESET, SUPER_CUBE, num_covered)
+pcover BB, CC;
+pcube RAISE, FREESET, SUPER_CUBE;
+int *num_covered;
+{
+ register pcube p, last, bestfeas, *feas;
+ register int i, j;
+ pcube *feas_new_lower;
+ int bestcount, bestsize, count, size, numfeas, lastfeas;
+ pcover new_lower;
+
+ /* Start out with all cubes covered by the over-expanded cube as
+ * the "possibly" feasibly-covered cubes (pfcc)
+ */
+ feas = ALLOC(pcube, CC->active_count);
+ numfeas = 0;
+ foreach_active_set(CC, last, p)
+ feas[numfeas++] = p;
+
+ /* Setup extra cubes to record parts forced low after a covering */
+ feas_new_lower = ALLOC(pcube, CC->active_count);
+ new_lower = new_cover(numfeas);
+ for(i = 0; i < numfeas; i++)
+ feas_new_lower[i] = GETSET(new_lower, i);
+
+
+loop:
+ /* Find the essentially raised parts -- this might cover some cubes
+ for us, without having to find out if they are fcc or not
+ */
+ essen_raising(BB, RAISE, FREESET);
+
+ /* Now check all "possibly" feasibly covered cubes to check feasibility */
+ lastfeas = numfeas;
+ numfeas = 0;
+ for(i = 0; i < lastfeas; i++) {
+ p = feas[i];
+
+ /* Check active because essen_parts might have removed it */
+ if (TESTP(p, ACTIVE)) {
+
+ /* See if the cube is already covered by RAISE --
+ * this can happen because of essen_raising() or because of
+ * the previous "loop"
+ */
+ if (setp_implies(p, RAISE)) {
+ (*num_covered) += 1;
+ (void) set_or(SUPER_CUBE, SUPER_CUBE, p);
+ CC->active_count--;
+ RESET(p, ACTIVE);
+ SET(p, COVERED);
+ /* otherwise, test if it is feasibly covered */
+ } else if (feasibly_covered(BB,p,RAISE,feas_new_lower[numfeas])) {
+ feas[numfeas] = p; /* save the fcc */
+ numfeas++;
+ }
+ }
+ }
+ if (debug & EXPAND1)
+ printf("SELECT_FEASIBLE: started with %d pfcc, ended with %d fcc\n",
+ lastfeas, numfeas);
+
+ /* Exit here if there are no feasibly covered cubes */
+ if (numfeas == 0) {
+ FREE(feas);
+ FREE(feas_new_lower);
+ free_cover(new_lower);
+ return;
+ }
+
+ /* Now find which is the best feasibly covered cube */
+ bestcount = 0;
+ bestsize = 9999;
+ for(i = 0; i < numfeas; i++) {
+ size = set_dist(feas[i], FREESET); /* # of newly raised parts */
+ count = 0; /* # of other cubes which remain fcc after raising */
+
+#define NEW
+#ifdef NEW
+ for(j = 0; j < numfeas; j++)
+ if (setp_disjoint(feas_new_lower[i], feas[j]))
+ count++;
+#else
+ for(j = 0; j < numfeas; j++)
+ if (setp_implies(feas[j], feas[i]))
+ count++;
+#endif
+ if (count > bestcount) {
+ bestcount = count;
+ bestfeas = feas[i];
+ bestsize = size;
+ } else if (count == bestcount && size < bestsize) {
+ bestfeas = feas[i];
+ bestsize = size;
+ }
+ }
+
+ /* Add the necessary parts to the raising set */
+ (void) set_or(RAISE, RAISE, bestfeas);
+ (void) set_diff(FREESET, FREESET, RAISE);
+ if (debug & EXPAND1)
+ printf("FEASIBLE: \tRAISE=%s FREESET=%s\n", pc1(RAISE), pc2(FREESET));
+ essen_parts(BB, CC, RAISE, FREESET);
+ goto loop;
+/* NOTREACHED */
+}
+
+/*
+ feasibly_covered -- determine if the cube c is feasibly covered
+ (i.e., if it is possible to raise all of the necessary variables
+ while still insuring orthogonality with R). Also, if c is feasibly
+ covered, then compute the new set of parts which are forced into
+ the lowering set.
+*/
+
+bool feasibly_covered(BB, c, RAISE, new_lower)
+pcover BB;
+pcube c, RAISE, new_lower;
+{
+ register pcube p, r = set_or(cube.temp[0], RAISE, c);
+ int dist;
+ pcube lastp;
+
+ set_copy(new_lower, cube.emptyset);
+ foreach_active_set(BB, lastp, p) {
+#ifdef NO_INLINE
+ if ((dist = cdist01(p, r)) > 1) goto exit_if;
+#else
+ {register int w,last;register unsigned int x;dist=0;if((last=cube.inword)!=-1)
+{x=p[last]&r[last];if(x=~(x|x>>1)&cube.inmask)if((dist=count_ones(x))>1)goto
+exit_if;for(w=1;w<last;w++){x=p[w]&r[w];if(x=~(x|x>>1)&DISJOINT)if(dist==1||(
+dist+=count_ones(x))>1)goto exit_if;}}}{register int w,var,last;register pcube
+mask;for(var=cube.num_binary_vars;var<cube.num_vars;var++){mask=cube.var_mask[
+var];last=cube.last_word[var];for(w=cube.first_word[var];w<=last;w++)if(p[w]&r[
+w]&mask[w])goto nextvar;if(++dist>1)goto exit_if;nextvar:;}}
+#endif
+ if (dist == 0)
+ return FALSE;
+ else
+ (void) force_lower(new_lower, p, r);
+ exit_if: ;
+ }
+ return TRUE;
+}
+
+/*
+ mincov -- transform the problem of expanding a cube to a maximally-
+ large prime implicant into the problem of selecting a minimum
+ cardinality cover over a family of sets.
+
+ When we get to this point, we must unravel the remaining off-set.
+ This may be painful.
+*/
+
+void mincov(BB, RAISE, FREESET)
+pcover BB;
+pcube RAISE, FREESET;
+{
+ int expansion, nset, var, dist;
+ pset_family B;
+ register pcube xraise=cube.temp[0], xlower, p, last, plower;
+
+#ifdef RANDOM_MINCOV
+#if defined(_POSIX_SOURCE) || defined(__SVR4)
+ dist = rand() % set_ord(FREESET);
+#else
+ dist = random() % set_ord(FREESET);
+#endif
+ for(var = 0; var < cube.size && dist >= 0; var++) {
+ if (is_in_set(FREESET, var)) {
+ dist--;
+ }
+ }
+
+ set_insert(RAISE, var);
+ set_remove(FREESET, var);
+ (void) essen_parts(BB, /*CC*/ (pcover) NULL, RAISE, FREESET);
+#else
+
+ /* Create B which are those cubes which we must avoid intersecting */
+ B = new_cover(BB->active_count);
+ foreach_active_set(BB, last, p) {
+ plower = set_copy(GETSET(B, B->count++), cube.emptyset);
+ (void) force_lower(plower, p, RAISE);
+ }
+
+ /* Determine how many sets it will blow up into after the unravel */
+ nset = 0;
+ foreach_set(B, last, p) {
+ expansion = 1;
+ for(var = cube.num_binary_vars; var < cube.num_vars; var++) {
+ if ((dist=set_dist(p, cube.var_mask[var])) > 1) {
+ expansion *= dist;
+ if (expansion > 500) goto heuristic_mincov;
+ }
+ }
+ nset += expansion;
+ if (nset > 500) goto heuristic_mincov;
+ }
+
+ B = unravel(B, cube.num_binary_vars);
+ xlower = do_sm_minimum_cover(B);
+
+ /* Add any remaining free parts to the raising set */
+ (void) set_or(RAISE, RAISE, set_diff(xraise, FREESET, xlower));
+ (void) set_copy(FREESET, cube.emptyset); /* free set is empty */
+ BB->active_count = 0; /* BB satisfied */
+ if (debug & EXPAND1) {
+ printf("MINCOV: \tRAISE=%s FREESET=%s\n", pc1(RAISE), pc2(FREESET));
+ }
+ sf_free(B);
+ set_free(xlower);
+ return;
+
+heuristic_mincov:
+ sf_free(B);
+ /* most_frequent will pick first free part */
+ set_insert(RAISE, most_frequent(/*CC*/ (pcover) NULL, FREESET));
+ (void) set_diff(FREESET, FREESET, RAISE);
+ essen_parts(BB, /*CC*/ (pcover) NULL, RAISE, FREESET);
+ return;
+#endif
+}
+
+/*
+ find_all_primes -- find all of the primes which cover the
+ currently reduced BB
+*/
+pcover find_all_primes(BB, RAISE, FREESET)
+pcover BB;
+register pcube RAISE, FREESET;
+{
+ register pset last, p, plower;
+ pset_family B, B1;
+
+ if (BB->active_count == 0) {
+ B1 = new_cover(1);
+ p = GETSET(B1, B1->count++);
+ (void) set_copy(p, RAISE);
+ SET(p, PRIME);
+ } else {
+ B = new_cover(BB->active_count);
+ foreach_active_set(BB, last, p) {
+ plower = set_copy(GETSET(B, B->count++), cube.emptyset);
+ (void) force_lower(plower, p, RAISE);
+ }
+ B = sf_rev_contain(unravel(B, cube.num_binary_vars));
+ B1 = exact_minimum_cover(B);
+ foreach_set(B1, last, p) {
+ INLINEset_diff(p, FREESET, p);
+ INLINEset_or(p, p, RAISE);
+ SET(p, PRIME);
+ }
+ free_cover(B);
+ }
+ return B1;
+}
+
+/*
+ all_primes -- foreach cube in F, generate all of the primes
+ which cover the cube.
+*/
+
+pcover all_primes(F, R)
+pcover F, R;
+{
+ register pcube last, p, RAISE, FREESET;
+ pcover Fall_primes, B1;
+
+ FREESET = new_cube();
+ RAISE = new_cube();
+ Fall_primes = new_cover(F->count);
+
+ foreach_set(F, last, p) {
+ if (TESTP(p, PRIME)) {
+ Fall_primes = sf_addset(Fall_primes, p);
+ } else {
+ /* Setup for call to essential parts */
+ (void) set_copy(RAISE, p);
+ (void) set_diff(FREESET, cube.fullset, RAISE);
+ setup_BB_CC(R, /* CC */ (pcover) NULL);
+ essen_parts(R, /* CC */ (pcover) NULL, RAISE, FREESET);
+
+ /* Find all of the primes, and add them to the prime set */
+ B1 = find_all_primes(R, RAISE, FREESET);
+ Fall_primes = sf_append(Fall_primes, B1);
+ }
+ }
+
+ set_free(RAISE);
+ set_free(FREESET);
+ return Fall_primes;
+}
diff --git a/src/misc/espresso/gasp.c b/src/misc/espresso/gasp.c
new file mode 100644
index 00000000..aa3254d3
--- /dev/null
+++ b/src/misc/espresso/gasp.c
@@ -0,0 +1,228 @@
+/*
+ * Revision Control Information
+ *
+ * $Source$
+ * $Author$
+ * $Revision$
+ * $Date$
+ *
+ */
+/*
+ module: gasp.c
+
+ The "last_gasp" heuristic computes the reduction of each cube in
+ the cover (without replacement) and then performs an expansion of
+ these cubes. The cubes which expand to cover some other cube are
+ added to the original cover and irredundant finds a minimal subset.
+
+ If one of the reduced cubes expands to cover some other reduced
+ cube, then the new prime thus generated is a candidate for reducing
+ the size of the cover.
+
+ super_gasp is a variation on this strategy which extracts a minimal
+ subset from the set of all prime implicants which cover all
+ maximally reduced cubes.
+*/
+
+#include "espresso.h"
+
+
+/*
+ * reduce_gasp -- compute the maximal reduction of each cube of F
+ *
+ * If a cube does not reduce, it remains prime; otherwise, it is marked
+ * as nonprime. If the cube is redundant (should NEVER happen here) we
+ * just crap out ...
+ *
+ * A cover with all of the cubes of F is returned. Those that did
+ * reduce are marked "NONPRIME"; those that reduced are marked "PRIME".
+ * The cubes are in the same order as in F.
+ */
+static pcover reduce_gasp(F, D)
+pcover F, D;
+{
+ pcube p, last, cunder, *FD;
+ pcover G;
+
+ G = new_cover(F->count);
+ FD = cube2list(F, D);
+
+ /* Reduce cubes of F without replacement */
+ foreach_set(F, last, p) {
+ cunder = reduce_cube(FD, p);
+ if (setp_empty(cunder)) {
+ fatal("empty reduction in reduce_gasp, shouldn't happen");
+ } else if (setp_equal(cunder, p)) {
+ SET(cunder, PRIME); /* just to make sure */
+ G = sf_addset(G, p); /* it did not reduce ... */
+ } else {
+ RESET(cunder, PRIME); /* it reduced ... */
+ G = sf_addset(G, cunder);
+ }
+ if (debug & GASP) {
+ printf("REDUCE_GASP: %s reduced to %s\n", pc1(p), pc2(cunder));
+ }
+ free_cube(cunder);
+ }
+
+ free_cubelist(FD);
+ return G;
+}
+
+/*
+ * expand_gasp -- expand each nonprime cube of F into a prime implicant
+ *
+ * The gasp strategy differs in that only those cubes which expand to
+ * cover some other cube are saved; also, all cubes are expanded
+ * regardless of whether they become covered or not.
+ */
+
+pcover expand_gasp(F, D, R, Foriginal)
+INOUT pcover F;
+IN pcover D;
+IN pcover R;
+IN pcover Foriginal;
+{
+ int c1index;
+ pcover G;
+
+ /* Try to expand each nonprime and noncovered cube */
+ G = new_cover(10);
+ for(c1index = 0; c1index < F->count; c1index++) {
+ expand1_gasp(F, D, R, Foriginal, c1index, &G);
+ }
+ G = sf_dupl(G);
+ G = expand(G, R, /*nonsparse*/ FALSE); /* Make them prime ! */
+ return G;
+}
+
+
+
+/*
+ * expand1 -- Expand a single cube against the OFF-set, using the gasp strategy
+ */
+void expand1_gasp(F, D, R, Foriginal, c1index, G)
+pcover F; /* reduced cubes of ON-set */
+pcover D; /* DC-set */
+pcover R; /* OFF-set */
+pcover Foriginal; /* ON-set before reduction (same order as F) */
+int c1index; /* which index of F (or Freduced) to be checked */
+pcover *G;
+{
+ register int c2index;
+ register pcube p, last, c2under;
+ pcube RAISE, FREESET, temp, *FD, c2essential;
+ pcover F1;
+
+ if (debug & EXPAND1) {
+ printf("\nEXPAND1_GASP: \t%s\n", pc1(GETSET(F, c1index)));
+ }
+
+ RAISE = new_cube();
+ FREESET = new_cube();
+ temp = new_cube();
+
+ /* Initialize the OFF-set */
+ R->active_count = R->count;
+ foreach_set(R, last, p) {
+ SET(p, ACTIVE);
+ }
+ /* Initialize the reduced ON-set, all nonprime cubes become active */
+ F->active_count = F->count;
+ foreachi_set(F, c2index, c2under) {
+ if (c1index == c2index || TESTP(c2under, PRIME)) {
+ F->active_count--;
+ RESET(c2under, ACTIVE);
+ } else {
+ SET(c2under, ACTIVE);
+ }
+ }
+
+ /* Initialize the raising and unassigned sets */
+ (void) set_copy(RAISE, GETSET(F, c1index));
+ (void) set_diff(FREESET, cube.fullset, RAISE);
+
+ /* Determine parts which must be lowered */
+ essen_parts(R, F, RAISE, FREESET);
+
+ /* Determine parts which can always be raised */
+ essen_raising(R, RAISE, FREESET);
+
+ /* See which, if any, of the reduced cubes we can cover */
+ foreachi_set(F, c2index, c2under) {
+ if (TESTP(c2under, ACTIVE)) {
+ /* See if this cube can be covered by an expansion */
+ if (setp_implies(c2under, RAISE) ||
+ feasibly_covered(R, c2under, RAISE, temp)) {
+
+ /* See if c1under can expanded to cover c2 reduced against
+ * (F - c1) u c1under; if so, c2 can definitely be removed !
+ */
+
+ /* Copy F and replace c1 with c1under */
+ F1 = sf_save(Foriginal);
+ (void) set_copy(GETSET(F1, c1index), GETSET(F, c1index));
+
+ /* Reduce c2 against ((F - c1) u c1under) */
+ FD = cube2list(F1, D);
+ c2essential = reduce_cube(FD, GETSET(F1, c2index));
+ free_cubelist(FD);
+ sf_free(F1);
+
+ /* See if c2essential is covered by an expansion of c1under */
+ if (feasibly_covered(R, c2essential, RAISE, temp)) {
+ (void) set_or(temp, RAISE, c2essential);
+ RESET(temp, PRIME); /* cube not prime */
+ *G = sf_addset(*G, temp);
+ }
+ set_free(c2essential);
+ }
+ }
+ }
+
+ free_cube(RAISE);
+ free_cube(FREESET);
+ free_cube(temp);
+}
+
+/* irred_gasp -- Add new primes to F and find an irredundant subset */
+pcover irred_gasp(F, D, G)
+pcover F, D, G; /* G is disposed of */
+{
+ if (G->count != 0)
+ F = irredundant(sf_append(F, G), D);
+ else
+ free_cover(G);
+ return F;
+}
+
+
+/* last_gasp */
+pcover last_gasp(F, D, R, cost)
+pcover F, D, R;
+cost_t *cost;
+{
+ pcover G, G1;
+
+ EXECUTE(G = reduce_gasp(F, D), GREDUCE_TIME, G, *cost);
+ EXECUTE(G1 = expand_gasp(G, D, R, F), GEXPAND_TIME, G1, *cost);
+ free_cover(G);
+ EXECUTE(F = irred_gasp(F, D, G1), GIRRED_TIME, F, *cost);
+ return F;
+}
+
+
+/* super_gasp */
+pcover super_gasp(F, D, R, cost)
+pcover F, D, R;
+cost_t *cost;
+{
+ pcover G, G1;
+
+ EXECUTE(G = reduce_gasp(F, D), GREDUCE_TIME, G, *cost);
+ EXECUTE(G1 = all_primes(G, R), GEXPAND_TIME, G1, *cost);
+ free_cover(G);
+ EXEC(G = sf_dupl(sf_append(F, G1)), "NEWPRIMES", G);
+ EXECUTE(F = irredundant(G, D), IRRED_TIME, F, *cost);
+ return F;
+}
diff --git a/src/misc/espresso/gimpel.c b/src/misc/espresso/gimpel.c
new file mode 100644
index 00000000..648bb64a
--- /dev/null
+++ b/src/misc/espresso/gimpel.c
@@ -0,0 +1,106 @@
+/*
+ * Revision Control Information
+ *
+ * $Source$
+ * $Author$
+ * $Revision$
+ * $Date$
+ *
+ */
+#include "mincov_int.h"
+
+
+/*
+ * check for:
+ *
+ * c1 c2 rest
+ * -- -- ---
+ * 1 1 0 0 0 0 <-- primary row
+ * 1 0 S1 <-- secondary row
+ * 0 1 T1
+ * 0 1 T2
+ * 0 1 Tn
+ * 0 0 R
+ */
+
+int
+gimpel_reduce(A, select, weight, lb, bound, depth, stats, best)
+sm_matrix *A;
+solution_t *select;
+int *weight;
+int lb;
+int bound;
+int depth;
+stats_t *stats;
+solution_t **best;
+{
+ register sm_row *prow, *save_sec;
+ register sm_col *c1, *c2;
+ register sm_element *p, *p1;
+ int c1_col_num, c2_col_num, primary_row_num, secondary_row_num;
+ int reduce_it;
+
+ reduce_it = 0;
+ for(prow = A->first_row; prow != 0; prow = prow->next_row) {
+ if (prow->length == 2) {
+ c1 = sm_get_col(A, prow->first_col->col_num);
+ c2 = sm_get_col(A, prow->last_col->col_num);
+ if (c1->length == 2) {
+ reduce_it = 1;
+ } else if (c2->length == 2) {
+ c1 = sm_get_col(A, prow->last_col->col_num);
+ c2 = sm_get_col(A, prow->first_col->col_num);
+ reduce_it = 1;
+ }
+ if (reduce_it) {
+ primary_row_num = prow->row_num;
+ secondary_row_num = c1->first_row->row_num;
+ if (secondary_row_num == primary_row_num) {
+ secondary_row_num = c1->last_row->row_num;
+ }
+ break;
+ }
+ }
+ }
+
+ if (reduce_it) {
+ c1_col_num = c1->col_num;
+ c2_col_num = c2->col_num;
+ save_sec = sm_row_dup(sm_get_row(A, secondary_row_num));
+ sm_row_remove(save_sec, c1_col_num);
+
+ for(p = c2->first_row; p != 0; p = p->next_row) {
+ if (p->row_num != primary_row_num) {
+ /* merge rows S1 and T */
+ for(p1 = save_sec->first_col; p1 != 0; p1 = p1->next_col) {
+ (void) sm_insert(A, p->row_num, p1->col_num);
+ }
+ }
+ }
+
+ sm_delcol(A, c1_col_num);
+ sm_delcol(A, c2_col_num);
+ sm_delrow(A, primary_row_num);
+ sm_delrow(A, secondary_row_num);
+
+ stats->gimpel_count++;
+ stats->gimpel++;
+ *best = sm_mincov(A, select, weight, lb-1, bound-1, depth, stats);
+ stats->gimpel--;
+
+ if (*best != NIL(solution_t)) {
+ /* is secondary row covered ? */
+ if (sm_row_intersects(save_sec, (*best)->row)) {
+ /* yes, actually select c2 */
+ solution_add(*best, weight, c2_col_num);
+ } else {
+ solution_add(*best, weight, c1_col_num);
+ }
+ }
+
+ sm_row_free(save_sec);
+ return 1;
+ } else {
+ return 0;
+ }
+}
diff --git a/src/misc/espresso/globals.c b/src/misc/espresso/globals.c
new file mode 100644
index 00000000..d04771e9
--- /dev/null
+++ b/src/misc/espresso/globals.c
@@ -0,0 +1,76 @@
+/*
+ * Revision Control Information
+ *
+ * $Source$
+ * $Author$
+ * $Revision$
+ * $Date$
+ *
+ */
+#include "espresso.h"
+
+/*
+ * Global Variable Declarations
+ */
+
+unsigned int debug; /* debug parameter */
+bool verbose_debug; /* -v: whether to print a lot */
+char *total_name[TIME_COUNT]; /* basic function names */
+long total_time[TIME_COUNT]; /* time spent in basic fcts */
+int total_calls[TIME_COUNT]; /* # calls to each fct */
+
+bool echo_comments; /* turned off by -eat option */
+bool echo_unknown_commands; /* always true ?? */
+bool force_irredundant; /* -nirr command line option */
+bool skip_make_sparse;
+bool kiss; /* -kiss command line option */
+bool pos; /* -pos command line option */
+bool print_solution; /* -x command line option */
+bool recompute_onset; /* -onset command line option */
+bool remove_essential; /* -ness command line option */
+bool single_expand; /* -fast command line option */
+bool summary; /* -s command line option */
+bool trace; /* -t command line option */
+bool unwrap_onset; /* -nunwrap command line option */
+bool use_random_order; /* -random command line option */
+bool use_super_gasp; /* -strong command line option */
+char *filename; /* filename PLA was read from */
+
+struct pla_types_struct pla_types[] = {
+ "-f", F_type,
+ "-r", R_type,
+ "-d", D_type,
+ "-fd", FD_type,
+ "-fr", FR_type,
+ "-dr", DR_type,
+ "-fdr", FDR_type,
+ "-fc", F_type | CONSTRAINTS_type,
+ "-rc", R_type | CONSTRAINTS_type,
+ "-dc", D_type | CONSTRAINTS_type,
+ "-fdc", FD_type | CONSTRAINTS_type,
+ "-frc", FR_type | CONSTRAINTS_type,
+ "-drc", DR_type | CONSTRAINTS_type,
+ "-fdrc", FDR_type | CONSTRAINTS_type,
+ "-pleasure", PLEASURE_type,
+ "-eqn", EQNTOTT_type,
+ "-eqntott", EQNTOTT_type,
+ "-kiss", KISS_type,
+ "-cons", CONSTRAINTS_type,
+ "-scons", SYMBOLIC_CONSTRAINTS_type,
+ 0, 0
+};
+
+
+struct cube_struct cube, temp_cube_save;
+struct cdata_struct cdata, temp_cdata_save;
+
+int bit_count[256] = {
+ 0,1,1,2,1,2,2,3,1,2,2,3,2,3,3,4,1,2,2,3,2,3,3,4,2,3,3,4,3,4,4,5,
+ 1,2,2,3,2,3,3,4,2,3,3,4,3,4,4,5,2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6,
+ 1,2,2,3,2,3,3,4,2,3,3,4,3,4,4,5,2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6,
+ 2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6,3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7,
+ 1,2,2,3,2,3,3,4,2,3,3,4,3,4,4,5,2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6,
+ 2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6,3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7,
+ 2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6,3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7,
+ 3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7,4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8
+};
diff --git a/src/misc/espresso/hack.c b/src/misc/espresso/hack.c
new file mode 100644
index 00000000..927f5341
--- /dev/null
+++ b/src/misc/espresso/hack.c
@@ -0,0 +1,641 @@
+/*
+ * Revision Control Information
+ *
+ * $Source$
+ * $Author$
+ * $Revision$
+ * $Date$
+ *
+ */
+#include "espresso.h"
+
+map_dcset(PLA)
+pPLA PLA;
+{
+ int var, i;
+ pcover Tplus, Tminus, Tplusbar, Tminusbar;
+ pcover newf, term1, term2, dcset, dcsetbar;
+ pcube cplus, cminus, last, p;
+
+ if (PLA->label == NIL(char *) || PLA->label[0] == NIL(char))
+ return;
+
+ /* try to find a binary variable named "DONT_CARE" */
+ var = -1;
+ for(i = 0; i < cube.num_binary_vars * 2; i++) {
+ if (strncmp(PLA->label[i], "DONT_CARE", 9) == 0 ||
+ strncmp(PLA->label[i], "DONTCARE", 8) == 0 ||
+ strncmp(PLA->label[i], "dont_care", 9) == 0 ||
+ strncmp(PLA->label[i], "dontcare", 8) == 0) {
+ var = i/2;
+ break;
+ }
+ }
+ if (var == -1) {
+ return;
+ }
+
+ /* form the cofactor cubes for the don't-care variable */
+ cplus = set_save(cube.fullset);
+ cminus = set_save(cube.fullset);
+ set_remove(cplus, var*2);
+ set_remove(cminus, var*2 + 1);
+
+ /* form the don't-care set */
+ EXEC(simp_comp(cofactor(cube1list(PLA->F), cplus), &Tplus, &Tplusbar),
+ "simpcomp+", Tplus);
+ EXEC(simp_comp(cofactor(cube1list(PLA->F), cminus), &Tminus, &Tminusbar),
+ "simpcomp-", Tminus);
+ EXEC(term1 = cv_intersect(Tplus, Tminusbar), "term1 ", term1);
+ EXEC(term2 = cv_intersect(Tminus, Tplusbar), "term2 ", term2);
+ EXEC(dcset = sf_union(term1, term2), "union ", dcset);
+ EXEC(simp_comp(cube1list(dcset), &PLA->D, &dcsetbar), "simplify", PLA->D);
+ EXEC(newf = cv_intersect(PLA->F, dcsetbar), "separate ", PLA->F);
+ free_cover(PLA->F);
+ PLA->F = newf;
+ free_cover(Tplus);
+ free_cover(Tminus);
+ free_cover(Tplusbar);
+ free_cover(Tminusbar);
+ free_cover(dcsetbar);
+
+ /* remove any cubes dependent on the DONT_CARE variable */
+ (void) sf_active(PLA->F);
+ foreach_set(PLA->F, last, p) {
+ if (! is_in_set(p, var*2) || ! is_in_set(p, var*2+1)) {
+ RESET(p, ACTIVE);
+ }
+ }
+ PLA->F = sf_inactive(PLA->F);
+
+ /* resize the cube and delete the don't-care variable */
+ setdown_cube();
+ for(i = 2*var+2; i < cube.size; i++) {
+ PLA->label[i-2] = PLA->label[i];
+ }
+ for(i = var+1; i < cube.num_vars; i++) {
+ cube.part_size[i-1] = cube.part_size[i];
+ }
+ cube.num_binary_vars--;
+ cube.num_vars--;
+ cube_setup();
+ PLA->F = sf_delc(PLA->F, 2*var, 2*var+1);
+ PLA->D = sf_delc(PLA->D, 2*var, 2*var+1);
+}
+
+map_output_symbolic(PLA)
+pPLA PLA;
+{
+ pset_family newF, newD;
+ pset compress;
+ symbolic_t *p1;
+ symbolic_list_t *p2;
+ int i, bit, tot_size, base, old_size;
+
+ /* Remove the DC-set from the ON-set (is this necessary ??) */
+ if (PLA->D->count > 0) {
+ sf_free(PLA->F);
+ PLA->F = complement(cube2list(PLA->D, PLA->R));
+ }
+
+ /* tot_size = width added for all symbolic variables */
+ tot_size = 0;
+ for(p1=PLA->symbolic_output; p1!=NIL(symbolic_t); p1=p1->next) {
+ for(p2=p1->symbolic_list; p2!=NIL(symbolic_list_t); p2=p2->next) {
+ if (p2->pos<0 || p2->pos>=cube.part_size[cube.output]) {
+ fatal("symbolic-output index out of range");
+/* } else if (p2->variable != cube.output) {
+ fatal("symbolic-output label must be an output");*/
+ }
+ }
+ tot_size += 1 << p1->symbolic_list_length;
+ }
+
+ /* adjust the indices to skip over new outputs */
+ for(p1=PLA->symbolic_output; p1!=NIL(symbolic_t); p1=p1->next) {
+ for(p2=p1->symbolic_list; p2!=NIL(symbolic_list_t); p2=p2->next) {
+ p2->pos += tot_size;
+ }
+ }
+
+ /* resize the cube structure -- add enough for the one-hot outputs */
+ old_size = cube.size;
+ cube.part_size[cube.output] += tot_size;
+ setdown_cube();
+ cube_setup();
+
+ /* insert space in the output part for the one-hot output */
+ base = cube.first_part[cube.output];
+ PLA->F = sf_addcol(PLA->F, base, tot_size);
+ PLA->D = sf_addcol(PLA->D, base, tot_size);
+ PLA->R = sf_addcol(PLA->R, base, tot_size);
+
+ /* do the real work */
+ for(p1=PLA->symbolic_output; p1!=NIL(symbolic_t); p1=p1->next) {
+ newF = new_cover(100);
+ newD = new_cover(100);
+ find_inputs(NIL(set_family_t), PLA, p1->symbolic_list, base, 0,
+ &newF, &newD);
+/*
+ * Not sure what this means
+ find_dc_inputs(PLA, p1->symbolic_list,
+ base, 1 << p1->symbolic_list_length, &newF, &newD);
+ */
+ free_cover(PLA->F);
+ PLA->F = newF;
+/*
+ * retain OLD DC-set -- but we've lost the don't-care arc information
+ * (it defaults to branch to the zero state)
+ free_cover(PLA->D);
+ PLA->D = newD;
+ */
+ free_cover(newD);
+ base += 1 << p1->symbolic_list_length;
+ }
+
+ /* delete the old outputs, and resize the cube */
+ compress = set_full(newF->sf_size);
+ for(p1=PLA->symbolic_output; p1!=NIL(symbolic_t); p1=p1->next) {
+ for(p2=p1->symbolic_list; p2!=NIL(symbolic_list_t); p2=p2->next) {
+ bit = cube.first_part[cube.output] + p2->pos;
+ set_remove(compress, bit);
+ }
+ }
+ cube.part_size[cube.output] -= newF->sf_size - set_ord(compress);
+ setdown_cube();
+ cube_setup();
+ PLA->F = sf_compress(PLA->F, compress);
+ PLA->D = sf_compress(PLA->D, compress);
+ if (cube.size != PLA->F->sf_size) fatal("error");
+
+ /* Quick minimization */
+ PLA->F = sf_contain(PLA->F);
+ PLA->D = sf_contain(PLA->D);
+ for(i = 0; i < cube.num_vars; i++) {
+ PLA->F = d1merge(PLA->F, i);
+ PLA->D = d1merge(PLA->D, i);
+ }
+ PLA->F = sf_contain(PLA->F);
+ PLA->D = sf_contain(PLA->D);
+
+ free_cover(PLA->R);
+ PLA->R = new_cover(0);
+
+ symbolic_hack_labels(PLA, PLA->symbolic_output,
+ compress, cube.size, old_size, tot_size);
+ set_free(compress);
+}
+
+
+find_inputs(A, PLA, list, base, value, newF, newD)
+pcover A;
+pPLA PLA;
+symbolic_list_t *list;
+int base, value;
+pcover *newF, *newD;
+{
+ pcover S, S1;
+ register pset last, p;
+
+ /*
+ * A represents th 'input' values for which the outputs assume
+ * the integer value 'value
+ */
+ if (list == NIL(symbolic_list_t)) {
+ /*
+ * Simulate these inputs against the on-set; then, insert into the
+ * new on-set a 1 in the proper position
+ */
+ S = cv_intersect(A, PLA->F);
+ foreach_set(S, last, p) {
+ set_insert(p, base + value);
+ }
+ *newF = sf_append(*newF, S);
+
+ /*
+ * 'simulate' these inputs against the don't-care set
+ S = cv_intersect(A, PLA->D);
+ *newD = sf_append(*newD, S);
+ */
+
+ } else {
+ /* intersect and recur with the OFF-set */
+ S = cof_output(PLA->R, cube.first_part[cube.output] + list->pos);
+ if (A != NIL(set_family_t)) {
+ S1 = cv_intersect(A, S);
+ free_cover(S);
+ S = S1;
+ }
+ find_inputs(S, PLA, list->next, base, value*2, newF, newD);
+ free_cover(S);
+
+ /* intersect and recur with the ON-set */
+ S = cof_output(PLA->F, cube.first_part[cube.output] + list->pos);
+ if (A != NIL(set_family_t)) {
+ S1 = cv_intersect(A, S);
+ free_cover(S);
+ S = S1;
+ }
+ find_inputs(S, PLA, list->next, base, value*2 + 1, newF, newD);
+ free_cover(S);
+ }
+}
+
+
+#if 0
+find_dc_inputs(PLA, list, base, maxval, newF, newD)
+pPLA PLA;
+symbolic_list_t *list;
+int base, maxval;
+pcover *newF, *newD;
+{
+ pcover A, S, S1;
+ symbolic_list_t *p2;
+ register pset p, last;
+ register int i;
+
+ /* painfully find the points for which the symbolic output is dc */
+ A = NIL(set_family_t);
+ for(p2=list; p2!=NIL(symbolic_list_t); p2=p2->next) {
+ S = cof_output(PLA->D, cube.first_part[cube.output] + p2->pos);
+ if (A == NIL(set_family_t)) {
+ A = S;
+ } else {
+ S1 = cv_intersect(A, S);
+ free_cover(S);
+ free_cover(A);
+ A = S1;
+ }
+ }
+
+ S = cv_intersect(A, PLA->F);
+ *newF = sf_append(*newF, S);
+
+ S = cv_intersect(A, PLA->D);
+ foreach_set(S, last, p) {
+ for(i = base; i < base + maxval; i++) {
+ set_insert(p, i);
+ }
+ }
+ *newD = sf_append(*newD, S);
+ free_cover(A);
+}
+#endif
+
+map_symbolic(PLA)
+pPLA PLA;
+{
+ symbolic_t *p1;
+ symbolic_list_t *p2;
+ int var, base, num_vars, num_binary_vars, *new_part_size;
+ int new_size, size_added, num_deleted_vars, num_added_vars, newvar;
+ pset compress;
+
+ /* Verify legal values are in the symbolic lists */
+ for(p1 = PLA->symbolic; p1 != NIL(symbolic_t); p1 = p1->next) {
+ for(p2=p1->symbolic_list; p2!=NIL(symbolic_list_t); p2=p2->next) {
+ if (p2->variable < 0 || p2->variable >= cube.num_binary_vars) {
+ fatal(".symbolic requires binary variables");
+ }
+ }
+ }
+
+ /*
+ * size_added = width added for all symbolic variables
+ * num_deleted_vars = # binary variables to be deleted
+ * num_added_vars = # new mv variables
+ * compress = a cube which will be used to compress the set families
+ */
+ size_added = 0;
+ num_added_vars = 0;
+ for(p1 = PLA->symbolic; p1 != NIL(symbolic_t); p1 = p1->next) {
+ size_added += 1 << p1->symbolic_list_length;
+ num_added_vars++;
+ }
+ compress = set_full(PLA->F->sf_size + size_added);
+ for(p1 = PLA->symbolic; p1 != NIL(symbolic_t); p1 = p1->next) {
+ for(p2=p1->symbolic_list; p2!=NIL(symbolic_list_t); p2=p2->next) {
+ set_remove(compress, p2->variable*2);
+ set_remove(compress, p2->variable*2+1);
+ }
+ }
+ num_deleted_vars = ((PLA->F->sf_size + size_added) - set_ord(compress))/2;
+
+ /* compute the new cube constants */
+ num_vars = cube.num_vars - num_deleted_vars + num_added_vars;
+ num_binary_vars = cube.num_binary_vars - num_deleted_vars;
+ new_size = cube.size - num_deleted_vars*2 + size_added;
+ new_part_size = ALLOC(int, num_vars);
+ new_part_size[num_vars-1] = cube.part_size[cube.num_vars-1];
+ for(var = cube.num_binary_vars; var < cube.num_vars-1; var++) {
+ new_part_size[var-num_deleted_vars] = cube.part_size[var];
+ }
+
+ /* re-size the covers, opening room for the new mv variables */
+ base = cube.first_part[cube.output];
+ PLA->F = sf_addcol(PLA->F, base, size_added);
+ PLA->D = sf_addcol(PLA->D, base, size_added);
+ PLA->R = sf_addcol(PLA->R, base, size_added);
+
+ /* compute the values for the new mv variables */
+ newvar = (cube.num_vars - 1) - num_deleted_vars;
+ for(p1 = PLA->symbolic; p1 != NIL(symbolic_t); p1 = p1->next) {
+ PLA->F = map_symbolic_cover(PLA->F, p1->symbolic_list, base);
+ PLA->D = map_symbolic_cover(PLA->D, p1->symbolic_list, base);
+ PLA->R = map_symbolic_cover(PLA->R, p1->symbolic_list, base);
+ base += 1 << p1->symbolic_list_length;
+ new_part_size[newvar++] = 1 << p1->symbolic_list_length;
+ }
+
+ /* delete the binary variables which disappear */
+ PLA->F = sf_compress(PLA->F, compress);
+ PLA->D = sf_compress(PLA->D, compress);
+ PLA->R = sf_compress(PLA->R, compress);
+
+ symbolic_hack_labels(PLA, PLA->symbolic, compress,
+ new_size, cube.size, size_added);
+ setdown_cube();
+ FREE(cube.part_size);
+ cube.num_vars = num_vars;
+ cube.num_binary_vars = num_binary_vars;
+ cube.part_size = new_part_size;
+ cube_setup();
+ set_free(compress);
+}
+
+
+pcover map_symbolic_cover(T, list, base)
+pcover T;
+symbolic_list_t *list;
+int base;
+{
+ pset last, p;
+ foreach_set(T, last, p) {
+ form_bitvector(p, base, 0, list);
+ }
+ return T;
+}
+
+
+form_bitvector(p, base, value, list)
+pset p; /* old cube, looking at binary variables */
+int base; /* where in mv cube the new variable starts */
+int value; /* current value for this recursion */
+symbolic_list_t *list; /* current place in the symbolic list */
+{
+ if (list == NIL(symbolic_list_t)) {
+ set_insert(p, base + value);
+ } else {
+ switch(GETINPUT(p, list->variable)) {
+ case ZERO:
+ form_bitvector(p, base, value*2, list->next);
+ break;
+ case ONE:
+ form_bitvector(p, base, value*2+1, list->next);
+ break;
+ case TWO:
+ form_bitvector(p, base, value*2, list->next);
+ form_bitvector(p, base, value*2+1, list->next);
+ break;
+ default:
+ fatal("bad cube in form_bitvector");
+ }
+ }
+}
+
+
+symbolic_hack_labels(PLA, list, compress, new_size, old_size, size_added)
+pPLA PLA;
+symbolic_t *list;
+pset compress;
+int new_size, old_size, size_added;
+{
+ int i, base;
+ char **oldlabel;
+ symbolic_t *p1;
+ symbolic_label_t *p3;
+
+ /* hack with the labels */
+ if ((oldlabel = PLA->label) == NIL(char *))
+ return;
+ PLA->label = ALLOC(char *, new_size);
+ for(i = 0; i < new_size; i++) {
+ PLA->label[i] = NIL(char);
+ }
+
+ /* copy the binary variable labels and unchanged mv variable labels */
+ base = 0;
+ for(i = 0; i < cube.first_part[cube.output]; i++) {
+ if (is_in_set(compress, i)) {
+ PLA->label[base++] = oldlabel[i];
+ } else {
+ if (oldlabel[i] != NIL(char)) {
+ FREE(oldlabel[i]);
+ }
+ }
+ }
+
+ /* add the user-defined labels for the symbolic outputs */
+ for(p1 = list; p1 != NIL(symbolic_t); p1 = p1->next) {
+ p3 = p1->symbolic_label;
+ for(i = 0; i < (1 << p1->symbolic_list_length); i++) {
+ if (p3 == NIL(symbolic_label_t)) {
+ PLA->label[base+i] = ALLOC(char, 10);
+ (void) sprintf(PLA->label[base+i], "X%d", i);
+ } else {
+ PLA->label[base+i] = p3->label;
+ p3 = p3->next;
+ }
+ }
+ base += 1 << p1->symbolic_list_length;
+ }
+
+ /* copy the labels for the binary outputs which remain */
+ for(i = cube.first_part[cube.output]; i < old_size; i++) {
+ if (is_in_set(compress, i + size_added)) {
+ PLA->label[base++] = oldlabel[i];
+ } else {
+ if (oldlabel[i] != NIL(char)) {
+ FREE(oldlabel[i]);
+ }
+ }
+ }
+ FREE(oldlabel);
+}
+
+static pcover fsm_simplify(F)
+pcover F;
+{
+ pcover D, R;
+ D = new_cover(0);
+ R = complement(cube1list(F));
+ F = espresso(F, D, R);
+ free_cover(D);
+ free_cover(R);
+ return F;
+}
+
+
+disassemble_fsm(PLA, verbose_mode)
+pPLA PLA;
+int verbose_mode;
+{
+ int nin, nstates, nout;
+ int before, after, present_state, next_state, i, j;
+ pcube next_state_mask, present_state_mask, state_mask, p, p1, last;
+ pcover go_nowhere, F, tF;
+
+ /* We make the DISGUSTING assumption that the first 'n' outputs have
+ * been created by .symbolic-output, and represent a one-hot encoding
+ * of the next state. 'n' is the size of the second-to-last multiple-
+ * valued variable (i.e., before the outputs
+ */
+
+ if (cube.num_vars - cube.num_binary_vars != 2) {
+ (void) fprintf(stderr,
+ "use .symbolic and .symbolic-output to specify\n");
+ (void) fprintf(stderr,
+ "the present state and next state field information\n");
+ fatal("disassemble_pla: need two multiple-valued variables\n");
+ }
+
+ nin = cube.num_binary_vars;
+ nstates = cube.part_size[cube.num_binary_vars];
+ nout = cube.part_size[cube.num_vars - 1];
+ if (nout < nstates) {
+ (void) fprintf(stderr,
+ "use .symbolic and .symbolic-output to specify\n");
+ (void) fprintf(stderr,
+ "the present state and next state field information\n");
+ fatal("disassemble_pla: # outputs < # states\n");
+ }
+
+
+ present_state = cube.first_part[cube.num_binary_vars];
+ present_state_mask = new_cube();
+ for(i = 0; i < nstates; i++) {
+ set_insert(present_state_mask, i + present_state);
+ }
+
+ next_state = cube.first_part[cube.num_binary_vars+1];
+ next_state_mask = new_cube();
+ for(i = 0; i < nstates; i++) {
+ set_insert(next_state_mask, i + next_state);
+ }
+
+ state_mask = set_or(new_cube(), next_state_mask, present_state_mask);
+
+ F = new_cover(10);
+
+
+ /*
+ * check for arcs which go from ANY state to state #i
+ */
+ for(i = 0; i < nstates; i++) {
+ tF = new_cover(10);
+ foreach_set(PLA->F, last, p) {
+ if (setp_implies(present_state_mask, p)) { /* from any state ! */
+ if (is_in_set(p, next_state + i)) {
+ tF = sf_addset(tF, p);
+ }
+ }
+ }
+ before = tF->count;
+ if (before > 0) {
+ tF = fsm_simplify(tF);
+ /* don't allow the next state to disappear ... */
+ foreach_set(tF, last, p) {
+ set_insert(p, next_state + i);
+ }
+ after = tF->count;
+ F = sf_append(F, tF);
+ if (verbose_mode) {
+ printf("# state EVERY to %d, before=%d after=%d\n",
+ i, before, after);
+ }
+ }
+ }
+
+
+ /*
+ * some 'arcs' may NOT have a next state -- handle these
+ * we must unravel the present state part
+ */
+ go_nowhere = new_cover(10);
+ foreach_set(PLA->F, last, p) {
+ if (setp_disjoint(p, next_state_mask)) { /* no next state !! */
+ go_nowhere = sf_addset(go_nowhere, p);
+ }
+ }
+ before = go_nowhere->count;
+ go_nowhere = unravel_range(go_nowhere,
+ cube.num_binary_vars, cube.num_binary_vars);
+ after = go_nowhere->count;
+ F = sf_append(F, go_nowhere);
+ if (verbose_mode) {
+ printf("# state ANY to NOWHERE, before=%d after=%d\n", before, after);
+ }
+
+
+ /*
+ * minimize cover for all arcs from state #i to state #j
+ */
+ for(i = 0; i < nstates; i++) {
+ for(j = 0; j < nstates; j++) {
+ tF = new_cover(10);
+ foreach_set(PLA->F, last, p) {
+ /* not EVERY state */
+ if (! setp_implies(present_state_mask, p)) {
+ if (is_in_set(p, present_state + i)) {
+ if (is_in_set(p, next_state + j)) {
+ p1 = set_save(p);
+ set_diff(p1, p1, state_mask);
+ set_insert(p1, present_state + i);
+ set_insert(p1, next_state + j);
+ tF = sf_addset(tF, p1);
+ set_free(p1);
+ }
+ }
+ }
+ }
+ before = tF->count;
+ if (before > 0) {
+ tF = fsm_simplify(tF);
+ /* don't allow the next state to disappear ... */
+ foreach_set(tF, last, p) {
+ set_insert(p, next_state + j);
+ }
+ after = tF->count;
+ F = sf_append(F, tF);
+ if (verbose_mode) {
+ printf("# state %d to %d, before=%d after=%d\n",
+ i, j, before, after);
+ }
+ }
+ }
+ }
+
+
+ free_cube(state_mask);
+ free_cube(present_state_mask);
+ free_cube(next_state_mask);
+
+ free_cover(PLA->F);
+ PLA->F = F;
+ free_cover(PLA->D);
+ PLA->D = new_cover(0);
+
+ setdown_cube();
+ FREE(cube.part_size);
+ cube.num_binary_vars = nin;
+ cube.num_vars = nin + 3;
+ cube.part_size = ALLOC(int, cube.num_vars);
+ cube.part_size[cube.num_binary_vars] = nstates;
+ cube.part_size[cube.num_binary_vars+1] = nstates;
+ cube.part_size[cube.num_binary_vars+2] = nout - nstates;
+ cube_setup();
+
+ foreach_set(PLA->F, last, p) {
+ kiss_print_cube(stdout, PLA, p, "~1");
+ }
+}
diff --git a/src/misc/espresso/indep.c b/src/misc/espresso/indep.c
new file mode 100644
index 00000000..10b363a0
--- /dev/null
+++ b/src/misc/espresso/indep.c
@@ -0,0 +1,134 @@
+/*
+ * Revision Control Information
+ *
+ * $Source$
+ * $Author$
+ * $Revision$
+ * $Date$
+ *
+ */
+#include "mincov_int.h"
+
+static sm_matrix *build_intersection_matrix();
+
+
+#if 0
+/*
+ * verify that all rows in 'indep' are actually independent !
+ */
+static int
+verify_indep_set(A, indep)
+sm_matrix *A;
+sm_row *indep;
+{
+ register sm_row *prow, *prow1;
+ register sm_element *p, *p1;
+
+ for(p = indep->first_col; p != 0; p = p->next_col) {
+ prow = sm_get_row(A, p->col_num);
+ for(p1 = p->next_col; p1 != 0; p1 = p1->next_col) {
+ prow1 = sm_get_row(A, p1->col_num);
+ if (sm_row_intersects(prow, prow1)) {
+ return 0;
+ }
+ }
+ }
+ return 1;
+}
+#endif
+
+solution_t *
+sm_maximal_independent_set(A, weight)
+sm_matrix *A;
+int *weight;
+{
+ register sm_row *best_row, *prow;
+ register sm_element *p;
+ int least_weight;
+ sm_row *save;
+ sm_matrix *B;
+ solution_t *indep;
+
+ indep = solution_alloc();
+ B = build_intersection_matrix(A);
+
+ while (B->nrows > 0) {
+ /* Find the row which is disjoint from a maximum number of rows */
+ best_row = B->first_row;
+ for(prow = B->first_row->next_row; prow != 0; prow = prow->next_row) {
+ if (prow->length < best_row->length) {
+ best_row = prow;
+ }
+ }
+
+ /* Find which element in this row has least weight */
+ if (weight == NIL(int)) {
+ least_weight = 1;
+ } else {
+ prow = sm_get_row(A, best_row->row_num);
+ least_weight = weight[prow->first_col->col_num];
+ for(p = prow->first_col->next_col; p != 0; p = p->next_col) {
+ if (weight[p->col_num] < least_weight) {
+ least_weight = weight[p->col_num];
+ }
+ }
+ }
+ indep->cost += least_weight;
+ (void) sm_row_insert(indep->row, best_row->row_num);
+
+ /* Discard the rows which intersect this row */
+ save = sm_row_dup(best_row);
+ for(p = save->first_col; p != 0; p = p->next_col) {
+ sm_delrow(B, p->col_num);
+ sm_delcol(B, p->col_num);
+ }
+ sm_row_free(save);
+ }
+
+ sm_free(B);
+
+/*
+ if (! verify_indep_set(A, indep->row)) {
+ fail("sm_maximal_independent_set: row set is not independent");
+ }
+*/
+ return indep;
+}
+
+static sm_matrix *
+build_intersection_matrix(A)
+sm_matrix *A;
+{
+ register sm_row *prow, *prow1;
+ register sm_element *p, *p1;
+ register sm_col *pcol;
+ sm_matrix *B;
+
+ /* Build row-intersection matrix */
+ B = sm_alloc();
+ for(prow = A->first_row; prow != 0; prow = prow->next_row) {
+
+ /* Clear flags on all rows we can reach from row 'prow' */
+ for(p = prow->first_col; p != 0; p = p->next_col) {
+ pcol = sm_get_col(A, p->col_num);
+ for(p1 = pcol->first_row; p1 != 0; p1 = p1->next_row) {
+ prow1 = sm_get_row(A, p1->row_num);
+ prow1->flag = 0;
+ }
+ }
+
+ /* Now record which rows can be reached */
+ for(p = prow->first_col; p != 0; p = p->next_col) {
+ pcol = sm_get_col(A, p->col_num);
+ for(p1 = pcol->first_row; p1 != 0; p1 = p1->next_row) {
+ prow1 = sm_get_row(A, p1->row_num);
+ if (! prow1->flag) {
+ prow1->flag = 1;
+ (void) sm_insert(B, prow->row_num, prow1->row_num);
+ }
+ }
+ }
+ }
+
+ return B;
+}
diff --git a/src/misc/espresso/irred.c b/src/misc/espresso/irred.c
new file mode 100644
index 00000000..384e698f
--- /dev/null
+++ b/src/misc/espresso/irred.c
@@ -0,0 +1,440 @@
+/*
+ * Revision Control Information
+ *
+ * $Source$
+ * $Author$
+ * $Revision$
+ * $Date$
+ *
+ */
+#include "espresso.h"
+
+static void fcube_is_covered();
+static void ftautology();
+static bool ftaut_special_cases();
+
+
+static int Rp_current;
+
+/*
+ * irredundant -- Return a minimal subset of F
+ */
+
+pcover
+irredundant(F, D)
+pcover F, D;
+{
+ mark_irredundant(F, D);
+ return sf_inactive(F);
+}
+
+
+/*
+ * mark_irredundant -- find redundant cubes, and mark them "INACTIVE"
+ */
+
+void
+mark_irredundant(F, D)
+pcover F, D;
+{
+ pcover E, Rt, Rp;
+ pset p, p1, last;
+ sm_matrix *table;
+ sm_row *cover;
+ sm_element *pe;
+
+ /* extract a minimum cover */
+ irred_split_cover(F, D, &E, &Rt, &Rp);
+ table = irred_derive_table(D, E, Rp);
+ cover = sm_minimum_cover(table, NIL(int), /* heuristic */ 1, /* debug */ 0);
+
+ /* mark the cubes for the result */
+ foreach_set(F, last, p) {
+ RESET(p, ACTIVE);
+ RESET(p, RELESSEN);
+ }
+ foreach_set(E, last, p) {
+ p1 = GETSET(F, SIZE(p));
+ assert(setp_equal(p1, p));
+ SET(p1, ACTIVE);
+ SET(p1, RELESSEN); /* for essen(), mark as rel. ess. */
+ }
+ sm_foreach_row_element(cover, pe) {
+ p1 = GETSET(F, pe->col_num);
+ SET(p1, ACTIVE);
+ }
+
+ if (debug & IRRED) {
+ printf("# IRRED: F=%d E=%d R=%d Rt=%d Rp=%d Rc=%d Final=%d Bound=%d\n",
+ F->count, E->count, Rt->count+Rp->count, Rt->count, Rp->count,
+ cover->length, E->count + cover->length, 0);
+ }
+
+ free_cover(E);
+ free_cover(Rt);
+ free_cover(Rp);
+ sm_free(table);
+ sm_row_free(cover);
+}
+
+/*
+ * irred_split_cover -- find E, Rt, and Rp from the cover F, D
+ *
+ * E -- relatively essential cubes
+ * Rt -- totally redundant cubes
+ * Rp -- partially redundant cubes
+ */
+
+void
+irred_split_cover(F, D, E, Rt, Rp)
+pcover F, D;
+pcover *E, *Rt, *Rp;
+{
+ register pcube p, last;
+ register int index;
+ pcover R;
+ pcube *FD, *ED;
+
+ /* number the cubes of F -- these numbers track into E, Rp, Rt, etc. */
+ index = 0;
+ foreach_set(F, last, p) {
+ PUTSIZE(p, index);
+ index++;
+ }
+
+ *E = new_cover(10);
+ *Rt = new_cover(10);
+ *Rp = new_cover(10);
+ R = new_cover(10);
+
+ /* Split F into E and R */
+ FD = cube2list(F, D);
+ foreach_set(F, last, p) {
+ if (cube_is_covered(FD, p)) {
+ R = sf_addset(R, p);
+ } else {
+ *E = sf_addset(*E, p);
+ }
+ if (debug & IRRED1) {
+ (void) printf("IRRED1: zr=%d ze=%d to-go=%d time=%s\n",
+ R->count, (*E)->count, F->count - (R->count + (*E)->count),
+ print_time(ptime()));
+ }
+ }
+ free_cubelist(FD);
+
+ /* Split R into Rt and Rp */
+ ED = cube2list(*E, D);
+ foreach_set(R, last, p) {
+ if (cube_is_covered(ED, p)) {
+ *Rt = sf_addset(*Rt, p);
+ } else {
+ *Rp = sf_addset(*Rp, p);
+ }
+ if (debug & IRRED1) {
+ (void) printf("IRRED1: zr=%d zrt=%d to-go=%d time=%s\n",
+ (*Rp)->count, (*Rt)->count,
+ R->count - ((*Rp)->count +(*Rt)->count), print_time(ptime()));
+ }
+ }
+ free_cubelist(ED);
+
+ free_cover(R);
+}
+
+/*
+ * irred_derive_table -- given the covers D, E and the set of
+ * partially redundant primes Rp, build a covering table showing
+ * possible selections of primes to cover Rp.
+ */
+
+sm_matrix *
+irred_derive_table(D, E, Rp)
+pcover D, E, Rp;
+{
+ register pcube last, p, *list;
+ sm_matrix *table;
+ int size_last_dominance, i;
+
+ /* Mark each cube in DE as not part of the redundant set */
+ foreach_set(D, last, p) {
+ RESET(p, REDUND);
+ }
+ foreach_set(E, last, p) {
+ RESET(p, REDUND);
+ }
+
+ /* Mark each cube in Rp as partially redundant */
+ foreach_set(Rp, last, p) {
+ SET(p, REDUND); /* belongs to redundant set */
+ }
+
+ /* For each cube in Rp, find ways to cover its minterms */
+ list = cube3list(D, E, Rp);
+ table = sm_alloc();
+ size_last_dominance = 0;
+ i = 0;
+ foreach_set(Rp, last, p) {
+ Rp_current = SIZE(p);
+ fcube_is_covered(list, p, table);
+ RESET(p, REDUND); /* can now consider this cube redundant */
+ if (debug & IRRED1) {
+ (void) printf("IRRED1: %d of %d to-go=%d, table=%dx%d time=%s\n",
+ i, Rp->count, Rp->count - i,
+ table->nrows, table->ncols, print_time(ptime()));
+ }
+ /* try to keep memory limits down by reducing table as we go along */
+ if (table->nrows - size_last_dominance > 1000) {
+ (void) sm_row_dominance(table);
+ size_last_dominance = table->nrows;
+ if (debug & IRRED1) {
+ (void) printf("IRRED1: delete redundant rows, now %dx%d\n",
+ table->nrows, table->ncols);
+ }
+ }
+ i++;
+ }
+ free_cubelist(list);
+
+ return table;
+}
+
+/* cube_is_covered -- determine if a cubelist "covers" a single cube */
+bool
+cube_is_covered(T, c)
+pcube *T, c;
+{
+ return tautology(cofactor(T,c));
+}
+
+
+
+/* tautology -- answer the tautology question for T */
+bool
+tautology(T)
+pcube *T; /* T will be disposed of */
+{
+ register pcube cl, cr;
+ register int best, result;
+ static int taut_level = 0;
+
+ if (debug & TAUT) {
+ debug_print(T, "TAUTOLOGY", taut_level++);
+ }
+
+ if ((result = taut_special_cases(T)) == MAYBE) {
+ cl = new_cube();
+ cr = new_cube();
+ best = binate_split_select(T, cl, cr, TAUT);
+ result = tautology(scofactor(T, cl, best)) &&
+ tautology(scofactor(T, cr, best));
+ free_cubelist(T);
+ free_cube(cl);
+ free_cube(cr);
+ }
+
+ if (debug & TAUT) {
+ printf("exit TAUTOLOGY[%d]: %s\n", --taut_level, print_bool(result));
+ }
+ return result;
+}
+
+/*
+ * taut_special_cases -- check special cases for tautology
+ */
+
+bool
+taut_special_cases(T)
+pcube *T; /* will be disposed if answer is determined */
+{
+ register pcube *T1, *Tsave, p, ceil=cube.temp[0], temp=cube.temp[1];
+ pcube *A, *B;
+ int var;
+
+ /* Check for a row of all 1's which implies tautology */
+ for(T1 = T+2; (p = *T1++) != NULL; ) {
+ if (full_row(p, T[0])) {
+ free_cubelist(T);
+ return TRUE;
+ }
+ }
+
+ /* Check for a column of all 0's which implies no tautology */
+start:
+ INLINEset_copy(ceil, T[0]);
+ for(T1 = T+2; (p = *T1++) != NULL; ) {
+ INLINEset_or(ceil, ceil, p);
+ }
+ if (! setp_equal(ceil, cube.fullset)) {
+ free_cubelist(T);
+ return FALSE;
+ }
+
+ /* Collect column counts, determine unate variables, etc. */
+ massive_count(T);
+
+ /* If function is unate (and no row of all 1's), then no tautology */
+ if (cdata.vars_unate == cdata.vars_active) {
+ free_cubelist(T);
+ return FALSE;
+
+ /* If active in a single variable (and no column of 0's) then tautology */
+ } else if (cdata.vars_active == 1) {
+ free_cubelist(T);
+ return TRUE;
+
+ /* Check for unate variables, and reduce cover if there are any */
+ } else if (cdata.vars_unate != 0) {
+ /* Form a cube "ceil" with full variables in the unate variables */
+ (void) set_copy(ceil, cube.emptyset);
+ for(var = 0; var < cube.num_vars; var++) {
+ if (cdata.is_unate[var]) {
+ INLINEset_or(ceil, ceil, cube.var_mask[var]);
+ }
+ }
+
+ /* Save only those cubes that are "full" in all unate variables */
+ for(Tsave = T1 = T+2; (p = *T1++) != 0; ) {
+ if (setp_implies(ceil, set_or(temp, p, T[0]))) {
+ *Tsave++ = p;
+ }
+ }
+ *Tsave++ = NULL;
+ T[1] = (pcube) Tsave;
+
+ if (debug & TAUT) {
+ printf("UNATE_REDUCTION: %d unate variables, reduced to %d\n",
+ cdata.vars_unate, CUBELISTSIZE(T));
+ }
+ goto start;
+
+ /* Check for component reduction */
+ } else if (cdata.var_zeros[cdata.best] < CUBELISTSIZE(T) / 2) {
+ if (cubelist_partition(T, &A, &B, debug & TAUT) == 0) {
+ return MAYBE;
+ } else {
+ free_cubelist(T);
+ if (tautology(A)) {
+ free_cubelist(B);
+ return TRUE;
+ } else {
+ return tautology(B);
+ }
+ }
+ }
+
+ /* We tried as hard as we could, but must recurse from here on */
+ return MAYBE;
+}
+
+/* fcube_is_covered -- determine exactly how a cubelist "covers" a cube */
+static void
+fcube_is_covered(T, c, table)
+pcube *T, c;
+sm_matrix *table;
+{
+ ftautology(cofactor(T,c), table);
+}
+
+
+/* ftautology -- find ways to make a tautology */
+static void
+ftautology(T, table)
+pcube *T; /* T will be disposed of */
+sm_matrix *table;
+{
+ register pcube cl, cr;
+ register int best;
+ static int ftaut_level = 0;
+
+ if (debug & TAUT) {
+ debug_print(T, "FIND_TAUTOLOGY", ftaut_level++);
+ }
+
+ if (ftaut_special_cases(T, table) == MAYBE) {
+ cl = new_cube();
+ cr = new_cube();
+ best = binate_split_select(T, cl, cr, TAUT);
+
+ ftautology(scofactor(T, cl, best), table);
+ ftautology(scofactor(T, cr, best), table);
+
+ free_cubelist(T);
+ free_cube(cl);
+ free_cube(cr);
+ }
+
+ if (debug & TAUT) {
+ (void) printf("exit FIND_TAUTOLOGY[%d]: table is %d by %d\n",
+ --ftaut_level, table->nrows, table->ncols);
+ }
+}
+
+static bool
+ftaut_special_cases(T, table)
+pcube *T; /* will be disposed if answer is determined */
+sm_matrix *table;
+{
+ register pcube *T1, *Tsave, p, temp = cube.temp[0], ceil = cube.temp[1];
+ int var, rownum;
+
+ /* Check for a row of all 1's in the essential cubes */
+ for(T1 = T+2; (p = *T1++) != 0; ) {
+ if (! TESTP(p, REDUND)) {
+ if (full_row(p, T[0])) {
+ /* subspace is covered by essentials -- no new rows for table */
+ free_cubelist(T);
+ return TRUE;
+ }
+ }
+ }
+
+ /* Collect column counts, determine unate variables, etc. */
+start:
+ massive_count(T);
+
+ /* If function is unate, find the rows of all 1's */
+ if (cdata.vars_unate == cdata.vars_active) {
+ /* find which nonessentials cover this subspace */
+ rownum = table->last_row ? table->last_row->row_num+1 : 0;
+ (void) sm_insert(table, rownum, Rp_current);
+ for(T1 = T+2; (p = *T1++) != 0; ) {
+ if (TESTP(p, REDUND)) {
+ /* See if a redundant cube covers this leaf */
+ if (full_row(p, T[0])) {
+ (void) sm_insert(table, rownum, (int) SIZE(p));
+ }
+ }
+ }
+ free_cubelist(T);
+ return TRUE;
+
+ /* Perform unate reduction if there are any unate variables */
+ } else if (cdata.vars_unate != 0) {
+ /* Form a cube "ceil" with full variables in the unate variables */
+ (void) set_copy(ceil, cube.emptyset);
+ for(var = 0; var < cube.num_vars; var++) {
+ if (cdata.is_unate[var]) {
+ INLINEset_or(ceil, ceil, cube.var_mask[var]);
+ }
+ }
+
+ /* Save only those cubes that are "full" in all unate variables */
+ for(Tsave = T1 = T+2; (p = *T1++) != 0; ) {
+ if (setp_implies(ceil, set_or(temp, p, T[0]))) {
+ *Tsave++ = p;
+ }
+ }
+ *Tsave++ = 0;
+ T[1] = (pcube) Tsave;
+
+ if (debug & TAUT) {
+ printf("UNATE_REDUCTION: %d unate variables, reduced to %d\n",
+ cdata.vars_unate, CUBELISTSIZE(T));
+ }
+ goto start;
+ }
+
+ /* Not much we can do about it */
+ return MAYBE;
+}
diff --git a/src/misc/espresso/main.c b/src/misc/espresso/main.c
new file mode 100644
index 00000000..0a511c0e
--- /dev/null
+++ b/src/misc/espresso/main.c
@@ -0,0 +1,746 @@
+/*
+ * Revision Control Information
+ *
+ * $Source$
+ * $Author$
+ * $Revision$
+ * $Date$
+ *
+ */
+/*
+ * Main driver for espresso
+ *
+ * Old style -do xxx, -out xxx, etc. are still supported.
+ */
+
+#include "espresso.h"
+#include "main.h" /* table definitions for options */
+
+static FILE *last_fp;
+static int input_type = FD_type;
+
+
+main(argc, argv)
+int argc;
+char *argv[];
+{
+ int i, j, first, last, strategy, out_type, option;
+ pPLA PLA, PLA1;
+ pcover F, Fold, Dold;
+ pset last1, p;
+ cost_t cost;
+ bool error, exact_cover;
+ long start;
+ extern char *util_optarg;
+ extern int util_optind;
+
+ start = ptime();
+
+ error = FALSE;
+ init_runtime();
+#ifdef RANDOM
+ srandom(314973);
+#endif
+
+ option = 0; /* default -D: ESPRESSO */
+ out_type = F_type; /* default -o: default is ON-set only */
+ debug = 0; /* default -d: no debugging info */
+ verbose_debug = FALSE; /* default -v: not verbose */
+ print_solution = TRUE; /* default -x: print the solution (!) */
+ summary = FALSE; /* default -s: no summary */
+ trace = FALSE; /* default -t: no trace information */
+ strategy = 0; /* default -S: strategy number */
+ first = -1; /* default -R: select range */
+ last = -1;
+ remove_essential = TRUE; /* default -e: */
+ force_irredundant = TRUE;
+ unwrap_onset = TRUE;
+ single_expand = FALSE;
+ pos = FALSE;
+ recompute_onset = FALSE;
+ use_super_gasp = FALSE;
+ use_random_order = FALSE;
+ kiss = FALSE;
+ echo_comments = TRUE;
+ echo_unknown_commands = TRUE;
+ exact_cover = FALSE; /* for -qm option, the default */
+
+ backward_compatibility_hack(&argc, argv, &option, &out_type);
+
+
+ /* parse command line options*/
+ while ((i = util_getopt(argc, argv, "D:S:de:o:r:stv:x")) != EOF) {
+ switch(i) {
+ case 'D': /* -Dcommand invokes a subcommand */
+ for(j = 0; option_table[j].name != 0; j++) {
+ if (strcmp(util_optarg, option_table[j].name) == 0) {
+ option = j;
+ break;
+ }
+ }
+ if (option_table[j].name == 0) {
+ (void) fprintf(stderr, "%s: bad subcommand \"%s\"\n",
+ argv[0], util_optarg);
+ exit(1);
+ }
+ break;
+
+ case 'o': /* -ooutput selects and output option */
+ for(j = 0; pla_types[j].key != 0; j++) {
+ if (strcmp(util_optarg, pla_types[j].key+1) == 0) {
+ out_type = pla_types[j].value;
+ break;
+ }
+ }
+ if (pla_types[j].key == 0) {
+ (void) fprintf(stderr, "%s: bad output type \"%s\"\n",
+ argv[0], util_optarg);
+ exit(1);
+ }
+ break;
+
+ case 'e': /* -eespresso selects an option for espresso */
+ for(j = 0; esp_opt_table[j].name != 0; j++) {
+ if (strcmp(util_optarg, esp_opt_table[j].name) == 0) {
+ *(esp_opt_table[j].variable) = esp_opt_table[j].value;
+ break;
+ }
+ }
+ if (esp_opt_table[j].name == 0) {
+ (void) fprintf(stderr, "%s: bad espresso option \"%s\"\n",
+ argv[0], util_optarg);
+ exit(1);
+ }
+ break;
+
+ case 'd': /* -d turns on (softly) all debug switches */
+ debug = debug_table[0].value;
+ trace = TRUE;
+ summary = TRUE;
+ break;
+
+ case 'v': /* -vdebug invokes a debug option */
+ verbose_debug = TRUE;
+ for(j = 0; debug_table[j].name != 0; j++) {
+ if (strcmp(util_optarg, debug_table[j].name) == 0) {
+ debug |= debug_table[j].value;
+ break;
+ }
+ }
+ if (debug_table[j].name == 0) {
+ (void) fprintf(stderr, "%s: bad debug type \"%s\"\n",
+ argv[0], util_optarg);
+ exit(1);
+ }
+ break;
+
+ case 't':
+ trace = TRUE;
+ break;
+
+ case 's':
+ summary = TRUE;
+ break;
+
+ case 'x': /* -x suppress printing of results */
+ print_solution = FALSE;
+ break;
+
+ case 'S': /* -S sets a strategy for several cmds */
+ strategy = atoi(util_optarg);
+ break;
+
+ case 'r': /* -r selects range (outputs or vars) */
+ if (sscanf(util_optarg, "%d-%d", &first, &last) < 2) {
+ (void) fprintf(stderr, "%s: bad output range \"%s\"\n",
+ argv[0], util_optarg);
+ exit(1);
+ }
+ break;
+
+ default:
+ usage();
+ exit(1);
+ }
+ }
+
+ /* provide version information and summaries */
+ if (summary || trace) {
+ /* echo command line and arguments */
+ printf("#");
+ for(i = 0; i < argc; i++) {
+ printf(" %s", argv[i]);
+ }
+ printf("\n");
+ printf("# %s\n", VERSION);
+ }
+
+ /* the remaining arguments are argv[util_optind ... argc-1] */
+ PLA = PLA1 = NIL(PLA_t);
+ switch(option_table[option].num_plas) {
+ case 2:
+ if (util_optind+2 < argc) fatal("trailing arguments on command line");
+ getPLA(util_optind++, argc, argv, option, &PLA, out_type);
+ getPLA(util_optind++, argc, argv, option, &PLA1, out_type);
+ break;
+ case 1:
+ if (util_optind+1 < argc) fatal("trailing arguments on command line");
+ getPLA(util_optind++, argc, argv, option, &PLA, out_type);
+ break;
+ }
+ if (util_optind < argc) fatal("trailing arguments on command line");
+
+ if (summary || trace) {
+ if (PLA != NIL(PLA_t)) PLA_summary(PLA);
+ if (PLA1 != NIL(PLA_t)) PLA_summary(PLA1);
+ }
+
+/*
+ * Now a case-statement to decide what to do
+ */
+
+ switch(option_table[option].key) {
+
+
+/******************** Espresso operations ********************/
+
+ case KEY_ESPRESSO:
+ Fold = sf_save(PLA->F);
+ PLA->F = espresso(PLA->F, PLA->D, PLA->R);
+ EXECUTE(error=verify(PLA->F,Fold,PLA->D), VERIFY_TIME, PLA->F, cost);
+ if (error) {
+ print_solution = FALSE;
+ PLA->F = Fold;
+ (void) check_consistency(PLA);
+ } else {
+ free_cover(Fold);
+ }
+ break;
+
+ case KEY_MANY_ESPRESSO: {
+ int pla_type;
+ do {
+ EXEC(PLA->F=espresso(PLA->F,PLA->D,PLA->R),"ESPRESSO ",PLA->F);
+ if (print_solution) {
+ fprint_pla(stdout, PLA, out_type);
+ (void) fflush(stdout);
+ }
+ pla_type = PLA->pla_type;
+ free_PLA(PLA);
+ setdown_cube();
+ FREE(cube.part_size);
+ } while (read_pla(last_fp, TRUE, TRUE, pla_type, &PLA) != EOF);
+ exit(0);
+ }
+
+ case KEY_simplify:
+ EXEC(PLA->F = simplify(cube1list(PLA->F)), "SIMPLIFY ", PLA->F);
+ break;
+
+ case KEY_so: /* minimize all functions as single-output */
+ if (strategy < 0 || strategy > 1) {
+ strategy = 0;
+ }
+ so_espresso(PLA, strategy);
+ break;
+
+ case KEY_so_both: /* minimize all functions as single-output */
+ if (strategy < 0 || strategy > 1) {
+ strategy = 0;
+ }
+ so_both_espresso(PLA, strategy);
+ break;
+
+ case KEY_expand: /* execute expand */
+ EXECUTE(PLA->F=expand(PLA->F,PLA->R,FALSE),EXPAND_TIME, PLA->F, cost);
+ break;
+
+ case KEY_irred: /* extract minimal irredundant subset */
+ EXECUTE(PLA->F = irredundant(PLA->F, PLA->D), IRRED_TIME, PLA->F, cost);
+ break;
+
+ case KEY_reduce: /* perform reduction */
+ EXECUTE(PLA->F = reduce(PLA->F, PLA->D), REDUCE_TIME, PLA->F, cost);
+ break;
+
+ case KEY_essen: /* check for essential primes */
+ foreach_set(PLA->F, last1, p) {
+ SET(p, RELESSEN);
+ RESET(p, NONESSEN);
+ }
+ EXECUTE(F = essential(&(PLA->F), &(PLA->D)), ESSEN_TIME, PLA->F, cost);
+ free_cover(F);
+ break;
+
+ case KEY_super_gasp:
+ PLA->F = super_gasp(PLA->F, PLA->D, PLA->R, &cost);
+ break;
+
+ case KEY_gasp:
+ PLA->F = last_gasp(PLA->F, PLA->D, PLA->R, &cost);
+ break;
+
+ case KEY_make_sparse: /* make_sparse step of Espresso */
+ PLA->F = make_sparse(PLA->F, PLA->D, PLA->R);
+ break;
+
+ case KEY_exact:
+ exact_cover = TRUE;
+
+ case KEY_qm:
+ Fold = sf_save(PLA->F);
+ PLA->F = minimize_exact(PLA->F, PLA->D, PLA->R, exact_cover);
+ EXECUTE(error=verify(PLA->F,Fold,PLA->D), VERIFY_TIME, PLA->F, cost);
+ if (error) {
+ print_solution = FALSE;
+ PLA->F = Fold;
+ (void) check_consistency(PLA);
+ }
+ free_cover(Fold);
+ break;
+
+ case KEY_primes: /* generate all prime implicants */
+ EXEC(PLA->F = primes_consensus(cube2list(PLA->F, PLA->D)),
+ "PRIMES ", PLA->F);
+ break;
+
+ case KEY_map: /* print out a Karnaugh map of function */
+ map(PLA->F);
+ print_solution = FALSE;
+ break;
+
+
+
+/******************** Output phase and bit pairing ********************/
+
+ case KEY_opo: /* sasao output phase assignment */
+ phase_assignment(PLA, strategy);
+ break;
+
+ case KEY_opoall: /* try all phase assignments (!) */
+ if (first < 0 || first >= cube.part_size[cube.output]) {
+ first = 0;
+ }
+ if (last < 0 || last >= cube.part_size[cube.output]) {
+ last = cube.part_size[cube.output] - 1;
+ }
+ opoall(PLA, first, last, strategy);
+ break;
+
+ case KEY_pair: /* find an optimal pairing */
+ find_optimal_pairing(PLA, strategy);
+ break;
+
+ case KEY_pairall: /* try all pairings !! */
+ pair_all(PLA, strategy);
+ break;
+
+
+
+/******************** Simple cover operations ********************/
+
+ case KEY_echo: /* echo the PLA */
+ break;
+
+ case KEY_taut: /* tautology check */
+ printf("ON-set is%sa tautology\n",
+ tautology(cube1list(PLA->F)) ? " " : " not ");
+ print_solution = FALSE;
+ break;
+
+ case KEY_contain: /* single cube containment */
+ PLA->F = sf_contain(PLA->F);
+ break;
+
+ case KEY_intersect: /* cover intersection */
+ PLA->F = cv_intersect(PLA->F, PLA1->F);
+ break;
+
+ case KEY_union: /* cover union */
+ PLA->F = sf_union(PLA->F, PLA1->F);
+ break;
+
+ case KEY_disjoint: /* make cover disjoint */
+ PLA->F = make_disjoint(PLA->F);
+ break;
+
+ case KEY_dsharp: /* cover disjoint-sharp */
+ PLA->F = cv_dsharp(PLA->F, PLA1->F);
+ break;
+
+ case KEY_sharp: /* cover sharp */
+ PLA->F = cv_sharp(PLA->F, PLA1->F);
+ break;
+
+ case KEY_lexsort: /* lexical sort order */
+ PLA->F = lex_sort(PLA->F);
+ break;
+
+ case KEY_stats: /* print info on size */
+ if (! summary) PLA_summary(PLA);
+ print_solution = FALSE;
+ break;
+
+ case KEY_minterms: /* explode into minterms */
+ if (first < 0 || first >= cube.num_vars) {
+ first = 0;
+ }
+ if (last < 0 || last >= cube.num_vars) {
+ last = cube.num_vars - 1;
+ }
+ PLA->F = sf_dupl(unravel_range(PLA->F, first, last));
+ break;
+
+ case KEY_d1merge: /* distance-1 merge */
+ if (first < 0 || first >= cube.num_vars) {
+ first = 0;
+ }
+ if (last < 0 || last >= cube.num_vars) {
+ last = cube.num_vars - 1;
+ }
+ for(i = first; i <= last; i++) {
+ PLA->F = d1merge(PLA->F, i);
+ }
+ break;
+
+ case KEY_d1merge_in: /* distance-1 merge inputs only */
+ for(i = 0; i < cube.num_binary_vars; i++) {
+ PLA->F = d1merge(PLA->F, i);
+ }
+ break;
+
+ case KEY_PLA_verify: /* check two PLAs for equivalence */
+ EXECUTE(error = PLA_verify(PLA, PLA1), VERIFY_TIME, PLA->F, cost);
+ if (error) {
+ printf("PLA comparison failed; the PLA's are not equivalent\n");
+ exit(1);
+ } else {
+ printf("PLA's compared equal\n");
+ exit(0);
+ }
+ break; /* silly */
+
+ case KEY_verify: /* check two covers for equivalence */
+ Fold = PLA->F; Dold = PLA->D; F = PLA1->F;
+ EXECUTE(error=verify(F, Fold, Dold), VERIFY_TIME, PLA->F, cost);
+ if (error) {
+ printf("PLA comparison failed; the PLA's are not equivalent\n");
+ exit(1);
+ } else {
+ printf("PLA's compared equal\n");
+ exit(0);
+ }
+ break; /* silly */
+
+ case KEY_check: /* check consistency */
+ (void) check_consistency(PLA);
+ print_solution = FALSE;
+ break;
+
+ case KEY_mapdc: /* compute don't care set */
+ map_dcset(PLA);
+ out_type = FD_type;
+ break;
+
+ case KEY_equiv:
+ find_equiv_outputs(PLA);
+ print_solution = FALSE;
+ break;
+
+ case KEY_separate: /* remove PLA->D from PLA->F */
+ PLA->F = complement(cube2list(PLA->D, PLA->R));
+ break;
+
+ case KEY_xor: {
+ pcover T1 = cv_intersect(PLA->F, PLA1->R);
+ pcover T2 = cv_intersect(PLA1->F, PLA->R);
+ free_cover(PLA->F);
+ PLA->F = sf_contain(sf_join(T1, T2));
+ free_cover(T1);
+ free_cover(T2);
+ break;
+ }
+
+ case KEY_fsm: {
+ disassemble_fsm(PLA, summary);
+ print_solution = FALSE;
+ break;
+ }
+
+ case KEY_test: {
+ pcover T, E;
+ T = sf_join(PLA->D, PLA->R);
+ E = new_cover(10);
+ sf_free(PLA->F);
+ EXECUTE(PLA->F = complement(cube1list(T)), COMPL_TIME, PLA->F, cost);
+ EXECUTE(PLA->F = expand(PLA->F, T, FALSE), EXPAND_TIME, PLA->F, cost);
+ EXECUTE(PLA->F = irredundant(PLA->F, E), IRRED_TIME, PLA->F, cost);
+ sf_free(T);
+ T = sf_join(PLA->F, PLA->R);
+ EXECUTE(PLA->D = expand(PLA->D, T, FALSE), EXPAND_TIME, PLA->D, cost);
+ EXECUTE(PLA->D = irredundant(PLA->D, E), IRRED_TIME, PLA->D, cost);
+ sf_free(T);
+ sf_free(E);
+ break;
+ }
+
+
+ }
+
+ /* Print a runtime summary if trace mode enabled */
+ if (trace) {
+ runtime();
+ }
+
+ /* Print total runtime */
+ if (summary || trace) {
+ print_trace(PLA->F, option_table[option].name, ptime()-start);
+ }
+
+ /* Output the solution */
+ if (print_solution) {
+ EXECUTE(fprint_pla(stdout, PLA, out_type), WRITE_TIME, PLA->F, cost);
+ }
+
+ /* Crash and burn if there was a verify error */
+ if (error) {
+ fatal("cover verification failed");
+ }
+
+ /* cleanup all used memory */
+ free_PLA(PLA);
+ FREE(cube.part_size);
+ setdown_cube(); /* free the cube/cdata structure data */
+ sf_cleanup(); /* free unused set structures */
+ sm_cleanup(); /* sparse matrix cleanup */
+
+ exit(0);
+}
+
+
+getPLA(opt, argc, argv, option, PLA, out_type)
+int opt;
+int argc;
+char *argv[];
+int option;
+pPLA *PLA;
+int out_type;
+{
+ FILE *fp;
+ int needs_dcset, needs_offset;
+ char *fname;
+
+ if (opt >= argc) {
+ fp = stdin;
+ fname = "(stdin)";
+ } else {
+ fname = argv[opt];
+ if (strcmp(fname, "-") == 0) {
+ fp = stdin;
+ } else if ((fp = fopen(argv[opt], "r")) == NULL) {
+ (void) fprintf(stderr, "%s: Unable to open %s\n", argv[0], fname);
+ exit(1);
+ }
+ }
+ if (option_table[option].key == KEY_echo) {
+ needs_dcset = (out_type & D_type) != 0;
+ needs_offset = (out_type & R_type) != 0;
+ } else {
+ needs_dcset = option_table[option].needs_dcset;
+ needs_offset = option_table[option].needs_offset;
+ }
+
+ if (read_pla(fp, needs_dcset, needs_offset, input_type, PLA) == EOF) {
+ (void) fprintf(stderr, "%s: Unable to find PLA on file %s\n", argv[0], fname);
+ exit(1);
+ }
+ (*PLA)->filename = util_strsav(fname);
+ filename = (*PLA)->filename;
+/* (void) fclose(fp);*/
+/* hackto support -Dmany */
+ last_fp = fp;
+}
+
+
+runtime()
+{
+ int i;
+ long total = 1, temp;
+
+ for(i = 0; i < TIME_COUNT; i++) {
+ total += total_time[i];
+ }
+ for(i = 0; i < TIME_COUNT; i++) {
+ if (total_calls[i] != 0) {
+ temp = 100 * total_time[i];
+ printf("# %s\t%2d call(s) for %s (%2ld.%01ld%%)\n",
+ total_name[i], total_calls[i], print_time(total_time[i]),
+ temp/total, (10 * (temp%total)) / total);
+ }
+ }
+}
+
+
+init_runtime()
+{
+ total_name[READ_TIME] = "READ ";
+ total_name[WRITE_TIME] = "WRITE ";
+ total_name[COMPL_TIME] = "COMPL ";
+ total_name[REDUCE_TIME] = "REDUCE ";
+ total_name[EXPAND_TIME] = "EXPAND ";
+ total_name[ESSEN_TIME] = "ESSEN ";
+ total_name[IRRED_TIME] = "IRRED ";
+ total_name[GREDUCE_TIME] = "REDUCE_GASP";
+ total_name[GEXPAND_TIME] = "EXPAND_GASP";
+ total_name[GIRRED_TIME] = "IRRED_GASP ";
+ total_name[MV_REDUCE_TIME] ="MV_REDUCE ";
+ total_name[RAISE_IN_TIME] = "RAISE_IN ";
+ total_name[VERIFY_TIME] = "VERIFY ";
+ total_name[PRIMES_TIME] = "PRIMES ";
+ total_name[MINCOV_TIME] = "MINCOV ";
+}
+
+
+subcommands()
+{
+ int i, col;
+ printf(" ");
+ col = 16;
+ for(i = 0; option_table[i].name != 0; i++) {
+ if ((col + strlen(option_table[i].name) + 1) > 76) {
+ printf(",\n ");
+ col = 16;
+ } else if (i != 0) {
+ printf(", ");
+ }
+ printf("%s", option_table[i].name);
+ col += strlen(option_table[i].name) + 2;
+ }
+ printf("\n");
+}
+
+
+usage()
+{
+ printf("%s\n\n", VERSION);
+ printf("SYNOPSIS: espresso [options] [file]\n\n");
+ printf(" -d Enable debugging\n");
+ printf(" -e[opt] Select espresso option:\n");
+ printf(" fast, ness, nirr, nunwrap, onset, pos, strong,\n");
+ printf(" eat, eatdots, kiss, random\n");
+ printf(" -o[type] Select output format:\n");
+ printf(" f, fd, fr, fdr, pleasure, eqntott, kiss, cons\n");
+ printf(" -rn-m Select range for subcommands:\n");
+ printf(" d1merge: first and last variables (0 ... m-1)\n");
+ printf(" minterms: first and last variables (0 ... m-1)\n");
+ printf(" opoall: first and last outputs (0 ... m-1)\n");
+ printf(" -s Provide short execution summary\n");
+ printf(" -t Provide longer execution trace\n");
+ printf(" -x Suppress printing of solution\n");
+ printf(" -v[type] Verbose debugging detail (-v '' for all)\n");
+ printf(" -D[cmd] Execute subcommand 'cmd':\n");
+ subcommands();
+ printf(" -Sn Select strategy for subcommands:\n");
+ printf(" opo: bit2=exact bit1=repeated bit0=skip sparse\n");
+ printf(" opoall: 0=minimize, 1=exact\n");
+ printf(" pair: 0=algebraic, 1=strongd, 2=espresso, 3=exact\n");
+ printf(" pairall: 0=minimize, 1=exact, 2=opo\n");
+ printf(" so_espresso: 0=minimize, 1=exact\n");
+ printf(" so_both: 0=minimize, 1=exact\n");
+}
+
+/*
+ * Hack for backward compatibility (ACK! )
+ */
+
+backward_compatibility_hack(argc, argv, option, out_type)
+int *argc;
+char **argv;
+int *option;
+int *out_type;
+{
+ int i, j;
+
+ /* Scan the argument list for something to do (default is ESPRESSO) */
+ *option = 0;
+ for(i = 1; i < (*argc)-1; i++) {
+ if (strcmp(argv[i], "-do") == 0) {
+ for(j = 0; option_table[j].name != 0; j++)
+ if (strcmp(argv[i+1], option_table[j].name) == 0) {
+ *option = j;
+ delete_arg(argc, argv, i+1);
+ delete_arg(argc, argv, i);
+ break;
+ }
+ if (option_table[j].name == 0) {
+ (void) fprintf(stderr,
+ "espresso: bad keyword \"%s\" following -do\n",argv[i+1]);
+ exit(1);
+ }
+ break;
+ }
+ }
+
+ for(i = 1; i < (*argc)-1; i++) {
+ if (strcmp(argv[i], "-out") == 0) {
+ for(j = 0; pla_types[j].key != 0; j++)
+ if (strcmp(pla_types[j].key+1, argv[i+1]) == 0) {
+ *out_type = pla_types[j].value;
+ delete_arg(argc, argv, i+1);
+ delete_arg(argc, argv, i);
+ break;
+ }
+ if (pla_types[j].key == 0) {
+ (void) fprintf(stderr,
+ "espresso: bad keyword \"%s\" following -out\n",argv[i+1]);
+ exit(1);
+ }
+ break;
+ }
+ }
+
+ for(i = 1; i < (*argc); i++) {
+ if (argv[i][0] == '-') {
+ for(j = 0; esp_opt_table[j].name != 0; j++) {
+ if (strcmp(argv[i]+1, esp_opt_table[j].name) == 0) {
+ delete_arg(argc, argv, i);
+ *(esp_opt_table[j].variable) = esp_opt_table[j].value;
+ break;
+ }
+ }
+ }
+ }
+
+ if (check_arg(argc, argv, "-fdr")) input_type = FDR_type;
+ if (check_arg(argc, argv, "-fr")) input_type = FR_type;
+ if (check_arg(argc, argv, "-f")) input_type = F_type;
+}
+
+
+/* delete_arg -- delete an argument from the argument list */
+delete_arg(argc, argv, num)
+int *argc, num;
+register char *argv[];
+{
+ register int i;
+ (*argc)--;
+ for(i = num; i < *argc; i++) {
+ argv[i] = argv[i+1];
+ }
+}
+
+
+/* check_arg -- scan argv for an argument, and return TRUE if found */
+bool check_arg(argc, argv, s)
+int *argc;
+register char *argv[], *s;
+{
+ register int i;
+ for(i = 1; i < *argc; i++) {
+ if (strcmp(argv[i], s) == 0) {
+ delete_arg(argc, argv, i);
+ return TRUE;
+ }
+ }
+ return FALSE;
+}
diff --git a/src/misc/espresso/main.h b/src/misc/espresso/main.h
new file mode 100644
index 00000000..00657f39
--- /dev/null
+++ b/src/misc/espresso/main.h
@@ -0,0 +1,122 @@
+/*
+ * Revision Control Information
+ *
+ * $Source$
+ * $Author$
+ * $Revision$
+ * $Date$
+ *
+ */
+enum keys {
+ KEY_ESPRESSO, KEY_PLA_verify, KEY_check, KEY_contain, KEY_d1merge,
+ KEY_disjoint, KEY_dsharp, KEY_echo, KEY_essen, KEY_exact, KEY_expand,
+ KEY_gasp, KEY_intersect, KEY_irred, KEY_lexsort, KEY_make_sparse,
+ KEY_map, KEY_mapdc, KEY_minterms, KEY_opo, KEY_opoall,
+ KEY_pair, KEY_pairall, KEY_primes, KEY_qm, KEY_reduce, KEY_sharp,
+ KEY_simplify, KEY_so, KEY_so_both, KEY_stats, KEY_super_gasp, KEY_taut,
+ KEY_test, KEY_equiv, KEY_union, KEY_verify, KEY_MANY_ESPRESSO,
+ KEY_separate, KEY_xor, KEY_d1merge_in, KEY_fsm,
+ KEY_unknown
+};
+
+/* Lookup table for program options */
+struct {
+ char *name;
+ enum keys key;
+ int num_plas;
+ bool needs_offset;
+ bool needs_dcset;
+} option_table [] = {
+ /* ways to minimize functions */
+ "ESPRESSO", KEY_ESPRESSO, 1, TRUE, TRUE, /* must be first */
+ "many", KEY_MANY_ESPRESSO, 1, TRUE, TRUE,
+ "exact", KEY_exact, 1, TRUE, TRUE,
+ "qm", KEY_qm, 1, TRUE, TRUE,
+ "single_output", KEY_so, 1, TRUE, TRUE,
+ "so", KEY_so, 1, TRUE, TRUE,
+ "so_both", KEY_so_both, 1, TRUE, TRUE,
+ "simplify", KEY_simplify, 1, FALSE, FALSE,
+ "echo", KEY_echo, 1, FALSE, FALSE,
+
+ /* output phase assignment and assignment of inputs to two-bit decoders */
+ "opo", KEY_opo, 1, TRUE, TRUE,
+ "opoall", KEY_opoall, 1, TRUE, TRUE,
+ "pair", KEY_pair, 1, TRUE, TRUE,
+ "pairall", KEY_pairall, 1, TRUE, TRUE,
+
+ /* Ways to check covers */
+ "check", KEY_check, 1, TRUE, TRUE,
+ "stats", KEY_stats, 1, FALSE, FALSE,
+ "verify", KEY_verify, 2, FALSE, TRUE,
+ "PLAverify", KEY_PLA_verify, 2, FALSE, TRUE,
+
+ /* hacks */
+ "equiv", KEY_equiv, 1, TRUE, TRUE,
+ "map", KEY_map, 1, FALSE, FALSE,
+ "mapdc", KEY_mapdc, 1, FALSE, FALSE,
+ "fsm", KEY_fsm, 1, FALSE, TRUE,
+
+ /* the basic boolean operations on covers */
+ "contain", KEY_contain, 1, FALSE, FALSE,
+ "d1merge", KEY_d1merge, 1, FALSE, FALSE,
+ "d1merge_in", KEY_d1merge_in, 1, FALSE, FALSE,
+ "disjoint", KEY_disjoint, 1, TRUE, FALSE,
+ "dsharp", KEY_dsharp, 2, FALSE, FALSE,
+ "intersect", KEY_intersect, 2, FALSE, FALSE,
+ "minterms", KEY_minterms, 1, FALSE, FALSE,
+ "primes", KEY_primes, 1, FALSE, TRUE,
+ "separate", KEY_separate, 1, TRUE, TRUE,
+ "sharp", KEY_sharp, 2, FALSE, FALSE,
+ "union", KEY_union, 2, FALSE, FALSE,
+ "xor", KEY_xor, 2, TRUE, TRUE,
+
+ /* debugging only -- call each step of the espresso algorithm */
+ "essen", KEY_essen, 1, FALSE, TRUE,
+ "expand", KEY_expand, 1, TRUE, FALSE,
+ "gasp", KEY_gasp, 1, TRUE, TRUE,
+ "irred", KEY_irred, 1, FALSE, TRUE,
+ "make_sparse", KEY_make_sparse, 1, TRUE, TRUE,
+ "reduce", KEY_reduce, 1, FALSE, TRUE,
+ "taut", KEY_taut, 1, FALSE, FALSE,
+ "super_gasp", KEY_super_gasp, 1, TRUE, TRUE,
+ "lexsort", KEY_lexsort, 1, FALSE, FALSE,
+ "test", KEY_test, 1, TRUE, TRUE,
+ 0, KEY_unknown, 0, FALSE, FALSE /* must be last */
+};
+
+
+struct {
+ char *name;
+ int value;
+} debug_table[] = {
+ "", EXPAND + ESSEN + IRRED + REDUCE + SPARSE + GASP + SHARP + MINCOV,
+ "compl", COMPL, "essen", ESSEN,
+ "expand", EXPAND, "expand1", EXPAND1|EXPAND,
+ "irred", IRRED, "irred1", IRRED1|IRRED,
+ "reduce", REDUCE, "reduce1", REDUCE1|REDUCE,
+ "mincov", MINCOV, "mincov1", MINCOV1|MINCOV,
+ "sparse", SPARSE, "sharp", SHARP,
+ "taut", TAUT, "gasp", GASP,
+ "exact", EXACT,
+ 0,
+};
+
+
+struct {
+ char *name;
+ int *variable;
+ int value;
+} esp_opt_table[] = {
+ "eat", &echo_comments, FALSE,
+ "eatdots", &echo_unknown_commands, FALSE,
+ "fast", &single_expand, TRUE,
+ "kiss", &kiss, TRUE,
+ "ness", &remove_essential, FALSE,
+ "nirr", &force_irredundant, FALSE,
+ "nunwrap", &unwrap_onset, FALSE,
+ "onset", &recompute_onset, TRUE,
+ "pos", &pos, TRUE,
+ "random", &use_random_order, TRUE,
+ "strong", &use_super_gasp, TRUE,
+ 0,
+};
diff --git a/src/misc/espresso/map.c b/src/misc/espresso/map.c
new file mode 100644
index 00000000..5ccf264c
--- /dev/null
+++ b/src/misc/espresso/map.c
@@ -0,0 +1,115 @@
+/*
+ * Revision Control Information
+ *
+ * $Source$
+ * $Author$
+ * $Revision$
+ * $Date$
+ *
+ */
+#include "espresso.h"
+
+static pcube Gcube;
+static pset Gminterm;
+
+pset minterms(T)
+pcover T;
+{
+ int size, var;
+ register pcube last;
+
+ size = 1;
+ for(var = 0; var < cube.num_vars; var++)
+ size *= cube.part_size[var];
+ Gminterm = set_new(size);
+
+ foreach_set(T, last, Gcube)
+ explode(cube.num_vars-1, 0);
+
+ return Gminterm;
+}
+
+
+void explode(var, z)
+int var, z;
+{
+ int i, last = cube.last_part[var];
+ for(i=cube.first_part[var], z *= cube.part_size[var]; i<=last; i++, z++)
+ if (is_in_set(Gcube, i))
+ if (var == 0)
+ set_insert(Gminterm, z);
+ else
+ explode(var-1, z);
+}
+
+
+static int mapindex[16][16] = {
+ 0, 1, 3, 2, 16, 17, 19, 18, 80, 81, 83, 82, 64, 65, 67, 66,
+ 4, 5, 7, 6, 20, 21, 23, 22, 84, 85, 87, 86, 68, 69, 71, 70,
+ 12, 13, 15, 14, 28, 29, 31, 30, 92, 93, 95, 94, 76, 77, 79, 78,
+ 8, 9, 11, 10, 24, 25, 27, 26, 88, 89, 91, 90, 72, 73, 75, 74,
+
+ 32, 33, 35, 34, 48, 49, 51, 50, 112,113,115,114, 96, 97, 99, 98,
+ 36, 37, 39, 38, 52, 53, 55, 54, 116,117,119,118, 100,101,103,102,
+ 44, 45, 47, 46, 60, 61, 63, 62, 124,125,127,126, 108,109,111,110,
+ 40, 41, 43, 42, 56, 57, 59, 58, 120,121,123,122, 104,105,107,106,
+
+
+ 160,161,163,162, 176,177,179,178, 240,241,243,242, 224,225,227,226,
+ 164,165,167,166, 180,181,183,182, 244,245,247,246, 228,229,231,230,
+ 172,173,175,174, 188,189,191,190, 252,253,255,254, 236,237,239,238,
+ 168,169,171,170, 184,185,187,186, 248,249,251,250, 232,233,235,234,
+
+ 128,129,131,130, 144,145,147,146, 208,209,211,210, 192,193,195,194,
+ 132,133,135,134, 148,149,151,150, 212,213,215,214, 196,197,199,198,
+ 140,141,143,142, 156,157,159,158, 220,221,223,222, 204,205,207,206,
+ 136,137,139,138, 152,153,155,154, 216,217,219,218, 200,201,203,202
+};
+
+#define POWER2(n) (1 << n)
+void map(T)
+pcover T;
+{
+ int j, k, l, other_input_offset, output_offset, outnum, ind;
+ int largest_input_ind, numout;
+ char c;
+ pset m;
+ bool some_output;
+
+ m = minterms(T);
+ largest_input_ind = POWER2(cube.num_binary_vars);
+ numout = cube.part_size[cube.num_vars-1];
+
+ for(outnum = 0; outnum < numout; outnum++) {
+ output_offset = outnum * largest_input_ind;
+ printf("\n\nOutput space # %d\n", outnum);
+ for(l = 0; l <= MAX(cube.num_binary_vars - 8, 0); l++) {
+ other_input_offset = l * 256;
+ for(k = 0; k < 16; k++) {
+ some_output = FALSE;
+ for(j = 0; j < 16; j++) {
+ ind = mapindex[k][j] + other_input_offset;
+ if (ind < largest_input_ind) {
+ c = is_in_set(m, ind+output_offset) ? '1' : '.';
+ putchar(c);
+ some_output = TRUE;
+ }
+ if ((j+1)%4 == 0)
+ putchar(' ');
+ if ((j+1)%8 == 0)
+ printf(" ");
+ }
+ if (some_output)
+ putchar('\n');
+ if ((k+1)%4 == 0) {
+ if (k != 15 && mapindex[k+1][0] >= largest_input_ind)
+ break;
+ putchar('\n');
+ }
+ if ((k+1)%8 == 0)
+ putchar('\n');
+ }
+ }
+ }
+ set_free(m);
+}
diff --git a/src/misc/espresso/matrix.c b/src/misc/espresso/matrix.c
new file mode 100644
index 00000000..747fe54f
--- /dev/null
+++ b/src/misc/espresso/matrix.c
@@ -0,0 +1,574 @@
+/*
+ * Revision Control Information
+ *
+ * $Source$
+ * $Author$
+ * $Revision$
+ * $Date$
+ *
+ */
+//#include "port.h"
+#include "sparse_int.h"
+
+/*
+ * free-lists are only used if 'FAST_AND_LOOSE' is set; this is because
+ * we lose the debugging capability of libmm_t which trashes objects when
+ * they are free'd. However, FAST_AND_LOOSE is much faster if matrices
+ * are created and freed frequently.
+ */
+
+#ifdef FAST_AND_LOOSE
+sm_element *sm_element_freelist;
+sm_row *sm_row_freelist;
+sm_col *sm_col_freelist;
+#endif
+
+
+sm_matrix *
+sm_alloc()
+{
+ register sm_matrix *A;
+
+ A = ALLOC(sm_matrix, 1);
+ A->rows = NIL(sm_row *);
+ A->cols = NIL(sm_col *);
+ A->nrows = A->ncols = 0;
+ A->rows_size = A->cols_size = 0;
+ A->first_row = A->last_row = NIL(sm_row);
+ A->first_col = A->last_col = NIL(sm_col);
+ A->user_word = NIL(char); /* for our user ... */
+ return A;
+}
+
+
+sm_matrix *
+sm_alloc_size(row, col)
+int row, col;
+{
+ register sm_matrix *A;
+
+ A = sm_alloc();
+ sm_resize(A, row, col);
+ return A;
+}
+
+
+void
+sm_free(A)
+sm_matrix *A;
+{
+#ifdef FAST_AND_LOOSE
+ register sm_row *prow;
+
+ if (A->first_row != 0) {
+ for(prow = A->first_row; prow != 0; prow = prow->next_row) {
+ /* add the elements to the free list of elements */
+ prow->last_col->next_col = sm_element_freelist;
+ sm_element_freelist = prow->first_col;
+ }
+
+ /* Add the linked list of rows to the row-free-list */
+ A->last_row->next_row = sm_row_freelist;
+ sm_row_freelist = A->first_row;
+
+ /* Add the linked list of cols to the col-free-list */
+ A->last_col->next_col = sm_col_freelist;
+ sm_col_freelist = A->first_col;
+ }
+#else
+ register sm_row *prow, *pnext_row;
+ register sm_col *pcol, *pnext_col;
+
+ for(prow = A->first_row; prow != 0; prow = pnext_row) {
+ pnext_row = prow->next_row;
+ sm_row_free(prow);
+ }
+ for(pcol = A->first_col; pcol != 0; pcol = pnext_col) {
+ pnext_col = pcol->next_col;
+ pcol->first_row = pcol->last_row = NIL(sm_element);
+ sm_col_free(pcol);
+ }
+#endif
+
+ /* Free the arrays to map row/col numbers into pointers */
+ FREE(A->rows);
+ FREE(A->cols);
+ FREE(A);
+}
+
+
+sm_matrix *
+sm_dup(A)
+sm_matrix *A;
+{
+ register sm_row *prow;
+ register sm_element *p;
+ register sm_matrix *B;
+
+ B = sm_alloc();
+ if (A->last_row != 0) {
+ sm_resize(B, A->last_row->row_num, A->last_col->col_num);
+ for(prow = A->first_row; prow != 0; prow = prow->next_row) {
+ for(p = prow->first_col; p != 0; p = p->next_col) {
+ (void) sm_insert(B, p->row_num, p->col_num);
+ }
+ }
+ }
+ return B;
+}
+
+
+void
+sm_resize(A, row, col)
+register sm_matrix *A;
+int row, col;
+{
+ register int i, new_size;
+
+ if (row >= A->rows_size) {
+ new_size = MAX(A->rows_size*2, row+1);
+ A->rows = REALLOC(sm_row *, A->rows, new_size);
+ for(i = A->rows_size; i < new_size; i++) {
+ A->rows[i] = NIL(sm_row);
+ }
+ A->rows_size = new_size;
+ }
+
+ if (col >= A->cols_size) {
+ new_size = MAX(A->cols_size*2, col+1);
+ A->cols = REALLOC(sm_col *, A->cols, new_size);
+ for(i = A->cols_size; i < new_size; i++) {
+ A->cols[i] = NIL(sm_col);
+ }
+ A->cols_size = new_size;
+ }
+}
+
+
+/*
+ * insert -- insert a value into the matrix
+ */
+sm_element *
+sm_insert(A, row, col)
+register sm_matrix *A;
+register int row, col;
+{
+ register sm_row *prow;
+ register sm_col *pcol;
+ register sm_element *element;
+ sm_element *save_element;
+
+ if (row >= A->rows_size || col >= A->cols_size) {
+ sm_resize(A, row, col);
+ }
+
+ prow = A->rows[row];
+ if (prow == NIL(sm_row)) {
+ prow = A->rows[row] = sm_row_alloc();
+ prow->row_num = row;
+ sorted_insert(sm_row, A->first_row, A->last_row, A->nrows,
+ next_row, prev_row, row_num, row, prow);
+ }
+
+ pcol = A->cols[col];
+ if (pcol == NIL(sm_col)) {
+ pcol = A->cols[col] = sm_col_alloc();
+ pcol->col_num = col;
+ sorted_insert(sm_col, A->first_col, A->last_col, A->ncols,
+ next_col, prev_col, col_num, col, pcol);
+ }
+
+ /* get a new item, save its address */
+ sm_element_alloc(element);
+ save_element = element;
+
+ /* insert it into the row list */
+ sorted_insert(sm_element, prow->first_col, prow->last_col,
+ prow->length, next_col, prev_col, col_num, col, element);
+
+ /* if it was used, also insert it into the column list */
+ if (element == save_element) {
+ sorted_insert(sm_element, pcol->first_row, pcol->last_row,
+ pcol->length, next_row, prev_row, row_num, row, element);
+ } else {
+ /* otherwise, it was already in matrix -- free element we allocated */
+ sm_element_free(save_element);
+ }
+ return element;
+}
+
+
+sm_element *
+sm_find(A, rownum, colnum)
+sm_matrix *A;
+int rownum, colnum;
+{
+ sm_row *prow;
+ sm_col *pcol;
+
+ prow = sm_get_row(A, rownum);
+ if (prow == NIL(sm_row)) {
+ return NIL(sm_element);
+ } else {
+ pcol = sm_get_col(A, colnum);
+ if (pcol == NIL(sm_col)) {
+ return NIL(sm_element);
+ }
+ if (prow->length < pcol->length) {
+ return sm_row_find(prow, colnum);
+ } else {
+ return sm_col_find(pcol, rownum);
+ }
+ }
+}
+
+
+void
+sm_remove(A, rownum, colnum)
+sm_matrix *A;
+int rownum, colnum;
+{
+ sm_remove_element(A, sm_find(A, rownum, colnum));
+}
+
+
+
+void
+sm_remove_element(A, p)
+register sm_matrix *A;
+register sm_element *p;
+{
+ register sm_row *prow;
+ register sm_col *pcol;
+
+ if (p == 0) return;
+
+ /* Unlink the element from its row */
+ prow = sm_get_row(A, p->row_num);
+ dll_unlink(p, prow->first_col, prow->last_col,
+ next_col, prev_col, prow->length);
+
+ /* if no more elements in the row, discard the row header */
+ if (prow->first_col == NIL(sm_element)) {
+ sm_delrow(A, p->row_num);
+ }
+
+ /* Unlink the element from its column */
+ pcol = sm_get_col(A, p->col_num);
+ dll_unlink(p, pcol->first_row, pcol->last_row,
+ next_row, prev_row, pcol->length);
+
+ /* if no more elements in the column, discard the column header */
+ if (pcol->first_row == NIL(sm_element)) {
+ sm_delcol(A, p->col_num);
+ }
+
+ sm_element_free(p);
+}
+
+void
+sm_delrow(A, i)
+sm_matrix *A;
+int i;
+{
+ register sm_element *p, *pnext;
+ sm_col *pcol;
+ sm_row *prow;
+
+ prow = sm_get_row(A, i);
+ if (prow != NIL(sm_row)) {
+ /* walk across the row */
+ for(p = prow->first_col; p != 0; p = pnext) {
+ pnext = p->next_col;
+
+ /* unlink the item from the column (and delete it) */
+ pcol = sm_get_col(A, p->col_num);
+ sm_col_remove_element(pcol, p);
+
+ /* discard the column if it is now empty */
+ if (pcol->first_row == NIL(sm_element)) {
+ sm_delcol(A, pcol->col_num);
+ }
+ }
+
+ /* discard the row -- we already threw away the elements */
+ A->rows[i] = NIL(sm_row);
+ dll_unlink(prow, A->first_row, A->last_row,
+ next_row, prev_row, A->nrows);
+ prow->first_col = prow->last_col = NIL(sm_element);
+ sm_row_free(prow);
+ }
+}
+
+void
+sm_delcol(A, i)
+sm_matrix *A;
+int i;
+{
+ register sm_element *p, *pnext;
+ sm_row *prow;
+ sm_col *pcol;
+
+ pcol = sm_get_col(A, i);
+ if (pcol != NIL(sm_col)) {
+ /* walk down the column */
+ for(p = pcol->first_row; p != 0; p = pnext) {
+ pnext = p->next_row;
+
+ /* unlink the element from the row (and delete it) */
+ prow = sm_get_row(A, p->row_num);
+ sm_row_remove_element(prow, p);
+
+ /* discard the row if it is now empty */
+ if (prow->first_col == NIL(sm_element)) {
+ sm_delrow(A, prow->row_num);
+ }
+ }
+
+ /* discard the column -- we already threw away the elements */
+ A->cols[i] = NIL(sm_col);
+ dll_unlink(pcol, A->first_col, A->last_col,
+ next_col, prev_col, A->ncols);
+ pcol->first_row = pcol->last_row = NIL(sm_element);
+ sm_col_free(pcol);
+ }
+}
+
+void
+sm_copy_row(dest, dest_row, prow)
+register sm_matrix *dest;
+int dest_row;
+sm_row *prow;
+{
+ register sm_element *p;
+
+ for(p = prow->first_col; p != 0; p = p->next_col) {
+ (void) sm_insert(dest, dest_row, p->col_num);
+ }
+}
+
+
+void
+sm_copy_col(dest, dest_col, pcol)
+register sm_matrix *dest;
+int dest_col;
+sm_col *pcol;
+{
+ register sm_element *p;
+
+ for(p = pcol->first_row; p != 0; p = p->next_row) {
+ (void) sm_insert(dest, dest_col, p->row_num);
+ }
+}
+
+
+sm_row *
+sm_longest_row(A)
+sm_matrix *A;
+{
+ register sm_row *large_row, *prow;
+ register int max_length;
+
+ max_length = 0;
+ large_row = NIL(sm_row);
+ for(prow = A->first_row; prow != 0; prow = prow->next_row) {
+ if (prow->length > max_length) {
+ max_length = prow->length;
+ large_row = prow;
+ }
+ }
+ return large_row;
+}
+
+
+sm_col *
+sm_longest_col(A)
+sm_matrix *A;
+{
+ register sm_col *large_col, *pcol;
+ register int max_length;
+
+ max_length = 0;
+ large_col = NIL(sm_col);
+ for(pcol = A->first_col; pcol != 0; pcol = pcol->next_col) {
+ if (pcol->length > max_length) {
+ max_length = pcol->length;
+ large_col = pcol;
+ }
+ }
+ return large_col;
+}
+
+int
+sm_num_elements(A)
+sm_matrix *A;
+{
+ register sm_row *prow;
+ register int num;
+
+ num = 0;
+ sm_foreach_row(A, prow) {
+ num += prow->length;
+ }
+ return num;
+}
+
+int
+sm_read(fp, A)
+FILE *fp;
+sm_matrix **A;
+{
+ int i, j, err;
+
+ *A = sm_alloc();
+ while (! feof(fp)) {
+ err = fscanf(fp, "%d %d", &i, &j);
+ if (err == EOF) {
+ return 1;
+ } else if (err != 2) {
+ return 0;
+ }
+ (void) sm_insert(*A, i, j);
+ }
+ return 1;
+}
+
+
+int
+sm_read_compressed(fp, A)
+FILE *fp;
+sm_matrix **A;
+{
+ int i, j, k, nrows, ncols;
+ unsigned long x;
+
+ *A = sm_alloc();
+ if (fscanf(fp, "%d %d", &nrows, &ncols) != 2) {
+ return 0;
+ }
+ sm_resize(*A, nrows, ncols);
+
+ for(i = 0; i < nrows; i++) {
+ if (fscanf(fp, "%lx", &x) != 1) {
+ return 0;
+ }
+ for(j = 0; j < ncols; j += 32) {
+ if (fscanf(fp, "%lx", &x) != 1) {
+ return 0;
+ }
+ for(k = j; x != 0; x >>= 1, k++) {
+ if (x & 1) {
+ (void) sm_insert(*A, i, k);
+ }
+ }
+ }
+ }
+ return 1;
+}
+
+
+void
+sm_write(fp, A)
+FILE *fp;
+sm_matrix *A;
+{
+ register sm_row *prow;
+ register sm_element *p;
+
+ for(prow = A->first_row; prow != 0; prow = prow->next_row) {
+ for(p = prow->first_col; p != 0; p = p->next_col) {
+ (void) fprintf(fp, "%d %d\n", p->row_num, p->col_num);
+ }
+ }
+}
+
+void
+sm_print(fp, A)
+FILE *fp;
+sm_matrix *A;
+{
+ register sm_row *prow;
+ register sm_col *pcol;
+ int c;
+
+ if (A->last_col->col_num >= 100) {
+ (void) fprintf(fp, " ");
+ for(pcol = A->first_col; pcol != 0; pcol = pcol->next_col) {
+ (void) fprintf(fp, "%d", (pcol->col_num / 100)%10);
+ }
+ putc('\n', fp);
+ }
+
+ if (A->last_col->col_num >= 10) {
+ (void) fprintf(fp, " ");
+ for(pcol = A->first_col; pcol != 0; pcol = pcol->next_col) {
+ (void) fprintf(fp, "%d", (pcol->col_num / 10)%10);
+ }
+ putc('\n', fp);
+ }
+
+ (void) fprintf(fp, " ");
+ for(pcol = A->first_col; pcol != 0; pcol = pcol->next_col) {
+ (void) fprintf(fp, "%d", pcol->col_num % 10);
+ }
+ putc('\n', fp);
+
+ (void) fprintf(fp, " ");
+ for(pcol = A->first_col; pcol != 0; pcol = pcol->next_col) {
+ (void) fprintf(fp, "-");
+ }
+ putc('\n', fp);
+
+ for(prow = A->first_row; prow != 0; prow = prow->next_row) {
+ (void) fprintf(fp, "%3d:", prow->row_num);
+
+ for(pcol = A->first_col; pcol != 0; pcol = pcol->next_col) {
+ c = sm_row_find(prow, pcol->col_num) ? '1' : '.';
+ putc(c, fp);
+ }
+ putc('\n', fp);
+ }
+}
+
+
+void
+sm_dump(A, s, max)
+sm_matrix *A;
+char *s;
+int max;
+{
+ FILE *fp = stdout;
+
+ (void) fprintf(fp, "%s %d rows by %d cols\n", s, A->nrows, A->ncols);
+ if (A->nrows < max) {
+ sm_print(fp, A);
+ }
+}
+
+void
+sm_cleanup()
+{
+#ifdef FAST_AND_LOOSE
+ register sm_element *p, *pnext;
+ register sm_row *prow, *pnextrow;
+ register sm_col *pcol, *pnextcol;
+
+ for(p = sm_element_freelist; p != 0; p = pnext) {
+ pnext = p->next_col;
+ FREE(p);
+ }
+ sm_element_freelist = 0;
+
+ for(prow = sm_row_freelist; prow != 0; prow = pnextrow) {
+ pnextrow = prow->next_row;
+ FREE(prow);
+ }
+ sm_row_freelist = 0;
+
+ for(pcol = sm_col_freelist; pcol != 0; pcol = pnextcol) {
+ pnextcol = pcol->next_col;
+ FREE(pcol);
+ }
+ sm_col_freelist = 0;
+#endif
+}
diff --git a/src/misc/espresso/mincov.c b/src/misc/espresso/mincov.c
new file mode 100644
index 00000000..ee18a3f1
--- /dev/null
+++ b/src/misc/espresso/mincov.c
@@ -0,0 +1,378 @@
+/*
+ * Revision Control Information
+ *
+ * $Source$
+ * $Author$
+ * $Revision$
+ * $Date$
+ *
+ */
+#include "mincov_int.h"
+
+/*
+ * mincov.c
+ */
+
+#define USE_GIMPEL
+#define USE_INDEP_SET
+
+static int select_column();
+static void select_essential();
+static int verify_cover();
+
+#define fail(why) {\
+ (void) fprintf(stderr, "Fatal error: file %s, line %d\n%s\n",\
+ __FILE__, __LINE__, why);\
+ (void) fflush(stdout);\
+ abort();\
+}
+
+sm_row *
+sm_minimum_cover(A, weight, heuristic, debug_level)
+sm_matrix *A;
+int *weight;
+int heuristic; /* set to 1 for a heuristic covering */
+int debug_level; /* how deep in the recursion to provide info */
+{
+ stats_t stats;
+ solution_t *best, *select;
+ sm_row *prow, *sol;
+ sm_col *pcol;
+ sm_matrix *dup_A;
+ int nelem, bound;
+ double sparsity;
+
+ /* Avoid sillyness */
+ if (A->nrows <= 0) {
+ return sm_row_alloc(); /* easy to cover */
+ }
+
+ /* Initialize debugging structure */
+ stats.start_time = util_cpu_time();
+ stats.debug = debug_level > 0;
+ stats.max_print_depth = debug_level;
+ stats.max_depth = -1;
+ stats.nodes = 0;
+ stats.component = stats.comp_count = 0;
+ stats.gimpel = stats.gimpel_count = 0;
+ stats.no_branching = heuristic != 0;
+ stats.lower_bound = -1;
+
+ /* Check the matrix sparsity */
+ nelem = 0;
+ sm_foreach_row(A, prow) {
+ nelem += prow->length;
+ }
+ sparsity = (double) nelem / (double) (A->nrows * A->ncols);
+
+ /* Determine an upper bound on the solution */
+ bound = 1;
+ sm_foreach_col(A, pcol) {
+ bound += WEIGHT(weight, pcol->col_num);
+ }
+
+ /* Perform the covering */
+ select = solution_alloc();
+ dup_A = sm_dup(A);
+ best = sm_mincov(dup_A, select, weight, 0, bound, 0, &stats);
+ sm_free(dup_A);
+ solution_free(select);
+
+ if (stats.debug) {
+ if (stats.no_branching) {
+ (void) printf("**** heuristic covering ...\n");
+ (void) printf("lower bound = %d\n", stats.lower_bound);
+ }
+ (void) printf("matrix = %d by %d with %d elements (%4.3f%%)\n",
+ A->nrows, A->ncols, nelem, sparsity * 100.0);
+ (void) printf("cover size = %d elements\n", best->row->length);
+ (void) printf("cover cost = %d\n", best->cost);
+ (void) printf("time = %s\n",
+ util_print_time(util_cpu_time() - stats.start_time));
+ (void) printf("components = %d\n", stats.comp_count);
+ (void) printf("gimpel = %d\n", stats.gimpel_count);
+ (void) printf("nodes = %d\n", stats.nodes);
+ (void) printf("max_depth = %d\n", stats.max_depth);
+ }
+
+ sol = sm_row_dup(best->row);
+ if (! verify_cover(A, sol)) {
+ fail("mincov: internal error -- cover verification failed\n");
+ }
+ solution_free(best);
+ return sol;
+}
+
+/*
+ * Find the best cover for 'A' (given that 'select' already selected);
+ *
+ * - abort search if a solution cannot be found which beats 'bound'
+ *
+ * - if any solution meets 'lower_bound', then it is the optimum solution
+ * and can be returned without further work.
+ */
+
+solution_t *
+sm_mincov(A, select, weight, lb, bound, depth, stats)
+sm_matrix *A;
+solution_t *select;
+int *weight;
+int lb;
+int bound;
+int depth;
+stats_t *stats;
+{
+ sm_matrix *A1, *A2, *L, *R;
+ sm_element *p;
+ solution_t *select1, *select2, *best, *best1, *best2, *indep;
+ int pick, lb_new, debug;
+
+ /* Start out with some debugging information */
+ stats->nodes++;
+ if (depth > stats->max_depth) stats->max_depth = depth;
+ debug = stats->debug && (depth <= stats->max_print_depth);
+
+ /* Apply row dominance, column dominance, and select essentials */
+ select_essential(A, select, weight, bound);
+ if (select->cost >= bound) {
+ return NIL(solution_t);
+ }
+
+ /* See if gimpel's reduction technique applies ... */
+#ifdef USE_GIMPEL
+ if ( weight == NIL(int)) { /* hack until we fix it */
+ if (gimpel_reduce(A, select, weight, lb, bound, depth, stats, &best)) {
+ return best;
+ }
+ }
+#endif
+
+#ifdef USE_INDEP_SET
+ /* Determine bound from here to final solution using independent-set */
+ indep = sm_maximal_independent_set(A, weight);
+
+ /* make sure the lower bound is monotonically increasing */
+ lb_new = MAX(select->cost + indep->cost, lb);
+ pick = select_column(A, weight, indep);
+ solution_free(indep);
+#else
+ lb_new = select->cost + (A->nrows > 0);
+ pick = select_column(A, weight, NIL(solution_t));
+#endif
+
+ if (depth == 0) {
+ stats->lower_bound = lb_new + stats->gimpel;
+ }
+
+ if (debug) {
+ (void) printf("ABSMIN[%2d]%s", depth, stats->component ? "*" : " ");
+ (void) printf(" %3dx%3d sel=%3d bnd=%3d lb=%3d %12s ",
+ A->nrows, A->ncols, select->cost + stats->gimpel,
+ bound + stats->gimpel, lb_new + stats->gimpel,
+ util_print_time(util_cpu_time()-stats->start_time));
+ }
+
+ /* Check for bounding based on no better solution possible */
+ if (lb_new >= bound) {
+ if (debug) (void) printf("bounded\n");
+ best = NIL(solution_t);
+
+
+ /* Check for new best solution */
+ } else if (A->nrows == 0) {
+ best = solution_dup(select);
+ if (debug) (void) printf("BEST\n");
+ if (stats->debug && stats->component == 0) {
+ (void) printf("new 'best' solution %d at level %d (time is %s)\n",
+ best->cost + stats->gimpel, depth,
+ util_print_time(util_cpu_time() - stats->start_time));
+ }
+
+
+ /* Check for a partition of the problem */
+ } else if (sm_block_partition(A, &L, &R)) {
+ /* Make L the smaller problem */
+ if (L->ncols > R->ncols) {
+ A1 = L;
+ L = R;
+ R = A1;
+ }
+ if (debug) (void) printf("comp %d %d\n", L->nrows, R->nrows);
+ stats->comp_count++;
+
+ /* Solve problem for L */
+ select1 = solution_alloc();
+ stats->component++;
+ best1 = sm_mincov(L, select1, weight, 0,
+ bound-select->cost, depth+1, stats);
+ stats->component--;
+ solution_free(select1);
+ sm_free(L);
+
+ /* Add best solution to the selected set */
+ if (best1 == NIL(solution_t)) {
+ best = NIL(solution_t);
+ } else {
+ for(p = best1->row->first_col; p != 0; p = p->next_col) {
+ solution_add(select, weight, p->col_num);
+ }
+ solution_free(best1);
+
+ /* recur for the remaining block */
+ best = sm_mincov(R, select, weight, lb_new, bound, depth+1, stats);
+ }
+ sm_free(R);
+
+ /* We've tried as hard as possible, but now we must split and recur */
+ } else {
+ if (debug) (void) printf("pick=%d\n", pick);
+
+ /* Assume we choose this column to be in the covering set */
+ A1 = sm_dup(A);
+ select1 = solution_dup(select);
+ solution_accept(select1, A1, weight, pick);
+ best1 = sm_mincov(A1, select1, weight, lb_new, bound, depth+1, stats);
+ solution_free(select1);
+ sm_free(A1);
+
+ /* Update the upper bound if we found a better solution */
+ if (best1 != NIL(solution_t) && bound > best1->cost) {
+ bound = best1->cost;
+ }
+
+ /* See if this is a heuristic covering (no branching) */
+ if (stats->no_branching) {
+ return best1;
+ }
+
+ /* Check for reaching lower bound -- if so, don't actually branch */
+ if (best1 != NIL(solution_t) && best1->cost == lb_new) {
+ return best1;
+ }
+
+ /* Now assume we cannot have that column */
+ A2 = sm_dup(A);
+ select2 = solution_dup(select);
+ solution_reject(select2, A2, weight, pick);
+ best2 = sm_mincov(A2, select2, weight, lb_new, bound, depth+1, stats);
+ solution_free(select2);
+ sm_free(A2);
+
+ best = solution_choose_best(best1, best2);
+ }
+
+ return best;
+}
+
+static int
+select_column(A, weight, indep)
+sm_matrix *A;
+int *weight;
+solution_t *indep;
+{
+ register sm_col *pcol;
+ register sm_row *prow, *indep_cols;
+ register sm_element *p, *p1;
+ double w, best;
+ int best_col;
+
+ indep_cols = sm_row_alloc();
+ if (indep != NIL(solution_t)) {
+ /* Find which columns are in the independent sets */
+ for(p = indep->row->first_col; p != 0; p = p->next_col) {
+ prow = sm_get_row(A, p->col_num);
+ for(p1 = prow->first_col; p1 != 0; p1 = p1->next_col) {
+ (void) sm_row_insert(indep_cols, p1->col_num);
+ }
+ }
+ } else {
+ /* select out of all columns */
+ sm_foreach_col(A, pcol) {
+ (void) sm_row_insert(indep_cols, pcol->col_num);
+ }
+ }
+
+ /* Find the best column */
+ best_col = -1;
+ best = -1;
+
+ /* Consider only columns which are in some independent row */
+ sm_foreach_row_element(indep_cols, p1) {
+ pcol = sm_get_col(A, p1->col_num);
+
+ /* Compute the total 'value' of all things covered by the column */
+ w = 0.0;
+ for(p = pcol->first_row; p != 0; p = p->next_row) {
+ prow = sm_get_row(A, p->row_num);
+ w += 1.0 / ((double) prow->length - 1.0);
+ }
+
+ /* divide this by the relative cost of choosing this column */
+ w = w / (double) WEIGHT(weight, pcol->col_num);
+
+ /* maximize this ratio */
+ if (w > best) {
+ best_col = pcol->col_num;
+ best = w;
+ }
+ }
+
+ sm_row_free(indep_cols);
+ return best_col;
+}
+
+static void
+select_essential(A, select, weight, bound)
+sm_matrix *A;
+solution_t *select;
+int *weight;
+int bound; /* must beat this solution */
+{
+ register sm_element *p;
+ register sm_row *prow, *essen;
+ int delcols, delrows, essen_count;
+
+ do {
+ /* Check for dominated columns */
+ delcols = sm_col_dominance(A, weight);
+
+ /* Find the rows with only 1 element (the essentials) */
+ essen = sm_row_alloc();
+ sm_foreach_row(A, prow) {
+ if (prow->length == 1) {
+ (void) sm_row_insert(essen, prow->first_col->col_num);
+ }
+ }
+
+ /* Select all of the elements */
+ sm_foreach_row_element(essen, p) {
+ solution_accept(select, A, weight, p->col_num);
+ /* Make sure solution still looks good */
+ if (select->cost >= bound) {
+ sm_row_free(essen);
+ return;
+ }
+ }
+ essen_count = essen->length;
+ sm_row_free(essen);
+
+ /* Check for dominated rows */
+ delrows = sm_row_dominance(A);
+
+ } while (delcols > 0 || delrows > 0 || essen_count > 0);
+}
+
+static int
+verify_cover(A, cover)
+sm_matrix *A;
+sm_row *cover;
+{
+ sm_row *prow;
+
+ sm_foreach_row(A, prow) {
+ if (! sm_row_intersects(prow, cover)) {
+ return 0;
+ }
+ }
+ return 1;
+}
diff --git a/src/misc/espresso/mincov.h b/src/misc/espresso/mincov.h
new file mode 100644
index 00000000..95310774
--- /dev/null
+++ b/src/misc/espresso/mincov.h
@@ -0,0 +1,11 @@
+/*
+ * Revision Control Information
+ *
+ * $Source$
+ * $Author$
+ * $Revision$
+ * $Date$
+ *
+ */
+/* exported */
+extern sm_row *sm_minimum_cover();
diff --git a/src/misc/espresso/mincov_int.h b/src/misc/espresso/mincov_int.h
new file mode 100644
index 00000000..e81850f2
--- /dev/null
+++ b/src/misc/espresso/mincov_int.h
@@ -0,0 +1,55 @@
+/*
+ * Revision Control Information
+ *
+ * $Source$
+ * $Author$
+ * $Revision$
+ * $Date$
+ *
+ */
+//#include "port.h"
+//#include "utility.h"
+#include "sparse.h"
+#include "mincov.h"
+
+#include "util_hack.h" // added
+
+
+typedef struct stats_struct stats_t;
+struct stats_struct {
+ int debug; /* 1 if debugging is enabled */
+ int max_print_depth; /* dump stats for levels up to this level */
+ int max_depth; /* deepest the recursion has gone */
+ int nodes; /* total nodes visited */
+ int component; /* currently solving a component */
+ int comp_count; /* number of components detected */
+ int gimpel_count; /* number of times Gimpel reduction applied */
+ int gimpel; /* currently inside Gimpel reduction */
+ long start_time; /* cpu time when the covering started */
+ int no_branching;
+ int lower_bound;
+};
+
+
+
+typedef struct solution_struct solution_t;
+struct solution_struct {
+ sm_row *row;
+ int cost;
+};
+
+
+extern solution_t *solution_alloc();
+extern void solution_free();
+extern solution_t *solution_dup();
+extern void solution_accept();
+extern void solution_reject();
+extern void solution_add();
+extern solution_t *solution_choose_best();
+
+extern solution_t *sm_maximal_independent_set();
+extern solution_t *sm_mincov();
+extern int gimpel_reduce();
+
+
+#define WEIGHT(weight, col) (weight == NIL(int) ? 1 : weight[col])
diff --git a/src/misc/espresso/module.make b/src/misc/espresso/module.make
new file mode 100644
index 00000000..53ce982a
--- /dev/null
+++ b/src/misc/espresso/module.make
@@ -0,0 +1,39 @@
+SRC += src/misc/espresso/cofactor.c \
+ src/misc/espresso/cols.c \
+ src/misc/espresso/compl.c \
+ src/misc/espresso/contain.c \
+ src/misc/espresso/cubehack.c \
+ src/misc/espresso/cubestr.c \
+ src/misc/espresso/cvrin.c \
+ src/misc/espresso/cvrm.c \
+ src/misc/espresso/cvrmisc.c \
+ src/misc/espresso/cvrout.c \
+ src/misc/espresso/dominate.c \
+ src/misc/espresso/equiv.c \
+ src/misc/espresso/espresso.c \
+ src/misc/espresso/essen.c \
+ src/misc/espresso/exact.c \
+ src/misc/espresso/expand.c \
+ src/misc/espresso/gasp.c \
+ src/misc/espresso/gimpel.c \
+ src/misc/espresso/globals.c \
+ src/misc/espresso/hack.c \
+ src/misc/espresso/indep.c \
+ src/misc/espresso/irred.c \
+ src/misc/espresso/map.c \
+ src/misc/espresso/matrix.c \
+ src/misc/espresso/mincov.c \
+ src/misc/espresso/opo.c \
+ src/misc/espresso/pair.c \
+ src/misc/espresso/part.c \
+ src/misc/espresso/primes.c \
+ src/misc/espresso/reduce.c \
+ src/misc/espresso/rows.c \
+ src/misc/espresso/set.c \
+ src/misc/espresso/setc.c \
+ src/misc/espresso/sharp.c \
+ src/misc/espresso/sminterf.c \
+ src/misc/espresso/solution.c \
+ src/misc/espresso/sparse.c \
+ src/misc/espresso/unate.c \
+ src/misc/espresso/verify.c
diff --git a/src/misc/espresso/opo.c b/src/misc/espresso/opo.c
new file mode 100644
index 00000000..8daa0771
--- /dev/null
+++ b/src/misc/espresso/opo.c
@@ -0,0 +1,624 @@
+/*
+ * Revision Control Information
+ *
+ * $Source$
+ * $Author$
+ * $Revision$
+ * $Date$
+ *
+ */
+#include "espresso.h"
+
+/*
+ * Phase assignment technique (T. Sasao):
+ *
+ * 1. create a function with 2*m outputs which implements the
+ * original function and its complement for each output
+ *
+ * 2. minimize this function
+ *
+ * 3. choose the minimum number of prime implicants from the
+ * result of step 2 which are needed to realize either a function
+ * or its complement for each output
+ *
+ * Step 3 is performed in a rather crude way -- by simply multiplying
+ * out a large expression of the form:
+ *
+ * I = (ab + cdef)(acd + bgh) ...
+ *
+ * which is a product of m expressions where each expression has two
+ * product terms -- one representing which primes are needed for the
+ * function, and one representing which primes are needed for the
+ * complement. The largest product term resulting shows which primes
+ * to keep to implement one function or the other for each output.
+ * For problems with many outputs, this may grind to a
+ * halt.
+ *
+ * Untried: form complement of I and use unate_complement ...
+ *
+ * I have unsuccessfully tried several modifications to the basic
+ * algorithm. The first is quite simple: use Sasao's technique, but
+ * only commit to a single output at a time (rather than all
+ * outputs). The goal would be that the later minimizations can "take
+ * into account" the partial assignment at each step. This is
+ * expensive (m+1 minimizations rather than 2), and the results are
+ * discouraging.
+ *
+ * The second modification is rather complicated. The result from the
+ * minimization in step 2 is guaranteed to be minimal. Hence, for
+ * each output, the set of primes with a 1 in that output are both
+ * necessary and sufficient to implement the function. Espresso
+ * achieves the minimality using the routine MAKE_SPARSE. The
+ * modification is to prevent MAKE_SPARSE from running. Hence, there
+ * are potentially many subsets of the set of primes with a 1 in a
+ * column which can be used to implement that output. We use
+ * IRREDUNDANT to enumerate all possible subsets and then proceed as
+ * before.
+ */
+
+static int opo_no_make_sparse;
+static int opo_repeated;
+static int opo_exact;
+static void minimize();
+
+void phase_assignment(PLA, opo_strategy)
+pPLA PLA;
+int opo_strategy;
+{
+ opo_no_make_sparse = opo_strategy % 2;
+ skip_make_sparse = opo_no_make_sparse;
+ opo_repeated = (opo_strategy / 2) % 2;
+ opo_exact = (opo_strategy / 4) % 2;
+
+ /* Determine a phase assignment */
+ if (PLA->phase != NULL) {
+ FREE(PLA->phase);
+ }
+
+ if (opo_repeated) {
+ PLA->phase = set_save(cube.fullset);
+ repeated_phase_assignment(PLA);
+ } else {
+ PLA->phase = find_phase(PLA, 0, (pcube) NULL);
+ }
+
+ /* Now minimize with this assignment */
+ skip_make_sparse = FALSE;
+ (void) set_phase(PLA);
+ minimize(PLA);
+}
+
+/*
+ * repeated_phase_assignment -- an alternate strategy which commits
+ * to a single phase assignment a step at a time. Performs m + 1
+ * minimizations !
+ */
+void repeated_phase_assignment(PLA)
+pPLA PLA;
+{
+ int i;
+ pcube phase;
+
+ for(i = 0; i < cube.part_size[cube.output]; i++) {
+
+ /* Find best assignment for all undecided outputs */
+ phase = find_phase(PLA, i, PLA->phase);
+
+ /* Commit for only a single output ... */
+ if (! is_in_set(phase, cube.first_part[cube.output] + i)) {
+ set_remove(PLA->phase, cube.first_part[cube.output] + i);
+ }
+
+ if (trace || summary) {
+ printf("\nOPO loop for output #%d\n", i);
+ printf("PLA->phase is %s\n", pc1(PLA->phase));
+ printf("phase is %s\n", pc1(phase));
+ }
+ set_free(phase);
+ }
+}
+
+
+/*
+ * find_phase -- find a phase assignment for the PLA for all outputs starting
+ * with output number first_output.
+ */
+pcube find_phase(PLA, first_output, phase1)
+pPLA PLA;
+int first_output;
+pcube phase1;
+{
+ pcube phase;
+ pPLA PLA1;
+
+ phase = set_save(cube.fullset);
+
+ /* setup the double-phase characteristic function, resize the cube */
+ PLA1 = new_PLA();
+ PLA1->F = sf_save(PLA->F);
+ PLA1->R = sf_save(PLA->R);
+ PLA1->D = sf_save(PLA->D);
+ if (phase1 != NULL) {
+ PLA1->phase = set_save(phase1);
+ (void) set_phase(PLA1);
+ }
+ EXEC_S(output_phase_setup(PLA1, first_output), "OPO-SETUP ", PLA1->F);
+
+ /* minimize the double-phase function */
+ minimize(PLA1);
+
+ /* set the proper phases according to what gives a minimum solution */
+ EXEC_S(PLA1->F = opo(phase, PLA1->F, PLA1->D, PLA1->R, first_output),
+ "OPO ", PLA1->F);
+ free_PLA(PLA1);
+
+ /* set the cube structure to reflect the old size */
+ setdown_cube();
+ cube.part_size[cube.output] -=
+ (cube.part_size[cube.output] - first_output) / 2;
+ cube_setup();
+
+ return phase;
+}
+
+/*
+ * opo -- multiply the expression out to determine a minimum subset of
+ * primes.
+ */
+
+/*ARGSUSED*/
+pcover opo(phase, T, D, R, first_output)
+pcube phase;
+pcover T, D, R;
+int first_output;
+{
+ int offset, output, i, last_output, ind;
+ pset pdest, select, p, p1, last, last1, not_covered, tmp;
+ pset_family temp, T1, T2;
+
+ /* must select all primes for outputs [0 .. first_output-1] */
+ select = set_full(T->count);
+ for(output = 0; output < first_output; output++) {
+ ind = cube.first_part[cube.output] + output;
+ foreachi_set(T, i, p) {
+ if (is_in_set(p, ind)) {
+ set_remove(select, i);
+ }
+ }
+ }
+
+ /* Recursively perform the intersections */
+ offset = (cube.part_size[cube.output] - first_output) / 2;
+ last_output = first_output + offset - 1;
+ temp = opo_recur(T, D, select, offset, first_output, last_output);
+
+ /* largest set is on top -- select primes which are inferred from it */
+ pdest = temp->data;
+ T1 = new_cover(T->count);
+ foreachi_set(T, i, p) {
+ if (! is_in_set(pdest, i)) {
+ T1 = sf_addset(T1, p);
+ }
+ }
+
+ set_free(select);
+ sf_free(temp);
+
+ /* finding phases is difficult -- see which functions are not covered */
+ T2 = complement(cube1list(T1));
+ not_covered = new_cube();
+ tmp = new_cube();
+ foreach_set(T, last, p) {
+ foreach_set(T2, last1, p1) {
+ if (cdist0(p, p1)) {
+ (void) set_or(not_covered, not_covered, set_and(tmp, p, p1));
+ }
+ }
+ }
+ free_cover(T);
+ free_cover(T2);
+ set_free(tmp);
+
+ /* Now reflect the phase choice in a single cube */
+ for(output = first_output; output <= last_output; output++) {
+ ind = cube.first_part[cube.output] + output;
+ if (is_in_set(not_covered, ind)) {
+ if (is_in_set(not_covered, ind + offset)) {
+ fatal("error in output phase assignment");
+ } else {
+ set_remove(phase, ind);
+ }
+ }
+ }
+ set_free(not_covered);
+ return T1;
+}
+
+pset_family opo_recur(T, D, select, offset, first, last)
+pcover T, D;
+pcube select;
+int offset, first, last;
+{
+ static int level = 0;
+ int middle;
+ pset_family sl, sr, temp;
+
+ level++;
+ if (first == last) {
+#if 0
+ if (opo_no_make_sparse) {
+ temp = form_cover_table(T, D, select, first, first + offset);
+ } else {
+ temp = opo_leaf(T, select, first, first + offset);
+ }
+#else
+ temp = opo_leaf(T, select, first, first + offset);
+#endif
+ } else {
+ middle = (first + last) / 2;
+ sl = opo_recur(T, D, select, offset, first, middle);
+ sr = opo_recur(T, D, select, offset, middle+1, last);
+ temp = unate_intersect(sl, sr, level == 1);
+ if (trace) {
+ printf("# OPO[%d]: %4d = %4d x %4d, time = %s\n", level - 1,
+ temp->count, sl->count, sr->count, print_time(ptime()));
+ (void) fflush(stdout);
+ }
+ free_cover(sl);
+ free_cover(sr);
+ }
+ level--;
+ return temp;
+}
+
+
+pset_family opo_leaf(T, select, out1, out2)
+register pcover T;
+pset select;
+int out1, out2;
+{
+ register pset_family temp;
+ register pset p, pdest;
+ register int i;
+
+ out1 += cube.first_part[cube.output];
+ out2 += cube.first_part[cube.output];
+
+ /* Allocate space for the result */
+ temp = sf_new(2, T->count);
+
+ /* Find which primes are needed for the ON-set of this fct */
+ pdest = GETSET(temp, temp->count++);
+ (void) set_copy(pdest, select);
+ foreachi_set(T, i, p) {
+ if (is_in_set(p, out1)) {
+ set_remove(pdest, i);
+ }
+ }
+
+ /* Find which primes are needed for the OFF-set of this fct */
+ pdest = GETSET(temp, temp->count++);
+ (void) set_copy(pdest, select);
+ foreachi_set(T, i, p) {
+ if (is_in_set(p, out2)) {
+ set_remove(pdest, i);
+ }
+ }
+
+ return temp;
+}
+
+#if 0
+pset_family form_cover_table(F, D, select, f, fbar)
+pcover F, D;
+pset select;
+int f, fbar; /* indices of f and fbar in the output part */
+{
+ register int i;
+ register pcube p;
+ pset_family f_table, fbar_table;
+
+ /* setup required for fcube_is_covered */
+ Rp_size = F->count;
+ Rp_start = set_new(Rp_size);
+ foreachi_set(F, i, p) {
+ PUTSIZE(p, i);
+ }
+ foreachi_set(D, i, p) {
+ RESET(p, REDUND);
+ }
+
+ f_table = find_covers(F, D, select, f);
+ fbar_table = find_covers(F, D, select, fbar);
+ f_table = sf_append(f_table, fbar_table);
+
+ set_free(Rp_start);
+ return f_table;
+}
+
+
+pset_family find_covers(F, D, select, n)
+pcover F, D;
+register pset select;
+int n;
+{
+ register pset p, last, new;
+ pcover F1;
+ pcube *Flist;
+ pset_family f_table, table;
+ int i;
+
+ n += cube.first_part[cube.output];
+
+ /* save cubes in this output, and remove the output variable */
+ F1 = new_cover(F->count);
+ foreach_set(F, last, p)
+ if (is_in_set(p, n)) {
+ new = GETSET(F1, F1->count++);
+ set_or(new, p, cube.var_mask[cube.output]);
+ PUTSIZE(new, SIZE(p));
+ SET(new, REDUND);
+ }
+
+ /* Find ways (sop form) to fail to cover output indexed by n */
+ Flist = cube2list(F1, D);
+ table = sf_new(10, Rp_size);
+ foreach_set(F1, last, p) {
+ set_fill(Rp_start, Rp_size);
+ set_remove(Rp_start, SIZE(p));
+ table = sf_append(table, fcube_is_covered(Flist, p));
+ RESET(p, REDUND);
+ }
+ set_fill(Rp_start, Rp_size);
+ foreach_set(table, last, p) {
+ set_diff(p, Rp_start, p);
+ }
+
+ /* complement this to get possible ways to cover the function */
+ for(i = 0; i < Rp_size; i++) {
+ if (! is_in_set(select, i)) {
+ p = set_new(Rp_size);
+ set_insert(p, i);
+ table = sf_addset(table, p);
+ set_free(p);
+ }
+ }
+ f_table = unate_compl(table);
+
+ /* what a pain, but we need bitwise complement of this */
+ set_fill(Rp_start, Rp_size);
+ foreach_set(f_table, last, p) {
+ set_diff(p, Rp_start, p);
+ }
+
+ free_cubelist(Flist);
+ sf_free(F1);
+ return f_table;
+}
+#endif
+
+/*
+ * Take a PLA (ON-set, OFF-set and DC-set) and create the
+ * "double-phase characteristic function" which is merely a new
+ * function which has twice as many outputs and realizes both the
+ * function and the complement.
+ *
+ * The cube structure is assumed to represent the PLA upon entering.
+ * It will be modified to represent the double-phase function upon
+ * exit.
+ *
+ * Only the outputs numbered starting with "first_output" are
+ * duplicated in the output part
+ */
+
+output_phase_setup(PLA, first_output)
+INOUT pPLA PLA;
+int first_output;
+{
+ pcover F, R, D;
+ pcube mask, mask1, last;
+ int first_part, offset;
+ bool save;
+ register pcube p, pr, pf;
+ register int i, last_part;
+
+ if (cube.output == -1)
+ fatal("output_phase_setup: must have an output");
+
+ F = PLA->F;
+ D = PLA->D;
+ R = PLA->R;
+ first_part = cube.first_part[cube.output] + first_output;
+ last_part = cube.last_part[cube.output];
+ offset = cube.part_size[cube.output] - first_output;
+
+ /* Change the output size, setup the cube structure */
+ setdown_cube();
+ cube.part_size[cube.output] += offset;
+ cube_setup();
+
+ /* Create a mask to select that part of the cube which isn't changing */
+ mask = set_save(cube.fullset);
+ for(i = first_part; i < cube.size; i++)
+ set_remove(mask, i);
+ mask1 = set_save(mask);
+ for(i = cube.first_part[cube.output]; i < first_part; i++) {
+ set_remove(mask1, i);
+ }
+
+ PLA->F = new_cover(F->count + R->count);
+ PLA->R = new_cover(F->count + R->count);
+ PLA->D = new_cover(D->count);
+
+ foreach_set(F, last, p) {
+ pf = GETSET(PLA->F, (PLA->F)->count++);
+ pr = GETSET(PLA->R, (PLA->R)->count++);
+ INLINEset_and(pf, mask, p);
+ INLINEset_and(pr, mask1, p);
+ for(i = first_part; i <= last_part; i++)
+ if (is_in_set(p, i))
+ set_insert(pf, i);
+ save = FALSE;
+ for(i = first_part; i <= last_part; i++)
+ if (is_in_set(p, i))
+ save = TRUE, set_insert(pr, i+offset);
+ if (! save) PLA->R->count--;
+ }
+
+ foreach_set(R, last, p) {
+ pf = GETSET(PLA->F, (PLA->F)->count++);
+ pr = GETSET(PLA->R, (PLA->R)->count++);
+ INLINEset_and(pf, mask1, p);
+ INLINEset_and(pr, mask, p);
+ save = FALSE;
+ for(i = first_part; i <= last_part; i++)
+ if (is_in_set(p, i))
+ save = TRUE, set_insert(pf, i+offset);
+ if (! save) PLA->F->count--;
+ for(i = first_part; i <= last_part; i++)
+ if (is_in_set(p, i))
+ set_insert(pr, i);
+ }
+
+ foreach_set(D, last, p) {
+ pf = GETSET(PLA->D, (PLA->D)->count++);
+ INLINEset_and(pf, mask, p);
+ for(i = first_part; i <= last_part; i++)
+ if (is_in_set(p, i)) {
+ set_insert(pf, i);
+ set_insert(pf, i+offset);
+ }
+ }
+
+ free_cover(F);
+ free_cover(D);
+ free_cover(R);
+ set_free(mask);
+ set_free(mask1);
+}
+
+/*
+ * set_phase -- given a "cube" which describes which phases of the output
+ * are to be implemented, compute the appropriate on-set and off-set
+ */
+pPLA set_phase(PLA)
+INOUT pPLA PLA;
+{
+ pcover F1, R1;
+ register pcube last, p, outmask;
+ register pcube temp=cube.temp[0], phase=PLA->phase, phase1=cube.temp[1];
+
+ outmask = cube.var_mask[cube.num_vars - 1];
+ set_diff(phase1, outmask, phase);
+ set_or(phase1, set_diff(temp, cube.fullset, outmask), phase1);
+ F1 = new_cover((PLA->F)->count + (PLA->R)->count);
+ R1 = new_cover((PLA->F)->count + (PLA->R)->count);
+
+ foreach_set(PLA->F, last, p) {
+ if (! setp_disjoint(set_and(temp, p, phase), outmask))
+ set_copy(GETSET(F1, F1->count++), temp);
+ if (! setp_disjoint(set_and(temp, p, phase1), outmask))
+ set_copy(GETSET(R1, R1->count++), temp);
+ }
+ foreach_set(PLA->R, last, p) {
+ if (! setp_disjoint(set_and(temp, p, phase), outmask))
+ set_copy(GETSET(R1, R1->count++), temp);
+ if (! setp_disjoint(set_and(temp, p, phase1), outmask))
+ set_copy(GETSET(F1, F1->count++), temp);
+ }
+ free_cover(PLA->F);
+ free_cover(PLA->R);
+ PLA->F = F1;
+ PLA->R = R1;
+ return PLA;
+}
+
+#define POW2(x) (1 << (x))
+
+void opoall(PLA, first_output, last_output, opo_strategy)
+pPLA PLA;
+int first_output, last_output;
+int opo_strategy;
+{
+ pcover F, D, R, best_F, best_D, best_R;
+ int i, j, ind, num;
+ pcube bestphase;
+
+ opo_exact = opo_strategy;
+
+ if (PLA->phase != NULL) {
+ set_free(PLA->phase);
+ }
+
+ bestphase = set_save(cube.fullset);
+ best_F = sf_save(PLA->F);
+ best_D = sf_save(PLA->D);
+ best_R = sf_save(PLA->R);
+
+ for(i = 0; i < POW2(last_output - first_output + 1); i++) {
+
+ /* save the initial PLA covers */
+ F = sf_save(PLA->F);
+ D = sf_save(PLA->D);
+ R = sf_save(PLA->R);
+
+ /* compute the phase cube for this iteration */
+ PLA->phase = set_save(cube.fullset);
+ num = i;
+ for(j = last_output; j >= first_output; j--) {
+ if (num % 2 == 0) {
+ ind = cube.first_part[cube.output] + j;
+ set_remove(PLA->phase, ind);
+ }
+ num /= 2;
+ }
+
+ /* set the phase and minimize */
+ (void) set_phase(PLA);
+ printf("# phase is %s\n", pc1(PLA->phase));
+ summary = TRUE;
+ minimize(PLA);
+
+ /* see if this is the best so far */
+ if (PLA->F->count < best_F->count) {
+ /* save new best solution */
+ set_copy(bestphase, PLA->phase);
+ sf_free(best_F);
+ sf_free(best_D);
+ sf_free(best_R);
+ best_F = PLA->F;
+ best_D = PLA->D;
+ best_R = PLA->R;
+ } else {
+ /* throw away the solution */
+ free_cover(PLA->F);
+ free_cover(PLA->D);
+ free_cover(PLA->R);
+ }
+ set_free(PLA->phase);
+
+ /* restore the initial PLA covers */
+ PLA->F = F;
+ PLA->D = D;
+ PLA->R = R;
+ }
+
+ /* one more minimization to restore the best answer */
+ PLA->phase = bestphase;
+ sf_free(PLA->F);
+ sf_free(PLA->D);
+ sf_free(PLA->R);
+ PLA->F = best_F;
+ PLA->D = best_D;
+ PLA->R = best_R;
+}
+
+static void minimize(PLA)
+pPLA PLA;
+{
+ if (opo_exact) {
+ EXEC_S(PLA->F = minimize_exact(PLA->F,PLA->D,PLA->R,1), "EXACT", PLA->F);
+ } else {
+ EXEC_S(PLA->F = espresso(PLA->F, PLA->D, PLA->R), "ESPRESSO ",PLA->F);
+ }
+}
diff --git a/src/misc/espresso/pair.c b/src/misc/espresso/pair.c
new file mode 100644
index 00000000..a8077176
--- /dev/null
+++ b/src/misc/espresso/pair.c
@@ -0,0 +1,675 @@
+/*
+ * Revision Control Information
+ *
+ * $Source$
+ * $Author$
+ * $Revision$
+ * $Date$
+ *
+ */
+#include "espresso.h"
+
+void set_pair(PLA)
+pPLA PLA;
+{
+ set_pair1(PLA, TRUE);
+}
+
+void set_pair1(PLA, adjust_labels)
+pPLA PLA;
+bool adjust_labels;
+{
+ int i, var, *paired, newvar;
+ int old_num_vars, old_num_binary_vars, old_size, old_mv_start;
+ int *new_part_size, new_num_vars, new_num_binary_vars, new_mv_start;
+ ppair pair = PLA->pair;
+ char scratch[1000], **oldlabel, *var1, *var1bar, *var2, *var2bar;
+
+ if (adjust_labels)
+ makeup_labels(PLA);
+
+ /* Check the pair structure for valid entries and see which binary
+ variables are left unpaired
+ */
+ paired = ALLOC(bool, cube.num_binary_vars);
+ for(var = 0; var < cube.num_binary_vars; var++)
+ paired[var] = FALSE;
+ for(i = 0; i < pair->cnt; i++)
+ if ((pair->var1[i] > 0 && pair->var1[i] <= cube.num_binary_vars) &&
+ (pair->var2[i] > 0 && pair->var2[i] <= cube.num_binary_vars)) {
+ paired[pair->var1[i]-1] = TRUE;
+ paired[pair->var2[i]-1] = TRUE;
+ } else
+ fatal("can only pair binary-valued variables");
+
+ PLA->F = delvar(pairvar(PLA->F, pair), paired);
+ PLA->R = delvar(pairvar(PLA->R, pair), paired);
+ PLA->D = delvar(pairvar(PLA->D, pair), paired);
+
+ /* Now painfully adjust the cube size */
+ old_size = cube.size;
+ old_num_vars = cube.num_vars;
+ old_num_binary_vars = cube.num_binary_vars;
+ old_mv_start = cube.first_part[cube.num_binary_vars];
+ /* Create the new cube.part_size vector and setup the cube structure */
+ new_num_binary_vars = 0;
+ for(var = 0; var < old_num_binary_vars; var++)
+ new_num_binary_vars += (paired[var] == FALSE);
+ new_num_vars = new_num_binary_vars + pair->cnt;
+ new_num_vars += old_num_vars - old_num_binary_vars;
+ new_part_size = ALLOC(int, new_num_vars);
+ for(var = 0; var < pair->cnt; var++)
+ new_part_size[new_num_binary_vars + var] = 4;
+ for(var = 0; var < old_num_vars - old_num_binary_vars; var++)
+ new_part_size[new_num_binary_vars + pair->cnt + var] =
+ cube.part_size[old_num_binary_vars + var];
+ setdown_cube();
+ FREE(cube.part_size);
+ cube.num_vars = new_num_vars;
+ cube.num_binary_vars = new_num_binary_vars;
+ cube.part_size = new_part_size;
+ cube_setup();
+
+ /* hack with the labels to get them correct */
+ if (adjust_labels) {
+ oldlabel = PLA->label;
+ PLA->label = ALLOC(char *, cube.size);
+ for(var = 0; var < pair->cnt; var++) {
+ newvar = cube.num_binary_vars*2 + var*4;
+ var1 = oldlabel[ (pair->var1[var]-1) * 2 + 1];
+ var2 = oldlabel[ (pair->var2[var]-1) * 2 + 1];
+ var1bar = oldlabel[ (pair->var1[var]-1) * 2];
+ var2bar = oldlabel[ (pair->var2[var]-1) * 2];
+ (void) sprintf(scratch, "%s+%s", var1bar, var2bar);
+ PLA->label[newvar] = util_strsav(scratch);
+ (void) sprintf(scratch, "%s+%s", var1bar, var2);
+ PLA->label[newvar+1] = util_strsav(scratch);
+ (void) sprintf(scratch, "%s+%s", var1, var2bar);
+ PLA->label[newvar+2] = util_strsav(scratch);
+ (void) sprintf(scratch, "%s+%s", var1, var2);
+ PLA->label[newvar+3] = util_strsav(scratch);
+ }
+ /* Copy the old labels for the unpaired binary vars */
+ i = 0;
+ for(var = 0; var < old_num_binary_vars; var++) {
+ if (paired[var] == FALSE) {
+ PLA->label[2*i] = oldlabel[2*var];
+ PLA->label[2*i+1] = oldlabel[2*var+1];
+ oldlabel[2*var] = oldlabel[2*var+1] = (char *) NULL;
+ i++;
+ }
+ }
+ /* Copy the old labels for the remaining unpaired vars */
+ new_mv_start = cube.num_binary_vars*2 + pair->cnt*4;
+ for(i = old_mv_start; i < old_size; i++) {
+ PLA->label[new_mv_start + i - old_mv_start] = oldlabel[i];
+ oldlabel[i] = (char *) NULL;
+ }
+ /* free remaining entries in oldlabel */
+ for(i = 0; i < old_size; i++)
+ if (oldlabel[i] != (char *) NULL)
+ FREE(oldlabel[i]);
+ FREE(oldlabel);
+ }
+
+ /* the paired variables should not be sparse (cf. mv_reduce/raise_in)*/
+ for(var = 0; var < pair->cnt; var++)
+ cube.sparse[cube.num_binary_vars + var] = 0;
+ FREE(paired);
+}
+
+pcover pairvar(A, pair)
+pcover A;
+ppair pair;
+{
+ register pcube last, p;
+ register int val, p1, p2, b1, b0;
+ int insert_col, pairnum;
+
+ insert_col = cube.first_part[cube.num_vars - 1];
+
+ /* stretch the cover matrix to make room for the paired variables */
+ A = sf_delcol(A, insert_col, -4*pair->cnt);
+
+ /* compute the paired values */
+ foreach_set(A, last, p) {
+ for(pairnum = 0; pairnum < pair->cnt; pairnum++) {
+ p1 = cube.first_part[pair->var1[pairnum] - 1];
+ p2 = cube.first_part[pair->var2[pairnum] - 1];
+ b1 = is_in_set(p, p2+1);
+ b0 = is_in_set(p, p2);
+ val = insert_col + pairnum * 4;
+ if (/* a0 */ is_in_set(p, p1)) {
+ if (b0)
+ set_insert(p, val + 3);
+ if (b1)
+ set_insert(p, val + 2);
+ }
+ if (/* a1 */ is_in_set(p, p1+1)) {
+ if (b0)
+ set_insert(p, val + 1);
+ if (b1)
+ set_insert(p, val);
+ }
+ }
+ }
+ return A;
+}
+
+
+/* delvar -- delete variables from A, minimize the number of column shifts */
+pcover delvar(A, paired)
+pcover A;
+bool paired[];
+{
+ bool run;
+ int first_run, run_length, var, offset = 0;
+
+ run = FALSE; run_length = 0;
+ for(var = 0; var < cube.num_binary_vars; var++)
+ if (paired[var])
+ if (run)
+ run_length += cube.part_size[var];
+ else {
+ run = TRUE;
+ first_run = cube.first_part[var];
+ run_length = cube.part_size[var];
+ }
+ else
+ if (run) {
+ A = sf_delcol(A, first_run-offset, run_length);
+ run = FALSE;
+ offset += run_length;
+ }
+ if (run)
+ A = sf_delcol(A, first_run-offset, run_length);
+ return A;
+}
+
+/*
+ find_optimal_pairing -- find which binary variables should be paired
+ to maximally reduce the number of terms
+
+ This is essentially the technique outlined by T. Sasao in the
+ Trans. on Comp., Oct 1984. We estimate the cost of pairing each
+ pair individually using 1 of 4 strategies: (1) algebraic division
+ of F by the pair (exactly T. Sasao technique); (2) strong division
+ of F by the paired variables (using REDUCE/EXPAND/ IRREDUNDANT from
+ espresso); (3) full minimization using espresso; (4) exact
+ minimization. These are in order of both increasing accuracy and
+ increasing difficulty (!)
+
+ Once the n squared pairs have been evaluated, T. Sasao proposes a
+ graph covering of nodes by disjoint edges. For now, I solve this
+ problem exhaustively (complexity = (n-1)*(n-3)*...*3*1 for n
+ variables when n is even). Note that solving this problem exactly
+ is the same as evaluating the cost function for all possible
+ pairings.
+
+ n pairs
+
+ 1, 2 1
+ 3, 4 3
+ 5, 6 15
+ 7, 8 105
+ 9,10 945
+ 11,12 10,395
+ 13,14 135,135
+ 15,16 2,027,025
+ 17,18 34,459,425
+ 19,20 654,729,075
+*/
+void find_optimal_pairing(PLA, strategy)
+pPLA PLA;
+int strategy;
+{
+ int i, j, **cost_array;
+
+ cost_array = find_pairing_cost(PLA, strategy);
+
+ if (summary) {
+ printf(" ");
+ for(i = 0; i < cube.num_binary_vars; i++)
+ printf("%3d ", i+1);
+ printf("\n");
+ for(i = 0; i < cube.num_binary_vars; i++) {
+ printf("%3d ", i+1);
+ for(j = 0; j < cube.num_binary_vars; j++)
+ printf("%3d ", cost_array[i][j]);
+ printf("\n");
+ }
+ }
+
+ if (cube.num_binary_vars <= 14) {
+ PLA->pair = pair_best_cost(cost_array);
+ } else {
+ (void) greedy_best_cost(cost_array, &(PLA->pair));
+ }
+ printf("# ");
+ print_pair(PLA->pair);
+
+ for(i = 0; i < cube.num_binary_vars; i++)
+ FREE(cost_array[i]);
+ FREE(cost_array);
+
+ set_pair(PLA);
+ EXEC_S(PLA->F=espresso(PLA->F,PLA->D,PLA->R),"ESPRESSO ",PLA->F);
+}
+
+int **find_pairing_cost(PLA, strategy)
+pPLA PLA;
+int strategy;
+{
+ int var1, var2, **cost_array;
+ int i, j, xnum_binary_vars, xnum_vars, *xpart_size, cost;
+ pcover T, Fsave, Dsave, Rsave;
+ pset mask;
+/* char *s;*/
+
+ /* data is returned in the cost array */
+ cost_array = ALLOC(int *, cube.num_binary_vars);
+ for(i = 0; i < cube.num_binary_vars; i++)
+ cost_array[i] = ALLOC(int, cube.num_binary_vars);
+ for(i = 0; i < cube.num_binary_vars; i++)
+ for(j = 0; j < cube.num_binary_vars; j++)
+ cost_array[i][j] = 0;
+
+ /* Setup the pair structure for pairing variables together */
+ PLA->pair = pair_new(1);
+ PLA->pair->cnt = 1;
+
+ for(var1 = 0; var1 < cube.num_binary_vars-1; var1++) {
+ for(var2 = var1+1; var2 < cube.num_binary_vars; var2++) {
+ /* if anything but simple strategy, perform setup */
+ if (strategy > 0) {
+ /* save the original covers */
+ Fsave = sf_save(PLA->F);
+ Dsave = sf_save(PLA->D);
+ Rsave = sf_save(PLA->R);
+
+ /* save the original cube structure */
+ xnum_binary_vars = cube.num_binary_vars;
+ xnum_vars = cube.num_vars;
+ xpart_size = ALLOC(int, cube.num_vars);
+ for(i = 0; i < cube.num_vars; i++)
+ xpart_size[i] = cube.part_size[i];
+
+ /* pair two variables together */
+ PLA->pair->var1[0] = var1 + 1;
+ PLA->pair->var2[0] = var2 + 1;
+ set_pair1(PLA, /* adjust_labels */ FALSE);
+ }
+
+
+ /* decide how to best estimate worth of this pairing */
+ switch(strategy) {
+ case 3:
+ /*s = "exact minimization";*/
+ PLA->F = minimize_exact(PLA->F, PLA->D, PLA->R, 1);
+ cost = Fsave->count - PLA->F->count;
+ break;
+ case 2:
+ /*s = "full minimization";*/
+ PLA->F = espresso(PLA->F, PLA->D, PLA->R);
+ cost = Fsave->count - PLA->F->count;
+ break;
+ case 1:
+ /*s = "strong division";*/
+ PLA->F = reduce(PLA->F, PLA->D);
+ PLA->F = expand(PLA->F, PLA->R, FALSE);
+ PLA->F = irredundant(PLA->F, PLA->D);
+ cost = Fsave->count - PLA->F->count;
+ break;
+ case 0:
+ /*s = "weak division";*/
+ mask = new_cube();
+ set_or(mask, cube.var_mask[var1], cube.var_mask[var2]);
+ T = dist_merge(sf_save(PLA->F), mask);
+ cost = PLA->F->count - T->count;
+ sf_free(T);
+ set_free(mask);
+ }
+
+ cost_array[var1][var2] = cost;
+
+ if (strategy > 0) {
+ /* restore the original cube structure -- free the new ones */
+ setdown_cube();
+ FREE(cube.part_size);
+ cube.num_binary_vars = xnum_binary_vars;
+ cube.num_vars = xnum_vars;
+ cube.part_size = xpart_size;
+ cube_setup();
+
+ /* restore the original cover(s) -- free the new ones */
+ sf_free(PLA->F);
+ sf_free(PLA->D);
+ sf_free(PLA->R);
+ PLA->F = Fsave;
+ PLA->D = Dsave;
+ PLA->R = Rsave;
+ }
+ }
+ }
+
+ pair_free(PLA->pair);
+ PLA->pair = NULL;
+ return cost_array;
+}
+
+static int best_cost;
+static int **cost_array;
+static ppair best_pair;
+static pset best_phase;
+static pPLA global_PLA;
+static pcover best_F, best_D, best_R;
+static int pair_minim_strategy;
+
+
+print_pair(pair)
+ppair pair;
+{
+ int i;
+
+ printf("pair is");
+ for(i = 0; i < pair->cnt; i++)
+ printf (" (%d %d)", pair->var1[i], pair->var2[i]);
+ printf("\n");
+}
+
+
+int greedy_best_cost(cost_array_local, pair_p)
+int **cost_array_local;
+ppair *pair_p;
+{
+ int i, j, besti, bestj, maxcost, total_cost;
+ pset cand;
+ ppair pair;
+
+ pair = pair_new(cube.num_binary_vars);
+ cand = set_full(cube.num_binary_vars);
+ total_cost = 0;
+
+ while (set_ord(cand) >= 2) {
+ maxcost = -1;
+ for(i = 0; i < cube.num_binary_vars; i++) {
+ if (is_in_set(cand, i)) {
+ for(j = i+1; j < cube.num_binary_vars; j++) {
+ if (is_in_set(cand, j)) {
+ if (cost_array_local[i][j] > maxcost) {
+ maxcost = cost_array_local[i][j];
+ besti = i;
+ bestj = j;
+ }
+ }
+ }
+ }
+ }
+ pair->var1[pair->cnt] = besti+1;
+ pair->var2[pair->cnt] = bestj+1;
+ pair->cnt++;
+ set_remove(cand, besti);
+ set_remove(cand, bestj);
+ total_cost += maxcost;
+ }
+ set_free(cand);
+ *pair_p = pair;
+ return total_cost;
+}
+
+
+ppair pair_best_cost(cost_array_local)
+int **cost_array_local;
+{
+ ppair pair;
+ pset candidate;
+
+ best_cost = -1;
+ best_pair = NULL;
+ cost_array = cost_array_local;
+
+ pair = pair_new(cube.num_binary_vars);
+ candidate = set_full(cube.num_binary_vars);
+ generate_all_pairs(pair, cube.num_binary_vars, candidate, find_best_cost);
+ pair_free(pair);
+ set_free(candidate);
+ return best_pair;
+}
+
+
+int find_best_cost(pair)
+register ppair pair;
+{
+ register int i, cost;
+
+ cost = 0;
+ for(i = 0; i < pair->cnt; i++)
+ cost += cost_array[pair->var1[i]-1][pair->var2[i]-1];
+ if (cost > best_cost) {
+ best_cost = cost;
+ best_pair = pair_save(pair, pair->cnt);
+ }
+ if ((debug & MINCOV) && trace) {
+ printf("cost is %d ", cost);
+ print_pair(pair);
+ }
+}
+
+/*
+ pair_all: brute-force approach to try all possible pairings
+
+ pair_strategy is:
+ 2) for espresso
+ 3) for minimize_exact
+ 4) for phase assignment
+*/
+
+pair_all(PLA, pair_strategy)
+pPLA PLA;
+int pair_strategy;
+{
+ ppair pair;
+ pset candidate;
+
+ global_PLA = PLA;
+ pair_minim_strategy = pair_strategy;
+ best_cost = PLA->F->count + 1;
+ best_pair = NULL;
+ best_phase = NULL;
+ best_F = best_D = best_R = NULL;
+ pair = pair_new(cube.num_binary_vars);
+ candidate = set_fill(set_new(cube.num_binary_vars), cube.num_binary_vars);
+
+ generate_all_pairs(pair, cube.num_binary_vars, candidate, minimize_pair);
+
+ pair_free(pair);
+ set_free(candidate);
+
+ PLA->pair = best_pair;
+ PLA->phase = best_phase;
+/* not really necessary
+ if (phase != NULL)
+ (void) set_phase(PLA->phase);
+*/
+ set_pair(PLA);
+ printf("# ");
+ print_pair(PLA->pair);
+
+ sf_free(PLA->F);
+ sf_free(PLA->D);
+ sf_free(PLA->R);
+ PLA->F = best_F;
+ PLA->D = best_D;
+ PLA->R = best_R;
+}
+
+
+/*
+ * minimize_pair -- called as each pair is generated
+ */
+int minimize_pair(pair)
+ppair pair;
+{
+ pcover Fsave, Dsave, Rsave;
+ int i, xnum_binary_vars, xnum_vars, *xpart_size;
+
+ /* save the original covers */
+ Fsave = sf_save(global_PLA->F);
+ Dsave = sf_save(global_PLA->D);
+ Rsave = sf_save(global_PLA->R);
+
+ /* save the original cube structure */
+ xnum_binary_vars = cube.num_binary_vars;
+ xnum_vars = cube.num_vars;
+ xpart_size = ALLOC(int, cube.num_vars);
+ for(i = 0; i < cube.num_vars; i++)
+ xpart_size[i] = cube.part_size[i];
+
+ /* setup the paired variables */
+ global_PLA->pair = pair;
+ set_pair1(global_PLA, /* adjust_labels */ FALSE);
+
+ /* call the minimizer */
+ if (summary)
+ print_pair(pair);
+ switch(pair_minim_strategy) {
+ case 2:
+ EXEC_S(phase_assignment(global_PLA,0), "OPO ", global_PLA->F);
+ if (summary)
+ printf("# phase is %s\n", pc1(global_PLA->phase));
+ break;
+ case 1:
+ EXEC_S(global_PLA->F = minimize_exact(global_PLA->F, global_PLA->D,
+ global_PLA->R, 1), "EXACT ", global_PLA->F);
+ break;
+ case 0:
+ EXEC_S(global_PLA->F = espresso(global_PLA->F, global_PLA->D,
+ global_PLA->R), "ESPRESSO ", global_PLA->F);
+ break;
+ default:
+ break;
+ }
+
+ /* see if we have a new best solution */
+ if (global_PLA->F->count < best_cost) {
+ best_cost = global_PLA->F->count;
+ best_pair = pair_save(pair, pair->cnt);
+ best_phase = global_PLA->phase!=NULL?set_save(global_PLA->phase):NULL;
+ if (best_F != NULL) sf_free(best_F);
+ if (best_D != NULL) sf_free(best_D);
+ if (best_R != NULL) sf_free(best_R);
+ best_F = sf_save(global_PLA->F);
+ best_D = sf_save(global_PLA->D);
+ best_R = sf_save(global_PLA->R);
+ }
+
+ /* restore the original cube structure -- free the new ones */
+ setdown_cube();
+ FREE(cube.part_size);
+ cube.num_binary_vars = xnum_binary_vars;
+ cube.num_vars = xnum_vars;
+ cube.part_size = xpart_size;
+ cube_setup();
+
+ /* restore the original cover(s) -- free the new ones */
+ sf_free(global_PLA->F);
+ sf_free(global_PLA->D);
+ sf_free(global_PLA->R);
+ global_PLA->F = Fsave;
+ global_PLA->D = Dsave;
+ global_PLA->R = Rsave;
+ global_PLA->pair = NULL;
+ global_PLA->phase = NULL;
+}
+
+generate_all_pairs(pair, n, candidate, action)
+ppair pair;
+int n;
+pset candidate;
+int (*action)();
+{
+ int i, j;
+ pset recur_candidate;
+ ppair recur_pair;
+
+ if (set_ord(candidate) < 2) {
+ (*action)(pair);
+ return;
+ }
+
+ recur_pair = pair_save(pair, n);
+ recur_candidate = set_save(candidate);
+
+ /* Find first variable still in the candidate set */
+ for(i = 0; i < n; i++)
+ if (is_in_set(candidate, i))
+ break;
+
+ /* Try all pairs of i with other variables */
+ for(j = i+1; j < n; j++)
+ if (is_in_set(candidate, j)) {
+ /* pair (i j) -- remove from candidate set for future pairings */
+ set_remove(recur_candidate, i);
+ set_remove(recur_candidate, j);
+
+ /* add to the pair array */
+ recur_pair->var1[recur_pair->cnt] = i+1;
+ recur_pair->var2[recur_pair->cnt] = j+1;
+ recur_pair->cnt++;
+
+ /* recur looking for the end ... */
+ generate_all_pairs(recur_pair, n, recur_candidate, action);
+
+ /* now break this pair, and restore candidate set */
+ recur_pair->cnt--;
+ set_insert(recur_candidate, i);
+ set_insert(recur_candidate, j);
+ }
+
+ /* if odd, generate all pairs which do NOT include i */
+ if ((set_ord(candidate) % 2) == 1) {
+ set_remove(recur_candidate, i);
+ generate_all_pairs(recur_pair, n, recur_candidate, action);
+ }
+
+ pair_free(recur_pair);
+ set_free(recur_candidate);
+}
+
+ppair pair_new(n)
+register int n;
+{
+ register ppair pair1;
+
+ pair1 = ALLOC(pair_t, 1);
+ pair1->cnt = 0;
+ pair1->var1 = ALLOC(int, n);
+ pair1->var2 = ALLOC(int, n);
+ return pair1;
+}
+
+
+ppair pair_save(pair, n)
+register ppair pair;
+register int n;
+{
+ register int k;
+ register ppair pair1;
+
+ pair1 = pair_new(n);
+ pair1->cnt = pair->cnt;
+ for(k = 0; k < pair->cnt; k++) {
+ pair1->var1[k] = pair->var1[k];
+ pair1->var2[k] = pair->var2[k];
+ }
+ return pair1;
+}
+
+
+int pair_free(pair)
+register ppair pair;
+{
+ FREE(pair->var1);
+ FREE(pair->var2);
+ FREE(pair);
+}
diff --git a/src/misc/espresso/part.c b/src/misc/espresso/part.c
new file mode 100644
index 00000000..42843aeb
--- /dev/null
+++ b/src/misc/espresso/part.c
@@ -0,0 +1,122 @@
+/*
+ * Revision Control Information
+ *
+ * $Source$
+ * $Author$
+ * $Revision$
+ * $Date$
+ *
+ */
+#include "mincov_int.h"
+
+static int visit_col();
+
+static void
+copy_row(A, prow)
+register sm_matrix *A;
+register sm_row *prow;
+{
+ register sm_element *p;
+
+ for(p = prow->first_col; p != 0; p = p->next_col) {
+ (void) sm_insert(A, p->row_num, p->col_num);
+ }
+}
+
+
+static int
+visit_row(A, prow, rows_visited, cols_visited)
+sm_matrix *A;
+sm_row *prow;
+int *rows_visited;
+int *cols_visited;
+{
+ sm_element *p;
+ sm_col *pcol;
+
+ if (! prow->flag) {
+ prow->flag = 1;
+ (*rows_visited)++;
+ if (*rows_visited == A->nrows) {
+ return 1;
+ }
+ for(p = prow->first_col; p != 0; p = p->next_col) {
+ pcol = sm_get_col(A, p->col_num);
+ if (! pcol->flag) {
+ if (visit_col(A, pcol, rows_visited, cols_visited)) {
+ return 1;
+ }
+ }
+ }
+ }
+ return 0;
+}
+
+
+static int
+visit_col(A, pcol, rows_visited, cols_visited)
+sm_matrix *A;
+sm_col *pcol;
+int *rows_visited;
+int *cols_visited;
+{
+ sm_element *p;
+ sm_row *prow;
+
+ if (! pcol->flag) {
+ pcol->flag = 1;
+ (*cols_visited)++;
+ if (*cols_visited == A->ncols) {
+ return 1;
+ }
+ for(p = pcol->first_row; p != 0; p = p->next_row) {
+ prow = sm_get_row(A, p->row_num);
+ if (! prow->flag) {
+ if (visit_row(A, prow, rows_visited, cols_visited)) {
+ return 1;
+ }
+ }
+ }
+ }
+ return 0;
+}
+
+int
+sm_block_partition(A, L, R)
+sm_matrix *A;
+sm_matrix **L, **R;
+{
+ int cols_visited, rows_visited;
+ register sm_row *prow;
+ register sm_col *pcol;
+
+ /* Avoid the trivial case */
+ if (A->nrows == 0) {
+ return 0;
+ }
+
+ /* Reset the visited flags for each row and column */
+ for(prow = A->first_row; prow != 0; prow = prow->next_row) {
+ prow->flag = 0;
+ }
+ for(pcol = A->first_col; pcol != 0; pcol = pcol->next_col) {
+ pcol->flag = 0;
+ }
+
+ cols_visited = rows_visited = 0;
+ if (visit_row(A, A->first_row, &rows_visited, &cols_visited)) {
+ /* we found all of the rows */
+ return 0;
+ } else {
+ *L = sm_alloc();
+ *R = sm_alloc();
+ for(prow = A->first_row; prow != 0; prow = prow->next_row) {
+ if (prow->flag) {
+ copy_row(*L, prow);
+ } else {
+ copy_row(*R, prow);
+ }
+ }
+ return 1;
+ }
+}
diff --git a/src/misc/espresso/primes.c b/src/misc/espresso/primes.c
new file mode 100644
index 00000000..3e40da27
--- /dev/null
+++ b/src/misc/espresso/primes.c
@@ -0,0 +1,170 @@
+/*
+ * Revision Control Information
+ *
+ * $Source$
+ * $Author$
+ * $Revision$
+ * $Date$
+ *
+ */
+#include "espresso.h"
+
+static bool primes_consensus_special_cases();
+static pcover primes_consensus_merge();
+static pcover and_with_cofactor();
+
+
+/* primes_consensus -- generate primes using consensus */
+pcover primes_consensus(T)
+pcube *T; /* T will be disposed of */
+{
+ register pcube cl, cr;
+ register int best;
+ pcover Tnew, Tl, Tr;
+
+ if (primes_consensus_special_cases(T, &Tnew) == MAYBE) {
+ cl = new_cube();
+ cr = new_cube();
+ best = binate_split_select(T, cl, cr, COMPL);
+
+ Tl = primes_consensus(scofactor(T, cl, best));
+ Tr = primes_consensus(scofactor(T, cr, best));
+ Tnew = primes_consensus_merge(Tl, Tr, cl, cr);
+
+ free_cube(cl);
+ free_cube(cr);
+ free_cubelist(T);
+ }
+
+ return Tnew;
+}
+
+static bool
+primes_consensus_special_cases(T, Tnew)
+pcube *T; /* will be disposed if answer is determined */
+pcover *Tnew; /* returned only if answer determined */
+{
+ register pcube *T1, p, ceil, cof=T[0];
+ pcube last;
+ pcover A;
+
+ /* Check for no cubes in the cover */
+ if (T[2] == NULL) {
+ *Tnew = new_cover(0);
+ free_cubelist(T);
+ return TRUE;
+ }
+
+ /* Check for only a single cube in the cover */
+ if (T[3] == NULL) {
+ *Tnew = sf_addset(new_cover(1), set_or(cof, cof, T[2]));
+ free_cubelist(T);
+ return TRUE;
+ }
+
+ /* Check for a row of all 1's (implies function is a tautology) */
+ for(T1 = T+2; (p = *T1++) != NULL; ) {
+ if (full_row(p, cof)) {
+ *Tnew = sf_addset(new_cover(1), cube.fullset);
+ free_cubelist(T);
+ return TRUE;
+ }
+ }
+
+ /* Check for a column of all 0's which can be factored out */
+ ceil = set_save(cof);
+ for(T1 = T+2; (p = *T1++) != NULL; ) {
+ INLINEset_or(ceil, ceil, p);
+ }
+ if (! setp_equal(ceil, cube.fullset)) {
+ p = new_cube();
+ (void) set_diff(p, cube.fullset, ceil);
+ (void) set_or(cof, cof, p);
+ free_cube(p);
+
+ A = primes_consensus(T);
+ foreach_set(A, last, p) {
+ INLINEset_and(p, p, ceil);
+ }
+ *Tnew = A;
+ set_free(ceil);
+ return TRUE;
+ }
+ set_free(ceil);
+
+ /* Collect column counts, determine unate variables, etc. */
+ massive_count(T);
+
+ /* If single active variable not factored out above, then tautology ! */
+ if (cdata.vars_active == 1) {
+ *Tnew = sf_addset(new_cover(1), cube.fullset);
+ free_cubelist(T);
+ return TRUE;
+
+ /* Check for unate cover */
+ } else if (cdata.vars_unate == cdata.vars_active) {
+ A = cubeunlist(T);
+ *Tnew = sf_contain(A);
+ free_cubelist(T);
+ return TRUE;
+
+ /* Not much we can do about it */
+ } else {
+ return MAYBE;
+ }
+}
+
+static pcover
+primes_consensus_merge(Tl, Tr, cl, cr)
+pcover Tl, Tr;
+pcube cl, cr;
+{
+ register pcube pl, pr, lastl, lastr, pt;
+ pcover T, Tsave;
+
+ Tl = and_with_cofactor(Tl, cl);
+ Tr = and_with_cofactor(Tr, cr);
+
+ T = sf_new(500, Tl->sf_size);
+ pt = T->data;
+ Tsave = sf_contain(sf_join(Tl, Tr));
+
+ foreach_set(Tl, lastl, pl) {
+ foreach_set(Tr, lastr, pr) {
+ if (cdist01(pl, pr) == 1) {
+ consensus(pt, pl, pr);
+ if (++T->count >= T->capacity) {
+ Tsave = sf_union(Tsave, sf_contain(T));
+ T = sf_new(500, Tl->sf_size);
+ pt = T->data;
+ } else {
+ pt += T->wsize;
+ }
+ }
+ }
+ }
+ free_cover(Tl);
+ free_cover(Tr);
+
+ Tsave = sf_union(Tsave, sf_contain(T));
+ return Tsave;
+}
+
+
+static pcover
+and_with_cofactor(A, cof)
+pset_family A;
+register pset cof;
+{
+ register pset last, p;
+
+ foreach_set(A, last, p) {
+ INLINEset_and(p, p, cof);
+ if (cdist(p, cube.fullset) > 0) {
+ RESET(p, ACTIVE);
+ } else {
+ SET(p, ACTIVE);
+ }
+ }
+ return sf_inactive(A);
+}
diff --git a/src/misc/espresso/reduce.c b/src/misc/espresso/reduce.c
new file mode 100644
index 00000000..00e4507f
--- /dev/null
+++ b/src/misc/espresso/reduce.c
@@ -0,0 +1,258 @@
+/*
+ * Revision Control Information
+ *
+ * $Source$
+ * $Author$
+ * $Revision$
+ * $Date$
+ *
+ */
+/*
+ module: reduce.c
+ purpose: Perform the Espresso-II reduction step
+
+ Reduction is a technique used to explore larger regions of the
+ optimization space. We replace each cube of F with a smaller
+ cube while still maintaining a cover of the same logic function.
+*/
+
+#include "espresso.h"
+
+static bool toggle = TRUE;
+
+
+/*
+ reduce -- replace each cube in F with its reduction
+
+ The reduction of a cube is the smallest cube contained in the cube
+ which can replace the cube in the original cover without changing
+ the cover. This is equivalent to the super cube of all of the
+ essential points in the cube. This can be computed directly.
+
+ The problem is that the order in which the cubes are reduced can
+ greatly affect the final result. We alternate between two ordering
+ strategies:
+
+ (1) Order the cubes in ascending order of distance from the
+ largest cube breaking ties by ordering cubes of equal distance
+ in descending order of size (sort_reduce)
+
+ (2) Order the cubes in descending order of the inner-product of
+ the cube and the column sums (mini_sort)
+
+ The real workhorse of this section is the routine SCCC which is
+ used to find the Smallest Cube Containing the Complement of a cover.
+ Reduction as proposed by Espresso-II takes a cube and computes its
+ maximal reduction as the intersection between the cube and the
+ smallest cube containing the complement of (F u D - {c}) cofactored
+ against c.
+
+ As usual, the unate-recursive paradigm is used to compute SCCC.
+ The SCCC of a unate cover is trivial to compute, and thus we perform
+ Shannon Cofactor expansion attempting to drive the cover to be unate
+ as fast as possible.
+*/
+
+pcover reduce(F, D)
+INOUT pcover F;
+IN pcover D;
+{
+ register pcube last, p, cunder, *FD;
+
+ /* Order the cubes */
+ if (use_random_order)
+ F = random_order(F);
+ else {
+ F = toggle ? sort_reduce(F) : mini_sort(F, descend);
+ toggle = ! toggle;
+ }
+
+ /* Try to reduce each cube */
+ FD = cube2list(F, D);
+ foreach_set(F, last, p) {
+ cunder = reduce_cube(FD, p); /* reduce the cube */
+ if (setp_equal(cunder, p)) { /* see if it actually did */
+ SET(p, ACTIVE); /* cube remains active */
+ SET(p, PRIME); /* cube remains prime ? */
+ } else {
+ if (debug & REDUCE) {
+ printf("REDUCE: %s to %s %s\n",
+ pc1(p), pc2(cunder), print_time(ptime()));
+ }
+ set_copy(p, cunder); /* save reduced version */
+ RESET(p, PRIME); /* cube is no longer prime */
+ if (setp_empty(cunder))
+ RESET(p, ACTIVE); /* if null, kill the cube */
+ else
+ SET(p, ACTIVE); /* cube is active */
+ }
+ free_cube(cunder);
+ }
+ free_cubelist(FD);
+
+ /* Delete any cubes of F which reduced to the empty cube */
+ return sf_inactive(F);
+}
+
+/* reduce_cube -- find the maximal reduction of a cube */
+pcube reduce_cube(FD, p)
+IN pcube *FD, p;
+{
+ pcube cunder;
+
+ cunder = sccc(cofactor(FD, p));
+ return set_and(cunder, cunder, p);
+}
+
+
+/* sccc -- find Smallest Cube Containing the Complement of a cover */
+pcube sccc(T)
+INOUT pcube *T; /* T will be disposed of */
+{
+ pcube r;
+ register pcube cl, cr;
+ register int best;
+ static int sccc_level = 0;
+
+ if (debug & REDUCE1) {
+ debug_print(T, "SCCC", sccc_level++);
+ }
+
+ if (sccc_special_cases(T, &r) == MAYBE) {
+ cl = new_cube();
+ cr = new_cube();
+ best = binate_split_select(T, cl, cr, REDUCE1);
+ r = sccc_merge(sccc(scofactor(T, cl, best)),
+ sccc(scofactor(T, cr, best)), cl, cr);
+ free_cubelist(T);
+ }
+
+ if (debug & REDUCE1)
+ printf("SCCC[%d]: result is %s\n", --sccc_level, pc1(r));
+ return r;
+}
+
+
+pcube sccc_merge(left, right, cl, cr)
+INOUT register pcube left, right; /* will be disposed of ... */
+INOUT register pcube cl, cr; /* will be disposed of ... */
+{
+ INLINEset_and(left, left, cl);
+ INLINEset_and(right, right, cr);
+ INLINEset_or(left, left, right);
+ free_cube(right);
+ free_cube(cl);
+ free_cube(cr);
+ return left;
+}
+
+
+/*
+ sccc_cube -- find the smallest cube containing the complement of a cube
+
+ By DeMorgan's law and the fact that the smallest cube containing a
+ cover is the "or" of the positional cubes, it is simple to see that
+ the SCCC is the universe if the cube has more than two active
+ variables. If there is only a single active variable, then the
+ SCCC is merely the bitwise complement of the cube in that
+ variable. A last special case is no active variables, in which
+ case the SCCC is empty.
+
+ This is "anded" with the incoming cube result.
+*/
+pcube sccc_cube(result, p)
+register pcube result, p;
+{
+ register pcube temp=cube.temp[0], mask;
+ int var;
+
+ if ((var = cactive(p)) >= 0) {
+ mask = cube.var_mask[var];
+ INLINEset_xor(temp, p, mask);
+ INLINEset_and(result, result, temp);
+ }
+ return result;
+}
+
+/*
+ * sccc_special_cases -- check the special cases for sccc
+ */
+
+bool sccc_special_cases(T, result)
+INOUT pcube *T; /* will be disposed if answer is determined */
+OUT pcube *result; /* returned only if answer determined */
+{
+ register pcube *T1, p, temp = cube.temp[1], ceil, cof = T[0];
+ pcube *A, *B;
+
+ /* empty cover => complement is universe => SCCC is universe */
+ if (T[2] == NULL) {
+ *result = set_save(cube.fullset);
+ free_cubelist(T);
+ return TRUE;
+ }
+
+ /* row of 1's => complement is empty => SCCC is empty */
+ for(T1 = T+2; (p = *T1++) != NULL; ) {
+ if (full_row(p, cof)) {
+ *result = new_cube();
+ free_cubelist(T);
+ return TRUE;
+ }
+ }
+
+ /* Collect column counts, determine unate variables, etc. */
+ massive_count(T);
+
+ /* If cover is unate (or single cube), apply simple rules to find SCCCU */
+ if (cdata.vars_unate == cdata.vars_active || T[3] == NULL) {
+ *result = set_save(cube.fullset);
+ for(T1 = T+2; (p = *T1++) != NULL; ) {
+ (void) sccc_cube(*result, set_or(temp, p, cof));
+ }
+ free_cubelist(T);
+ return TRUE;
+ }
+
+ /* Check for column of 0's (which can be easily factored( */
+ ceil = set_save(cof);
+ for(T1 = T+2; (p = *T1++) != NULL; ) {
+ INLINEset_or(ceil, ceil, p);
+ }
+ if (! setp_equal(ceil, cube.fullset)) {
+ *result = sccc_cube(set_save(cube.fullset), ceil);
+ if (setp_equal(*result, cube.fullset)) {
+ free_cube(ceil);
+ } else {
+ *result = sccc_merge(sccc(cofactor(T,ceil)),
+ set_save(cube.fullset), ceil, *result);
+ }
+ free_cubelist(T);
+ return TRUE;
+ }
+ free_cube(ceil);
+
+ /* Single active column at this point => tautology => SCCC is empty */
+ if (cdata.vars_active == 1) {
+ *result = new_cube();
+ free_cubelist(T);
+ return TRUE;
+ }
+
+ /* Check for components */
+ if (cdata.var_zeros[cdata.best] < CUBELISTSIZE(T)/2) {
+ if (cubelist_partition(T, &A, &B, debug & REDUCE1) == 0) {
+ return MAYBE;
+ } else {
+ free_cubelist(T);
+ *result = sccc(A);
+ ceil = sccc(B);
+ (void) set_and(*result, *result, ceil);
+ set_free(ceil);
+ return TRUE;
+ }
+ }
+
+ /* Not much we can do about it */
+ return MAYBE;
+}
diff --git a/src/misc/espresso/rows.c b/src/misc/espresso/rows.c
new file mode 100644
index 00000000..bf0c0baa
--- /dev/null
+++ b/src/misc/espresso/rows.c
@@ -0,0 +1,314 @@
+/*
+ * Revision Control Information
+ *
+ * $Source$
+ * $Author$
+ * $Revision$
+ * $Date$
+ *
+ */
+//#include "port.h"
+#include "sparse_int.h"
+
+
+/*
+ * allocate a new row vector
+ */
+sm_row *
+sm_row_alloc()
+{
+ register sm_row *prow;
+
+#ifdef FAST_AND_LOOSE
+ if (sm_row_freelist == NIL(sm_row)) {
+ prow = ALLOC(sm_row, 1);
+ } else {
+ prow = sm_row_freelist;
+ sm_row_freelist = prow->next_row;
+ }
+#else
+ prow = ALLOC(sm_row, 1);
+#endif
+
+ prow->row_num = 0;
+ prow->length = 0;
+ prow->first_col = prow->last_col = NIL(sm_element);
+ prow->next_row = prow->prev_row = NIL(sm_row);
+ prow->flag = 0;
+ prow->user_word = NIL(char); /* for our user ... */
+ return prow;
+}
+
+
+/*
+ * free a row vector -- for FAST_AND_LOOSE, this is real cheap for rows;
+ * however, freeing a column must still walk down the column discarding
+ * the elements one-by-one; that is the only use for the extra '-DCOLS'
+ * compile flag ...
+ */
+void
+sm_row_free(prow)
+register sm_row *prow;
+{
+#if defined(FAST_AND_LOOSE) && ! defined(COLS)
+ if (prow->first_col != NIL(sm_element)) {
+ /* Add the linked list of row items to the free list */
+ prow->last_col->next_col = sm_element_freelist;
+ sm_element_freelist = prow->first_col;
+ }
+
+ /* Add the row to the free list of rows */
+ prow->next_row = sm_row_freelist;
+ sm_row_freelist = prow;
+#else
+ register sm_element *p, *pnext;
+
+ for(p = prow->first_col; p != 0; p = pnext) {
+ pnext = p->next_col;
+ sm_element_free(p);
+ }
+ FREE(prow);
+#endif
+}
+
+
+/*
+ * duplicate an existing row
+ */
+sm_row *
+sm_row_dup(prow)
+register sm_row *prow;
+{
+ register sm_row *pnew;
+ register sm_element *p;
+
+ pnew = sm_row_alloc();
+ for(p = prow->first_col; p != 0; p = p->next_col) {
+ (void) sm_row_insert(pnew, p->col_num);
+ }
+ return pnew;
+}
+
+
+/*
+ * insert an element into a row vector
+ */
+sm_element *
+sm_row_insert(prow, col)
+register sm_row *prow;
+register int col;
+{
+ register sm_element *test, *element;
+
+ /* get a new item, save its address */
+ sm_element_alloc(element);
+ test = element;
+ sorted_insert(sm_element, prow->first_col, prow->last_col, prow->length,
+ next_col, prev_col, col_num, col, test);
+
+ /* if item was not used, free it */
+ if (element != test) {
+ sm_element_free(element);
+ }
+
+ /* either way, return the current new value */
+ return test;
+}
+
+
+/*
+ * remove an element from a row vector
+ */
+void
+sm_row_remove(prow, col)
+register sm_row *prow;
+register int col;
+{
+ register sm_element *p;
+
+ for(p = prow->first_col; p != 0 && p->col_num < col; p = p->next_col)
+ ;
+ if (p != 0 && p->col_num == col) {
+ dll_unlink(p, prow->first_col, prow->last_col,
+ next_col, prev_col, prow->length);
+ sm_element_free(p);
+ }
+}
+
+
+/*
+ * find an element (if it is in the row vector)
+ */
+sm_element *
+sm_row_find(prow, col)
+sm_row *prow;
+int col;
+{
+ register sm_element *p;
+
+ for(p = prow->first_col; p != 0 && p->col_num < col; p = p->next_col)
+ ;
+ if (p != 0 && p->col_num == col) {
+ return p;
+ } else {
+ return NIL(sm_element);
+ }
+}
+
+/*
+ * return 1 if row p2 contains row p1; 0 otherwise
+ */
+int
+sm_row_contains(p1, p2)
+sm_row *p1, *p2;
+{
+ register sm_element *q1, *q2;
+
+ q1 = p1->first_col;
+ q2 = p2->first_col;
+ while (q1 != 0) {
+ if (q2 == 0 || q1->col_num < q2->col_num) {
+ return 0;
+ } else if (q1->col_num == q2->col_num) {
+ q1 = q1->next_col;
+ q2 = q2->next_col;
+ } else {
+ q2 = q2->next_col;
+ }
+ }
+ return 1;
+}
+
+
+/*
+ * return 1 if row p1 and row p2 share an element in common
+ */
+int
+sm_row_intersects(p1, p2)
+sm_row *p1, *p2;
+{
+ register sm_element *q1, *q2;
+
+ q1 = p1->first_col;
+ q2 = p2->first_col;
+ if (q1 == 0 || q2 == 0) return 0;
+ for(;;) {
+ if (q1->col_num < q2->col_num) {
+ if ((q1 = q1->next_col) == 0) {
+ return 0;
+ }
+ } else if (q1->col_num > q2->col_num) {
+ if ((q2 = q2->next_col) == 0) {
+ return 0;
+ }
+ } else {
+ return 1;
+ }
+ }
+}
+
+
+/*
+ * compare two rows, lexical ordering
+ */
+int
+sm_row_compare(p1, p2)
+sm_row *p1, *p2;
+{
+ register sm_element *q1, *q2;
+
+ q1 = p1->first_col;
+ q2 = p2->first_col;
+ while(q1 != 0 && q2 != 0) {
+ if (q1->col_num != q2->col_num) {
+ return q1->col_num - q2->col_num;
+ }
+ q1 = q1->next_col;
+ q2 = q2->next_col;
+ }
+
+ if (q1 != 0) {
+ return 1;
+ } else if (q2 != 0) {
+ return -1;
+ } else {
+ return 0;
+ }
+}
+
+
+/*
+ * return the intersection
+ */
+sm_row *
+sm_row_and(p1, p2)
+sm_row *p1, *p2;
+{
+ register sm_element *q1, *q2;
+ register sm_row *result;
+
+ result = sm_row_alloc();
+ q1 = p1->first_col;
+ q2 = p2->first_col;
+ if (q1 == 0 || q2 == 0) return result;
+ for(;;) {
+ if (q1->col_num < q2->col_num) {
+ if ((q1 = q1->next_col) == 0) {
+ return result;
+ }
+ } else if (q1->col_num > q2->col_num) {
+ if ((q2 = q2->next_col) == 0) {
+ return result;
+ }
+ } else {
+ (void) sm_row_insert(result, q1->col_num);
+ if ((q1 = q1->next_col) == 0) {
+ return result;
+ }
+ if ((q2 = q2->next_col) == 0) {
+ return result;
+ }
+ }
+ }
+}
+
+int
+sm_row_hash(prow, modulus)
+sm_row *prow;
+int modulus;
+{
+ register int sum;
+ register sm_element *p;
+
+ sum = 0;
+ for(p = prow->first_col; p != 0; p = p->next_col) {
+ sum = (sum*17 + p->col_num) % modulus;
+ }
+ return sum;
+}
+
+/*
+ * remove an element from a row vector (given a pointer to the element)
+ */
+void
+sm_row_remove_element(prow, p)
+register sm_row *prow;
+register sm_element *p;
+{
+ dll_unlink(p, prow->first_col, prow->last_col,
+ next_col, prev_col, prow->length);
+ sm_element_free(p);
+}
+
+
+void
+sm_row_print(fp, prow)
+FILE *fp;
+sm_row *prow;
+{
+ sm_element *p;
+
+ for(p = prow->first_col; p != 0; p = p->next_col) {
+ (void) fprintf(fp, " %d", p->col_num);
+ }
+}
diff --git a/src/misc/espresso/set.c b/src/misc/espresso/set.c
new file mode 100644
index 00000000..fce88288
--- /dev/null
+++ b/src/misc/espresso/set.c
@@ -0,0 +1,820 @@
+/*
+ * Revision Control Information
+ *
+ * $Source$
+ * $Author$
+ * $Revision$
+ * $Date$
+ *
+ */
+/*
+ * set.c -- routines for maniuplating sets and set families
+ */
+
+/* LINTLIBRARY */
+
+#include "espresso.h"
+static pset_family set_family_garbage = NULL;
+
+static int intcpy(d, s, n)
+register unsigned int *d, *s;
+register long n;
+{
+ register int i;
+ for(i = 0; i < n; i++) {
+ *d++ = *s++;
+ }
+}
+
+
+/* bit_index -- find first bit (from LSB) in a word (MSB=bit n, LSB=bit 0) */
+int bit_index(a)
+register unsigned int a;
+{
+ register int i;
+ if (a == 0)
+ return -1;
+ for(i = 0; (a & 1) == 0; a >>= 1, i++)
+ ;
+ return i;
+}
+
+
+/* set_ord -- count number of elements in a set */
+int set_ord(a)
+register pset a;
+{
+ register int i, sum = 0;
+ register unsigned int val;
+ for(i = LOOP(a); i > 0; i--)
+ if ((val = a[i]) != 0)
+ sum += count_ones(val);
+ return sum;
+}
+
+/* set_dist -- distance between two sets (# elements in common) */
+int set_dist(a, b)
+register pset a, b;
+{
+ register int i, sum = 0;
+ register unsigned int val;
+ for(i = LOOP(a); i > 0; i--)
+ if ((val = a[i] & b[i]) != 0)
+ sum += count_ones(val);
+ return sum;
+}
+
+/* set_clear -- make "r" the empty set of "size" elements */
+pset set_clear(r, size)
+register pset r;
+int size;
+{
+ register int i = LOOPINIT(size);
+ *r = i; do r[i] = 0; while (--i > 0);
+ return r;
+}
+
+/* set_fill -- make "r" the universal set of "size" elements */
+pset set_fill(r, size)
+register pset r;
+register int size;
+{
+ register int i = LOOPINIT(size);
+ *r = i;
+ r[i] = ~ (unsigned) 0;
+ r[i] >>= i * BPI - size;
+ while (--i > 0)
+ r[i] = ~ (unsigned) 0;
+ return r;
+}
+
+/* set_copy -- copy set a into set r */
+pset set_copy(r, a)
+register pset r, a;
+{
+ register int i = LOOPCOPY(a);
+ do r[i] = a[i]; while (--i >= 0);
+ return r;
+}
+
+/* set_and -- compute intersection of sets "a" and "b" */
+pset set_and(r, a, b)
+register pset r, a, b;
+{
+ register int i = LOOP(a);
+ PUTLOOP(r,i); do r[i] = a[i] & b[i]; while (--i > 0);
+ return r;
+}
+
+/* set_or -- compute union of sets "a" and "b" */
+pset set_or(r, a, b)
+register pset r, a, b;
+{
+ register int i = LOOP(a);
+ PUTLOOP(r,i); do r[i] = a[i] | b[i]; while (--i > 0);
+ return r;
+}
+
+/* set_diff -- compute difference of sets "a" and "b" */
+pset set_diff(r, a, b)
+register pset r, a, b;
+{
+ register int i = LOOP(a);
+ PUTLOOP(r,i); do r[i] = a[i] & ~b[i]; while (--i > 0);
+ return r;
+}
+
+/* set_xor -- compute exclusive-or of sets "a" and "b" */
+pset set_xor(r, a, b)
+register pset r, a, b;
+{
+ register int i = LOOP(a);
+#ifdef IBM_WATC
+ PUTLOOP(r,i); do r[i] = (a[i]&~b[i]) | (~a[i]&b[i]); while (--i > 0);
+#else
+ PUTLOOP(r,i); do r[i] = a[i] ^ b[i]; while (--i > 0);
+#endif
+ return r;
+}
+
+/* set_merge -- compute "a" & "mask" | "b" & ~ "mask" */
+pset set_merge(r, a, b, mask)
+register pset r, a, b, mask;
+{
+ register int i = LOOP(a);
+ PUTLOOP(r,i); do r[i] = (a[i]&mask[i]) | (b[i]&~mask[i]); while (--i > 0);
+ return r;
+}
+
+/* set_andp -- compute intersection of sets "a" and "b" , TRUE if nonempty */
+bool set_andp(r, a, b)
+register pset r, a, b;
+{
+ register int i = LOOP(a);
+ register unsigned int x = 0;
+ PUTLOOP(r,i); do {r[i] = a[i] & b[i]; x |= r[i];} while (--i > 0);
+ return x != 0;
+}
+
+/* set_orp -- compute union of sets "a" and "b" , TRUE if nonempty */
+bool set_orp(r, a, b)
+register pset r, a, b;
+{
+ register int i = LOOP(a);
+ register unsigned int x = 0;
+ PUTLOOP(r,i); do {r[i] = a[i] | b[i]; x |= r[i];} while (--i > 0);
+ return x != 0;
+}
+
+/* setp_empty -- check if the set "a" is empty */
+bool setp_empty(a)
+register pset a;
+{
+ register int i = LOOP(a);
+ do if (a[i]) return FALSE; while (--i > 0);
+ return TRUE;
+}
+
+/* setp_full -- check if the set "a" is the full set of "size" elements */
+bool setp_full(a, size)
+register pset a;
+register int size;
+{
+ register int i = LOOP(a);
+ register unsigned int test;
+ test = ~ (unsigned) 0;
+ test >>= i * BPI - size;
+ if (a[i] != test)
+ return FALSE;
+ while (--i > 0)
+ if (a[i] != (~(unsigned) 0))
+ return FALSE;
+ return TRUE;
+}
+
+/* setp_equal -- check if the set "a" equals set "b" */
+bool setp_equal(a, b)
+register pset a, b;
+{
+ register int i = LOOP(a);
+ do if (a[i] != b[i]) return FALSE; while (--i > 0);
+ return TRUE;
+}
+
+/* setp_disjoint -- check if intersection of "a" and "b" is empty */
+bool setp_disjoint(a, b)
+register pset a, b;
+{
+ register int i = LOOP(a);
+ do if (a[i] & b[i]) return FALSE; while (--i > 0);
+ return TRUE;
+}
+
+/* setp_implies -- check if "a" implies "b" ("b" contains "a") */
+bool setp_implies(a, b)
+register pset a, b;
+{
+ register int i = LOOP(a);
+ do if (a[i] & ~b[i]) return FALSE; while (--i > 0);
+ return TRUE;
+}
+
+/* sf_or -- form the "or" of all sets in a set family */
+pset sf_or(A)
+pset_family A;
+{
+ register pset or, last, p;
+
+ or = set_new(A->sf_size);
+ foreach_set(A, last, p)
+ INLINEset_or(or, or, p);
+ return or;
+}
+
+/* sf_and -- form the "and" of all sets in a set family */
+pset sf_and(A)
+pset_family A;
+{
+ register pset and, last, p;
+
+ and = set_fill(set_new(A->sf_size), A->sf_size);
+ foreach_set(A, last, p)
+ INLINEset_and(and, and, p);
+ return and;
+}
+
+/* sf_active -- make all members of the set family active */
+pset_family sf_active(A)
+pset_family A;
+{
+ register pset p, last;
+ foreach_set(A, last, p) {
+ SET(p, ACTIVE);
+ }
+ A->active_count = A->count;
+ return A;
+}
+
+
+/* sf_inactive -- remove all inactive cubes in a set family */
+pset_family sf_inactive(A)
+pset_family A;
+{
+ register pset p, last, pdest;
+
+ pdest = A->data;
+ foreach_set(A, last, p) {
+ if (TESTP(p, ACTIVE)) {
+ if (pdest != p) {
+ INLINEset_copy(pdest, p);
+ }
+ pdest += A->wsize;
+ } else {
+ A->count--;
+ }
+ }
+ return A;
+}
+
+
+/* sf_copy -- copy a set family */
+pset_family sf_copy(R, A)
+pset_family R, A;
+{
+ R->sf_size = A->sf_size;
+ R->wsize = A->wsize;
+/*R->capacity = A->count;*/
+/*R->data = REALLOC(unsigned int, R->data, (long) R->capacity * R->wsize);*/
+ R->count = A->count;
+ R->active_count = A->active_count;
+ intcpy(R->data, A->data, (long) A->wsize * A->count);
+ return R;
+}
+
+
+/* sf_join -- join A and B into a single set_family */
+pset_family sf_join(A, B)
+pset_family A, B;
+{
+ pset_family R;
+ long asize = A->count * A->wsize;
+ long bsize = B->count * B->wsize;
+
+ if (A->sf_size != B->sf_size) fatal("sf_join: sf_size mismatch");
+ R = sf_new(A->count + B->count, A->sf_size);
+ R->count = A->count + B->count;
+ R->active_count = A->active_count + B->active_count;
+ intcpy(R->data, A->data, asize);
+ intcpy(R->data + asize, B->data, bsize);
+ return R;
+}
+
+
+/* sf_append -- append the sets of B to the end of A, and dispose of B */
+pset_family sf_append(A, B)
+pset_family A, B;
+{
+ long asize = A->count * A->wsize;
+ long bsize = B->count * B->wsize;
+
+ if (A->sf_size != B->sf_size) fatal("sf_append: sf_size mismatch");
+ A->capacity = A->count + B->count;
+ A->data = REALLOC(unsigned int, A->data, (long) A->capacity * A->wsize);
+ intcpy(A->data + asize, B->data, bsize);
+ A->count += B->count;
+ A->active_count += B->active_count;
+ sf_free(B);
+ return A;
+}
+
+
+/* sf_new -- allocate "num" sets of "size" elements each */
+pset_family sf_new(num, size)
+int num, size;
+{
+ pset_family A;
+ if (set_family_garbage == NULL) {
+ A = ALLOC(set_family_t, 1);
+ } else {
+ A = set_family_garbage;
+ set_family_garbage = A->next;
+ }
+ A->sf_size = size;
+ A->wsize = SET_SIZE(size);
+ A->capacity = num;
+ A->data = ALLOC(unsigned int, (long) A->capacity * A->wsize);
+ A->count = 0;
+ A->active_count = 0;
+ return A;
+}
+
+
+/* sf_save -- create a duplicate copy of a set family */
+pset_family sf_save(A)
+register pset_family A;
+{
+ return sf_copy(sf_new(A->count, A->sf_size), A);
+}
+
+
+/* sf_free -- free the storage allocated for a set family */
+void sf_free(A)
+pset_family A;
+{
+ FREE(A->data);
+ A->next = set_family_garbage;
+ set_family_garbage = A;
+}
+
+
+/* sf_cleanup -- free all of the set families from the garbage list */
+void sf_cleanup()
+{
+ register pset_family p, pnext;
+ for(p = set_family_garbage; p != (pset_family) NULL; p = pnext) {
+ pnext = p->next;
+ FREE(p);
+ }
+ set_family_garbage = (pset_family) NULL;
+}
+
+
+/* sf_addset -- add a set to the end of a set family */
+pset_family sf_addset(A, s)
+pset_family A;
+pset s;
+{
+ register pset p;
+
+ if (A->count >= A->capacity) {
+ A->capacity = A->capacity + A->capacity/2 + 1;
+ A->data = REALLOC(unsigned int, A->data, (long) A->capacity * A->wsize);
+ }
+ p = GETSET(A, A->count++);
+ INLINEset_copy(p, s);
+ return A;
+}
+
+/* sf_delset -- delete a set from a set family */
+void sf_delset(A, i)
+pset_family A;
+int i;
+{ (void) set_copy(GETSET(A,i), GETSET(A, --A->count));}
+
+/* sf_print -- print a set_family as a set (list the element numbers) */
+void sf_print(A)
+pset_family A;
+{
+ char *ps1();
+ register pset p;
+ register int i;
+ foreachi_set(A, i, p)
+ printf("A[%d] = %s\n", i, ps1(p));
+}
+
+/* sf_bm_print -- print a set_family as a bit-matrix */
+void sf_bm_print(A)
+pset_family A;
+{
+ char *pbv1();
+ register pset p;
+ register int i;
+ foreachi_set(A, i, p)
+ printf("[%4d] %s\n", i, pbv1(p, A->sf_size));
+}
+
+
+/* sf_write -- output a set family in an unintelligable manner */
+void sf_write(fp, A)
+FILE *fp;
+pset_family A;
+{
+ register pset p, last;
+ (void) fprintf(fp, "%d %d\n", A->count, A->sf_size);
+ foreach_set(A, last, p)
+ set_write(fp, p);
+ (void) fflush(fp);
+}
+
+
+/* sf_read -- read a set family written by sf_write */
+pset_family sf_read(fp)
+FILE *fp;
+{
+ int i, j;
+ register pset p, last;
+ pset_family A;
+
+ (void) fscanf(fp, "%d %d\n", &i, &j);
+ A = sf_new(i, j);
+ A->count = i;
+ foreach_set(A, last, p) {
+ (void) fscanf(fp, "%x", p);
+ for(j = 1; j <= LOOP(p); j++)
+ (void) fscanf(fp, "%x", p+j);
+ }
+ return A;
+}
+
+
+/* set_write -- output a set in an unintelligable manner */
+void set_write(fp, a)
+register FILE *fp;
+register pset a;
+{
+ register int n = LOOP(a), j;
+
+ for(j = 0; j <= n; j++) {
+ (void) fprintf(fp, "%x ", a[j]);
+ if ((j+1) % 8 == 0 && j != n)
+ (void) fprintf(fp, "\n\t");
+ }
+ (void) fprintf(fp, "\n");
+}
+
+
+/* sf_bm_read -- read a set family written by sf_bm_print (almost) */
+pset_family sf_bm_read(fp)
+FILE *fp;
+{
+ int i, j, rows, cols;
+ register pset pdest;
+ pset_family A;
+
+ (void) fscanf(fp, "%d %d\n", &rows, &cols);
+ A = sf_new(rows, cols);
+ for(i = 0; i < rows; i++) {
+ pdest = GETSET(A, A->count++);
+ (void) set_clear(pdest, A->sf_size);
+ for(j = 0; j < cols; j++) {
+ switch(getc(fp)) {
+ case '0':
+ break;
+ case '1':
+ set_insert(pdest, j);
+ break;
+ default:
+ fatal("Error reading set family");
+ }
+ }
+ if (getc(fp) != '\n') {
+ fatal("Error reading set family (at end of line)");
+ }
+ }
+ return A;
+}
+
+
+
+/* ps1 -- convert a set into a printable string */
+#define largest_string 120
+static char s1[largest_string];
+char *ps1(a)
+register pset a;
+{
+ register int i, num, l, len = 0, n = NELEM(a);
+ char temp[20];
+ bool first = TRUE;
+
+ s1[len++] = '[';
+ for(i = 0; i < n; i++)
+ if (is_in_set(a,i)) {
+ if (! first)
+ s1[len++] = ',';
+ first = FALSE; num = i;
+ /* Generate digits (reverse order) */
+ l = 0; do temp[l++] = num % 10 + '0'; while ((num /= 10) > 0);
+ /* Copy them back in correct order */
+ do s1[len++] = temp[--l]; while (l > 0);
+ if (len > largest_string-15) {
+ s1[len++] = '.'; s1[len++] = '.'; s1[len++] = '.';
+ break;
+ }
+ }
+
+ s1[len++] = ']';
+ s1[len++] = '\0';
+ return s1;
+}
+
+/* pbv1 -- print bit-vector */
+char *pbv1(s, n)
+pset s;
+int n;
+{
+ register int i;
+ for(i = 0; i < n; i++)
+ s1[i] = is_in_set(s,i) ? '1' : '0';
+ s1[n] = '\0';
+ return s1;
+}
+
+
+/* set_adjcnt -- adjust the counts for a set by "weight" */
+void
+set_adjcnt(a, count, weight)
+register pset a;
+register int *count, weight;
+{
+ register int i, base;
+ register unsigned int val;
+
+ for(i = LOOP(a); i > 0; ) {
+ for(val = a[i], base = --i << LOGBPI; val != 0; base++, val >>= 1) {
+ if (val & 1) {
+ count[base] += weight;
+ }
+ }
+ }
+}
+
+
+
+/* sf_count -- perform a column sum over a set family */
+int *sf_count(A)
+pset_family A;
+{
+ register pset p, last;
+ register int i, base, *count;
+ register unsigned int val;
+
+ count = ALLOC(int, A->sf_size);
+ for(i = A->sf_size - 1; i >= 0; i--) {
+ count[i] = 0;
+ }
+
+ foreach_set(A, last, p) {
+ for(i = LOOP(p); i > 0; ) {
+ for(val = p[i], base = --i << LOGBPI; val != 0; base++, val >>= 1) {
+ if (val & 1) {
+ count[base]++;
+ }
+ }
+ }
+ }
+ return count;
+}
+
+
+/* sf_count_restricted -- perform a column sum over a set family, restricting
+ * to only the columns which are in r; also, the columns are weighted by the
+ * number of elements which are in each row
+ */
+int *sf_count_restricted(A, r)
+pset_family A;
+register pset r;
+{
+ register pset p;
+ register int i, base, *count;
+ register unsigned int val;
+ int weight;
+ pset last;
+
+ count = ALLOC(int, A->sf_size);
+ for(i = A->sf_size - 1; i >= 0; i--) {
+ count[i] = 0;
+ }
+
+ /* Loop for each set */
+ foreach_set(A, last, p) {
+ weight = 1024 / (set_ord(p) - 1);
+ for(i = LOOP(p); i > 0; ) {
+ for(val=p[i]&r[i], base= --i<<LOGBPI; val!=0; base++, val >>= 1) {
+ if (val & 1) {
+ count[base] += weight;
+ }
+ }
+ }
+ }
+ return count;
+}
+
+
+/*
+ * sf_delc -- delete columns first ... last of A
+ */
+pset_family sf_delc(A, first, last)
+pset_family A;
+int first, last;
+{
+ return sf_delcol(A, first, last-first + 1);
+}
+
+
+/*
+ * sf_addcol -- add columns to a set family; includes a quick check to see
+ * if there is already enough room (and hence, can avoid copying)
+ */
+pset_family sf_addcol(A, firstcol, n)
+pset_family A;
+int firstcol, n;
+{
+ int maxsize;
+
+ /* Check if adding columns at the end ... */
+ if (firstcol == A->sf_size) {
+ /* If so, check if there is already enough room */
+ maxsize = BPI * LOOPINIT(A->sf_size);
+ if ((A->sf_size + n) <= maxsize) {
+ A->sf_size += n;
+ return A;
+ }
+ }
+ return sf_delcol(A, firstcol, -n);
+}
+
+/*
+ * sf_delcol -- add/delete columns to/from a set family
+ *
+ * if n > 0 then n columns starting from firstcol are deleted if n < 0
+ * then n blank columns are inserted starting at firstcol
+ * (i.e., the first new column number is firstcol)
+ *
+ * This is done by copying columns in the array which is a relatively
+ * slow operation.
+ */
+pset_family sf_delcol(A, firstcol, n)
+pset_family A;
+register int firstcol, n;
+{
+ register pset p, last, pdest;
+ register int i;
+ pset_family B;
+
+ B = sf_new(A->count, A->sf_size - n);
+ foreach_set(A, last, p) {
+ pdest = GETSET(B, B->count++);
+ INLINEset_clear(pdest, B->sf_size);
+ for(i = 0; i < firstcol; i++)
+ if (is_in_set(p, i))
+ set_insert(pdest, i);
+ for(i = n > 0 ? firstcol + n : firstcol; i < A->sf_size; i++)
+ if (is_in_set(p, i))
+ set_insert(pdest, i - n);
+ }
+ sf_free(A);
+ return B;
+}
+
+
+/*
+ * sf_copy_col -- copy column "srccol" from "src" to column "dstcol" of "dst"
+ */
+pset_family sf_copy_col(dst, dstcol, src, srccol)
+pset_family dst, src;
+int dstcol, srccol;
+{
+ register pset last, p, pdest;
+ register int word_test, word_set;
+ unsigned int bit_set, bit_test;
+
+ /* CHEAT! form these constants outside the loop */
+ word_test = WHICH_WORD(srccol);
+ bit_test = 1 << WHICH_BIT(srccol);
+ word_set = WHICH_WORD(dstcol);
+ bit_set = 1 << WHICH_BIT(dstcol);
+
+ pdest = dst->data;
+ foreach_set(src, last, p) {
+ if ((p[word_test] & bit_test) != 0)
+ pdest[word_set] |= bit_set;
+/*
+ * equivalent code for this is ...
+ * if (is_in_set(p, srccol)) set_insert(pdest, destcol);
+ */
+ pdest += dst->wsize;
+ }
+ return dst;
+}
+
+
+
+/*
+ * sf_compress -- delete columns from a matrix
+ */
+pset_family sf_compress(A, c)
+pset_family A; /* will be freed */
+register pset c;
+{
+ register pset p;
+ register int i, bcol;
+ pset_family B;
+
+ /* create a clean set family for the result */
+ B = sf_new(A->count, set_ord(c));
+ for(i = 0; i < A->count; i++) {
+ p = GETSET(B, B->count++);
+ INLINEset_clear(p, B->sf_size);
+ }
+
+ /* copy each column of A which has a 1 in c */
+ bcol = 0;
+ for(i = 0; i < A->sf_size; i++) {
+ if (is_in_set(c, i)) {
+ (void) sf_copy_col(B, bcol++, A, i);
+ }
+ }
+ sf_free(A);
+ return B;
+}
+
+
+
+/*
+ * sf_transpose -- transpose a bit matrix
+ *
+ * There are trickier ways of doing this, but this works.
+ */
+pset_family sf_transpose(A)
+pset_family A;
+{
+ pset_family B;
+ register pset p;
+ register int i, j;
+
+ B = sf_new(A->sf_size, A->count);
+ B->count = A->sf_size;
+ foreachi_set(B, i, p) {
+ INLINEset_clear(p, B->sf_size);
+ }
+ foreachi_set(A, i, p) {
+ for(j = 0; j < A->sf_size; j++) {
+ if (is_in_set(p, j)) {
+ set_insert(GETSET(B, j), i);
+ }
+ }
+ }
+ sf_free(A);
+ return B;
+}
+
+
+/*
+ * sf_permute -- permute the columns of a set_family
+ *
+ * permute is an array of integers containing column numbers of A which
+ * are to be retained.
+ */
+pset_family sf_permute(A, permute, npermute)
+pset_family A;
+register int *permute, npermute;
+{
+ pset_family B;
+ register pset p, last, pdest;
+ register int j;
+
+ B = sf_new(A->count, npermute);
+ B->count = A->count;
+ foreach_set(B, last, p)
+ INLINEset_clear(p, npermute);
+
+ pdest = B->data;
+ foreach_set(A, last, p) {
+ for(j = 0; j < npermute; j++)
+ if (is_in_set(p, permute[j]))
+ set_insert(pdest, j);
+ pdest += B->wsize;
+ }
+ sf_free(A);
+ return B;
+}
diff --git a/src/misc/espresso/setc.c b/src/misc/espresso/setc.c
new file mode 100644
index 00000000..a6112ebc
--- /dev/null
+++ b/src/misc/espresso/setc.c
@@ -0,0 +1,483 @@
+/*
+ * Revision Control Information
+ *
+ * $Source$
+ * $Author$
+ * $Revision$
+ * $Date$
+ *
+ */
+/*
+ setc.c -- massive bit-hacking for performing special "cube"-type
+ operations on a set
+
+ The basic trick used for binary valued variables is the following:
+
+ If a[w] and b[w] contain a full word of binary variables, then:
+
+ 1) to get the full word of their intersection, we use
+
+ x = a[w] & b[w];
+
+
+ 2) to see if the intersection is null in any variables, we examine
+
+ x = ~(x | x >> 1) & DISJOINT;
+
+ this will have a single 1 in each binary variable for which
+ the intersection is null. In particular, if this is zero,
+ then there are no disjoint variables; or, if this is nonzero,
+ then there is at least one disjoint variable. A "count_ones"
+ over x will tell in how many variables they have an null
+ intersection.
+
+
+ 3) to get a mask which selects the disjoint variables, we use
+
+ (x | x << 1)
+
+ this provides a selector which can be used to see where
+ they have an null intersection
+
+
+ cdist return distance between two cubes
+ cdist0 return true if two cubes are distance 0 apart
+ cdist01 return distance, or 2 if distance exceeds 1
+ consensus compute consensus of two cubes distance 1 apart
+ force_lower expand hack (for now), related to consensus
+*/
+
+#include "espresso.h"
+
+/* see if the cube has a full row of 1's (with respect to cof) */
+bool full_row(p, cof)
+IN register pcube p, cof;
+{
+ register int i = LOOP(p);
+ do if ((p[i] | cof[i]) != cube.fullset[i]) return FALSE; while (--i > 0);
+ return TRUE;
+}
+
+/*
+ cdist0 -- return TRUE if a and b are distance 0 apart
+*/
+
+bool cdist0(a, b)
+register pcube a, b;
+{
+ { /* Check binary variables */
+ register int w, last; register unsigned int x;
+ if ((last = cube.inword) != -1) {
+
+ /* Check the partial word of binary variables */
+ x = a[last] & b[last];
+ if (~(x | x >> 1) & cube.inmask)
+ return FALSE; /* disjoint in some variable */
+
+ /* Check the full words of binary variables */
+ for(w = 1; w < last; w++) {
+ x = a[w] & b[w];
+ if (~(x | x >> 1) & DISJOINT)
+ return FALSE; /* disjoint in some variable */
+ }
+ }
+ }
+
+ { /* Check the multiple-valued variables */
+ register int w, var, last; register pcube mask;
+ for(var = cube.num_binary_vars; var < cube.num_vars; var++) {
+ mask = cube.var_mask[var]; last = cube.last_word[var];
+ for(w = cube.first_word[var]; w <= last; w++)
+ if (a[w] & b[w] & mask[w])
+ goto nextvar;
+ return FALSE; /* disjoint in this variable */
+ nextvar: ;
+ }
+ }
+ return TRUE;
+}
+
+/*
+ cdist01 -- return the "distance" between two cubes (defined as the
+ number of null variables in their intersection). If the distance
+ exceeds 1, the value 2 is returned.
+*/
+
+int cdist01(a, b)
+register pset a, b;
+{
+ int dist = 0;
+
+ { /* Check binary variables */
+ register int w, last; register unsigned int x;
+ if ((last = cube.inword) != -1) {
+
+ /* Check the partial word of binary variables */
+ x = a[last] & b[last];
+ if (x = ~ (x | x >> 1) & cube.inmask)
+ if ((dist = count_ones(x)) > 1)
+ return 2;
+
+ /* Check the full words of binary variables */
+ for(w = 1; w < last; w++) {
+ x = a[w] & b[w];
+ if (x = ~ (x | x >> 1) & DISJOINT)
+ if (dist == 1 || (dist += count_ones(x)) > 1)
+ return 2;
+ }
+ }
+ }
+
+ { /* Check the multiple-valued variables */
+ register int w, var, last; register pcube mask;
+ for(var = cube.num_binary_vars; var < cube.num_vars; var++) {
+ mask = cube.var_mask[var]; last = cube.last_word[var];
+ for(w = cube.first_word[var]; w <= last; w++)
+ if (a[w] & b[w] & mask[w])
+ goto nextvar;
+ if (++dist > 1)
+ return 2;
+ nextvar: ;
+ }
+ }
+ return dist;
+}
+
+/*
+ cdist -- return the "distance" between two cubes (defined as the
+ number of null variables in their intersection).
+*/
+
+int cdist(a, b)
+register pset a, b;
+{
+ int dist = 0;
+
+ { /* Check binary variables */
+ register int w, last; register unsigned int x;
+ if ((last = cube.inword) != -1) {
+
+ /* Check the partial word of binary variables */
+ x = a[last] & b[last];
+ if (x = ~ (x | x >> 1) & cube.inmask)
+ dist = count_ones(x);
+
+ /* Check the full words of binary variables */
+ for(w = 1; w < last; w++) {
+ x = a[w] & b[w];
+ if (x = ~ (x | x >> 1) & DISJOINT)
+ dist += count_ones(x);
+ }
+ }
+ }
+
+ { /* Check the multiple-valued variables */
+ register int w, var, last; register pcube mask;
+ for(var = cube.num_binary_vars; var < cube.num_vars; var++) {
+ mask = cube.var_mask[var]; last = cube.last_word[var];
+ for(w = cube.first_word[var]; w <= last; w++)
+ if (a[w] & b[w] & mask[w])
+ goto nextvar;
+ dist++;
+ nextvar: ;
+ }
+ }
+ return dist;
+}
+
+/*
+ force_lower -- Determine which variables of a do not intersect b.
+*/
+
+pset force_lower(xlower, a, b)
+INOUT pset xlower;
+IN register pset a, b;
+{
+
+ { /* Check binary variables (if any) */
+ register int w, last; register unsigned int x;
+ if ((last = cube.inword) != -1) {
+
+ /* Check the partial word of binary variables */
+ x = a[last] & b[last];
+ if (x = ~(x | x >> 1) & cube.inmask)
+ xlower[last] |= (x | (x << 1)) & a[last];
+
+ /* Check the full words of binary variables */
+ for(w = 1; w < last; w++) {
+ x = a[w] & b[w];
+ if (x = ~(x | x >> 1) & DISJOINT)
+ xlower[w] |= (x | (x << 1)) & a[w];
+ }
+ }
+ }
+
+ { /* Check the multiple-valued variables */
+ register int w, var, last; register pcube mask;
+ for(var = cube.num_binary_vars; var < cube.num_vars; var++) {
+ mask = cube.var_mask[var]; last = cube.last_word[var];
+ for(w = cube.first_word[var]; w <= last; w++)
+ if (a[w] & b[w] & mask[w])
+ goto nextvar;
+ for(w = cube.first_word[var]; w <= last; w++)
+ xlower[w] |= a[w] & mask[w];
+ nextvar: ;
+ }
+ }
+ return xlower;
+}
+
+/*
+ consensus -- multiple-valued consensus
+
+ Although this looks very messy, the idea is to compute for r the
+ "and" of the cubes a and b for each variable, unless the "and" is
+ null in a variable, in which case the "or" of a and b is computed
+ for this variable.
+
+ Because we don't check how many variables are null in the
+ intersection of a and b, the returned value for r really only
+ represents the consensus when a and b are distance 1 apart.
+*/
+
+void consensus(r, a, b)
+INOUT pcube r;
+IN register pcube a, b;
+{
+ INLINEset_clear(r, cube.size);
+
+ { /* Check binary variables (if any) */
+ register int w, last; register unsigned int x;
+ if ((last = cube.inword) != -1) {
+
+ /* Check the partial word of binary variables */
+ r[last] = x = a[last] & b[last];
+ if (x = ~(x | x >> 1) & cube.inmask)
+ r[last] |= (x | (x << 1)) & (a[last] | b[last]);
+
+ /* Check the full words of binary variables */
+ for(w = 1; w < last; w++) {
+ r[w] = x = a[w] & b[w];
+ if (x = ~(x | x >> 1) & DISJOINT)
+ r[w] |= (x | (x << 1)) & (a[w] | b[w]);
+ }
+ }
+ }
+
+
+ { /* Check the multiple-valued variables */
+ bool empty; int var; unsigned int x;
+ register int w, last; register pcube mask;
+ for(var = cube.num_binary_vars; var < cube.num_vars; var++) {
+ mask = cube.var_mask[var];
+ last = cube.last_word[var];
+ empty = TRUE;
+ for(w = cube.first_word[var]; w <= last; w++)
+ if (x = a[w] & b[w] & mask[w])
+ empty = FALSE, r[w] |= x;
+ if (empty)
+ for(w = cube.first_word[var]; w <= last; w++)
+ r[w] |= mask[w] & (a[w] | b[w]);
+ }
+ }
+}
+
+/*
+ cactive -- return the index of the single active variable in
+ the cube, or return -1 if there are none or more than 2.
+*/
+
+int cactive(a)
+register pcube a;
+{
+ int active = -1, dist = 0, bit_index();
+
+ { /* Check binary variables */
+ register int w, last;
+ register unsigned int x;
+ if ((last = cube.inword) != -1) {
+
+ /* Check the partial word of binary variables */
+ x = a[last];
+ if (x = ~ (x & x >> 1) & cube.inmask) {
+ if ((dist = count_ones(x)) > 1)
+ return -1; /* more than 2 active variables */
+ active = (last-1)*(BPI/2) + bit_index(x) / 2;
+ }
+
+ /* Check the full words of binary variables */
+ for(w = 1; w < last; w++) {
+ x = a[w];
+ if (x = ~ (x & x >> 1) & DISJOINT) {
+ if ((dist += count_ones(x)) > 1)
+ return -1; /* more than 2 active variables */
+ active = (w-1)*(BPI/2) + bit_index(x) / 2;
+ }
+ }
+ }
+ }
+
+ { /* Check the multiple-valued variables */
+ register int w, var, last;
+ register pcube mask;
+ for(var = cube.num_binary_vars; var < cube.num_vars; var++) {
+ mask = cube.var_mask[var];
+ last = cube.last_word[var];
+ for(w = cube.first_word[var]; w <= last; w++)
+ if (mask[w] & ~ a[w]) {
+ if (++dist > 1)
+ return -1;
+ active = var;
+ break;
+ }
+ }
+ }
+ return active;
+}
+
+/*
+ ccommon -- return TRUE if a and b are share "active" variables
+ active variables include variables that are empty;
+*/
+
+bool ccommon(a, b, cof)
+register pcube a, b, cof;
+{
+ { /* Check binary variables */
+ int last;
+ register int w;
+ register unsigned int x, y;
+ if ((last = cube.inword) != -1) {
+
+ /* Check the partial word of binary variables */
+ x = a[last] | cof[last];
+ y = b[last] | cof[last];
+ if (~(x & x>>1) & ~(y & y>>1) & cube.inmask)
+ return TRUE;
+
+ /* Check the full words of binary variables */
+ for(w = 1; w < last; w++) {
+ x = a[w] | cof[w];
+ y = b[w] | cof[w];
+ if (~(x & x>>1) & ~(y & y>>1) & DISJOINT)
+ return TRUE;
+ }
+ }
+ }
+
+ { /* Check the multiple-valued variables */
+ int var;
+ register int w, last;
+ register pcube mask;
+ for(var = cube.num_binary_vars; var < cube.num_vars; var++) {
+ mask = cube.var_mask[var]; last = cube.last_word[var];
+ /* Check for some part missing from a */
+ for(w = cube.first_word[var]; w <= last; w++)
+ if (mask[w] & ~a[w] & ~cof[w]) {
+
+ /* If so, check for some part missing from b */
+ for(w = cube.first_word[var]; w <= last; w++)
+ if (mask[w] & ~b[w] & ~cof[w])
+ return TRUE; /* both active */
+ break;
+ }
+ }
+ }
+ return FALSE;
+}
+
+/*
+ These routines compare two sets (cubes) for the qsort() routine and
+ return:
+
+ -1 if set a is to precede set b
+ 0 if set a and set b are equal
+ 1 if set a is to follow set b
+
+ Usually the SIZE field of the set is assumed to contain the size
+ of the set (which will save recomputing the set size during the
+ sort). For distance-1 merging, the global variable cube.temp[0] is
+ a mask which mask's-out the merging variable.
+*/
+
+/* descend -- comparison for descending sort on set size */
+int descend(a, b)
+pset *a, *b;
+{
+ register pset a1 = *a, b1 = *b;
+ if (SIZE(a1) > SIZE(b1)) return -1;
+ else if (SIZE(a1) < SIZE(b1)) return 1;
+ else {
+ register int i = LOOP(a1);
+ do
+ if (a1[i] > b1[i]) return -1; else if (a1[i] < b1[i]) return 1;
+ while (--i > 0);
+ }
+ return 0;
+}
+
+/* ascend -- comparison for ascending sort on set size */
+int ascend(a, b)
+pset *a, *b;
+{
+ register pset a1 = *a, b1 = *b;
+ if (SIZE(a1) > SIZE(b1)) return 1;
+ else if (SIZE(a1) < SIZE(b1)) return -1;
+ else {
+ register int i = LOOP(a1);
+ do
+ if (a1[i] > b1[i]) return 1; else if (a1[i] < b1[i]) return -1;
+ while (--i > 0);
+ }
+ return 0;
+}
+
+
+/* lex_order -- comparison for "lexical" ordering of cubes */
+int lex_order(a, b)
+pset *a, *b;
+{
+ register pset a1 = *a, b1 = *b;
+ register int i = LOOP(a1);
+ do
+ if (a1[i] > b1[i]) return -1; else if (a1[i] < b1[i]) return 1;
+ while (--i > 0);
+ return 0;
+}
+
+
+/* d1_order -- comparison for distance-1 merge routine */
+int d1_order(a, b)
+pset *a, *b;
+{
+ register pset a1 = *a, b1 = *b, c1 = cube.temp[0];
+ register int i = LOOP(a1);
+ register unsigned int x1, x2;
+ do
+ if ((x1 = a1[i] | c1[i]) > (x2 = b1[i] | c1[i])) return -1;
+ else if (x1 < x2) return 1;
+ while (--i > 0);
+ return 0;
+}
+
+
+/* desc1 -- comparison (without indirection) for descending sort */
+/* also has effect of handling NULL pointers,and a NULL pointer has smallest
+order */
+int desc1(a, b)
+register pset a, b;
+{
+ if (a == (pset) NULL)
+ return (b == (pset) NULL) ? 0 : 1;
+ else if (b == (pset) NULL)
+ return -1;
+ if (SIZE(a) > SIZE(b)) return -1;
+ else if (SIZE(a) < SIZE(b)) return 1;
+ else {
+ register int i = LOOP(a);
+ do
+ if (a[i] > b[i]) return -1; else if (a[i] < b[i]) return 1;
+ while (--i > 0);
+ }
+ return 0;
+}
diff --git a/src/misc/espresso/sharp.c b/src/misc/espresso/sharp.c
new file mode 100644
index 00000000..53435078
--- /dev/null
+++ b/src/misc/espresso/sharp.c
@@ -0,0 +1,247 @@
+/*
+ * Revision Control Information
+ *
+ * $Source$
+ * $Author$
+ * $Revision$
+ * $Date$
+ *
+ */
+/*
+ sharp.c -- perform sharp, disjoint sharp, and intersection
+*/
+
+#include "espresso.h"
+
+long start_time;
+
+
+/* cv_sharp -- form the sharp product between two covers */
+pcover cv_sharp(A, B)
+pcover A, B;
+{
+ pcube last, p;
+ pcover T;
+
+ T = new_cover(0);
+ foreach_set(A, last, p)
+ T = sf_union(T, cb_sharp(p, B));
+ return T;
+}
+
+
+/* cb_sharp -- form the sharp product between a cube and a cover */
+pcover cb_sharp(c, T)
+pcube c;
+pcover T;
+{
+ if (T->count == 0) {
+ T = sf_addset(new_cover(1), c);
+ } else {
+ start_time = ptime();
+ T = cb_recur_sharp(c, T, 0, T->count-1, 0);
+ }
+ return T;
+}
+
+
+/* recursive formulation to provide balanced merging */
+pcover cb_recur_sharp(c, T, first, last, level)
+pcube c;
+pcover T;
+int first, last, level;
+{
+ pcover temp, left, right;
+ int middle;
+
+ if (first == last) {
+ temp = sharp(c, GETSET(T, first));
+ } else {
+ middle = (first + last) / 2;
+ left = cb_recur_sharp(c, T, first, middle, level+1);
+ right = cb_recur_sharp(c, T, middle+1, last, level+1);
+ temp = cv_intersect(left, right);
+ if ((debug & SHARP) && level < 4) {
+ printf("# SHARP[%d]: %4d = %4d x %4d, time = %s\n",
+ level, temp->count, left->count, right->count,
+ print_time(ptime() - start_time));
+ (void) fflush(stdout);
+ }
+ free_cover(left);
+ free_cover(right);
+ }
+ return temp;
+}
+
+
+/* sharp -- form the sharp product between two cubes */
+pcover sharp(a, b)
+pcube a, b;
+{
+ register int var;
+ register pcube d=cube.temp[0], temp=cube.temp[1], temp1=cube.temp[2];
+ pcover r = new_cover(cube.num_vars);
+
+ if (cdist0(a, b)) {
+ set_diff(d, a, b);
+ for(var = 0; var < cube.num_vars; var++) {
+ if (! setp_empty(set_and(temp, d, cube.var_mask[var]))) {
+ set_diff(temp1, a, cube.var_mask[var]);
+ set_or(GETSET(r, r->count++), temp, temp1);
+ }
+ }
+ } else {
+ r = sf_addset(r, a);
+ }
+ return r;
+}
+
+pcover make_disjoint(A)
+pcover A;
+{
+ pcover R, new;
+ register pset last, p;
+
+ R = new_cover(0);
+ foreach_set(A, last, p) {
+ new = cb_dsharp(p, R);
+ R = sf_append(R, new);
+ }
+ return R;
+}
+
+
+/* cv_dsharp -- disjoint-sharp product between two covers */
+pcover cv_dsharp(A, B)
+pcover A, B;
+{
+ register pcube last, p;
+ pcover T;
+
+ T = new_cover(0);
+ foreach_set(A, last, p) {
+ T = sf_union(T, cb_dsharp(p, B));
+ }
+ return T;
+}
+
+
+/* cb1_dsharp -- disjoint-sharp product between a cover and a cube */
+pcover cb1_dsharp(T, c)
+pcover T;
+pcube c;
+{
+ pcube last, p;
+ pcover R;
+
+ R = new_cover(T->count);
+ foreach_set(T, last, p) {
+ R = sf_union(R, dsharp(p, c));
+ }
+ return R;
+}
+
+
+/* cb_dsharp -- disjoint-sharp product between a cube and a cover */
+pcover cb_dsharp(c, T)
+pcube c;
+pcover T;
+{
+ pcube last, p;
+ pcover Y, Y1;
+
+ if (T->count == 0) {
+ Y = sf_addset(new_cover(1), c);
+ } else {
+ Y = new_cover(T->count);
+ set_copy(GETSET(Y,Y->count++), c);
+ foreach_set(T, last, p) {
+ Y1 = cb1_dsharp(Y, p);
+ free_cover(Y);
+ Y = Y1;
+ }
+ }
+ return Y;
+}
+
+
+/* dsharp -- form the disjoint-sharp product between two cubes */
+pcover dsharp(a, b)
+pcube a, b;
+{
+ register pcube mask, diff, and, temp, temp1 = cube.temp[0];
+ int var;
+ pcover r;
+
+ r = new_cover(cube.num_vars);
+
+ if (cdist0(a, b)) {
+ diff = set_diff(new_cube(), a, b);
+ and = set_and(new_cube(), a, b);
+ mask = new_cube();
+ for(var = 0; var < cube.num_vars; var++) {
+ /* check if position var of "a and not b" is not empty */
+ if (! setp_disjoint(diff, cube.var_mask[var])) {
+
+ /* coordinate var equals the difference between a and b */
+ temp = GETSET(r, r->count++);
+ (void) set_and(temp, diff, cube.var_mask[var]);
+
+ /* coordinates 0 ... var-1 equal the intersection */
+ INLINEset_and(temp1, and, mask);
+ INLINEset_or(temp, temp, temp1);
+
+ /* coordinates var+1 .. cube.num_vars equal a */
+ set_or(mask, mask, cube.var_mask[var]);
+ INLINEset_diff(temp1, a, mask);
+ INLINEset_or(temp, temp, temp1);
+ }
+ }
+ free_cube(diff);
+ free_cube(and);
+ free_cube(mask);
+ } else {
+ r = sf_addset(r, a);
+ }
+ return r;
+}
+
+/* cv_intersect -- form the intersection of two covers */
+
+#define MAGIC 500 /* save 500 cubes before containment */
+
+pcover cv_intersect(A, B)
+pcover A, B;
+{
+ register pcube pi, pj, lasti, lastj, pt;
+ pcover T, Tsave = NULL;
+
+ /* How large should each temporary result cover be ? */
+ T = new_cover(MAGIC);
+ pt = T->data;
+
+ /* Form pairwise intersection of each cube of A with each cube of B */
+ foreach_set(A, lasti, pi) {
+ foreach_set(B, lastj, pj) {
+ if (cdist0(pi, pj)) {
+ (void) set_and(pt, pi, pj);
+ if (++T->count >= T->capacity) {
+ if (Tsave == NULL)
+ Tsave = sf_contain(T);
+ else
+ Tsave = sf_union(Tsave, sf_contain(T));
+ T = new_cover(MAGIC);
+ pt = T->data;
+ } else
+ pt += T->wsize;
+ }
+ }
+ }
+
+
+ if (Tsave == NULL)
+ Tsave = sf_contain(T);
+ else
+ Tsave = sf_union(Tsave, sf_contain(T));
+ return Tsave;
+}
diff --git a/src/misc/espresso/sminterf.c b/src/misc/espresso/sminterf.c
new file mode 100644
index 00000000..50a6db4e
--- /dev/null
+++ b/src/misc/espresso/sminterf.c
@@ -0,0 +1,44 @@
+/*
+ * Revision Control Information
+ *
+ * $Source$
+ * $Author$
+ * $Revision$
+ * $Date$
+ *
+ */
+#include "espresso.h"
+
+
+pset
+do_sm_minimum_cover(A)
+pset_family A;
+{
+ sm_matrix *M;
+ sm_row *sparse_cover;
+ sm_element *pe;
+ pset cover;
+ register int i, base, rownum;
+ register unsigned val;
+ register pset last, p;
+
+ M = sm_alloc();
+ rownum = 0;
+ foreach_set(A, last, p) {
+ foreach_set_element(p, i, val, base) {
+ (void) sm_insert(M, rownum, base);
+ }
+ rownum++;
+ }
+
+ sparse_cover = sm_minimum_cover(M, NIL(int), 1, 0);
+ sm_free(M);
+
+ cover = set_new(A->sf_size);
+ sm_foreach_row_element(sparse_cover, pe) {
+ set_insert(cover, pe->col_num);
+ }
+ sm_row_free(sparse_cover);
+
+ return cover;
+}
diff --git a/src/misc/espresso/solution.c b/src/misc/espresso/solution.c
new file mode 100644
index 00000000..26119185
--- /dev/null
+++ b/src/misc/espresso/solution.c
@@ -0,0 +1,114 @@
+/*
+ * Revision Control Information
+ *
+ * $Source$
+ * $Author$
+ * $Revision$
+ * $Date$
+ *
+ */
+#include "mincov_int.h"
+
+
+solution_t *
+solution_alloc()
+{
+ solution_t *sol;
+
+ sol = ALLOC(solution_t, 1);
+ sol->cost = 0;
+ sol->row = sm_row_alloc();
+ return sol;
+}
+
+
+void
+solution_free(sol)
+solution_t *sol;
+{
+ sm_row_free(sol->row);
+ FREE(sol);
+}
+
+
+solution_t *
+solution_dup(sol)
+solution_t *sol;
+{
+ solution_t *new_sol;
+
+ new_sol = ALLOC(solution_t, 1);
+ new_sol->cost = sol->cost;
+ new_sol->row = sm_row_dup(sol->row);
+ return new_sol;
+}
+
+
+void
+solution_add(sol, weight, col)
+solution_t *sol;
+int *weight;
+int col;
+{
+ (void) sm_row_insert(sol->row, col);
+ sol->cost += WEIGHT(weight, col);
+}
+
+
+void
+solution_accept(sol, A, weight, col)
+solution_t *sol;
+sm_matrix *A;
+int *weight;
+int col;
+{
+ register sm_element *p, *pnext;
+ sm_col *pcol;
+
+ solution_add(sol, weight, col);
+
+ /* delete rows covered by this column */
+ pcol = sm_get_col(A, col);
+ for(p = pcol->first_row; p != 0; p = pnext) {
+ pnext = p->next_row; /* grab it before it disappears */
+ sm_delrow(A, p->row_num);
+ }
+}
+
+
+/* ARGSUSED */
+void
+solution_reject(sol, A, weight, col)
+solution_t *sol;
+sm_matrix *A;
+int *weight;
+int col;
+{
+ sm_delcol(A, col);
+}
+
+
+solution_t *
+solution_choose_best(best1, best2)
+solution_t *best1, *best2;
+{
+ if (best1 != NIL(solution_t)) {
+ if (best2 != NIL(solution_t)) {
+ if (best1->cost <= best2->cost) {
+ solution_free(best2);
+ return best1;
+ } else {
+ solution_free(best1);
+ return best2;
+ }
+ } else {
+ return best1;
+ }
+ } else {
+ if (best2 != NIL(solution_t)) {
+ return best2;
+ } else {
+ return NIL(solution_t);
+ }
+ }
+}
diff --git a/src/misc/espresso/sparse.c b/src/misc/espresso/sparse.c
new file mode 100644
index 00000000..137ce7c1
--- /dev/null
+++ b/src/misc/espresso/sparse.c
@@ -0,0 +1,146 @@
+/*
+ * Revision Control Information
+ *
+ * $Source$
+ * $Author$
+ * $Revision$
+ * $Date$
+ *
+ */
+/*
+ module: sparse.c
+
+ make_sparse is a last-step cleanup to reduce the total number
+ of literals in the cover.
+
+ This is done by reducing the "sparse" variables (using a modified
+ version of irredundant rather than reduce), followed by expanding
+ the "dense" variables (using modified version of expand).
+*/
+
+#include "espresso.h"
+
+pcover make_sparse(F, D, R)
+pcover F, D, R;
+{
+ cost_t cost, best_cost;
+
+ cover_cost(F, &best_cost);
+
+ do {
+ EXECUTE(F = mv_reduce(F, D), MV_REDUCE_TIME, F, cost);
+ if (cost.total == best_cost.total)
+ break;
+ copy_cost(&cost, &best_cost);
+
+ EXECUTE(F = expand(F, R, TRUE), RAISE_IN_TIME, F, cost);
+ if (cost.total == best_cost.total)
+ break;
+ copy_cost(&cost, &best_cost);
+ } while (force_irredundant);
+
+ return F;
+}
+
+/*
+ mv_reduce -- perform an "optimal" reduction of the variables which
+ we desire to be sparse
+
+ This could be done using "reduce" and then saving just the desired
+ part of the reduction. Instead, this version uses IRRED to find
+ which cubes of an output are redundant. Note that this gets around
+ the cube-ordering problem.
+
+ In normal use, it is expected that the cover is irredundant and
+ hence no cubes will be reduced to the empty cube (however, this is
+ checked for and such cubes will be deleted)
+*/
+
+pcover
+mv_reduce(F, D)
+pcover F, D;
+{
+ register int i, var;
+ register pcube p, p1, last;
+ int index;
+ pcover F1, D1;
+ pcube *F_cube_table;
+
+ /* loop for each multiple-valued variable */
+ for(var = 0; var < cube.num_vars; var++) {
+
+ if (cube.sparse[var]) {
+
+ /* loop for each part of the variable */
+ for(i = cube.first_part[var]; i <= cube.last_part[var]; i++) {
+
+ /* remember mapping of F1 cubes back to F cubes */
+ F_cube_table = ALLOC(pcube, F->count);
+
+ /* 'cofactor' against part #i of variable #var */
+ F1 = new_cover(F->count);
+ foreach_set(F, last, p) {
+ if (is_in_set(p, i)) {
+ F_cube_table[F1->count] = p;
+ p1 = GETSET(F1, F1->count++);
+ (void) set_diff(p1, p, cube.var_mask[var]);
+ set_insert(p1, i);
+ }
+ }
+
+ /* 'cofactor' against part #i of variable #var */
+ /* not really necessary -- just more efficient ? */
+ D1 = new_cover(D->count);
+ foreach_set(D, last, p) {
+ if (is_in_set(p, i)) {
+ p1 = GETSET(D1, D1->count++);
+ (void) set_diff(p1, p, cube.var_mask[var]);
+ set_insert(p1, i);
+ }
+ }
+
+ mark_irredundant(F1, D1);
+
+ /* now remove part i from cubes which are redundant */
+ index = 0;
+ foreach_set(F1, last, p1) {
+ if (! TESTP(p1, ACTIVE)) {
+ p = F_cube_table[index];
+
+ /* don't reduce a variable which is full
+ * (unless it is the output variable)
+ */
+ if (var == cube.num_vars-1 ||
+ ! setp_implies(cube.var_mask[var], p)) {
+ set_remove(p, i);
+ }
+ RESET(p, PRIME);
+ }
+ index++;
+ }
+
+ free_cover(F1);
+ free_cover(D1);
+ FREE(F_cube_table);
+ }
+ }
+ }
+
+ /* Check if any cubes disappeared */
+ (void) sf_active(F);
+ for(var = 0; var < cube.num_vars; var++) {
+ if (cube.sparse[var]) {
+ foreach_active_set(F, last, p) {
+ if (setp_disjoint(p, cube.var_mask[var])) {
+ RESET(p, ACTIVE);
+ F->active_count--;
+ }
+ }
+ }
+ }
+
+ if (F->count != F->active_count) {
+ F = sf_inactive(F);
+ }
+ return F;
+}
diff --git a/src/misc/espresso/sparse.h b/src/misc/espresso/sparse.h
new file mode 100644
index 00000000..212a32ed
--- /dev/null
+++ b/src/misc/espresso/sparse.h
@@ -0,0 +1,135 @@
+/*
+ * Revision Control Information
+ *
+ * $Source$
+ * $Author$
+ * $Revision$
+ * $Date$
+ *
+ */
+#ifndef SPARSE_H
+#define SPARSE_H
+
+/*
+ * sparse.h -- sparse matrix package header file
+ */
+
+typedef struct sm_element_struct sm_element;
+typedef struct sm_row_struct sm_row;
+typedef struct sm_col_struct sm_col;
+typedef struct sm_matrix_struct sm_matrix;
+
+
+/*
+ * sparse matrix element
+ */
+struct sm_element_struct {
+ int row_num; /* row number of this element */
+ int col_num; /* column number of this element */
+ sm_element *next_row; /* next row in this column */
+ sm_element *prev_row; /* previous row in this column */
+ sm_element *next_col; /* next column in this row */
+ sm_element *prev_col; /* previous column in this row */
+ char *user_word; /* user-defined word */
+};
+
+
+/*
+ * row header
+ */
+struct sm_row_struct {
+ int row_num; /* the row number */
+ int length; /* number of elements in this row */
+ int flag; /* user-defined word */
+ sm_element *first_col; /* first element in this row */
+ sm_element *last_col; /* last element in this row */
+ sm_row *next_row; /* next row (in sm_matrix linked list) */
+ sm_row *prev_row; /* previous row (in sm_matrix linked list) */
+ char *user_word; /* user-defined word */
+};
+
+
+/*
+ * column header
+ */
+struct sm_col_struct {
+ int col_num; /* the column number */
+ int length; /* number of elements in this column */
+ int flag; /* user-defined word */
+ sm_element *first_row; /* first element in this column */
+ sm_element *last_row; /* last element in this column */
+ sm_col *next_col; /* next column (in sm_matrix linked list) */
+ sm_col *prev_col; /* prev column (in sm_matrix linked list) */
+ char *user_word; /* user-defined word */
+};
+
+
+/*
+ * A sparse matrix
+ */
+struct sm_matrix_struct {
+ sm_row **rows; /* pointer to row headers (by row #) */
+ int rows_size; /* alloc'ed size of above array */
+ sm_col **cols; /* pointer to column headers (by col #) */
+ int cols_size; /* alloc'ed size of above array */
+ sm_row *first_row; /* first row (linked list of all rows) */
+ sm_row *last_row; /* last row (linked list of all rows) */
+ int nrows; /* number of rows */
+ sm_col *first_col; /* first column (linked list of columns) */
+ sm_col *last_col; /* last column (linked list of columns) */
+ int ncols; /* number of columns */
+ char *user_word; /* user-defined word */
+};
+
+
+#define sm_get_col(A, colnum) \
+ (((colnum) >= 0 && (colnum) < (A)->cols_size) ? \
+ (A)->cols[colnum] : (sm_col *) 0)
+
+#define sm_get_row(A, rownum) \
+ (((rownum) >= 0 && (rownum) < (A)->rows_size) ? \
+ (A)->rows[rownum] : (sm_row *) 0)
+
+#define sm_foreach_row(A, prow) \
+ for(prow = A->first_row; prow != 0; prow = prow->next_row)
+
+#define sm_foreach_col(A, pcol) \
+ for(pcol = A->first_col; pcol != 0; pcol = pcol->next_col)
+
+#define sm_foreach_row_element(prow, p) \
+ for(p = prow->first_col; p != 0; p = p->next_col)
+
+#define sm_foreach_col_element(pcol, p) \
+ for(p = pcol->first_row; p != 0; p = p->next_row)
+
+#define sm_put(x, val) \
+ (x->user_word = (char *) val)
+
+#define sm_get(type, x) \
+ ((type) (x->user_word))
+
+extern sm_matrix *sm_alloc(), *sm_alloc_size(), *sm_dup();
+extern void sm_free(), sm_delrow(), sm_delcol(), sm_resize();
+extern void sm_write(), sm_print(), sm_dump(), sm_cleanup();
+extern void sm_copy_row(), sm_copy_col();
+extern void sm_remove(), sm_remove_element();
+extern sm_element *sm_insert(), *sm_find();
+extern sm_row *sm_longest_row();
+extern sm_col *sm_longest_col();
+extern int sm_read(), sm_read_compressed();
+
+extern sm_row *sm_row_alloc(), *sm_row_dup(), *sm_row_and();
+extern void sm_row_free(), sm_row_remove(), sm_row_print();
+extern sm_element *sm_row_insert(), *sm_row_find();
+extern int sm_row_contains(), sm_row_intersects();
+extern int sm_row_compare(), sm_row_hash();
+
+extern sm_col *sm_col_alloc(), *sm_col_dup(), *sm_col_and();
+extern void sm_col_free(), sm_col_remove(), sm_col_print();
+extern sm_element *sm_col_insert(), *sm_col_find();
+extern int sm_col_contains(), sm_col_intersects();
+extern int sm_col_compare(), sm_col_hash();
+
+extern int sm_row_dominance(), sm_col_dominance(), sm_block_partition();
+
+#endif
diff --git a/src/misc/espresso/sparse_int.h b/src/misc/espresso/sparse_int.h
new file mode 100644
index 00000000..49b2509a
--- /dev/null
+++ b/src/misc/espresso/sparse_int.h
@@ -0,0 +1,121 @@
+/*
+ * Revision Control Information
+ *
+ * $Source$
+ * $Author$
+ * $Revision$
+ * $Date$
+ *
+ */
+//#include "port.h"
+//#include "utility.h"
+#include "sparse.h"
+
+#include "util_hack.h" // added
+
+
+
+/*
+ * sorted, double-linked list insertion
+ *
+ * type: object type
+ *
+ * first, last: fields (in header) to head and tail of the list
+ * count: field (in header) of length of the list
+ *
+ * next, prev: fields (in object) to link next and previous objects
+ * value: field (in object) which controls the order
+ *
+ * newval: value field for new object
+ * e: an object to use if insertion needed (set to actual value used)
+ */
+
+#define sorted_insert(type, first, last, count, next, prev, value, newval, e) \
+ if (last == 0) { \
+ e->value = newval; \
+ first = e; \
+ last = e; \
+ e->next = 0; \
+ e->prev = 0; \
+ count++; \
+ } else if (last->value < newval) { \
+ e->value = newval; \
+ last->next = e; \
+ e->prev = last; \
+ last = e; \
+ e->next = 0; \
+ count++; \
+ } else if (first->value > newval) { \
+ e->value = newval; \
+ first->prev = e; \
+ e->next = first; \
+ first = e; \
+ e->prev = 0; \
+ count++; \
+ } else { \
+ type *p; \
+ for(p = first; p->value < newval; p = p->next) \
+ ; \
+ if (p->value > newval) { \
+ e->value = newval; \
+ p = p->prev; \
+ p->next->prev = e; \
+ e->next = p->next; \
+ p->next = e; \
+ e->prev = p; \
+ count++; \
+ } else { \
+ e = p; \
+ } \
+ }
+
+
+/*
+ * double linked-list deletion
+ */
+#define dll_unlink(p, first, last, next, prev, count) { \
+ if (p->prev == 0) { \
+ first = p->next; \
+ } else { \
+ p->prev->next = p->next; \
+ } \
+ if (p->next == 0) { \
+ last = p->prev; \
+ } else { \
+ p->next->prev = p->prev; \
+ } \
+ count--; \
+}
+
+
+#ifdef FAST_AND_LOOSE
+extern sm_element *sm_element_freelist;
+extern sm_row *sm_row_freelist;
+extern sm_col *sm_col_freelist;
+
+#define sm_element_alloc(newobj) \
+ if (sm_element_freelist == NIL(sm_element)) { \
+ newobj = ALLOC(sm_element, 1); \
+ } else { \
+ newobj = sm_element_freelist; \
+ sm_element_freelist = sm_element_freelist->next_col; \
+ } \
+ newobj->user_word = NIL(char); \
+
+#define sm_element_free(e) \
+ (e->next_col = sm_element_freelist, sm_element_freelist = e)
+
+#else
+
+#define sm_element_alloc(newobj) \
+ newobj = ALLOC(sm_element, 1); \
+ newobj->user_word = NIL(char);
+#define sm_element_free(e) \
+ FREE(e)
+#endif
+
+
+extern void sm_row_remove_element();
+extern void sm_col_remove_element();
+
+/* LINTLIBRARY */
diff --git a/src/misc/espresso/unate.c b/src/misc/espresso/unate.c
new file mode 100644
index 00000000..bd71207f
--- /dev/null
+++ b/src/misc/espresso/unate.c
@@ -0,0 +1,441 @@
+/*
+ * Revision Control Information
+ *
+ * $Source$
+ * $Author$
+ * $Revision$
+ * $Date$
+ *
+ */
+/*
+ * unate.c -- routines for dealing with unate functions
+ */
+
+#include "espresso.h"
+
+static pset_family abs_covered();
+static pset_family abs_covered_many();
+static int abs_select_restricted();
+
+pcover map_cover_to_unate(T)
+pcube *T;
+{
+ register unsigned int word_test, word_set, bit_test, bit_set;
+ register pcube p, pA;
+ pset_family A;
+ pcube *T1;
+ int ncol, i;
+
+ A = sf_new(CUBELISTSIZE(T), cdata.vars_unate);
+ A->count = CUBELISTSIZE(T);
+ foreachi_set(A, i, p) {
+ (void) set_clear(p, A->sf_size);
+ }
+ ncol = 0;
+
+ for(i = 0; i < cube.size; i++) {
+ if (cdata.part_zeros[i] > 0) {
+ assert(ncol <= cdata.vars_unate);
+
+ /* Copy a column from T to A */
+ word_test = WHICH_WORD(i);
+ bit_test = 1 << WHICH_BIT(i);
+ word_set = WHICH_WORD(ncol);
+ bit_set = 1 << WHICH_BIT(ncol);
+
+ pA = A->data;
+ for(T1 = T+2; (p = *T1++) != 0; ) {
+ if ((p[word_test] & bit_test) == 0) {
+ pA[word_set] |= bit_set;
+ }
+ pA += A->wsize;
+ }
+
+ ncol++;
+ }
+ }
+
+ return A;
+}
+
+pcover map_unate_to_cover(A)
+pset_family A;
+{
+ register int i, ncol, lp;
+ register pcube p, pB;
+ int var, nunate, *unate;
+ pcube last;
+ pset_family B;
+
+ B = sf_new(A->count, cube.size);
+ B->count = A->count;
+
+ /* Find the unate variables */
+ unate = ALLOC(int, cube.num_vars);
+ nunate = 0;
+ for(var = 0; var < cube.num_vars; var++) {
+ if (cdata.is_unate[var]) {
+ unate[nunate++] = var;
+ }
+ }
+
+ /* Loop for each set of A */
+ pB = B->data;
+ foreach_set(A, last, p) {
+
+ /* Initialize this set of B */
+ INLINEset_fill(pB, cube.size);
+
+ /* Now loop for the unate variables; if the part is in A,
+ * then this variable of B should be a single 1 in the unate
+ * part.
+ */
+ for(ncol = 0; ncol < nunate; ncol++) {
+ if (is_in_set(p, ncol)) {
+ lp = cube.last_part[unate[ncol]];
+ for(i = cube.first_part[unate[ncol]]; i <= lp; i++) {
+ if (cdata.part_zeros[i] == 0) {
+ set_remove(pB, i);
+ }
+ }
+ }
+ }
+ pB += B->wsize;
+ }
+
+ FREE(unate);
+ return B;
+}
+
+/*
+ * unate_compl
+ */
+
+pset_family unate_compl(A)
+pset_family A;
+{
+ register pset p, last;
+
+ /* Make sure A is single-cube containment minimal */
+/* A = sf_rev_contain(A);*/
+
+ foreach_set(A, last, p) {
+ PUTSIZE(p, set_ord(p));
+ }
+
+ /* Recursively find the complement */
+ A = unate_complement(A);
+
+ /* Now, we can guarantee a minimal result by containing the result */
+ A = sf_rev_contain(A);
+ return A;
+}
+
+
+/*
+ * Assume SIZE(p) records the size of each set
+ */
+pset_family unate_complement(A)
+pset_family A; /* disposes of A */
+{
+ pset_family Abar;
+ register pset p, p1, restrict;
+ register int i;
+ int max_i, min_set_ord, j;
+
+ /* Check for no sets in the matrix -- complement is the universe */
+ if (A->count == 0) {
+ sf_free(A);
+ Abar = sf_new(1, A->sf_size);
+ (void) set_clear(GETSET(Abar, Abar->count++), A->sf_size);
+
+ /* Check for a single set in the maxtrix -- compute de Morgan complement */
+ } else if (A->count == 1) {
+ p = A->data;
+ Abar = sf_new(A->sf_size, A->sf_size);
+ for(i = 0; i < A->sf_size; i++) {
+ if (is_in_set(p, i)) {
+ p1 = set_clear(GETSET(Abar, Abar->count++), A->sf_size);
+ set_insert(p1, i);
+ }
+ }
+ sf_free(A);
+
+ } else {
+
+ /* Select splitting variable as the variable which belongs to a set
+ * of the smallest size, and which has greatest column count
+ */
+ restrict = set_new(A->sf_size);
+ min_set_ord = A->sf_size + 1;
+ foreachi_set(A, i, p) {
+ if (SIZE(p) < min_set_ord) {
+ set_copy(restrict, p);
+ min_set_ord = SIZE(p);
+ } else if (SIZE(p) == min_set_ord) {
+ set_or(restrict, restrict, p);
+ }
+ }
+
+ /* Check for no data (shouldn't happen ?) */
+ if (min_set_ord == 0) {
+ A->count = 0;
+ Abar = A;
+
+ /* Check for "essential" columns */
+ } else if (min_set_ord == 1) {
+ Abar = unate_complement(abs_covered_many(A, restrict));
+ sf_free(A);
+ foreachi_set(Abar, i, p) {
+ set_or(p, p, restrict);
+ }
+
+ /* else, recur as usual */
+ } else {
+ max_i = abs_select_restricted(A, restrict);
+
+ /* Select those rows of A which are not covered by max_i,
+ * recursively find all minimal covers of these rows, and
+ * then add back in max_i
+ */
+ Abar = unate_complement(abs_covered(A, max_i));
+ foreachi_set(Abar, i, p) {
+ set_insert(p, max_i);
+ }
+
+ /* Now recur on A with all zero's on column max_i */
+ foreachi_set(A, i, p) {
+ if (is_in_set(p, max_i)) {
+ set_remove(p, max_i);
+ j = SIZE(p) - 1;
+ PUTSIZE(p, j);
+ }
+ }
+
+ Abar = sf_append(Abar, unate_complement(A));
+ }
+ set_free(restrict);
+ }
+
+ return Abar;
+}
+
+pset_family exact_minimum_cover(T)
+IN pset_family T;
+{
+ register pset p, last, p1;
+ register int i, n;
+ int lev, lvl;
+ pset nlast;
+ pset_family temp;
+ long start = ptime();
+ struct {
+ pset_family sf;
+ int level;
+ } stack[32]; /* 32 suffices for 2 ** 32 cubes ! */
+
+ if (T->count <= 0)
+ return sf_new(1, T->sf_size);
+ for(n = T->count, lev = 0; n != 0; n >>= 1, lev++) ;
+
+ /* A simple heuristic ordering */
+ T = lex_sort(sf_save(T));
+
+ /* Push a full set on the stack to get things started */
+ n = 1;
+ stack[0].sf = sf_new(1, T->sf_size);
+ stack[0].level = lev;
+ set_fill(GETSET(stack[0].sf, stack[0].sf->count++), T->sf_size);
+
+ nlast = GETSET(T, T->count - 1);
+ foreach_set(T, last, p) {
+
+ /* "unstack" the set into a family */
+ temp = sf_new(set_ord(p), T->sf_size);
+ for(i = 0; i < T->sf_size; i++)
+ if (is_in_set(p, i)) {
+ p1 = set_fill(GETSET(temp, temp->count++), T->sf_size);
+ set_remove(p1, i);
+ }
+ stack[n].sf = temp;
+ stack[n++].level = lev;
+
+ /* Pop the stack and perform (leveled) intersections */
+ while (n > 1 && (stack[n-1].level==stack[n-2].level || p == nlast)) {
+ temp = unate_intersect(stack[n-1].sf, stack[n-2].sf, FALSE);
+ lvl = MIN(stack[n-1].level, stack[n-2].level) - 1;
+ if (debug & MINCOV && lvl < 10) {
+ printf("# EXACT_MINCOV[%d]: %4d = %4d x %4d, time = %s\n",
+ lvl, temp->count, stack[n-1].sf->count,
+ stack[n-2].sf->count, print_time(ptime() - start));
+ (void) fflush(stdout);
+ }
+ sf_free(stack[n-2].sf);
+ sf_free(stack[n-1].sf);
+ stack[n-2].sf = temp;
+ stack[n-2].level = lvl;
+ n--;
+ }
+ }
+
+ temp = stack[0].sf;
+ p1 = set_fill(set_new(T->sf_size), T->sf_size);
+ foreach_set(temp, last, p)
+ INLINEset_diff(p, p1, p);
+ set_free(p1);
+ if (debug & MINCOV1) {
+ printf("MINCOV: family of all minimal coverings is\n");
+ sf_print(temp);
+ }
+ sf_free(T); /* this is the copy of T we made ... */
+ return temp;
+}
+
+/*
+ * unate_intersect -- intersect two unate covers
+ *
+ * If largest_only is TRUE, then only the largest cube(s) are returned
+ */
+
+#define MAGIC 500 /* save 500 cubes before containment */
+
+pset_family unate_intersect(A, B, largest_only)
+pset_family A, B;
+bool largest_only;
+{
+ register pset pi, pj, lasti, lastj, pt;
+ pset_family T, Tsave;
+ bool save;
+ int maxord, ord;
+
+ /* How large should each temporary result cover be ? */
+ T = sf_new(MAGIC, A->sf_size);
+ Tsave = NULL;
+ maxord = 0;
+ pt = T->data;
+
+ /* Form pairwise intersection of each set of A with each cube of B */
+ foreach_set(A, lasti, pi) {
+
+ foreach_set(B, lastj, pj) {
+
+ save = set_andp(pt, pi, pj);
+
+ /* Check if we want the largest only */
+ if (save && largest_only) {
+ if ((ord = set_ord(pt)) > maxord) {
+ /* discard Tsave and T */
+ if (Tsave != NULL) {
+ sf_free(Tsave);
+ Tsave = NULL;
+ }
+ pt = T->data;
+ T->count = 0;
+ /* Re-create pt (which was just thrown away) */
+ (void) set_and(pt, pi, pj);
+ maxord = ord;
+ } else if (ord < maxord) {
+ save = FALSE;
+ }
+ }
+
+ if (save) {
+ if (++T->count >= T->capacity) {
+ T = sf_contain(T);
+ Tsave = (Tsave == NULL) ? T : sf_union(Tsave, T);
+ T = sf_new(MAGIC, A->sf_size);
+ pt = T->data;
+ } else {
+ pt += T->wsize;
+ }
+ }
+ }
+ }
+
+
+ /* Contain the final result and merge it into Tsave */
+ T = sf_contain(T);
+ Tsave = (Tsave == NULL) ? T : sf_union(Tsave, T);
+
+ return Tsave;
+}
+
+/*
+ * abs_covered -- after selecting a new column for the selected set,
+ * create a new matrix which is only those rows which are still uncovered
+ */
+static pset_family
+abs_covered(A, pick)
+pset_family A;
+register int pick;
+{
+ register pset last, p, pdest;
+ register pset_family Aprime;
+
+ Aprime = sf_new(A->count, A->sf_size);
+ pdest = Aprime->data;
+ foreach_set(A, last, p)
+ if (! is_in_set(p, pick)) {
+ INLINEset_copy(pdest, p);
+ Aprime->count++;
+ pdest += Aprime->wsize;
+ }
+ return Aprime;
+}
+
+
+/*
+ * abs_covered_many -- after selecting many columns for ther selected set,
+ * create a new matrix which is only those rows which are still uncovered
+ */
+static pset_family
+abs_covered_many(A, pick_set)
+pset_family A;
+register pset pick_set;
+{
+ register pset last, p, pdest;
+ register pset_family Aprime;
+
+ Aprime = sf_new(A->count, A->sf_size);
+ pdest = Aprime->data;
+ foreach_set(A, last, p)
+ if (setp_disjoint(p, pick_set)) {
+ INLINEset_copy(pdest, p);
+ Aprime->count++;
+ pdest += Aprime->wsize;
+ }
+ return Aprime;
+}
+
+
+/*
+ * abs_select_restricted -- select the column of maximum column count which
+ * also belongs to the set "restrict"; weight each column of a set as
+ * 1 / (set_ord(p) - 1).
+ */
+static int
+abs_select_restricted(A, restrict)
+pset_family A;
+pset restrict;
+{
+ register int i, best_var, best_count, *count;
+
+ /* Sum the elements in these columns */
+ count = sf_count_restricted(A, restrict);
+
+ /* Find which variable has maximum weight */
+ best_var = -1;
+ best_count = 0;
+ for(i = 0; i < A->sf_size; i++) {
+ if (count[i] > best_count) {
+ best_var = i;
+ best_count = count[i];
+ }
+ }
+ FREE(count);
+
+ if (best_var == -1)
+ fatal("abs_select_restricted: should not have best_var == -1");
+
+ return best_var;
+}
diff --git a/src/misc/espresso/util_old.h b/src/misc/espresso/util_old.h
new file mode 100644
index 00000000..5451cbe9
--- /dev/null
+++ b/src/misc/espresso/util_old.h
@@ -0,0 +1,301 @@
+/*
+ * Revision Control Information
+ *
+ * $Source: /vol/opua/opua2/sis/sis-1.2/common/src/sis/util/RCS/util.h,v $
+ * $Author: sis $
+ * $Revision: 1.9 $
+ * $Date: 1993/06/07 21:04:07 $
+ *
+ */
+#ifndef UTIL_H
+#define UTIL_H
+
+#if defined(_IBMR2)
+#ifndef _POSIX_SOURCE
+#define _POSIX_SOURCE /* Argh! IBM strikes again */
+#endif
+#ifndef _ALL_SOURCE
+#define _ALL_SOURCE /* Argh! IBM strikes again */
+#endif
+#ifndef _ANSI_C_SOURCE
+#define _ANSI_C_SOURCE /* Argh! IBM strikes again */
+#endif
+#endif
+
+#if defined(__STDC__) || defined(sprite) || defined(_IBMR2) || defined(__osf__)
+#include <unistd.h>
+#endif
+
+#if defined(_IBMR2) && !defined(__STDC__)
+#define _BSD
+#endif
+
+#include "ansi.h" /* since some files don't include sis.h */
+
+/* This was taken out and defined at compile time in the SIS Makefile
+ that uses the OctTools. When the OctTools are used, USE_MM is defined,
+ because the OctTools contain libmm.a. Otherwise, USE_MM is not defined,
+ since the mm package is not distributed with SIS, only with Oct. */
+
+/* #define USE_MM */ /* choose libmm.a as the memory allocator */
+
+#define NIL(type) ((type *) 0)
+
+#ifdef USE_MM
+/*
+ * assumes the memory manager is libmm.a
+ * - allows malloc(0) or realloc(obj, 0)
+ * - catches out of memory (and calls MMout_of_memory())
+ * - catch free(0) and realloc(0, size) in the macros
+ */
+#define ALLOC(type, num) \
+ ((type *) malloc(sizeof(type) * (num)))
+#define REALLOC(type, obj, num) \
+ (obj) ? ((type *) realloc((char *) obj, sizeof(type) * (num))) : \
+ ((type *) malloc(sizeof(type) * (num)))
+#define FREE(obj) \
+ ((obj) ? (free((char *) (obj)), (obj) = 0) : 0)
+#else
+/*
+ * enforce strict semantics on the memory allocator
+ * - when in doubt, delete the '#define USE_MM' above
+ */
+#define ALLOC(type, num) \
+ ((type *) MMalloc((long) sizeof(type) * (long) (num)))
+#define REALLOC(type, obj, num) \
+ ((type *) MMrealloc((char *) (obj), (long) sizeof(type) * (long) (num)))
+#define FREE(obj) \
+ ((obj) ? (free((void *) (obj)), (obj) = 0) : 0)
+#endif
+
+
+/* Ultrix (and SABER) have 'fixed' certain functions which used to be int */
+#if defined(ultrix) || defined(SABER) || defined(aiws) || defined(__hpux) || defined(__STDC__) || defined(apollo)
+#define VOID_HACK void
+#else
+#define VOID_HACK int
+#endif
+
+
+/* No machines seem to have much of a problem with these */
+#include <stdio.h>
+#include <ctype.h>
+
+
+/* Some machines fail to define some functions in stdio.h */
+#if !defined(__STDC__) && !defined(sprite) && !defined(_IBMR2) && !defined(__osf__)
+extern FILE *popen(), *tmpfile();
+extern int pclose();
+#ifndef clearerr /* is a macro on many machines, but not all */
+extern VOID_HACK clearerr();
+#endif
+#ifndef rewind
+extern VOID_HACK rewind();
+#endif
+#endif
+
+#ifndef PORT_H
+#include <sys/types.h>
+#include <signal.h>
+#if defined(ultrix)
+#if defined(_SIZE_T_)
+#define ultrix4
+#else
+#if defined(SIGLOST)
+#define ultrix3
+#else
+#define ultrix2
+#endif
+#endif
+#endif
+#endif
+
+/* most machines don't give us a header file for these */
+#if defined(__STDC__) || defined(sprite) || defined(_IBMR2) || defined(__osf__) || defined(sunos4) || defined(__hpux)
+#include <stdlib.h>
+#if defined(__hpux)
+#include <errno.h> /* For perror() defininition */
+#endif /* __hpux */
+#else
+extern VOID_HACK abort(), free(), exit(), perror();
+extern char *getenv();
+#ifdef ultrix4
+extern void *malloc(), *realloc(), *calloc();
+#else
+extern char *malloc(), *realloc(), *calloc();
+#endif
+#if defined(aiws)
+extern int sprintf();
+#else
+#ifndef _IBMR2
+extern char *sprintf();
+#endif
+#endif
+extern int system();
+extern double atof();
+#endif
+
+#ifndef PORT_H
+#if defined(ultrix3) || defined(sunos4) || defined(_IBMR2) || defined(__STDC__)
+#define SIGNAL_FN void
+#else
+/* sequent, ultrix2, 4.3BSD (vax, hp), sunos3 */
+#define SIGNAL_FN int
+#endif
+#endif
+
+/* some call it strings.h, some call it string.h; others, also have memory.h */
+#if defined(__STDC__) || defined(sprite)
+#include <string.h>
+#else
+#if defined(ultrix4) || defined(__hpux)
+#include <strings.h>
+#else
+#if defined(_IBMR2) || defined(__osf__)
+#include<string.h>
+#include<strings.h>
+#else
+/* ANSI C string.h -- 1/11/88 Draft Standard */
+/* ugly, awful hack */
+#ifndef PORT_H
+extern char *strcpy(), *strncpy(), *strcat(), *strncat(), *strerror();
+extern char *strpbrk(), *strtok(), *strchr(), *strrchr(), *strstr();
+extern int strcoll(), strxfrm(), strncmp(), strlen(), strspn(), strcspn();
+extern char *memmove(), *memccpy(), *memchr(), *memcpy(), *memset();
+extern int memcmp(), strcmp();
+#endif
+#endif
+#endif
+#endif
+
+/* a few extras */
+#if defined(__hpux)
+#define random() lrand48()
+#define srandom(a) srand48(a)
+#define bzero(a,b) memset(a, 0, b)
+#else
+#if !defined(__osf__) && !defined(linux)
+/* these are defined as macros in stdlib.h */
+extern VOID_HACK srandom();
+extern long random();
+#endif
+#endif
+
+/* code from sis-1.3 commented out below
+#if defined(__STDC__) || defined(sprite)
+#include <assert.h>
+#else
+#ifndef NDEBUG
+#define assert(ex) {\
+ if (! (ex)) {\
+ (void) fprintf(stderr,\
+ "Assertion failed: file %s, line %d\n\"%s\"\n",\
+ __FILE__, __LINE__, "ex");\
+ (void) fflush(stdout);\
+ abort();\
+ }\
+}
+#else
+#define assert(ex) {ex;}
+#endif
+#endif
+*/
+
+ /* Sunil 5/3/97:
+ sis-1.4: dont let the assert call go to the OS, since
+ much of the code in SIS has actual computation done in
+ the assert function. %$#$@@#! The OS version of assert
+ will do nothing if NDEBUG is set. We cant let that happen...
+ */
+# ifdef NDEBUG
+# define assert(ex) {ex;}
+# else
+# define assert(ex) {\
+ if (! (ex)) {\
+ (void) fprintf(stderr,\
+ "Assertion failed: file %s, line %d\n\"%s\"\n",\
+ __FILE__, __LINE__, "ex");\
+ (void) fflush(stdout);\
+ abort();\
+ }\
+}
+# endif
+
+
+#define fail(why) {\
+ (void) fprintf(stderr, "Fatal error: file %s, line %d\n%s\n",\
+ __FILE__, __LINE__, why);\
+ (void) fflush(stdout);\
+ abort();\
+}
+
+
+#ifdef lint
+#undef putc /* correct lint '_flsbuf' bug */
+#undef ALLOC /* allow for lint -h flag */
+#undef REALLOC
+#define ALLOC(type, num) (((type *) 0) + (num))
+#define REALLOC(type, obj, num) ((obj) + (num))
+#endif
+
+/*
+#if !defined(__osf__)
+#define MAXPATHLEN 1024
+#endif
+*/
+
+/* These arguably do NOT belong in util.h */
+#ifndef ABS
+#define ABS(a) ((a) < 0 ? -(a) : (a))
+#endif
+#ifndef MAX
+#define MAX(a,b) ((a) > (b) ? (a) : (b))
+#endif
+#ifndef MIN
+#define MIN(a,b) ((a) < (b) ? (a) : (b))
+#endif
+
+
+#ifndef USE_MM
+EXTERN void MMout_of_memory ARGS((long));
+EXTERN char *MMalloc ARGS((long));
+EXTERN char *MMrealloc ARGS((char *, long));
+EXTERN void MMfree ARGS((char *));
+#endif
+
+EXTERN void util_print_cpu_stats ARGS((FILE *));
+EXTERN long util_cpu_time ARGS((void));
+EXTERN void util_getopt_reset ARGS((void));
+EXTERN int util_getopt ARGS((int, char **, char *));
+EXTERN char *util_path_search ARGS((char *));
+EXTERN char *util_file_search ARGS((char *, char *, char *));
+EXTERN int util_pipefork ARGS((char **, FILE **, FILE **, int *));
+EXTERN char *util_print_time ARGS((long));
+EXTERN int util_save_image ARGS((char *, char *));
+EXTERN char *util_strsav ARGS((char *));
+EXTERN int util_do_nothing ARGS((void));
+EXTERN char *util_tilde_expand ARGS((char *));
+EXTERN char *util_tempnam ARGS((char *, char *));
+EXTERN FILE *util_tmpfile ARGS((void));
+EXTERN long getSoftDataLimit();
+
+#define ptime() util_cpu_time()
+#define print_time(t) util_print_time(t)
+
+/* util_getopt() global variables (ack !) */
+extern int util_optind;
+extern char *util_optarg;
+
+#include <math.h>
+#ifndef HUGE_VAL
+#ifndef HUGE
+#define HUGE 8.9884656743115790e+307
+#endif
+#define HUGE_VAL HUGE
+#endif
+#ifndef MAXINT
+#define MAXINT (1 << 30)
+#endif
+
+#include <varargs.h>
+#endif
diff --git a/src/misc/espresso/verify.c b/src/misc/espresso/verify.c
new file mode 100644
index 00000000..64342787
--- /dev/null
+++ b/src/misc/espresso/verify.c
@@ -0,0 +1,193 @@
+/*
+ * Revision Control Information
+ *
+ * $Source$
+ * $Author$
+ * $Revision$
+ * $Date$
+ *
+ */
+/*
+ */
+
+#include "espresso.h"
+
+/*
+ * verify -- check that all minterms of F are contained in (Fold u Dold)
+ * and that all minterms of Fold are contained in (F u Dold).
+ */
+bool verify(F, Fold, Dold)
+pcover F, Fold, Dold;
+{
+ pcube p, last, *FD;
+ bool verify_error = FALSE;
+
+ /* Make sure the function didn't grow too large */
+ FD = cube2list(Fold, Dold);
+ foreach_set(F, last, p)
+ if (! cube_is_covered(FD, p)) {
+ printf("some minterm in F is not covered by Fold u Dold\n");
+ verify_error = TRUE;
+ if (verbose_debug) printf("%s\n", pc1(p)); else break;
+ }
+ free_cubelist(FD);
+
+ /* Make sure minimized function covers the original function */
+ FD = cube2list(F, Dold);
+ foreach_set(Fold, last, p)
+ if (! cube_is_covered(FD, p)) {
+ printf("some minterm in Fold is not covered by F u Dold\n");
+ verify_error = TRUE;
+ if (verbose_debug) printf("%s\n", pc1(p)); else break;
+ }
+ free_cubelist(FD);
+
+ return verify_error;
+}
+
+
+
+/*
+ * PLA_verify -- verify that two PLA's are identical
+ *
+ * If names are given, row and column permutations are done to make
+ * the comparison meaningful.
+ *
+ */
+bool PLA_verify(PLA1, PLA2)
+pPLA PLA1, PLA2;
+{
+ /* Check if both have names given; if so, attempt to permute to
+ * match the names
+ */
+ if (PLA1->label != NULL && PLA1->label[0] != NULL &&
+ PLA2->label != NULL && PLA2->label[0] != NULL) {
+ PLA_permute(PLA1, PLA2);
+ } else {
+ (void) fprintf(stderr, "Warning: cannot permute columns without names\n");
+ return TRUE;
+ }
+
+ if (PLA1->F->sf_size != PLA2->F->sf_size) {
+ (void) fprintf(stderr, "PLA_verify: PLA's are not the same size\n");
+ return TRUE;
+ }
+
+ return verify(PLA2->F, PLA1->F, PLA1->D);
+}
+
+
+
+/*
+ * Permute the columns of PLA1 so that they match the order of PLA2
+ * Discard any columns of PLA1 which are not in PLA2
+ * Association is strictly by the names of the columns of the cover.
+ */
+PLA_permute(PLA1, PLA2)
+pPLA PLA1, PLA2;
+{
+ register int i, j, *permute, npermute;
+ register char *labi;
+ char **label;
+
+ /* determine which columns of PLA1 to save, and place these in the list
+ * "permute"; the order in this list is the final output order
+ */
+ npermute = 0;
+ permute = ALLOC(int, PLA2->F->sf_size);
+ for(i = 0; i < PLA2->F->sf_size; i++) {
+ labi = PLA2->label[i];
+ for(j = 0; j < PLA1->F->sf_size; j++) {
+ if (strcmp(labi, PLA1->label[j]) == 0) {
+ permute[npermute++] = j;
+ break;
+ }
+ }
+ }
+
+ /* permute columns */
+ if (PLA1->F != NULL) {
+ PLA1->F = sf_permute(PLA1->F, permute, npermute);
+ }
+ if (PLA1->R != NULL) {
+ PLA1->R = sf_permute(PLA1->R, permute, npermute);
+ }
+ if (PLA1->D != NULL) {
+ PLA1->D = sf_permute(PLA1->D, permute, npermute);
+ }
+
+ /* permute the labels */
+ label = ALLOC(char *, cube.size);
+ for(i = 0; i < npermute; i++) {
+ label[i] = PLA1->label[permute[i]];
+ }
+ for(i = npermute; i < cube.size; i++) {
+ label[i] = NULL;
+ }
+ FREE(PLA1->label);
+ PLA1->label = label;
+
+ FREE(permute);
+}
+
+
+
+/*
+ * check_consistency -- test that the ON-set, OFF-set and DC-set form
+ * a partition of the boolean space.
+ */
+bool check_consistency(PLA)
+pPLA PLA;
+{
+ bool verify_error = FALSE;
+ pcover T;
+
+ T = cv_intersect(PLA->F, PLA->D);
+ if (T->count == 0)
+ printf("ON-SET and DC-SET are disjoint\n");
+ else {
+ printf("Some minterm(s) belong to both the ON-SET and DC-SET !\n");
+ if (verbose_debug)
+ cprint(T);
+ verify_error = TRUE;
+ }
+ (void) fflush(stdout);
+ free_cover(T);
+
+ T = cv_intersect(PLA->F, PLA->R);
+ if (T->count == 0)
+ printf("ON-SET and OFF-SET are disjoint\n");
+ else {
+ printf("Some minterm(s) belong to both the ON-SET and OFF-SET !\n");
+ if (verbose_debug)
+ cprint(T);
+ verify_error = TRUE;
+ }
+ (void) fflush(stdout);
+ free_cover(T);
+
+ T = cv_intersect(PLA->D, PLA->R);
+ if (T->count == 0)
+ printf("DC-SET and OFF-SET are disjoint\n");
+ else {
+ printf("Some minterm(s) belong to both the OFF-SET and DC-SET !\n");
+ if (verbose_debug)
+ cprint(T);
+ verify_error = TRUE;
+ }
+ (void) fflush(stdout);
+ free_cover(T);
+
+ if (tautology(cube3list(PLA->F, PLA->D, PLA->R)))
+ printf("Union of ON-SET, OFF-SET and DC-SET is the universe\n");
+ else {
+ T = complement(cube3list(PLA->F, PLA->D, PLA->R));
+ printf("There are minterms left unspecified !\n");
+ if (verbose_debug)
+ cprint(T);
+ verify_error = TRUE;
+ free_cover(T);
+ }
+ (void) fflush(stdout);
+ return verify_error;
+}
diff --git a/src/misc/extra/extra.h b/src/misc/extra/extra.h
index f36b113f..314257a2 100644
--- a/src/misc/extra/extra.h
+++ b/src/misc/extra/extra.h
@@ -29,6 +29,10 @@
#ifndef __EXTRA_H__
#define __EXTRA_H__
+#ifdef __cplusplus
+extern "C" {
+#endif
+
#ifdef _WIN32
#define inline __inline // compatible with MS VS 6.0
#endif
@@ -37,9 +41,15 @@
/* Nested includes */
/*---------------------------------------------------------------------------*/
+// this include should be the first one in the list
+// it is used to catch memory leaks on Windows
+#include "leaks.h"
+
+#include <stdio.h>
+#include <stdlib.h>
#include <string.h>
+#include <assert.h>
#include <time.h>
-#include "util.h"
#include "st.h"
#include "cuddInt.h"
@@ -63,6 +73,15 @@
/* Macro declarations */
/*---------------------------------------------------------------------------*/
+typedef unsigned char uint8;
+typedef unsigned short uint16;
+typedef unsigned int uint32;
+#ifdef WIN32
+typedef unsigned __int64 uint64;
+#else
+typedef unsigned long long uint64;
+#endif
+
/* constants of the manager */
#define b0 Cudd_Not((dd)->one)
#define b1 (dd)->one
@@ -91,13 +110,59 @@
#ifndef PRT
#define PRT(a,t) printf("%s = ", (a)); printf("%6.2f sec\n", (float)(t)/(float)(CLOCKS_PER_SEC))
+#define PRTn(a,t) printf("%s = ", (a)); printf("%6.2f sec ", (float)(t)/(float)(CLOCKS_PER_SEC))
+#endif
+
+#ifndef PRTP
+#define PRTP(a,t,T) printf("%s = ", (a)); printf("%6.2f sec (%6.2f %%)\n", (float)(t)/(float)(CLOCKS_PER_SEC), (T)? 100.0*(t)/(T) : 0.0)
#endif
/*===========================================================================*/
/* Various Utilities */
/*===========================================================================*/
-/*=== extraUtilBdd.c ========================================================*/
+/*=== extraBddAuto.c ========================================================*/
+
+extern DdNode * Extra_bddSpaceFromFunctionFast( DdManager * dd, DdNode * bFunc );
+extern DdNode * Extra_bddSpaceFromFunction( DdManager * dd, DdNode * bF, DdNode * bG );
+extern DdNode * extraBddSpaceFromFunction( DdManager * dd, DdNode * bF, DdNode * bG );
+extern DdNode * Extra_bddSpaceFromFunctionPos( DdManager * dd, DdNode * bFunc );
+extern DdNode * extraBddSpaceFromFunctionPos( DdManager * dd, DdNode * bFunc );
+extern DdNode * Extra_bddSpaceFromFunctionNeg( DdManager * dd, DdNode * bFunc );
+extern DdNode * extraBddSpaceFromFunctionNeg( DdManager * dd, DdNode * bFunc );
+
+extern DdNode * Extra_bddSpaceCanonVars( DdManager * dd, DdNode * bSpace );
+extern DdNode * extraBddSpaceCanonVars( DdManager * dd, DdNode * bSpace );
+
+extern DdNode * Extra_bddSpaceEquations( DdManager * dd, DdNode * bSpace );
+extern DdNode * Extra_bddSpaceEquationsNeg( DdManager * dd, DdNode * bSpace );
+extern DdNode * extraBddSpaceEquationsNeg( DdManager * dd, DdNode * bSpace );
+extern DdNode * Extra_bddSpaceEquationsPos( DdManager * dd, DdNode * bSpace );
+extern DdNode * extraBddSpaceEquationsPos( DdManager * dd, DdNode * bSpace );
+
+extern DdNode * Extra_bddSpaceFromMatrixPos( DdManager * dd, DdNode * zA );
+extern DdNode * extraBddSpaceFromMatrixPos( DdManager * dd, DdNode * zA );
+extern DdNode * Extra_bddSpaceFromMatrixNeg( DdManager * dd, DdNode * zA );
+extern DdNode * extraBddSpaceFromMatrixNeg( DdManager * dd, DdNode * zA );
+
+extern DdNode * Extra_bddSpaceReduce( DdManager * dd, DdNode * bFunc, DdNode * bCanonVars );
+extern DdNode ** Extra_bddSpaceExorGates( DdManager * dd, DdNode * bFuncRed, DdNode * zEquations );
+
+/*=== extraBddCas.c =============================================================*/
+
+/* performs the binary encoding of the set of function using the given vars */
+extern DdNode * Extra_bddEncodingBinary( DdManager * dd, DdNode ** pbFuncs, int nFuncs, DdNode ** pbVars, int nVars );
+/* solves the column encoding problem using a sophisticated method */
+extern DdNode * Extra_bddEncodingNonStrict( DdManager * dd, DdNode ** pbColumns, int nColumns, DdNode * bVarsCol, DdNode ** pCVars, int nMulti, int * pSimple );
+/* collects the nodes under the cut and, for each node, computes the sum of paths leading to it from the root */
+extern st_table * Extra_bddNodePathsUnderCut( DdManager * dd, DdNode * bFunc, int CutLevel );
+/* collects the nodes under the cut starting from the given set of ADD nodes */
+extern int Extra_bddNodePathsUnderCutArray( DdManager * dd, DdNode ** paNodes, DdNode ** pbCubes, int nNodes, DdNode ** paNodesRes, DdNode ** pbCubesRes, int CutLevel );
+/* find the profile of a DD (the number of edges crossing each level) */
+extern int Extra_ProfileWidth( DdManager * dd, DdNode * F, int * Profile, int CutLevel );
+
+/*=== extraBddMisc.c ========================================================*/
+
extern DdNode * Extra_TransferPermute( DdManager * ddSource, DdManager * ddDestination, DdNode * f, int * Permute );
extern DdNode * Extra_TransferLevelByLevel( DdManager * ddSource, DdManager * ddDestination, DdNode * f );
extern DdNode * Extra_bddRemapUp( DdManager * dd, DdNode * bF );
@@ -116,6 +181,21 @@ extern int * Extra_VectorSupportArray( DdManager * dd, DdNode ** F, int n
extern DdNode * Extra_bddFindOneCube( DdManager * dd, DdNode * bF );
extern DdNode * Extra_bddGetOneCube( DdManager * dd, DdNode * bFunc );
extern DdNode * Extra_bddComputeRangeCube( DdManager * dd, int iStart, int iStop );
+extern DdNode * Extra_bddBitsToCube( DdManager * dd, int Code, int CodeWidth, DdNode ** pbVars, int fMsbFirst );
+extern DdNode * Extra_bddSupportNegativeCube( DdManager * dd, DdNode * f );
+extern int Extra_bddIsVar( DdNode * bFunc );
+extern DdNode * Extra_bddCreateAnd( DdManager * dd, int nVars );
+extern DdNode * Extra_bddCreateOr( DdManager * dd, int nVars );
+extern DdNode * Extra_bddCreateExor( DdManager * dd, int nVars );
+extern DdNode * Extra_zddPrimes( DdManager * dd, DdNode * F );
+extern void Extra_bddPermuteArray( DdManager * dd, DdNode ** bNodesIn, DdNode ** bNodesOut, int nNodes, int *permut );
+
+/*=== extraBddKmap.c ================================================================*/
+
+/* displays the Karnaugh Map of a function */
+extern void Extra_PrintKMap( FILE * pFile, DdManager * dd, DdNode * OnSet, DdNode * OffSet, int nVars, DdNode ** XVars, int fSuppType, char ** pVarNames );
+/* displays the Karnaugh Map of a relation */
+extern void Extra_PrintKMapRelation( FILE * pFile, DdManager * dd, DdNode * OnSet, DdNode * OffSet, int nXVars, int nYVars, DdNode ** XVars, DdNode ** YVars );
/*=== extraBddSymm.c =================================================================*/
@@ -168,6 +248,46 @@ extern DdNode * extraZddTuplesFromBdd( DdManager * dd, DdNode * bVarsK, DdNo
extern DdNode * Extra_zddSelectOneSubset( DdManager * dd, DdNode * zS );
extern DdNode * extraZddSelectOneSubset( DdManager * dd, DdNode * zS );
+/*=== extraBddUnate.c =================================================================*/
+
+typedef struct Extra_UnateVar_t_ Extra_UnateVar_t;
+struct Extra_UnateVar_t_ {
+ unsigned iVar : 30; // index of the variable
+ unsigned Pos : 1; // 1 if positive unate
+ unsigned Neg : 1; // 1 if negative unate
+};
+
+typedef struct Extra_UnateInfo_t_ Extra_UnateInfo_t;
+struct Extra_UnateInfo_t_ {
+ int nVars; // the number of variables in the support
+ int nVarsMax; // the number of variables in the DD manager
+ int nUnate; // the number of unate variables
+ Extra_UnateVar_t * pVars; // the array of variables present in the support
+};
+
+/* allocates the data structure */
+extern Extra_UnateInfo_t * Extra_UnateInfoAllocate( int nVars );
+/* deallocates the data structure */
+extern void Extra_UnateInfoDissolve( Extra_UnateInfo_t * );
+/* print the contents the data structure */
+extern void Extra_UnateInfoPrint( Extra_UnateInfo_t * );
+/* converts the ZDD into the Extra_SymmInfo_t structure */
+extern Extra_UnateInfo_t * Extra_UnateInfoCreateFromZdd( DdManager * dd, DdNode * zUnate, DdNode * bVars );
+/* naive check of unateness of one variable */
+extern int Extra_bddCheckUnateNaive( DdManager * dd, DdNode * bF, int iVar );
+
+/* computes the unateness information for the function */
+extern Extra_UnateInfo_t * Extra_UnateComputeFast( DdManager * dd, DdNode * bFunc );
+extern Extra_UnateInfo_t * Extra_UnateComputeSlow( DdManager * dd, DdNode * bFunc );
+
+/* computes the classical symmetry information as a ZDD */
+extern DdNode * Extra_zddUnateInfoCompute( DdManager * dd, DdNode * bF, DdNode * bVars );
+extern DdNode * extraZddUnateInfoCompute( DdManager * dd, DdNode * bF, DdNode * bVars );
+
+/* converts a set of variables into a set of singleton subsets */
+extern DdNode * Extra_zddGetSingletonsBoth( DdManager * dd, DdNode * bVars );
+extern DdNode * extraZddGetSingletonsBoth( DdManager * dd, DdNode * bVars );
+
/*=== extraUtilBitMatrix.c ================================================================*/
typedef struct Extra_BitMat_t_ Extra_BitMat_t;
@@ -191,7 +311,7 @@ extern int Extra_BitMatrixIsClique( Extra_BitMat_t * p );
/*=== extraUtilFile.c ========================================================*/
extern char * Extra_FileGetSimilarName( char * pFileNameWrong, char * pS1, char * pS2, char * pS3, char * pS4, char * pS5 );
-extern int Extra_FileNameCheckExtension( char * FileName, char * Extension );
+extern char * Extra_FileNameExtension( char * FileName );
extern char * Extra_FileNameAppend( char * pBase, char * pSuffix );
extern char * Extra_FileNameGeneric( char * FileName );
extern int Extra_FileSize( char * pFileName );
@@ -200,6 +320,9 @@ extern char * Extra_TimeStamp();
extern char * Extra_StringAppend( char * pStrGiven, char * pStrAdd );
extern unsigned Extra_ReadBinary( char * Buffer );
extern void Extra_PrintBinary( FILE * pFile, unsigned Sign[], int nBits );
+extern int Extra_ReadHexadecimal( unsigned Sign[], char * pString, int nVars );
+extern void Extra_PrintHexadecimal( FILE * pFile, unsigned Sign[], int nVars );
+extern void Extra_PrintHexadecimalString( char * pString, unsigned Sign[], int nVars );
extern void Extra_PrintHex( FILE * pFile, unsigned uTruth, int nVars );
extern void Extra_PrintSymbols( FILE * pFile, char Char, int nTimes, int fPrintNewLine );
@@ -223,26 +346,28 @@ typedef struct Extra_MmStep_t_ Extra_MmStep_t;
// fixed-size-block memory manager
extern Extra_MmFixed_t * Extra_MmFixedStart( int nEntrySize );
-extern void Extra_MmFixedStop( Extra_MmFixed_t * p, int fVerbose );
+extern void Extra_MmFixedStop( Extra_MmFixed_t * p );
extern char * Extra_MmFixedEntryFetch( Extra_MmFixed_t * p );
extern void Extra_MmFixedEntryRecycle( Extra_MmFixed_t * p, char * pEntry );
extern void Extra_MmFixedRestart( Extra_MmFixed_t * p );
extern int Extra_MmFixedReadMemUsage( Extra_MmFixed_t * p );
+extern int Extra_MmFixedReadMaxEntriesUsed( Extra_MmFixed_t * p );
// flexible-size-block memory manager
extern Extra_MmFlex_t * Extra_MmFlexStart();
-extern void Extra_MmFlexStop( Extra_MmFlex_t * p, int fVerbose );
+extern void Extra_MmFlexStop( Extra_MmFlex_t * p );
+extern void Extra_MmFlexPrint( Extra_MmFlex_t * p );
extern char * Extra_MmFlexEntryFetch( Extra_MmFlex_t * p, int nBytes );
extern int Extra_MmFlexReadMemUsage( Extra_MmFlex_t * p );
// hierarchical memory manager
extern Extra_MmStep_t * Extra_MmStepStart( int nSteps );
-extern void Extra_MmStepStop( Extra_MmStep_t * p, int fVerbose );
+extern void Extra_MmStepStop( Extra_MmStep_t * p );
extern char * Extra_MmStepEntryFetch( Extra_MmStep_t * p, int nBytes );
extern void Extra_MmStepEntryRecycle( Extra_MmStep_t * p, char * pEntry, int nBytes );
extern int Extra_MmStepReadMemUsage( Extra_MmStep_t * p );
/*=== extraUtilMisc.c ========================================================*/
-/* finds the smallest integer larger of equal than the logarithm. */
+/* 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 );
@@ -252,6 +377,8 @@ extern int Extra_Power3( int Num );
/* the number of combinations of k elements out of n */
extern int Extra_NumCombinations( int k, int n );
extern int * Extra_DeriveRadixCode( int Number, int Radix, int nDigits );
+/* counts the number of 1s in the bitstring */
+extern int Extra_CountOnes( unsigned char * pBytes, int nBytes );
/* the factorial of number */
extern int Extra_Factorial( int n );
/* the permutation of the given number of elements */
@@ -272,11 +399,14 @@ extern void Extra_Truth4VarN( unsigned short ** puCanons, char *** puPhas
extern unsigned short Extra_TruthPerm4One( unsigned uTruth, int Phase );
extern unsigned Extra_TruthPerm5One( unsigned uTruth, int Phase );
extern void Extra_TruthPerm6One( unsigned * uTruth, int Phase, unsigned * uTruthRes );
+extern void Extra_TruthExpand( int nVars, int nWords, unsigned * puTruth, unsigned uPhase, unsigned * puTruthR );
/* precomputing tables for permutation mapping */
extern void ** Extra_ArrayAlloc( int nCols, int nRows, int Size );
extern unsigned short ** Extra_TruthPerm43();
extern unsigned ** Extra_TruthPerm53();
extern unsigned ** Extra_TruthPerm54();
+/* bubble sort for small number of entries */
+extern void Extra_BubbleSort( int Order[], int Costs[], int nSize, int fIncreasing );
/* for independence from CUDD */
extern unsigned int Cudd_PrimeCopy( unsigned int p );
@@ -294,31 +424,203 @@ extern void Extra_ProgressBarStop( ProgressBar * p );
extern void Extra_ProgressBarUpdate_int( ProgressBar * p, int nItemsCur, char * pString );
static inline void Extra_ProgressBarUpdate( ProgressBar * p, int nItemsCur, char * pString )
-{ if ( nItemsCur < *((int*)p) ) return; Extra_ProgressBarUpdate_int(p, nItemsCur, pString); }
-
-/*=== extraUtilIntVec.c ================================================================*/
-
-typedef struct Extra_IntVec_t_ Extra_IntVec_t;
-extern Extra_IntVec_t * Extra_IntVecAlloc( int nCap );
-extern Extra_IntVec_t * Extra_IntVecAllocArray( int * pArray, int nSize );
-extern Extra_IntVec_t * Extra_IntVecAllocArrayCopy( int * pArray, int nSize );
-extern Extra_IntVec_t * Extra_IntVecDup( Extra_IntVec_t * pVec );
-extern Extra_IntVec_t * Extra_IntVecDupArray( Extra_IntVec_t * pVec );
-extern void Extra_IntVecFree( Extra_IntVec_t * p );
-extern void Extra_IntVecFill( Extra_IntVec_t * p, int nSize, int Entry );
-extern int * Extra_IntVecReleaseArray( Extra_IntVec_t * p );
-extern int * Extra_IntVecReadArray( Extra_IntVec_t * p );
-extern int Extra_IntVecReadSize( Extra_IntVec_t * p );
-extern int Extra_IntVecReadEntry( Extra_IntVec_t * p, int i );
-extern int Extra_IntVecReadEntryLast( Extra_IntVec_t * p );
-extern void Extra_IntVecWriteEntry( Extra_IntVec_t * p, int i, int Entry );
-extern void Extra_IntVecGrow( Extra_IntVec_t * p, int nCapMin );
-extern void Extra_IntVecShrink( Extra_IntVec_t * p, int nSizeNew );
-extern void Extra_IntVecClear( Extra_IntVec_t * p );
-extern void Extra_IntVecPush( Extra_IntVec_t * p, int Entry );
-extern int Extra_IntVecPop( Extra_IntVec_t * p );
-extern void Extra_IntVecSort( Extra_IntVec_t * p );
+{ if ( p && nItemsCur < *((int*)p) ) return; Extra_ProgressBarUpdate_int(p, nItemsCur, pString); }
+
+/*=== extraUtilTruth.c ================================================================*/
+
+static inline int Extra_Float2Int( float Val ) { return *((int *)&Val); }
+static inline float Extra_Int2Float( int Num ) { return *((float *)&Num); }
+static inline int Extra_BitWordNum( int nBits ) { return nBits/(8*sizeof(unsigned)) + ((nBits%(8*sizeof(unsigned))) > 0); }
+static inline int Extra_TruthWordNum( int nVars ) { return nVars <= 5 ? 1 : (1 << (nVars - 5)); }
+
+static inline void Extra_TruthSetBit( unsigned * p, int Bit ) { p[Bit>>5] |= (1<<(Bit & 31)); }
+static inline void Extra_TruthXorBit( unsigned * p, int Bit ) { p[Bit>>5] ^= (1<<(Bit & 31)); }
+static inline int Extra_TruthHasBit( unsigned * p, int Bit ) { return (p[Bit>>5] & (1<<(Bit & 31))) > 0; }
+
+static inline int Extra_WordCountOnes( unsigned uWord )
+{
+ uWord = (uWord & 0x55555555) + ((uWord>>1) & 0x55555555);
+ uWord = (uWord & 0x33333333) + ((uWord>>2) & 0x33333333);
+ uWord = (uWord & 0x0F0F0F0F) + ((uWord>>4) & 0x0F0F0F0F);
+ uWord = (uWord & 0x00FF00FF) + ((uWord>>8) & 0x00FF00FF);
+ return (uWord & 0x0000FFFF) + (uWord>>16);
+}
+static inline int Extra_TruthCountOnes( unsigned * pIn, int nVars )
+{
+ int w, Counter = 0;
+ for ( w = Extra_TruthWordNum(nVars)-1; w >= 0; w-- )
+ Counter += Extra_WordCountOnes(pIn[w]);
+ return Counter;
+}
+static inline int Extra_TruthIsEqual( unsigned * pIn0, unsigned * pIn1, int nVars )
+{
+ int w;
+ for ( w = Extra_TruthWordNum(nVars)-1; w >= 0; w-- )
+ if ( pIn0[w] != pIn1[w] )
+ return 0;
+ return 1;
+}
+static inline int Extra_TruthIsConst0( unsigned * pIn, int nVars )
+{
+ int w;
+ for ( w = Extra_TruthWordNum(nVars)-1; w >= 0; w-- )
+ if ( pIn[w] )
+ return 0;
+ return 1;
+}
+static inline int Extra_TruthIsConst1( unsigned * pIn, int nVars )
+{
+ int w;
+ for ( w = Extra_TruthWordNum(nVars)-1; w >= 0; w-- )
+ if ( pIn[w] != ~(unsigned)0 )
+ return 0;
+ return 1;
+}
+static inline int Extra_TruthIsImply( unsigned * pIn1, unsigned * pIn2, int nVars )
+{
+ int w;
+ for ( w = Extra_TruthWordNum(nVars)-1; w >= 0; w-- )
+ if ( pIn1[w] & ~pIn2[w] )
+ return 0;
+ return 1;
+}
+static inline void Extra_TruthCopy( unsigned * pOut, unsigned * pIn, int nVars )
+{
+ int w;
+ for ( w = Extra_TruthWordNum(nVars)-1; w >= 0; w-- )
+ pOut[w] = pIn[w];
+}
+static inline void Extra_TruthClear( unsigned * pOut, int nVars )
+{
+ int w;
+ for ( w = Extra_TruthWordNum(nVars)-1; w >= 0; w-- )
+ pOut[w] = 0;
+}
+static inline void Extra_TruthFill( unsigned * pOut, int nVars )
+{
+ int w;
+ for ( w = Extra_TruthWordNum(nVars)-1; w >= 0; w-- )
+ pOut[w] = ~(unsigned)0;
+}
+static inline void Extra_TruthNot( unsigned * pOut, unsigned * pIn, int nVars )
+{
+ int w;
+ for ( w = Extra_TruthWordNum(nVars)-1; w >= 0; w-- )
+ pOut[w] = ~pIn[w];
+}
+static inline void Extra_TruthAnd( unsigned * pOut, unsigned * pIn0, unsigned * pIn1, int nVars )
+{
+ int w;
+ for ( w = Extra_TruthWordNum(nVars)-1; w >= 0; w-- )
+ pOut[w] = pIn0[w] & pIn1[w];
+}
+static inline void Extra_TruthOr( unsigned * pOut, unsigned * pIn0, unsigned * pIn1, int nVars )
+{
+ int w;
+ for ( w = Extra_TruthWordNum(nVars)-1; w >= 0; w-- )
+ pOut[w] = pIn0[w] | pIn1[w];
+}
+static inline void Extra_TruthSharp( unsigned * pOut, unsigned * pIn0, unsigned * pIn1, int nVars )
+{
+ int w;
+ for ( w = Extra_TruthWordNum(nVars)-1; w >= 0; w-- )
+ pOut[w] = pIn0[w] & ~pIn1[w];
+}
+static inline void Extra_TruthNand( unsigned * pOut, unsigned * pIn0, unsigned * pIn1, int nVars )
+{
+ int w;
+ for ( w = Extra_TruthWordNum(nVars)-1; w >= 0; w-- )
+ pOut[w] = ~(pIn0[w] & pIn1[w]);
+}
+static inline void Extra_TruthAndPhase( unsigned * pOut, unsigned * pIn0, unsigned * pIn1, int nVars, int fCompl0, int fCompl1 )
+{
+ int w;
+ if ( fCompl0 && fCompl1 )
+ {
+ for ( w = Extra_TruthWordNum(nVars)-1; w >= 0; w-- )
+ pOut[w] = ~(pIn0[w] | pIn1[w]);
+ }
+ else if ( fCompl0 && !fCompl1 )
+ {
+ for ( w = Extra_TruthWordNum(nVars)-1; w >= 0; w-- )
+ pOut[w] = ~pIn0[w] & pIn1[w];
+ }
+ else if ( !fCompl0 && fCompl1 )
+ {
+ for ( w = Extra_TruthWordNum(nVars)-1; w >= 0; w-- )
+ pOut[w] = pIn0[w] & ~pIn1[w];
+ }
+ else // if ( !fCompl0 && !fCompl1 )
+ {
+ for ( w = Extra_TruthWordNum(nVars)-1; w >= 0; w-- )
+ pOut[w] = pIn0[w] & pIn1[w];
+ }
+}
+
+extern unsigned ** Extra_TruthElementary( int nVars );
+extern void Extra_TruthSwapAdjacentVars( unsigned * pOut, unsigned * pIn, int nVars, int Start );
+extern void Extra_TruthStretch( unsigned * pOut, unsigned * pIn, int nVars, int nVarsAll, unsigned Phase );
+extern void Extra_TruthShrink( unsigned * pOut, unsigned * pIn, int nVars, int nVarsAll, unsigned Phase );
+extern int Extra_TruthVarInSupport( unsigned * pTruth, int nVars, int iVar );
+extern int Extra_TruthSupportSize( unsigned * pTruth, int nVars );
+extern int Extra_TruthSupport( unsigned * pTruth, int nVars );
+extern void Extra_TruthCofactor0( unsigned * pTruth, int nVars, int iVar );
+extern void Extra_TruthCofactor1( unsigned * pTruth, int nVars, int iVar );
+extern void Extra_TruthExist( unsigned * pTruth, int nVars, int iVar );
+extern void Extra_TruthForall( unsigned * pTruth, int nVars, int iVar );
+extern void Extra_TruthMux( unsigned * pOut, unsigned * pCof0, unsigned * pCof1, int nVars, int iVar );
+extern void Extra_TruthChangePhase( unsigned * pTruth, int nVars, int iVar );
+extern int Extra_TruthMinCofSuppOverlap( unsigned * pTruth, int nVars, int * pVarMin );
+extern void Extra_TruthCountOnesInCofs( unsigned * pTruth, int nVars, short * pStore );
+extern unsigned Extra_TruthHash( unsigned * pIn, int nWords );
+extern unsigned Extra_TruthSemiCanonicize( unsigned * pInOut, unsigned * pAux, int nVars, char * pCanonPerm, short * pStore );
+
+/*=== extraUtilUtil.c ================================================================*/
+
+#ifndef ABS
+#define ABS(a) ((a) < 0 ? -(a) : (a))
+#endif
+
+#ifndef MAX
+#define MAX(a,b) ((a) > (b) ? (a) : (b))
+#endif
+
+#ifndef MIN
+#define MIN(a,b) ((a) < (b) ? (a) : (b))
+#endif
+
+#ifndef ALLOC
+#define ALLOC(type, num) ((type *) malloc(sizeof(type) * (num)))
+#endif
+
+#ifndef FREE
+#define FREE(obj) ((obj) ? (free((char *) (obj)), (obj) = 0) : 0)
+#endif
+
+#ifndef REALLOC
+#define REALLOC(type, obj, num) \
+ ((obj) ? ((type *) realloc((char *)(obj), sizeof(type) * (num))) : \
+ ((type *) malloc(sizeof(type) * (num))))
+#endif
+
+
+extern long Extra_CpuTime();
+extern int Extra_GetSoftDataLimit();
+extern void Extra_UtilGetoptReset();
+extern int Extra_UtilGetopt( int argc, char *argv[], char *optstring );
+extern char * Extra_UtilPrintTime( long t );
+extern char * Extra_UtilStrsav( char *s );
+extern char * Extra_UtilTildeExpand( char *fname );
+extern char * Extra_UtilFileSearch( char *file, char *path, char *mode );
+extern void (*Extra_UtilMMoutOfMemory)();
+
+extern char * globalUtilOptarg;
+extern int globalUtilOptind;
/**AutomaticEnd***************************************************************/
+#ifdef __cplusplus
+}
+#endif
+
#endif /* __EXTRA_H__ */
diff --git a/src/misc/extra/extraBddAuto.c b/src/misc/extra/extraBddAuto.c
new file mode 100644
index 00000000..21a969ba
--- /dev/null
+++ b/src/misc/extra/extraBddAuto.c
@@ -0,0 +1,1558 @@
+/**CFile****************************************************************
+
+ FileName [extraBddAuto.c]
+
+ PackageName [extra]
+
+ Synopsis [Computation of autosymmetries.]
+
+ Author [Alan Mishchenko]
+
+ Affiliation [UC Berkeley]
+
+ Date [Ver. 2.0. Started - September 1, 2003.]
+
+ Revision [$Id: extraBddAuto.c,v 1.0 2003/05/21 18:03:50 alanmi Exp $]
+
+***********************************************************************/
+
+#include "extra.h"
+
+/*---------------------------------------------------------------------------*/
+/* Constant declarations */
+/*---------------------------------------------------------------------------*/
+
+/*---------------------------------------------------------------------------*/
+/* Stucture declarations */
+/*---------------------------------------------------------------------------*/
+
+/*---------------------------------------------------------------------------*/
+/* Type declarations */
+/*---------------------------------------------------------------------------*/
+
+/*---------------------------------------------------------------------------*/
+/* Variable declarations */
+/*---------------------------------------------------------------------------*/
+
+/*---------------------------------------------------------------------------*/
+/* Macro declarations */
+/*---------------------------------------------------------------------------*/
+
+
+/**AutomaticStart*************************************************************/
+
+/*---------------------------------------------------------------------------*/
+/* Static function prototypes */
+/*---------------------------------------------------------------------------*/
+
+/**AutomaticEnd***************************************************************/
+
+
+/*
+ LinearSpace(f) = Space(f,f)
+
+ Space(f,g)
+ {
+ if ( f = const )
+ {
+ if ( f = g ) return 1;
+ else return 0;
+ }
+ if ( g = const ) return 0;
+ return x' * Space(fx',gx') * Space(fx,gx) + x * Space(fx',gx) * Space(fx,gx');
+ }
+
+ Equations(s) = Pos(s) + Neg(s);
+
+ Pos(s)
+ {
+ if ( s = 0 ) return 1;
+ if ( s = 1 ) return 0;
+ if ( sx'= 0 ) return Pos(sx) + x;
+ if ( sx = 0 ) return Pos(sx');
+ return 1 * [Pos(sx') & Pos(sx)] + x * [Pos(sx') & Neg(sx)];
+ }
+
+ Neg(s)
+ {
+ if ( s = 0 ) return 1;
+ if ( s = 1 ) return 0;
+ if ( sx'= 0 ) return Neg(sx);
+ if ( sx = 0 ) return Neg(sx') + x;
+ return 1 * [Neg(sx') & Neg(sx)] + x * [Neg(sx') & Pos(sx)];
+ }
+
+
+ SpaceP(A)
+ {
+ if ( A = 0 ) return 1;
+ if ( A = 1 ) return 1;
+ return x' * SpaceP(Ax') * SpaceP(Ax) + x * SpaceP(Ax') * SpaceN(Ax);
+ }
+
+ SpaceN(A)
+ {
+ if ( A = 0 ) return 1;
+ if ( A = 1 ) return 0;
+ return x' * SpaceN(Ax') * SpaceN(Ax) + x * SpaceN(Ax') * SpaceP(Ax);
+ }
+
+
+ LinInd(A)
+ {
+ if ( A = const ) return 1;
+ if ( !LinInd(Ax') ) return 0;
+ if ( !LinInd(Ax) ) return 0;
+ if ( LinSumOdd(Ax') & LinSumEven(Ax) != 0 ) return 0;
+ if ( LinSumEven(Ax') & LinSumEven(Ax) != 0 ) return 0;
+ return 1;
+ }
+
+ LinSumOdd(A)
+ {
+ if ( A = 0 ) return 0; // Odd0 ---e-- Odd1
+ if ( A = 1 ) return 1; // \ o
+ Odd0 = LinSumOdd(Ax'); // x is absent // \
+ Even0 = LinSumEven(Ax'); // x is absent // / o
+ Odd1 = LinSumOdd(Ax); // x is present // Even0 ---e-- Even1
+ Even1 = LinSumEven(Ax); // x is absent
+ return 1 * [Odd0 + ExorP(Odd0, Even1)] + x * [Odd1 + ExorP(Odd1, Even0)];
+ }
+
+ LinSumEven(A)
+ {
+ if ( A = 0 ) return 0;
+ if ( A = 1 ) return 0;
+ Odd0 = LinSumOdd(Ax'); // x is absent
+ Even0 = LinSumEven(Ax'); // x is absent
+ Odd1 = LinSumOdd(Ax); // x is present
+ Even1 = LinSumEven(Ax); // x is absent
+ return 1 * [Even0 + Even1 + ExorP(Even0, Even1)] + x * [ExorP(Odd0, Odd1)];
+ }
+
+*/
+
+/*---------------------------------------------------------------------------*/
+/* Definition of exported functions */
+/*---------------------------------------------------------------------------*/
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+DdNode * Extra_bddSpaceFromFunctionFast( DdManager * dd, DdNode * bFunc )
+{
+ int * pSupport;
+ int * pPermute;
+ int * pPermuteBack;
+ DdNode ** pCompose;
+ DdNode * bCube, * bTemp;
+ DdNode * bSpace, * bFunc1, * bFunc2, * bSpaceShift;
+ int nSupp, Counter;
+ int i, lev;
+
+ // get the support
+ pSupport = ALLOC( int, ddMax(dd->size,dd->sizeZ) );
+ Extra_SupportArray( dd, bFunc, pSupport );
+ nSupp = 0;
+ for ( i = 0; i < dd->size; i++ )
+ if ( pSupport[i] )
+ nSupp++;
+
+ // make sure the manager has enough variables
+ if ( 2*nSupp > dd->size )
+ {
+ printf( "Cannot derive linear space, because DD manager does not have enough variables.\n" );
+ fflush( stdout );
+ free( pSupport );
+ return NULL;
+ }
+
+ // create the permutation arrays
+ pPermute = ALLOC( int, dd->size );
+ pPermuteBack = ALLOC( int, dd->size );
+ pCompose = ALLOC( DdNode *, dd->size );
+ for ( i = 0; i < dd->size; i++ )
+ {
+ pPermute[i] = i;
+ pPermuteBack[i] = i;
+ pCompose[i] = dd->vars[i]; Cudd_Ref( pCompose[i] );
+ }
+
+ // remap the function in such a way that the variables are interleaved
+ Counter = 0;
+ bCube = b1; Cudd_Ref( bCube );
+ for ( lev = 0; lev < dd->size; lev++ )
+ if ( pSupport[ dd->invperm[lev] ] )
+ { // var "dd->invperm[lev]" on level "lev" should go to level 2*Counter;
+ pPermute[ dd->invperm[lev] ] = dd->invperm[2*Counter];
+ // var from level 2*Counter+1 should go back to the place of this var
+ pPermuteBack[ dd->invperm[2*Counter+1] ] = dd->invperm[lev];
+ // the permutation should be defined in such a way that variable
+ // on level 2*Counter is replaced by an EXOR of itself and var on the next level
+ Cudd_Deref( pCompose[ dd->invperm[2*Counter] ] );
+ pCompose[ dd->invperm[2*Counter] ] =
+ Cudd_bddXor( dd, dd->vars[ dd->invperm[2*Counter] ], dd->vars[ dd->invperm[2*Counter+1] ] );
+ Cudd_Ref( pCompose[ dd->invperm[2*Counter] ] );
+ // add this variable to the cube
+ bCube = Cudd_bddAnd( dd, bTemp = bCube, dd->vars[ dd->invperm[2*Counter] ] ); Cudd_Ref( bCube );
+ Cudd_RecursiveDeref( dd, bTemp );
+ // increment the counter
+ Counter ++;
+ }
+
+ // permute the functions
+ bFunc1 = Cudd_bddPermute( dd, bFunc, pPermute ); Cudd_Ref( bFunc1 );
+ // compose to gate the function depending on both vars
+ bFunc2 = Cudd_bddVectorCompose( dd, bFunc1, pCompose ); Cudd_Ref( bFunc2 );
+ // gate the vector space
+ // L(a) = ForAll x [ F(x) = F(x+a) ] = Not( Exist x [ F(x) (+) F(x+a) ] )
+ bSpaceShift = Cudd_bddXorExistAbstract( dd, bFunc1, bFunc2, bCube ); Cudd_Ref( bSpaceShift );
+ bSpaceShift = Cudd_Not( bSpaceShift );
+ // permute the space back into the original mapping
+ bSpace = Cudd_bddPermute( dd, bSpaceShift, pPermuteBack ); Cudd_Ref( bSpace );
+ Cudd_RecursiveDeref( dd, bFunc1 );
+ Cudd_RecursiveDeref( dd, bFunc2 );
+ Cudd_RecursiveDeref( dd, bSpaceShift );
+ Cudd_RecursiveDeref( dd, bCube );
+
+ for ( i = 0; i < dd->size; i++ )
+ Cudd_RecursiveDeref( dd, pCompose[i] );
+ free( pPermute );
+ free( pPermuteBack );
+ free( pCompose );
+ free( pSupport );
+
+ Cudd_Deref( bSpace );
+ return bSpace;
+}
+
+
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+DdNode * Extra_bddSpaceFromFunction( DdManager * dd, DdNode * bF, DdNode * bG )
+{
+ DdNode * bRes;
+ do {
+ dd->reordered = 0;
+ bRes = extraBddSpaceFromFunction( dd, bF, bG );
+ } while (dd->reordered == 1);
+ return bRes;
+}
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+DdNode * Extra_bddSpaceFromFunctionPos( DdManager * dd, DdNode * bFunc )
+{
+ DdNode * bRes;
+ do {
+ dd->reordered = 0;
+ bRes = extraBddSpaceFromFunctionPos( dd, bFunc );
+ } while (dd->reordered == 1);
+ return bRes;
+}
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+DdNode * Extra_bddSpaceFromFunctionNeg( DdManager * dd, DdNode * bFunc )
+{
+ DdNode * bRes;
+ do {
+ dd->reordered = 0;
+ bRes = extraBddSpaceFromFunctionNeg( dd, bFunc );
+ } while (dd->reordered == 1);
+ return bRes;
+}
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+DdNode * Extra_bddSpaceCanonVars( DdManager * dd, DdNode * bSpace )
+{
+ DdNode * bRes;
+ do {
+ dd->reordered = 0;
+ bRes = extraBddSpaceCanonVars( dd, bSpace );
+ } while (dd->reordered == 1);
+ return bRes;
+}
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+DdNode * Extra_bddSpaceReduce( DdManager * dd, DdNode * bFunc, DdNode * bCanonVars )
+{
+ DdNode * bNegCube;
+ DdNode * bResult;
+ bNegCube = Extra_bddSupportNegativeCube( dd, bCanonVars ); Cudd_Ref( bNegCube );
+ bResult = Cudd_Cofactor( dd, bFunc, bNegCube ); Cudd_Ref( bResult );
+ Cudd_RecursiveDeref( dd, bNegCube );
+ Cudd_Deref( bResult );
+ return bResult;
+}
+
+
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+DdNode * Extra_bddSpaceEquations( DdManager * dd, DdNode * bSpace )
+{
+ DdNode * zRes;
+ DdNode * zEquPos;
+ DdNode * zEquNeg;
+ zEquPos = Extra_bddSpaceEquationsPos( dd, bSpace ); Cudd_Ref( zEquPos );
+ zEquNeg = Extra_bddSpaceEquationsNeg( dd, bSpace ); Cudd_Ref( zEquNeg );
+ zRes = Cudd_zddUnion( dd, zEquPos, zEquNeg ); Cudd_Ref( zRes );
+ Cudd_RecursiveDerefZdd( dd, zEquPos );
+ Cudd_RecursiveDerefZdd( dd, zEquNeg );
+ Cudd_Deref( zRes );
+ return zRes;
+}
+
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+DdNode * Extra_bddSpaceEquationsPos( DdManager * dd, DdNode * bSpace )
+{
+ DdNode * zRes;
+ do {
+ dd->reordered = 0;
+ zRes = extraBddSpaceEquationsPos( dd, bSpace );
+ } while (dd->reordered == 1);
+ return zRes;
+}
+
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+DdNode * Extra_bddSpaceEquationsNeg( DdManager * dd, DdNode * bSpace )
+{
+ DdNode * zRes;
+ do {
+ dd->reordered = 0;
+ zRes = extraBddSpaceEquationsNeg( dd, bSpace );
+ } while (dd->reordered == 1);
+ return zRes;
+}
+
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+DdNode * Extra_bddSpaceFromMatrixPos( DdManager * dd, DdNode * zA )
+{
+ DdNode * bRes;
+ do {
+ dd->reordered = 0;
+ bRes = extraBddSpaceFromMatrixPos( dd, zA );
+ } while (dd->reordered == 1);
+ return bRes;
+}
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+DdNode * Extra_bddSpaceFromMatrixNeg( DdManager * dd, DdNode * zA )
+{
+ DdNode * bRes;
+ do {
+ dd->reordered = 0;
+ bRes = extraBddSpaceFromMatrixNeg( dd, zA );
+ } while (dd->reordered == 1);
+ return bRes;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Counts the number of literals in one combination.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Extra_zddLitCountComb( DdManager * dd, DdNode * zComb )
+{
+ int Counter;
+ if ( zComb == z0 )
+ return 0;
+ Counter = 0;
+ for ( ; zComb != z1; zComb = cuddT(zComb) )
+ Counter++;
+ return Counter;
+}
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description [Returns the array of ZDDs with the number equal to the number of
+ vars in the DD manager. If the given var is non-canonical, this array contains
+ the referenced ZDD representing literals in the corresponding EXOR equation.]
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+DdNode ** Extra_bddSpaceExorGates( DdManager * dd, DdNode * bFuncRed, DdNode * zEquations )
+{
+ DdNode ** pzRes;
+ int * pVarsNonCan;
+ DdNode * zEquRem;
+ int iVarNonCan;
+ DdNode * zExor, * zTemp;
+
+ // get the set of non-canonical variables
+ pVarsNonCan = ALLOC( int, ddMax(dd->size,dd->sizeZ) );
+ Extra_SupportArray( dd, bFuncRed, pVarsNonCan );
+
+ // allocate storage for the EXOR sets
+ pzRes = ALLOC( DdNode *, dd->size );
+ memset( pzRes, 0, sizeof(DdNode *) * dd->size );
+
+ // go through all the equations
+ zEquRem = zEquations; Cudd_Ref( zEquRem );
+ while ( zEquRem != z0 )
+ {
+ // extract one product
+ zExor = Extra_zddSelectOneSubset( dd, zEquRem ); Cudd_Ref( zExor );
+ // remove it from the set
+ zEquRem = Cudd_zddDiff( dd, zTemp = zEquRem, zExor ); Cudd_Ref( zEquRem );
+ Cudd_RecursiveDerefZdd( dd, zTemp );
+
+ // locate the non-canonical variable
+ iVarNonCan = -1;
+ for ( zTemp = zExor; zTemp != z1; zTemp = cuddT(zTemp) )
+ {
+ if ( pVarsNonCan[zTemp->index/2] == 1 )
+ {
+ assert( iVarNonCan == -1 );
+ iVarNonCan = zTemp->index/2;
+ }
+ }
+ assert( iVarNonCan != -1 );
+
+ if ( Extra_zddLitCountComb( dd, zExor ) > 1 )
+ pzRes[ iVarNonCan ] = zExor; // takes ref
+ else
+ Cudd_RecursiveDerefZdd( dd, zExor );
+ }
+ Cudd_RecursiveDerefZdd( dd, zEquRem );
+
+ free( pVarsNonCan );
+ return pzRes;
+}
+
+
+/*---------------------------------------------------------------------------*/
+/* Definition of internal functions */
+/*---------------------------------------------------------------------------*/
+
+/**Function********************************************************************
+
+ Synopsis [Performs the recursive steps of Extra_bddSpaceFromFunction.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+******************************************************************************/
+DdNode * extraBddSpaceFromFunction( DdManager * dd, DdNode * bF, DdNode * bG )
+{
+ DdNode * bRes;
+ DdNode * bFR, * bGR;
+
+ bFR = Cudd_Regular( bF );
+ bGR = Cudd_Regular( bG );
+ if ( cuddIsConstant(bFR) )
+ {
+ if ( bF == bG )
+ return b1;
+ else
+ return b0;
+ }
+ if ( cuddIsConstant(bGR) )
+ return b0;
+ // both bFunc and bCore are not constants
+
+ // the operation is commutative - normalize the problem
+ if ( (unsigned)bF > (unsigned)bG )
+ return extraBddSpaceFromFunction(dd, bG, bF);
+
+
+ if ( bRes = cuddCacheLookup2(dd, extraBddSpaceFromFunction, bF, bG) )
+ return bRes;
+ else
+ {
+ DdNode * bF0, * bF1;
+ DdNode * bG0, * bG1;
+ DdNode * bTemp1, * bTemp2;
+ DdNode * bRes0, * bRes1;
+ int LevelF, LevelG;
+ int index;
+
+ LevelF = dd->perm[bFR->index];
+ LevelG = dd->perm[bGR->index];
+ if ( LevelF <= LevelG )
+ {
+ index = dd->invperm[LevelF];
+ if ( bFR != bF )
+ {
+ bF0 = Cudd_Not( cuddE(bFR) );
+ bF1 = Cudd_Not( cuddT(bFR) );
+ }
+ else
+ {
+ bF0 = cuddE(bFR);
+ bF1 = cuddT(bFR);
+ }
+ }
+ else
+ {
+ index = dd->invperm[LevelG];
+ bF0 = bF1 = bF;
+ }
+
+ if ( LevelG <= LevelF )
+ {
+ if ( bGR != bG )
+ {
+ bG0 = Cudd_Not( cuddE(bGR) );
+ bG1 = Cudd_Not( cuddT(bGR) );
+ }
+ else
+ {
+ bG0 = cuddE(bGR);
+ bG1 = cuddT(bGR);
+ }
+ }
+ else
+ bG0 = bG1 = bG;
+
+ bTemp1 = extraBddSpaceFromFunction( dd, bF0, bG0 );
+ if ( bTemp1 == NULL )
+ return NULL;
+ cuddRef( bTemp1 );
+
+ bTemp2 = extraBddSpaceFromFunction( dd, bF1, bG1 );
+ if ( bTemp2 == NULL )
+ {
+ Cudd_RecursiveDeref( dd, bTemp1 );
+ return NULL;
+ }
+ cuddRef( bTemp2 );
+
+
+ bRes0 = cuddBddAndRecur( dd, bTemp1, bTemp2 );
+ if ( bRes0 == NULL )
+ {
+ Cudd_RecursiveDeref( dd, bTemp1 );
+ Cudd_RecursiveDeref( dd, bTemp2 );
+ return NULL;
+ }
+ cuddRef( bRes0 );
+ Cudd_RecursiveDeref( dd, bTemp1 );
+ Cudd_RecursiveDeref( dd, bTemp2 );
+
+
+ bTemp1 = extraBddSpaceFromFunction( dd, bF0, bG1 );
+ if ( bTemp1 == NULL )
+ {
+ Cudd_RecursiveDeref( dd, bRes0 );
+ return NULL;
+ }
+ cuddRef( bTemp1 );
+
+ bTemp2 = extraBddSpaceFromFunction( dd, bF1, bG0 );
+ if ( bTemp2 == NULL )
+ {
+ Cudd_RecursiveDeref( dd, bRes0 );
+ Cudd_RecursiveDeref( dd, bTemp1 );
+ return NULL;
+ }
+ cuddRef( bTemp2 );
+
+ bRes1 = cuddBddAndRecur( dd, bTemp1, bTemp2 );
+ if ( bRes1 == NULL )
+ {
+ Cudd_RecursiveDeref( dd, bRes0 );
+ Cudd_RecursiveDeref( dd, bTemp1 );
+ Cudd_RecursiveDeref( dd, bTemp2 );
+ return NULL;
+ }
+ cuddRef( bRes1 );
+ Cudd_RecursiveDeref( dd, bTemp1 );
+ Cudd_RecursiveDeref( dd, bTemp2 );
+
+
+
+ // consider the case when Res0 and Res1 are the same node
+ if ( bRes0 == bRes1 )
+ bRes = bRes1;
+ // consider the case when Res1 is complemented
+ else if ( Cudd_IsComplement(bRes1) )
+ {
+ bRes = cuddUniqueInter(dd, index, Cudd_Not(bRes1), Cudd_Not(bRes0));
+ if ( bRes == NULL )
+ {
+ Cudd_RecursiveDeref(dd,bRes0);
+ Cudd_RecursiveDeref(dd,bRes1);
+ return NULL;
+ }
+ bRes = Cudd_Not(bRes);
+ }
+ else
+ {
+ bRes = cuddUniqueInter( dd, index, bRes1, bRes0 );
+ if ( bRes == NULL )
+ {
+ Cudd_RecursiveDeref(dd,bRes0);
+ Cudd_RecursiveDeref(dd,bRes1);
+ return NULL;
+ }
+ }
+ cuddDeref( bRes0 );
+ cuddDeref( bRes1 );
+
+ // insert the result into cache
+ cuddCacheInsert2(dd, extraBddSpaceFromFunction, bF, bG, bRes);
+ return bRes;
+ }
+} /* end of extraBddSpaceFromFunction */
+
+
+
+/**Function*************************************************************
+
+ Synopsis [Performs the recursive step of Extra_bddSpaceFromFunctionPos().]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+DdNode * extraBddSpaceFromFunctionPos( DdManager * dd, DdNode * bF )
+{
+ DdNode * bRes, * bFR;
+ statLine( dd );
+
+ bFR = Cudd_Regular(bF);
+ if ( cuddIsConstant(bFR) )
+ return b1;
+
+ if ( bRes = cuddCacheLookup1(dd, extraBddSpaceFromFunctionPos, bF) )
+ return bRes;
+ else
+ {
+ DdNode * bF0, * bF1;
+ DdNode * bPos0, * bPos1;
+ DdNode * bNeg0, * bNeg1;
+ DdNode * bRes0, * bRes1;
+
+ if ( bFR != bF ) // bF is complemented
+ {
+ bF0 = Cudd_Not( cuddE(bFR) );
+ bF1 = Cudd_Not( cuddT(bFR) );
+ }
+ else
+ {
+ bF0 = cuddE(bFR);
+ bF1 = cuddT(bFR);
+ }
+
+
+ bPos0 = extraBddSpaceFromFunctionPos( dd, bF0 );
+ if ( bPos0 == NULL )
+ return NULL;
+ cuddRef( bPos0 );
+
+ bPos1 = extraBddSpaceFromFunctionPos( dd, bF1 );
+ if ( bPos1 == NULL )
+ {
+ Cudd_RecursiveDeref( dd, bPos0 );
+ return NULL;
+ }
+ cuddRef( bPos1 );
+
+ bRes0 = cuddBddAndRecur( dd, bPos0, bPos1 );
+ if ( bRes0 == NULL )
+ {
+ Cudd_RecursiveDeref( dd, bPos0 );
+ Cudd_RecursiveDeref( dd, bPos1 );
+ return NULL;
+ }
+ cuddRef( bRes0 );
+ Cudd_RecursiveDeref( dd, bPos0 );
+ Cudd_RecursiveDeref( dd, bPos1 );
+
+
+ bNeg0 = extraBddSpaceFromFunctionNeg( dd, bF0 );
+ if ( bNeg0 == NULL )
+ {
+ Cudd_RecursiveDeref( dd, bRes0 );
+ return NULL;
+ }
+ cuddRef( bNeg0 );
+
+ bNeg1 = extraBddSpaceFromFunctionNeg( dd, bF1 );
+ if ( bNeg1 == NULL )
+ {
+ Cudd_RecursiveDeref( dd, bRes0 );
+ Cudd_RecursiveDeref( dd, bNeg0 );
+ return NULL;
+ }
+ cuddRef( bNeg1 );
+
+ bRes1 = cuddBddAndRecur( dd, bNeg0, bNeg1 );
+ if ( bRes1 == NULL )
+ {
+ Cudd_RecursiveDeref( dd, bRes0 );
+ Cudd_RecursiveDeref( dd, bNeg0 );
+ Cudd_RecursiveDeref( dd, bNeg1 );
+ return NULL;
+ }
+ cuddRef( bRes1 );
+ Cudd_RecursiveDeref( dd, bNeg0 );
+ Cudd_RecursiveDeref( dd, bNeg1 );
+
+
+ // consider the case when Res0 and Res1 are the same node
+ if ( bRes0 == bRes1 )
+ bRes = bRes1;
+ // consider the case when Res1 is complemented
+ else if ( Cudd_IsComplement(bRes1) )
+ {
+ bRes = cuddUniqueInter( dd, bFR->index, Cudd_Not(bRes1), Cudd_Not(bRes0) );
+ if ( bRes == NULL )
+ {
+ Cudd_RecursiveDeref(dd,bRes0);
+ Cudd_RecursiveDeref(dd,bRes1);
+ return NULL;
+ }
+ bRes = Cudd_Not(bRes);
+ }
+ else
+ {
+ bRes = cuddUniqueInter( dd, bFR->index, bRes1, bRes0 );
+ if ( bRes == NULL )
+ {
+ Cudd_RecursiveDeref(dd,bRes0);
+ Cudd_RecursiveDeref(dd,bRes1);
+ return NULL;
+ }
+ }
+ cuddDeref( bRes0 );
+ cuddDeref( bRes1 );
+
+ cuddCacheInsert1( dd, extraBddSpaceFromFunctionPos, bF, bRes );
+ return bRes;
+ }
+}
+
+
+
+/**Function*************************************************************
+
+ Synopsis [Performs the recursive step of Extra_bddSpaceFromFunctionPos().]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+DdNode * extraBddSpaceFromFunctionNeg( DdManager * dd, DdNode * bF )
+{
+ DdNode * bRes, * bFR;
+ statLine( dd );
+
+ bFR = Cudd_Regular(bF);
+ if ( cuddIsConstant(bFR) )
+ return b0;
+
+ if ( bRes = cuddCacheLookup1(dd, extraBddSpaceFromFunctionNeg, bF) )
+ return bRes;
+ else
+ {
+ DdNode * bF0, * bF1;
+ DdNode * bPos0, * bPos1;
+ DdNode * bNeg0, * bNeg1;
+ DdNode * bRes0, * bRes1;
+
+ if ( bFR != bF ) // bF is complemented
+ {
+ bF0 = Cudd_Not( cuddE(bFR) );
+ bF1 = Cudd_Not( cuddT(bFR) );
+ }
+ else
+ {
+ bF0 = cuddE(bFR);
+ bF1 = cuddT(bFR);
+ }
+
+
+ bPos0 = extraBddSpaceFromFunctionNeg( dd, bF0 );
+ if ( bPos0 == NULL )
+ return NULL;
+ cuddRef( bPos0 );
+
+ bPos1 = extraBddSpaceFromFunctionNeg( dd, bF1 );
+ if ( bPos1 == NULL )
+ {
+ Cudd_RecursiveDeref( dd, bPos0 );
+ return NULL;
+ }
+ cuddRef( bPos1 );
+
+ bRes0 = cuddBddAndRecur( dd, bPos0, bPos1 );
+ if ( bRes0 == NULL )
+ {
+ Cudd_RecursiveDeref( dd, bPos0 );
+ Cudd_RecursiveDeref( dd, bPos1 );
+ return NULL;
+ }
+ cuddRef( bRes0 );
+ Cudd_RecursiveDeref( dd, bPos0 );
+ Cudd_RecursiveDeref( dd, bPos1 );
+
+
+ bNeg0 = extraBddSpaceFromFunctionPos( dd, bF0 );
+ if ( bNeg0 == NULL )
+ {
+ Cudd_RecursiveDeref( dd, bRes0 );
+ return NULL;
+ }
+ cuddRef( bNeg0 );
+
+ bNeg1 = extraBddSpaceFromFunctionPos( dd, bF1 );
+ if ( bNeg1 == NULL )
+ {
+ Cudd_RecursiveDeref( dd, bRes0 );
+ Cudd_RecursiveDeref( dd, bNeg0 );
+ return NULL;
+ }
+ cuddRef( bNeg1 );
+
+ bRes1 = cuddBddAndRecur( dd, bNeg0, bNeg1 );
+ if ( bRes1 == NULL )
+ {
+ Cudd_RecursiveDeref( dd, bRes0 );
+ Cudd_RecursiveDeref( dd, bNeg0 );
+ Cudd_RecursiveDeref( dd, bNeg1 );
+ return NULL;
+ }
+ cuddRef( bRes1 );
+ Cudd_RecursiveDeref( dd, bNeg0 );
+ Cudd_RecursiveDeref( dd, bNeg1 );
+
+
+ // consider the case when Res0 and Res1 are the same node
+ if ( bRes0 == bRes1 )
+ bRes = bRes1;
+ // consider the case when Res1 is complemented
+ else if ( Cudd_IsComplement(bRes1) )
+ {
+ bRes = cuddUniqueInter( dd, bFR->index, Cudd_Not(bRes1), Cudd_Not(bRes0) );
+ if ( bRes == NULL )
+ {
+ Cudd_RecursiveDeref(dd,bRes0);
+ Cudd_RecursiveDeref(dd,bRes1);
+ return NULL;
+ }
+ bRes = Cudd_Not(bRes);
+ }
+ else
+ {
+ bRes = cuddUniqueInter( dd, bFR->index, bRes1, bRes0 );
+ if ( bRes == NULL )
+ {
+ Cudd_RecursiveDeref(dd,bRes0);
+ Cudd_RecursiveDeref(dd,bRes1);
+ return NULL;
+ }
+ }
+ cuddDeref( bRes0 );
+ cuddDeref( bRes1 );
+
+ cuddCacheInsert1( dd, extraBddSpaceFromFunctionNeg, bF, bRes );
+ return bRes;
+ }
+}
+
+
+
+/**Function*************************************************************
+
+ Synopsis [Performs the recursive step of Extra_bddSpaceCanonVars().]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+DdNode * extraBddSpaceCanonVars( DdManager * dd, DdNode * bF )
+{
+ DdNode * bRes, * bFR;
+ statLine( dd );
+
+ bFR = Cudd_Regular(bF);
+ if ( cuddIsConstant(bFR) )
+ return bF;
+
+ if ( bRes = cuddCacheLookup1(dd, extraBddSpaceCanonVars, bF) )
+ return bRes;
+ else
+ {
+ DdNode * bF0, * bF1;
+ DdNode * bRes, * bRes0;
+
+ if ( bFR != bF ) // bF is complemented
+ {
+ bF0 = Cudd_Not( cuddE(bFR) );
+ bF1 = Cudd_Not( cuddT(bFR) );
+ }
+ else
+ {
+ bF0 = cuddE(bFR);
+ bF1 = cuddT(bFR);
+ }
+
+ if ( bF0 == b0 )
+ {
+ bRes = extraBddSpaceCanonVars( dd, bF1 );
+ if ( bRes == NULL )
+ return NULL;
+ }
+ else if ( bF1 == b0 )
+ {
+ bRes = extraBddSpaceCanonVars( dd, bF0 );
+ if ( bRes == NULL )
+ return NULL;
+ }
+ else
+ {
+ bRes0 = extraBddSpaceCanonVars( dd, bF0 );
+ if ( bRes0 == NULL )
+ return NULL;
+ cuddRef( bRes0 );
+
+ bRes = cuddUniqueInter( dd, bFR->index, bRes0, b0 );
+ if ( bRes == NULL )
+ {
+ Cudd_RecursiveDeref( dd,bRes0 );
+ return NULL;
+ }
+ cuddDeref( bRes0 );
+ }
+
+ cuddCacheInsert1( dd, extraBddSpaceCanonVars, bF, bRes );
+ return bRes;
+ }
+}
+
+/**Function*************************************************************
+
+ Synopsis [Performs the recursive step of Extra_bddSpaceEquationsPos().]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+DdNode * extraBddSpaceEquationsPos( DdManager * dd, DdNode * bF )
+{
+ DdNode * zRes;
+ statLine( dd );
+
+ if ( bF == b0 )
+ return z1;
+ if ( bF == b1 )
+ return z0;
+
+ if ( zRes = cuddCacheLookup1Zdd(dd, extraBddSpaceEquationsPos, bF) )
+ return zRes;
+ else
+ {
+ DdNode * bFR, * bF0, * bF1;
+ DdNode * zPos0, * zPos1, * zNeg1;
+ DdNode * zRes, * zRes0, * zRes1;
+
+ bFR = Cudd_Regular(bF);
+ if ( bFR != bF ) // bF is complemented
+ {
+ bF0 = Cudd_Not( cuddE(bFR) );
+ bF1 = Cudd_Not( cuddT(bFR) );
+ }
+ else
+ {
+ bF0 = cuddE(bFR);
+ bF1 = cuddT(bFR);
+ }
+
+ if ( bF0 == b0 )
+ {
+ zRes1 = extraBddSpaceEquationsPos( dd, bF1 );
+ if ( zRes1 == NULL )
+ return NULL;
+ cuddRef( zRes1 );
+
+ // add the current element to the set
+ zRes = cuddZddGetNode( dd, 2*bFR->index, z1, zRes1 );
+ if ( zRes == NULL )
+ {
+ Cudd_RecursiveDerefZdd(dd, zRes1);
+ return NULL;
+ }
+ cuddDeref( zRes1 );
+ }
+ else if ( bF1 == b0 )
+ {
+ zRes = extraBddSpaceEquationsPos( dd, bF0 );
+ if ( zRes == NULL )
+ return NULL;
+ }
+ else
+ {
+ zPos0 = extraBddSpaceEquationsPos( dd, bF0 );
+ if ( zPos0 == NULL )
+ return NULL;
+ cuddRef( zPos0 );
+
+ zPos1 = extraBddSpaceEquationsPos( dd, bF1 );
+ if ( zPos1 == NULL )
+ {
+ Cudd_RecursiveDerefZdd(dd, zPos0);
+ return NULL;
+ }
+ cuddRef( zPos1 );
+
+ zNeg1 = extraBddSpaceEquationsNeg( dd, bF1 );
+ if ( zNeg1 == NULL )
+ {
+ Cudd_RecursiveDerefZdd(dd, zPos0);
+ Cudd_RecursiveDerefZdd(dd, zPos1);
+ return NULL;
+ }
+ cuddRef( zNeg1 );
+
+
+ zRes0 = cuddZddIntersect( dd, zPos0, zPos1 );
+ if ( zRes0 == NULL )
+ {
+ Cudd_RecursiveDerefZdd(dd, zNeg1);
+ Cudd_RecursiveDerefZdd(dd, zPos0);
+ Cudd_RecursiveDerefZdd(dd, zPos1);
+ return NULL;
+ }
+ cuddRef( zRes0 );
+
+ zRes1 = cuddZddIntersect( dd, zPos0, zNeg1 );
+ if ( zRes1 == NULL )
+ {
+ Cudd_RecursiveDerefZdd(dd, zRes0);
+ Cudd_RecursiveDerefZdd(dd, zNeg1);
+ Cudd_RecursiveDerefZdd(dd, zPos0);
+ Cudd_RecursiveDerefZdd(dd, zPos1);
+ return NULL;
+ }
+ cuddRef( zRes1 );
+ Cudd_RecursiveDerefZdd(dd, zNeg1);
+ Cudd_RecursiveDerefZdd(dd, zPos0);
+ Cudd_RecursiveDerefZdd(dd, zPos1);
+ // only zRes0 and zRes1 are refed at this point
+
+ zRes = cuddZddGetNode( dd, 2*bFR->index, zRes1, zRes0 );
+ if ( zRes == NULL )
+ {
+ Cudd_RecursiveDerefZdd(dd, zRes0);
+ Cudd_RecursiveDerefZdd(dd, zRes1);
+ return NULL;
+ }
+ cuddDeref( zRes0 );
+ cuddDeref( zRes1 );
+ }
+
+ cuddCacheInsert1( dd, extraBddSpaceEquationsPos, bF, zRes );
+ return zRes;
+ }
+}
+
+
+/**Function*************************************************************
+
+ Synopsis [Performs the recursive step of Extra_bddSpaceEquationsNev().]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+DdNode * extraBddSpaceEquationsNeg( DdManager * dd, DdNode * bF )
+{
+ DdNode * zRes;
+ statLine( dd );
+
+ if ( bF == b0 )
+ return z1;
+ if ( bF == b1 )
+ return z0;
+
+ if ( zRes = cuddCacheLookup1Zdd(dd, extraBddSpaceEquationsNeg, bF) )
+ return zRes;
+ else
+ {
+ DdNode * bFR, * bF0, * bF1;
+ DdNode * zPos0, * zPos1, * zNeg1;
+ DdNode * zRes, * zRes0, * zRes1;
+
+ bFR = Cudd_Regular(bF);
+ if ( bFR != bF ) // bF is complemented
+ {
+ bF0 = Cudd_Not( cuddE(bFR) );
+ bF1 = Cudd_Not( cuddT(bFR) );
+ }
+ else
+ {
+ bF0 = cuddE(bFR);
+ bF1 = cuddT(bFR);
+ }
+
+ if ( bF0 == b0 )
+ {
+ zRes = extraBddSpaceEquationsNeg( dd, bF1 );
+ if ( zRes == NULL )
+ return NULL;
+ }
+ else if ( bF1 == b0 )
+ {
+ zRes0 = extraBddSpaceEquationsNeg( dd, bF0 );
+ if ( zRes0 == NULL )
+ return NULL;
+ cuddRef( zRes0 );
+
+ // add the current element to the set
+ zRes = cuddZddGetNode( dd, 2*bFR->index, z1, zRes0 );
+ if ( zRes == NULL )
+ {
+ Cudd_RecursiveDerefZdd(dd, zRes0);
+ return NULL;
+ }
+ cuddDeref( zRes0 );
+ }
+ else
+ {
+ zPos0 = extraBddSpaceEquationsNeg( dd, bF0 );
+ if ( zPos0 == NULL )
+ return NULL;
+ cuddRef( zPos0 );
+
+ zPos1 = extraBddSpaceEquationsNeg( dd, bF1 );
+ if ( zPos1 == NULL )
+ {
+ Cudd_RecursiveDerefZdd(dd, zPos0);
+ return NULL;
+ }
+ cuddRef( zPos1 );
+
+ zNeg1 = extraBddSpaceEquationsPos( dd, bF1 );
+ if ( zNeg1 == NULL )
+ {
+ Cudd_RecursiveDerefZdd(dd, zPos0);
+ Cudd_RecursiveDerefZdd(dd, zPos1);
+ return NULL;
+ }
+ cuddRef( zNeg1 );
+
+
+ zRes0 = cuddZddIntersect( dd, zPos0, zPos1 );
+ if ( zRes0 == NULL )
+ {
+ Cudd_RecursiveDerefZdd(dd, zNeg1);
+ Cudd_RecursiveDerefZdd(dd, zPos0);
+ Cudd_RecursiveDerefZdd(dd, zPos1);
+ return NULL;
+ }
+ cuddRef( zRes0 );
+
+ zRes1 = cuddZddIntersect( dd, zPos0, zNeg1 );
+ if ( zRes1 == NULL )
+ {
+ Cudd_RecursiveDerefZdd(dd, zRes0);
+ Cudd_RecursiveDerefZdd(dd, zNeg1);
+ Cudd_RecursiveDerefZdd(dd, zPos0);
+ Cudd_RecursiveDerefZdd(dd, zPos1);
+ return NULL;
+ }
+ cuddRef( zRes1 );
+ Cudd_RecursiveDerefZdd(dd, zNeg1);
+ Cudd_RecursiveDerefZdd(dd, zPos0);
+ Cudd_RecursiveDerefZdd(dd, zPos1);
+ // only zRes0 and zRes1 are refed at this point
+
+ zRes = cuddZddGetNode( dd, 2*bFR->index, zRes1, zRes0 );
+ if ( zRes == NULL )
+ {
+ Cudd_RecursiveDerefZdd(dd, zRes0);
+ Cudd_RecursiveDerefZdd(dd, zRes1);
+ return NULL;
+ }
+ cuddDeref( zRes0 );
+ cuddDeref( zRes1 );
+ }
+
+ cuddCacheInsert1( dd, extraBddSpaceEquationsNeg, bF, zRes );
+ return zRes;
+ }
+}
+
+
+
+
+/**Function*************************************************************
+
+ Synopsis [Performs the recursive step of Extra_bddSpaceFromFunctionPos().]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+DdNode * extraBddSpaceFromMatrixPos( DdManager * dd, DdNode * zA )
+{
+ DdNode * bRes;
+ statLine( dd );
+
+ if ( zA == z0 )
+ return b1;
+ if ( zA == z1 )
+ return b1;
+
+ if ( bRes = cuddCacheLookup1(dd, extraBddSpaceFromMatrixPos, zA) )
+ return bRes;
+ else
+ {
+ DdNode * bP0, * bP1;
+ DdNode * bN0, * bN1;
+ DdNode * bRes0, * bRes1;
+
+ bP0 = extraBddSpaceFromMatrixPos( dd, cuddE(zA) );
+ if ( bP0 == NULL )
+ return NULL;
+ cuddRef( bP0 );
+
+ bP1 = extraBddSpaceFromMatrixPos( dd, cuddT(zA) );
+ if ( bP1 == NULL )
+ {
+ Cudd_RecursiveDeref( dd, bP0 );
+ return NULL;
+ }
+ cuddRef( bP1 );
+
+ bRes0 = cuddBddAndRecur( dd, bP0, bP1 );
+ if ( bRes0 == NULL )
+ {
+ Cudd_RecursiveDeref( dd, bP0 );
+ Cudd_RecursiveDeref( dd, bP1 );
+ return NULL;
+ }
+ cuddRef( bRes0 );
+ Cudd_RecursiveDeref( dd, bP0 );
+ Cudd_RecursiveDeref( dd, bP1 );
+
+
+ bN0 = extraBddSpaceFromMatrixPos( dd, cuddE(zA) );
+ if ( bN0 == NULL )
+ {
+ Cudd_RecursiveDeref( dd, bRes0 );
+ return NULL;
+ }
+ cuddRef( bN0 );
+
+ bN1 = extraBddSpaceFromMatrixNeg( dd, cuddT(zA) );
+ if ( bN1 == NULL )
+ {
+ Cudd_RecursiveDeref( dd, bRes0 );
+ Cudd_RecursiveDeref( dd, bN0 );
+ return NULL;
+ }
+ cuddRef( bN1 );
+
+ bRes1 = cuddBddAndRecur( dd, bN0, bN1 );
+ if ( bRes1 == NULL )
+ {
+ Cudd_RecursiveDeref( dd, bRes0 );
+ Cudd_RecursiveDeref( dd, bN0 );
+ Cudd_RecursiveDeref( dd, bN1 );
+ return NULL;
+ }
+ cuddRef( bRes1 );
+ Cudd_RecursiveDeref( dd, bN0 );
+ Cudd_RecursiveDeref( dd, bN1 );
+
+
+ // consider the case when Res0 and Res1 are the same node
+ if ( bRes0 == bRes1 )
+ bRes = bRes1;
+ // consider the case when Res1 is complemented
+ else if ( Cudd_IsComplement(bRes1) )
+ {
+ bRes = cuddUniqueInter( dd, zA->index/2, Cudd_Not(bRes1), Cudd_Not(bRes0) );
+ if ( bRes == NULL )
+ {
+ Cudd_RecursiveDeref(dd,bRes0);
+ Cudd_RecursiveDeref(dd,bRes1);
+ return NULL;
+ }
+ bRes = Cudd_Not(bRes);
+ }
+ else
+ {
+ bRes = cuddUniqueInter( dd, zA->index/2, bRes1, bRes0 );
+ if ( bRes == NULL )
+ {
+ Cudd_RecursiveDeref(dd,bRes0);
+ Cudd_RecursiveDeref(dd,bRes1);
+ return NULL;
+ }
+ }
+ cuddDeref( bRes0 );
+ cuddDeref( bRes1 );
+
+ cuddCacheInsert1( dd, extraBddSpaceFromMatrixPos, zA, bRes );
+ return bRes;
+ }
+}
+
+
+/**Function*************************************************************
+
+ Synopsis [Performs the recursive step of Extra_bddSpaceFromFunctionPos().]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+DdNode * extraBddSpaceFromMatrixNeg( DdManager * dd, DdNode * zA )
+{
+ DdNode * bRes;
+ statLine( dd );
+
+ if ( zA == z0 )
+ return b1;
+ if ( zA == z1 )
+ return b0;
+
+ if ( bRes = cuddCacheLookup1(dd, extraBddSpaceFromMatrixNeg, zA) )
+ return bRes;
+ else
+ {
+ DdNode * bP0, * bP1;
+ DdNode * bN0, * bN1;
+ DdNode * bRes0, * bRes1;
+
+ bP0 = extraBddSpaceFromMatrixNeg( dd, cuddE(zA) );
+ if ( bP0 == NULL )
+ return NULL;
+ cuddRef( bP0 );
+
+ bP1 = extraBddSpaceFromMatrixNeg( dd, cuddT(zA) );
+ if ( bP1 == NULL )
+ {
+ Cudd_RecursiveDeref( dd, bP0 );
+ return NULL;
+ }
+ cuddRef( bP1 );
+
+ bRes0 = cuddBddAndRecur( dd, bP0, bP1 );
+ if ( bRes0 == NULL )
+ {
+ Cudd_RecursiveDeref( dd, bP0 );
+ Cudd_RecursiveDeref( dd, bP1 );
+ return NULL;
+ }
+ cuddRef( bRes0 );
+ Cudd_RecursiveDeref( dd, bP0 );
+ Cudd_RecursiveDeref( dd, bP1 );
+
+
+ bN0 = extraBddSpaceFromMatrixNeg( dd, cuddE(zA) );
+ if ( bN0 == NULL )
+ {
+ Cudd_RecursiveDeref( dd, bRes0 );
+ return NULL;
+ }
+ cuddRef( bN0 );
+
+ bN1 = extraBddSpaceFromMatrixPos( dd, cuddT(zA) );
+ if ( bN1 == NULL )
+ {
+ Cudd_RecursiveDeref( dd, bRes0 );
+ Cudd_RecursiveDeref( dd, bN0 );
+ return NULL;
+ }
+ cuddRef( bN1 );
+
+ bRes1 = cuddBddAndRecur( dd, bN0, bN1 );
+ if ( bRes1 == NULL )
+ {
+ Cudd_RecursiveDeref( dd, bRes0 );
+ Cudd_RecursiveDeref( dd, bN0 );
+ Cudd_RecursiveDeref( dd, bN1 );
+ return NULL;
+ }
+ cuddRef( bRes1 );
+ Cudd_RecursiveDeref( dd, bN0 );
+ Cudd_RecursiveDeref( dd, bN1 );
+
+
+ // consider the case when Res0 and Res1 are the same node
+ if ( bRes0 == bRes1 )
+ bRes = bRes1;
+ // consider the case when Res1 is complemented
+ else if ( Cudd_IsComplement(bRes1) )
+ {
+ bRes = cuddUniqueInter( dd, zA->index/2, Cudd_Not(bRes1), Cudd_Not(bRes0) );
+ if ( bRes == NULL )
+ {
+ Cudd_RecursiveDeref(dd,bRes0);
+ Cudd_RecursiveDeref(dd,bRes1);
+ return NULL;
+ }
+ bRes = Cudd_Not(bRes);
+ }
+ else
+ {
+ bRes = cuddUniqueInter( dd, zA->index/2, bRes1, bRes0 );
+ if ( bRes == NULL )
+ {
+ Cudd_RecursiveDeref(dd,bRes0);
+ Cudd_RecursiveDeref(dd,bRes1);
+ return NULL;
+ }
+ }
+ cuddDeref( bRes0 );
+ cuddDeref( bRes1 );
+
+ cuddCacheInsert1( dd, extraBddSpaceFromMatrixNeg, zA, bRes );
+ return bRes;
+ }
+}
+
+
+/*---------------------------------------------------------------------------*/
+/* Definition of static functions */
+/*---------------------------------------------------------------------------*/
+
diff --git a/src/misc/extra/extraBddCas.c b/src/misc/extra/extraBddCas.c
new file mode 100644
index 00000000..29382bfb
--- /dev/null
+++ b/src/misc/extra/extraBddCas.c
@@ -0,0 +1,1230 @@
+/**CFile****************************************************************
+
+ FileName [extraBddCas.c]
+
+ PackageName [extra]
+
+ Synopsis [Procedures related to LUT cascade synthesis.]
+
+ Author [Alan Mishchenko]
+
+ Affiliation [UC Berkeley]
+
+ Date [Ver. 2.0. Started - September 1, 2003.]
+
+ Revision [$Id: extraBddCas.c,v 1.0 2003/05/21 18:03:50 alanmi Exp $]
+
+***********************************************************************/
+
+#include "extra.h"
+
+/*---------------------------------------------------------------------------*/
+/* Constant declarations */
+/*---------------------------------------------------------------------------*/
+
+/*---------------------------------------------------------------------------*/
+/* Stucture declarations */
+/*---------------------------------------------------------------------------*/
+
+/*---------------------------------------------------------------------------*/
+/* Type declarations */
+/*---------------------------------------------------------------------------*/
+
+// the table to store cofactor operations
+#define _TABLESIZE_COF 51113
+typedef struct
+{
+ unsigned Sign;
+ DdNode * Arg1;
+} _HashEntry_cof;
+_HashEntry_cof HHTable1[_TABLESIZE_COF];
+
+// the table to store the result of computation of the number of minterms
+#define _TABLESIZE_MINT 15113
+typedef struct
+{
+ DdNode * Arg1;
+ unsigned Arg2;
+ unsigned Res;
+} _HashEntry_mint;
+_HashEntry_mint HHTable2[_TABLESIZE_MINT];
+
+typedef struct
+{
+ int nEdges; // the number of in-coming edges of the node
+ DdNode * bSum; // the sum of paths of the incoming edges
+} traventry;
+
+// the signature used for hashing
+static unsigned s_Signature = 1;
+
+static int s_CutLevel = 0;
+
+/*---------------------------------------------------------------------------*/
+/* Variable declarations */
+/*---------------------------------------------------------------------------*/
+
+// because the proposed solution to the optimal encoding problem has exponential complexity
+// we limit the depth of the branch and bound procedure to 5 levels
+static int s_MaxDepth = 5;
+
+static int s_nVarsBest; // the number of vars in the best ordering
+static int s_VarOrderBest[32]; // storing the best ordering of vars in the "simple encoding"
+static int s_VarOrderCur[32]; // storing the current ordering of vars
+
+// the place to store the supports of the encoded function
+static DdNode * s_Field[8][256]; // the size should be K, 2^K, where K is no less than MaxDepth
+static DdNode * s_Encoded; // this is the original function
+static DdNode * s_VarAll; // the set of all column variables
+static int s_MultiStart; // the total number of encoding variables used
+// the array field now stores the supports
+
+static DdNode ** s_pbTemp; // the temporary storage for the columns
+
+static int s_BackTracks;
+static int s_BackTrackLimit = 100;
+
+static DdNode * s_Terminal; // the terminal value for counting minterms
+
+
+static int s_EncodingVarsLevel;
+
+
+/*---------------------------------------------------------------------------*/
+/* Macro declarations */
+/*---------------------------------------------------------------------------*/
+
+
+/**AutomaticStart*************************************************************/
+
+/*---------------------------------------------------------------------------*/
+/* Static function prototypes */
+/*---------------------------------------------------------------------------*/
+
+static DdNode * CreateTheCodes_rec( DdManager * dd, DdNode * bEncoded, int Level, DdNode ** pCVars );
+static void EvaluateEncodings_rec( DdManager * dd, DdNode * bVarsCol, int nVarsCol, int nMulti, int Level );
+// functions called from EvaluateEncodings_rec()
+static DdNode * ComputeVarSetAndCountMinterms( DdManager * dd, DdNode * bVars, DdNode * bVarTop, unsigned * Cost );
+static DdNode * ComputeVarSetAndCountMinterms2( DdManager * dd, DdNode * bVars, DdNode * bVarTop, unsigned * Cost );
+unsigned Extra_CountCofactorMinterms( DdManager * dd, DdNode * bFunc, DdNode * bVarsCof, DdNode * bVarsAll );
+static unsigned Extra_CountMintermsSimple( DdNode * bFunc, unsigned max );
+
+static void CountNodeVisits_rec( DdManager * dd, DdNode * aFunc, st_table * Visited );
+static void CollectNodesAndComputePaths_rec( DdManager * dd, DdNode * aFunc, DdNode * bCube, st_table * Visited, st_table * CutNodes );
+
+/**AutomaticEnd***************************************************************/
+
+
+/*---------------------------------------------------------------------------*/
+/* Definition of exported functions */
+/*---------------------------------------------------------------------------*/
+
+/**Function********************************************************************
+
+ Synopsis [Performs the binary encoding of the set of function using the given vars.]
+
+ Description [Performs a straight binary encoding of the set of functions using
+ the variable cubes formed from the given set of variables. ]
+
+ SideEffects []
+
+ SeeAlso []
+
+******************************************************************************/
+DdNode *
+Extra_bddEncodingBinary(
+ DdManager * dd,
+ DdNode ** pbFuncs, // pbFuncs is the array of columns to be encoded
+ int nFuncs, // nFuncs is the number of columns in the array
+ DdNode ** pbVars, // pbVars is the array of variables to use for the codes
+ int nVars ) // nVars is the column multiplicity, [log2(nFuncs)]
+{
+ int i;
+ DdNode * bResult;
+ DdNode * bCube, * bTemp, * bProd;
+
+ assert( nVars >= Extra_Base2Log(nFuncs) );
+
+ bResult = b0; Cudd_Ref( bResult );
+ for ( i = 0; i < nFuncs; i++ )
+ {
+ bCube = Extra_bddBitsToCube( dd, i, nVars, pbVars, 1 ); Cudd_Ref( bCube );
+ bProd = Cudd_bddAnd( dd, bCube, pbFuncs[i] ); Cudd_Ref( bProd );
+ Cudd_RecursiveDeref( dd, bCube );
+
+ bResult = Cudd_bddOr( dd, bProd, bTemp = bResult ); Cudd_Ref( bResult );
+ Cudd_RecursiveDeref( dd, bTemp );
+ Cudd_RecursiveDeref( dd, bProd );
+ }
+
+ Cudd_Deref( bResult );
+ return bResult;
+} /* end of Extra_bddEncodingBinary */
+
+
+/**Function********************************************************************
+
+ Synopsis [Solves the column encoding problem using a sophisticated method.]
+
+ Description [The encoding is based on the idea of deriving functions which
+ depend on only one variable, which corresponds to the case of non-disjoint
+ decompostion. It is assumed that the variables pCVars are ordered below the variables
+ representing the solumns, and the first variable pCVars[0] is the topmost one.]
+
+ SideEffects []
+
+ SeeAlso [Extra_bddEncodingBinary]
+
+******************************************************************************/
+
+DdNode *
+Extra_bddEncodingNonStrict(
+ DdManager * dd,
+ DdNode ** pbColumns, // pbColumns is the array of columns to be encoded;
+ int nColumns, // nColumns is the number of columns in the array
+ DdNode * bVarsCol, // bVarsCol is the cube of variables on which the columns depend
+ DdNode ** pCVars, // pCVars is the array of variables to use for the codes
+ int nMulti, // nMulti is the column multiplicity, [log2(nColumns)]
+ int * pSimple ) // pSimple gets the number of code variables taken from the input varibles without change
+{
+ DdNode * bEncoded, * bResult;
+ int nVarsCol = Cudd_SupportSize(dd,bVarsCol);
+ long clk;
+
+ // cannot work with more that 32-bit codes
+ assert( nMulti < 32 );
+
+ // perform the preliminary encoding using the straight binary code
+ bEncoded = Extra_bddEncodingBinary( dd, pbColumns, nColumns, pCVars, nMulti ); Cudd_Ref( bEncoded );
+ //printf( "Node count = %d", Cudd_DagSize(bEncoded) );
+
+ // set the backgroup value for counting minterms
+ s_Terminal = b0;
+ // set the level of the encoding variables
+ s_EncodingVarsLevel = dd->invperm[pCVars[0]->index];
+
+ // the current number of backtracks
+ s_BackTracks = 0;
+ // the variables that are cofactored on the topmost level where everything starts (no vars)
+ s_Field[0][0] = b1;
+ // the size of the best set of "simple" encoding variables found so far
+ s_nVarsBest = 0;
+
+ // set the relation to be accessible to traversal procedures
+ s_Encoded = bEncoded;
+ // the set of all vars to be accessible to traversal procedures
+ s_VarAll = bVarsCol;
+ // the column multiplicity
+ s_MultiStart = nMulti;
+
+
+ clk = clock();
+ // find the simplest encoding
+ if ( nColumns > 2 )
+ EvaluateEncodings_rec( dd, bVarsCol, nVarsCol, nMulti, 1 );
+// printf( "The number of backtracks = %d\n", s_BackTracks );
+// s_EncSearchTime += clock() - clk;
+
+ // allocate the temporary storage for the columns
+ s_pbTemp = (DdNode **) malloc( nColumns * sizeof(DdNode *) );
+
+// clk = clock();
+ bResult = CreateTheCodes_rec( dd, bEncoded, 0, pCVars ); Cudd_Ref( bResult );
+// s_EncComputeTime += clock() - clk;
+
+ // delocate the preliminarily encoded set
+ Cudd_RecursiveDeref( dd, bEncoded );
+// Cudd_RecursiveDeref( dd, aEncoded );
+
+ free( s_pbTemp );
+
+ *pSimple = s_nVarsBest;
+ Cudd_Deref( bResult );
+ return bResult;
+}
+
+/**Function********************************************************************
+
+ Synopsis [Collects the nodes under the cut and, for each node, computes the sum of paths leading to it from the root.]
+
+ Description [The table returned contains the set of BDD nodes pointed to under the cut
+ and, for each node, the BDD of the sum of paths leading to this node from the root
+ The sums of paths in the table are referenced. CutLevel is the first DD level
+ considered to be under the cut.]
+
+ SideEffects []
+
+ SeeAlso [Extra_bddNodePaths]
+
+******************************************************************************/
+st_table * Extra_bddNodePathsUnderCut( DdManager * dd, DdNode * bFunc, int CutLevel )
+{
+ st_table * Visited; // temporary table to remember the visited nodes
+ st_table * CutNodes; // the result goes here
+ st_table * Result; // the result goes here
+ DdNode * aFunc;
+
+ s_CutLevel = CutLevel;
+
+ Result = st_init_table(st_ptrcmp,st_ptrhash);
+ // the terminal cases
+ if ( Cudd_IsConstant( bFunc ) )
+ {
+ if ( bFunc == b1 )
+ {
+ st_insert( Result, (char*)b1, (char*)b1 );
+ Cudd_Ref( b1 );
+ Cudd_Ref( b1 );
+ }
+ else
+ {
+ st_insert( Result, (char*)b0, (char*)b0 );
+ Cudd_Ref( b0 );
+ Cudd_Ref( b0 );
+ }
+ return Result;
+ }
+
+ // create the ADD to simplify processing (no complemented edges)
+ aFunc = Cudd_BddToAdd( dd, bFunc ); Cudd_Ref( aFunc );
+
+ // Step 1: Start the tables and collect information about the nodes above the cut
+ // this information tells how many edges point to each node
+ Visited = st_init_table(st_ptrcmp,st_ptrhash);
+ CutNodes = st_init_table(st_ptrcmp,st_ptrhash);
+
+ CountNodeVisits_rec( dd, aFunc, Visited );
+
+ // Step 2: Traverse the BDD using the visited table and compute the sum of paths
+ CollectNodesAndComputePaths_rec( dd, aFunc, b1, Visited, CutNodes );
+
+ // at this point the table of cut nodes is ready and the table of visited is useless
+ {
+ st_generator * gen;
+ DdNode * aNode;
+ traventry * p;
+ st_foreach_item( Visited, gen, (char**)&aNode, (char**)&p )
+ {
+ Cudd_RecursiveDeref( dd, p->bSum );
+ free( p );
+ }
+ st_free_table( Visited );
+ }
+
+ // go through the table CutNodes and create the BDD and the path to be returned
+ {
+ st_generator * gen;
+ DdNode * aNode, * bNode, * bSum;
+ st_foreach_item( CutNodes, gen, (char**)&aNode, (char**)&bSum)
+ {
+ // aNode is not referenced, because aFunc is holding it
+ bNode = Cudd_addBddPattern( dd, aNode ); Cudd_Ref( bNode );
+ st_insert( Result, (char*)bNode, (char*)bSum );
+ // the new table takes both refs
+ }
+ st_free_table( CutNodes );
+ }
+
+ // dereference the ADD
+ Cudd_RecursiveDeref( dd, aFunc );
+
+ // return the table
+ return Result;
+
+} /* end of Extra_bddNodePathsUnderCut */
+
+/**Function********************************************************************
+
+ Synopsis [Collects the nodes under the cut in the ADD starting from the given set of ADD nodes.]
+
+ Description [Takes the array, paNodes, of ADD nodes to start the traversal,
+ the array, pbCubes, of BDD cubes to start the traversal with in each node,
+ and the number, nNodes, of ADD nodes and BDD cubes in paNodes and pbCubes.
+ Returns the number of columns found. Fills in paNodesRes (pbCubesRes)
+ with the set of ADD columns (BDD paths). These arrays should be allocated
+ by the user.]
+
+ SideEffects []
+
+ SeeAlso [Extra_bddNodePaths]
+
+******************************************************************************/
+int Extra_bddNodePathsUnderCutArray( DdManager * dd, DdNode ** paNodes, DdNode ** pbCubes, int nNodes, DdNode ** paNodesRes, DdNode ** pbCubesRes, int CutLevel )
+{
+ st_table * Visited; // temporary table to remember the visited nodes
+ st_table * CutNodes; // the nodes under the cut go here
+ int i, Counter;
+
+ s_CutLevel = CutLevel;
+
+ // there should be some nodes
+ assert( nNodes > 0 );
+ if ( nNodes == 1 && Cudd_IsConstant( paNodes[0] ) )
+ {
+ if ( paNodes[0] == a1 )
+ {
+ paNodesRes[0] = a1; Cudd_Ref( a1 );
+ pbCubesRes[0] = pbCubes[0]; Cudd_Ref( pbCubes[0] );
+ }
+ else
+ {
+ paNodesRes[0] = a0; Cudd_Ref( a0 );
+ pbCubesRes[0] = pbCubes[0]; Cudd_Ref( pbCubes[0] );
+ }
+ return 1;
+ }
+
+ // Step 1: Start the table and collect information about the nodes above the cut
+ // this information tells how many edges point to each node
+ CutNodes = st_init_table(st_ptrcmp,st_ptrhash);
+ Visited = st_init_table(st_ptrcmp,st_ptrhash);
+
+ for ( i = 0; i < nNodes; i++ )
+ CountNodeVisits_rec( dd, paNodes[i], Visited );
+
+ // Step 2: Traverse the BDD using the visited table and compute the sum of paths
+ for ( i = 0; i < nNodes; i++ )
+ CollectNodesAndComputePaths_rec( dd, paNodes[i], pbCubes[i], Visited, CutNodes );
+
+ // at this point, the table of cut nodes is ready and the table of visited is useless
+ {
+ st_generator * gen;
+ DdNode * aNode;
+ traventry * p;
+ st_foreach_item( Visited, gen, (char**)&aNode, (char**)&p )
+ {
+ Cudd_RecursiveDeref( dd, p->bSum );
+ free( p );
+ }
+ st_free_table( Visited );
+ }
+
+ // go through the table CutNodes and create the BDD and the path to be returned
+ {
+ st_generator * gen;
+ DdNode * aNode, * bSum;
+ Counter = 0;
+ st_foreach_item( CutNodes, gen, (char**)&aNode, (char**)&bSum)
+ {
+ paNodesRes[Counter] = aNode; Cudd_Ref( aNode );
+ pbCubesRes[Counter] = bSum;
+ Counter++;
+ }
+ st_free_table( CutNodes );
+ }
+
+ // return the number of cofactors found
+ return Counter;
+
+} /* end of Extra_bddNodePathsUnderCutArray */
+
+/**Function*************************************************************
+
+ Synopsis [Collects all the BDD nodes into the table.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void extraCollectNodes( DdNode * Func, st_table * tNodes )
+{
+ DdNode * FuncR;
+ FuncR = Cudd_Regular(Func);
+ if ( st_find_or_add( tNodes, (char*)FuncR, NULL ) )
+ return;
+ if ( cuddIsConstant(FuncR) )
+ return;
+ extraCollectNodes( cuddE(FuncR), tNodes );
+ extraCollectNodes( cuddT(FuncR), tNodes );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Collects all the nodes of one DD into the table.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+st_table * Extra_CollectNodes( DdNode * Func )
+{
+ st_table * tNodes;
+ tNodes = st_init_table( st_ptrcmp, st_ptrhash );
+ extraCollectNodes( Func, tNodes );
+ return tNodes;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Updates the topmost level from which the given node is referenced.]
+
+ Description [Takes the table which maps each BDD nodes (including the constants)
+ into the topmost level on which this node counts as a cofactor. Takes the topmost
+ level, on which this node counts as a cofactor (see Extra_ProfileWidthFast().
+ Takes the node, for which the table entry should be updated.]
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void extraProfileUpdateTopLevel( st_table * tNodeTopRef, int TopLevelNew, DdNode * node )
+{
+ int * pTopLevel;
+
+ if ( st_find_or_add( tNodeTopRef, (char*)node, (char***)&pTopLevel ) )
+ { // the node is already referenced
+ // the current top level should be updated if it is larger than the new level
+ if ( *pTopLevel > TopLevelNew )
+ *pTopLevel = TopLevelNew;
+ }
+ else
+ { // the node is not referenced
+ // its level should be set to the current new level
+ *pTopLevel = TopLevelNew;
+ }
+}
+/**Function*************************************************************
+
+ Synopsis [Fast computation of the BDD profile.]
+
+ Description [The array to store the profile is given by the user and should
+ contain at least as many entries as there is the maximum of the BDD/ZDD
+ size of the manager PLUS ONE.
+ When we say that the widths of the DD on level L is W, we mean the following.
+ Let us create the cut between the level L-1 and the level L and count the number
+ of different DD nodes pointed to across the cut. This number is the width W.
+ From this it follows the on level 0, the width is equal to the number of external
+ pointers to the considered DDs. If there is only one DD, then the profile on
+ level 0 is always 1. If this DD is rooted in the topmost variable, then the width
+ on level 1 is always 2, etc. The width at the level equal to dd->size is the
+ number of terminal nodes in the DD. (Because we consider the first level #0
+ and the last level #dd->size, the profile array should contain dd->size+1 entries.)
+ ]
+
+ SideEffects [This procedure will not work for BDDs w/ complement edges, only for ADDs and ZDDs]
+
+ SeeAlso []
+
+***********************************************************************/
+int Extra_ProfileWidth( DdManager * dd, DdNode * Func, int * pProfile, int CutLevel )
+{
+ st_generator * gen;
+ st_table * tNodeTopRef; // this table stores the top level from which this node is pointed to
+ st_table * tNodes;
+ DdNode * node;
+ DdNode * nodeR;
+ int LevelStart, Limit;
+ int i, size;
+ int WidthMax;
+
+ // start the mapping table
+ tNodeTopRef = st_init_table(st_ptrcmp,st_ptrhash);
+ // add the topmost node to the profile
+ extraProfileUpdateTopLevel( tNodeTopRef, 0, Func );
+
+ // collect all nodes
+ tNodes = Extra_CollectNodes( Func );
+ // go though all the nodes and set the top level the cofactors are pointed from
+// Cudd_ForeachNode( dd, Func, genDD, node )
+ st_foreach_item( tNodes, gen, (char**)&node, NULL )
+ {
+// assert( Cudd_Regular(node) ); // this procedure works only with ADD/ZDD (not BDD w/ compl.edges)
+ nodeR = Cudd_Regular(node);
+ if ( cuddIsConstant(nodeR) )
+ continue;
+ // this node is not a constant - consider its cofactors
+ extraProfileUpdateTopLevel( tNodeTopRef, dd->perm[node->index]+1, cuddE(nodeR) );
+ extraProfileUpdateTopLevel( tNodeTopRef, dd->perm[node->index]+1, cuddT(nodeR) );
+ }
+ st_free_table( tNodes );
+
+ // clean the profile
+ size = ddMax(dd->size, dd->sizeZ) + 1;
+ for ( i = 0; i < size; i++ )
+ pProfile[i] = 0;
+
+ // create the profile
+ st_foreach_item( tNodeTopRef, gen, (char**)&node, (char**)&LevelStart )
+ {
+ nodeR = Cudd_Regular(node);
+ Limit = (cuddIsConstant(nodeR))? dd->size: dd->perm[nodeR->index];
+ for ( i = LevelStart; i <= Limit; i++ )
+ pProfile[i]++;
+ }
+
+ if ( CutLevel != -1 && CutLevel != 0 )
+ size = CutLevel;
+
+ // get the max width
+ WidthMax = 0;
+ for ( i = 0; i < size; i++ )
+ if ( WidthMax < pProfile[i] )
+ WidthMax = pProfile[i];
+
+ // deref the table
+ st_free_table( tNodeTopRef );
+
+ return WidthMax;
+} /* end of Extra_ProfileWidth */
+
+
+/*---------------------------------------------------------------------------*/
+/* Definition of internal functions */
+/*---------------------------------------------------------------------------*/
+
+/*---------------------------------------------------------------------------*/
+/* Definition of static functions */
+/*---------------------------------------------------------------------------*/
+
+/**Function********************************************************************
+
+ Synopsis [Computes the non-strict codes when evaluation is finished.]
+
+ Description [The information about the best code is stored in s_VarOrderBest,
+ which has s_nVarsBest entries.]
+
+ SideEffects [None]
+
+******************************************************************************/
+DdNode * CreateTheCodes_rec( DdManager * dd, DdNode * bEncoded, int Level, DdNode ** pCVars )
+// bEncoded is the preliminarily encoded set of columns
+// Level is the current level in the recursion
+// pCVars are the variables to be used for encoding
+{
+ DdNode * bRes;
+ if ( Level == s_nVarsBest )
+ { // the terminal case, when we need to remap the encoded function
+ // from the preliminary encoded variables to the new ones
+ st_table * CutNodes;
+ int nCols;
+// double nMints;
+/*
+#ifdef _DEBUG
+
+ {
+ DdNode * bTemp;
+ // make sure that the given number of variables is enough
+ bTemp = Cudd_bddExistAbstract( dd, bEncoded, s_VarAll ); Cudd_Ref( bTemp );
+// nMints = Cudd_CountMinterm( dd, bTemp, s_MultiStart );
+ nMints = Extra_CountMintermsSimple( bTemp, (1<<s_MultiStart) );
+ if ( nMints > Extra_Power2( s_MultiStart-Level ) )
+ { // the number of minterms is too large to encode the columns
+ // using the given minimum number of encoding variables
+ assert( 0 );
+ }
+ Cudd_RecursiveDeref( dd, bTemp );
+ }
+#endif
+*/
+ // get the columns to be re-encoded
+ CutNodes = Extra_bddNodePathsUnderCut( dd, bEncoded, s_EncodingVarsLevel );
+ // LUT size is the cut level because because the temporary encoding variables
+ // are above the functional variables - this is not true!!!
+ // the temporary variables are below!
+
+ // put the entries from the table into the temporary array
+ {
+ st_generator * gen;
+ DdNode * bColumn, * bCode;
+ nCols = 0;
+ st_foreach_item( CutNodes, gen, (char**)&bCode, (char**)&bColumn )
+ {
+ if ( bCode == b0 )
+ { // the unused part of the columns
+ Cudd_RecursiveDeref( dd, bColumn );
+ Cudd_RecursiveDeref( dd, bCode );
+ continue;
+ }
+ else
+ {
+ s_pbTemp[ nCols ] = bColumn; // takes ref
+ Cudd_RecursiveDeref( dd, bCode );
+ nCols++;
+ }
+ }
+ st_free_table( CutNodes );
+// assert( nCols == (int)nMints );
+ }
+
+ // encode the columns
+ if ( s_MultiStart-Level == 0 ) // we reached the bottom level of recursion
+ {
+ assert( nCols == 1 );
+// assert( (int)nMints == 1 );
+ bRes = s_pbTemp[0]; Cudd_Ref( bRes );
+ }
+ else
+ {
+ bRes = Extra_bddEncodingBinary( dd, s_pbTemp, nCols, pCVars+Level, s_MultiStart-Level ); Cudd_Ref( bRes );
+ }
+
+ // deref the columns
+ {
+ int i;
+ for ( i = 0; i < nCols; i++ )
+ Cudd_RecursiveDeref( dd, s_pbTemp[i] );
+ }
+ }
+ else
+ {
+ // cofactor the problem as specified in the best solution
+ DdNode * bCof0, * bCof1;
+ DdNode * bRes0, * bRes1;
+ DdNode * bProd0, * bProd1;
+ DdNode * bTemp;
+ DdNode * bVarNext = dd->vars[ s_VarOrderBest[Level] ];
+
+ bCof0 = Cudd_Cofactor( dd, bEncoded, Cudd_Not( bVarNext ) ); Cudd_Ref( bCof0 );
+ bCof1 = Cudd_Cofactor( dd, bEncoded, bVarNext ); Cudd_Ref( bCof1 );
+
+ // call recursively
+ bRes0 = CreateTheCodes_rec( dd, bCof0, Level+1, pCVars ); Cudd_Ref( bRes0 );
+ bRes1 = CreateTheCodes_rec( dd, bCof1, Level+1, pCVars ); Cudd_Ref( bRes1 );
+
+ Cudd_RecursiveDeref( dd, bCof0 );
+ Cudd_RecursiveDeref( dd, bCof1 );
+
+ // compose the result using the identity (bVarNext <=> pCVars[Level]) - this is wrong!
+ // compose the result as follows: x'y'F0 + xyF1
+ bProd0 = Cudd_bddAnd( dd, Cudd_Not(bVarNext), Cudd_Not(pCVars[Level]) ); Cudd_Ref( bProd0 );
+ bProd1 = Cudd_bddAnd( dd, bVarNext , pCVars[Level] ); Cudd_Ref( bProd1 );
+
+ bProd0 = Cudd_bddAnd( dd, bTemp = bProd0, bRes0 ); Cudd_Ref( bProd0 );
+ Cudd_RecursiveDeref( dd, bTemp );
+ Cudd_RecursiveDeref( dd, bRes0 );
+
+ bProd1 = Cudd_bddAnd( dd, bTemp = bProd1, bRes1 ); Cudd_Ref( bProd1 );
+ Cudd_RecursiveDeref( dd, bTemp );
+ Cudd_RecursiveDeref( dd, bRes1 );
+
+ bRes = Cudd_bddOr( dd, bProd0, bProd1 ); Cudd_Ref( bRes );
+
+ Cudd_RecursiveDeref( dd, bProd0 );
+ Cudd_RecursiveDeref( dd, bProd1 );
+ }
+ Cudd_Deref( bRes );
+ return bRes;
+}
+
+/**Function********************************************************************
+
+ Synopsis [Computes the current set of variables and counts the number of minterms.]
+
+ Description [Old implementation.]
+
+ SideEffects []
+
+ SeeAlso []
+
+******************************************************************************/
+void EvaluateEncodings_rec( DdManager * dd, DdNode * bVarsCol, int nVarsCol, int nMulti, int Level )
+// bVarsCol is the set of remaining variables
+// nVarsCol is the number of remaining variables
+// nMulti is the number of encoding variables to be used
+// Level is the level of recursion, from which this function is called
+// if we successfully finish this procedure, Level also stands for how many encoding variabled we saved
+{
+ int i, k;
+ int nEntries = (1<<(Level-1)); // the number of entries in the field of the previous level
+ DdNode * bVars0, * bVars1; // the cofactors
+ unsigned nMint0, nMint1; // the number of minterms
+ DdNode * bTempV;
+ DdNode * bVarTop;
+ int fBreak;
+
+
+ // there is no need to search above this level
+ if ( Level > s_MaxDepth )
+ return;
+
+ // if there are no variables left, quit the research
+ if ( bVarsCol == b1 )
+ return;
+
+ if ( s_BackTracks > s_BackTrackLimit )
+ return;
+
+ s_BackTracks++;
+
+ // otherwise, go through the remaining variables
+ for ( bTempV = bVarsCol; bTempV != b1; bTempV = cuddT(bTempV) )
+ {
+ // the currently tested variable
+ bVarTop = dd->vars[bTempV->index];
+
+ // put it into the array
+ s_VarOrderCur[Level-1] = bTempV->index;
+
+ // go through the entries and fill them out by cofactoring
+ fBreak = 0;
+ for ( i = 0; i < nEntries; i++ )
+ {
+ bVars0 = ComputeVarSetAndCountMinterms( dd, s_Field[Level-1][i], Cudd_Not(bVarTop), &nMint0 );
+ Cudd_Ref( bVars0 );
+
+ if ( nMint0 > Extra_Power2( nMulti-1 ) )
+ {
+ // there is no way to encode - dereference and return
+ Cudd_RecursiveDeref( dd, bVars0 );
+ fBreak = 1;
+ break;
+ }
+
+ bVars1 = ComputeVarSetAndCountMinterms( dd, s_Field[Level-1][i], bVarTop, &nMint1 );
+ Cudd_Ref( bVars1 );
+
+ if ( nMint1 > Extra_Power2( nMulti-1 ) )
+ {
+ // there is no way to encode - dereference and return
+ Cudd_RecursiveDeref( dd, bVars0 );
+ Cudd_RecursiveDeref( dd, bVars1 );
+ fBreak = 1;
+ break;
+ }
+
+ // otherwise, add these two cofactors
+ s_Field[Level][2*i + 0] = bVars0; // takes ref
+ s_Field[Level][2*i + 1] = bVars1; // takes ref
+ }
+
+ if ( !fBreak )
+ {
+ DdNode * bVarsRem;
+ // if we ended up here, it means that the cofactors w.r.t. variable bVarTop satisfy the condition
+ // save this situation
+ if ( s_nVarsBest < Level )
+ {
+ s_nVarsBest = Level;
+ // copy the variable assignment
+ for ( k = 0; k < Level; k++ )
+ s_VarOrderBest[k] = s_VarOrderCur[k];
+ }
+
+ // call recursively
+ // get the new variable set
+ if ( nMulti-1 > 0 )
+ {
+ bVarsRem = Cudd_bddExistAbstract( dd, bVarsCol, bVarTop ); Cudd_Ref( bVarsRem );
+ EvaluateEncodings_rec( dd, bVarsRem, nVarsCol-1, nMulti-1, Level+1 );
+ Cudd_RecursiveDeref( dd, bVarsRem );
+ }
+ }
+
+ // deref the contents of the array
+ for ( k = 0; k < i; k++ )
+ {
+ Cudd_RecursiveDeref( dd, s_Field[Level][2*k + 0] );
+ Cudd_RecursiveDeref( dd, s_Field[Level][2*k + 1] );
+ }
+
+ // if the solution is found, there is no need to continue
+ if ( s_nVarsBest == s_MaxDepth )
+ return;
+
+ // if the solution is found, there is no need to continue
+ if ( s_nVarsBest == s_MultiStart )
+ return;
+ }
+ // at this point, we have tried all possible directions in the space of variables
+}
+
+/**Function********************************************************************
+
+ Synopsis [Computes the current set of variables and counts the number of minterms.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+******************************************************************************/
+DdNode * ComputeVarSetAndCountMinterms( DdManager * dd, DdNode * bVars, DdNode * bVarTop, unsigned * Cost )
+// takes bVars - the variables cofactored so far (some of them may be in negative polarity)
+// bVarTop - the topmost variable w.r.t. which to cofactor (may be in negative polarity)
+// returns the cost and the new set of variables (bVars & bVarTop)
+{
+ DdNode * bVarsRes;
+
+ // get the resulting set of variables
+ bVarsRes = Cudd_bddAnd( dd, bVars, bVarTop ); Cudd_Ref( bVarsRes );
+
+ // increment signature before calling Cudd_CountCofactorMinterms()
+ s_Signature++;
+ *Cost = Extra_CountCofactorMinterms( dd, s_Encoded, bVarsRes, s_VarAll );
+
+ Cudd_Deref( bVarsRes );
+// s_CountCalls++;
+ return bVarsRes;
+}
+
+/**Function********************************************************************
+
+ Synopsis [Computes the current set of variables and counts the number of minterms.]
+
+ Description [The old implementation, which is approximately 4 times slower.]
+
+ SideEffects []
+
+ SeeAlso []
+
+******************************************************************************/
+DdNode * ComputeVarSetAndCountMinterms2( DdManager * dd, DdNode * bVars, DdNode * bVarTop, unsigned * Cost )
+{
+ DdNode * bVarsRes;
+ DdNode * bCof, * bFun;
+
+ bVarsRes = Cudd_bddAnd( dd, bVars, bVarTop ); Cudd_Ref( bVarsRes );
+
+ bCof = Cudd_Cofactor( dd, s_Encoded, bVarsRes ); Cudd_Ref( bCof );
+ bFun = Cudd_bddExistAbstract( dd, bCof, s_VarAll ); Cudd_Ref( bFun );
+ *Cost = (unsigned)Cudd_CountMinterm( dd, bFun, s_MultiStart );
+ Cudd_RecursiveDeref( dd, bFun );
+ Cudd_RecursiveDeref( dd, bCof );
+
+ Cudd_Deref( bVarsRes );
+// s_CountCalls++;
+ return bVarsRes;
+}
+
+
+/**Function********************************************************************
+
+ Synopsis [Counts the number of encoding minterms pointed to by the cofactor of the function.]
+
+ Description []
+
+ SideEffects [None]
+
+******************************************************************************/
+unsigned Extra_CountCofactorMinterms( DdManager * dd, DdNode * bFunc, DdNode * bVarsCof, DdNode * bVarsAll )
+// this function computes how many minterms depending on the encoding variables
+// are there in the cofactor of bFunc w.r.t. variables bVarsCof
+// bFunc is assumed to depend on variables s_VarsAll
+// the variables s_VarsAll should be ordered above the encoding variables
+{
+ unsigned HKey;
+ DdNode * bFuncR;
+
+ // if the function is zero, there are no minterms
+// if ( bFunc == b0 )
+// return 0;
+
+// if ( st_lookup(Visited, (char*)bFunc, NULL) )
+// return 0;
+
+// HKey = hashKey2c( s_Signature, bFuncR );
+// if ( HHTable1[HKey].Sign == s_Signature && HHTable1[HKey].Arg1 == bFuncR ) // this node is visited
+// return 0;
+
+
+ // check the hash-table
+ bFuncR = Cudd_Regular(bFunc);
+// HKey = hashKey2( s_Signature, bFuncR, _TABLESIZE_COF );
+ HKey = hashKey2( s_Signature, bFunc, _TABLESIZE_COF );
+ for ( ; HHTable1[HKey].Sign == s_Signature; HKey = (HKey+1) % _TABLESIZE_COF )
+// if ( HHTable1[HKey].Arg1 == bFuncR ) // this node is visited
+ if ( HHTable1[HKey].Arg1 == bFunc ) // this node is visited
+ return 0;
+
+
+ // if the function is already the code
+ if ( dd->perm[bFuncR->index] >= s_EncodingVarsLevel )
+ {
+// st_insert(Visited, (char*)bFunc, NULL);
+
+// HHTable1[HKey].Sign = s_Signature;
+// HHTable1[HKey].Arg1 = bFuncR;
+
+ assert( HHTable1[HKey].Sign != s_Signature );
+ HHTable1[HKey].Sign = s_Signature;
+// HHTable1[HKey].Arg1 = bFuncR;
+ HHTable1[HKey].Arg1 = bFunc;
+
+ return Extra_CountMintermsSimple( bFunc, (1<<s_MultiStart) );
+ }
+ else
+ {
+ DdNode * bFunc0, * bFunc1;
+ DdNode * bVarsCof0, * bVarsCof1;
+ DdNode * bVarsCofR = Cudd_Regular(bVarsCof);
+ unsigned Res;
+
+ // get the levels
+ int LevelF = dd->perm[bFuncR->index];
+ int LevelC = cuddI(dd,bVarsCofR->index);
+ int LevelA = dd->perm[bVarsAll->index];
+
+ int LevelTop = LevelF;
+
+ if ( LevelTop > LevelC )
+ LevelTop = LevelC;
+
+ if ( LevelTop > LevelA )
+ LevelTop = LevelA;
+
+ // the top var in the function or in cofactoring vars always belongs to the set of all vars
+ assert( !( LevelTop == LevelF || LevelTop == LevelC ) || LevelTop == LevelA );
+
+ // cofactor the function
+ if ( LevelTop == LevelF )
+ {
+ if ( bFuncR != bFunc ) // bFunc is complemented
+ {
+ bFunc0 = Cudd_Not( cuddE(bFuncR) );
+ bFunc1 = Cudd_Not( cuddT(bFuncR) );
+ }
+ else
+ {
+ bFunc0 = cuddE(bFuncR);
+ bFunc1 = cuddT(bFuncR);
+ }
+ }
+ else // bVars is higher in the variable order
+ bFunc0 = bFunc1 = bFunc;
+
+ // cofactor the cube
+ if ( LevelTop == LevelC )
+ {
+ if ( bVarsCofR != bVarsCof ) // bFunc is complemented
+ {
+ bVarsCof0 = Cudd_Not( cuddE(bVarsCofR) );
+ bVarsCof1 = Cudd_Not( cuddT(bVarsCofR) );
+ }
+ else
+ {
+ bVarsCof0 = cuddE(bVarsCofR);
+ bVarsCof1 = cuddT(bVarsCofR);
+ }
+ }
+ else // bVars is higher in the variable order
+ bVarsCof0 = bVarsCof1 = bVarsCof;
+
+ // there are two cases:
+ // (1) the top variable belongs to the cofactoring variables
+ // (2) the top variable does not belong to the cofactoring variables
+
+ // (1) the top variable belongs to the cofactoring variables
+ Res = 0;
+ if ( LevelTop == LevelC )
+ {
+ if ( bVarsCof1 == b0 ) // this is a negative cofactor
+ {
+ if ( bFunc0 != b0 )
+ Res = Extra_CountCofactorMinterms( dd, bFunc0, bVarsCof0, cuddT(bVarsAll) );
+ }
+ else // this is a positive cofactor
+ {
+ if ( bFunc1 != b0 )
+ Res = Extra_CountCofactorMinterms( dd, bFunc1, bVarsCof1, cuddT(bVarsAll) );
+ }
+ }
+ else
+ {
+ if ( bFunc0 != b0 )
+ Res += Extra_CountCofactorMinterms( dd, bFunc0, bVarsCof0, cuddT(bVarsAll) );
+
+ if ( bFunc1 != b0 )
+ Res += Extra_CountCofactorMinterms( dd, bFunc1, bVarsCof1, cuddT(bVarsAll) );
+ }
+
+// st_insert(Visited, (char*)bFunc, NULL);
+
+// HHTable1[HKey].Sign = s_Signature;
+// HHTable1[HKey].Arg1 = bFuncR;
+
+ // skip through the entries with the same signatures
+ // (these might have been created at the time of recursive calls)
+ for ( ; HHTable1[HKey].Sign == s_Signature; HKey = (HKey+1) % _TABLESIZE_COF );
+ assert( HHTable1[HKey].Sign != s_Signature );
+ HHTable1[HKey].Sign = s_Signature;
+// HHTable1[HKey].Arg1 = bFuncR;
+ HHTable1[HKey].Arg1 = bFunc;
+
+ return Res;
+ }
+}
+
+/**Function********************************************************************
+
+ Synopsis [Counts the number of minterms.]
+
+ Description [This function counts minterms for functions up to 32 variables
+ using a local cache. The terminal value (s_Termina) should be adjusted for
+ BDDs and ADDs.]
+
+ SideEffects [None]
+
+******************************************************************************/
+unsigned Extra_CountMintermsSimple( DdNode * bFunc, unsigned max )
+{
+ unsigned HKey;
+
+ // normalize
+ if ( Cudd_IsComplement(bFunc) )
+ return max - Extra_CountMintermsSimple( Cudd_Not(bFunc), max );
+
+ // now it is known that the function is not complemented
+ if ( cuddIsConstant(bFunc) )
+ return ((bFunc==s_Terminal)? 0: max);
+
+ // check cache
+ HKey = hashKey2( bFunc, max, _TABLESIZE_MINT );
+ if ( HHTable2[HKey].Arg1 == bFunc && HHTable2[HKey].Arg2 == max )
+ return HHTable2[HKey].Res;
+ else
+ {
+ // min = min0/2 + min1/2;
+ unsigned min = (Extra_CountMintermsSimple( cuddE(bFunc), max ) >> 1) +
+ (Extra_CountMintermsSimple( cuddT(bFunc), max ) >> 1);
+
+ HHTable2[HKey].Arg1 = bFunc;
+ HHTable2[HKey].Arg2 = max;
+ HHTable2[HKey].Res = min;
+
+ return min;
+ }
+} /* end of Extra_CountMintermsSimple */
+
+
+/**Function********************************************************************
+
+ Synopsis [Visits the nodes.]
+
+ Description [Visits the nodes above the cut and the nodes pointed to below the cut;
+ collects the visited nodes, counts how many times each node is visited, and sets
+ the path-sum to be the constant zero BDD.]
+
+ SideEffects []
+
+ SeeAlso []
+
+******************************************************************************/
+void CountNodeVisits_rec( DdManager * dd, DdNode * aFunc, st_table * Visited )
+
+{
+ traventry * p;
+ char **slot;
+ if ( st_find_or_add(Visited, (char*)aFunc, &slot) )
+ { // the entry already exists
+ p = (traventry*) *slot;
+ // increment the counter of incoming edges
+ p->nEdges++;
+ return;
+ }
+ // this node has not been visited
+ assert( !Cudd_IsComplement(aFunc) );
+
+ // create the new traversal entry
+ p = (traventry *) malloc( sizeof(traventry) );
+ // set the initial sum of edges to zero BDD
+ p->bSum = b0; Cudd_Ref( b0 );
+ // set the starting number of incoming edges
+ p->nEdges = 1;
+ // set this entry into the slot
+ *slot = (char*)p;
+
+ // recur if the node is above the cut
+ if ( cuddI(dd,aFunc->index) < s_CutLevel )
+ {
+ CountNodeVisits_rec( dd, cuddE(aFunc), Visited );
+ CountNodeVisits_rec( dd, cuddT(aFunc), Visited );
+ }
+} /* end of CountNodeVisits_rec */
+
+
+/**Function********************************************************************
+
+ Synopsis [Revisits the nodes and computes the paths.]
+
+ Description [This function visits the nodes above the cut having the goal of
+ summing all the incomming BDD edges; when this function comes across the node
+ below the cut, it saves this node in the CutNode table.]
+
+ SideEffects []
+
+ SeeAlso []
+
+******************************************************************************/
+void CollectNodesAndComputePaths_rec( DdManager * dd, DdNode * aFunc, DdNode * bCube, st_table * Visited, st_table * CutNodes )
+{
+ // find the node in the visited table
+ DdNode * bTemp;
+ traventry * p;
+ char **slot;
+ if ( st_find_or_add(Visited, (char*)aFunc, &slot) )
+ { // the node is found
+ // get the pointer to the traversal entry
+ p = (traventry*) *slot;
+
+ // make sure that the counter of incoming edges is positive
+ assert( p->nEdges > 0 );
+
+ // add the cube to the currently accumulated cubes
+ p->bSum = Cudd_bddOr( dd, bTemp = p->bSum, bCube ); Cudd_Ref( p->bSum );
+ Cudd_RecursiveDeref( dd, bTemp );
+
+ // decrement the number of visits
+ p->nEdges--;
+
+ // if more visits to this node are expected, return
+ if ( p->nEdges )
+ return;
+ else // if ( p->nEdges == 0 )
+ { // this is the last visit - propagate the cube
+
+ // check where this node is
+ if ( cuddI(dd,aFunc->index) < s_CutLevel )
+ { // the node is above the cut
+ DdNode * bCube0, * bCube1;
+
+ // get the top-most variable
+ DdNode * bVarTop = dd->vars[aFunc->index];
+
+ // compute the propagated cubes
+ bCube0 = Cudd_bddAnd( dd, p->bSum, Cudd_Not( bVarTop ) ); Cudd_Ref( bCube0 );
+ bCube1 = Cudd_bddAnd( dd, p->bSum, bVarTop ); Cudd_Ref( bCube1 );
+
+ // call recursively
+ CollectNodesAndComputePaths_rec( dd, cuddE(aFunc), bCube0, Visited, CutNodes );
+ CollectNodesAndComputePaths_rec( dd, cuddT(aFunc), bCube1, Visited, CutNodes );
+
+ // dereference the cubes
+ Cudd_RecursiveDeref( dd, bCube0 );
+ Cudd_RecursiveDeref( dd, bCube1 );
+ return;
+ }
+ else
+ { // the node is below the cut
+ // add this node to the cut node table, if it is not yet there
+
+// DdNode * bNode;
+// bNode = Cudd_addBddPattern( dd, aFunc ); Cudd_Ref( bNode );
+ if ( st_find_or_add(CutNodes, (char*)aFunc, &slot) )
+ { // the node exists - should never happen
+ assert( 0 );
+ }
+ *slot = (char*) p->bSum; Cudd_Ref( p->bSum );
+ // the table takes the reference of bNode
+ return;
+ }
+ }
+ }
+
+ // the node does not exist in the visited table - should never happen
+ assert(0);
+
+} /* end of CollectNodesAndComputePaths_rec */
+
+
+
+////////////////////////////////////////////////////////////////////////
+/// END OF FILE ///
+////////////////////////////////////////////////////////////////////////
diff --git a/src/misc/extra/extraBddKmap.c b/src/misc/extra/extraBddKmap.c
new file mode 100644
index 00000000..bb43db68
--- /dev/null
+++ b/src/misc/extra/extraBddKmap.c
@@ -0,0 +1,783 @@
+/**CFile****************************************************************
+
+ FileName [extraBddKmap.c]
+
+ PackageName [extra]
+
+ Synopsis [Visualizing the K-map.]
+
+ Author [Alan Mishchenko]
+
+ Affiliation [UC Berkeley]
+
+ Date [Ver. 2.0. Started - September 1, 2003.]
+
+ Revision [$Id: extraBddKmap.c,v 1.0 2003/05/21 18:03:50 alanmi Exp $]
+
+***********************************************************************/
+
+/// K-map visualization using pseudo graphics ///
+/// Version 1.0. Started - August 20, 2000 ///
+/// Version 2.0. Added to EXTRA - July 17, 2001 ///
+
+#include "extra.h"
+
+/*---------------------------------------------------------------------------*/
+/* Constant declarations */
+/*---------------------------------------------------------------------------*/
+
+// the maximum number of variables in the Karnaugh Map
+#define MAXVARS 20
+
+/*
+// single line
+#define SINGLE_VERTICAL (char)179
+#define SINGLE_HORIZONTAL (char)196
+#define SINGLE_TOP_LEFT (char)218
+#define SINGLE_TOP_RIGHT (char)191
+#define SINGLE_BOT_LEFT (char)192
+#define SINGLE_BOT_RIGHT (char)217
+
+// double line
+#define DOUBLE_VERTICAL (char)186
+#define DOUBLE_HORIZONTAL (char)205
+#define DOUBLE_TOP_LEFT (char)201
+#define DOUBLE_TOP_RIGHT (char)187
+#define DOUBLE_BOT_LEFT (char)200
+#define DOUBLE_BOT_RIGHT (char)188
+
+// line intersections
+#define SINGLES_CROSS (char)197
+#define DOUBLES_CROSS (char)206
+#define S_HOR_CROSS_D_VER (char)215
+#define S_VER_CROSS_D_HOR (char)216
+
+// single line joining
+#define S_JOINS_S_VER_LEFT (char)180
+#define S_JOINS_S_VER_RIGHT (char)195
+#define S_JOINS_S_HOR_TOP (char)193
+#define S_JOINS_S_HOR_BOT (char)194
+
+// double line joining
+#define D_JOINS_D_VER_LEFT (char)185
+#define D_JOINS_D_VER_RIGHT (char)204
+#define D_JOINS_D_HOR_TOP (char)202
+#define D_JOINS_D_HOR_BOT (char)203
+
+// single line joining double line
+#define S_JOINS_D_VER_LEFT (char)182
+#define S_JOINS_D_VER_RIGHT (char)199
+#define S_JOINS_D_HOR_TOP (char)207
+#define S_JOINS_D_HOR_BOT (char)209
+*/
+
+// single line
+#define SINGLE_VERTICAL (char)'|'
+#define SINGLE_HORIZONTAL (char)'-'
+#define SINGLE_TOP_LEFT (char)'+'
+#define SINGLE_TOP_RIGHT (char)'+'
+#define SINGLE_BOT_LEFT (char)'+'
+#define SINGLE_BOT_RIGHT (char)'+'
+
+// double line
+#define DOUBLE_VERTICAL (char)'|'
+#define DOUBLE_HORIZONTAL (char)'-'
+#define DOUBLE_TOP_LEFT (char)'+'
+#define DOUBLE_TOP_RIGHT (char)'+'
+#define DOUBLE_BOT_LEFT (char)'+'
+#define DOUBLE_BOT_RIGHT (char)'+'
+
+// line intersections
+#define SINGLES_CROSS (char)'+'
+#define DOUBLES_CROSS (char)'+'
+#define S_HOR_CROSS_D_VER (char)'+'
+#define S_VER_CROSS_D_HOR (char)'+'
+
+// single line joining
+#define S_JOINS_S_VER_LEFT (char)'+'
+#define S_JOINS_S_VER_RIGHT (char)'+'
+#define S_JOINS_S_HOR_TOP (char)'+'
+#define S_JOINS_S_HOR_BOT (char)'+'
+
+// double line joining
+#define D_JOINS_D_VER_LEFT (char)'+'
+#define D_JOINS_D_VER_RIGHT (char)'+'
+#define D_JOINS_D_HOR_TOP (char)'+'
+#define D_JOINS_D_HOR_BOT (char)'+'
+
+// single line joining double line
+#define S_JOINS_D_VER_LEFT (char)'+'
+#define S_JOINS_D_VER_RIGHT (char)'+'
+#define S_JOINS_D_HOR_TOP (char)'+'
+#define S_JOINS_D_HOR_BOT (char)'+'
+
+
+// other symbols
+#define UNDERSCORE (char)95
+//#define SYMBOL_ZERO (char)248 // degree sign
+//#define SYMBOL_ZERO (char)'o'
+#define SYMBOL_ZERO (char)' '
+#define SYMBOL_ONE (char)'1'
+#define SYMBOL_DC (char)'-'
+#define SYMBOL_OVERLAP (char)'?'
+
+// full cells and half cells
+#define CELL_FREE (char)32
+#define CELL_FULL (char)219
+#define HALF_UPPER (char)223
+#define HALF_LOWER (char)220
+#define HALF_LEFT (char)221
+#define HALF_RIGHT (char)222
+
+
+/*---------------------------------------------------------------------------*/
+/* Structure declarations */
+/*---------------------------------------------------------------------------*/
+
+/*---------------------------------------------------------------------------*/
+/* Type declarations */
+/*---------------------------------------------------------------------------*/
+
+/*---------------------------------------------------------------------------*/
+/* Variable declarations */
+/*---------------------------------------------------------------------------*/
+
+// the array of BDD variables used internally
+static DdNode * s_XVars[MAXVARS];
+
+// flag which determines where the horizontal variable names are printed
+static int fHorizontalVarNamesPrintedAbove = 1;
+
+/*---------------------------------------------------------------------------*/
+/* Macro declarations */
+/*---------------------------------------------------------------------------*/
+
+
+/**AutomaticStart*************************************************************/
+
+/*---------------------------------------------------------------------------*/
+/* Static function prototypes */
+/*---------------------------------------------------------------------------*/
+
+// Oleg's way of generating the gray code
+static int GrayCode( int BinCode );
+static int BinCode ( int GrayCode );
+
+/**AutomaticEnd***************************************************************/
+
+
+/*---------------------------------------------------------------------------*/
+/* Definition of exported functions */
+/*---------------------------------------------------------------------------*/
+
+
+/**Function********************************************************************
+
+ Synopsis [Prints the K-map of the function.]
+
+ Description [If the pointer to the array of variables XVars is NULL,
+ fSuppType determines how the support will be determined.
+ fSuppType == 0 -- takes the first nVars of the manager
+ fSuppType == 1 -- takes the topmost nVars of the manager
+ fSuppType == 2 -- determines support from the on-set and the offset
+ ]
+
+ SideEffects []
+
+ SeeAlso []
+
+******************************************************************************/
+void Extra_PrintKMap(
+ FILE * Output, /* the output stream */
+ DdManager * dd,
+ DdNode * OnSet,
+ DdNode * OffSet,
+ int nVars,
+ DdNode ** XVars,
+ int fSuppType, /* the flag which determines how support is computed */
+ char ** pVarNames )
+{
+ int d, p, n, s, v, h, w;
+ int nVarsVer;
+ int nVarsHor;
+ int nCellsVer;
+ int nCellsHor;
+ int nSkipSpaces;
+
+ // make sure that on-set and off-set do not overlap
+ if ( !Cudd_bddLeq( dd, OnSet, Cudd_Not(OffSet) ) )
+ {
+ fprintf( Output, "PrintKMap(): The on-set and the off-set overlap\n" );
+ return;
+ }
+/*
+ if ( OnSet == b1 )
+ {
+ fprintf( Output, "PrintKMap(): Constant 1\n" );
+ return;
+ }
+ if ( OffSet == b1 )
+ {
+ fprintf( Output, "PrintKMap(): Constant 0\n" );
+ return;
+ }
+*/
+ if ( nVars < 0 || nVars > MAXVARS )
+ {
+ fprintf( Output, "PrintKMap(): The number of variables is less than zero or more than %d\n", MAXVARS );
+ return;
+ }
+
+ // determine the support if it is not given
+ if ( XVars == NULL )
+ {
+ if ( fSuppType == 0 )
+ { // assume that the support includes the first nVars of the manager
+ assert( nVars );
+ for ( v = 0; v < nVars; v++ )
+ s_XVars[v] = Cudd_bddIthVar( dd, v );
+ }
+ else if ( fSuppType == 1 )
+ { // assume that the support includes the topmost nVars of the manager
+ assert( nVars );
+ for ( v = 0; v < nVars; v++ )
+ s_XVars[v] = Cudd_bddIthVar( dd, dd->invperm[v] );
+ }
+ else // determine the support
+ {
+ DdNode * SuppOn, * SuppOff, * Supp;
+ int cVars = 0;
+ DdNode * TempSupp;
+
+ // determine support
+ SuppOn = Cudd_Support( dd, OnSet ); Cudd_Ref( SuppOn );
+ SuppOff = Cudd_Support( dd, OffSet ); Cudd_Ref( SuppOff );
+ Supp = Cudd_bddAnd( dd, SuppOn, SuppOff ); Cudd_Ref( Supp );
+ Cudd_RecursiveDeref( dd, SuppOn );
+ Cudd_RecursiveDeref( dd, SuppOff );
+
+ nVars = Cudd_SupportSize( dd, Supp );
+ if ( nVars > MAXVARS )
+ {
+ fprintf( Output, "PrintKMap(): The number of variables is more than %d\n", MAXVARS );
+ Cudd_RecursiveDeref( dd, Supp );
+ return;
+ }
+
+ // assign variables
+ for ( TempSupp = Supp; TempSupp != dd->one; TempSupp = Cudd_T(TempSupp), cVars++ )
+ s_XVars[cVars] = Cudd_bddIthVar( dd, TempSupp->index );
+
+ Cudd_RecursiveDeref( dd, TempSupp );
+ }
+ }
+ else
+ {
+ // copy variables
+ assert( XVars );
+ for ( v = 0; v < nVars; v++ )
+ s_XVars[v] = XVars[v];
+ }
+
+ ////////////////////////////////////////////////////////////////////
+ // determine the Karnaugh map parameters
+ nVarsVer = nVars/2;
+ nVarsHor = nVars - nVarsVer;
+ nCellsVer = (1<<nVarsVer);
+ nCellsHor = (1<<nVarsHor);
+ nSkipSpaces = nVarsVer + 1;
+
+ ////////////////////////////////////////////////////////////////////
+ // print variable names
+ fprintf( Output, "\n" );
+ for ( w = 0; w < nVarsVer; w++ )
+ if ( pVarNames == NULL )
+ fprintf( Output, "%c", 'a'+nVarsHor+w );
+ else
+ fprintf( Output, " %s", pVarNames[nVarsHor+w] );
+
+ if ( fHorizontalVarNamesPrintedAbove )
+ {
+ fprintf( Output, " \\ " );
+ for ( w = 0; w < nVarsHor; w++ )
+ if ( pVarNames == NULL )
+ fprintf( Output, "%c", 'a'+w );
+ else
+ fprintf( Output, "%s ", pVarNames[w] );
+ }
+ fprintf( Output, "\n" );
+
+ if ( fHorizontalVarNamesPrintedAbove )
+ {
+ ////////////////////////////////////////////////////////////////////
+ // print horizontal digits
+ for ( d = 0; d < nVarsHor; d++ )
+ {
+ for ( p = 0; p < nSkipSpaces + 2; p++, fprintf( Output, " " ) );
+ for ( n = 0; n < nCellsHor; n++ )
+ if ( GrayCode(n) & (1<<(nVarsHor-1-d)) )
+ fprintf( Output, "1 " );
+ else
+ fprintf( Output, "0 " );
+ fprintf( Output, "\n" );
+ }
+ }
+
+ ////////////////////////////////////////////////////////////////////
+ // print the upper line
+ for ( p = 0; p < nSkipSpaces; p++, fprintf( Output, " " ) );
+ fprintf( Output, "%c", DOUBLE_TOP_LEFT );
+ for ( s = 0; s < nCellsHor; s++ )
+ {
+ fprintf( Output, "%c", DOUBLE_HORIZONTAL );
+ fprintf( Output, "%c", DOUBLE_HORIZONTAL );
+ fprintf( Output, "%c", DOUBLE_HORIZONTAL );
+ if ( s != nCellsHor-1 )
+ if ( s&1 )
+ fprintf( Output, "%c", D_JOINS_D_HOR_BOT );
+ else
+ fprintf( Output, "%c", S_JOINS_D_HOR_BOT );
+ }
+ fprintf( Output, "%c", DOUBLE_TOP_RIGHT );
+ fprintf( Output, "\n" );
+
+ ////////////////////////////////////////////////////////////////////
+ // print the map
+ for ( v = 0; v < nCellsVer; v++ )
+ {
+ DdNode * CubeVerBDD;
+
+ // print horizontal digits
+// for ( p = 0; p < nSkipSpaces; p++, fprintf( Output, " " ) );
+ for ( n = 0; n < nVarsVer; n++ )
+ if ( GrayCode(v) & (1<<(nVarsVer-1-n)) )
+ fprintf( Output, "1" );
+ else
+ fprintf( Output, "0" );
+ fprintf( Output, " " );
+
+ // find vertical cube
+ CubeVerBDD = Extra_bddBitsToCube( dd, GrayCode(v), nVarsVer, s_XVars+nVarsHor, 1 ); Cudd_Ref( CubeVerBDD );
+
+ // print text line
+ fprintf( Output, "%c", DOUBLE_VERTICAL );
+ for ( h = 0; h < nCellsHor; h++ )
+ {
+ DdNode * CubeHorBDD, * Prod, * ValueOnSet, * ValueOffSet;
+
+ fprintf( Output, " " );
+// fprintf( Output, "x" );
+ ///////////////////////////////////////////////////////////////
+ // determine what should be printed
+ CubeHorBDD = Extra_bddBitsToCube( dd, GrayCode(h), nVarsHor, s_XVars, 1 ); Cudd_Ref( CubeHorBDD );
+ Prod = Cudd_bddAnd( dd, CubeHorBDD, CubeVerBDD ); Cudd_Ref( Prod );
+ Cudd_RecursiveDeref( dd, CubeHorBDD );
+
+ ValueOnSet = Cudd_Cofactor( dd, OnSet, Prod ); Cudd_Ref( ValueOnSet );
+ ValueOffSet = Cudd_Cofactor( dd, OffSet, Prod ); Cudd_Ref( ValueOffSet );
+ Cudd_RecursiveDeref( dd, Prod );
+
+ if ( ValueOnSet == b1 && ValueOffSet == b0 )
+ fprintf( Output, "%c", SYMBOL_ONE );
+ else if ( ValueOnSet == b0 && ValueOffSet == b1 )
+ fprintf( Output, "%c", SYMBOL_ZERO );
+ else if ( ValueOnSet == b0 && ValueOffSet == b0 )
+ fprintf( Output, "%c", SYMBOL_DC );
+ else if ( ValueOnSet == b1 && ValueOffSet == b1 )
+ fprintf( Output, "%c", SYMBOL_OVERLAP );
+ else
+ assert(0);
+
+ Cudd_RecursiveDeref( dd, ValueOnSet );
+ Cudd_RecursiveDeref( dd, ValueOffSet );
+ ///////////////////////////////////////////////////////////////
+ fprintf( Output, " " );
+
+ if ( h != nCellsHor-1 )
+ if ( h&1 )
+ fprintf( Output, "%c", DOUBLE_VERTICAL );
+ else
+ fprintf( Output, "%c", SINGLE_VERTICAL );
+ }
+ fprintf( Output, "%c", DOUBLE_VERTICAL );
+ fprintf( Output, "\n" );
+
+ Cudd_RecursiveDeref( dd, CubeVerBDD );
+
+ if ( v != nCellsVer-1 )
+ // print separator line
+ {
+ for ( p = 0; p < nSkipSpaces; p++, fprintf( Output, " " ) );
+ if ( v&1 )
+ {
+ fprintf( Output, "%c", D_JOINS_D_VER_RIGHT );
+ for ( s = 0; s < nCellsHor; s++ )
+ {
+ fprintf( Output, "%c", DOUBLE_HORIZONTAL );
+ fprintf( Output, "%c", DOUBLE_HORIZONTAL );
+ fprintf( Output, "%c", DOUBLE_HORIZONTAL );
+ if ( s != nCellsHor-1 )
+ if ( s&1 )
+ fprintf( Output, "%c", DOUBLES_CROSS );
+ else
+ fprintf( Output, "%c", S_VER_CROSS_D_HOR );
+ }
+ fprintf( Output, "%c", D_JOINS_D_VER_LEFT );
+ }
+ else
+ {
+ fprintf( Output, "%c", S_JOINS_D_VER_RIGHT );
+ for ( s = 0; s < nCellsHor; s++ )
+ {
+ fprintf( Output, "%c", SINGLE_HORIZONTAL );
+ fprintf( Output, "%c", SINGLE_HORIZONTAL );
+ fprintf( Output, "%c", SINGLE_HORIZONTAL );
+ if ( s != nCellsHor-1 )
+ if ( s&1 )
+ fprintf( Output, "%c", S_HOR_CROSS_D_VER );
+ else
+ fprintf( Output, "%c", SINGLES_CROSS );
+ }
+ fprintf( Output, "%c", S_JOINS_D_VER_LEFT );
+ }
+ fprintf( Output, "\n" );
+ }
+ }
+
+ ////////////////////////////////////////////////////////////////////
+ // print the lower line
+ for ( p = 0; p < nSkipSpaces; p++, fprintf( Output, " " ) );
+ fprintf( Output, "%c", DOUBLE_BOT_LEFT );
+ for ( s = 0; s < nCellsHor; s++ )
+ {
+ fprintf( Output, "%c", DOUBLE_HORIZONTAL );
+ fprintf( Output, "%c", DOUBLE_HORIZONTAL );
+ fprintf( Output, "%c", DOUBLE_HORIZONTAL );
+ if ( s != nCellsHor-1 )
+ if ( s&1 )
+ fprintf( Output, "%c", D_JOINS_D_HOR_TOP );
+ else
+ fprintf( Output, "%c", S_JOINS_D_HOR_TOP );
+ }
+ fprintf( Output, "%c", DOUBLE_BOT_RIGHT );
+ fprintf( Output, "\n" );
+
+ if ( !fHorizontalVarNamesPrintedAbove )
+ {
+ ////////////////////////////////////////////////////////////////////
+ // print horizontal digits
+ for ( d = 0; d < nVarsHor; d++ )
+ {
+ for ( p = 0; p < nSkipSpaces + 2; p++, fprintf( Output, " " ) );
+ for ( n = 0; n < nCellsHor; n++ )
+ if ( GrayCode(n) & (1<<(nVarsHor-1-d)) )
+ fprintf( Output, "1 " );
+ else
+ fprintf( Output, "0 " );
+
+ /////////////////////////////////
+ fprintf( Output, "%c", (char)('a'+d) );
+ /////////////////////////////////
+ fprintf( Output, "\n" );
+ }
+ }
+}
+
+
+
+/**Function********************************************************************
+
+ Synopsis [Prints the K-map of the relation.]
+
+ Description [Assumes that the relation depends the first nXVars of XVars and
+ the first nYVars of YVars. Draws X and Y vars and vertical and horizontal vars.]
+
+ SideEffects []
+
+ SeeAlso []
+
+******************************************************************************/
+void Extra_PrintKMapRelation(
+ FILE * Output, /* the output stream */
+ DdManager * dd,
+ DdNode * OnSet,
+ DdNode * OffSet,
+ int nXVars,
+ int nYVars,
+ DdNode ** XVars,
+ DdNode ** YVars ) /* the flag which determines how support is computed */
+{
+ int d, p, n, s, v, h, w;
+ int nVars;
+ int nVarsVer;
+ int nVarsHor;
+ int nCellsVer;
+ int nCellsHor;
+ int nSkipSpaces;
+
+ // make sure that on-set and off-set do not overlap
+ if ( !Cudd_bddLeq( dd, OnSet, Cudd_Not(OffSet) ) )
+ {
+ fprintf( Output, "PrintKMap(): The on-set and the off-set overlap\n" );
+ return;
+ }
+
+ if ( OnSet == b1 )
+ {
+ fprintf( Output, "PrintKMap(): Constant 1\n" );
+ return;
+ }
+ if ( OffSet == b1 )
+ {
+ fprintf( Output, "PrintKMap(): Constant 0\n" );
+ return;
+ }
+
+ nVars = nXVars + nYVars;
+ if ( nVars < 0 || nVars > MAXVARS )
+ {
+ fprintf( Output, "PrintKMap(): The number of variables is less than zero or more than %d\n", MAXVARS );
+ return;
+ }
+
+
+ ////////////////////////////////////////////////////////////////////
+ // determine the Karnaugh map parameters
+ nVarsVer = nXVars;
+ nVarsHor = nYVars;
+ nCellsVer = (1<<nVarsVer);
+ nCellsHor = (1<<nVarsHor);
+ nSkipSpaces = nVarsVer + 1;
+
+ ////////////////////////////////////////////////////////////////////
+ // print variable names
+ fprintf( Output, "\n" );
+ for ( w = 0; w < nVarsVer; w++ )
+ fprintf( Output, "%c", 'a'+nVarsHor+w );
+ if ( fHorizontalVarNamesPrintedAbove )
+ {
+ fprintf( Output, " \\ " );
+ for ( w = 0; w < nVarsHor; w++ )
+ fprintf( Output, "%c", 'a'+w );
+ }
+ fprintf( Output, "\n" );
+
+ if ( fHorizontalVarNamesPrintedAbove )
+ {
+ ////////////////////////////////////////////////////////////////////
+ // print horizontal digits
+ for ( d = 0; d < nVarsHor; d++ )
+ {
+ for ( p = 0; p < nSkipSpaces + 2; p++, fprintf( Output, " " ) );
+ for ( n = 0; n < nCellsHor; n++ )
+ if ( GrayCode(n) & (1<<(nVarsHor-1-d)) )
+ fprintf( Output, "1 " );
+ else
+ fprintf( Output, "0 " );
+ fprintf( Output, "\n" );
+ }
+ }
+
+ ////////////////////////////////////////////////////////////////////
+ // print the upper line
+ for ( p = 0; p < nSkipSpaces; p++, fprintf( Output, " " ) );
+ fprintf( Output, "%c", DOUBLE_TOP_LEFT );
+ for ( s = 0; s < nCellsHor; s++ )
+ {
+ fprintf( Output, "%c", DOUBLE_HORIZONTAL );
+ fprintf( Output, "%c", DOUBLE_HORIZONTAL );
+ fprintf( Output, "%c", DOUBLE_HORIZONTAL );
+ if ( s != nCellsHor-1 )
+ if ( s&1 )
+ fprintf( Output, "%c", D_JOINS_D_HOR_BOT );
+ else
+ fprintf( Output, "%c", S_JOINS_D_HOR_BOT );
+ }
+ fprintf( Output, "%c", DOUBLE_TOP_RIGHT );
+ fprintf( Output, "\n" );
+
+ ////////////////////////////////////////////////////////////////////
+ // print the map
+ for ( v = 0; v < nCellsVer; v++ )
+ {
+ DdNode * CubeVerBDD;
+
+ // print horizontal digits
+// for ( p = 0; p < nSkipSpaces; p++, fprintf( Output, " " ) );
+ for ( n = 0; n < nVarsVer; n++ )
+ if ( GrayCode(v) & (1<<(nVarsVer-1-n)) )
+ fprintf( Output, "1" );
+ else
+ fprintf( Output, "0" );
+ fprintf( Output, " " );
+
+ // find vertical cube
+// CubeVerBDD = Extra_bddBitsToCube( dd, GrayCode(v), nVarsVer, s_XVars+nVarsHor ); Cudd_Ref( CubeVerBDD );
+ CubeVerBDD = Extra_bddBitsToCube( dd, GrayCode(v), nXVars, XVars, 1 ); Cudd_Ref( CubeVerBDD );
+
+ // print text line
+ fprintf( Output, "%c", DOUBLE_VERTICAL );
+ for ( h = 0; h < nCellsHor; h++ )
+ {
+ DdNode * CubeHorBDD, * Prod, * ValueOnSet, * ValueOffSet;
+
+ fprintf( Output, " " );
+// fprintf( Output, "x" );
+ ///////////////////////////////////////////////////////////////
+ // determine what should be printed
+// CubeHorBDD = Extra_bddBitsToCube( dd, GrayCode(h), nVarsHor, s_XVars ); Cudd_Ref( CubeHorBDD );
+ CubeHorBDD = Extra_bddBitsToCube( dd, GrayCode(h), nYVars, YVars, 1 ); Cudd_Ref( CubeHorBDD );
+ Prod = Cudd_bddAnd( dd, CubeHorBDD, CubeVerBDD ); Cudd_Ref( Prod );
+ Cudd_RecursiveDeref( dd, CubeHorBDD );
+
+ ValueOnSet = Cudd_Cofactor( dd, OnSet, Prod ); Cudd_Ref( ValueOnSet );
+ ValueOffSet = Cudd_Cofactor( dd, OffSet, Prod ); Cudd_Ref( ValueOffSet );
+ Cudd_RecursiveDeref( dd, Prod );
+
+ if ( ValueOnSet == b1 && ValueOffSet == b0 )
+ fprintf( Output, "%c", SYMBOL_ONE );
+ else if ( ValueOnSet == b0 && ValueOffSet == b1 )
+ fprintf( Output, "%c", SYMBOL_ZERO );
+ else if ( ValueOnSet == b0 && ValueOffSet == b0 )
+ fprintf( Output, "%c", SYMBOL_DC );
+ else if ( ValueOnSet == b1 && ValueOffSet == b1 )
+ fprintf( Output, "%c", SYMBOL_OVERLAP );
+ else
+ assert(0);
+
+ Cudd_RecursiveDeref( dd, ValueOnSet );
+ Cudd_RecursiveDeref( dd, ValueOffSet );
+ ///////////////////////////////////////////////////////////////
+ fprintf( Output, " " );
+
+ if ( h != nCellsHor-1 )
+ if ( h&1 )
+ fprintf( Output, "%c", DOUBLE_VERTICAL );
+ else
+ fprintf( Output, "%c", SINGLE_VERTICAL );
+ }
+ fprintf( Output, "%c", DOUBLE_VERTICAL );
+ fprintf( Output, "\n" );
+
+ Cudd_RecursiveDeref( dd, CubeVerBDD );
+
+ if ( v != nCellsVer-1 )
+ // print separator line
+ {
+ for ( p = 0; p < nSkipSpaces; p++, fprintf( Output, " " ) );
+ if ( v&1 )
+ {
+ fprintf( Output, "%c", D_JOINS_D_VER_RIGHT );
+ for ( s = 0; s < nCellsHor; s++ )
+ {
+ fprintf( Output, "%c", DOUBLE_HORIZONTAL );
+ fprintf( Output, "%c", DOUBLE_HORIZONTAL );
+ fprintf( Output, "%c", DOUBLE_HORIZONTAL );
+ if ( s != nCellsHor-1 )
+ if ( s&1 )
+ fprintf( Output, "%c", DOUBLES_CROSS );
+ else
+ fprintf( Output, "%c", S_VER_CROSS_D_HOR );
+ }
+ fprintf( Output, "%c", D_JOINS_D_VER_LEFT );
+ }
+ else
+ {
+ fprintf( Output, "%c", S_JOINS_D_VER_RIGHT );
+ for ( s = 0; s < nCellsHor; s++ )
+ {
+ fprintf( Output, "%c", SINGLE_HORIZONTAL );
+ fprintf( Output, "%c", SINGLE_HORIZONTAL );
+ fprintf( Output, "%c", SINGLE_HORIZONTAL );
+ if ( s != nCellsHor-1 )
+ if ( s&1 )
+ fprintf( Output, "%c", S_HOR_CROSS_D_VER );
+ else
+ fprintf( Output, "%c", SINGLES_CROSS );
+ }
+ fprintf( Output, "%c", S_JOINS_D_VER_LEFT );
+ }
+ fprintf( Output, "\n" );
+ }
+ }
+
+ ////////////////////////////////////////////////////////////////////
+ // print the lower line
+ for ( p = 0; p < nSkipSpaces; p++, fprintf( Output, " " ) );
+ fprintf( Output, "%c", DOUBLE_BOT_LEFT );
+ for ( s = 0; s < nCellsHor; s++ )
+ {
+ fprintf( Output, "%c", DOUBLE_HORIZONTAL );
+ fprintf( Output, "%c", DOUBLE_HORIZONTAL );
+ fprintf( Output, "%c", DOUBLE_HORIZONTAL );
+ if ( s != nCellsHor-1 )
+ if ( s&1 )
+ fprintf( Output, "%c", D_JOINS_D_HOR_TOP );
+ else
+ fprintf( Output, "%c", S_JOINS_D_HOR_TOP );
+ }
+ fprintf( Output, "%c", DOUBLE_BOT_RIGHT );
+ fprintf( Output, "\n" );
+
+ if ( !fHorizontalVarNamesPrintedAbove )
+ {
+ ////////////////////////////////////////////////////////////////////
+ // print horizontal digits
+ for ( d = 0; d < nVarsHor; d++ )
+ {
+ for ( p = 0; p < nSkipSpaces + 2; p++, fprintf( Output, " " ) );
+ for ( n = 0; n < nCellsHor; n++ )
+ if ( GrayCode(n) & (1<<(nVarsHor-1-d)) )
+ fprintf( Output, "1 " );
+ else
+ fprintf( Output, "0 " );
+
+ /////////////////////////////////
+ fprintf( Output, "%c", (char)('a'+d) );
+ /////////////////////////////////
+ fprintf( Output, "\n" );
+ }
+ }
+}
+
+
+
+/*---------------------------------------------------------------------------*/
+/* Definition of static functions */
+/*---------------------------------------------------------------------------*/
+
+/**Function********************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+******************************************************************************/
+int GrayCode ( int BinCode )
+{
+ return BinCode ^ ( BinCode >> 1 );
+}
+
+/**Function********************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+******************************************************************************/
+int BinCode ( int GrayCode )
+{
+ int bc = GrayCode;
+ while( GrayCode >>= 1 ) bc ^= GrayCode;
+ return bc;
+}
+
+
diff --git a/src/misc/extra/extraBddMisc.c b/src/misc/extra/extraBddMisc.c
index 373ce5c5..a3320ad3 100644
--- a/src/misc/extra/extraBddMisc.c
+++ b/src/misc/extra/extraBddMisc.c
@@ -14,7 +14,7 @@
Date [Ver. 1.0. Started - June 20, 2005.]
- Revision [$Id: extraBddMisc.c,v 1.0 2003/09/01 00:00:00 alanmi Exp $]
+ Revision [$Id: extraBddMisc.c,v 1.4 2005/10/04 00:19:54 alanmi Exp $]
***********************************************************************/
@@ -50,10 +50,13 @@
// file "extraDdTransfer.c"
static DdNode * extraTransferPermuteRecur( DdManager * ddS, DdManager * ddD, DdNode * f, st_table * table, int * Permute );
static DdNode * extraTransferPermute( DdManager * ddS, DdManager * ddD, DdNode * f, int * Permute );
+static DdNode * cuddBddPermuteRecur ARGS( ( DdManager * manager, DdHashTable * table, DdNode * node, int *permut ) );
// file "cuddUtils.c"
-static void ddSupportStep ARGS((DdNode *f, int *support));
-static void ddClearFlag ARGS((DdNode *f));
+static void ddSupportStep(DdNode *f, int *support);
+static void ddClearFlag(DdNode *f);
+
+static DdNode* extraZddPrimes( DdManager *dd, DdNode* F );
/**AutomaticEnd***************************************************************/
@@ -684,6 +687,280 @@ DdNode * Extra_bddComputeRangeCube( DdManager * dd, int iStart, int iStop )
return bProd;
}
+/**Function********************************************************************
+
+ Synopsis [Computes the cube of BDD variables corresponding to bits it the bit-code]
+
+ Description [Returns a bdd composed of elementary bdds found in array BddVars[] such
+ that the bdd vars encode the number Value of bit length CodeWidth (if fMsbFirst is 1,
+ the most significant bit is encoded with the first bdd variable). If the variables
+ BddVars are not specified, takes the first CodeWidth variables of the manager]
+
+ SideEffects []
+
+ SeeAlso []
+
+******************************************************************************/
+DdNode * Extra_bddBitsToCube( DdManager * dd, int Code, int CodeWidth, DdNode ** pbVars, int fMsbFirst )
+{
+ int z;
+ DdNode * bTemp, * bVar, * bVarBdd, * bResult;
+
+ bResult = b1; Cudd_Ref( bResult );
+ for ( z = 0; z < CodeWidth; z++ )
+ {
+ bVarBdd = (pbVars)? pbVars[z]: dd->vars[z];
+ if ( fMsbFirst )
+ bVar = Cudd_NotCond( bVarBdd, (Code & (1 << (CodeWidth-1-z)))==0 );
+ else
+ bVar = Cudd_NotCond( bVarBdd, (Code & (1 << (z)))==0 );
+ bResult = Cudd_bddAnd( dd, bTemp = bResult, bVar ); Cudd_Ref( bResult );
+ Cudd_RecursiveDeref( dd, bTemp );
+ }
+ Cudd_Deref( bResult );
+
+ return bResult;
+} /* end of Extra_bddBitsToCube */
+
+/**Function********************************************************************
+
+ Synopsis [Finds the support as a negative polarity cube.]
+
+ Description [Finds the variables on which a DD depends. Returns a BDD
+ consisting of the product of the variables in the negative polarity
+ if successful; NULL otherwise.]
+
+ SideEffects [None]
+
+ SeeAlso [Cudd_VectorSupport Cudd_Support]
+
+******************************************************************************/
+DdNode * Extra_bddSupportNegativeCube( DdManager * dd, DdNode * f )
+{
+ int *support;
+ DdNode *res, *tmp, *var;
+ int i, j;
+ int size;
+
+ /* Allocate and initialize support array for ddSupportStep. */
+ size = ddMax( dd->size, dd->sizeZ );
+ support = ALLOC( int, size );
+ if ( support == NULL )
+ {
+ dd->errorCode = CUDD_MEMORY_OUT;
+ return ( NULL );
+ }
+ for ( i = 0; i < size; i++ )
+ {
+ support[i] = 0;
+ }
+
+ /* Compute support and clean up markers. */
+ ddSupportStep( Cudd_Regular( f ), support );
+ ddClearFlag( Cudd_Regular( f ) );
+
+ /* Transform support from array to cube. */
+ do
+ {
+ dd->reordered = 0;
+ res = DD_ONE( dd );
+ cuddRef( res );
+ for ( j = size - 1; j >= 0; j-- )
+ { /* for each level bottom-up */
+ i = ( j >= dd->size ) ? j : dd->invperm[j];
+ if ( support[i] == 1 )
+ {
+ var = cuddUniqueInter( dd, i, dd->one, Cudd_Not( dd->one ) );
+ //////////////////////////////////////////////////////////////////
+ var = Cudd_Not(var);
+ //////////////////////////////////////////////////////////////////
+ cuddRef( var );
+ tmp = cuddBddAndRecur( dd, res, var );
+ if ( tmp == NULL )
+ {
+ Cudd_RecursiveDeref( dd, res );
+ Cudd_RecursiveDeref( dd, var );
+ res = NULL;
+ break;
+ }
+ cuddRef( tmp );
+ Cudd_RecursiveDeref( dd, res );
+ Cudd_RecursiveDeref( dd, var );
+ res = tmp;
+ }
+ }
+ }
+ while ( dd->reordered == 1 );
+
+ FREE( support );
+ if ( res != NULL )
+ cuddDeref( res );
+ return ( res );
+
+} /* end of Extra_SupportNeg */
+
+/**Function********************************************************************
+
+ Synopsis [Returns 1 if the BDD is the BDD of elementary variable.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+******************************************************************************/
+int Extra_bddIsVar( DdNode * bFunc )
+{
+ bFunc = Cudd_Regular( bFunc );
+ if ( cuddIsConstant(bFunc) )
+ return 0;
+ return cuddIsConstant( cuddT(bFunc) ) && cuddIsConstant( Cudd_Regular(cuddE(bFunc)) );
+}
+
+/**Function********************************************************************
+
+ Synopsis [Creates AND composed of the first nVars of the manager.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+******************************************************************************/
+DdNode * Extra_bddCreateAnd( DdManager * dd, int nVars )
+{
+ DdNode * bFunc, * bTemp;
+ int i;
+ bFunc = Cudd_ReadOne(dd); Cudd_Ref( bFunc );
+ for ( i = 0; i < nVars; i++ )
+ {
+ bFunc = Cudd_bddAnd( dd, bTemp = bFunc, Cudd_bddIthVar(dd,i) ); Cudd_Ref( bFunc );
+ Cudd_RecursiveDeref( dd, bTemp );
+ }
+ Cudd_Deref( bFunc );
+ return bFunc;
+}
+
+/**Function********************************************************************
+
+ Synopsis [Creates OR composed of the first nVars of the manager.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+******************************************************************************/
+DdNode * Extra_bddCreateOr( DdManager * dd, int nVars )
+{
+ DdNode * bFunc, * bTemp;
+ int i;
+ bFunc = Cudd_ReadLogicZero(dd); Cudd_Ref( bFunc );
+ for ( i = 0; i < nVars; i++ )
+ {
+ bFunc = Cudd_bddOr( dd, bTemp = bFunc, Cudd_bddIthVar(dd,i) ); Cudd_Ref( bFunc );
+ Cudd_RecursiveDeref( dd, bTemp );
+ }
+ Cudd_Deref( bFunc );
+ return bFunc;
+}
+
+/**Function********************************************************************
+
+ Synopsis [Creates EXOR composed of the first nVars of the manager.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+******************************************************************************/
+DdNode * Extra_bddCreateExor( DdManager * dd, int nVars )
+{
+ DdNode * bFunc, * bTemp;
+ int i;
+ bFunc = Cudd_ReadLogicZero(dd); Cudd_Ref( bFunc );
+ for ( i = 0; i < nVars; i++ )
+ {
+ bFunc = Cudd_bddXor( dd, bTemp = bFunc, Cudd_bddIthVar(dd,i) ); Cudd_Ref( bFunc );
+ Cudd_RecursiveDeref( dd, bTemp );
+ }
+ Cudd_Deref( bFunc );
+ return bFunc;
+}
+
+/**Function********************************************************************
+
+ Synopsis [Computes the set of primes as a ZDD.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+******************************************************************************/
+DdNode * Extra_zddPrimes( DdManager * dd, DdNode * F )
+{
+ DdNode *res;
+ do {
+ dd->reordered = 0;
+ res = extraZddPrimes(dd, F);
+ if ( dd->reordered == 1 )
+ printf("\nReordering in Extra_zddPrimes()\n");
+ } while (dd->reordered == 1);
+ return(res);
+
+} /* end of Extra_zddPrimes */
+
+/**Function********************************************************************
+
+ Synopsis [Permutes the variables of the array of BDDs.]
+
+ Description [Given a permutation in array permut, creates a new BDD
+ with permuted variables. There should be an entry in array permut
+ for each variable in the manager. The i-th entry of permut holds the
+ index of the variable that is to substitute the i-th variable.
+ The DDs in the resulting array are already referenced.]
+
+ SideEffects [None]
+
+ SeeAlso [Cudd_addPermute Cudd_bddSwapVariables]
+
+******************************************************************************/
+void Extra_bddPermuteArray( DdManager * manager, DdNode ** bNodesIn, DdNode ** bNodesOut, int nNodes, int *permut )
+{
+ DdHashTable *table;
+ int i, k;
+ do
+ {
+ manager->reordered = 0;
+ table = cuddHashTableInit( manager, 1, 2 );
+
+ /* permute the output functions one-by-one */
+ for ( i = 0; i < nNodes; i++ )
+ {
+ bNodesOut[i] = cuddBddPermuteRecur( manager, table, bNodesIn[i], permut );
+ if ( bNodesOut[i] == NULL )
+ {
+ /* deref the array of the already computed outputs */
+ for ( k = 0; k < i; k++ )
+ Cudd_RecursiveDeref( manager, bNodesOut[k] );
+ break;
+ }
+ cuddRef( bNodesOut[i] );
+ }
+ /* Dispose of local cache. */
+ cuddHashTableQuit( table );
+ }
+ while ( manager->reordered == 1 );
+} /* end of Extra_bddPermuteArray */
+
+
/*---------------------------------------------------------------------------*/
/* Definition of internal functions */
/*---------------------------------------------------------------------------*/
@@ -1039,6 +1316,297 @@ ddClearFlag(
} /* end of ddClearFlag */
+/**Function********************************************************************
+
+ Synopsis [Composed three subcovers into one ZDD.]
+
+ Description []
+
+ SideEffects [None]
+
+ SeeAlso []
+
+******************************************************************************/
+DdNode *
+extraComposeCover(
+ DdManager* dd, /* the manager */
+ DdNode* zC0, /* the pointer to the negative var cofactor */
+ DdNode* zC1, /* the pointer to the positive var cofactor */
+ DdNode* zC2, /* the pointer to the cofactor without var */
+ int TopVar) /* the index of the positive ZDD var */
+{
+ DdNode * zRes, * zTemp;
+ /* compose with-neg-var and without-var using the neg ZDD var */
+ zTemp = cuddZddGetNode( dd, 2*TopVar + 1, zC0, zC2 );
+ if ( zTemp == NULL )
+ {
+ Cudd_RecursiveDerefZdd(dd, zC0);
+ Cudd_RecursiveDerefZdd(dd, zC1);
+ Cudd_RecursiveDerefZdd(dd, zC2);
+ return NULL;
+ }
+ cuddRef( zTemp );
+ cuddDeref( zC0 );
+ cuddDeref( zC2 );
+
+ /* compose with-pos-var and previous result using the pos ZDD var */
+ zRes = cuddZddGetNode( dd, 2*TopVar, zC1, zTemp );
+ if ( zRes == NULL )
+ {
+ Cudd_RecursiveDerefZdd(dd, zC1);
+ Cudd_RecursiveDerefZdd(dd, zTemp);
+ return NULL;
+ }
+ cuddDeref( zC1 );
+ cuddDeref( zTemp );
+ return zRes;
+} /* extraComposeCover */
+
+/**Function********************************************************************
+
+ Synopsis [Performs the recursive step of prime computation.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+******************************************************************************/
+DdNode* extraZddPrimes( DdManager *dd, DdNode* F )
+{
+ DdNode *zRes;
+
+ if ( F == Cudd_Not( dd->one ) )
+ return dd->zero;
+ if ( F == dd->one )
+ return dd->one;
+
+ /* check cache */
+ zRes = cuddCacheLookup1Zdd(dd, extraZddPrimes, F);
+ if (zRes)
+ return(zRes);
+ {
+ /* temporary variables */
+ DdNode *bF01, *zP0, *zP1;
+ /* three components of the prime set */
+ DdNode *zResE, *zResP, *zResN;
+ int fIsComp = Cudd_IsComplement( F );
+
+ /* find cofactors of F */
+ DdNode * bF0 = Cudd_NotCond( Cudd_E( F ), fIsComp );
+ DdNode * bF1 = Cudd_NotCond( Cudd_T( F ), fIsComp );
+
+ /* find the intersection of cofactors */
+ bF01 = cuddBddAndRecur( dd, bF0, bF1 );
+ if ( bF01 == NULL ) return NULL;
+ cuddRef( bF01 );
+
+ /* solve the problems for cofactors */
+ zP0 = extraZddPrimes( dd, bF0 );
+ if ( zP0 == NULL )
+ {
+ Cudd_RecursiveDeref( dd, bF01 );
+ return NULL;
+ }
+ cuddRef( zP0 );
+
+ zP1 = extraZddPrimes( dd, bF1 );
+ if ( zP1 == NULL )
+ {
+ Cudd_RecursiveDeref( dd, bF01 );
+ Cudd_RecursiveDerefZdd( dd, zP0 );
+ return NULL;
+ }
+ cuddRef( zP1 );
+
+ /* check for local unateness */
+ if ( bF01 == bF0 ) /* unate increasing */
+ {
+ /* intersection is useless */
+ cuddDeref( bF01 );
+ /* the primes of intersection are the primes of F0 */
+ zResE = zP0;
+ /* there are no primes with negative var */
+ zResN = dd->zero;
+ cuddRef( zResN );
+ /* primes with positive var are primes of F1 that are not primes of F01 */
+ zResP = cuddZddDiff( dd, zP1, zP0 );
+ if ( zResP == NULL )
+ {
+ Cudd_RecursiveDerefZdd( dd, zResE );
+ Cudd_RecursiveDerefZdd( dd, zResN );
+ Cudd_RecursiveDerefZdd( dd, zP1 );
+ return NULL;
+ }
+ cuddRef( zResP );
+ Cudd_RecursiveDerefZdd( dd, zP1 );
+ }
+ else if ( bF01 == bF1 ) /* unate decreasing */
+ {
+ /* intersection is useless */
+ cuddDeref( bF01 );
+ /* the primes of intersection are the primes of F1 */
+ zResE = zP1;
+ /* there are no primes with positive var */
+ zResP = dd->zero;
+ cuddRef( zResP );
+ /* primes with negative var are primes of F0 that are not primes of F01 */
+ zResN = cuddZddDiff( dd, zP0, zP1 );
+ if ( zResN == NULL )
+ {
+ Cudd_RecursiveDerefZdd( dd, zResE );
+ Cudd_RecursiveDerefZdd( dd, zResP );
+ Cudd_RecursiveDerefZdd( dd, zP0 );
+ return NULL;
+ }
+ cuddRef( zResN );
+ Cudd_RecursiveDerefZdd( dd, zP0 );
+ }
+ else /* not unate */
+ {
+ /* primes without the top var are primes of F10 */
+ zResE = extraZddPrimes( dd, bF01 );
+ if ( zResE == NULL )
+ {
+ Cudd_RecursiveDerefZdd( dd, bF01 );
+ Cudd_RecursiveDerefZdd( dd, zP0 );
+ Cudd_RecursiveDerefZdd( dd, zP1 );
+ return NULL;
+ }
+ cuddRef( zResE );
+ Cudd_RecursiveDeref( dd, bF01 );
+
+ /* primes with the negative top var are those of P0 that are not in F10 */
+ zResN = cuddZddDiff( dd, zP0, zResE );
+ if ( zResN == NULL )
+ {
+ Cudd_RecursiveDerefZdd( dd, zResE );
+ Cudd_RecursiveDerefZdd( dd, zP0 );
+ Cudd_RecursiveDerefZdd( dd, zP1 );
+ return NULL;
+ }
+ cuddRef( zResN );
+ Cudd_RecursiveDerefZdd( dd, zP0 );
+
+ /* primes with the positive top var are those of P1 that are not in F10 */
+ zResP = cuddZddDiff( dd, zP1, zResE );
+ if ( zResP == NULL )
+ {
+ Cudd_RecursiveDerefZdd( dd, zResE );
+ Cudd_RecursiveDerefZdd( dd, zResN );
+ Cudd_RecursiveDerefZdd( dd, zP1 );
+ return NULL;
+ }
+ cuddRef( zResP );
+ Cudd_RecursiveDerefZdd( dd, zP1 );
+ }
+
+ zRes = extraComposeCover( dd, zResN, zResP, zResE, Cudd_Regular(F)->index );
+ if ( zRes == NULL ) return NULL;
+
+ /* insert the result into cache */
+ cuddCacheInsert1(dd, extraZddPrimes, F, zRes);
+ return zRes;
+ }
+} /* end of extraZddPrimes */
+
+/**Function********************************************************************
+
+ Synopsis [Implements the recursive step of Cudd_bddPermute.]
+
+ Description [ Recursively puts the BDD in the order given in the array permut.
+ Checks for trivial cases to terminate recursion, then splits on the
+ children of this node. Once the solutions for the children are
+ obtained, it puts into the current position the node from the rest of
+ the BDD that should be here. Then returns this BDD.
+ The key here is that the node being visited is NOT put in its proper
+ place by this instance, but rather is switched when its proper position
+ is reached in the recursion tree.<p>
+ The DdNode * that is returned is the same BDD as passed in as node,
+ but in the new order.]
+
+ SideEffects [None]
+
+ SeeAlso [Cudd_bddPermute cuddAddPermuteRecur]
+
+******************************************************************************/
+static DdNode *
+cuddBddPermuteRecur( DdManager * manager /* DD manager */ ,
+ DdHashTable * table /* computed table */ ,
+ DdNode * node /* BDD to be reordered */ ,
+ int *permut /* permutation array */ )
+{
+ DdNode *N, *T, *E;
+ DdNode *res;
+ int index;
+
+ statLine( manager );
+ N = Cudd_Regular( node );
+
+ /* Check for terminal case of constant node. */
+ if ( cuddIsConstant( N ) )
+ {
+ return ( node );
+ }
+
+ /* If problem already solved, look up answer and return. */
+ if ( N->ref != 1 && ( res = cuddHashTableLookup1( table, N ) ) != NULL )
+ {
+#ifdef DD_DEBUG
+ bddPermuteRecurHits++;
+#endif
+ return ( Cudd_NotCond( res, N != node ) );
+ }
+
+ /* Split and recur on children of this node. */
+ T = cuddBddPermuteRecur( manager, table, cuddT( N ), permut );
+ if ( T == NULL )
+ return ( NULL );
+ cuddRef( T );
+ E = cuddBddPermuteRecur( manager, table, cuddE( N ), permut );
+ if ( E == NULL )
+ {
+ Cudd_IterDerefBdd( manager, T );
+ return ( NULL );
+ }
+ cuddRef( E );
+
+ /* Move variable that should be in this position to this position
+ ** by retrieving the single var BDD for that variable, and calling
+ ** cuddBddIteRecur with the T and E we just created.
+ */
+ index = permut[N->index];
+ res = cuddBddIteRecur( manager, manager->vars[index], T, E );
+ if ( res == NULL )
+ {
+ Cudd_IterDerefBdd( manager, T );
+ Cudd_IterDerefBdd( manager, E );
+ return ( NULL );
+ }
+ cuddRef( res );
+ Cudd_IterDerefBdd( manager, T );
+ Cudd_IterDerefBdd( manager, E );
+
+ /* Do not keep the result if the reference count is only 1, since
+ ** it will not be visited again.
+ */
+ if ( N->ref != 1 )
+ {
+ ptrint fanout = ( ptrint ) N->ref;
+ cuddSatDec( fanout );
+ if ( !cuddHashTableInsert1( table, N, res, fanout ) )
+ {
+ Cudd_IterDerefBdd( manager, res );
+ return ( NULL );
+ }
+ }
+ cuddDeref( res );
+ return ( Cudd_NotCond( res, N != node ) );
+
+} /* end of cuddBddPermuteRecur */
+
+
////////////////////////////////////////////////////////////////////////
/// END OF FILE ///
////////////////////////////////////////////////////////////////////////
diff --git a/src/misc/extra/extraBddSymm.c b/src/misc/extra/extraBddSymm.c
index 474f663f..358402b0 100644
--- a/src/misc/extra/extraBddSymm.c
+++ b/src/misc/extra/extraBddSymm.c
@@ -223,7 +223,7 @@ Extra_SymmInfo_t * Extra_SymmPairsAllocate( int nVars )
/**Function********************************************************************
- Synopsis [Delocates symmetry information structure.]
+ Synopsis [Deallocates symmetry information structure.]
Description []
diff --git a/src/misc/extra/extraBddUnate.c b/src/misc/extra/extraBddUnate.c
new file mode 100644
index 00000000..b0297c77
--- /dev/null
+++ b/src/misc/extra/extraBddUnate.c
@@ -0,0 +1,641 @@
+/**CFile****************************************************************
+
+ FileName [extraBddUnate.c]
+
+ PackageName [extra]
+
+ Synopsis [Efficient methods to compute the information about
+ unate variables using an algorithm that is conceptually similar to
+ the algorithm for two-variable symmetry computation presented in:
+ A. Mishchenko. Fast Computation of Symmetries in Boolean Functions.
+ Transactions on CAD, Nov. 2003.]
+
+ Author [Alan Mishchenko]
+
+ Affiliation [UC Berkeley]
+
+ Date [Ver. 2.0. Started - September 1, 2003.]
+
+ Revision [$Id: extraBddUnate.c,v 1.0 2003/09/01 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "extra.h"
+
+/*---------------------------------------------------------------------------*/
+/* Constant declarations */
+/*---------------------------------------------------------------------------*/
+
+/*---------------------------------------------------------------------------*/
+/* Stucture declarations */
+/*---------------------------------------------------------------------------*/
+
+/*---------------------------------------------------------------------------*/
+/* Type declarations */
+/*---------------------------------------------------------------------------*/
+
+/*---------------------------------------------------------------------------*/
+/* Variable declarations */
+/*---------------------------------------------------------------------------*/
+
+/*---------------------------------------------------------------------------*/
+/* Macro declarations */
+/*---------------------------------------------------------------------------*/
+
+/**AutomaticStart*************************************************************/
+
+/*---------------------------------------------------------------------------*/
+/* Static function prototypes */
+/*---------------------------------------------------------------------------*/
+
+/**AutomaticEnd***************************************************************/
+
+/*---------------------------------------------------------------------------*/
+/* Definition of exported functions */
+/*---------------------------------------------------------------------------*/
+
+
+/**Function********************************************************************
+
+ Synopsis [Computes the classical symmetry information for the function.]
+
+ Description [Returns the symmetry information in the form of Extra_UnateInfo_t structure.]
+
+ SideEffects [If the ZDD variables are not derived from BDD variables with
+ multiplicity 2, this function may derive them in a wrong way.]
+
+ SeeAlso []
+
+******************************************************************************/
+Extra_UnateInfo_t * Extra_UnateComputeFast(
+ DdManager * dd, /* the manager */
+ DdNode * bFunc) /* the function whose symmetries are computed */
+{
+ DdNode * bSupp;
+ DdNode * zRes;
+ Extra_UnateInfo_t * p;
+
+ bSupp = Cudd_Support( dd, bFunc ); Cudd_Ref( bSupp );
+ zRes = Extra_zddUnateInfoCompute( dd, bFunc, bSupp ); Cudd_Ref( zRes );
+
+ p = Extra_UnateInfoCreateFromZdd( dd, zRes, bSupp );
+
+ Cudd_RecursiveDeref( dd, bSupp );
+ Cudd_RecursiveDerefZdd( dd, zRes );
+
+ return p;
+
+} /* end of Extra_UnateInfoCompute */
+
+
+/**Function********************************************************************
+
+ Synopsis [Computes the classical symmetry information as a ZDD.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+******************************************************************************/
+DdNode * Extra_zddUnateInfoCompute(
+ DdManager * dd, /* the DD manager */
+ DdNode * bF,
+ DdNode * bVars)
+{
+ DdNode * res;
+ do {
+ dd->reordered = 0;
+ res = extraZddUnateInfoCompute( dd, bF, bVars );
+ } while (dd->reordered == 1);
+ return(res);
+
+} /* end of Extra_zddUnateInfoCompute */
+
+
+/**Function********************************************************************
+
+ Synopsis [Converts a set of variables into a set of singleton subsets.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+******************************************************************************/
+DdNode * Extra_zddGetSingletonsBoth(
+ DdManager * dd, /* the DD manager */
+ DdNode * bVars) /* the set of variables */
+{
+ DdNode * res;
+ do {
+ dd->reordered = 0;
+ res = extraZddGetSingletonsBoth( dd, bVars );
+ } while (dd->reordered == 1);
+ return(res);
+
+} /* end of Extra_zddGetSingletonsBoth */
+
+/**Function********************************************************************
+
+ Synopsis [Allocates unateness information structure.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+******************************************************************************/
+Extra_UnateInfo_t * Extra_UnateInfoAllocate( int nVars )
+{
+ Extra_UnateInfo_t * p;
+ // allocate and clean the storage for unateness info
+ p = ALLOC( Extra_UnateInfo_t, 1 );
+ memset( p, 0, sizeof(Extra_UnateInfo_t) );
+ p->nVars = nVars;
+ p->pVars = ALLOC( Extra_UnateVar_t, nVars );
+ memset( p->pVars, 0, nVars * sizeof(Extra_UnateVar_t) );
+ return p;
+} /* end of Extra_UnateInfoAllocate */
+
+/**Function********************************************************************
+
+ Synopsis [Deallocates symmetry information structure.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+******************************************************************************/
+void Extra_UnateInfoDissolve( Extra_UnateInfo_t * p )
+{
+ free( p->pVars );
+ free( p );
+} /* end of Extra_UnateInfoDissolve */
+
+/**Function********************************************************************
+
+ Synopsis [Allocates symmetry information structure.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+******************************************************************************/
+void Extra_UnateInfoPrint( Extra_UnateInfo_t * p )
+{
+ char * pBuffer;
+ int i;
+ pBuffer = ALLOC( char, p->nVarsMax+1 );
+ memset( pBuffer, ' ', p->nVarsMax );
+ pBuffer[p->nVarsMax] = 0;
+ for ( i = 0; i < p->nVars; i++ )
+ if ( p->pVars[i].Neg )
+ pBuffer[ p->pVars[i].iVar ] = 'n';
+ else if ( p->pVars[i].Pos )
+ pBuffer[ p->pVars[i].iVar ] = 'p';
+ else
+ pBuffer[ p->pVars[i].iVar ] = '.';
+ printf( "%s\n", pBuffer );
+ free( pBuffer );
+} /* end of Extra_UnateInfoPrint */
+
+
+/**Function********************************************************************
+
+ Synopsis [Creates the symmetry information structure from ZDD.]
+
+ Description [ZDD representation of symmetries is the set of cubes, each
+ of which has two variables in the positive polarity. These variables correspond
+ to the symmetric variable pair.]
+
+ SideEffects []
+
+ SeeAlso []
+
+******************************************************************************/
+Extra_UnateInfo_t * Extra_UnateInfoCreateFromZdd( DdManager * dd, DdNode * zPairs, DdNode * bSupp )
+{
+ Extra_UnateInfo_t * p;
+ DdNode * bTemp, * zSet, * zCube, * zTemp;
+ int * pMapVars2Nums;
+ int i, nSuppSize;
+
+ nSuppSize = Extra_bddSuppSize( dd, bSupp );
+
+ // allocate and clean the storage for symmetry info
+ p = Extra_UnateInfoAllocate( nSuppSize );
+
+ // allocate the storage for the temporary map
+ pMapVars2Nums = ALLOC( int, dd->size );
+ memset( pMapVars2Nums, 0, dd->size * sizeof(int) );
+
+ // assign the variables
+ p->nVarsMax = dd->size;
+ for ( i = 0, bTemp = bSupp; bTemp != b1; bTemp = cuddT(bTemp), i++ )
+ {
+ p->pVars[i].iVar = bTemp->index;
+ pMapVars2Nums[bTemp->index] = i;
+ }
+
+ // write the symmetry info into the structure
+ zSet = zPairs; Cudd_Ref( zSet );
+// Cudd_zddPrintCover( dd, zPairs ); printf( "\n" );
+ while ( zSet != z0 )
+ {
+ // get the next cube
+ zCube = Extra_zddSelectOneSubset( dd, zSet ); Cudd_Ref( zCube );
+
+ // add this var to the data structure
+ assert( cuddT(zCube) == z1 && cuddE(zCube) == z0 );
+ if ( zCube->index & 1 ) // neg
+ p->pVars[ pMapVars2Nums[zCube->index/2] ].Neg = 1;
+ else
+ p->pVars[ pMapVars2Nums[zCube->index/2] ].Pos = 1;
+ // count the unate vars
+ p->nUnate++;
+
+ // update the cuver and deref the cube
+ zSet = Cudd_zddDiff( dd, zTemp = zSet, zCube ); Cudd_Ref( zSet );
+ Cudd_RecursiveDerefZdd( dd, zTemp );
+ Cudd_RecursiveDerefZdd( dd, zCube );
+
+ } // for each cube
+ Cudd_RecursiveDerefZdd( dd, zSet );
+ FREE( pMapVars2Nums );
+ return p;
+
+} /* end of Extra_UnateInfoCreateFromZdd */
+
+
+
+/**Function********************************************************************
+
+ Synopsis [Computes the classical unateness information for the function.]
+
+ Description [Uses the naive way of comparing cofactors.]
+
+ SideEffects []
+
+ SeeAlso []
+
+******************************************************************************/
+Extra_UnateInfo_t * Extra_UnateComputeSlow( DdManager * dd, DdNode * bFunc )
+{
+ int nSuppSize;
+ DdNode * bSupp, * bTemp;
+ Extra_UnateInfo_t * p;
+ int i, Res;
+
+ // compute the support
+ bSupp = Cudd_Support( dd, bFunc ); Cudd_Ref( bSupp );
+ nSuppSize = Extra_bddSuppSize( dd, bSupp );
+//printf( "Support = %d. ", nSuppSize );
+//Extra_bddPrint( dd, bSupp );
+//printf( "%d ", nSuppSize );
+
+ // allocate the storage for symmetry info
+ p = Extra_UnateInfoAllocate( nSuppSize );
+
+ // assign the variables
+ p->nVarsMax = dd->size;
+ for ( i = 0, bTemp = bSupp; bTemp != b1; bTemp = cuddT(bTemp), i++ )
+ {
+ Res = Extra_bddCheckUnateNaive( dd, bFunc, bTemp->index );
+ p->pVars[i].iVar = bTemp->index;
+ if ( Res == -1 )
+ p->pVars[i].Neg = 1;
+ else if ( Res == 1 )
+ p->pVars[i].Pos = 1;
+ p->nUnate += (Res != 0);
+ }
+ Cudd_RecursiveDeref( dd, bSupp );
+ return p;
+
+} /* end of Extra_UnateComputeSlow */
+
+/**Function********************************************************************
+
+ Synopsis [Checks if the two variables are symmetric.]
+
+ Description [Returns 0 if vars are not unate. Return -1/+1 if the var is neg/pos unate.]
+
+ SideEffects []
+
+ SeeAlso []
+
+******************************************************************************/
+int Extra_bddCheckUnateNaive(
+ DdManager * dd, /* the DD manager */
+ DdNode * bF,
+ int iVar)
+{
+ DdNode * bCof0, * bCof1;
+ int Res;
+
+ assert( iVar < dd->size );
+
+ bCof0 = Cudd_Cofactor( dd, bF, Cudd_Not(Cudd_bddIthVar(dd,iVar)) ); Cudd_Ref( bCof0 );
+ bCof1 = Cudd_Cofactor( dd, bF, Cudd_bddIthVar(dd,iVar) ); Cudd_Ref( bCof1 );
+
+ if ( Cudd_bddLeq( dd, bCof0, bCof1 ) )
+ Res = 1;
+ else if ( Cudd_bddLeq( dd, bCof1, bCof0 ) )
+ Res =-1;
+ else
+ Res = 0;
+
+ Cudd_RecursiveDeref( dd, bCof0 );
+ Cudd_RecursiveDeref( dd, bCof1 );
+ return Res;
+} /* end of Extra_bddCheckUnateNaive */
+
+
+
+/*---------------------------------------------------------------------------*/
+/* Definition of internal functions */
+/*---------------------------------------------------------------------------*/
+
+/**Function********************************************************************
+
+ Synopsis [Performs a recursive step of Extra_UnateInfoCompute.]
+
+ Description [Returns the set of symmetric variable pairs represented as a set
+ of two-literal ZDD cubes. Both variables always appear in the positive polarity
+ in the cubes. This function works without building new BDD nodes. Some relatively
+ small number of ZDD nodes may be built to ensure proper bookkeeping of the
+ symmetry information.]
+
+ SideEffects []
+
+ SeeAlso []
+
+******************************************************************************/
+DdNode *
+extraZddUnateInfoCompute(
+ DdManager * dd, /* the manager */
+ DdNode * bFunc, /* the function whose symmetries are computed */
+ DdNode * bVars ) /* the set of variables on which this function depends */
+{
+ DdNode * zRes;
+ DdNode * bFR = Cudd_Regular(bFunc);
+
+ if ( cuddIsConstant(bFR) )
+ {
+ if ( cuddIsConstant(bVars) )
+ return z0;
+ return extraZddGetSingletonsBoth( dd, bVars );
+ }
+ assert( bVars != b1 );
+
+ if ( zRes = cuddCacheLookup2Zdd(dd, extraZddUnateInfoCompute, bFunc, bVars) )
+ return zRes;
+ else
+ {
+ DdNode * zRes0, * zRes1;
+ DdNode * zTemp, * zPlus;
+ DdNode * bF0, * bF1;
+ DdNode * bVarsNew;
+ int nVarsExtra;
+ int LevelF;
+ int AddVar;
+
+ // every variable in bF should be also in bVars, therefore LevelF cannot be above LevelV
+ // if LevelF is below LevelV, scroll through the vars in bVars to the same level as F
+ // count how many extra vars are there in bVars
+ nVarsExtra = 0;
+ LevelF = dd->perm[bFR->index];
+ for ( bVarsNew = bVars; LevelF > dd->perm[bVarsNew->index]; bVarsNew = cuddT(bVarsNew) )
+ nVarsExtra++;
+ // the indexes (level) of variables should be synchronized now
+ assert( bFR->index == bVarsNew->index );
+
+ // cofactor the function
+ if ( bFR != bFunc ) // bFunc is complemented
+ {
+ bF0 = Cudd_Not( cuddE(bFR) );
+ bF1 = Cudd_Not( cuddT(bFR) );
+ }
+ else
+ {
+ bF0 = cuddE(bFR);
+ bF1 = cuddT(bFR);
+ }
+
+ // solve subproblems
+ zRes0 = extraZddUnateInfoCompute( dd, bF0, cuddT(bVarsNew) );
+ if ( zRes0 == NULL )
+ return NULL;
+ cuddRef( zRes0 );
+
+ // if there is no symmetries in the negative cofactor
+ // there is no need to test the positive cofactor
+ if ( zRes0 == z0 )
+ zRes = zRes0; // zRes takes reference
+ else
+ {
+ zRes1 = extraZddUnateInfoCompute( dd, bF1, cuddT(bVarsNew) );
+ if ( zRes1 == NULL )
+ {
+ Cudd_RecursiveDerefZdd( dd, zRes0 );
+ return NULL;
+ }
+ cuddRef( zRes1 );
+
+ // only those variables are pair-wise symmetric
+ // that are pair-wise symmetric in both cofactors
+ // therefore, intersect the solutions
+ zRes = cuddZddIntersect( dd, zRes0, zRes1 );
+ if ( zRes == NULL )
+ {
+ Cudd_RecursiveDerefZdd( dd, zRes0 );
+ Cudd_RecursiveDerefZdd( dd, zRes1 );
+ return NULL;
+ }
+ cuddRef( zRes );
+ Cudd_RecursiveDerefZdd( dd, zRes0 );
+ Cudd_RecursiveDerefZdd( dd, zRes1 );
+ }
+
+ // consider the current top-most variable
+ AddVar = -1;
+ if ( Cudd_bddLeq( dd, bF0, bF1 ) ) // pos
+ AddVar = 0;
+ else if ( Cudd_bddLeq( dd, bF1, bF0 ) ) // neg
+ AddVar = 1;
+ if ( AddVar >= 0 )
+ {
+ // create the singleton
+ zPlus = cuddZddGetNode( dd, 2*bFR->index + AddVar, z1, z0 );
+ if ( zPlus == NULL )
+ {
+ Cudd_RecursiveDerefZdd( dd, zRes );
+ return NULL;
+ }
+ cuddRef( zPlus );
+
+ // add these to the result
+ zRes = cuddZddUnion( dd, zTemp = zRes, zPlus );
+ if ( zRes == NULL )
+ {
+ Cudd_RecursiveDerefZdd( dd, zTemp );
+ Cudd_RecursiveDerefZdd( dd, zPlus );
+ return NULL;
+ }
+ cuddRef( zRes );
+ Cudd_RecursiveDerefZdd( dd, zTemp );
+ Cudd_RecursiveDerefZdd( dd, zPlus );
+ }
+ // only zRes is referenced at this point
+
+ // if we skipped some variables, these variables cannot be symmetric with
+ // any variables that are currently in the support of bF, but they can be
+ // symmetric with the variables that are in bVars but not in the support of bF
+ for ( bVarsNew = bVars; LevelF > dd->perm[bVarsNew->index]; bVarsNew = cuddT(bVarsNew) )
+ {
+ // create the negative singleton
+ zPlus = cuddZddGetNode( dd, 2*bVarsNew->index+1, z1, z0 );
+ if ( zPlus == NULL )
+ {
+ Cudd_RecursiveDerefZdd( dd, zRes );
+ return NULL;
+ }
+ cuddRef( zPlus );
+
+ // add these to the result
+ zRes = cuddZddUnion( dd, zTemp = zRes, zPlus );
+ if ( zRes == NULL )
+ {
+ Cudd_RecursiveDerefZdd( dd, zTemp );
+ Cudd_RecursiveDerefZdd( dd, zPlus );
+ return NULL;
+ }
+ cuddRef( zRes );
+ Cudd_RecursiveDerefZdd( dd, zTemp );
+ Cudd_RecursiveDerefZdd( dd, zPlus );
+
+
+ // create the positive singleton
+ zPlus = cuddZddGetNode( dd, 2*bVarsNew->index, z1, z0 );
+ if ( zPlus == NULL )
+ {
+ Cudd_RecursiveDerefZdd( dd, zRes );
+ return NULL;
+ }
+ cuddRef( zPlus );
+
+ // add these to the result
+ zRes = cuddZddUnion( dd, zTemp = zRes, zPlus );
+ if ( zRes == NULL )
+ {
+ Cudd_RecursiveDerefZdd( dd, zTemp );
+ Cudd_RecursiveDerefZdd( dd, zPlus );
+ return NULL;
+ }
+ cuddRef( zRes );
+ Cudd_RecursiveDerefZdd( dd, zTemp );
+ Cudd_RecursiveDerefZdd( dd, zPlus );
+ }
+ cuddDeref( zRes );
+
+ /* insert the result into cache */
+ cuddCacheInsert2(dd, extraZddUnateInfoCompute, bFunc, bVars, zRes);
+ return zRes;
+ }
+} /* end of extraZddUnateInfoCompute */
+
+
+/**Function********************************************************************
+
+ Synopsis [Performs a recursive step of Extra_zddGetSingletons.]
+
+ Description [Returns the set of ZDD singletons, containing those pos/neg
+ polarity ZDD variables that correspond to the BDD variables in bVars.]
+
+ SideEffects []
+
+ SeeAlso []
+
+******************************************************************************/
+DdNode * extraZddGetSingletonsBoth(
+ DdManager * dd, /* the DD manager */
+ DdNode * bVars) /* the set of variables */
+{
+ DdNode * zRes;
+
+ if ( bVars == b1 )
+ return z1;
+
+ if ( zRes = cuddCacheLookup1Zdd(dd, extraZddGetSingletonsBoth, bVars) )
+ return zRes;
+ else
+ {
+ DdNode * zTemp, * zPlus;
+
+ // solve subproblem
+ zRes = extraZddGetSingletonsBoth( dd, cuddT(bVars) );
+ if ( zRes == NULL )
+ return NULL;
+ cuddRef( zRes );
+
+
+ // create the negative singleton
+ zPlus = cuddZddGetNode( dd, 2*bVars->index+1, z1, z0 );
+ if ( zPlus == NULL )
+ {
+ Cudd_RecursiveDerefZdd( dd, zRes );
+ return NULL;
+ }
+ cuddRef( zPlus );
+
+ // add these to the result
+ zRes = cuddZddUnion( dd, zTemp = zRes, zPlus );
+ if ( zRes == NULL )
+ {
+ Cudd_RecursiveDerefZdd( dd, zTemp );
+ Cudd_RecursiveDerefZdd( dd, zPlus );
+ return NULL;
+ }
+ cuddRef( zRes );
+ Cudd_RecursiveDerefZdd( dd, zTemp );
+ Cudd_RecursiveDerefZdd( dd, zPlus );
+
+
+ // create the positive singleton
+ zPlus = cuddZddGetNode( dd, 2*bVars->index, z1, z0 );
+ if ( zPlus == NULL )
+ {
+ Cudd_RecursiveDerefZdd( dd, zRes );
+ return NULL;
+ }
+ cuddRef( zPlus );
+
+ // add these to the result
+ zRes = cuddZddUnion( dd, zTemp = zRes, zPlus );
+ if ( zRes == NULL )
+ {
+ Cudd_RecursiveDerefZdd( dd, zTemp );
+ Cudd_RecursiveDerefZdd( dd, zPlus );
+ return NULL;
+ }
+ cuddRef( zRes );
+ Cudd_RecursiveDerefZdd( dd, zTemp );
+ Cudd_RecursiveDerefZdd( dd, zPlus );
+
+ cuddDeref( zRes );
+ cuddCacheInsert1( dd, extraZddGetSingletonsBoth, bVars, zRes );
+ return zRes;
+ }
+} /* end of extraZddGetSingletonsBoth */
+
+
+/*---------------------------------------------------------------------------*/
+/* Definition of static Functions */
+/*---------------------------------------------------------------------------*/
diff --git a/src/misc/extra/extraUtilBitMatrix.c b/src/misc/extra/extraUtilBitMatrix.c
index 93cbbeac..b860a538 100644
--- a/src/misc/extra/extraUtilBitMatrix.c
+++ b/src/misc/extra/extraUtilBitMatrix.c
@@ -348,7 +348,7 @@ int Extra_BitMatrixCountOnesUpper( Extra_BitMat_t * p )
int i, k, nTotal = 0;
for ( i = 0; i < p->nSize; i++ )
for ( k = i + 1; k < p->nSize; k++ )
- nTotal += ( (p->ppData[i][k/32] & (1 << (k%32))) > 0 );
+ nTotal += ( (p->ppData[i][k>>5] & (1 << (k&31))) > 0 );
return nTotal;
}
diff --git a/src/misc/extra/extraUtilCanon.c b/src/misc/extra/extraUtilCanon.c
index 9d4e5b5d..fcc7d84d 100644
--- a/src/misc/extra/extraUtilCanon.c
+++ b/src/misc/extra/extraUtilCanon.c
@@ -99,7 +99,8 @@ int Extra_TruthCanonFastN( int nVarsMax, int nVarsReal, unsigned * pt, unsigned
Description []
- SideEffects []
+ SideEffects [This procedure has a bug, which shows on Solaris.
+ Most likely has something to do with the casts, i.g *((unsigned *)pt0)]
SeeAlso []
@@ -129,21 +130,22 @@ int Extra_TruthCanonN_rec( int nVars, unsigned char * pt, unsigned ** pptRes, ch
pt0 = pt;
pt1 = pt + (1 << nVarsN) / 8;
// 5-var truth tables for this call
- uInit0 = *((unsigned *)pt0);
- uInit1 = *((unsigned *)pt1);
+// uInit0 = *((unsigned *)pt0);
+// uInit1 = *((unsigned *)pt1);
if ( nVarsN == 3 )
{
- uInit0 &= 0xFF;
- uInit1 &= 0xFF;
- uInit0 = (uInit0 << 24) | (uInit0 << 16) | (uInit0 << 8) | uInit0;
- uInit1 = (uInit1 << 24) | (uInit1 << 16) | (uInit1 << 8) | uInit1;
+ uInit0 = (pt0[0] << 24) | (pt0[0] << 16) | (pt0[0] << 8) | pt0[0];
+ uInit1 = (pt1[0] << 24) | (pt1[0] << 16) | (pt1[0] << 8) | pt1[0];
}
else if ( nVarsN == 4 )
{
- uInit0 &= 0xFFFF;
- uInit1 &= 0xFFFF;
- uInit0 = (uInit0 << 16) | uInit0;
- uInit1 = (uInit1 << 16) | uInit1;
+ uInit0 = (pt0[1] << 24) | (pt0[0] << 16) | (pt0[1] << 8) | pt0[0];
+ uInit1 = (pt1[1] << 24) | (pt1[0] << 16) | (pt1[1] << 8) | pt1[0];
+ }
+ else
+ {
+ uInit0 = (pt0[3] << 24) | (pt0[2] << 16) | (pt0[1] << 8) | pt0[0];
+ uInit1 = (pt1[3] << 24) | (pt1[2] << 16) | (pt1[1] << 8) | pt1[0];
}
// storage for truth tables and phases
diff --git a/src/misc/extra/extraUtilFile.c b/src/misc/extra/extraUtilFile.c
index 03b31fea..4c51b8b5 100644
--- a/src/misc/extra/extraUtilFile.c
+++ b/src/misc/extra/extraUtilFile.c
@@ -110,7 +110,7 @@ char * Extra_FileGetSimilarName( char * pFileNameWrong, char * pS1, char * pS2,
/**Function*************************************************************
- Synopsis []
+ Synopsis [Returns the pointer to the file extension.]
Description []
@@ -119,21 +119,14 @@ char * Extra_FileGetSimilarName( char * pFileNameWrong, char * pS1, char * pS2,
SeeAlso []
***********************************************************************/
-int Extra_FileNameCheckExtension( char * FileName, char * Extension )
+char * Extra_FileNameExtension( char * FileName )
{
char * pDot;
- // find "dot" if it is present in the file name
-// pDot = strstr( FileName, "." );
+ // find the last "dot" in the file name, if it is present
for ( pDot = FileName + strlen(FileName)-1; pDot >= FileName; pDot-- )
if ( *pDot == '.' )
- break;
- if ( *pDot != '.' )
- return 0;
- // check the extension
- if ( pDot && strcmp( pDot+1, Extension ) == 0 )
- return 1;
- else
- return 0;
+ return pDot + 1;
+ return NULL;
}
/**Function*************************************************************
@@ -172,7 +165,7 @@ char * Extra_FileNameGeneric( char * FileName )
char * pRes;
// find the generic name of the file
- pRes = util_strsav( FileName );
+ pRes = Extra_UtilStrsav( FileName );
// find the pointer to the "." symbol in the file name
// pUnd = strstr( FileName, "_" );
pUnd = NULL;
@@ -255,8 +248,8 @@ char * Extra_FileRead( FILE * pFile )
char * Extra_TimeStamp()
{
static char Buffer[100];
- time_t ltime;
char * TimeStamp;
+ time_t ltime;
// get the current time
time( &ltime );
TimeStamp = asctime( localtime( &ltime ) );
@@ -320,6 +313,97 @@ void Extra_PrintBinary( FILE * pFile, unsigned Sign[], int nBits )
/**Function*************************************************************
+ Synopsis [Reads the hex unsigned into the bit-string.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Extra_ReadHexadecimal( unsigned Sign[], char * pString, int nVars )
+{
+ int nWords, nDigits, Digit, k, c;
+ nWords = Extra_TruthWordNum( nVars );
+ for ( k = 0; k < nWords; k++ )
+ Sign[k] = 0;
+ // read the number from the string
+ nDigits = (1 << nVars) / 4;
+ if ( nDigits == 0 )
+ nDigits = 1;
+ for ( k = 0; k < nDigits; k++ )
+ {
+ c = nDigits-1-k;
+ if ( pString[c] >= '0' && pString[c] <= '9' )
+ Digit = pString[c] - '0';
+ else if ( pString[c] >= 'A' && pString[c] <= 'F' )
+ Digit = pString[c] - 'A' + 10;
+ else if ( pString[c] >= 'a' && pString[c] <= 'f' )
+ Digit = pString[c] - 'a' + 10;
+ else { assert( 0 ); return 0; }
+ Sign[k/8] |= ( (Digit & 15) << ((k%8) * 4) );
+ }
+ return 1;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Prints the hex unsigned into a file.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Extra_PrintHexadecimal( FILE * pFile, unsigned Sign[], int nVars )
+{
+ int nDigits, Digit, k;
+ // write the number into the file
+ nDigits = (1 << nVars) / 4;
+ for ( k = nDigits - 1; k >= 0; k-- )
+ {
+ Digit = ((Sign[k/8] >> ((k%8) * 4)) & 15);
+ if ( Digit < 10 )
+ fprintf( pFile, "%d", Digit );
+ else
+ fprintf( pFile, "%c", 'a' + Digit-10 );
+ }
+// fprintf( pFile, "\n" );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Prints the hex unsigned into a file.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Extra_PrintHexadecimalString( char * pString, unsigned Sign[], int nVars )
+{
+ int nDigits, Digit, k;
+ // write the number into the file
+ nDigits = (1 << nVars) / 4;
+ for ( k = nDigits - 1; k >= 0; k-- )
+ {
+ Digit = ((Sign[k/8] >> ((k%8) * 4)) & 15);
+ if ( Digit < 10 )
+ *pString++ = '0' + Digit;
+ else
+ *pString++ = 'a' + Digit-10;
+ }
+// fprintf( pFile, "\n" );
+ *pString = 0;
+}
+
+/**Function*************************************************************
+
Synopsis [Prints the hex unsigned into a file.]
Description []
@@ -391,7 +475,7 @@ char * Extra_StringAppend( char * pStrGiven, char * pStrAdd )
free( pStrGiven );
}
else
- pTemp = util_strsav( pStrAdd );
+ pTemp = Extra_UtilStrsav( pStrAdd );
return pTemp;
}
diff --git a/src/misc/extra/extraUtilMemory.c b/src/misc/extra/extraUtilMemory.c
index af1128ac..6eccf015 100644
--- a/src/misc/extra/extraUtilMemory.c
+++ b/src/misc/extra/extraUtilMemory.c
@@ -73,6 +73,9 @@ struct Extra_MmStep_t_
Extra_MmFixed_t ** pMems; // memory managers: 2^1 words, 2^2 words, etc
int nMapSize; // the size of the memory array
Extra_MmFixed_t ** pMap; // maps the number of bytes into its memory manager
+ int nLargeChunksAlloc; // the maximum number of large memory chunks
+ int nLargeChunks; // the current number of large memory chunks
+ void ** pLargeChunks; // the allocated large memory chunks
};
/*---------------------------------------------------------------------------*/
@@ -152,18 +155,30 @@ Extra_MmFixed_t * Extra_MmFixedStart( int nEntrySize )
SeeAlso []
***********************************************************************/
-void Extra_MmFixedStop( Extra_MmFixed_t * p, int fVerbose )
+void Extra_MmFixedPrint( Extra_MmFixed_t * p )
+{
+ printf( "Fixed memory manager: Entry = %5d. Chunk = %5d. Chunks used = %5d.\n",
+ p->nEntrySize, p->nChunkSize, p->nChunks );
+ printf( " Entries used = %8d. Entries peak = %8d. Memory used = %8d. Memory alloc = %8d.\n",
+ p->nEntriesUsed, p->nEntriesMax, p->nEntrySize * p->nEntriesUsed, p->nMemoryAlloc );
+}
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Extra_MmFixedStop( Extra_MmFixed_t * p )
{
int i;
if ( p == NULL )
return;
- if ( fVerbose )
- {
- printf( "Fixed memory manager: Entry = %5d. Chunk = %5d. Chunks used = %5d.\n",
- p->nEntrySize, p->nChunkSize, p->nChunks );
- printf( " Entries used = %8d. Entries peak = %8d. Memory used = %8d. Memory alloc = %8d.\n",
- p->nEntriesUsed, p->nEntriesMax, p->nEntrySize * p->nEntriesUsed, p->nMemoryAlloc );
- }
for ( i = 0; i < p->nChunks; i++ )
free( p->pChunks[i] );
free( p->pChunks );
@@ -257,7 +272,7 @@ void Extra_MmFixedRestart( Extra_MmFixed_t * p )
int i;
char * pTemp;
- // delocate all chunks except the first one
+ // deallocate all chunks except the first one
for ( i = 1; i < p->nChunks; i++ )
free( p->pChunks[i] );
p->nChunks = 1;
@@ -295,6 +310,21 @@ int Extra_MmFixedReadMemUsage( Extra_MmFixed_t * p )
return p->nMemoryAlloc;
}
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Extra_MmFixedReadMaxEntriesUsed( Extra_MmFixed_t * p )
+{
+ return p->nEntriesMax;
+}
/**Function*************************************************************
@@ -311,7 +341,7 @@ int Extra_MmFixedReadMemUsage( Extra_MmFixed_t * p )
Extra_MmFlex_t * Extra_MmFlexStart()
{
Extra_MmFlex_t * p;
-
+//printf( "allocing flex\n" );
p = ALLOC( Extra_MmFlex_t, 1 );
memset( p, 0, sizeof(Extra_MmFlex_t) );
@@ -319,7 +349,7 @@ Extra_MmFlex_t * Extra_MmFlexStart()
p->pCurrent = NULL;
p->pEnd = NULL;
- p->nChunkSize = (1 << 12);
+ p->nChunkSize = (1 << 10);
p->nChunksAlloc = 64;
p->nChunks = 0;
p->pChunks = ALLOC( char *, p->nChunksAlloc );
@@ -340,18 +370,31 @@ Extra_MmFlex_t * Extra_MmFlexStart()
SeeAlso []
***********************************************************************/
-void Extra_MmFlexStop( Extra_MmFlex_t * p, int fVerbose )
+void Extra_MmFlexPrint( Extra_MmFlex_t * p )
+{
+ printf( "Flexible memory manager: Chunk size = %d. Chunks used = %d.\n",
+ p->nChunkSize, p->nChunks );
+ printf( " Entries used = %d. Memory used = %d. Memory alloc = %d.\n",
+ p->nEntriesUsed, p->nMemoryUsed, p->nMemoryAlloc );
+}
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Extra_MmFlexStop( Extra_MmFlex_t * p )
{
int i;
if ( p == NULL )
return;
- 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 );
- }
+//printf( "deleting flex\n" );
for ( i = 0; i < p->nChunks; i++ )
free( p->pChunks[i] );
free( p->pChunks );
@@ -448,6 +491,7 @@ Extra_MmStep_t * Extra_MmStepStart( int nSteps )
Extra_MmStep_t * p;
int i, k;
p = ALLOC( Extra_MmStep_t, 1 );
+ memset( p, 0, sizeof(Extra_MmStep_t) );
p->nMems = nSteps;
// start the fixed memory managers
p->pMems = ALLOC( Extra_MmFixed_t *, p->nMems );
@@ -478,11 +522,17 @@ Extra_MmStep_t * Extra_MmStepStart( int nSteps )
SeeAlso []
***********************************************************************/
-void Extra_MmStepStop( Extra_MmStep_t * p, int fVerbose )
+void Extra_MmStepStop( Extra_MmStep_t * p )
{
int i;
for ( i = 0; i < p->nMems; i++ )
- Extra_MmFixedStop( p->pMems[i], fVerbose );
+ Extra_MmFixedStop( p->pMems[i] );
+// if ( p->pLargeChunks )
+// {
+// for ( i = 0; i < p->nLargeChunks; i++ )
+// free( p->pLargeChunks[i] );
+// free( p->pLargeChunks );
+// }
free( p->pMems );
free( p->pMap );
free( p );
@@ -506,6 +556,17 @@ char * Extra_MmStepEntryFetch( Extra_MmStep_t * p, int nBytes )
if ( nBytes > p->nMapSize )
{
// printf( "Allocating %d bytes.\n", nBytes );
+/*
+ if ( p->nLargeChunks == p->nLargeChunksAlloc )
+ {
+ if ( p->nLargeChunksAlloc == 0 )
+ p->nLargeChunksAlloc = 5;
+ p->nLargeChunksAlloc *= 2;
+ p->pLargeChunks = REALLOC( char *, p->pLargeChunks, p->nLargeChunksAlloc );
+ }
+ p->pLargeChunks[ p->nLargeChunks++ ] = ALLOC( char, nBytes );
+ return p->pLargeChunks[ p->nLargeChunks - 1 ];
+*/
return ALLOC( char, nBytes );
}
return Extra_MmFixedEntryFetch( p->pMap[nBytes] );
diff --git a/src/misc/extra/extraUtilMisc.c b/src/misc/extra/extraUtilMisc.c
index 6d771990..dff774bc 100644
--- a/src/misc/extra/extraUtilMisc.c
+++ b/src/misc/extra/extraUtilMisc.c
@@ -209,6 +209,37 @@ int * Extra_DeriveRadixCode( int Number, int Radix, int nDigits )
return Code;
}
+/**Function*************************************************************
+
+ Synopsis [Counts the number of ones in the bitstring.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Extra_CountOnes( unsigned char * pBytes, int nBytes )
+{
+ static int bit_count[256] = {
+ 0,1,1,2,1,2,2,3,1,2,2,3,2,3,3,4,1,2,2,3,2,3,3,4,2,3,3,4,3,4,4,5,
+ 1,2,2,3,2,3,3,4,2,3,3,4,3,4,4,5,2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6,
+ 1,2,2,3,2,3,3,4,2,3,3,4,3,4,4,5,2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6,
+ 2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6,3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7,
+ 1,2,2,3,2,3,3,4,2,3,3,4,3,4,4,5,2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6,
+ 2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6,3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7,
+ 2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6,3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7,
+ 3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7,4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8
+ };
+
+ int i, Counter;
+ Counter = 0;
+ for ( i = 0; i < nBytes; i++ )
+ Counter += bit_count[ *(pBytes+i) ];
+ return Counter;
+}
+
/**Function********************************************************************
Synopsis [Computes the factorial.]
@@ -1274,6 +1305,635 @@ void Extra_TruthPerm6One( unsigned * uTruth, int Phase, unsigned * uTruthRes )
/**Function*************************************************************
+ Synopsis [Computes a phase of the 8-var function.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Extra_TruthExpand( int nVars, int nWords, unsigned * puTruth, unsigned uPhase, unsigned * puTruthR )
+{
+ // elementary truth tables
+ static unsigned uTruths[8][8] = {
+ { 0xAAAAAAAA,0xAAAAAAAA,0xAAAAAAAA,0xAAAAAAAA,0xAAAAAAAA,0xAAAAAAAA,0xAAAAAAAA,0xAAAAAAAA },
+ { 0xCCCCCCCC,0xCCCCCCCC,0xCCCCCCCC,0xCCCCCCCC,0xCCCCCCCC,0xCCCCCCCC,0xCCCCCCCC,0xCCCCCCCC },
+ { 0xF0F0F0F0,0xF0F0F0F0,0xF0F0F0F0,0xF0F0F0F0,0xF0F0F0F0,0xF0F0F0F0,0xF0F0F0F0,0xF0F0F0F0 },
+ { 0xFF00FF00,0xFF00FF00,0xFF00FF00,0xFF00FF00,0xFF00FF00,0xFF00FF00,0xFF00FF00,0xFF00FF00 },
+ { 0xFFFF0000,0xFFFF0000,0xFFFF0000,0xFFFF0000,0xFFFF0000,0xFFFF0000,0xFFFF0000,0xFFFF0000 },
+ { 0x00000000,0xFFFFFFFF,0x00000000,0xFFFFFFFF,0x00000000,0xFFFFFFFF,0x00000000,0xFFFFFFFF },
+ { 0x00000000,0x00000000,0xFFFFFFFF,0xFFFFFFFF,0x00000000,0x00000000,0xFFFFFFFF,0xFFFFFFFF },
+ { 0x00000000,0x00000000,0x00000000,0x00000000,0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF }
+ };
+ static char Cases[256] = {
+ 0, // 00000000
+ 0, // 00000001
+ 1, // 00000010
+ 0, // 00000011
+ 2, // 00000100
+ -1, // 00000101
+ -1, // 00000110
+ 0, // 00000111
+ 3, // 00001000
+ -1, // 00001001
+ -1, // 00001010
+ -1, // 00001011
+ -1, // 00001100
+ -1, // 00001101
+ -1, // 00001110
+ 0, // 00001111
+ 4, // 00010000
+ -1, // 00010001
+ -1, // 00010010
+ -1, // 00010011
+ -1, // 00010100
+ -1, // 00010101
+ -1, // 00010110
+ -1, // 00010111
+ -1, // 00011000
+ -1, // 00011001
+ -1, // 00011010
+ -1, // 00011011
+ -1, // 00011100
+ -1, // 00011101
+ -1, // 00011110
+ 0, // 00011111
+ 5, // 00100000
+ -1, // 00100001
+ -1, // 00100010
+ -1, // 00100011
+ -1, // 00100100
+ -1, // 00100101
+ -1, // 00100110
+ -1, // 00100111
+ -1, // 00101000
+ -1, // 00101001
+ -1, // 00101010
+ -1, // 00101011
+ -1, // 00101100
+ -1, // 00101101
+ -1, // 00101110
+ -1, // 00101111
+ -1, // 00110000
+ -1, // 00110001
+ -1, // 00110010
+ -1, // 00110011
+ -1, // 00110100
+ -1, // 00110101
+ -1, // 00110110
+ -1, // 00110111
+ -1, // 00111000
+ -1, // 00111001
+ -1, // 00111010
+ -1, // 00111011
+ -1, // 00111100
+ -1, // 00111101
+ -1, // 00111110
+ 0, // 00111111
+ 6, // 01000000
+ -1, // 01000001
+ -1, // 01000010
+ -1, // 01000011
+ -1, // 01000100
+ -1, // 01000101
+ -1, // 01000110
+ -1, // 01000111
+ -1, // 01001000
+ -1, // 01001001
+ -1, // 01001010
+ -1, // 01001011
+ -1, // 01001100
+ -1, // 01001101
+ -1, // 01001110
+ -1, // 01001111
+ -1, // 01010000
+ -1, // 01010001
+ -1, // 01010010
+ -1, // 01010011
+ -1, // 01010100
+ -1, // 01010101
+ -1, // 01010110
+ -1, // 01010111
+ -1, // 01011000
+ -1, // 01011001
+ -1, // 01011010
+ -1, // 01011011
+ -1, // 01011100
+ -1, // 01011101
+ -1, // 01011110
+ -1, // 01011111
+ -1, // 01100000
+ -1, // 01100001
+ -1, // 01100010
+ -1, // 01100011
+ -1, // 01100100
+ -1, // 01100101
+ -1, // 01100110
+ -1, // 01100111
+ -1, // 01101000
+ -1, // 01101001
+ -1, // 01101010
+ -1, // 01101011
+ -1, // 01101100
+ -1, // 01101101
+ -1, // 01101110
+ -1, // 01101111
+ -1, // 01110000
+ -1, // 01110001
+ -1, // 01110010
+ -1, // 01110011
+ -1, // 01110100
+ -1, // 01110101
+ -1, // 01110110
+ -1, // 01110111
+ -1, // 01111000
+ -1, // 01111001
+ -1, // 01111010
+ -1, // 01111011
+ -1, // 01111100
+ -1, // 01111101
+ -1, // 01111110
+ 0, // 01111111
+ 7, // 10000000
+ -1, // 10000001
+ -1, // 10000010
+ -1, // 10000011
+ -1, // 10000100
+ -1, // 10000101
+ -1, // 10000110
+ -1, // 10000111
+ -1, // 10001000
+ -1, // 10001001
+ -1, // 10001010
+ -1, // 10001011
+ -1, // 10001100
+ -1, // 10001101
+ -1, // 10001110
+ -1, // 10001111
+ -1, // 10010000
+ -1, // 10010001
+ -1, // 10010010
+ -1, // 10010011
+ -1, // 10010100
+ -1, // 10010101
+ -1, // 10010110
+ -1, // 10010111
+ -1, // 10011000
+ -1, // 10011001
+ -1, // 10011010
+ -1, // 10011011
+ -1, // 10011100
+ -1, // 10011101
+ -1, // 10011110
+ -1, // 10011111
+ -1, // 10100000
+ -1, // 10100001
+ -1, // 10100010
+ -1, // 10100011
+ -1, // 10100100
+ -1, // 10100101
+ -1, // 10100110
+ -1, // 10100111
+ -1, // 10101000
+ -1, // 10101001
+ -1, // 10101010
+ -1, // 10101011
+ -1, // 10101100
+ -1, // 10101101
+ -1, // 10101110
+ -1, // 10101111
+ -1, // 10110000
+ -1, // 10110001
+ -1, // 10110010
+ -1, // 10110011
+ -1, // 10110100
+ -1, // 10110101
+ -1, // 10110110
+ -1, // 10110111
+ -1, // 10111000
+ -1, // 10111001
+ -1, // 10111010
+ -1, // 10111011
+ -1, // 10111100
+ -1, // 10111101
+ -1, // 10111110
+ -1, // 10111111
+ -1, // 11000000
+ -1, // 11000001
+ -1, // 11000010
+ -1, // 11000011
+ -1, // 11000100
+ -1, // 11000101
+ -1, // 11000110
+ -1, // 11000111
+ -1, // 11001000
+ -1, // 11001001
+ -1, // 11001010
+ -1, // 11001011
+ -1, // 11001100
+ -1, // 11001101
+ -1, // 11001110
+ -1, // 11001111
+ -1, // 11010000
+ -1, // 11010001
+ -1, // 11010010
+ -1, // 11010011
+ -1, // 11010100
+ -1, // 11010101
+ -1, // 11010110
+ -1, // 11010111
+ -1, // 11011000
+ -1, // 11011001
+ -1, // 11011010
+ -1, // 11011011
+ -1, // 11011100
+ -1, // 11011101
+ -1, // 11011110
+ -1, // 11011111
+ -1, // 11100000
+ -1, // 11100001
+ -1, // 11100010
+ -1, // 11100011
+ -1, // 11100100
+ -1, // 11100101
+ -1, // 11100110
+ -1, // 11100111
+ -1, // 11101000
+ -1, // 11101001
+ -1, // 11101010
+ -1, // 11101011
+ -1, // 11101100
+ -1, // 11101101
+ -1, // 11101110
+ -1, // 11101111
+ -1, // 11110000
+ -1, // 11110001
+ -1, // 11110010
+ -1, // 11110011
+ -1, // 11110100
+ -1, // 11110101
+ -1, // 11110110
+ -1, // 11110111
+ -1, // 11111000
+ -1, // 11111001
+ -1, // 11111010
+ -1, // 11111011
+ -1, // 11111100
+ -1, // 11111101
+ -1, // 11111110
+ 0 // 11111111
+ };
+ static char Perms[256][8] = {
+ { 0, 1, 2, 3, 4, 5, 6, 7 }, // 00000000
+ { 0, 1, 2, 3, 4, 5, 6, 7 }, // 00000001
+ { 1, 0, 2, 3, 4, 5, 6, 7 }, // 00000010
+ { 0, 1, 2, 3, 4, 5, 6, 7 }, // 00000011
+ { 1, 2, 0, 3, 4, 5, 6, 7 }, // 00000100
+ { 0, 2, 1, 3, 4, 5, 6, 7 }, // 00000101
+ { 2, 0, 1, 3, 4, 5, 6, 7 }, // 00000110
+ { 0, 1, 2, 3, 4, 5, 6, 7 }, // 00000111
+ { 1, 2, 3, 0, 4, 5, 6, 7 }, // 00001000
+ { 0, 2, 3, 1, 4, 5, 6, 7 }, // 00001001
+ { 2, 0, 3, 1, 4, 5, 6, 7 }, // 00001010
+ { 0, 1, 3, 2, 4, 5, 6, 7 }, // 00001011
+ { 2, 3, 0, 1, 4, 5, 6, 7 }, // 00001100
+ { 0, 3, 1, 2, 4, 5, 6, 7 }, // 00001101
+ { 3, 0, 1, 2, 4, 5, 6, 7 }, // 00001110
+ { 0, 1, 2, 3, 4, 5, 6, 7 }, // 00001111
+ { 1, 2, 3, 4, 0, 5, 6, 7 }, // 00010000
+ { 0, 2, 3, 4, 1, 5, 6, 7 }, // 00010001
+ { 2, 0, 3, 4, 1, 5, 6, 7 }, // 00010010
+ { 0, 1, 3, 4, 2, 5, 6, 7 }, // 00010011
+ { 2, 3, 0, 4, 1, 5, 6, 7 }, // 00010100
+ { 0, 3, 1, 4, 2, 5, 6, 7 }, // 00010101
+ { 3, 0, 1, 4, 2, 5, 6, 7 }, // 00010110
+ { 0, 1, 2, 4, 3, 5, 6, 7 }, // 00010111
+ { 2, 3, 4, 0, 1, 5, 6, 7 }, // 00011000
+ { 0, 3, 4, 1, 2, 5, 6, 7 }, // 00011001
+ { 3, 0, 4, 1, 2, 5, 6, 7 }, // 00011010
+ { 0, 1, 4, 2, 3, 5, 6, 7 }, // 00011011
+ { 3, 4, 0, 1, 2, 5, 6, 7 }, // 00011100
+ { 0, 4, 1, 2, 3, 5, 6, 7 }, // 00011101
+ { 4, 0, 1, 2, 3, 5, 6, 7 }, // 00011110
+ { 0, 1, 2, 3, 4, 5, 6, 7 }, // 00011111
+ { 1, 2, 3, 4, 5, 0, 6, 7 }, // 00100000
+ { 0, 2, 3, 4, 5, 1, 6, 7 }, // 00100001
+ { 2, 0, 3, 4, 5, 1, 6, 7 }, // 00100010
+ { 0, 1, 3, 4, 5, 2, 6, 7 }, // 00100011
+ { 2, 3, 0, 4, 5, 1, 6, 7 }, // 00100100
+ { 0, 3, 1, 4, 5, 2, 6, 7 }, // 00100101
+ { 3, 0, 1, 4, 5, 2, 6, 7 }, // 00100110
+ { 0, 1, 2, 4, 5, 3, 6, 7 }, // 00100111
+ { 2, 3, 4, 0, 5, 1, 6, 7 }, // 00101000
+ { 0, 3, 4, 1, 5, 2, 6, 7 }, // 00101001
+ { 3, 0, 4, 1, 5, 2, 6, 7 }, // 00101010
+ { 0, 1, 4, 2, 5, 3, 6, 7 }, // 00101011
+ { 3, 4, 0, 1, 5, 2, 6, 7 }, // 00101100
+ { 0, 4, 1, 2, 5, 3, 6, 7 }, // 00101101
+ { 4, 0, 1, 2, 5, 3, 6, 7 }, // 00101110
+ { 0, 1, 2, 3, 5, 4, 6, 7 }, // 00101111
+ { 2, 3, 4, 5, 0, 1, 6, 7 }, // 00110000
+ { 0, 3, 4, 5, 1, 2, 6, 7 }, // 00110001
+ { 3, 0, 4, 5, 1, 2, 6, 7 }, // 00110010
+ { 0, 1, 4, 5, 2, 3, 6, 7 }, // 00110011
+ { 3, 4, 0, 5, 1, 2, 6, 7 }, // 00110100
+ { 0, 4, 1, 5, 2, 3, 6, 7 }, // 00110101
+ { 4, 0, 1, 5, 2, 3, 6, 7 }, // 00110110
+ { 0, 1, 2, 5, 3, 4, 6, 7 }, // 00110111
+ { 3, 4, 5, 0, 1, 2, 6, 7 }, // 00111000
+ { 0, 4, 5, 1, 2, 3, 6, 7 }, // 00111001
+ { 4, 0, 5, 1, 2, 3, 6, 7 }, // 00111010
+ { 0, 1, 5, 2, 3, 4, 6, 7 }, // 00111011
+ { 4, 5, 0, 1, 2, 3, 6, 7 }, // 00111100
+ { 0, 5, 1, 2, 3, 4, 6, 7 }, // 00111101
+ { 5, 0, 1, 2, 3, 4, 6, 7 }, // 00111110
+ { 0, 1, 2, 3, 4, 5, 6, 7 }, // 00111111
+ { 1, 2, 3, 4, 5, 6, 0, 7 }, // 01000000
+ { 0, 2, 3, 4, 5, 6, 1, 7 }, // 01000001
+ { 2, 0, 3, 4, 5, 6, 1, 7 }, // 01000010
+ { 0, 1, 3, 4, 5, 6, 2, 7 }, // 01000011
+ { 2, 3, 0, 4, 5, 6, 1, 7 }, // 01000100
+ { 0, 3, 1, 4, 5, 6, 2, 7 }, // 01000101
+ { 3, 0, 1, 4, 5, 6, 2, 7 }, // 01000110
+ { 0, 1, 2, 4, 5, 6, 3, 7 }, // 01000111
+ { 2, 3, 4, 0, 5, 6, 1, 7 }, // 01001000
+ { 0, 3, 4, 1, 5, 6, 2, 7 }, // 01001001
+ { 3, 0, 4, 1, 5, 6, 2, 7 }, // 01001010
+ { 0, 1, 4, 2, 5, 6, 3, 7 }, // 01001011
+ { 3, 4, 0, 1, 5, 6, 2, 7 }, // 01001100
+ { 0, 4, 1, 2, 5, 6, 3, 7 }, // 01001101
+ { 4, 0, 1, 2, 5, 6, 3, 7 }, // 01001110
+ { 0, 1, 2, 3, 5, 6, 4, 7 }, // 01001111
+ { 2, 3, 4, 5, 0, 6, 1, 7 }, // 01010000
+ { 0, 3, 4, 5, 1, 6, 2, 7 }, // 01010001
+ { 3, 0, 4, 5, 1, 6, 2, 7 }, // 01010010
+ { 0, 1, 4, 5, 2, 6, 3, 7 }, // 01010011
+ { 3, 4, 0, 5, 1, 6, 2, 7 }, // 01010100
+ { 0, 4, 1, 5, 2, 6, 3, 7 }, // 01010101
+ { 4, 0, 1, 5, 2, 6, 3, 7 }, // 01010110
+ { 0, 1, 2, 5, 3, 6, 4, 7 }, // 01010111
+ { 3, 4, 5, 0, 1, 6, 2, 7 }, // 01011000
+ { 0, 4, 5, 1, 2, 6, 3, 7 }, // 01011001
+ { 4, 0, 5, 1, 2, 6, 3, 7 }, // 01011010
+ { 0, 1, 5, 2, 3, 6, 4, 7 }, // 01011011
+ { 4, 5, 0, 1, 2, 6, 3, 7 }, // 01011100
+ { 0, 5, 1, 2, 3, 6, 4, 7 }, // 01011101
+ { 5, 0, 1, 2, 3, 6, 4, 7 }, // 01011110
+ { 0, 1, 2, 3, 4, 6, 5, 7 }, // 01011111
+ { 2, 3, 4, 5, 6, 0, 1, 7 }, // 01100000
+ { 0, 3, 4, 5, 6, 1, 2, 7 }, // 01100001
+ { 3, 0, 4, 5, 6, 1, 2, 7 }, // 01100010
+ { 0, 1, 4, 5, 6, 2, 3, 7 }, // 01100011
+ { 3, 4, 0, 5, 6, 1, 2, 7 }, // 01100100
+ { 0, 4, 1, 5, 6, 2, 3, 7 }, // 01100101
+ { 4, 0, 1, 5, 6, 2, 3, 7 }, // 01100110
+ { 0, 1, 2, 5, 6, 3, 4, 7 }, // 01100111
+ { 3, 4, 5, 0, 6, 1, 2, 7 }, // 01101000
+ { 0, 4, 5, 1, 6, 2, 3, 7 }, // 01101001
+ { 4, 0, 5, 1, 6, 2, 3, 7 }, // 01101010
+ { 0, 1, 5, 2, 6, 3, 4, 7 }, // 01101011
+ { 4, 5, 0, 1, 6, 2, 3, 7 }, // 01101100
+ { 0, 5, 1, 2, 6, 3, 4, 7 }, // 01101101
+ { 5, 0, 1, 2, 6, 3, 4, 7 }, // 01101110
+ { 0, 1, 2, 3, 6, 4, 5, 7 }, // 01101111
+ { 3, 4, 5, 6, 0, 1, 2, 7 }, // 01110000
+ { 0, 4, 5, 6, 1, 2, 3, 7 }, // 01110001
+ { 4, 0, 5, 6, 1, 2, 3, 7 }, // 01110010
+ { 0, 1, 5, 6, 2, 3, 4, 7 }, // 01110011
+ { 4, 5, 0, 6, 1, 2, 3, 7 }, // 01110100
+ { 0, 5, 1, 6, 2, 3, 4, 7 }, // 01110101
+ { 5, 0, 1, 6, 2, 3, 4, 7 }, // 01110110
+ { 0, 1, 2, 6, 3, 4, 5, 7 }, // 01110111
+ { 4, 5, 6, 0, 1, 2, 3, 7 }, // 01111000
+ { 0, 5, 6, 1, 2, 3, 4, 7 }, // 01111001
+ { 5, 0, 6, 1, 2, 3, 4, 7 }, // 01111010
+ { 0, 1, 6, 2, 3, 4, 5, 7 }, // 01111011
+ { 5, 6, 0, 1, 2, 3, 4, 7 }, // 01111100
+ { 0, 6, 1, 2, 3, 4, 5, 7 }, // 01111101
+ { 6, 0, 1, 2, 3, 4, 5, 7 }, // 01111110
+ { 0, 1, 2, 3, 4, 5, 6, 7 }, // 01111111
+ { 1, 2, 3, 4, 5, 6, 7, 0 }, // 10000000
+ { 0, 2, 3, 4, 5, 6, 7, 1 }, // 10000001
+ { 2, 0, 3, 4, 5, 6, 7, 1 }, // 10000010
+ { 0, 1, 3, 4, 5, 6, 7, 2 }, // 10000011
+ { 2, 3, 0, 4, 5, 6, 7, 1 }, // 10000100
+ { 0, 3, 1, 4, 5, 6, 7, 2 }, // 10000101
+ { 3, 0, 1, 4, 5, 6, 7, 2 }, // 10000110
+ { 0, 1, 2, 4, 5, 6, 7, 3 }, // 10000111
+ { 2, 3, 4, 0, 5, 6, 7, 1 }, // 10001000
+ { 0, 3, 4, 1, 5, 6, 7, 2 }, // 10001001
+ { 3, 0, 4, 1, 5, 6, 7, 2 }, // 10001010
+ { 0, 1, 4, 2, 5, 6, 7, 3 }, // 10001011
+ { 3, 4, 0, 1, 5, 6, 7, 2 }, // 10001100
+ { 0, 4, 1, 2, 5, 6, 7, 3 }, // 10001101
+ { 4, 0, 1, 2, 5, 6, 7, 3 }, // 10001110
+ { 0, 1, 2, 3, 5, 6, 7, 4 }, // 10001111
+ { 2, 3, 4, 5, 0, 6, 7, 1 }, // 10010000
+ { 0, 3, 4, 5, 1, 6, 7, 2 }, // 10010001
+ { 3, 0, 4, 5, 1, 6, 7, 2 }, // 10010010
+ { 0, 1, 4, 5, 2, 6, 7, 3 }, // 10010011
+ { 3, 4, 0, 5, 1, 6, 7, 2 }, // 10010100
+ { 0, 4, 1, 5, 2, 6, 7, 3 }, // 10010101
+ { 4, 0, 1, 5, 2, 6, 7, 3 }, // 10010110
+ { 0, 1, 2, 5, 3, 6, 7, 4 }, // 10010111
+ { 3, 4, 5, 0, 1, 6, 7, 2 }, // 10011000
+ { 0, 4, 5, 1, 2, 6, 7, 3 }, // 10011001
+ { 4, 0, 5, 1, 2, 6, 7, 3 }, // 10011010
+ { 0, 1, 5, 2, 3, 6, 7, 4 }, // 10011011
+ { 4, 5, 0, 1, 2, 6, 7, 3 }, // 10011100
+ { 0, 5, 1, 2, 3, 6, 7, 4 }, // 10011101
+ { 5, 0, 1, 2, 3, 6, 7, 4 }, // 10011110
+ { 0, 1, 2, 3, 4, 6, 7, 5 }, // 10011111
+ { 2, 3, 4, 5, 6, 0, 7, 1 }, // 10100000
+ { 0, 3, 4, 5, 6, 1, 7, 2 }, // 10100001
+ { 3, 0, 4, 5, 6, 1, 7, 2 }, // 10100010
+ { 0, 1, 4, 5, 6, 2, 7, 3 }, // 10100011
+ { 3, 4, 0, 5, 6, 1, 7, 2 }, // 10100100
+ { 0, 4, 1, 5, 6, 2, 7, 3 }, // 10100101
+ { 4, 0, 1, 5, 6, 2, 7, 3 }, // 10100110
+ { 0, 1, 2, 5, 6, 3, 7, 4 }, // 10100111
+ { 3, 4, 5, 0, 6, 1, 7, 2 }, // 10101000
+ { 0, 4, 5, 1, 6, 2, 7, 3 }, // 10101001
+ { 4, 0, 5, 1, 6, 2, 7, 3 }, // 10101010
+ { 0, 1, 5, 2, 6, 3, 7, 4 }, // 10101011
+ { 4, 5, 0, 1, 6, 2, 7, 3 }, // 10101100
+ { 0, 5, 1, 2, 6, 3, 7, 4 }, // 10101101
+ { 5, 0, 1, 2, 6, 3, 7, 4 }, // 10101110
+ { 0, 1, 2, 3, 6, 4, 7, 5 }, // 10101111
+ { 3, 4, 5, 6, 0, 1, 7, 2 }, // 10110000
+ { 0, 4, 5, 6, 1, 2, 7, 3 }, // 10110001
+ { 4, 0, 5, 6, 1, 2, 7, 3 }, // 10110010
+ { 0, 1, 5, 6, 2, 3, 7, 4 }, // 10110011
+ { 4, 5, 0, 6, 1, 2, 7, 3 }, // 10110100
+ { 0, 5, 1, 6, 2, 3, 7, 4 }, // 10110101
+ { 5, 0, 1, 6, 2, 3, 7, 4 }, // 10110110
+ { 0, 1, 2, 6, 3, 4, 7, 5 }, // 10110111
+ { 4, 5, 6, 0, 1, 2, 7, 3 }, // 10111000
+ { 0, 5, 6, 1, 2, 3, 7, 4 }, // 10111001
+ { 5, 0, 6, 1, 2, 3, 7, 4 }, // 10111010
+ { 0, 1, 6, 2, 3, 4, 7, 5 }, // 10111011
+ { 5, 6, 0, 1, 2, 3, 7, 4 }, // 10111100
+ { 0, 6, 1, 2, 3, 4, 7, 5 }, // 10111101
+ { 6, 0, 1, 2, 3, 4, 7, 5 }, // 10111110
+ { 0, 1, 2, 3, 4, 5, 7, 6 }, // 10111111
+ { 2, 3, 4, 5, 6, 7, 0, 1 }, // 11000000
+ { 0, 3, 4, 5, 6, 7, 1, 2 }, // 11000001
+ { 3, 0, 4, 5, 6, 7, 1, 2 }, // 11000010
+ { 0, 1, 4, 5, 6, 7, 2, 3 }, // 11000011
+ { 3, 4, 0, 5, 6, 7, 1, 2 }, // 11000100
+ { 0, 4, 1, 5, 6, 7, 2, 3 }, // 11000101
+ { 4, 0, 1, 5, 6, 7, 2, 3 }, // 11000110
+ { 0, 1, 2, 5, 6, 7, 3, 4 }, // 11000111
+ { 3, 4, 5, 0, 6, 7, 1, 2 }, // 11001000
+ { 0, 4, 5, 1, 6, 7, 2, 3 }, // 11001001
+ { 4, 0, 5, 1, 6, 7, 2, 3 }, // 11001010
+ { 0, 1, 5, 2, 6, 7, 3, 4 }, // 11001011
+ { 4, 5, 0, 1, 6, 7, 2, 3 }, // 11001100
+ { 0, 5, 1, 2, 6, 7, 3, 4 }, // 11001101
+ { 5, 0, 1, 2, 6, 7, 3, 4 }, // 11001110
+ { 0, 1, 2, 3, 6, 7, 4, 5 }, // 11001111
+ { 3, 4, 5, 6, 0, 7, 1, 2 }, // 11010000
+ { 0, 4, 5, 6, 1, 7, 2, 3 }, // 11010001
+ { 4, 0, 5, 6, 1, 7, 2, 3 }, // 11010010
+ { 0, 1, 5, 6, 2, 7, 3, 4 }, // 11010011
+ { 4, 5, 0, 6, 1, 7, 2, 3 }, // 11010100
+ { 0, 5, 1, 6, 2, 7, 3, 4 }, // 11010101
+ { 5, 0, 1, 6, 2, 7, 3, 4 }, // 11010110
+ { 0, 1, 2, 6, 3, 7, 4, 5 }, // 11010111
+ { 4, 5, 6, 0, 1, 7, 2, 3 }, // 11011000
+ { 0, 5, 6, 1, 2, 7, 3, 4 }, // 11011001
+ { 5, 0, 6, 1, 2, 7, 3, 4 }, // 11011010
+ { 0, 1, 6, 2, 3, 7, 4, 5 }, // 11011011
+ { 5, 6, 0, 1, 2, 7, 3, 4 }, // 11011100
+ { 0, 6, 1, 2, 3, 7, 4, 5 }, // 11011101
+ { 6, 0, 1, 2, 3, 7, 4, 5 }, // 11011110
+ { 0, 1, 2, 3, 4, 7, 5, 6 }, // 11011111
+ { 3, 4, 5, 6, 7, 0, 1, 2 }, // 11100000
+ { 0, 4, 5, 6, 7, 1, 2, 3 }, // 11100001
+ { 4, 0, 5, 6, 7, 1, 2, 3 }, // 11100010
+ { 0, 1, 5, 6, 7, 2, 3, 4 }, // 11100011
+ { 4, 5, 0, 6, 7, 1, 2, 3 }, // 11100100
+ { 0, 5, 1, 6, 7, 2, 3, 4 }, // 11100101
+ { 5, 0, 1, 6, 7, 2, 3, 4 }, // 11100110
+ { 0, 1, 2, 6, 7, 3, 4, 5 }, // 11100111
+ { 4, 5, 6, 0, 7, 1, 2, 3 }, // 11101000
+ { 0, 5, 6, 1, 7, 2, 3, 4 }, // 11101001
+ { 5, 0, 6, 1, 7, 2, 3, 4 }, // 11101010
+ { 0, 1, 6, 2, 7, 3, 4, 5 }, // 11101011
+ { 5, 6, 0, 1, 7, 2, 3, 4 }, // 11101100
+ { 0, 6, 1, 2, 7, 3, 4, 5 }, // 11101101
+ { 6, 0, 1, 2, 7, 3, 4, 5 }, // 11101110
+ { 0, 1, 2, 3, 7, 4, 5, 6 }, // 11101111
+ { 4, 5, 6, 7, 0, 1, 2, 3 }, // 11110000
+ { 0, 5, 6, 7, 1, 2, 3, 4 }, // 11110001
+ { 5, 0, 6, 7, 1, 2, 3, 4 }, // 11110010
+ { 0, 1, 6, 7, 2, 3, 4, 5 }, // 11110011
+ { 5, 6, 0, 7, 1, 2, 3, 4 }, // 11110100
+ { 0, 6, 1, 7, 2, 3, 4, 5 }, // 11110101
+ { 6, 0, 1, 7, 2, 3, 4, 5 }, // 11110110
+ { 0, 1, 2, 7, 3, 4, 5, 6 }, // 11110111
+ { 5, 6, 7, 0, 1, 2, 3, 4 }, // 11111000
+ { 0, 6, 7, 1, 2, 3, 4, 5 }, // 11111001
+ { 6, 0, 7, 1, 2, 3, 4, 5 }, // 11111010
+ { 0, 1, 7, 2, 3, 4, 5, 6 }, // 11111011
+ { 6, 7, 0, 1, 2, 3, 4, 5 }, // 11111100
+ { 0, 7, 1, 2, 3, 4, 5, 6 }, // 11111101
+ { 7, 0, 1, 2, 3, 4, 5, 6 }, // 11111110
+ { 0, 1, 2, 3, 4, 5, 6, 7 } // 11111111
+ };
+
+ assert( uPhase > 0 && uPhase < (unsigned)(1 << nVars) );
+
+ // the same function
+ if ( Cases[uPhase] == 0 )
+ {
+ int i;
+ for ( i = 0; i < nWords; i++ )
+ puTruthR[i] = puTruth[i];
+ return;
+ }
+
+ // an elementary variable
+ if ( Cases[uPhase] > 0 )
+ {
+ int i;
+ for ( i = 0; i < nWords; i++ )
+ puTruthR[i] = uTruths[Cases[uPhase]][i];
+ return;
+ }
+
+ // truth table takes one word
+ if ( nWords == 1 )
+ {
+ int i, k, nMints, iRes;
+ char * pPerm = Perms[uPhase];
+ puTruthR[0] = 0;
+ nMints = (1 << nVars);
+ for ( i = 0; i < nMints; i++ )
+ if ( puTruth[0] & (1 << i) )
+ {
+ for ( iRes = 0, k = 0; k < nVars; k++ )
+ if ( i & (1 << pPerm[k]) )
+ iRes |= (1 << k);
+ puTruthR[0] |= (1 << iRes);
+ }
+ return;
+ }
+ else if ( nWords == 2 )
+ {
+ int i, k, iRes;
+ char * pPerm = Perms[uPhase];
+ puTruthR[0] = puTruthR[1] = 0;
+ for ( i = 0; i < 32; i++ )
+ {
+ if ( puTruth[0] & (1 << i) )
+ {
+ for ( iRes = 0, k = 0; k < 6; k++ )
+ if ( i & (1 << pPerm[k]) )
+ iRes |= (1 << k);
+ if ( iRes < 32 )
+ puTruthR[0] |= (1 << iRes);
+ else
+ puTruthR[1] |= (1 << (iRes-32));
+ }
+ }
+ for ( ; i < 64; i++ )
+ {
+ if ( puTruth[1] & (1 << (i-32)) )
+ {
+ for ( iRes = 0, k = 0; k < 6; k++ )
+ if ( i & (1 << pPerm[k]) )
+ iRes |= (1 << k);
+ if ( iRes < 32 )
+ puTruthR[0] |= (1 << iRes);
+ else
+ puTruthR[1] |= (1 << (iRes-32));
+ }
+ }
+ }
+ // truth table takes more than one word
+ else
+ {
+ int i, k, nMints, iRes;
+ char * pPerm = Perms[uPhase];
+ for ( i = 0; i < nWords; i++ )
+ puTruthR[i] = 0;
+ nMints = (1 << nVars);
+ for ( i = 0; i < nMints; i++ )
+ if ( puTruth[i>>5] & (1 << (i&31)) )
+ {
+ for ( iRes = 0, k = 0; k < 5; k++ )
+ if ( i & (1 << pPerm[k]) )
+ iRes |= (1 << k);
+ puTruthR[iRes>>5] |= (1 << (iRes&31));
+ }
+ }
+}
+
+/**Function*************************************************************
+
Synopsis [Allocated lookup table for truth table permutation.]
Description []
@@ -1381,6 +2041,84 @@ unsigned ** Extra_TruthPerm63()
/**Function*************************************************************
+ Synopsis [Returns the pointer to the elementary truth tables.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+unsigned ** Extra_Truths8()
+{
+ static unsigned uTruths[8][8] = {
+ { 0xAAAAAAAA,0xAAAAAAAA,0xAAAAAAAA,0xAAAAAAAA,0xAAAAAAAA,0xAAAAAAAA,0xAAAAAAAA,0xAAAAAAAA },
+ { 0xCCCCCCCC,0xCCCCCCCC,0xCCCCCCCC,0xCCCCCCCC,0xCCCCCCCC,0xCCCCCCCC,0xCCCCCCCC,0xCCCCCCCC },
+ { 0xF0F0F0F0,0xF0F0F0F0,0xF0F0F0F0,0xF0F0F0F0,0xF0F0F0F0,0xF0F0F0F0,0xF0F0F0F0,0xF0F0F0F0 },
+ { 0xFF00FF00,0xFF00FF00,0xFF00FF00,0xFF00FF00,0xFF00FF00,0xFF00FF00,0xFF00FF00,0xFF00FF00 },
+ { 0xFFFF0000,0xFFFF0000,0xFFFF0000,0xFFFF0000,0xFFFF0000,0xFFFF0000,0xFFFF0000,0xFFFF0000 },
+ { 0x00000000,0xFFFFFFFF,0x00000000,0xFFFFFFFF,0x00000000,0xFFFFFFFF,0x00000000,0xFFFFFFFF },
+ { 0x00000000,0x00000000,0xFFFFFFFF,0xFFFFFFFF,0x00000000,0x00000000,0xFFFFFFFF,0xFFFFFFFF },
+ { 0x00000000,0x00000000,0x00000000,0x00000000,0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF }
+ };
+ static unsigned * puResult[8] = {
+ uTruths[0], uTruths[1], uTruths[2], uTruths[3], uTruths[4], uTruths[5], uTruths[6], uTruths[7]
+ };
+ return (unsigned **)puResult;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Bubble-sorts components by scores in increasing order.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Extra_BubbleSort( int Order[], int Costs[], int nSize, int fIncreasing )
+{
+ int i, Temp, fChanges;
+ assert( nSize < 1000 );
+ for ( i = 0; i < nSize; i++ )
+ Order[i] = i;
+ if ( fIncreasing )
+ {
+ do {
+ fChanges = 0;
+ for ( i = 0; i < nSize - 1; i++ )
+ {
+ if ( Costs[Order[i]] <= Costs[Order[i+1]] )
+ continue;
+ Temp = Order[i];
+ Order[i] = Order[i+1];
+ Order[i+1] = Temp;
+ fChanges = 1;
+ }
+ } while ( fChanges );
+ }
+ else
+ {
+ do {
+ fChanges = 0;
+ for ( i = 0; i < nSize - 1; i++ )
+ {
+ if ( Costs[Order[i]] >= Costs[Order[i+1]] )
+ continue;
+ Temp = Order[i];
+ Order[i] = Order[i+1];
+ Order[i+1] = Temp;
+ fChanges = 1;
+ }
+ } while ( fChanges );
+ }
+}
+
+/**Function*************************************************************
+
Synopsis [Returns the smallest prime larger than the number.]
Description []
@@ -1415,7 +2153,6 @@ unsigned int Cudd_PrimeCopy( unsigned int p)
} /* end of Cudd_Prime */
-
/*---------------------------------------------------------------------------*/
/* Definition of internal functions */
/*---------------------------------------------------------------------------*/
@@ -1425,6 +2162,72 @@ unsigned int Cudd_PrimeCopy( unsigned int p)
/*---------------------------------------------------------------------------*/
+/**Function*************************************************************
+
+ Synopsis [Computes the permutation table for 8 variables.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Extra_TruthExpandGeneratePermTable()
+{
+ int i, k, nOnes, Last1, First0;
+ int iOne, iZero;
+
+ printf( "\nstatic char Cases[256] = {\n" );
+ for ( i = 0; i < 256; i++ )
+ {
+ nOnes = 0;
+ Last1 = First0 = -1;
+ for ( k = 0; k < 8; k++ )
+ {
+ if ( i & (1 << k) )
+ {
+ nOnes++;
+ Last1 = k;
+ }
+ else if ( First0 == -1 )
+ First0 = k;
+ }
+ if ( Last1 + 1 == First0 || i == 255 )
+ printf( " %d%s", 0, (i==255? " ":",") );
+ else if ( nOnes == 1 )
+ printf( " %d,", Last1 );
+ else
+ printf( " -%d,", 1 );
+ printf( " // " );
+ Extra_PrintBinary( stdout, (unsigned*)&i, 8 );
+ printf( "\n" );
+ }
+ printf( "};\n" );
+
+ printf( "\nstatic char Perms[256][8] = {\n" );
+ for ( i = 0; i < 256; i++ )
+ {
+ printf( " {" );
+ nOnes = 0;
+ for ( k = 0; k < 8; k++ )
+ if ( i & (1 << k) )
+ nOnes++;
+ iOne = 0;
+ iZero = nOnes;
+ for ( k = 0; k < 8; k++ )
+ if ( i & (1 << k) )
+ printf( "%s %d", (k==0? "":","), iOne++ );
+ else
+ printf( "%s %d", (k==0? "":","), iZero++ );
+ assert( iOne + iZero == 8 );
+ printf( " }%s // ", (i==255? " ":",") );
+ Extra_PrintBinary( stdout, (unsigned*)&i, 8 );
+ printf( "\n" );
+ }
+ printf( "};\n" );
+}
+
////////////////////////////////////////////////////////////////////////
/// END OF FILE ///
////////////////////////////////////////////////////////////////////////
diff --git a/src/misc/extra/extraUtilProgress.c b/src/misc/extra/extraUtilProgress.c
index 7b0efb5c..6b6d5132 100644
--- a/src/misc/extra/extraUtilProgress.c
+++ b/src/misc/extra/extraUtilProgress.c
@@ -18,7 +18,7 @@
***********************************************************************/
-#include "stdio.h"
+#include <stdio.h>
#include "extra.h"
////////////////////////////////////////////////////////////////////////
@@ -38,7 +38,7 @@ static void Extra_ProgressBarShow( ProgressBar * p, char * pString );
static void Extra_ProgressBarClean( ProgressBar * p );
////////////////////////////////////////////////////////////////////////
-/// FUNCTION DEFITIONS ///
+/// FUNCTION DEFINITIONS ///
////////////////////////////////////////////////////////////////////////
/**Function*************************************************************
@@ -58,13 +58,17 @@ static void Extra_ProgressBarClean( ProgressBar * p );
ProgressBar * Extra_ProgressBarStart( FILE * pFile, int nItemsTotal )
{
ProgressBar * p;
+ extern int Abc_FrameShowProgress( void * p );
+ extern void * Abc_FrameGetGlobalFrame();
+
+ if ( !Abc_FrameShowProgress(Abc_FrameGetGlobalFrame()) ) return NULL;
p = ALLOC( ProgressBar, 1 );
memset( p, 0, sizeof(ProgressBar) );
p->pFile = pFile;
p->nItemsTotal = nItemsTotal;
p->posTotal = 78;
p->posCur = 1;
- p->nItemsNext = (int)((float)p->nItemsTotal/p->posTotal)*(p->posCur+5)+2;
+ p->nItemsNext = (int)((7.0+p->posCur)*p->nItemsTotal/p->posTotal);
Extra_ProgressBarShow( p, NULL );
return p;
}
@@ -82,14 +86,19 @@ ProgressBar * Extra_ProgressBarStart( FILE * pFile, int nItemsTotal )
***********************************************************************/
void Extra_ProgressBarUpdate_int( ProgressBar * p, int nItemsCur, char * pString )
{
+ if ( p == NULL ) return;
if ( nItemsCur < p->nItemsNext )
return;
- if ( nItemsCur > p->nItemsTotal )
- nItemsCur = p->nItemsTotal;
- p->posCur = (int)((float)nItemsCur * p->posTotal / p->nItemsTotal);
- p->nItemsNext = (int)((float)p->nItemsTotal/p->posTotal)*(p->posCur+10)+1;
- if ( p->posCur == 0 )
- p->posCur = 1;
+ if ( nItemsCur >= p->nItemsTotal )
+ {
+ p->posCur = 78;
+ p->nItemsNext = 0x7FFFFFFF;
+ }
+ else
+ {
+ p->posCur += 7;
+ p->nItemsNext = (int)((7.0+p->posCur)*p->nItemsTotal/p->posTotal);
+ }
Extra_ProgressBarShow( p, pString );
}
@@ -107,6 +116,7 @@ void Extra_ProgressBarUpdate_int( ProgressBar * p, int nItemsCur, char * pString
***********************************************************************/
void Extra_ProgressBarStop( ProgressBar * p )
{
+ if ( p == NULL ) return;
Extra_ProgressBarClean( p );
FREE( p );
}
@@ -125,6 +135,7 @@ void Extra_ProgressBarStop( ProgressBar * p )
void Extra_ProgressBarShow( ProgressBar * p, char * pString )
{
int i;
+ if ( p == NULL ) return;
if ( pString )
fprintf( p->pFile, "%s ", pString );
for ( i = (pString? strlen(pString) + 1 : 0); i < p->posCur; i++ )
@@ -151,6 +162,7 @@ void Extra_ProgressBarShow( ProgressBar * p, char * pString )
void Extra_ProgressBarClean( ProgressBar * p )
{
int i;
+ if ( p == NULL ) return;
for ( i = 0; i <= p->posTotal; i++ )
fprintf( p->pFile, " " );
fprintf( p->pFile, "\r" );
diff --git a/src/misc/extra/extraUtilReader.c b/src/misc/extra/extraUtilReader.c
index 042dfaca..c165b989 100644
--- a/src/misc/extra/extraUtilReader.c
+++ b/src/misc/extra/extraUtilReader.c
@@ -18,7 +18,7 @@
***********************************************************************/
-#include "stdio.h"
+#include <stdio.h>
#include "extra.h"
#include "vec.h"
@@ -26,7 +26,7 @@
/// DECLARATIONS ///
////////////////////////////////////////////////////////////////////////
-#define EXTRA_BUFFER_SIZE 1048576 // 1M - size of the data chunk stored in memory
+#define EXTRA_BUFFER_SIZE 4*1048576 // 1M - size of the data chunk stored in memory
#define EXTRA_OFFSET_SIZE 4096 // 4K - load new data when less than this is left
#define EXTRA_MINIMUM(a,b) (((a) < (b))? (a) : (b))
@@ -67,7 +67,7 @@ static void * Extra_FileReaderGetTokens_int( Extra_FileReader_t * p );
static void Extra_FileReaderReload( Extra_FileReader_t * p );
////////////////////////////////////////////////////////////////////////
-/// FUNCTION DEFITIONS ///
+/// FUNCTION DEFINITIONS ///
////////////////////////////////////////////////////////////////////////
/**Function*************************************************************
@@ -262,6 +262,9 @@ void * Extra_FileReaderGetTokens_int( Extra_FileReader_t * p )
// check if the new data should to be loaded
if ( p->pBufferCur > p->pBufferStop )
Extra_FileReaderReload( p );
+
+// printf( "%d\n", p->pBufferEnd - p->pBufferCur );
+
// process the string starting from the current position
for ( pChar = p->pBufferCur; pChar < p->pBufferEnd; pChar++ )
{
@@ -270,6 +273,10 @@ void * Extra_FileReaderGetTokens_int( Extra_FileReader_t * p )
p->nLineCounter++;
// switch depending on the character
MapValue = p->pCharMap[*pChar];
+
+// printf( "Char value = %d. Map value = %d.\n", *pChar, MapValue );
+
+
switch ( MapValue )
{
case EXTRA_CHAR_COMMENT:
@@ -326,6 +333,14 @@ void * Extra_FileReaderGetTokens_int( Extra_FileReader_t * p )
return p->vTokens;
}
printf( "Extra_FileReader failed to parse the file \"%s\".\n", p->pFileName );
+/*
+ {
+ int i;
+ for ( i = 0; i < p->vTokens->nSize; i++ )
+ printf( "%s ", p->vTokens->pArray[i] );
+ printf( "\n" );
+ }
+*/
return NULL;
}
diff --git a/src/misc/extra/extraUtilTruth.c b/src/misc/extra/extraUtilTruth.c
new file mode 100644
index 00000000..3b0b16eb
--- /dev/null
+++ b/src/misc/extra/extraUtilTruth.c
@@ -0,0 +1,1148 @@
+/**CFile****************************************************************
+
+ FileName [extraUtilMisc.c]
+
+ SystemName [ABC: Logic synthesis and verification system.]
+
+ PackageName [extra]
+
+ Synopsis [Various procedures for truth table manipulation.]
+
+ Author [Alan Mishchenko]
+
+ Affiliation [UC Berkeley]
+
+ Date [Ver. 1.0. Started - June 20, 2005.]
+
+ Revision [$Id: extraUtilMisc.c,v 1.0 2003/09/01 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "extra.h"
+
+/*---------------------------------------------------------------------------*/
+/* Constant declarations */
+/*---------------------------------------------------------------------------*/
+
+/*---------------------------------------------------------------------------*/
+/* Stucture declarations */
+/*---------------------------------------------------------------------------*/
+
+/*---------------------------------------------------------------------------*/
+/* Type declarations */
+/*---------------------------------------------------------------------------*/
+
+/*---------------------------------------------------------------------------*/
+/* Variable declarations */
+/*---------------------------------------------------------------------------*/
+
+static unsigned s_VarMasks[5][2] = {
+ { 0x33333333, 0xAAAAAAAA },
+ { 0x55555555, 0xCCCCCCCC },
+ { 0x0F0F0F0F, 0xF0F0F0F0 },
+ { 0x00FF00FF, 0xFF00FF00 },
+ { 0x0000FFFF, 0xFFFF0000 }
+};
+
+/*---------------------------------------------------------------------------*/
+/* Macro declarations */
+/*---------------------------------------------------------------------------*/
+
+/**AutomaticStart*************************************************************/
+
+/*---------------------------------------------------------------------------*/
+/* Static function prototypes */
+/*---------------------------------------------------------------------------*/
+
+/**AutomaticEnd***************************************************************/
+
+/*---------------------------------------------------------------------------*/
+/* Definition of exported functions */
+/*---------------------------------------------------------------------------*/
+
+/**Function*************************************************************
+
+ Synopsis [Derive elementary truth tables.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+unsigned ** Extra_TruthElementary( int nVars )
+{
+ unsigned ** pRes;
+ int i, k, nWords;
+ nWords = Extra_TruthWordNum(nVars);
+ pRes = (unsigned **)Extra_ArrayAlloc( nVars, nWords, 4 );
+ for ( i = 0; i < nVars; i++ )
+ {
+ if ( i < 5 )
+ {
+ for ( k = 0; k < nWords; k++ )
+ pRes[i][k] = s_VarMasks[i][1];
+ }
+ else
+ {
+ for ( k = 0; k < nWords; k++ )
+ if ( k & (1 << (i-5)) )
+ pRes[i][k] = ~(unsigned)0;
+ else
+ pRes[i][k] = 0;
+ }
+ }
+ return pRes;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Swaps two adjacent variables in the truth table.]
+
+ Description [Swaps var number Start and var number Start+1 (0-based numbers).
+ The input truth table is pIn. The output truth table is pOut.]
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Extra_TruthSwapAdjacentVars( unsigned * pOut, unsigned * pIn, int nVars, int iVar )
+{
+ static unsigned PMasks[4][3] = {
+ { 0x99999999, 0x22222222, 0x44444444 },
+ { 0xC3C3C3C3, 0x0C0C0C0C, 0x30303030 },
+ { 0xF00FF00F, 0x00F000F0, 0x0F000F00 },
+ { 0xFF0000FF, 0x0000FF00, 0x00FF0000 }
+ };
+ int nWords = Extra_TruthWordNum( nVars );
+ int i, k, Step, Shift;
+
+ assert( iVar < nVars - 1 );
+ if ( iVar < 4 )
+ {
+ Shift = (1 << iVar);
+ for ( i = 0; i < nWords; i++ )
+ pOut[i] = (pIn[i] & PMasks[iVar][0]) | ((pIn[i] & PMasks[iVar][1]) << Shift) | ((pIn[i] & PMasks[iVar][2]) >> Shift);
+ }
+ else if ( iVar > 4 )
+ {
+ Step = (1 << (iVar - 5));
+ for ( k = 0; k < nWords; k += 4*Step )
+ {
+ for ( i = 0; i < Step; i++ )
+ pOut[i] = pIn[i];
+ for ( i = 0; i < Step; i++ )
+ pOut[Step+i] = pIn[2*Step+i];
+ for ( i = 0; i < Step; i++ )
+ pOut[2*Step+i] = pIn[Step+i];
+ for ( i = 0; i < Step; i++ )
+ pOut[3*Step+i] = pIn[3*Step+i];
+ pIn += 4*Step;
+ pOut += 4*Step;
+ }
+ }
+ else // if ( iVar == 4 )
+ {
+ for ( i = 0; i < nWords; i += 2 )
+ {
+ pOut[i] = (pIn[i] & 0x0000FFFF) | ((pIn[i+1] & 0x0000FFFF) << 16);
+ pOut[i+1] = (pIn[i+1] & 0xFFFF0000) | ((pIn[i] & 0xFFFF0000) >> 16);
+ }
+ }
+}
+
+/**Function*************************************************************
+
+ Synopsis [Swaps two adjacent variables in the truth table.]
+
+ Description [Swaps var number Start and var number Start+1 (0-based numbers).
+ The input truth table is pIn. The output truth table is pOut.]
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Extra_TruthSwapAdjacentVars2( unsigned * pIn, unsigned * pOut, int nVars, int Start )
+{
+ int nWords = (nVars <= 5)? 1 : (1 << (nVars-5));
+ int i, k, Step;
+
+ assert( Start < nVars - 1 );
+ switch ( Start )
+ {
+ case 0:
+ for ( i = 0; i < nWords; i++ )
+ pOut[i] = (pIn[i] & 0x99999999) | ((pIn[i] & 0x22222222) << 1) | ((pIn[i] & 0x44444444) >> 1);
+ return;
+ case 1:
+ for ( i = 0; i < nWords; i++ )
+ pOut[i] = (pIn[i] & 0xC3C3C3C3) | ((pIn[i] & 0x0C0C0C0C) << 2) | ((pIn[i] & 0x30303030) >> 2);
+ return;
+ case 2:
+ for ( i = 0; i < nWords; i++ )
+ pOut[i] = (pIn[i] & 0xF00FF00F) | ((pIn[i] & 0x00F000F0) << 4) | ((pIn[i] & 0x0F000F00) >> 4);
+ return;
+ case 3:
+ for ( i = 0; i < nWords; i++ )
+ pOut[i] = (pIn[i] & 0xFF0000FF) | ((pIn[i] & 0x0000FF00) << 8) | ((pIn[i] & 0x00FF0000) >> 8);
+ return;
+ case 4:
+ for ( i = 0; i < nWords; i += 2 )
+ {
+ pOut[i] = (pIn[i] & 0x0000FFFF) | ((pIn[i+1] & 0x0000FFFF) << 16);
+ pOut[i+1] = (pIn[i+1] & 0xFFFF0000) | ((pIn[i] & 0xFFFF0000) >> 16);
+ }
+ return;
+ default:
+ Step = (1 << (Start - 5));
+ for ( k = 0; k < nWords; k += 4*Step )
+ {
+ for ( i = 0; i < Step; i++ )
+ pOut[i] = pIn[i];
+ for ( i = 0; i < Step; i++ )
+ pOut[Step+i] = pIn[2*Step+i];
+ for ( i = 0; i < Step; i++ )
+ pOut[2*Step+i] = pIn[Step+i];
+ for ( i = 0; i < Step; i++ )
+ pOut[3*Step+i] = pIn[3*Step+i];
+ pIn += 4*Step;
+ pOut += 4*Step;
+ }
+ return;
+ }
+}
+
+/**Function*************************************************************
+
+ Synopsis [Expands the truth table according to the phase.]
+
+ Description [The input and output truth tables are in pIn/pOut. The current number
+ of variables is nVars. The total number of variables in nVarsAll. The last argument
+ (Phase) contains shows where the variables should go.]
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Extra_TruthStretch( unsigned * pOut, unsigned * pIn, int nVars, int nVarsAll, unsigned Phase )
+{
+ unsigned * pTemp;
+ int i, k, Var = nVars - 1, Counter = 0;
+ for ( i = nVarsAll - 1; i >= 0; i-- )
+ if ( Phase & (1 << i) )
+ {
+ for ( k = Var; k < i; k++ )
+ {
+ Extra_TruthSwapAdjacentVars( pOut, pIn, nVarsAll, k );
+ pTemp = pIn; pIn = pOut; pOut = pTemp;
+ Counter++;
+ }
+ Var--;
+ }
+ assert( Var == -1 );
+ // swap if it was moved an even number of times
+ if ( !(Counter & 1) )
+ Extra_TruthCopy( pOut, pIn, nVarsAll );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Shrinks the truth table according to the phase.]
+
+ Description [The input and output truth tables are in pIn/pOut. The current number
+ of variables is nVars. The total number of variables in nVarsAll. The last argument
+ (Phase) contains shows what variables should remain.]
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Extra_TruthShrink( unsigned * pOut, unsigned * pIn, int nVars, int nVarsAll, unsigned Phase )
+{
+ unsigned * pTemp;
+ int i, k, Var = 0, Counter = 0;
+ for ( i = 0; i < nVarsAll; i++ )
+ if ( Phase & (1 << i) )
+ {
+ for ( k = i-1; k >= Var; k-- )
+ {
+ Extra_TruthSwapAdjacentVars( pOut, pIn, nVarsAll, k );
+ pTemp = pIn; pIn = pOut; pOut = pTemp;
+ Counter++;
+ }
+ Var++;
+ }
+ assert( Var == nVars );
+ // swap if it was moved an even number of times
+ if ( !(Counter & 1) )
+ Extra_TruthCopy( pOut, pIn, nVarsAll );
+}
+
+
+/**Function*************************************************************
+
+ Synopsis [Returns 1 if TT depends on the given variable.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Extra_TruthVarInSupport( unsigned * pTruth, int nVars, int iVar )
+{
+ int nWords = Extra_TruthWordNum( nVars );
+ int i, k, Step;
+
+ assert( iVar < nVars );
+ switch ( iVar )
+ {
+ case 0:
+ for ( i = 0; i < nWords; i++ )
+ if ( (pTruth[i] & 0x55555555) != ((pTruth[i] & 0xAAAAAAAA) >> 1) )
+ return 1;
+ return 0;
+ case 1:
+ for ( i = 0; i < nWords; i++ )
+ if ( (pTruth[i] & 0x33333333) != ((pTruth[i] & 0xCCCCCCCC) >> 2) )
+ return 1;
+ return 0;
+ case 2:
+ for ( i = 0; i < nWords; i++ )
+ if ( (pTruth[i] & 0x0F0F0F0F) != ((pTruth[i] & 0xF0F0F0F0) >> 4) )
+ return 1;
+ return 0;
+ case 3:
+ for ( i = 0; i < nWords; i++ )
+ if ( (pTruth[i] & 0x00FF00FF) != ((pTruth[i] & 0xFF00FF00) >> 8) )
+ return 1;
+ return 0;
+ case 4:
+ for ( i = 0; i < nWords; i++ )
+ if ( (pTruth[i] & 0x0000FFFF) != ((pTruth[i] & 0xFFFF0000) >> 16) )
+ return 1;
+ return 0;
+ default:
+ Step = (1 << (iVar - 5));
+ for ( k = 0; k < nWords; k += 2*Step )
+ {
+ for ( i = 0; i < Step; i++ )
+ if ( pTruth[i] != pTruth[Step+i] )
+ return 1;
+ pTruth += 2*Step;
+ }
+ return 0;
+ }
+}
+
+/**Function*************************************************************
+
+ Synopsis [Returns the number of support vars.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Extra_TruthSupportSize( unsigned * pTruth, int nVars )
+{
+ int i, Counter = 0;
+ for ( i = 0; i < nVars; i++ )
+ Counter += Extra_TruthVarInSupport( pTruth, nVars, i );
+ return Counter;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Returns support of the function.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Extra_TruthSupport( unsigned * pTruth, int nVars )
+{
+ int i, Support = 0;
+ for ( i = 0; i < nVars; i++ )
+ if ( Extra_TruthVarInSupport( pTruth, nVars, i ) )
+ Support |= (1 << i);
+ return Support;
+}
+
+
+
+/**Function*************************************************************
+
+ Synopsis [Computes positive cofactor of the function.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Extra_TruthCofactor1( unsigned * pTruth, int nVars, int iVar )
+{
+ int nWords = Extra_TruthWordNum( nVars );
+ int i, k, Step;
+
+ assert( iVar < nVars );
+ switch ( iVar )
+ {
+ case 0:
+ for ( i = 0; i < nWords; i++ )
+ pTruth[i] = (pTruth[i] & 0xAAAAAAAA) | ((pTruth[i] & 0xAAAAAAAA) >> 1);
+ return;
+ case 1:
+ for ( i = 0; i < nWords; i++ )
+ pTruth[i] = (pTruth[i] & 0xCCCCCCCC) | ((pTruth[i] & 0xCCCCCCCC) >> 2);
+ return;
+ case 2:
+ for ( i = 0; i < nWords; i++ )
+ pTruth[i] = (pTruth[i] & 0xF0F0F0F0) | ((pTruth[i] & 0xF0F0F0F0) >> 4);
+ return;
+ case 3:
+ for ( i = 0; i < nWords; i++ )
+ pTruth[i] = (pTruth[i] & 0xFF00FF00) | ((pTruth[i] & 0xFF00FF00) >> 8);
+ return;
+ case 4:
+ for ( i = 0; i < nWords; i++ )
+ pTruth[i] = (pTruth[i] & 0xFFFF0000) | ((pTruth[i] & 0xFFFF0000) >> 16);
+ return;
+ default:
+ Step = (1 << (iVar - 5));
+ for ( k = 0; k < nWords; k += 2*Step )
+ {
+ for ( i = 0; i < Step; i++ )
+ pTruth[i] = pTruth[Step+i];
+ pTruth += 2*Step;
+ }
+ return;
+ }
+}
+
+/**Function*************************************************************
+
+ Synopsis [Computes negative cofactor of the function.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Extra_TruthCofactor0( unsigned * pTruth, int nVars, int iVar )
+{
+ int nWords = Extra_TruthWordNum( nVars );
+ int i, k, Step;
+
+ assert( iVar < nVars );
+ switch ( iVar )
+ {
+ case 0:
+ for ( i = 0; i < nWords; i++ )
+ pTruth[i] = (pTruth[i] & 0x55555555) | ((pTruth[i] & 0x55555555) << 1);
+ return;
+ case 1:
+ for ( i = 0; i < nWords; i++ )
+ pTruth[i] = (pTruth[i] & 0x33333333) | ((pTruth[i] & 0x33333333) << 2);
+ return;
+ case 2:
+ for ( i = 0; i < nWords; i++ )
+ pTruth[i] = (pTruth[i] & 0x0F0F0F0F) | ((pTruth[i] & 0x0F0F0F0F) << 4);
+ return;
+ case 3:
+ for ( i = 0; i < nWords; i++ )
+ pTruth[i] = (pTruth[i] & 0x00FF00FF) | ((pTruth[i] & 0x00FF00FF) << 8);
+ return;
+ case 4:
+ for ( i = 0; i < nWords; i++ )
+ pTruth[i] = (pTruth[i] & 0x0000FFFF) | ((pTruth[i] & 0x0000FFFF) << 16);
+ return;
+ default:
+ Step = (1 << (iVar - 5));
+ for ( k = 0; k < nWords; k += 2*Step )
+ {
+ for ( i = 0; i < Step; i++ )
+ pTruth[Step+i] = pTruth[i];
+ pTruth += 2*Step;
+ }
+ return;
+ }
+}
+
+
+/**Function*************************************************************
+
+ Synopsis [Existentially quantifies the variable.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Extra_TruthExist( unsigned * pTruth, int nVars, int iVar )
+{
+ int nWords = Extra_TruthWordNum( nVars );
+ int i, k, Step;
+
+ assert( iVar < nVars );
+ switch ( iVar )
+ {
+ case 0:
+ for ( i = 0; i < nWords; i++ )
+ pTruth[i] |= ((pTruth[i] & 0xAAAAAAAA) >> 1) | ((pTruth[i] & 0x55555555) << 1);
+ return;
+ case 1:
+ for ( i = 0; i < nWords; i++ )
+ pTruth[i] |= ((pTruth[i] & 0xCCCCCCCC) >> 2) | ((pTruth[i] & 0x33333333) << 2);
+ return;
+ case 2:
+ for ( i = 0; i < nWords; i++ )
+ pTruth[i] |= ((pTruth[i] & 0xF0F0F0F0) >> 4) | ((pTruth[i] & 0x0F0F0F0F) << 4);
+ return;
+ case 3:
+ for ( i = 0; i < nWords; i++ )
+ pTruth[i] |= ((pTruth[i] & 0xFF00FF00) >> 8) | ((pTruth[i] & 0x00FF00FF) << 8);
+ return;
+ case 4:
+ for ( i = 0; i < nWords; i++ )
+ pTruth[i] |= ((pTruth[i] & 0xFFFF0000) >> 16) | ((pTruth[i] & 0x0000FFFF) << 16);
+ return;
+ default:
+ Step = (1 << (iVar - 5));
+ for ( k = 0; k < nWords; k += 2*Step )
+ {
+ for ( i = 0; i < Step; i++ )
+ {
+ pTruth[i] |= pTruth[Step+i];
+ pTruth[Step+i] = pTruth[i];
+ }
+ pTruth += 2*Step;
+ }
+ return;
+ }
+}
+
+/**Function*************************************************************
+
+ Synopsis [Existentially quantifies the variable.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Extra_TruthForall( unsigned * pTruth, int nVars, int iVar )
+{
+ int nWords = Extra_TruthWordNum( nVars );
+ int i, k, Step;
+
+ assert( iVar < nVars );
+ switch ( iVar )
+ {
+ case 0:
+ for ( i = 0; i < nWords; i++ )
+ pTruth[i] &= ((pTruth[i] & 0xAAAAAAAA) >> 1) | ((pTruth[i] & 0x55555555) << 1);
+ return;
+ case 1:
+ for ( i = 0; i < nWords; i++ )
+ pTruth[i] &= ((pTruth[i] & 0xCCCCCCCC) >> 2) | ((pTruth[i] & 0x33333333) << 2);
+ return;
+ case 2:
+ for ( i = 0; i < nWords; i++ )
+ pTruth[i] &= ((pTruth[i] & 0xF0F0F0F0) >> 4) | ((pTruth[i] & 0x0F0F0F0F) << 4);
+ return;
+ case 3:
+ for ( i = 0; i < nWords; i++ )
+ pTruth[i] &= ((pTruth[i] & 0xFF00FF00) >> 8) | ((pTruth[i] & 0x00FF00FF) << 8);
+ return;
+ case 4:
+ for ( i = 0; i < nWords; i++ )
+ pTruth[i] &= ((pTruth[i] & 0xFFFF0000) >> 16) | ((pTruth[i] & 0x0000FFFF) << 16);
+ return;
+ default:
+ Step = (1 << (iVar - 5));
+ for ( k = 0; k < nWords; k += 2*Step )
+ {
+ for ( i = 0; i < Step; i++ )
+ {
+ pTruth[i] &= pTruth[Step+i];
+ pTruth[Step+i] = pTruth[i];
+ }
+ pTruth += 2*Step;
+ }
+ return;
+ }
+}
+
+
+/**Function*************************************************************
+
+ Synopsis [Computes negative cofactor of the function.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Extra_TruthMux( unsigned * pOut, unsigned * pCof0, unsigned * pCof1, int nVars, int iVar )
+{
+ int nWords = Extra_TruthWordNum( nVars );
+ int i, k, Step;
+
+ assert( iVar < nVars );
+ switch ( iVar )
+ {
+ case 0:
+ for ( i = 0; i < nWords; i++ )
+ pOut[i] = (pCof0[i] & 0x55555555) | (pCof1[i] & 0xAAAAAAAA);
+ return;
+ case 1:
+ for ( i = 0; i < nWords; i++ )
+ pOut[i] = (pCof0[i] & 0x33333333) | (pCof1[i] & 0xCCCCCCCC);
+ return;
+ case 2:
+ for ( i = 0; i < nWords; i++ )
+ pOut[i] = (pCof0[i] & 0x0F0F0F0F) | (pCof1[i] & 0xF0F0F0F0);
+ return;
+ case 3:
+ for ( i = 0; i < nWords; i++ )
+ pOut[i] = (pCof0[i] & 0x00FF00FF) | (pCof1[i] & 0xFF00FF00);
+ return;
+ case 4:
+ for ( i = 0; i < nWords; i++ )
+ pOut[i] = (pCof0[i] & 0x0000FFFF) | (pCof1[i] & 0xFFFF0000);
+ return;
+ default:
+ Step = (1 << (iVar - 5));
+ for ( k = 0; k < nWords; k += 2*Step )
+ {
+ for ( i = 0; i < Step; i++ )
+ {
+ pOut[i] = pCof0[i];
+ pOut[Step+i] = pCof1[Step+i];
+ }
+ pOut += 2*Step;
+ }
+ return;
+ }
+}
+
+/**Function*************************************************************
+
+ Synopsis [Checks symmetry of two variables.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Extra_TruthVarsSymm( unsigned * pTruth, int nVars, int iVar0, int iVar1 )
+{
+ static unsigned uTemp0[16], uTemp1[16];
+ assert( nVars <= 9 );
+ // compute Cof01
+ Extra_TruthCopy( uTemp0, pTruth, nVars );
+ Extra_TruthCofactor0( uTemp0, nVars, iVar0 );
+ Extra_TruthCofactor1( uTemp0, nVars, iVar1 );
+ // compute Cof10
+ Extra_TruthCopy( uTemp1, pTruth, nVars );
+ Extra_TruthCofactor1( uTemp1, nVars, iVar0 );
+ Extra_TruthCofactor0( uTemp1, nVars, iVar1 );
+ // compare
+ return Extra_TruthIsEqual( uTemp0, uTemp1, nVars );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Checks antisymmetry of two variables.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Extra_TruthVarsAntiSymm( unsigned * pTruth, int nVars, int iVar0, int iVar1 )
+{
+ static unsigned uTemp0[16], uTemp1[16];
+ assert( nVars <= 9 );
+ // compute Cof00
+ Extra_TruthCopy( uTemp0, pTruth, nVars );
+ Extra_TruthCofactor0( uTemp0, nVars, iVar0 );
+ Extra_TruthCofactor0( uTemp0, nVars, iVar1 );
+ // compute Cof11
+ Extra_TruthCopy( uTemp1, pTruth, nVars );
+ Extra_TruthCofactor1( uTemp1, nVars, iVar0 );
+ Extra_TruthCofactor1( uTemp1, nVars, iVar1 );
+ // compare
+ return Extra_TruthIsEqual( uTemp0, uTemp1, nVars );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Changes phase of the function w.r.t. one variable.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Extra_TruthChangePhase( unsigned * pTruth, int nVars, int iVar )
+{
+ int nWords = Extra_TruthWordNum( nVars );
+ int i, k, Step;
+ unsigned Temp;
+
+ assert( iVar < nVars );
+ switch ( iVar )
+ {
+ case 0:
+ for ( i = 0; i < nWords; i++ )
+ pTruth[i] = ((pTruth[i] & 0x55555555) << 1) | ((pTruth[i] & 0xAAAAAAAA) >> 1);
+ return;
+ case 1:
+ for ( i = 0; i < nWords; i++ )
+ pTruth[i] = ((pTruth[i] & 0x33333333) << 2) | ((pTruth[i] & 0xCCCCCCCC) >> 2);
+ return;
+ case 2:
+ for ( i = 0; i < nWords; i++ )
+ pTruth[i] = ((pTruth[i] & 0x0F0F0F0F) << 4) | ((pTruth[i] & 0xF0F0F0F0) >> 4);
+ return;
+ case 3:
+ for ( i = 0; i < nWords; i++ )
+ pTruth[i] = ((pTruth[i] & 0x00FF00FF) << 8) | ((pTruth[i] & 0xFF00FF00) >> 8);
+ return;
+ case 4:
+ for ( i = 0; i < nWords; i++ )
+ pTruth[i] = ((pTruth[i] & 0x0000FFFF) << 16) | ((pTruth[i] & 0xFFFF0000) >> 16);
+ return;
+ default:
+ Step = (1 << (iVar - 5));
+ for ( k = 0; k < nWords; k += 2*Step )
+ {
+ for ( i = 0; i < Step; i++ )
+ {
+ Temp = pTruth[i];
+ pTruth[i] = pTruth[Step+i];
+ pTruth[Step+i] = Temp;
+ }
+ pTruth += 2*Step;
+ }
+ return;
+ }
+}
+
+/**Function*************************************************************
+
+ Synopsis [Computes minimum overlap in supports of cofactors.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Extra_TruthMinCofSuppOverlap( unsigned * pTruth, int nVars, int * pVarMin )
+{
+ static unsigned uCofactor[16];
+ int i, ValueCur, ValueMin, VarMin;
+ unsigned uSupp0, uSupp1;
+ int nVars0, nVars1;
+ assert( nVars <= 9 );
+ ValueMin = 32;
+ VarMin = -1;
+ for ( i = 0; i < nVars; i++ )
+ {
+ // get negative cofactor
+ Extra_TruthCopy( uCofactor, pTruth, nVars );
+ Extra_TruthCofactor0( uCofactor, nVars, i );
+ uSupp0 = Extra_TruthSupport( uCofactor, nVars );
+ nVars0 = Extra_WordCountOnes( uSupp0 );
+//Extra_PrintBinary( stdout, &uSupp0, 8 ); printf( "\n" );
+ // get positive cofactor
+ Extra_TruthCopy( uCofactor, pTruth, nVars );
+ Extra_TruthCofactor1( uCofactor, nVars, i );
+ uSupp1 = Extra_TruthSupport( uCofactor, nVars );
+ nVars1 = Extra_WordCountOnes( uSupp1 );
+//Extra_PrintBinary( stdout, &uSupp1, 8 ); printf( "\n" );
+ // get the number of common vars
+ ValueCur = Extra_WordCountOnes( uSupp0 & uSupp1 );
+ if ( ValueMin > ValueCur && nVars0 <= 5 && nVars1 <= 5 )
+ {
+ ValueMin = ValueCur;
+ VarMin = i;
+ }
+ if ( ValueMin == 0 )
+ break;
+ }
+ if ( pVarMin )
+ *pVarMin = VarMin;
+ return ValueMin;
+}
+
+
+/**Function*************************************************************
+
+ Synopsis [Counts the number of 1's in each cofactor.]
+
+ Description [The resulting numbers are stored in the array of shorts,
+ whose length is 2*nVars. The number of 1's is counted in a different
+ space than the original function. For example, if the function depends
+ on k variables, the cofactors are assumed to depend on k-1 variables.]
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Extra_TruthCountOnesInCofs( unsigned * pTruth, int nVars, short * pStore )
+{
+ int nWords = Extra_TruthWordNum( nVars );
+ int i, k, Counter;
+ memset( pStore, 0, sizeof(short) * 2 * nVars );
+ if ( nVars <= 5 )
+ {
+ if ( nVars > 0 )
+ {
+ pStore[2*0+0] = Extra_WordCountOnes( pTruth[0] & 0x55555555 );
+ pStore[2*0+1] = Extra_WordCountOnes( pTruth[0] & 0xAAAAAAAA );
+ }
+ if ( nVars > 1 )
+ {
+ pStore[2*1+0] = Extra_WordCountOnes( pTruth[0] & 0x33333333 );
+ pStore[2*1+1] = Extra_WordCountOnes( pTruth[0] & 0xCCCCCCCC );
+ }
+ if ( nVars > 2 )
+ {
+ pStore[2*2+0] = Extra_WordCountOnes( pTruth[0] & 0x0F0F0F0F );
+ pStore[2*2+1] = Extra_WordCountOnes( pTruth[0] & 0xF0F0F0F0 );
+ }
+ if ( nVars > 3 )
+ {
+ pStore[2*3+0] = Extra_WordCountOnes( pTruth[0] & 0x00FF00FF );
+ pStore[2*3+1] = Extra_WordCountOnes( pTruth[0] & 0xFF00FF00 );
+ }
+ if ( nVars > 4 )
+ {
+ pStore[2*4+0] = Extra_WordCountOnes( pTruth[0] & 0x0000FFFF );
+ pStore[2*4+1] = Extra_WordCountOnes( pTruth[0] & 0xFFFF0000 );
+ }
+ return;
+ }
+ // nVars >= 6
+ // count 1's for all other variables
+ for ( k = 0; k < nWords; k++ )
+ {
+ Counter = Extra_WordCountOnes( pTruth[k] );
+ for ( i = 5; i < nVars; i++ )
+ if ( k & (1 << (i-5)) )
+ pStore[2*i+1] += Counter;
+ else
+ pStore[2*i+0] += Counter;
+ }
+ // count 1's for the first five variables
+ for ( k = 0; k < nWords/2; k++ )
+ {
+ pStore[2*0+0] += Extra_WordCountOnes( (pTruth[0] & 0x55555555) | ((pTruth[1] & 0x55555555) << 1) );
+ pStore[2*0+1] += Extra_WordCountOnes( (pTruth[0] & 0xAAAAAAAA) | ((pTruth[1] & 0xAAAAAAAA) >> 1) );
+ pStore[2*1+0] += Extra_WordCountOnes( (pTruth[0] & 0x33333333) | ((pTruth[1] & 0x33333333) << 2) );
+ pStore[2*1+1] += Extra_WordCountOnes( (pTruth[0] & 0xCCCCCCCC) | ((pTruth[1] & 0xCCCCCCCC) >> 2) );
+ pStore[2*2+0] += Extra_WordCountOnes( (pTruth[0] & 0x0F0F0F0F) | ((pTruth[1] & 0x0F0F0F0F) << 4) );
+ pStore[2*2+1] += Extra_WordCountOnes( (pTruth[0] & 0xF0F0F0F0) | ((pTruth[1] & 0xF0F0F0F0) >> 4) );
+ pStore[2*3+0] += Extra_WordCountOnes( (pTruth[0] & 0x00FF00FF) | ((pTruth[1] & 0x00FF00FF) << 8) );
+ pStore[2*3+1] += Extra_WordCountOnes( (pTruth[0] & 0xFF00FF00) | ((pTruth[1] & 0xFF00FF00) >> 8) );
+ pStore[2*4+0] += Extra_WordCountOnes( (pTruth[0] & 0x0000FFFF) | ((pTruth[1] & 0x0000FFFF) << 16) );
+ pStore[2*4+1] += Extra_WordCountOnes( (pTruth[0] & 0xFFFF0000) | ((pTruth[1] & 0xFFFF0000) >> 16) );
+ pTruth += 2;
+ }
+}
+
+
+/**Function*************************************************************
+
+ Synopsis [Canonicize the truth table.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+unsigned Extra_TruthHash( unsigned * pIn, int nWords )
+{
+ // The 1,024 smallest prime numbers used to compute the hash value
+ // http://www.math.utah.edu/~alfeld/math/primelist.html
+ static int HashPrimes[1024] = { 2, 3, 5,
+ 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47, 53, 59, 61, 67, 71, 73, 79, 83, 89, 97,
+ 101, 103, 107, 109, 113, 127, 131, 137, 139, 149, 151, 157, 163, 167, 173, 179, 181, 191,
+ 193, 197, 199, 211, 223, 227, 229, 233, 239, 241, 251, 257, 263, 269, 271, 277, 281, 283,
+ 293, 307, 311, 313, 317, 331, 337, 347, 349, 353, 359, 367, 373, 379, 383, 389, 397, 401,
+ 409, 419, 421, 431, 433, 439, 443, 449, 457, 461, 463, 467, 479, 487, 491, 499, 503, 509,
+ 521, 523, 541, 547, 557, 563, 569, 571, 577, 587, 593, 599, 601, 607, 613, 617, 619, 631,
+ 641, 643, 647, 653, 659, 661, 673, 677, 683, 691, 701, 709, 719, 727, 733, 739, 743, 751,
+ 757, 761, 769, 773, 787, 797, 809, 811, 821, 823, 827, 829, 839, 853, 857, 859, 863, 877,
+ 881, 883, 887, 907, 911, 919, 929, 937, 941, 947, 953, 967, 971, 977, 983, 991, 997,
+ 1009, 1013, 1019, 1021, 1031, 1033, 1039, 1049, 1051, 1061, 1063, 1069, 1087, 1091,
+ 1093, 1097, 1103, 1109, 1117, 1123, 1129, 1151, 1153, 1163, 1171, 1181, 1187, 1193,
+ 1201, 1213, 1217, 1223, 1229, 1231, 1237, 1249, 1259, 1277, 1279, 1283, 1289, 1291,
+ 1297, 1301, 1303, 1307, 1319, 1321, 1327, 1361, 1367, 1373, 1381, 1399, 1409, 1423,
+ 1427, 1429, 1433, 1439, 1447, 1451, 1453, 1459, 1471, 1481, 1483, 1487, 1489, 1493,
+ 1499, 1511, 1523, 1531, 1543, 1549, 1553, 1559, 1567, 1571, 1579, 1583, 1597, 1601,
+ 1607, 1609, 1613, 1619, 1621, 1627, 1637, 1657, 1663, 1667, 1669, 1693, 1697, 1699,
+ 1709, 1721, 1723, 1733, 1741, 1747, 1753, 1759, 1777, 1783, 1787, 1789, 1801, 1811,
+ 1823, 1831, 1847, 1861, 1867, 1871, 1873, 1877, 1879, 1889, 1901, 1907, 1913, 1931,
+ 1933, 1949, 1951, 1973, 1979, 1987, 1993, 1997, 1999, 2003, 2011, 2017, 2027, 2029,
+ 2039, 2053, 2063, 2069, 2081, 2083, 2087, 2089, 2099, 2111, 2113, 2129, 2131, 2137,
+ 2141, 2143, 2153, 2161, 2179, 2203, 2207, 2213, 2221, 2237, 2239, 2243, 2251, 2267,
+ 2269, 2273, 2281, 2287, 2293, 2297, 2309, 2311, 2333, 2339, 2341, 2347, 2351, 2357,
+ 2371, 2377, 2381, 2383, 2389, 2393, 2399, 2411, 2417, 2423, 2437, 2441, 2447, 2459,
+ 2467, 2473, 2477, 2503, 2521, 2531, 2539, 2543, 2549, 2551, 2557, 2579, 2591, 2593,
+ 2609, 2617, 2621, 2633, 2647, 2657, 2659, 2663, 2671, 2677, 2683, 2687, 2689, 2693,
+ 2699, 2707, 2711, 2713, 2719, 2729, 2731, 2741, 2749, 2753, 2767, 2777, 2789, 2791,
+ 2797, 2801, 2803, 2819, 2833, 2837, 2843, 2851, 2857, 2861, 2879, 2887, 2897, 2903,
+ 2909, 2917, 2927, 2939, 2953, 2957, 2963, 2969, 2971, 2999, 3001, 3011, 3019, 3023,
+ 3037, 3041, 3049, 3061, 3067, 3079, 3083, 3089, 3109, 3119, 3121, 3137, 3163, 3167,
+ 3169, 3181, 3187, 3191, 3203, 3209, 3217, 3221, 3229, 3251, 3253, 3257, 3259, 3271,
+ 3299, 3301, 3307, 3313, 3319, 3323, 3329, 3331, 3343, 3347, 3359, 3361, 3371, 3373,
+ 3389, 3391, 3407, 3413, 3433, 3449, 3457, 3461, 3463, 3467, 3469, 3491, 3499, 3511,
+ 3517, 3527, 3529, 3533, 3539, 3541, 3547, 3557, 3559, 3571, 3581, 3583, 3593, 3607,
+ 3613, 3617, 3623, 3631, 3637, 3643, 3659, 3671, 3673, 3677, 3691, 3697, 3701, 3709,
+ 3719, 3727, 3733, 3739, 3761, 3767, 3769, 3779, 3793, 3797, 3803, 3821, 3823, 3833,
+ 3847, 3851, 3853, 3863, 3877, 3881, 3889, 3907, 3911, 3917, 3919, 3923, 3929, 3931,
+ 3943, 3947, 3967, 3989, 4001, 4003, 4007, 4013, 4019, 4021, 4027, 4049, 4051, 4057,
+ 4073, 4079, 4091, 4093, 4099, 4111, 4127, 4129, 4133, 4139, 4153, 4157, 4159, 4177,
+ 4201, 4211, 4217, 4219, 4229, 4231, 4241, 4243, 4253, 4259, 4261, 4271, 4273, 4283,
+ 4289, 4297, 4327, 4337, 4339, 4349, 4357, 4363, 4373, 4391, 4397, 4409, 4421, 4423,
+ 4441, 4447, 4451, 4457, 4463, 4481, 4483, 4493, 4507, 4513, 4517, 4519, 4523, 4547,
+ 4549, 4561, 4567, 4583, 4591, 4597, 4603, 4621, 4637, 4639, 4643, 4649, 4651, 4657,
+ 4663, 4673, 4679, 4691, 4703, 4721, 4723, 4729, 4733, 4751, 4759, 4783, 4787, 4789,
+ 4793, 4799, 4801, 4813, 4817, 4831, 4861, 4871, 4877, 4889, 4903, 4909, 4919, 4931,
+ 4933, 4937, 4943, 4951, 4957, 4967, 4969, 4973, 4987, 4993, 4999, 5003, 5009, 5011,
+ 5021, 5023, 5039, 5051, 5059, 5077, 5081, 5087, 5099, 5101, 5107, 5113, 5119, 5147,
+ 5153, 5167, 5171, 5179, 5189, 5197, 5209, 5227, 5231, 5233, 5237, 5261, 5273, 5279,
+ 5281, 5297, 5303, 5309, 5323, 5333, 5347, 5351, 5381, 5387, 5393, 5399, 5407, 5413,
+ 5417, 5419, 5431, 5437, 5441, 5443, 5449, 5471, 5477, 5479, 5483, 5501, 5503, 5507,
+ 5519, 5521, 5527, 5531, 5557, 5563, 5569, 5573, 5581, 5591, 5623, 5639, 5641, 5647,
+ 5651, 5653, 5657, 5659, 5669, 5683, 5689, 5693, 5701, 5711, 5717, 5737, 5741, 5743,
+ 5749, 5779, 5783, 5791, 5801, 5807, 5813, 5821, 5827, 5839, 5843, 5849, 5851, 5857,
+ 5861, 5867, 5869, 5879, 5881, 5897, 5903, 5923, 5927, 5939, 5953, 5981, 5987, 6007,
+ 6011, 6029, 6037, 6043, 6047, 6053, 6067, 6073, 6079, 6089, 6091, 6101, 6113, 6121,
+ 6131, 6133, 6143, 6151, 6163, 6173, 6197, 6199, 6203, 6211, 6217, 6221, 6229, 6247,
+ 6257, 6263, 6269, 6271, 6277, 6287, 6299, 6301, 6311, 6317, 6323, 6329, 6337, 6343,
+ 6353, 6359, 6361, 6367, 6373, 6379, 6389, 6397, 6421, 6427, 6449, 6451, 6469, 6473,
+ 6481, 6491, 6521, 6529, 6547, 6551, 6553, 6563, 6569, 6571, 6577, 6581, 6599, 6607,
+ 6619, 6637, 6653, 6659, 6661, 6673, 6679, 6689, 6691, 6701, 6703, 6709, 6719, 6733,
+ 6737, 6761, 6763, 6779, 6781, 6791, 6793, 6803, 6823, 6827, 6829, 6833, 6841, 6857,
+ 6863, 6869, 6871, 6883, 6899, 6907, 6911, 6917, 6947, 6949, 6959, 6961, 6967, 6971,
+ 6977, 6983, 6991, 6997, 7001, 7013, 7019, 7027, 7039, 7043, 7057, 7069, 7079, 7103,
+ 7109, 7121, 7127, 7129, 7151, 7159, 7177, 7187, 7193, 7207, 7211, 7213, 7219, 7229,
+ 7237, 7243, 7247, 7253, 7283, 7297, 7307, 7309, 7321, 7331, 7333, 7349, 7351, 7369,
+ 7393, 7411, 7417, 7433, 7451, 7457, 7459, 7477, 7481, 7487, 7489, 7499, 7507, 7517,
+ 7523, 7529, 7537, 7541, 7547, 7549, 7559, 7561, 7573, 7577, 7583, 7589, 7591, 7603,
+ 7607, 7621, 7639, 7643, 7649, 7669, 7673, 7681, 7687, 7691, 7699, 7703, 7717, 7723,
+ 7727, 7741, 7753, 7757, 7759, 7789, 7793, 7817, 7823, 7829, 7841, 7853, 7867, 7873,
+ 7877, 7879, 7883, 7901, 7907, 7919, 7927, 7933, 7937, 7949, 7951, 7963, 7993, 8009,
+ 8011, 8017, 8039, 8053, 8059, 8069, 8081, 8087, 8089, 8093, 8101, 8111, 8117, 8123,
+ 8147, 8161 };
+ int i;
+ unsigned uHashKey;
+ assert( nWords <= 1024 );
+ uHashKey = 0;
+ for ( i = 0; i < nWords; i++ )
+ uHashKey ^= HashPrimes[i] * pIn[i];
+ return uHashKey;
+}
+
+
+/**Function*************************************************************
+
+ Synopsis [Canonicize the truth table.]
+
+ Description [Returns the phase. ]
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+unsigned Extra_TruthSemiCanonicize( unsigned * pInOut, unsigned * pAux, int nVars, char * pCanonPerm, short * pStore )
+{
+ unsigned * pIn = pInOut, * pOut = pAux, * pTemp;
+ int nWords = Extra_TruthWordNum( nVars );
+ int i, Temp, fChange, Counter, nOnes;//, k, j, w, Limit;
+ unsigned uCanonPhase;
+
+ // canonicize output
+ uCanonPhase = 0;
+ nOnes = Extra_TruthCountOnes(pIn, nVars);
+ if ( (nOnes > nWords * 16) || ((nOnes == nWords * 16) && (pIn[0] & 1)) )
+ {
+ uCanonPhase |= (1 << nVars);
+ Extra_TruthNot( pIn, pIn, nVars );
+ }
+
+ // collect the minterm counts
+ Extra_TruthCountOnesInCofs( pIn, nVars, pStore );
+
+ // canonicize phase
+ for ( i = 0; i < nVars; i++ )
+ {
+ if ( pStore[2*i+0] <= pStore[2*i+1] )
+ continue;
+ uCanonPhase |= (1 << i);
+ Temp = pStore[2*i+0];
+ pStore[2*i+0] = pStore[2*i+1];
+ pStore[2*i+1] = Temp;
+ Extra_TruthChangePhase( pIn, nVars, i );
+ }
+
+// Extra_PrintHexadecimal( stdout, pIn, nVars );
+// printf( "\n" );
+
+ // permute
+ Counter = 0;
+ do {
+ fChange = 0;
+ for ( i = 0; i < nVars-1; i++ )
+ {
+ if ( pStore[2*i] <= pStore[2*(i+1)] )
+ continue;
+ Counter++;
+ fChange = 1;
+
+ Temp = pCanonPerm[i];
+ pCanonPerm[i] = pCanonPerm[i+1];
+ pCanonPerm[i+1] = Temp;
+
+ Temp = pStore[2*i];
+ pStore[2*i] = pStore[2*(i+1)];
+ pStore[2*(i+1)] = Temp;
+
+ Temp = pStore[2*i+1];
+ pStore[2*i+1] = pStore[2*(i+1)+1];
+ pStore[2*(i+1)+1] = Temp;
+
+ Extra_TruthSwapAdjacentVars( pOut, pIn, nVars, i );
+ pTemp = pIn; pIn = pOut; pOut = pTemp;
+ }
+ } while ( fChange );
+
+/*
+ Extra_PrintBinary( stdout, &uCanonPhase, nVars+1 ); printf( " : " );
+ for ( i = 0; i < nVars; i++ )
+ printf( "%d=%d/%d ", pCanonPerm[i], pStore[2*i], pStore[2*i+1] );
+ printf( " C = %d\n", Counter );
+ Extra_PrintHexadecimal( stdout, pIn, nVars );
+ printf( "\n" );
+*/
+
+/*
+ // process symmetric variable groups
+ uSymms = 0;
+ for ( i = 0; i < nVars-1; i++ )
+ {
+ if ( pStore[2*i] != pStore[2*(i+1)] ) // i and i+1 cannot be symmetric
+ continue;
+ if ( pStore[2*i] != pStore[2*i+1] )
+ continue;
+ if ( Extra_TruthVarsSymm( pIn, nVars, i, i+1 ) )
+ continue;
+ if ( Extra_TruthVarsAntiSymm( pIn, nVars, i, i+1 ) )
+ Extra_TruthChangePhase( pIn, nVars, i+1 );
+ }
+*/
+
+/*
+ // process symmetric variable groups
+ uSymms = 0;
+ for ( i = 0; i < nVars-1; i++ )
+ {
+ if ( pStore[2*i] != pStore[2*(i+1)] ) // i and i+1 cannot be symmetric
+ continue;
+ // i and i+1 can be symmetric
+ // find the end of this group
+ for ( k = i+1; k < nVars; k++ )
+ if ( pStore[2*i] != pStore[2*k] )
+ break;
+ Limit = k;
+ assert( i < Limit-1 );
+ // go through the variables in this group
+ for ( j = i + 1; j < Limit; j++ )
+ {
+ // check symmetry
+ if ( Extra_TruthVarsSymm( pIn, nVars, i, j ) )
+ {
+ uSymms |= (1 << j);
+ continue;
+ }
+ // they are phase-unknown
+ if ( pStore[2*i] == pStore[2*i+1] )
+ {
+ if ( Extra_TruthVarsAntiSymm( pIn, nVars, i, j ) )
+ {
+ Extra_TruthChangePhase( pIn, nVars, j );
+ uCanonPhase ^= (1 << j);
+ uSymms |= (1 << j);
+ continue;
+ }
+ }
+
+ // they are not symmetric - move j as far as it goes in the group
+ for ( k = j; k < Limit-1; k++ )
+ {
+ Counter++;
+
+ Temp = pCanonPerm[k];
+ pCanonPerm[k] = pCanonPerm[k+1];
+ pCanonPerm[k+1] = Temp;
+
+ assert( pStore[2*k] == pStore[2*(k+1)] );
+ Extra_TruthSwapAdjacentVars( pOut, pIn, nVars, k );
+ pTemp = pIn; pIn = pOut; pOut = pTemp;
+ }
+ Limit--;
+ j--;
+ }
+ i = Limit - 1;
+ }
+*/
+
+ // swap if it was moved an even number of times
+ if ( Counter & 1 )
+ Extra_TruthCopy( pOut, pIn, nVars );
+ return uCanonPhase;
+}
+
+////////////////////////////////////////////////////////////////////////
+/// END OF FILE ///
+////////////////////////////////////////////////////////////////////////
+
+
diff --git a/src/misc/extra/extraUtilUtil.c b/src/misc/extra/extraUtilUtil.c
new file mode 100644
index 00000000..c685f7bc
--- /dev/null
+++ b/src/misc/extra/extraUtilUtil.c
@@ -0,0 +1,356 @@
+/**CFile****************************************************************
+
+ FileName [extraUtilUtil.c]
+
+ SystemName [ABC: Logic synthesis and verification system.]
+
+ PackageName [extra]
+
+ Synopsis [Old SIS utilities.]
+
+ Author [Alan Mishchenko]
+
+ Affiliation [UC Berkeley]
+
+ Date [Ver. 1.0. Started - June 20, 2005.]
+
+ Revision [$Id: extraUtilUtil.c,v 1.0 2003/02/01 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include <stdio.h>
+#include "extra.h"
+
+////////////////////////////////////////////////////////////////////////
+/// DECLARATIONS ///
+////////////////////////////////////////////////////////////////////////
+
+#define EXTRA_RLIMIT_DATA_DEFAULT 67108864 // assume 64MB by default
+
+/* File : getopt.c
+ * Author : Henry Spencer, University of Toronto
+ * Updated: 28 April 1984
+ *
+ * Changes: (R Rudell)
+ * changed index() to strchr();
+ * added getopt_reset() to reset the getopt argument parsing
+ *
+ * Purpose: get option letter from argv.
+ */
+
+char * globalUtilOptarg; // Global argument pointer (util_optarg)
+int globalUtilOptind = 0; // Global argv index (util_optind)
+
+static char *pScanStr;
+
+////////////////////////////////////////////////////////////////////////
+/// FUNCTION DEFINITIONS ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+ Synopsis [util_cpu_time()]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+long Extra_CpuTime()
+{
+ return clock();
+}
+
+/**Function*************************************************************
+
+ Synopsis [getSoftDataLimit()]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Extra_GetSoftDataLimit()
+{
+ return EXTRA_RLIMIT_DATA_DEFAULT;
+}
+
+/**Function*************************************************************
+
+ Synopsis [util_getopt_reset()]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Extra_UtilGetoptReset()
+{
+ globalUtilOptarg = 0;
+ globalUtilOptind = 0;
+ pScanStr = 0;
+}
+
+/**Function*************************************************************
+
+ Synopsis [util_getopt()]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Extra_UtilGetopt( int argc, char *argv[], char *optstring )
+{
+ register int c;
+ register char *place;
+
+ globalUtilOptarg = NULL;
+
+ if (pScanStr == NULL || *pScanStr == '\0') {
+ if (globalUtilOptind == 0) globalUtilOptind++;
+ if (globalUtilOptind >= argc) return EOF;
+ place = argv[globalUtilOptind];
+ if (place[0] != '-' || place[1] == '\0') return EOF;
+ globalUtilOptind++;
+ if (place[1] == '-' && place[2] == '\0') return EOF;
+ pScanStr = place+1;
+ }
+
+ c = *pScanStr++;
+ place = strchr(optstring, c);
+ if (place == NULL || c == ':') {
+ (void) fprintf(stderr, "%s: unknown option %c\n", argv[0], c);
+ return '?';
+ }
+ if (*++place == ':') {
+ if (*pScanStr != '\0') {
+ globalUtilOptarg = pScanStr;
+ pScanStr = NULL;
+ } else {
+ if (globalUtilOptind >= argc) {
+ (void) fprintf(stderr, "%s: %c requires an argument\n",
+ argv[0], c);
+ return '?';
+ }
+ globalUtilOptarg = argv[globalUtilOptind];
+ globalUtilOptind++;
+ }
+ }
+ return c;
+}
+
+/**Function*************************************************************
+
+ Synopsis [util_print_time()]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+char * Extra_UtilPrintTime( long t )
+{
+ static char s[40];
+
+ (void) sprintf(s, "%ld.%02ld sec", t/1000, (t%1000)/10);
+ return s;
+}
+
+
+/**Function*************************************************************
+
+ Synopsis [Extra_UtilStrsav()]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+char * Extra_UtilStrsav( char *s )
+{
+ if(s == NULL) { /* added 7/95, for robustness */
+ return s;
+ }
+ else {
+ return strcpy(ALLOC(char, strlen(s)+1), s);
+ }
+}
+
+/**Function*************************************************************
+
+ Synopsis [util_tilde_expand()]
+
+ Description [The code contributed by Niklas Sorensson.]
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+char * Extra_UtilTildeExpand( char *fname )
+{
+ return Extra_UtilStrsav( fname );
+/*
+ int n_tildes = 0;
+ const char* home;
+ char* expanded;
+ int length;
+ int i, j, k;
+
+ for (i = 0; i < (int)strlen(fname); i++)
+ if (fname[i] == '~') n_tildes++;
+
+ home = getenv("HOME");
+ length = n_tildes * strlen(home) + strlen(fname);
+ expanded = ALLOC(char, length + 1);
+
+ j = 0;
+ for (i = 0; i < (int)strlen(fname); i++){
+ if (fname[i] == '~'){
+ for (k = 0; k < (int)strlen(home); k++)
+ expanded[j++] = home[k];
+ }else
+ expanded[j++] = fname[i];
+ }
+
+ expanded[j] = '\0';
+ return expanded;
+*/
+}
+
+/**Function*************************************************************
+
+ Synopsis [check_file()]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Extra_UtilCheckFile(char *filename, char *mode)
+{
+ FILE *fp;
+ int got_file;
+
+ if (strcmp(mode, "x") == 0) {
+ mode = "r";
+ }
+ fp = fopen(filename, mode);
+ got_file = (fp != 0);
+ if (fp != 0) {
+ (void) fclose(fp);
+ }
+ return got_file;
+}
+
+/**Function*************************************************************
+
+ Synopsis [util_file_search()]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+char * Extra_UtilFileSearch(char *file, char *path, char *mode)
+//char *file; // file we're looking for
+//char *path; // search path, colon separated
+//char *mode; // "r", "w", or "x"
+{
+ int quit;
+ char *buffer, *filename, *save_path, *cp;
+
+ if (path == 0 || strcmp(path, "") == 0) {
+ path = "."; /* just look in the current directory */
+ }
+
+ save_path = path = Extra_UtilStrsav(path);
+ quit = 0;
+ do {
+ cp = strchr(path, ':');
+ if (cp != 0) {
+ *cp = '\0';
+ } else {
+ quit = 1;
+ }
+
+ /* cons up the filename out of the path and file name */
+ if (strcmp(path, ".") == 0) {
+ buffer = Extra_UtilStrsav(file);
+ } else {
+ buffer = ALLOC(char, strlen(path) + strlen(file) + 4);
+ (void) sprintf(buffer, "%s/%s", path, file);
+ }
+ filename = Extra_UtilTildeExpand(buffer);
+ FREE(buffer);
+
+ /* see if we can access it */
+ if (Extra_UtilCheckFile(filename, mode)) {
+ FREE(save_path);
+ return filename;
+ }
+ FREE(filename);
+ path = ++cp;
+ } while (! quit);
+
+ FREE(save_path);
+ return 0;
+}
+
+/**Function*************************************************************
+
+ Synopsis [MMout_of_memory()]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+/* MMout_of_memory -- out of memory for lazy people, flush and exit */
+void Extra_UtilMMout_Of_Memory( long size )
+{
+ (void) fflush(stdout);
+ (void) fprintf(stderr, "\nout of memory allocating %u bytes\n",
+ (unsigned) size);
+ assert( 0 );
+ exit(1);
+}
+
+/**Function*************************************************************
+
+ Synopsis [MMoutOfMemory()]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void (*Extra_UtilMMoutOfMemory)() = Extra_UtilMMout_Of_Memory;
+
+
+////////////////////////////////////////////////////////////////////////
+/// END OF FILE ///
+////////////////////////////////////////////////////////////////////////
+
+
diff --git a/src/misc/extra/module.make b/src/misc/extra/module.make
index 6cbf5d2c..ec8bca4d 100644
--- a/src/misc/extra/module.make
+++ b/src/misc/extra/module.make
@@ -1,9 +1,15 @@
-SRC += src/misc/extra/extraBddMisc.c \
+SRC += src/misc/extra/extraBddAuto.c \
+ src/misc/extra/extraBddCas.c \
+ src/misc/extra/extraBddKmap.c \
+ src/misc/extra/extraBddMisc.c \
src/misc/extra/extraBddSymm.c \
+ src/misc/extra/extraBddUnate.c \
src/misc/extra/extraUtilBitMatrix.c \
src/misc/extra/extraUtilCanon.c \
src/misc/extra/extraUtilFile.c \
src/misc/extra/extraUtilMemory.c \
src/misc/extra/extraUtilMisc.c \
src/misc/extra/extraUtilProgress.c \
- src/misc/extra/extraUtilReader.c
+ src/misc/extra/extraUtilReader.c \
+ src/misc/extra/extraUtilTruth.c \
+ src/misc/extra/extraUtilUtil.c
diff --git a/src/misc/hash/hash.h b/src/misc/hash/hash.h
new file mode 100644
index 00000000..90e72868
--- /dev/null
+++ b/src/misc/hash/hash.h
@@ -0,0 +1,65 @@
+/**CFile****************************************************************
+
+ FileName [hash.h]
+
+ SystemName [ABC: Logic synthesis and verification system.]
+
+ PackageName [Hash map.]
+
+ Synopsis [External declarations.]
+
+ Author [Aaron P. Hurst]
+
+ Affiliation [UC Berkeley]
+
+ Date [Ver. 1.0. Started - May 16, 2005.]
+
+ Revision [$Id: vec.h,v 1.00 2005/06/20 00:00:00 ahurst Exp $]
+
+***********************************************************************/
+
+#ifndef __HASH_H__
+#define __HASH_H__
+
+////////////////////////////////////////////////////////////////////////
+/// INCLUDES ///
+////////////////////////////////////////////////////////////////////////
+
+#ifdef _WIN32
+#define inline __inline // compatible with MS VS 6.0
+#endif
+
+#include "hashInt.h"
+#include "hashFlt.h"
+#include "hashPtr.h"
+
+////////////////////////////////////////////////////////////////////////
+/// PARAMETERS ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+/// BASIC TYPES ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+/// MACRO DEFINITIONS ///
+////////////////////////////////////////////////////////////////////////
+
+#ifndef ABS
+#define ABS(a) ((a) < 0 ? -(a) : (a))
+#endif
+
+////////////////////////////////////////////////////////////////////////
+/// FUNCTION DECLARATIONS ///
+////////////////////////////////////////////////////////////////////////
+
+int Hash_DefaultHashFunc(int key, int nBins) {
+ return ABS( ( (key+11)*(key)*7+3 ) % nBins );
+}
+
+////////////////////////////////////////////////////////////////////////
+/// END OF FILE ///
+////////////////////////////////////////////////////////////////////////
+
+#endif
+
diff --git a/src/misc/hash/hashFlt.h b/src/misc/hash/hashFlt.h
new file mode 100644
index 00000000..da20ee28
--- /dev/null
+++ b/src/misc/hash/hashFlt.h
@@ -0,0 +1,330 @@
+/**CFile****************************************************************
+
+ FileName [hashFlt.h]
+
+ SystemName [ABC: Logic synthesis and verification system.]
+
+ PackageName [Hash maps.]
+
+ Synopsis [Hash maps.]
+
+ Author [Aaron P. Hurst]
+
+ Affiliation [UC Berkeley]
+
+ Date [Ver. 1.0. Started - May 16, 2006.]
+
+ Revision [$Id: vecInt.h,v 1.00 2005/06/20 00:00:00 ahurst Exp $]
+
+***********************************************************************/
+
+#ifndef __HASH_FLT_H__
+#define __HASH_FLT_H__
+
+////////////////////////////////////////////////////////////////////////
+/// INCLUDES ///
+////////////////////////////////////////////////////////////////////////
+
+#include <stdio.h>
+#include "extra.h"
+
+extern int Hash_DefaultHashFunc(int key, int nBins);
+
+////////////////////////////////////////////////////////////////////////
+/// PARAMETERS ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+/// BASIC TYPES ///
+////////////////////////////////////////////////////////////////////////
+
+typedef struct Hash_Flt_t_ Hash_Flt_t;
+typedef struct Hash_Flt_Entry_t_ Hash_Flt_Entry_t;
+
+struct Hash_Flt_Entry_t_
+{
+ int key;
+ float data;
+ struct Hash_Flt_Entry_t_ * pNext;
+};
+
+struct Hash_Flt_t_
+{
+ int nSize;
+ int nBins;
+ int (* fHash)(int key, int nBins);
+ Hash_Flt_Entry_t ** pArray;
+};
+
+
+
+////////////////////////////////////////////////////////////////////////
+/// MACRO DEFINITIONS ///
+////////////////////////////////////////////////////////////////////////
+
+#define Hash_FltForEachEntry( pHash, pEntry, bin) \
+ for(bin=-1, pEntry=NULL; bin < pHash->nBins; (!pEntry)?(pEntry=pHash->pArray[++bin]):(pEntry=pEntry->pNext)) \
+ if (pEntry)
+
+////////////////////////////////////////////////////////////////////////
+/// FUNCTION DEFINITIONS ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+ Synopsis [Allocates a hash map with the given number of bins.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+static inline Hash_Flt_t * Hash_FltAlloc( int nBins )
+{
+ Hash_Flt_t * p;
+ int i;
+ assert(nBins > 0);
+ p = ALLOC( Hash_Flt_t, 1);
+ p->nBins = nBins;
+ p->fHash = Hash_DefaultHashFunc;
+ p->nSize = 0;
+ p->pArray = ALLOC( Hash_Flt_Entry_t *, nBins );
+ for(i=0; i<nBins; i++)
+ p->pArray[i] = NULL;
+
+ return p;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Returns 1 if a key already exists.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+static inline int Hash_FltExists( Hash_Flt_t *p, int key )
+{
+ int bin;
+ Hash_Flt_Entry_t *pEntry, **pLast;
+
+ // find the bin where this key would live
+ bin = (*(p->fHash))(key, p->nBins);
+
+ // search for key
+ pLast = &(p->pArray[bin]);
+ pEntry = p->pArray[bin];
+ while(pEntry) {
+ if (pEntry->key == key) {
+ return 1;
+ }
+ pLast = &(pEntry->pNext);
+ pEntry = pEntry->pNext;
+ }
+
+ return 0;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Finds or creates an entry with a key and writes value.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+static inline void Hash_FltWriteEntry( Hash_Flt_t *p, int key, float data )
+{
+ int bin;
+ Hash_Flt_Entry_t *pEntry, **pLast;
+
+ // find the bin where this key would live
+ bin = (*(p->fHash))(key, p->nBins);
+
+ // search for key
+ pLast = &(p->pArray[bin]);
+ pEntry = p->pArray[bin];
+ while(pEntry) {
+ if (pEntry->key == key) {
+ pEntry->data = data;
+ return;
+ }
+ pLast = &(pEntry->pNext);
+ pEntry = pEntry->pNext;
+ }
+
+ // this key does not currently exist
+ // create a new entry and add to bin
+ p->nSize++;
+ (*pLast) = pEntry = ALLOC( Hash_Flt_Entry_t, 1 );
+ pEntry->pNext = NULL;
+ pEntry->key = key;
+ pEntry->data = data;
+
+ return;
+}
+
+
+/**Function*************************************************************
+
+ Synopsis [Finds or creates an entry with a key.]
+
+ Description [fCreate specifies whether new entries should be created.]
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+static inline float Hash_FltEntry( Hash_Flt_t *p, int key, int fCreate )
+{
+ int bin;
+ Hash_Flt_Entry_t *pEntry, **pLast;
+
+ // find the bin where this key would live
+ bin = (*(p->fHash))(key, p->nBins);
+
+ // search for key
+ pLast = &(p->pArray[bin]);
+ pEntry = p->pArray[bin];
+ while(pEntry) {
+ if (pEntry->key == key)
+ return pEntry->data;
+ pLast = &(pEntry->pNext);
+ pEntry = pEntry->pNext;
+ }
+
+ // this key does not currently exist
+ if (fCreate) {
+ // create a new entry and add to bin
+ p->nSize++;
+ (*pLast) = pEntry = ALLOC( Hash_Flt_Entry_t, 1 );
+ pEntry->pNext = NULL;
+ pEntry->key = key;
+ pEntry->data = 0.0;
+ return pEntry->data;
+ }
+
+ return 0.0;
+}
+
+
+/**Function*************************************************************
+
+ Synopsis [Finds or creates an entry with a key and returns the pointer to it.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+static inline float* Hash_FltEntryPtr( Hash_Flt_t *p, int key )
+{
+ int bin;
+ Hash_Flt_Entry_t *pEntry, **pLast;
+
+ // find the bin where this key would live
+ bin = (*(p->fHash))(key, p->nBins);
+
+ // search for key
+ pLast = &(p->pArray[bin]);
+ pEntry = p->pArray[bin];
+ while(pEntry) {
+ if (pEntry->key == key)
+ return &(pEntry->data);
+ pLast = &(pEntry->pNext);
+ pEntry = pEntry->pNext;
+ }
+
+ // this key does not currently exist
+ // create a new entry and add to bin
+ p->nSize++;
+ (*pLast) = pEntry = ALLOC( Hash_Flt_Entry_t, 1 );
+ pEntry->pNext = NULL;
+ pEntry->key = key;
+ pEntry->data = 0.0;
+
+ return &(pEntry->data);
+}
+
+/**Function*************************************************************
+
+ Synopsis [Deletes an entry.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+static inline void Hash_FltRemove( Hash_Flt_t *p, int key )
+{
+ int bin;
+ Hash_Flt_Entry_t *pEntry, **pLast;
+
+ // find the bin where this key would live
+ bin = (*(p->fHash))(key, p->nBins);
+
+ // search for key
+ pLast = &(p->pArray[bin]);
+ pEntry = p->pArray[bin];
+ while(pEntry) {
+ if (pEntry->key == key) {
+ p->nSize--;
+ *pLast = pEntry->pNext;
+ FREE( pEntry );
+ return;
+ }
+ pLast = &(pEntry->pNext);
+ pEntry = pEntry->pNext;
+ }
+
+ // could not find key
+ return;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Frees the hash.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+static inline void Hash_FltFree( Hash_Flt_t *p ) {
+ int bin;
+ Hash_Flt_Entry_t *pEntry;
+
+ // free bins
+ for(bin = 0; bin < p->nBins; bin++) {
+ pEntry = p->pArray[bin];
+ while(pEntry) {
+ pEntry = pEntry->pNext;
+ FREE( pEntry );
+ }
+ }
+
+ // free hash
+ FREE( p->pArray );
+ FREE( p );
+}
+
+////////////////////////////////////////////////////////////////////////
+/// END OF FILE ///
+////////////////////////////////////////////////////////////////////////
+
+#endif
diff --git a/src/misc/hash/hashInt.h b/src/misc/hash/hashInt.h
new file mode 100644
index 00000000..3b91f5df
--- /dev/null
+++ b/src/misc/hash/hashInt.h
@@ -0,0 +1,293 @@
+/**CFile****************************************************************
+
+ FileName [hashInt.h]
+
+ SystemName [ABC: Logic synthesis and verification system.]
+
+ PackageName [Hash maps.]
+
+ Synopsis [Hash maps.]
+
+ Author [Aaron P. Hurst]
+
+ Affiliation [UC Berkeley]
+
+ Date [Ver. 1.0. Started - May 16, 2006.]
+
+ Revision [$Id: vecInt.h,v 1.00 2005/06/20 00:00:00 ahurst Exp $]
+
+***********************************************************************/
+
+#ifndef __HASH_INT_H__
+#define __HASH_INT_H__
+
+////////////////////////////////////////////////////////////////////////
+/// INCLUDES ///
+////////////////////////////////////////////////////////////////////////
+
+#include <stdio.h>
+#include "extra.h"
+
+extern int Hash_DefaultHashFunc(int key, int nBins);
+
+////////////////////////////////////////////////////////////////////////
+/// PARAMETERS ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+/// BASIC TYPES ///
+////////////////////////////////////////////////////////////////////////
+
+typedef struct Hash_Int_t_ Hash_Int_t;
+typedef struct Hash_Int_Entry_t_ Hash_Int_Entry_t;
+
+struct Hash_Int_Entry_t_
+{
+ int key;
+ int data;
+ struct Hash_Int_Entry_t_ * pNext;
+};
+
+struct Hash_Int_t_
+{
+ int nSize;
+ int nBins;
+ int (* fHash)(int key, int nBins);
+ Hash_Int_Entry_t ** pArray;
+};
+
+
+
+////////////////////////////////////////////////////////////////////////
+/// MACRO DEFINITIONS ///
+////////////////////////////////////////////////////////////////////////
+
+#define Hash_IntForEachEntry( pHash, pEntry, bin) \
+ for(bin=-1, pEntry=NULL; bin < pHash->nBins; (!pEntry)?(pEntry=pHash->pArray[++bin]):(pEntry=pEntry->pNext)) \
+ if (pEntry)
+
+////////////////////////////////////////////////////////////////////////
+/// FUNCTION DEFINITIONS ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+ Synopsis [Allocates a hash map with the given number of bins.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+static inline Hash_Int_t * Hash_IntAlloc( int nBins )
+{
+ Hash_Int_t * p;
+ int i;
+ assert(nBins > 0);
+ p = ALLOC( Hash_Int_t, 1);
+ p->nBins = nBins;
+ p->fHash = Hash_DefaultHashFunc;
+ p->nSize = 0;
+ p->pArray = ALLOC( Hash_Int_Entry_t *, nBins );
+ for(i=0; i<nBins; i++)
+ p->pArray[i] = NULL;
+
+ return p;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Returns 1 if a key already exists.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+static inline int Hash_IntExists( Hash_Int_t *p, int key)
+{
+ int bin;
+ Hash_Int_Entry_t *pEntry, **pLast;
+
+ // find the bin where this key would live
+ bin = (*(p->fHash))(key, p->nBins);
+
+ // search for key
+ pLast = &(p->pArray[bin]);
+ pEntry = p->pArray[bin];
+ while(pEntry) {
+ if (pEntry->key == key) {
+ return 1;
+ }
+ pLast = &(pEntry->pNext);
+ pEntry = pEntry->pNext;
+ }
+
+ return 0;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Finds or creates an entry with a key and writes value.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+static inline void Hash_IntWriteEntry( Hash_Int_t *p, int key, int data )
+{
+ int bin;
+ Hash_Int_Entry_t *pEntry, **pLast;
+
+ // find the bin where this key would live
+ bin = (*(p->fHash))(key, p->nBins);
+
+ // search for key
+ pLast = &(p->pArray[bin]);
+ pEntry = p->pArray[bin];
+ while(pEntry) {
+ if (pEntry->key == key) {
+ pEntry->data = data;
+ return;
+ }
+ pLast = &(pEntry->pNext);
+ pEntry = pEntry->pNext;
+ }
+
+ // this key does not currently exist
+ // create a new entry and add to bin
+ p->nSize++;
+ (*pLast) = pEntry = ALLOC( Hash_Int_Entry_t, 1 );
+ pEntry->pNext = NULL;
+ pEntry->key = key;
+ pEntry->data = data;
+
+ return;
+}
+
+
+/**Function*************************************************************
+
+ Synopsis [Finds or creates an entry with a key.]
+
+ Description [fCreate specifies whether new entries will be created.]
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+static inline int Hash_IntEntry( Hash_Int_t *p, int key, int fCreate )
+{
+ int bin;
+ Hash_Int_Entry_t *pEntry, **pLast;
+
+ // find the bin where this key would live
+ bin = (*(p->fHash))(key, p->nBins);
+
+ // search for key
+ pLast = &(p->pArray[bin]);
+ pEntry = p->pArray[bin];
+ while(pEntry) {
+ if (pEntry->key == key)
+ return pEntry->data;
+ pLast = &(pEntry->pNext);
+ pEntry = pEntry->pNext;
+ }
+
+ // this key does not currently exist
+ if (fCreate) {
+ // create a new entry and add to bin
+ p->nSize++;
+ (*pLast) = pEntry = ALLOC( Hash_Int_Entry_t, 1 );
+ pEntry->pNext = NULL;
+ pEntry->key = key;
+ pEntry->data = 0;
+ return pEntry->data;
+ }
+
+ return 0;
+}
+
+
+/**Function*************************************************************
+
+ Synopsis [Finds or creates an entry with a key and returns the pointer to it.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+static inline int* Hash_IntEntryPtr( Hash_Int_t *p, int key )
+{
+ int bin;
+ Hash_Int_Entry_t *pEntry, **pLast;
+
+ // find the bin where this key would live
+ bin = (*(p->fHash))(key, p->nBins);
+
+ // search for key
+ pLast = &(p->pArray[bin]);
+ pEntry = p->pArray[bin];
+ while(pEntry) {
+ if (pEntry->key == key)
+ return &(pEntry->data);
+ pLast = &(pEntry->pNext);
+ pEntry = pEntry->pNext;
+ }
+
+ // this key does not currently exist
+ // create a new entry and add to bin
+ p->nSize++;
+ (*pLast) = pEntry = ALLOC( Hash_Int_Entry_t, 1 );
+ pEntry->pNext = NULL;
+ pEntry->key = key;
+ pEntry->data = 0;
+
+ return &(pEntry->data);
+}
+
+/**Function*************************************************************
+
+ Synopsis [Frees the hash.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+static inline void Hash_IntFree( Hash_Int_t *p ) {
+ int bin;
+ Hash_Int_Entry_t *pEntry;
+
+ // free bins
+ for(bin = 0; bin < p->nBins; bin++) {
+ pEntry = p->pArray[bin];
+ while(pEntry) {
+ pEntry = pEntry->pNext;
+ FREE( pEntry );
+ }
+ }
+
+ // free hash
+ FREE( p->pArray );
+ FREE( p );
+}
+
+////////////////////////////////////////////////////////////////////////
+/// END OF FILE ///
+////////////////////////////////////////////////////////////////////////
+
+#endif
diff --git a/src/misc/hash/hashPtr.h b/src/misc/hash/hashPtr.h
new file mode 100644
index 00000000..15398a8a
--- /dev/null
+++ b/src/misc/hash/hashPtr.h
@@ -0,0 +1,331 @@
+/**CFile****************************************************************
+
+ FileName [hashFlt.h]
+
+ SystemName [ABC: Logic synthesis and verification system.]
+
+ PackageName [Hash maps.]
+
+ Synopsis [Hash maps.]
+
+ Author [Aaron P. Hurst]
+
+ Affiliation [UC Berkeley]
+
+ Date [Ver. 1.0. Started - May 16, 2006.]
+
+ Revision [$Id: vecInt.h,v 1.00 2005/06/20 00:00:00 ahurst Exp $]
+
+***********************************************************************/
+
+#ifndef __HASH_PTR_H__
+#define __HASH_PTR_H__
+
+////////////////////////////////////////////////////////////////////////
+/// INCLUDES ///
+////////////////////////////////////////////////////////////////////////
+
+#include <stdio.h>
+#include "extra.h"
+
+extern int Hash_DefaultHashFunc(int key, int nBins);
+
+////////////////////////////////////////////////////////////////////////
+/// PARAMETERS ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+/// BASIC TYPES ///
+////////////////////////////////////////////////////////////////////////
+
+typedef struct Hash_Ptr_t_ Hash_Ptr_t;
+typedef struct Hash_Ptr_Entry_t_ Hash_Ptr_Entry_t;
+
+struct Hash_Ptr_Entry_t_
+{
+ int key;
+ void * data;
+ struct Hash_Ptr_Entry_t_ * pNext;
+};
+
+struct Hash_Ptr_t_
+{
+ int nSize;
+ int nBins;
+ int (* fHash)(int key, int nBins);
+ Hash_Ptr_Entry_t ** pArray;
+};
+
+
+
+////////////////////////////////////////////////////////////////////////
+/// MACRO DEFINITIONS ///
+////////////////////////////////////////////////////////////////////////
+
+#define Hash_PtrForEachEntry( pHash, pEntry, bin ) \
+ for(bin=-1, pEntry=NULL; bin < pHash->nBins; (!pEntry)?(pEntry=pHash->pArray[++bin]):(pEntry=pEntry->pNext)) \
+ if (pEntry)
+
+////////////////////////////////////////////////////////////////////////
+/// FUNCTION DEFINITIONS ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+ Synopsis [Allocates a hash map with the given number of bins.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+static inline Hash_Ptr_t * Hash_PtrAlloc( int nBins )
+{
+ Hash_Ptr_t * p;
+ int i;
+ assert(nBins > 0);
+ p = ALLOC( Hash_Ptr_t, 1);
+ p->nBins = nBins;
+ p->fHash = Hash_DefaultHashFunc;
+ p->nSize = 0;
+ p->pArray = ALLOC( Hash_Ptr_Entry_t *, nBins );
+ for(i=0; i<nBins; i++)
+ p->pArray[i] = NULL;
+
+ return p;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Returns 1 if a key already exists.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+static inline int Hash_PtrExists( Hash_Ptr_t *p, int key )
+{
+ int bin;
+ Hash_Ptr_Entry_t *pEntry, **pLast;
+
+ // find the bin where this key would live
+ bin = (*(p->fHash))(key, p->nBins);
+
+ // search for key
+ pLast = &(p->pArray[bin]);
+ pEntry = p->pArray[bin];
+ while(pEntry) {
+ if (pEntry->key == key) {
+ return 1;
+ }
+ pLast = &(pEntry->pNext);
+ pEntry = pEntry->pNext;
+ }
+
+ return 0;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Finds or creates an entry with a key and writes value.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+static inline void Hash_PtrWriteEntry( Hash_Ptr_t *p, int key, void * data )
+{
+ int bin;
+ Hash_Ptr_Entry_t *pEntry, **pLast;
+
+ // find the bin where this key would live
+ bin = (*(p->fHash))(key, p->nBins);
+
+ // search for key
+ pLast = &(p->pArray[bin]);
+ pEntry = p->pArray[bin];
+ while(pEntry) {
+ if (pEntry->key == key) {
+ pEntry->data = data;
+ return;
+ }
+ pLast = &(pEntry->pNext);
+ pEntry = pEntry->pNext;
+ }
+
+ // this key does not currently exist
+ // create a new entry and add to bin
+ p->nSize++;
+ (*pLast) = pEntry = ALLOC( Hash_Ptr_Entry_t, 1 );
+ pEntry->pNext = NULL;
+ pEntry->key = key;
+ pEntry->data = data;
+
+ return;
+}
+
+
+/**Function*************************************************************
+
+ Synopsis [Finds or creates an entry with a key.]
+
+ Description [fCreate specifies whether a new entry should be created.]
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+static inline void * Hash_PtrEntry( Hash_Ptr_t *p, int key, int fCreate )
+{
+ int bin;
+ Hash_Ptr_Entry_t *pEntry, **pLast;
+
+ // find the bin where this key would live
+ bin = (*(p->fHash))(key, p->nBins);
+
+ // search for key
+ pLast = &(p->pArray[bin]);
+ pEntry = p->pArray[bin];
+ while(pEntry) {
+ if (pEntry->key == key)
+ return pEntry->data;
+ pLast = &(pEntry->pNext);
+ pEntry = pEntry->pNext;
+ }
+
+ // this key does not currently exist
+ if (fCreate) {
+ // create a new entry and add to bin
+ p->nSize++;
+ (*pLast) = pEntry = ALLOC( Hash_Ptr_Entry_t, 1 );
+ pEntry->pNext = NULL;
+ pEntry->key = key;
+ pEntry->data = NULL;
+ return pEntry->data;
+ }
+
+ return NULL;
+}
+
+
+/**Function*************************************************************
+
+ Synopsis [Finds or creates an entry with a key and returns the pointer to it.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+static inline void** Hash_PtrEntryPtr( Hash_Ptr_t *p, int key )
+{
+ int bin;
+ Hash_Ptr_Entry_t *pEntry, **pLast;
+
+ // find the bin where this key would live
+ bin = (*(p->fHash))(key, p->nBins);
+
+ // search for key
+ pLast = &(p->pArray[bin]);
+ pEntry = p->pArray[bin];
+ while(pEntry) {
+ if (pEntry->key == key)
+ return &(pEntry->data);
+ pLast = &(pEntry->pNext);
+ pEntry = pEntry->pNext;
+ }
+
+ // this key does not currently exist
+ // create a new entry and add to bin
+ p->nSize++;
+ (*pLast) = pEntry = ALLOC( Hash_Ptr_Entry_t, 1 );
+ pEntry->pNext = NULL;
+ pEntry->key = key;
+ pEntry->data = NULL;
+
+ return &(pEntry->data);
+}
+
+/**Function*************************************************************
+
+ Synopsis [Deletes an entry.]
+
+ Description [Returns data, if there was any.]
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+static inline void* Hash_PtrRemove( Hash_Ptr_t *p, int key )
+{
+ int bin;
+ void * data;
+ Hash_Ptr_Entry_t *pEntry, **pLast;
+
+ // find the bin where this key would live
+ bin = (*(p->fHash))(key, p->nBins);
+
+ // search for key
+ pLast = &(p->pArray[bin]);
+ pEntry = p->pArray[bin];
+ while(pEntry) {
+ if (pEntry->key == key) {
+ p->nSize--;
+ data = pEntry->data;
+ *pLast = pEntry->pNext;
+ return data;
+ }
+ pLast = &(pEntry->pNext);
+ pEntry = pEntry->pNext;
+ }
+
+ // could not find key
+ return NULL;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Frees the hash.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+static inline void Hash_PtrFree( Hash_Ptr_t *p ) {
+ int bin;
+ Hash_Ptr_Entry_t *pEntry;
+
+ // free bins
+ for(bin = 0; bin < p->nBins; bin++) {
+ pEntry = p->pArray[bin];
+ while(pEntry) {
+ pEntry = pEntry->pNext;
+ FREE( pEntry );
+ }
+ }
+
+ // free hash
+ FREE( p->pArray );
+ FREE( p );
+}
+
+////////////////////////////////////////////////////////////////////////
+/// END OF FILE ///
+////////////////////////////////////////////////////////////////////////
+
+#endif
diff --git a/src/misc/hash/module.make b/src/misc/hash/module.make
new file mode 100644
index 00000000..d6d908e7
--- /dev/null
+++ b/src/misc/hash/module.make
@@ -0,0 +1 @@
+SRC +=
diff --git a/src/misc/mvc/mvc.c b/src/misc/mvc/mvc.c
index 9430276c..001b1c63 100644
--- a/src/misc/mvc/mvc.c
+++ b/src/misc/mvc/mvc.c
@@ -23,7 +23,7 @@
////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////
-/// FUNCTION DEFITIONS ///
+/// FUNCTION DEFINITIONS ///
////////////////////////////////////////////////////////////////////////
/**Function*************************************************************
diff --git a/src/misc/mvc/mvc.h b/src/misc/mvc/mvc.h
index ee8c31be..70834e0a 100644
--- a/src/misc/mvc/mvc.h
+++ b/src/misc/mvc/mvc.h
@@ -24,9 +24,8 @@
////////////////////////////////////////////////////////////////////////
#include <stdio.h>
-#include "util.h"
#include "extra.h"
-//#include "vm.h"
+#include "extra.h"
////////////////////////////////////////////////////////////////////////
/// PARAMETERS ///
@@ -50,7 +49,7 @@
////////////////////////////////////////////////////////////////////////
// cube/list/cover/data
-typedef unsigned long Mvc_CubeWord_t;
+typedef unsigned int Mvc_CubeWord_t;
typedef struct MvcCubeStruct Mvc_Cube_t;
typedef struct MvcListStruct Mvc_List_t;
typedef struct MvcCoverStruct Mvc_Cover_t;
@@ -112,7 +111,7 @@ struct MvcManagerStruct
};
////////////////////////////////////////////////////////////////////////
-/// MACRO DEFITIONS ///
+/// MACRO DEFINITIONS ///
////////////////////////////////////////////////////////////////////////
// reading data from the header of the cube
@@ -566,7 +565,7 @@ struct MvcManagerStruct
#define MEM_FREE( Manager, Type, Size, Pointer ) if ( Pointer ) { free(Pointer); Pointer = NULL; }
////////////////////////////////////////////////////////////////////////
-/// FUNCTION DEFITIONS ///
+/// FUNCTION DEFINITIONS ///
////////////////////////////////////////////////////////////////////////
/*=== mvcApi.c ====================================================*/
@@ -725,9 +724,9 @@ extern Mvc_Manager_t * Mvc_ManagerAllocCube( int nWords );
extern Mvc_Manager_t * Mvc_ManagerFreeCover( Mvc_Cover_t * pCover );
extern Mvc_Manager_t * Mvc_ManagerFreeCube( Mvc_Cover_t * pCube, int nWords );
+#endif
+
////////////////////////////////////////////////////////////////////////
/// END OF FILE ///
////////////////////////////////////////////////////////////////////////
-#endif
-
diff --git a/src/misc/mvc/mvcApi.c b/src/misc/mvc/mvcApi.c
index 1f51a235..eb942f93 100644
--- a/src/misc/mvc/mvcApi.c
+++ b/src/misc/mvc/mvcApi.c
@@ -23,7 +23,7 @@
////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////
-/// FUNCTION DEFITIONS ///
+/// FUNCTION DEFINITIONS ///
////////////////////////////////////////////////////////////////////////
/**Function*************************************************************
diff --git a/src/misc/mvc/mvcCompare.c b/src/misc/mvc/mvcCompare.c
index c7999d40..9cff99cd 100644
--- a/src/misc/mvc/mvcCompare.c
+++ b/src/misc/mvc/mvcCompare.c
@@ -23,7 +23,7 @@
////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////
-/// FUNCTION DEFITIONS ///
+/// FUNCTION DEFINITIONS ///
////////////////////////////////////////////////////////////////////////
/**Function*************************************************************
diff --git a/src/misc/mvc/mvcContain.c b/src/misc/mvc/mvcContain.c
index 37b933b8..a9eae06e 100644
--- a/src/misc/mvc/mvcContain.c
+++ b/src/misc/mvc/mvcContain.c
@@ -26,7 +26,7 @@ static void Mvc_CoverRemoveDuplicates( Mvc_Cover_t * pCover );
static void Mvc_CoverRemoveContained( Mvc_Cover_t * pCover );
////////////////////////////////////////////////////////////////////////
-/// FUNCTION DEFITIONS ///
+/// FUNCTION DEFINITIONS ///
////////////////////////////////////////////////////////////////////////
diff --git a/src/misc/mvc/mvcCover.c b/src/misc/mvc/mvcCover.c
index bd9c4412..d8584446 100644
--- a/src/misc/mvc/mvcCover.c
+++ b/src/misc/mvc/mvcCover.c
@@ -23,7 +23,7 @@
////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////
-/// FUNCTION DEFITIONS ///
+/// FUNCTION DEFINITIONS ///
////////////////////////////////////////////////////////////////////////
/**Function*************************************************************
diff --git a/src/misc/mvc/mvcCube.c b/src/misc/mvc/mvcCube.c
index d02fa270..e157879f 100644
--- a/src/misc/mvc/mvcCube.c
+++ b/src/misc/mvc/mvcCube.c
@@ -23,7 +23,7 @@
////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////
-/// FUNCTION DEFITIONS ///
+/// FUNCTION DEFINITIONS ///
////////////////////////////////////////////////////////////////////////
/**Function*************************************************************
diff --git a/src/misc/mvc/mvcDivide.c b/src/misc/mvc/mvcDivide.c
index 6aa3d58d..03643dcf 100644
--- a/src/misc/mvc/mvcDivide.c
+++ b/src/misc/mvc/mvcDivide.c
@@ -27,7 +27,7 @@ static void Mvc_CoverVerifyDivision( Mvc_Cover_t * pCover, Mvc_Cover_t * pDiv, M
int s_fVerbose = 0;
////////////////////////////////////////////////////////////////////////
-/// FUNCTION DEFITIONS ///
+/// FUNCTION DEFINITIONS ///
////////////////////////////////////////////////////////////////////////
/**Function*************************************************************
diff --git a/src/misc/mvc/mvcDivisor.c b/src/misc/mvc/mvcDivisor.c
index e92c3a65..ecdea75b 100644
--- a/src/misc/mvc/mvcDivisor.c
+++ b/src/misc/mvc/mvcDivisor.c
@@ -25,7 +25,7 @@
static void Mvc_CoverDivisorZeroKernel( Mvc_Cover_t * pCover );
////////////////////////////////////////////////////////////////////////
-/// FUNCTION DEFITIONS ///
+/// FUNCTION DEFINITIONS ///
////////////////////////////////////////////////////////////////////////
/**Function*************************************************************
diff --git a/src/misc/mvc/mvcList.c b/src/misc/mvc/mvcList.c
index 678ae9fd..8a82f911 100644
--- a/src/misc/mvc/mvcList.c
+++ b/src/misc/mvc/mvcList.c
@@ -23,7 +23,7 @@
////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////
-/// FUNCTION DEFITIONS ///
+/// FUNCTION DEFINITIONS ///
////////////////////////////////////////////////////////////////////////
/**Function*************************************************************
diff --git a/src/misc/mvc/mvcLits.c b/src/misc/mvc/mvcLits.c
index 98211719..910158e9 100644
--- a/src/misc/mvc/mvcLits.c
+++ b/src/misc/mvc/mvcLits.c
@@ -23,7 +23,7 @@
////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////
-/// FUNCTION DEFITIONS ///
+/// FUNCTION DEFINITIONS ///
////////////////////////////////////////////////////////////////////////
/**Function*************************************************************
diff --git a/src/misc/mvc/mvcMan.c b/src/misc/mvc/mvcMan.c
index f2943e0c..7b4ef2af 100644
--- a/src/misc/mvc/mvcMan.c
+++ b/src/misc/mvc/mvcMan.c
@@ -24,7 +24,7 @@
////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////
-/// FUNCTION DEFITIONS ///
+/// FUNCTION DEFINITIONS ///
////////////////////////////////////////////////////////////////////////
/**Function*************************************************************
@@ -63,10 +63,10 @@ Mvc_Manager_t * Mvc_ManagerStart()
***********************************************************************/
void Mvc_ManagerFree( Mvc_Manager_t * p )
{
- Extra_MmFixedStop( p->pMan1, 0 );
- Extra_MmFixedStop( p->pMan2, 0 );
- Extra_MmFixedStop( p->pMan4, 0 );
- Extra_MmFixedStop( p->pManC, 0 );
+ Extra_MmFixedStop( p->pMan1 );
+ Extra_MmFixedStop( p->pMan2 );
+ Extra_MmFixedStop( p->pMan4 );
+ Extra_MmFixedStop( p->pManC );
free( p );
}
diff --git a/src/misc/mvc/mvcOpAlg.c b/src/misc/mvc/mvcOpAlg.c
index befccb70..65c02fa5 100644
--- a/src/misc/mvc/mvcOpAlg.c
+++ b/src/misc/mvc/mvcOpAlg.c
@@ -23,7 +23,7 @@
////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////
-/// FUNCTION DEFITIONS ///
+/// FUNCTION DEFINITIONS ///
////////////////////////////////////////////////////////////////////////
/**Function*************************************************************
diff --git a/src/misc/mvc/mvcOpBool.c b/src/misc/mvc/mvcOpBool.c
index 57b1a968..0b34f1de 100644
--- a/src/misc/mvc/mvcOpBool.c
+++ b/src/misc/mvc/mvcOpBool.c
@@ -23,7 +23,7 @@
////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////
-/// FUNCTION DEFITIONS ///
+/// FUNCTION DEFINITIONS ///
////////////////////////////////////////////////////////////////////////
/**Function*************************************************************
diff --git a/src/misc/mvc/mvcPrint.c b/src/misc/mvc/mvcPrint.c
index 3a31235b..52ac76b3 100644
--- a/src/misc/mvc/mvcPrint.c
+++ b/src/misc/mvc/mvcPrint.c
@@ -27,7 +27,7 @@
static void Mvc_CubePrintBinary( Mvc_Cover_t * pCover, Mvc_Cube_t * pCube );
////////////////////////////////////////////////////////////////////////
-/// FUNCTION DEFITIONS ///
+/// FUNCTION DEFINITIONS ///
////////////////////////////////////////////////////////////////////////
/**Function*************************************************************
diff --git a/src/misc/mvc/mvcSort.c b/src/misc/mvc/mvcSort.c
index 1126b22a..3c975cb3 100644
--- a/src/misc/mvc/mvcSort.c
+++ b/src/misc/mvc/mvcSort.c
@@ -27,7 +27,7 @@ Mvc_Cube_t * Mvc_CoverSort_rec( Mvc_Cube_t * pList, int nItems, Mvc_Cube_t * pMa
Mvc_Cube_t * Mvc_CoverSortMerge( Mvc_Cube_t * pList1, Mvc_Cube_t * pList2, Mvc_Cube_t * pMask, int (* pCompareFunc)(Mvc_Cube_t *, Mvc_Cube_t *, Mvc_Cube_t *) );
////////////////////////////////////////////////////////////////////////
-/// FuNCTION DEFITIONS ///
+/// FuNCTION DEFINITIONS ///
////////////////////////////////////////////////////////////////////////
/**Function*************************************************************
diff --git a/src/misc/mvc/mvcUtils.c b/src/misc/mvc/mvcUtils.c
index 3fb57276..4b13b23d 100644
--- a/src/misc/mvc/mvcUtils.c
+++ b/src/misc/mvc/mvcUtils.c
@@ -38,7 +38,7 @@ static void Mvc_CoverCopyColumn( Mvc_Cover_t * pCoverOld, Mvc_Cover_t * pCoverNe
////////////////////////////////////////////////////////////////////////
-/// FUNCTION DEFITIONS ///
+/// FUNCTION DEFINITIONS ///
////////////////////////////////////////////////////////////////////////
/**Function*************************************************************
diff --git a/src/misc/nm/module.make b/src/misc/nm/module.make
new file mode 100644
index 00000000..2a3820c7
--- /dev/null
+++ b/src/misc/nm/module.make
@@ -0,0 +1,2 @@
+SRC += src/misc/nm/nmApi.c \
+ src/misc/nm/nmTable.c
diff --git a/src/misc/nm/nm.h b/src/misc/nm/nm.h
new file mode 100644
index 00000000..c6344bbf
--- /dev/null
+++ b/src/misc/nm/nm.h
@@ -0,0 +1,92 @@
+/**CFilextern e****************************************************************
+
+ FileName [nm.h]
+
+ SystemName [ABC: Logic synthesis and verification system.]
+
+ PackageName [Name manager.]
+
+ Synopsis [External declarations.]
+
+ Author [Alan Mishchenko]
+
+ Affiliation [UC Berkeley]
+
+ Date [Ver. 1.0. Started - June 20, 2005.]
+
+ Revision [$Id: nm.h,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#ifndef __NM_H__
+#define __NM_H__
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*
+ This manager is designed to store ID-to-name and name-to-ID mapping
+ for Boolean networks and And-Inverter Graphs.
+
+ In a netlist, net names are unique. In this case, there is a one-to-one
+ mapping between IDs and names.
+
+ In a logic network, which do not have nets, several objects may have
+ the same name. For example, a latch output and a primary output.
+ Another example, a primary input and an input to a black box.
+ In this case, for each ID on an object there is only one name,
+ but for each name may be several IDs of objects having this name.
+
+ The name manager maps ID-to-name uniquely but it allows one name to
+ be mapped into several IDs. When a query to find an ID of the object
+ by its name is submitted, it is possible to specify the object type,
+ which will help select one of several IDs. If the type is -1, and
+ there is more than one object with the given name, any object with
+ the given name is returned.
+*/
+
+////////////////////////////////////////////////////////////////////////
+/// INCLUDES ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+/// PARAMETERS ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+/// BASIC TYPES ///
+////////////////////////////////////////////////////////////////////////
+
+typedef struct Nm_Man_t_ Nm_Man_t;
+
+////////////////////////////////////////////////////////////////////////
+/// MACRO DEFINITIONS ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+/// FUNCTION DECLARATIONS ///
+////////////////////////////////////////////////////////////////////////
+
+/*=== nmApi.c ==========================================================*/
+extern Nm_Man_t * Nm_ManCreate( int nSize );
+extern void Nm_ManFree( Nm_Man_t * p );
+extern int Nm_ManNumEntries( Nm_Man_t * p );
+extern char * Nm_ManStoreIdName( Nm_Man_t * p, int ObjId, int Type, char * pName, char * pSuffix );
+extern void Nm_ManDeleteIdName( Nm_Man_t * p, int ObjId );
+extern char * Nm_ManCreateUniqueName( Nm_Man_t * p, int ObjId );
+extern char * Nm_ManFindNameById( Nm_Man_t * p, int ObjId );
+extern int Nm_ManFindIdByName( Nm_Man_t * p, char * pName, int Type );
+extern int Nm_ManFindIdByNameTwoTypes( Nm_Man_t * p, char * pName, int Type1, int Type2 );
+extern Vec_Int_t * Nm_ManReturnNameIds( Nm_Man_t * p );
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
+
+////////////////////////////////////////////////////////////////////////
+/// END OF FILE ///
+////////////////////////////////////////////////////////////////////////
+
diff --git a/src/misc/nm/nmApi.c b/src/misc/nm/nmApi.c
new file mode 100644
index 00000000..9165922f
--- /dev/null
+++ b/src/misc/nm/nmApi.c
@@ -0,0 +1,272 @@
+/**CFile****************************************************************
+
+ FileName [nmApi.c]
+
+ SystemName [ABC: Logic synthesis and verification system.]
+
+ PackageName [Name manager.]
+
+ Synopsis [APIs of the name manager.]
+
+ Author [Alan Mishchenko]
+
+ Affiliation [UC Berkeley]
+
+ Date [Ver. 1.0. Started - June 20, 2005.]
+
+ Revision [$Id: nmApi.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "nmInt.h"
+
+////////////////////////////////////////////////////////////////////////
+/// DECLARATIONS ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+/// FUNCTION DEFINITIONS ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+ Synopsis [Allocates the name manager.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Nm_Man_t * Nm_ManCreate( int nSize )
+{
+ Nm_Man_t * p;
+ // allocate the table
+ p = ALLOC( Nm_Man_t, 1 );
+ memset( p, 0, sizeof(Nm_Man_t) );
+ // set the parameters
+ p->nSizeFactor = 2; // determined the limit on the grow of data before the table resizes
+ p->nGrowthFactor = 3; // determined how much the table grows after resizing
+ // allocate and clean the bins
+ p->nBins = Cudd_PrimeNm(nSize);
+ p->pBinsI2N = ALLOC( Nm_Entry_t *, p->nBins );
+ p->pBinsN2I = ALLOC( Nm_Entry_t *, p->nBins );
+ memset( p->pBinsI2N, 0, sizeof(Nm_Entry_t *) * p->nBins );
+ memset( p->pBinsN2I, 0, sizeof(Nm_Entry_t *) * p->nBins );
+ // start the memory manager
+ p->pMem = Extra_MmFlexStart();
+ return p;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Deallocates the name manager.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Nm_ManFree( Nm_Man_t * p )
+{
+ Extra_MmFlexStop( p->pMem );
+ FREE( p->pBinsI2N );
+ FREE( p->pBinsN2I );
+ FREE( p );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Returns the number of objects with names.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Nm_ManNumEntries( Nm_Man_t * p )
+{
+ return p->nEntries;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Creates a new entry in the name manager.]
+
+ Description [Returns 1 if the entry with the given object ID
+ already exists in the name manager.]
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+char * Nm_ManStoreIdName( Nm_Man_t * p, int ObjId, int Type, char * pName, char * pSuffix )
+{
+ Nm_Entry_t * pEntry;
+ int RetValue, nEntrySize;
+ // check if the object with this ID is already stored
+ if ( pEntry = Nm_ManTableLookupId(p, ObjId) )
+ {
+ printf( "Nm_ManStoreIdName(): Entry with the same ID already exists.\n" );
+ return NULL;
+ }
+ // create a new entry
+ nEntrySize = sizeof(Nm_Entry_t) + strlen(pName) + (pSuffix?strlen(pSuffix):0) + 1;
+ nEntrySize = (nEntrySize / 4 + ((nEntrySize % 4) > 0)) * 4;
+ pEntry = (Nm_Entry_t *)Extra_MmFlexEntryFetch( p->pMem, nEntrySize );
+ pEntry->pNextI2N = pEntry->pNextN2I = pEntry->pNameSake = NULL;
+ pEntry->ObjId = ObjId;
+ pEntry->Type = Type;
+ sprintf( pEntry->Name, "%s%s", pName, pSuffix? pSuffix : "" );
+ // add the entry to the hash table
+ RetValue = Nm_ManTableAdd( p, pEntry );
+ assert( RetValue == 1 );
+ return pEntry->Name;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Creates a new entry in the name manager.]
+
+ Description [Returns 1 if the entry with the given object ID
+ already exists in the name manager.]
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Nm_ManDeleteIdName( Nm_Man_t * p, int ObjId )
+{
+ Nm_Entry_t * pEntry;
+ pEntry = Nm_ManTableLookupId(p, ObjId);
+ if ( pEntry == NULL )
+ {
+ printf( "Nm_ManDeleteIdName(): This entry is not in the table.\n" );
+ return;
+ }
+ // remove entry from the table
+ Nm_ManTableDelete( p, ObjId );
+}
+
+
+/**Function*************************************************************
+
+ Synopsis [Finds a unique name for the node.]
+
+ Description [If the name exists, tries appending numbers to it until
+ it becomes unique. The name is not added to the table.]
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+char * Nm_ManCreateUniqueName( Nm_Man_t * p, int ObjId )
+{
+ static char NameStr[1000];
+ Nm_Entry_t * pEntry;
+ int i;
+ if ( pEntry = Nm_ManTableLookupId(p, ObjId) )
+ return pEntry->Name;
+ sprintf( NameStr, "n%d", ObjId );
+ for ( i = 1; Nm_ManTableLookupName(p, NameStr, -1); i++ )
+ sprintf( NameStr, "n%d_%d", ObjId, i );
+ return NameStr;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Returns name of the object if the ID is known.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+char * Nm_ManFindNameById( Nm_Man_t * p, int ObjId )
+{
+ Nm_Entry_t * pEntry;
+ if ( pEntry = Nm_ManTableLookupId(p, ObjId) )
+ return pEntry->Name;
+ return NULL;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Returns ID of the object if its name is known.]
+
+ Description [This procedure may return two IDs because POs and latches
+ may have the same name (the only allowed case of name duplication).]
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Nm_ManFindIdByName( Nm_Man_t * p, char * pName, int Type )
+{
+ Nm_Entry_t * pEntry;
+ if ( pEntry = Nm_ManTableLookupName(p, pName, Type) )
+ return pEntry->ObjId;
+ return -1;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Returns ID of the object if its name is known.]
+
+ Description [This procedure may return two IDs because POs and latches
+ may have the same name (the only allowed case of name duplication).]
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Nm_ManFindIdByNameTwoTypes( Nm_Man_t * p, char * pName, int Type1, int Type2 )
+{
+ int iNodeId;
+ iNodeId = Nm_ManFindIdByName( p, pName, Type1 );
+ if ( iNodeId == -1 )
+ iNodeId = Nm_ManFindIdByName( p, pName, Type2 );
+ if ( iNodeId == -1 )
+ return -1;
+ return iNodeId;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Return the IDs of objects with names.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Vec_Int_t * Nm_ManReturnNameIds( Nm_Man_t * p )
+{
+ Vec_Int_t * vNameIds;
+ int i;
+ vNameIds = Vec_IntAlloc( p->nEntries );
+ for ( i = 0; i < p->nBins; i++ )
+ if ( p->pBinsI2N[i] )
+ Vec_IntPush( vNameIds, p->pBinsI2N[i]->ObjId );
+ return vNameIds;
+}
+
+////////////////////////////////////////////////////////////////////////
+/// END OF FILE ///
+////////////////////////////////////////////////////////////////////////
+
+
diff --git a/src/misc/nm/nmInt.h b/src/misc/nm/nmInt.h
new file mode 100644
index 00000000..028316e1
--- /dev/null
+++ b/src/misc/nm/nmInt.h
@@ -0,0 +1,91 @@
+/**CFile****************************************************************
+
+ FileName [nmInt.h]
+
+ SystemName [ABC: Logic synthesis and verification system.]
+
+ PackageName [Name manager.]
+
+ Synopsis [Internal declarations.]
+
+ Author [Alan Mishchenko]
+
+ Affiliation [UC Berkeley]
+
+ Date [Ver. 1.0. Started - June 20, 2005.]
+
+ Revision [$Id: nmInt.h,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#ifndef __NM_INT_H__
+#define __NM_INT_H__
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+////////////////////////////////////////////////////////////////////////
+/// INCLUDES ///
+////////////////////////////////////////////////////////////////////////
+
+#include "extra.h"
+#include "vec.h"
+#include "nm.h"
+
+////////////////////////////////////////////////////////////////////////
+/// PARAMETERS ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+/// BASIC TYPES ///
+////////////////////////////////////////////////////////////////////////
+
+typedef struct Nm_Entry_t_ Nm_Entry_t;
+struct Nm_Entry_t_
+{
+ unsigned Type : 4; // object type
+ unsigned ObjId : 28; // object ID
+ Nm_Entry_t * pNextI2N; // the next entry in the ID hash table
+ Nm_Entry_t * pNextN2I; // the next entry in the name hash table
+ Nm_Entry_t * pNameSake; // the next entry with the same name
+ char Name[0]; // name of the object
+};
+
+struct Nm_Man_t_
+{
+ Nm_Entry_t ** pBinsI2N; // mapping IDs into names
+ Nm_Entry_t ** pBinsN2I; // mapping names into IDs
+ int nBins; // the number of bins in tables
+ int nEntries; // the number of entries
+ int nSizeFactor; // determined how much larger the table should be
+ int nGrowthFactor; // determined how much the table grows after resizing
+ Extra_MmFlex_t * pMem; // memory manager for entries (and names)
+};
+
+////////////////////////////////////////////////////////////////////////
+/// MACRO DEFINITIONS ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+/// FUNCTION DECLARATIONS ///
+////////////////////////////////////////////////////////////////////////
+
+/*=== nmTable.c ==========================================================*/
+extern int Nm_ManTableAdd( Nm_Man_t * p, Nm_Entry_t * pEntry );
+extern int Nm_ManTableDelete( Nm_Man_t * p, int ObjId );
+extern Nm_Entry_t * Nm_ManTableLookupId( Nm_Man_t * p, int ObjId );
+extern Nm_Entry_t * Nm_ManTableLookupName( Nm_Man_t * p, char * pName, int Type );
+extern unsigned int Cudd_PrimeNm( unsigned int p );
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
+
+////////////////////////////////////////////////////////////////////////
+/// END OF FILE ///
+////////////////////////////////////////////////////////////////////////
+
+
diff --git a/src/misc/nm/nmTable.c b/src/misc/nm/nmTable.c
new file mode 100644
index 00000000..f97a2f0b
--- /dev/null
+++ b/src/misc/nm/nmTable.c
@@ -0,0 +1,340 @@
+/**CFile****************************************************************
+
+ FileName [nmTable.c]
+
+ SystemName [ABC: Logic synthesis and verification system.]
+
+ PackageName [Name manager.]
+
+ Synopsis [Hash table for the name manager.]
+
+ Author [Alan Mishchenko]
+
+ Affiliation [UC Berkeley]
+
+ Date [Ver. 1.0. Started - June 20, 2005.]
+
+ Revision [$Id: nmTable.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "nmInt.h"
+
+////////////////////////////////////////////////////////////////////////
+/// DECLARATIONS ///
+////////////////////////////////////////////////////////////////////////
+
+// hashing for integers
+static unsigned Nm_HashNumber( int Num, int TableSize )
+{
+ unsigned Key = 0;
+ Key ^= ( Num & 0xFF) * 7937;
+ Key ^= ((Num >> 8) & 0xFF) * 2971;
+ Key ^= ((Num >> 16) & 0xFF) * 911;
+ Key ^= ((Num >> 24) & 0xFF) * 353;
+ return Key % TableSize;
+}
+
+// hashing for strings
+static unsigned Nm_HashString( char * pName, int TableSize )
+{
+ static int s_Primes[10] = {
+ 1291, 1699, 2357, 4177, 5147,
+ 5647, 6343, 7103, 7873, 8147
+ };
+ unsigned i, Key = 0;
+ for ( i = 0; pName[i] != '\0'; i++ )
+ Key ^= s_Primes[i%10]*pName[i]*pName[i];
+ return Key % TableSize;
+}
+
+static void Nm_ManResize( Nm_Man_t * p );
+
+////////////////////////////////////////////////////////////////////////
+/// FUNCTION DEFINITIONS ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+ Synopsis [Adds an entry to two hash tables.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Nm_ManTableAdd( Nm_Man_t * p, Nm_Entry_t * pEntry )
+{
+ Nm_Entry_t ** ppSpot, * pOther;
+ // resize the tables if needed
+ if ( p->nEntries > p->nBins * p->nSizeFactor )
+ Nm_ManResize( p );
+ // add the entry to the table Id->Name
+ assert( Nm_ManTableLookupId(p, pEntry->ObjId) == NULL );
+ ppSpot = p->pBinsI2N + Nm_HashNumber(pEntry->ObjId, p->nBins);
+ pEntry->pNextI2N = *ppSpot;
+ *ppSpot = pEntry;
+ // check if an entry with the same name already exists
+ if ( pOther = Nm_ManTableLookupName(p, pEntry->Name, -1) )
+ {
+ // entry with the same name already exists - add it to the ring
+ pEntry->pNameSake = pOther->pNameSake? pOther->pNameSake : pOther;
+ pOther->pNameSake = pEntry;
+ }
+ else
+ {
+ // entry with the same name does not exist - add it to the table
+ ppSpot = p->pBinsN2I + Nm_HashString(pEntry->Name, p->nBins);
+ pEntry->pNextN2I = *ppSpot;
+ *ppSpot = pEntry;
+ }
+ // report successfully added entry
+ p->nEntries++;
+ return 1;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Deletes the entry from two hash tables.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Nm_ManTableDelete( Nm_Man_t * p, int ObjId )
+{
+ Nm_Entry_t ** ppSpot, * pEntry, * pPrev;
+ int fRemoved;
+ p->nEntries--;
+ // remove the entry from the table Id->Name
+ assert( Nm_ManTableLookupId(p, ObjId) != NULL );
+ ppSpot = p->pBinsI2N + Nm_HashNumber(ObjId, p->nBins);
+ while ( (*ppSpot)->ObjId != (unsigned)ObjId )
+ ppSpot = &(*ppSpot)->pNextI2N;
+ pEntry = *ppSpot;
+ *ppSpot = (*ppSpot)->pNextI2N;
+ // remove the entry from the table Name->Id
+ ppSpot = p->pBinsN2I + Nm_HashString(pEntry->Name, p->nBins);
+ while ( *ppSpot && *ppSpot != pEntry )
+ ppSpot = &(*ppSpot)->pNextN2I;
+ // remember if we found this one in the list
+ fRemoved = (*ppSpot != NULL);
+ if ( *ppSpot )
+ {
+ assert( *ppSpot == pEntry );
+ *ppSpot = (*ppSpot)->pNextN2I;
+ }
+ // quit if this entry has no namesakes
+ if ( pEntry->pNameSake == NULL )
+ {
+ assert( fRemoved );
+ return 1;
+ }
+ // remove entry from the ring of namesakes
+ assert( pEntry->pNameSake != pEntry );
+ for ( pPrev = pEntry; pPrev->pNameSake != pEntry; pPrev = pPrev->pNameSake );
+ assert( !strcmp(pPrev->Name, pEntry->Name) );
+ assert( pPrev->pNameSake == pEntry );
+ if ( pEntry->pNameSake == pPrev ) // two entries in the ring
+ pPrev->pNameSake = NULL;
+ else
+ pPrev->pNameSake = pEntry->pNameSake;
+ // reinsert the ring back if we removed its connection with the list in the table
+ if ( fRemoved )
+ {
+ assert( pPrev->pNextN2I == NULL );
+ pPrev->pNextN2I = *ppSpot;
+ *ppSpot = pPrev;
+ }
+ return 1;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Looks up the entry by ID.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Nm_Entry_t * Nm_ManTableLookupId( Nm_Man_t * p, int ObjId )
+{
+ Nm_Entry_t * pEntry;
+ for ( pEntry = p->pBinsI2N[ Nm_HashNumber(ObjId, p->nBins) ]; pEntry; pEntry = pEntry->pNextI2N )
+ if ( pEntry->ObjId == (unsigned)ObjId )
+ return pEntry;
+ return NULL;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Looks up the entry by name and type.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Nm_Entry_t * Nm_ManTableLookupName( Nm_Man_t * p, char * pName, int Type )
+{
+ Nm_Entry_t * pEntry, * pTemp;
+ int Counter = 0;
+ for ( pEntry = p->pBinsN2I[ Nm_HashString(pName, p->nBins) ]; pEntry; pEntry = pEntry->pNextN2I )
+ {
+ // check the entry itself
+ if ( !strcmp(pEntry->Name, pName) && (Type == -1 || pEntry->Type == (unsigned)Type) )
+ return pEntry;
+ // if there is no namesakes, continue
+ if ( pEntry->pNameSake == NULL )
+ continue;
+ // check the list of namesakes
+ for ( pTemp = pEntry->pNameSake; pTemp != pEntry; pTemp = pTemp->pNameSake )
+ if ( !strcmp(pTemp->Name, pName) && (Type == -1 || pTemp->Type == (unsigned)Type) )
+ return pTemp;
+ }
+ return NULL;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Profiles hash tables.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Nm_ManProfile( Nm_Man_t * p )
+{
+ Nm_Entry_t * pEntry;
+ int Counter, e;
+ printf( "I2N table: " );
+ for ( e = 0; e < p->nBins; e++ )
+ {
+ Counter = 0;
+ for ( pEntry = p->pBinsI2N[e]; pEntry; pEntry = pEntry->pNextI2N )
+ Counter++;
+ printf( "%d ", Counter );
+ }
+ printf( "\n" );
+ printf( "N2I table: " );
+ for ( e = 0; e < p->nBins; e++ )
+ {
+ Counter = 0;
+ for ( pEntry = p->pBinsN2I[e]; pEntry; pEntry = pEntry->pNextN2I )
+ Counter++;
+ printf( "%d ", Counter );
+ }
+ printf( "\n" );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Resizes the table.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Nm_ManResize( Nm_Man_t * p )
+{
+ Nm_Entry_t ** pBinsNewI2N, ** pBinsNewN2I, * pEntry, * pEntry2, ** ppSpot;
+ int nBinsNew, Counter, e, clk;
+
+clk = clock();
+ // get the new table size
+ nBinsNew = Cudd_PrimeCopy( p->nGrowthFactor * p->nBins );
+ // allocate a new array
+ pBinsNewI2N = ALLOC( Nm_Entry_t *, nBinsNew );
+ pBinsNewN2I = ALLOC( Nm_Entry_t *, nBinsNew );
+ memset( pBinsNewI2N, 0, sizeof(Nm_Entry_t *) * nBinsNew );
+ memset( pBinsNewN2I, 0, sizeof(Nm_Entry_t *) * nBinsNew );
+ // rehash entries in Id->Name table
+ Counter = 0;
+ for ( e = 0; e < p->nBins; e++ )
+ for ( pEntry = p->pBinsI2N[e], pEntry2 = pEntry? pEntry->pNextI2N : NULL;
+ pEntry; pEntry = pEntry2, pEntry2 = pEntry? pEntry->pNextI2N : NULL )
+ {
+ ppSpot = pBinsNewI2N + Nm_HashNumber(pEntry->ObjId, nBinsNew);
+ pEntry->pNextI2N = *ppSpot;
+ *ppSpot = pEntry;
+ Counter++;
+ }
+ // rehash entries in Name->Id table
+ for ( e = 0; e < p->nBins; e++ )
+ for ( pEntry = p->pBinsN2I[e], pEntry2 = pEntry? pEntry->pNextN2I : NULL;
+ pEntry; pEntry = pEntry2, pEntry2 = pEntry? pEntry->pNextN2I : NULL )
+ {
+ ppSpot = pBinsNewN2I + Nm_HashString(pEntry->Name, nBinsNew);
+ pEntry->pNextN2I = *ppSpot;
+ *ppSpot = pEntry;
+ }
+ assert( Counter == p->nEntries );
+// printf( "Increasing the structural table size from %6d to %6d. ", p->nBins, nBinsNew );
+// PRT( "Time", clock() - clk );
+ // replace the table and the parameters
+ free( p->pBinsI2N );
+ free( p->pBinsN2I );
+ p->pBinsI2N = pBinsNewI2N;
+ p->pBinsN2I = pBinsNewN2I;
+ p->nBins = nBinsNew;
+// Nm_ManProfile( p );
+}
+
+
+/**Function*************************************************************
+
+ Synopsis [Returns the smallest prime larger than the number.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+unsigned int Cudd_PrimeNm( unsigned int p)
+{
+ int i,pn;
+
+ p--;
+ do {
+ p++;
+ if (p&1) {
+ pn = 1;
+ i = 3;
+ while ((unsigned) (i * i) <= p) {
+ if (p % i == 0) {
+ pn = 0;
+ break;
+ }
+ i += 2;
+ }
+ } else {
+ pn = 0;
+ }
+ } while (!pn);
+ return(p);
+
+} /* end of Cudd_Prime */
+
+////////////////////////////////////////////////////////////////////////
+/// END OF FILE ///
+////////////////////////////////////////////////////////////////////////
+
+
diff --git a/src/misc/st/st.c b/src/misc/st/st.c
index 13e9bd6a..872fe51b 100644
--- a/src/misc/st/st.c
+++ b/src/misc/st/st.c
@@ -8,12 +8,31 @@
*
*/
#include <stdio.h>
-#include "util.h"
+#include <stdlib.h>
#include "st.h"
+#ifndef ABS
+# define ABS(a) ((a) < 0 ? -(a) : (a))
+#endif
+
+#ifndef ALLOC
+#define ALLOC(type, num) ((type *) malloc(sizeof(type) * (num)))
+#endif
+
+#ifndef FREE
+#define FREE(obj) ((obj) ? (free((char *) (obj)), (obj) = 0) : 0)
+#endif
+
+#ifndef REALLOC
+#define REALLOC(type, obj, num) \
+ ((obj) ? ((type *) realloc((char *)(obj), sizeof(type) * (num))) : \
+ ((type *) malloc(sizeof(type) * (num))))
+#endif
+
#define ST_NUMCMP(x,y) ((x) != (y))
#define ST_NUMHASH(x,size) (ABS((long)x)%(size))
-#define ST_PTRHASH(x,size) ((int)((unsigned long)(x)>>2)%size)
+//#define ST_PTRHASH(x,size) ((int)((unsigned long)(x)>>2)%size) // 64-bit bug fix 9/17/2007
+#define ST_PTRHASH(x,size) ((int)(((unsigned long)(x)>>2)%size))
#define EQUAL(func, x, y) \
((((func) == st_numcmp) || ((func) == st_ptrcmp)) ?\
(ST_NUMCMP((x),(y)) == 0) : ((*func)((x), (y)) == 0))
@@ -41,8 +60,8 @@ int reorder_flag;
st_table *new;
new = ALLOC(st_table, 1);
- if (new == NIL(st_table)) {
- return NIL(st_table);
+ if (new == NULL) {
+ return NULL;
}
new->compare = compare;
new->hash = hash;
@@ -55,9 +74,9 @@ int reorder_flag;
}
new->num_bins = size;
new->bins = ALLOC(st_table_entry *, size);
- if (new->bins == NIL(st_table_entry *)) {
+ if (new->bins == NULL) {
FREE(new);
- return NIL(st_table);
+ return NULL;
}
for(i = 0; i < size; i++) {
new->bins[i] = 0;
@@ -85,7 +104,7 @@ st_table *table;
for(i = 0; i < table->num_bins ; i++) {
ptr = table->bins[i];
- while (ptr != NIL(st_table_entry)) {
+ while (ptr != NULL) {
next = ptr->next;
FREE(ptr);
ptr = next;
@@ -96,7 +115,7 @@ st_table *table;
}
#define PTR_NOT_EQUAL(table, ptr, user_key)\
-(ptr != NIL(st_table_entry) && !EQUAL(table->compare, user_key, (ptr)->key))
+(ptr != NULL && !EQUAL(table->compare, user_key, (ptr)->key))
#define FIND_ENTRY(table, hash_val, key, ptr, last) \
(last) = &(table)->bins[hash_val];\
@@ -104,7 +123,7 @@ st_table *table;
while (PTR_NOT_EQUAL((table), (ptr), (key))) {\
(last) = &(ptr)->next; (ptr) = *(last);\
}\
- if ((ptr) != NIL(st_table_entry) && (table)->reorder_flag) {\
+ if ((ptr) != NULL && (table)->reorder_flag) {\
*(last) = (ptr)->next;\
(ptr)->next = (table)->bins[hash_val];\
(table)->bins[hash_val] = (ptr);\
@@ -123,10 +142,10 @@ char **value;
FIND_ENTRY(table, hash_val, key, ptr, last);
- if (ptr == NIL(st_table_entry)) {
+ if (ptr == NULL) {
return 0;
} else {
- if (value != NIL(char *)) {
+ if (value != NULL) {
*value = ptr->record;
}
return 1;
@@ -146,10 +165,10 @@ int *value;
FIND_ENTRY(table, hash_val, key, ptr, last);
- if (ptr == NIL(st_table_entry)) {
+ if (ptr == NULL) {
return 0;
} else {
- if (value != NIL(int)) {
+ if (value != 0) {
*value = (long) ptr->record;
}
return 1;
@@ -187,7 +206,7 @@ char *value;
FIND_ENTRY(table, hash_val, key, ptr, last);
- if (ptr == NIL(st_table_entry)) {
+ if (ptr == NULL) {
if (table->num_entries/table->num_bins >= table->max_density) {
if (rehash(table) == ST_OUT_OF_MEM) {
return ST_OUT_OF_MEM;
@@ -195,7 +214,7 @@ char *value;
hash_val = do_hash(key, table);
}
new = ALLOC(st_table_entry, 1);
- if (new == NIL(st_table_entry)) {
+ if (new == NULL) {
return ST_OUT_OF_MEM;
}
new->key = key;
@@ -227,7 +246,7 @@ char *value;
}
hash_val = do_hash(key, table);
new = ALLOC(st_table_entry, 1);
- if (new == NIL(st_table_entry)) {
+ if (new == NULL) {
return ST_OUT_OF_MEM;
}
new->key = key;
@@ -251,7 +270,7 @@ char ***slot;
FIND_ENTRY(table, hash_val, key, ptr, last);
- if (ptr == NIL(st_table_entry)) {
+ if (ptr == NULL) {
if (table->num_entries / table->num_bins >= table->max_density) {
if (rehash(table) == ST_OUT_OF_MEM) {
return ST_OUT_OF_MEM;
@@ -259,7 +278,7 @@ char ***slot;
hash_val = do_hash(key, table);
}
new = ALLOC(st_table_entry, 1);
- if (new == NIL(st_table_entry)) {
+ if (new == NULL) {
return ST_OUT_OF_MEM;
}
new->key = key;
@@ -267,10 +286,10 @@ char ***slot;
new->next = table->bins[hash_val];
table->bins[hash_val] = new;
table->num_entries++;
- if (slot != NIL(char **)) *slot = &new->record;
+ if (slot != NULL) *slot = &new->record;
return 0;
} else {
- if (slot != NIL(char **)) *slot = &ptr->record;
+ if (slot != NULL) *slot = &ptr->record;
return 1;
}
}
@@ -288,10 +307,10 @@ char ***slot;
FIND_ENTRY(table, hash_val, key, ptr, last);
- if (ptr == NIL(st_table_entry)) {
+ if (ptr == NULL) {
return 0;
} else {
- if (slot != NIL(char **)) {
+ if (slot != NULL) {
*slot = &ptr->record;
}
return 1;
@@ -317,7 +336,7 @@ register st_table *table;
}
table->num_entries = 0;
table->bins = ALLOC(st_table_entry *, table->num_bins);
- if (table->bins == NIL(st_table_entry *)) {
+ if (table->bins == NULL) {
table->bins = old_bins;
table->num_bins = old_num_bins;
table->num_entries = old_num_entries;
@@ -331,7 +350,7 @@ register st_table *table;
/* copy data over */
for (i = 0; i < old_num_bins; i++) {
ptr = old_bins[i];
- while (ptr != NIL(st_table_entry)) {
+ while (ptr != NULL) {
next = ptr->next;
hash_val = do_hash(ptr->key, table);
ptr->next = table->bins[hash_val];
@@ -354,25 +373,25 @@ st_table *old_table;
int i, j, num_bins = old_table->num_bins;
new_table = ALLOC(st_table, 1);
- if (new_table == NIL(st_table)) {
- return NIL(st_table);
+ if (new_table == NULL) {
+ return NULL;
}
*new_table = *old_table;
new_table->bins = ALLOC(st_table_entry *, num_bins);
- if (new_table->bins == NIL(st_table_entry *)) {
+ if (new_table->bins == NULL) {
FREE(new_table);
- return NIL(st_table);
+ return NULL;
}
for(i = 0; i < num_bins ; i++) {
- new_table->bins[i] = NIL(st_table_entry);
+ new_table->bins[i] = NULL;
ptr = old_table->bins[i];
- while (ptr != NIL(st_table_entry)) {
+ while (ptr != NULL) {
new = ALLOC(st_table_entry, 1);
- if (new == NIL(st_table_entry)) {
+ if (new == NULL) {
for (j = 0; j <= i; j++) {
newptr = new_table->bins[j];
- while (newptr != NIL(st_table_entry)) {
+ while (newptr != NULL) {
next = newptr->next;
FREE(newptr);
newptr = next;
@@ -380,7 +399,7 @@ st_table *old_table;
}
FREE(new_table->bins);
FREE(new_table);
- return NIL(st_table);
+ return NULL;
}
*new = *ptr;
new->next = new_table->bins[i];
@@ -405,12 +424,12 @@ char **value;
FIND_ENTRY(table, hash_val, key, ptr ,last);
- if (ptr == NIL(st_table_entry)) {
+ if (ptr == NULL) {
return 0;
}
*last = ptr->next;
- if (value != NIL(char *)) *value = ptr->record;
+ if (value != NULL) *value = ptr->record;
*keyp = ptr->key;
FREE(ptr);
table->num_entries--;
@@ -431,12 +450,12 @@ char **value;
FIND_ENTRY(table, hash_val, key, ptr ,last);
- if (ptr == NIL(st_table_entry)) {
+ if (ptr == NULL) {
return 0;
}
*last = ptr->next;
- if (value != NIL(char *)) *value = ptr->record;
+ if (value != NULL) *value = ptr->record;
*keyp = (long) ptr->key;
FREE(ptr);
table->num_entries--;
@@ -455,7 +474,7 @@ char *arg;
for(i = 0; i < table->num_bins; i++) {
last = &table->bins[i]; ptr = *last;
- while (ptr != NIL(st_table_entry)) {
+ while (ptr != NULL) {
retval = (*func)(ptr->key, ptr->record, arg);
switch (retval) {
case ST_CONTINUE:
@@ -528,11 +547,11 @@ st_table *table;
st_generator *gen;
gen = ALLOC(st_generator, 1);
- if (gen == NIL(st_generator)) {
- return NIL(st_generator);
+ if (gen == NULL) {
+ return NULL;
}
gen->table = table;
- gen->entry = NIL(st_table_entry);
+ gen->entry = NULL;
gen->index = 0;
return gen;
}
@@ -546,16 +565,16 @@ char **value_p;
{
register int i;
- if (gen->entry == NIL(st_table_entry)) {
+ if (gen->entry == NULL) {
/* try to find next entry */
for(i = gen->index; i < gen->table->num_bins; i++) {
- if (gen->table->bins[i] != NIL(st_table_entry)) {
+ if (gen->table->bins[i] != NULL) {
gen->index = i+1;
gen->entry = gen->table->bins[i];
break;
}
}
- if (gen->entry == NIL(st_table_entry)) {
+ if (gen->entry == NULL) {
return 0; /* that's all folks ! */
}
}
@@ -576,21 +595,21 @@ long *value_p;
{
register int i;
- if (gen->entry == NIL(st_table_entry)) {
+ if (gen->entry == NULL) {
/* try to find next entry */
for(i = gen->index; i < gen->table->num_bins; i++) {
- if (gen->table->bins[i] != NIL(st_table_entry)) {
+ if (gen->table->bins[i] != NULL) {
gen->index = i+1;
gen->entry = gen->table->bins[i];
break;
}
}
- if (gen->entry == NIL(st_table_entry)) {
+ if (gen->entry == NULL) {
return 0; /* that's all folks ! */
}
}
*key_p = gen->entry->key;
- if (value_p != NIL(long)) {
+ if (value_p != 0) {
*value_p = (long) gen->entry->record;
}
gen->entry = gen->entry->next;
diff --git a/src/misc/st/st.h b/src/misc/st/st.h
index c51873e9..b15f3c83 100644
--- a/src/misc/st/st.h
+++ b/src/misc/st/st.h
@@ -14,6 +14,10 @@
#ifndef ST_INCLUDED
#define ST_INCLUDED
+#ifdef __cplusplus
+extern "C" {
+#endif
+
typedef struct st_table_entry st_table_entry;
struct st_table_entry {
char *key;
@@ -48,28 +52,28 @@ enum st_retval {ST_CONTINUE, ST_STOP, ST_DELETE};
typedef enum st_retval (*ST_PFSR)();
typedef int (*ST_PFI)();
-EXTERN st_table *st_init_table_with_params ARGS((ST_PFI, ST_PFI, int, int, double, int));
-EXTERN st_table *st_init_table ARGS((ST_PFI, ST_PFI));
-EXTERN void st_free_table ARGS((st_table *));
-EXTERN int st_lookup ARGS((st_table *, char *, char **));
-EXTERN int st_lookup_int ARGS((st_table *, char *, int *));
-EXTERN int st_insert ARGS((st_table *, char *, char *));
-EXTERN int st_add_direct ARGS((st_table *, char *, char *));
-EXTERN int st_find_or_add ARGS((st_table *, char *, char ***));
-EXTERN int st_find ARGS((st_table *, char *, char ***));
-EXTERN st_table *st_copy ARGS((st_table *));
-EXTERN int st_delete ARGS((st_table *, char **, char **));
-EXTERN int st_delete_int ARGS((st_table *, long *, char **));
-EXTERN int st_foreach ARGS((st_table *, ST_PFSR, char *));
-EXTERN int st_strhash ARGS((char *, int));
-EXTERN int st_numhash ARGS((char *, int));
-EXTERN int st_ptrhash ARGS((char *, int));
-EXTERN int st_numcmp ARGS((char *, char *));
-EXTERN int st_ptrcmp ARGS((char *, char *));
-EXTERN st_generator *st_init_gen ARGS((st_table *));
-EXTERN int st_gen ARGS((st_generator *, char **, char **));
-EXTERN int st_gen_int ARGS((st_generator *, char **, long *));
-EXTERN void st_free_gen ARGS((st_generator *));
+extern st_table *st_init_table_with_params (ST_PFI, ST_PFI, int, int, double, int);
+extern st_table *st_init_table (ST_PFI, ST_PFI);
+extern void st_free_table (st_table *);
+extern int st_lookup (st_table *, char *, char **);
+extern int st_lookup_int (st_table *, char *, int *);
+extern int st_insert (st_table *, char *, char *);
+extern int st_add_direct (st_table *, char *, char *);
+extern int st_find_or_add (st_table *, char *, char ***);
+extern int st_find (st_table *, char *, char ***);
+extern st_table *st_copy (st_table *);
+extern int st_delete (st_table *, char **, char **);
+extern int st_delete_int (st_table *, long *, char **);
+extern int st_foreach (st_table *, ST_PFSR, char *);
+extern int st_strhash (char *, int);
+extern int st_numhash (char *, int);
+extern int st_ptrhash (char *, int);
+extern int st_numcmp (char *, char *);
+extern int st_ptrcmp (char *, char *);
+extern st_generator *st_init_gen (st_table *);
+extern int st_gen (st_generator *, char **, char **);
+extern int st_gen_int (st_generator *, char **, long *);
+extern void st_free_gen (st_generator *);
#define ST_DEFAULT_MAX_DENSITY 5
@@ -85,4 +89,8 @@ EXTERN void st_free_gen ARGS((st_generator *));
#define ST_OUT_OF_MEM -10000
+#ifdef __cplusplus
+}
+#endif
+
#endif /* ST_INCLUDED */
diff --git a/src/misc/st/stmm.c b/src/misc/st/stmm.c
index b75b0134..8dfacfe4 100644
--- a/src/misc/st/stmm.c
+++ b/src/misc/st/stmm.c
@@ -8,12 +8,17 @@
*
*/
#include <stdio.h>
-#include "util.h"
+#include "extra.h"
#include "stmm.h"
+#ifndef ABS
+# define ABS(a) ((a) < 0 ? -(a) : (a))
+#endif
+
#define STMM_NUMCMP(x,y) ((x) != (y))
#define STMM_NUMHASH(x,size) (ABS((long)x)%(size))
-#define STMM_PTRHASH(x,size) ((int)((unsigned long)(x)>>2)%size)
+//#define STMM_PTRHASH(x,size) ((int)((unsigned long)(x)>>2)%size) // 64-bit bug fix 9/17/2007
+#define STMM_PTRHASH(x,size) ((int)(((unsigned long)(x)>>2)%size))
#define EQUAL(func, x, y) \
((((func) == stmm_numcmp) || ((func) == stmm_ptrcmp)) ?\
(STMM_NUMCMP((x),(y)) == 0) : ((*func)((x), (y)) == 0))
@@ -41,8 +46,8 @@ stmm_init_table_with_params (compare, hash, size, density, grow_factor,
stmm_table *new;
new = ALLOC (stmm_table, 1);
- if (new == NIL (stmm_table)) {
- return NIL (stmm_table);
+ if (new == NULL) {
+ return NULL;
}
new->compare = compare;
new->hash = hash;
@@ -55,9 +60,9 @@ stmm_init_table_with_params (compare, hash, size, density, grow_factor,
}
new->num_bins = size;
new->bins = ALLOC (stmm_table_entry *, size);
- if (new->bins == NIL (stmm_table_entry *)) {
+ if (new->bins == NULL) {
FREE (new);
- return NIL (stmm_table);
+ return NULL;
}
for (i = 0; i < size; i++) {
new->bins[i] = 0;
@@ -90,7 +95,7 @@ stmm_free_table (table)
for ( i = 0; i < table->num_bins; i++ )
{
ptr = table->bins[i];
- while ( ptr != NIL( stmm_table_entry ) )
+ while ( ptr != NULL )
{
next = ptr->next;
FREE( ptr );
@@ -101,7 +106,7 @@ stmm_free_table (table)
// no need to deallocate entries because they are in the memory manager now
// added by alanmi
if ( table->pMemMan )
- Extra_MmFixedStop (table->pMemMan, 0);
+ Extra_MmFixedStop (table->pMemMan);
FREE (table->bins);
FREE (table);
}
@@ -123,7 +128,7 @@ stmm_clean (table)
#define PTR_NOT_EQUAL(table, ptr, user_key)\
-(ptr != NIL(stmm_table_entry) && !EQUAL(table->compare, user_key, (ptr)->key))
+(ptr != NULL && !EQUAL(table->compare, user_key, (ptr)->key))
#define FIND_ENTRY(table, hash_val, key, ptr, last) \
(last) = &(table)->bins[hash_val];\
@@ -131,7 +136,7 @@ stmm_clean (table)
while (PTR_NOT_EQUAL((table), (ptr), (key))) {\
(last) = &(ptr)->next; (ptr) = *(last);\
}\
- if ((ptr) != NIL(stmm_table_entry) && (table)->reorder_flag) {\
+ if ((ptr) != NULL && (table)->reorder_flag) {\
*(last) = (ptr)->next;\
(ptr)->next = (table)->bins[hash_val];\
(table)->bins[hash_val] = (ptr);\
@@ -150,11 +155,11 @@ stmm_lookup (table, key, value)
FIND_ENTRY (table, hash_val, key, ptr, last);
- if (ptr == NIL (stmm_table_entry)) {
+ if (ptr == NULL) {
return 0;
}
else {
- if (value != NIL (char *))
+ if (value != NULL)
{
*value = ptr->record;
}
@@ -175,11 +180,11 @@ stmm_lookup_int (table, key, value)
FIND_ENTRY (table, hash_val, key, ptr, last);
- if (ptr == NIL (stmm_table_entry)) {
+ if (ptr == NULL) {
return 0;
}
else {
- if (value != NIL (int))
+ if (value != 0)
{
*value = (long) ptr->record;
}
@@ -223,7 +228,7 @@ stmm_insert (table, key, value)
FIND_ENTRY (table, hash_val, key, ptr, last);
- if (ptr == NIL (stmm_table_entry)) {
+ if (ptr == NULL) {
if (table->num_entries / table->num_bins >= table->max_density) {
if (rehash (table) == STMM_OUT_OF_MEM) {
return STMM_OUT_OF_MEM;
@@ -233,7 +238,7 @@ stmm_insert (table, key, value)
// new = ALLOC( stmm_table_entry, 1 );
new = (stmm_table_entry *) Extra_MmFixedEntryFetch (table->pMemMan);
- if (new == NIL (stmm_table_entry)) {
+ if (new == NULL) {
return STMM_OUT_OF_MEM;
}
@@ -269,7 +274,7 @@ stmm_add_direct (table, key, value)
// new = ALLOC( stmm_table_entry, 1 );
new = (stmm_table_entry *) Extra_MmFixedEntryFetch (table->pMemMan);
- if (new == NIL (stmm_table_entry)) {
+ if (new == NULL) {
return STMM_OUT_OF_MEM;
}
@@ -294,7 +299,7 @@ stmm_find_or_add (table, key, slot)
FIND_ENTRY (table, hash_val, key, ptr, last);
- if (ptr == NIL (stmm_table_entry)) {
+ if (ptr == NULL) {
if (table->num_entries / table->num_bins >= table->max_density) {
if (rehash (table) == STMM_OUT_OF_MEM) {
return STMM_OUT_OF_MEM;
@@ -304,7 +309,7 @@ stmm_find_or_add (table, key, slot)
// new = ALLOC( stmm_table_entry, 1 );
new = (stmm_table_entry *) Extra_MmFixedEntryFetch (table->pMemMan);
- if (new == NIL (stmm_table_entry)) {
+ if (new == NULL) {
return STMM_OUT_OF_MEM;
}
@@ -313,12 +318,12 @@ stmm_find_or_add (table, key, slot)
new->next = table->bins[hash_val];
table->bins[hash_val] = new;
table->num_entries++;
- if (slot != NIL (char **))
+ if (slot != NULL)
*slot = &new->record;
return 0;
}
else {
- if (slot != NIL (char **))
+ if (slot != NULL)
*slot = &ptr->record;
return 1;
}
@@ -337,11 +342,11 @@ stmm_find (table, key, slot)
FIND_ENTRY (table, hash_val, key, ptr, last);
- if (ptr == NIL (stmm_table_entry)) {
+ if (ptr == NULL) {
return 0;
}
else {
- if (slot != NIL (char **))
+ if (slot != NULL)
{
*slot = &ptr->record;
}
@@ -368,7 +373,7 @@ rehash (table)
}
table->num_entries = 0;
table->bins = ALLOC (stmm_table_entry *, table->num_bins);
- if (table->bins == NIL (stmm_table_entry *)) {
+ if (table->bins == NULL) {
table->bins = old_bins;
table->num_bins = old_num_bins;
table->num_entries = old_num_entries;
@@ -382,7 +387,7 @@ rehash (table)
/* copy data over */
for (i = 0; i < old_num_bins; i++) {
ptr = old_bins[i];
- while (ptr != NIL (stmm_table_entry)) {
+ while (ptr != NULL) {
next = ptr->next;
hash_val = do_hash (ptr->key, table);
ptr->next = table->bins[hash_val];
@@ -405,15 +410,15 @@ stmm_copy (old_table)
int i, /*j, */ num_bins = old_table->num_bins;
new_table = ALLOC (stmm_table, 1);
- if (new_table == NIL (stmm_table)) {
- return NIL (stmm_table);
+ if (new_table == NULL) {
+ return NULL;
}
*new_table = *old_table;
new_table->bins = ALLOC (stmm_table_entry *, num_bins);
- if (new_table->bins == NIL (stmm_table_entry *)) {
+ if (new_table->bins == NULL) {
FREE (new_table);
- return NIL (stmm_table);
+ return NULL;
}
// allocate the memory manager for the new table
@@ -421,20 +426,20 @@ stmm_copy (old_table)
Extra_MmFixedStart (sizeof (stmm_table_entry));
for (i = 0; i < num_bins; i++) {
- new_table->bins[i] = NIL (stmm_table_entry);
+ new_table->bins[i] = NULL;
ptr = old_table->bins[i];
- while (ptr != NIL (stmm_table_entry)) {
+ while (ptr != NULL) {
// new = ALLOC( stmm_table_entry, 1 );
new =
(stmm_table_entry *) Extra_MmFixedEntryFetch (new_table->
pMemMan);
- if (new == NIL (stmm_table_entry)) {
+ if (new == NULL) {
/*
for ( j = 0; j <= i; j++ )
{
newptr = new_table->bins[j];
- while ( newptr != NIL( stmm_table_entry ) )
+ while ( newptr != NULL )
{
next = newptr->next;
FREE( newptr );
@@ -442,11 +447,11 @@ stmm_copy (old_table)
}
}
*/
- Extra_MmFixedStop (new_table->pMemMan, 0);
+ Extra_MmFixedStop (new_table->pMemMan);
FREE (new_table->bins);
FREE (new_table);
- return NIL (stmm_table);
+ return NULL;
}
*new = *ptr;
new->next = new_table->bins[i];
@@ -471,12 +476,12 @@ stmm_delete (table, keyp, value)
FIND_ENTRY (table, hash_val, key, ptr, last);
- if (ptr == NIL (stmm_table_entry)) {
+ if (ptr == NULL) {
return 0;
}
*last = ptr->next;
- if (value != NIL (char *))
+ if (value != NULL)
*value = ptr->record;
*keyp = ptr->key;
// FREE( ptr );
@@ -500,12 +505,12 @@ stmm_delete_int (table, keyp, value)
FIND_ENTRY (table, hash_val, key, ptr, last);
- if (ptr == NIL (stmm_table_entry)) {
+ if (ptr == NULL) {
return 0;
}
*last = ptr->next;
- if (value != NIL (char *))
+ if (value != NULL)
*value = ptr->record;
*keyp = (long) ptr->key;
// FREE( ptr );
@@ -528,7 +533,7 @@ stmm_foreach (table, func, arg)
for (i = 0; i < table->num_bins; i++) {
last = &table->bins[i];
ptr = *last;
- while (ptr != NIL (stmm_table_entry)) {
+ while (ptr != NULL) {
retval = (*func) (ptr->key, ptr->record, arg);
switch (retval) {
case STMM_CONTINUE:
@@ -604,11 +609,11 @@ stmm_init_gen (table)
stmm_generator *gen;
gen = ALLOC (stmm_generator, 1);
- if (gen == NIL (stmm_generator)) {
- return NIL (stmm_generator);
+ if (gen == NULL) {
+ return NULL;
}
gen->table = table;
- gen->entry = NIL (stmm_table_entry);
+ gen->entry = NULL;
gen->index = 0;
return gen;
}
@@ -622,16 +627,16 @@ stmm_gen (gen, key_p, value_p)
{
register int i;
- if (gen->entry == NIL (stmm_table_entry)) {
+ if (gen->entry == NULL) {
/* try to find next entry */
for (i = gen->index; i < gen->table->num_bins; i++) {
- if (gen->table->bins[i] != NIL (stmm_table_entry)) {
+ if (gen->table->bins[i] != NULL) {
gen->index = i + 1;
gen->entry = gen->table->bins[i];
break;
}
}
- if (gen->entry == NIL (stmm_table_entry)) {
+ if (gen->entry == NULL) {
return 0; /* that's all folks ! */
}
}
@@ -652,21 +657,21 @@ stmm_gen_int (gen, key_p, value_p)
{
register int i;
- if (gen->entry == NIL (stmm_table_entry)) {
+ if (gen->entry == NULL) {
/* try to find next entry */
for (i = gen->index; i < gen->table->num_bins; i++) {
- if (gen->table->bins[i] != NIL (stmm_table_entry)) {
+ if (gen->table->bins[i] != NULL) {
gen->index = i + 1;
gen->entry = gen->table->bins[i];
break;
}
}
- if (gen->entry == NIL (stmm_table_entry)) {
+ if (gen->entry == NULL) {
return 0; /* that's all folks ! */
}
}
*key_p = gen->entry->key;
- if (value_p != NIL (long))
+ if (value_p != 0)
{
*value_p = (long) gen->entry->record;
}
diff --git a/src/misc/st/stmm.h b/src/misc/st/stmm.h
index 1fe3dfd2..4330416e 100644
--- a/src/misc/st/stmm.h
+++ b/src/misc/st/stmm.h
@@ -14,6 +14,10 @@
#ifndef STMM_INCLUDED
#define STMM_INCLUDED
+#ifdef __cplusplus
+extern "C" {
+#endif
+
#include "extra.h"
typedef struct stmm_table_entry stmm_table_entry;
@@ -93,7 +97,7 @@ EXTERN void stmm_clean ARGS ((stmm_table *));
// added by Zhihong: no need for memory allocation
#define stmm_foreach_item2(tb, /* stmm_generator */gen, key, value) \
- for(gen.table=(tb), gen.entry=NIL(stmm_table_entry), gen.index=0; \
+ for(gen.table=(tb), gen.entry=NULL, gen.index=0; \
stmm_gen(&(gen),key,value);)
#define stmm_foreach_item(table, gen, key, value) \
@@ -116,4 +120,8 @@ EXTERN void stmm_clean ARGS ((stmm_table *));
*/
+#ifdef __cplusplus
+}
+#endif
+
#endif /* STMM_INCLUDED */
diff --git a/src/misc/util/cpu_stats.c b/src/misc/util/cpu_stats.c
deleted file mode 100644
index aa2d18ef..00000000
--- a/src/misc/util/cpu_stats.c
+++ /dev/null
@@ -1,122 +0,0 @@
-/*
- * Revision Control Information
- *
- * /projects/hsis/CVS/utilities/util/cpu_stats.c,v
- * rajeev
- * 1.4
- * 1995/08/08 22:41:17
- *
- */
-/* LINTLIBRARY */
-
-#include <stdio.h>
-#include "util.h"
-
-
-#include <sys/types.h>
-//#include <sys/time.h>
-#ifdef HAVE_SYS_RESOURCE_H
-# include <sys/resource.h>
-#endif
-
-#if defined(_IBMR2)
-#define etext _etext
-#define edata _edata
-#define end _end
-#endif
-
-#ifndef __CYGWIN32__
-extern int end, etext, edata;
-#endif
-
-void
-util_print_cpu_stats(fp)
-FILE *fp;
-{
- (void) fprintf(fp, "Usage statistics not available\n");
-}
-
-#if 0
-
-void
-util_print_cpu_stats(fp)
-FILE *fp;
-{
-#if HAVE_SYS_RESOURCE_H && !defined(__CYGWIN32__)
- struct rusage rusage;
-#ifdef RLIMIT_DATA
- struct rlimit rlp;
-#endif
- int text, data, vm_limit, vm_soft_limit;
- double user, system, scale;
- char hostname[257];
- int vm_text, vm_init_data, vm_uninit_data, vm_sbrk_data;
-
- /* Get the hostname */
- (void) gethostname(hostname, 256);
- hostname[256] = '\0'; /* just in case */
-
- /* Get the virtual memory sizes */
- vm_text = ((int) (&etext)) / 1024.0 + 0.5;
- vm_init_data = ((int) (&edata) - (int) (&etext)) / 1024.0 + 0.5;
- vm_uninit_data = ((int) (&end) - (int) (&edata)) / 1024.0 + 0.5;
- vm_sbrk_data = (sizeof(char) * ((char *) sbrk(0) - (char *) (&end))) / 1024.0 + 0.5;
-
- /* Get virtual memory limits */
-#ifdef RLIMIT_DATA /* In HP-UX, with cc, this constant does not exist */
- (void) getrlimit(RLIMIT_DATA, &rlp);
- vm_limit = rlp.rlim_max / 1024.0 + 0.5;
- vm_soft_limit = rlp.rlim_cur / 1024.0 + 0.5;
-#else
- vm_limit = -1;
- vm_soft_limit = -1;
-#endif
-
- /* Get usage stats */
- (void) getrusage(RUSAGE_SELF, &rusage);
- user = rusage.ru_utime.tv_sec + rusage.ru_utime.tv_usec/1.0e6;
- system = rusage.ru_stime.tv_sec + rusage.ru_stime.tv_usec/1.0e6;
- scale = (user + system)*100.0;
- if (scale == 0.0) scale = 0.001;
-
- (void) fprintf(fp, "Runtime Statistics\n");
- (void) fprintf(fp, "------------------\n");
- (void) fprintf(fp, "Machine name: %s\n", hostname);
- (void) fprintf(fp, "User time %6.1f seconds\n", user);
- (void) fprintf(fp, "System time %6.1f seconds\n\n", system);
-
- text = rusage.ru_ixrss / scale + 0.5;
- data = (rusage.ru_idrss + rusage.ru_isrss) / scale + 0.5;
- (void) fprintf(fp, "Average resident text size = %5dK\n", text);
- (void) fprintf(fp, "Average resident data+stack size = %5dK\n", data);
- (void) fprintf(fp, "Maximum resident size = %5ldK\n\n",
- rusage.ru_maxrss/2);
- (void) fprintf(fp, "Virtual text size = %5dK\n",
- vm_text);
- (void) fprintf(fp, "Virtual data size = %5dK\n",
- vm_init_data + vm_uninit_data + vm_sbrk_data);
- (void) fprintf(fp, " data size initialized = %5dK\n",
- vm_init_data);
- (void) fprintf(fp, " data size uninitialized = %5dK\n",
- vm_uninit_data);
- (void) fprintf(fp, " data size sbrk = %5dK\n",
- vm_sbrk_data);
- /* In some platforms, this constant does not exist */
-#ifdef RLIMIT_DATA
- (void) fprintf(fp, "Virtual memory limit = %5dK (%dK)\n\n",
- vm_soft_limit, vm_limit);
-#endif
- (void) fprintf(fp, "Major page faults = %ld\n", rusage.ru_majflt);
- (void) fprintf(fp, "Minor page faults = %ld\n", rusage.ru_minflt);
- (void) fprintf(fp, "Swaps = %ld\n", rusage.ru_nswap);
- (void) fprintf(fp, "Input blocks = %ld\n", rusage.ru_inblock);
- (void) fprintf(fp, "Output blocks = %ld\n", rusage.ru_oublock);
- (void) fprintf(fp, "Context switch (voluntary) = %ld\n", rusage.ru_nvcsw);
- (void) fprintf(fp, "Context switch (involuntary) = %ld\n", rusage.ru_nivcsw);
-#else /* Do not have sys/resource.h */
- (void) fprintf(fp, "Usage statistics not available\n");
-#endif
-}
-
-#endif
-
diff --git a/src/misc/util/cpu_time.c b/src/misc/util/cpu_time.c
deleted file mode 100644
index d264bdc9..00000000
--- a/src/misc/util/cpu_time.c
+++ /dev/null
@@ -1,128 +0,0 @@
-/**CFile***********************************************************************
-
- FileName [ cpu_time.c ]
-
- PackageName [ util ]
-
- Synopsis [ System time calls ]
-
- Description [ The problem is that all unix systems have a different notion
- of how fast time goes (i.e., the units returned by). This
- returns a consistent result. ]
-
- Author [ Stephen Edwards <sedwards@eecs.berkeley.edu> and others ]
-
- Copyright [Copyright (c) 1994-1996 The Regents of the Univ. of California.
- All rights reserved.
-
- Permission is hereby granted, without written agreement and without license
- or royalty fees, to use, copy, modify, and distribute this software and its
- documentation for any purpose, provided that the above copyright notice and
- the following two paragraphs appear in all copies of this software.
-
- IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY FOR
- DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT
- OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF THE UNIVERSITY OF
- CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
- THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES,
- INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
- FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS ON AN
- "AS IS" BASIS, AND THE UNIVERSITY OF CALIFORNIA HAS NO OBLIGATION TO PROVIDE
- MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.]
-
-******************************************************************************/
-
-#include "util.h"
-
-#if HAVE_SYS_TYPES_H
-# include<sys/types.h>
-#endif
-
-#if HAVE_SYS_TIMES_H
-# include<sys/times.h>
-#endif
-
-/**AutomaticStart*************************************************************/
-
-/*---------------------------------------------------------------------------*/
-/* Static function prototypes */
-/*---------------------------------------------------------------------------*/
-
-/**AutomaticEnd***************************************************************/
-
-/**Function********************************************************************
-
- Synopsis [ Return elapsed time in milliseconds ]
-
- Description [ Return a long which represents the elapsed time in
- milliseconds since some constant reference. <P>
-
- There are two possibilities:
- <OL>
- <LI> The system is non-POSIX compliant, so unistd.h
- and hence sysconf() can't tell us the clock tick
- speed. At this point, we have to resort to
- using the user-settable CLOCK_RESOLUTION definition
- to get the right speed
- <LI> The system is POSIX-compliant. unistd.h gives
- us sysconf(), which tells us the clock rate.
- </OL>
- ]
-
- SideEffects [ none ]
-
-******************************************************************************/
-
-/*
-long
-util_cpu_time()
-{
- long t = 0;
-
-#if HAVE_SYSCONF == 1
-
- // Code for POSIX systems
-
- struct tms buffer;
- long nticks; // number of clock ticks per second
-
- nticks = sysconf(_SC_CLK_TCK);
- times(&buffer);
- t = buffer.tms_utime * (1000.0/nticks);
-
-#else
-# ifndef vms
-
- // Code for non-POSIX systems
-
- struct tms buffer;
-
- time(&buffer);
- t = buffer.tms_utime * 1000.0 / CLOCK_RESOLUTION;
-
-# else
-
- // Code for VMS (?)
-
- struct {int p1, p2, p3, p4;} buffer;
- static long ref_time;
- times(&buffer);
- t = buffer.p1 * 10;
- if (ref_time == 0)
- ref_time = t;
- t = t - ref_time;
-
-# endif // vms
-#endif // _POSIX_VERSION
-
- return t;
-}
-*/
-
-
-long
-util_cpu_time()
-{
- return clock();
-}
diff --git a/src/misc/util/datalimit.c b/src/misc/util/datalimit.c
deleted file mode 100644
index 96c2ce95..00000000
--- a/src/misc/util/datalimit.c
+++ /dev/null
@@ -1,95 +0,0 @@
-/**CFile************************************************************************
-
- FileName [datalimit.c]
-
- PackageName [util]
-
- Synopsis [Routine to obtain the maximum data size available to a program. The
- routine is based on "getrlimit". If the system does not have this function,
- the default value RLIMIT_DATA_DEFAULT is assumed. This function provides an
- informative value, it does not restrict the size of the program in any way.]
-
- Author [Fabio Somenzi <fabio@colorado.edu>]
-
- Copyright [This file was created at the University of Colorado at
- Boulder. The University of Colorado at Boulder makes no warranty
- about the suitability of this software for any purpose. It is
- presented on an AS IS basis.]
-
-******************************************************************************/
-
-#include "util.h"
-
-static char rcsid[] UNUSED = "$Id: datalimit.c,v 1.1.1.1 2003/02/24 22:24:04 wjiang Exp $";
-
-#if HAVE_SYS_RESOURCE_H
-#if HAVE_SYS_TIME_H
-#include <sys/time.h>
-#endif
-#include <sys/resource.h>
-#endif
-
-/*---------------------------------------------------------------------------*/
-/* Type declarations */
-/*---------------------------------------------------------------------------*/
-
-/*---------------------------------------------------------------------------*/
-/* Structure declarations */
-/*---------------------------------------------------------------------------*/
-
-/*---------------------------------------------------------------------------*/
-/* Macro declarations */
-/*---------------------------------------------------------------------------*/
-
-#ifndef RLIMIT_DATA_DEFAULT
-#define RLIMIT_DATA_DEFAULT 67108864 /* assume 64MB by default */
-#endif
-
-/*---------------------------------------------------------------------------*/
-/* Variable declarations */
-/*---------------------------------------------------------------------------*/
-
-/**AutomaticStart*************************************************************/
-
-/*---------------------------------------------------------------------------*/
-/* Static function prototypes */
-/*---------------------------------------------------------------------------*/
-
-/**AutomaticEnd***************************************************************/
-
-/*---------------------------------------------------------------------------*/
-/* Definition of exported functions */
-/*---------------------------------------------------------------------------*/
-
-/**Function********************************************************************
-
- Synopsis [Function that computes the data limit of the process.]
-
- SideEffects []
-
-******************************************************************************/
-int
-getSoftDataLimit()
-{
-#if HAVE_SYS_RESOURCE_H && HAVE_GETRLIMIT && defined(RLIMIT_DATA)
- struct rlimit rl;
- int result;
-
- result = getrlimit(RLIMIT_DATA, &rl);
- if (result != 0 || rl.rlim_cur == RLIM_INFINITY)
- return(RLIMIT_DATA_DEFAULT);
- else
- return(rl.rlim_cur);
-#else
- return(RLIMIT_DATA_DEFAULT);
-#endif
-
-} /* end of getSoftDataLimit */
-
-/*---------------------------------------------------------------------------*/
-/* Definition of internal functions */
-/*---------------------------------------------------------------------------*/
-
-/*---------------------------------------------------------------------------*/
-/* Definition of static functions */
-/*---------------------------------------------------------------------------*/
diff --git a/src/misc/util/getopt.c b/src/misc/util/getopt.c
deleted file mode 100644
index 778c34d6..00000000
--- a/src/misc/util/getopt.c
+++ /dev/null
@@ -1,84 +0,0 @@
-/*
- * Revision Control Information
- *
- * /projects/hsis/CVS/utilities/util/getopt.c,v
- * rajeev
- * 1.3
- * 1995/08/08 22:41:22
- *
- */
-/* LINTLIBRARY */
-
-#include <stdio.h>
-#include "util.h"
-
-
-/* File : getopt.c
- * Author : Henry Spencer, University of Toronto
- * Updated: 28 April 1984
- *
- * Changes: (R Rudell)
- * changed index() to strchr();
- * added getopt_reset() to reset the getopt argument parsing
- *
- * Purpose: get option letter from argv.
- */
-
-char *util_optarg; /* Global argument pointer. */
-int util_optind = 0; /* Global argv index. */
-static char *scan;
-
-
-void
-util_getopt_reset()
-{
- util_optarg = 0;
- util_optind = 0;
- scan = 0;
-}
-
-
-
-int
-util_getopt(argc, argv, optstring)
-int argc;
-char *argv[];
-char *optstring;
-{
- register int c;
- register char *place;
-
- util_optarg = NIL(char);
-
- if (scan == NIL(char) || *scan == '\0') {
- if (util_optind == 0) util_optind++;
- if (util_optind >= argc) return EOF;
- place = argv[util_optind];
- if (place[0] != '-' || place[1] == '\0') return EOF;
- util_optind++;
- if (place[1] == '-' && place[2] == '\0') return EOF;
- scan = place+1;
- }
-
- c = *scan++;
- place = strchr(optstring, c);
- if (place == NIL(char) || c == ':') {
- (void) fprintf(stderr, "%s: unknown option %c\n", argv[0], c);
- return '?';
- }
- if (*++place == ':') {
- if (*scan != '\0') {
- util_optarg = scan;
- scan = NIL(char);
- } else {
- if (util_optind >= argc) {
- (void) fprintf(stderr, "%s: %c requires an argument\n",
- argv[0], c);
- return '?';
- }
- util_optarg = argv[util_optind];
- util_optind++;
- }
- }
- return c;
-}
diff --git a/src/misc/util/leaks.h b/src/misc/util/leaks.h
index daa628b1..1a32062a 100644
--- a/src/misc/util/leaks.h
+++ b/src/misc/util/leaks.h
@@ -1,8 +1,8 @@
-///////////////////////////////////////////////////////////////////////
+//////////////////////////////////////////////////////////////////////////
// This file is used to detect memory leaks using Visual Studio 6.0
-// The idea comes from the following webpage:
-// http://www.michaelmoser.org/memory.htm
-//////////////////////////////////////
+// The idea comes from this page: http://www.michaelmoser.org/memory.htm
+// In addition to this file, it required the presence of "stdlib_hack.h"
+//////////////////////////////////////////////////////////////////////////
#ifndef __LEAKS_H__
#define __LEAKS_H__
diff --git a/src/misc/util/module.make b/src/misc/util/module.make
index 06eba7e4..d6d908e7 100644
--- a/src/misc/util/module.make
+++ b/src/misc/util/module.make
@@ -1,8 +1 @@
-SRC += src/misc/util/cpu_stats.c \
- src/misc/util/cpu_time.c \
- src/misc/util/datalimit.c \
- src/misc/util/getopt.c \
- src/misc/util/pathsearch.c \
- src/misc/util/safe_mem.c \
- src/misc/util/strsav.c \
- src/misc/util/texpand.c
+SRC +=
diff --git a/src/misc/util/pathsearch.c b/src/misc/util/pathsearch.c
deleted file mode 100644
index d4d845eb..00000000
--- a/src/misc/util/pathsearch.c
+++ /dev/null
@@ -1,131 +0,0 @@
-/*
- * Revision Control Information
- *
- * /projects/hsis/CVS/utilities/util/pathsearch.c,v
- * rajeev
- * 1.3
- * 1995/08/08 22:41:24
- *
- */
-/* LINTLIBRARY */
-
-#if HAVE_SYS_FILE_H
-# include <sys/file.h>
-#endif
-
-#if HAVE_SYS_STAT_H
-# include <sys/stat.h>
-#endif
-
-#include "util.h"
-
-/**Function********************************************************************
-
- Synopsis [ Check that a given file is present and accessible ]
-
- SideEffects [none]
-******************************************************************************/
-static int
-check_file(filename, mode)
-char *filename;
-char *mode;
-{
-#if defined(HAVE_SYS_STAT_H)
- struct stat stat_rec;
- int access_char = mode[0];
- int access_mode = R_OK;
-
- /* First check that the file is a regular file. */
-
- if (stat(filename,&stat_rec) == 0
- && (stat_rec.st_mode&S_IFMT) == S_IFREG) {
- if (access_char == 'w') {
- access_mode = W_OK;
- } else if (access_char == 'x') {
- access_mode = X_OK;
- }
- return access(filename,access_mode) == 0;
- }
- return 0;
-
-#else
-
- FILE *fp;
- int got_file;
-
- if (strcmp(mode, "x") == 0) {
- mode = "r";
- }
- fp = fopen(filename, mode);
- got_file = (fp != 0);
- if (fp != 0) {
- (void) fclose(fp);
- }
- return got_file;
-
-#endif
-}
-
-/**Function********************************************************************
-
- Synopsis [ Search for a program in all possible paths ]
-
- SideEffects [none]
-
-******************************************************************************/
-char *
-util_path_search(prog)
-char *prog;
-{
-#ifdef HAVE_GETENV
- return util_file_search(prog, getenv("PATH"), "x");
-#else
- return util_file_search(prog, NIL(char), "x");
-#endif
-}
-
-char *
-util_file_search(file, path, mode)
-char *file; /* file we're looking for */
-char *path; /* search path, colon separated */
-char *mode; /* "r", "w", or "x" */
-{
- int quit;
- char *buffer, *filename, *save_path, *cp;
-
- if (path == 0 || strcmp(path, "") == 0) {
- path = "."; /* just look in the current directory */
- }
-
- save_path = path = util_strsav(path);
- quit = 0;
- do {
- cp = strchr(path, ':');
- if (cp != 0) {
- *cp = '\0';
- } else {
- quit = 1;
- }
-
- /* cons up the filename out of the path and file name */
- if (strcmp(path, ".") == 0) {
- buffer = util_strsav(file);
- } else {
- buffer = ALLOC(char, strlen(path) + strlen(file) + 4);
- (void) sprintf(buffer, "%s/%s", path, file);
- }
- filename = util_tilde_expand(buffer);
- FREE(buffer);
-
- /* see if we can access it */
- if (check_file(filename, mode)) {
- FREE(save_path);
- return filename;
- }
- FREE(filename);
- path = ++cp;
- } while (! quit);
-
- FREE(save_path);
- return 0;
-}
diff --git a/src/misc/util/safe_mem.c b/src/misc/util/safe_mem.c
deleted file mode 100644
index 5a8a5de8..00000000
--- a/src/misc/util/safe_mem.c
+++ /dev/null
@@ -1,104 +0,0 @@
-/*
- * Revision Control Information
- *
- * /projects/hsis/CVS/utilities/util/safe_mem.c,v
- * rajeev
- * 1.3
- * 1995/08/08 22:41:29
- *
- */
-/* LINTLIBRARY */
-
-#include "util.h"
-
-/*
- * These are interface routines to be placed between a program and the
- * system memory allocator.
- *
- * It forces well-defined semantics for several 'borderline' cases:
- *
- * malloc() of a 0 size object is guaranteed to return something
- * which is not 0, and can safely be freed (but not dereferenced)
- * free() accepts (silently) an 0 pointer
- * realloc of a 0 pointer is allowed, and is equiv. to malloc()
- * For the IBM/PC it forces no object > 64K; note that the size argument
- * to malloc/realloc is a 'long' to catch this condition
- *
- * The function pointer MMoutOfMemory() contains a vector to handle a
- * 'out-of-memory' error (which, by default, points at a simple wrap-up
- * and exit routine).
- */
-
-extern char *MMalloc();
-extern void MMout_of_memory();
-extern char *MMrealloc();
-
-
-void (*MMoutOfMemory)() = MMout_of_memory;
-
-
-/* MMout_of_memory -- out of memory for lazy people, flush and exit */
-void
-MMout_of_memory(size)
-long size;
-{
- (void) fflush(stdout);
- (void) fprintf(stderr, "\nout of memory allocating %u bytes\n",
- (unsigned) size);
- assert( 0 );
- exit(1);
-}
-
-
-char *
-MMalloc(size)
-long size;
-{
- char *p;
-
-#ifdef IBMPC
- if (size > 65000L) {
- if (MMoutOfMemory != (void (*)()) 0 ) (*MMoutOfMemory)(size);
- return NIL(char);
- }
-#endif
- if (size == 0) size = sizeof(long);
- if ((p = (char *) malloc((unsigned) size)) == NIL(char)) {
- if (MMoutOfMemory != (void (*)()) 0 ) (*MMoutOfMemory)(size);
- return NIL(char);
- }
- return p;
-}
-
-
-char *
-MMrealloc(obj, size)
-char *obj;
-long size;
-{
- char *p;
-
-#ifdef IBMPC
- if (size > 65000L) {
- if (MMoutOfMemory != (void (*)()) 0 ) (*MMoutOfMemory)(size);
- return NIL(char);
- }
-#endif
- if (obj == NIL(char)) return MMalloc(size);
- if (size <= 0) size = sizeof(long);
- if ((p = (char *) realloc(obj, (unsigned) size)) == NIL(char)) {
- if (MMoutOfMemory != (void (*)()) 0 ) (*MMoutOfMemory)(size);
- return NIL(char);
- }
- return p;
-}
-
-
-void
-MMfree(obj)
-char *obj;
-{
- if (obj != 0) {
- free(obj);
- }
-}
diff --git a/src/misc/util/strsav.c b/src/misc/util/strsav.c
deleted file mode 100644
index 8da1f0c9..00000000
--- a/src/misc/util/strsav.c
+++ /dev/null
@@ -1,157 +0,0 @@
-/*
- * Revision Control Information
- *
- * /projects/hsis/CVS/utilities/util/strsav.c,v
- * shiple
- * 1.4
- * 1995/08/30 17:37:58
- *
- */
-/* LINTLIBRARY */
-
-#include <stdio.h>
-#include "util.h"
-
-
-/*
- * util_strsav -- save a copy of a string
- */
-char *
-util_strsav(s)
-char *s;
-{
- if(s == NIL(char)) { /* added 7/95, for robustness */
- return s;
- }
- else {
- return strcpy(ALLOC(char, strlen(s)+1), s);
- }
-}
-
-/*
- * util_inttostr -- converts an integer into a string
- */
-char *
-util_inttostr(i)
- int i;
-{
- unsigned int mod, len;
- char *s;
-
- if (i == 0)
- len = 1;
- else {
- if (i < 0) {
- len = 1;
- mod = -i;
- }
- else {
- len = 0;
- mod = i;
- }
- len += (unsigned)floor(log10(mod)) + 1;
- }
-
- s = ALLOC(char, len + 1);
- sprintf(s, "%d", i);
-
- return s;
-}
-
-/*
- * util_strcat3 -- Creates a new string which is the concatenation of 3
- * strings. It is the responsibility of the caller to free this string
- * using FREE.
- */
-char *
-util_strcat3(
- char * str1,
- char * str2,
- char * str3)
-{
- char *str = ALLOC(char, strlen(str1) + strlen(str2) + strlen(str3) + 1);
-
- (void) strcpy(str, str1);
- (void) strcat(str, str2);
- (void) strcat(str, str3);
-
- return (str);
-}
-
-/*
- * util_strcat4 -- Creates a new string which is the concatenation of 4
- * strings. It is the responsibility of the caller to free this string
- * using FREE.
- */
-char *
-util_strcat4(
- char * str1,
- char * str2,
- char * str3,
- char * str4)
-{
- char *str = ALLOC(char, strlen(str1) + strlen(str2) + strlen(str3) +
- strlen(str4) + 1);
-
- (void) strcpy(str, str1);
- (void) strcat(str, str2);
- (void) strcat(str, str3);
- (void) strcat(str, str4);
-
- return (str);
-}
-
-
-#if !HAVE_STRSTR
-/**Function********************************************************************
-
- Synopsis [required]
-
- Description [optional]
-
- SideEffects [required]
-
- SeeAlso [optional]
-
-******************************************************************************/
-char *
-strstr(
- const char * s,
- const char * pat)
-{
- int len;
-
- len = strlen(pat);
- for (; *s != '\0'; ++s)
- if (*s == *pat && memcmp(s, pat, len) == 0) {
- return (char *)s; /* UGH */
- }
- return NULL;
-}
-#endif /* !HAVE_STRSTR */
-
-#if !HAVE_STRCHR
-/**Function********************************************************************
-
- Synopsis [required]
-
- Description [optional]
-
- SideEffects [required]
-
- SeeAlso [optional]
-
-******************************************************************************/
-char *
-strchr(const char * s,
- int c)
-{
- for (; *s != '\0'; s++) {
- if (*s == c) {
- return (char *)s;
- }
- }
- return NULL;
-
-}
-#endif /* !HAVE_STRCHR */
diff --git a/src/misc/util/texpand.c b/src/misc/util/texpand.c
deleted file mode 100644
index 37f71cbd..00000000
--- a/src/misc/util/texpand.c
+++ /dev/null
@@ -1,66 +0,0 @@
-/*
- * Revision Control Information
- *
- * /projects/hsis/CVS/utilities/util/texpand.c,v
- * rajeev
- * 1.3
- * 1995/08/08 22:41:36
- *
- */
-
-#include "util.h"
-
-#if HAVE_PWD_H
-# include <pwd.h>
-#endif
-
-
-char *
-util_tilde_expand(fname)
-char *fname;
-{
-#if HAVE_PWD_H
- struct passwd *userRecord;
- char username[256], *filename, *dir;
- register int i, j;
-
- filename = ALLOC(char, strlen(fname) + 256);
-
- /* Clear the return string */
- i = 0;
- filename[0] = '\0';
-
- /* Tilde? */
- if (fname[0] == '~') {
- j = 0;
- i = 1;
- while ((fname[i] != '\0') && (fname[i] != '/')) {
- username[j++] = fname[i++];
- }
- username[j] = '\0';
- dir = (char *)0;
- if (username[0] == '\0') {
- /* ~/ resolves to home directory of current user */
- userRecord = getpwuid(getuid());
- if (userRecord) dir = userRecord->pw_dir;
- } else {
- /* Special check for ~octtools */
- if (!strcmp(username,"octtools"))
- dir = getenv("OCTTOOLS");
- /* ~user/ resolves to home directory of 'user' */
- if (!dir) {
- userRecord = getpwnam(username);
- if (userRecord) dir = userRecord->pw_dir;
- }
- }
- if (dir) (void) strcat(filename, dir);
- else i = 0; /* leave fname as-is */
- } /* if tilde */
-
- /* Concantenate remaining portion of file name */
- (void) strcat(filename, fname + i);
- return filename;
-#else
- return util_strsav(fname);
-#endif
-}
diff --git a/src/misc/util/util.h b/src/misc/util/util.h
deleted file mode 100644
index 0b147347..00000000
--- a/src/misc/util/util.h
+++ /dev/null
@@ -1,331 +0,0 @@
-/**CHeaderFile*****************************************************************
-
- FileName [ util.h ]
-
- PackageName [ util ]
-
- Synopsis [ Very low-level utilities ]
-
- Description [ Includes file access, pipes, forks, time, and temporary file
- access. ]
-
- Author [ Stephen Edwards <sedwards@eecs.berkeley.edu> and many others]
-
- Copyright [Copyright (c) 1994-1996 The Regents of the Univ. of California.
- All rights reserved.
-
- Permission is hereby granted, without written agreement and without license
- or royalty fees, to use, copy, modify, and distribute this software and its
- documentation for any purpose, provided that the above copyright notice and
- the following two paragraphs appear in all copies of this software.
-
- IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY FOR
- DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT
- OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF THE UNIVERSITY OF
- CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
- THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES,
- INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
- FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS ON AN
- "AS IS" BASIS, AND THE UNIVERSITY OF CALIFORNIA HAS NO OBLIGATION TO PROVIDE
- MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.]
-
- Revision [$Id: util.h,v 1.11 1998/05/04 02:05:08 hsv Exp $]
-
-******************************************************************************/
-
-#ifndef _UTIL
-#define _UTIL
-
-////////////////////////////////////////////
-#include "leaks.h"
-////////////////////////////////////////////
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <math.h>
-
-//////////////// added by alanmi, November 22, 2001 ////////////////
-//#include <ctype.h>
-#include <time.h>
-#include <signal.h>
-
-#ifndef SIGALRM
-#define SIGALRM SIGINT
-#endif
-
-#ifndef SIGSTOP
-#define SIGSTOP SIGINT
-#endif
-
-#ifndef SIGXCPU
-#define SIGXCPU SIGINT
-#endif
-
-#ifndef SIGUSR1
-#define SIGUSR1 SIGINT
-#endif
-
-#ifndef SIGKILL
-#define SIGKILL SIGINT
-#endif
-
-#ifndef HUGE
-#define HUGE HUGE_VAL
-#endif
-
-#if defined(__STDC__)
-#define SIGNAL_FN void
-#endif
-
-#define alarm(n) ((void)0)
-#define kill(a,b) ((void)0)
-
-#define random rand
-#define srandom srand
-////////////////////////////////////////////////////////////////////
-
-
-#if HAVE_UNISTD_H
-# include <unistd.h>
-#endif
-
-#if HAVE_SYS_TYPES_H
-# include <sys/types.h>
-#endif
-
-#if HAVE_VARARGS_H
-///////////////////////////////////////
-#undef __STDC__
-# include <varargs.h>
-#define __STDC__ 1
-////////////////// alanmi Feb 03, 2001
-#endif
-
-#ifndef STDC_HEADERS
-#define STDC_HEADERS 1
-#endif
-
-#ifndef HAVE_STRCHR
-#define HAVE_STRCHR 1
-#endif
-
-#ifndef HAVE_GETENV
-#define HAVE_GETENV 1
-#endif
-
-#if STDC_HEADERS
-//# include <stdlib.h>
-# include <string.h>
-#else
-# ifdef HAVE_STRCHR
-char * strchr();
-int strcmp();
-# else
-# define strchr index
-# endif
-# ifdef HAVE_GETENV
-char * getenv();
-# endif
-#endif /* STDC_HEADERS */
-
-#if HAVE_ERRNO_H
-# include <errno.h>
-#endif
-
-/*
- * Ensure we have reasonable assert() and fail() functions
- */
-
-#ifndef HAVE_ASSERT_H
-#define HAVE_ASSERT_H 1
-#endif
-
-#if HAVE_ASSERT_H
-# include <assert.h>
-#else
-# ifdef NDEBUG
-# define assert(ex) ;
-# else
-# define assert(ex) {\
- if (! (ex)) {\
- (void) fprintf(stderr,\
- "Assertion failed: file %s, line %d\n\"%s\"\n",\
- __FILE__, __LINE__, "ex");\
- (void) fflush(stdout);\
- abort();\
- }\
-}
-# endif
-#endif
-
-#define fail(why) {\
- (void) fprintf(stderr, "Fatal error: file %s, line %d\n%s\n",\
- __FILE__, __LINE__, why);\
- (void) fflush(stdout);\
- abort();\
-}
-
-/*
- * Support for ANSI function prototypes in non-ANSI compilers
- *
- * Usage:
- * extern int foo ARGS((char *, double))
- */
-
-#ifndef ARGS
-# ifdef __STDC__
-# define ARGS(args) args
-# else
-# define ARGS(args) ()
-# endif
-#endif
-
-#ifndef NULLARGS
-# ifdef __STDC__
-# define NULLARGS (void)
-# else
-# define NULLARGS ()
-# endif
-#endif
-
-/*
- * A little support for C++ compilers
- */
-
-#ifdef __cplusplus
-# define EXTERN extern "C"
-#else
-# define EXTERN extern
-#endif
-
-/*
- * Support to define unused varibles
- */
-#if (__GNUC__ >2 || __GNUC_MINOR__ >=7) && !defined(UNUSED)
-#define UNUSED __attribute__ ((unused))
-#else
-#define UNUSED
-#endif
-
-/*
- * A neater way to define zero pointers
- *
- * Usage:
- * int * fred;
- * fred = NIL(int);
- */
-
-#define NIL(type) ((type *) 0)
-
-/*
- * Left over from SIS and Octtools:
- */
-
-//#define USE_MM
-// uncommented this line,
-// because to detect memory leaks, we need to work with malloc(), etc directly
-#define USE_MM
-
-
-
-#ifdef USE_MM
-/*
- * assumes the memory manager is libmm.a (a deprecated (?) Octtools library)
- * - allows malloc(0) or realloc(obj, 0)
- * - catches out of memory (and calls MMout_of_memory())
- * - catch free(0) and realloc(0, size) in the macros
- */
-# define ALLOC(type, num) \
- ((type *) malloc(sizeof(type) * (num)))
-# define REALLOC(type, obj, num) \
- (obj) ? ((type *) realloc((char *) obj, sizeof(type) * (num))) : \
- ((type *) malloc(sizeof(type) * (num)))
-# define FREE(obj) \
- ((obj) ? (free((char *) (obj)), (obj) = 0) : 0)
-#else
-/*
- * enforce strict semantics on the memory allocator
- */
-# define ALLOC(type, num) \
- ((type *) MMalloc((long) sizeof(type) * (long) (num)))
-# define REALLOC(type, obj, num) \
- ((type *) MMrealloc((char *) (obj), (long) sizeof(type) * (long) (num)))
-# define FREE(obj) \
- ((obj) ? (free((void *) (obj)), (obj) = 0) : 0)
-EXTERN void MMout_of_memory ARGS((long));
-EXTERN char *MMalloc ARGS((long));
-EXTERN char *MMrealloc ARGS((char *, long));
-EXTERN void MMfree ARGS((char *));
-#endif
-
-#ifndef TRUE
-# define TRUE 1
-#endif
-
-#ifndef FALSE
-# define FALSE 0
-#endif
-
-#ifndef ABS
-# define ABS(a) ((a) < 0 ? -(a) : (a))
-#endif
-
-#ifndef MAX
-# define MAX(a,b) ((a) > (b) ? (a) : (b))
-#endif
-
-#ifndef MIN
-# define MIN(a,b) ((a) < (b) ? (a) : (b))
-#endif
-
-#define ptime() util_cpu_time()
-#define print_time(t) util_print_time(t)
-
-#ifndef HUGE_VAL
-# ifndef HUGE
-# define HUGE 8.9884656743115790e+307
-# endif
-# define HUGE_VAL HUGE
-#endif
-
-#ifndef MAXINT
-# define MAXINT (1 << 30)
-#endif
-
-EXTERN void util_print_cpu_stats ARGS((FILE *));
-EXTERN long util_cpu_time ARGS((void));
-EXTERN void util_getopt_reset ARGS((void));
-EXTERN int util_getopt ARGS((int, char **, char *));
-EXTERN char *util_path_search ARGS((char *));
-EXTERN char *util_file_search ARGS((char *, char *, char *));
-EXTERN char *util_print_time ARGS((long));
-EXTERN int util_save_image ARGS((char *, char *));
-EXTERN char *util_strsav ARGS((char *));
-EXTERN char *util_inttostr ARGS((int));
-EXTERN char *util_strcat3 ARGS((char *, char *, char *));
-EXTERN char *util_strcat4 ARGS((char *, char *, char *, char *));
-EXTERN int util_do_nothing ARGS((void));
-EXTERN char *util_tilde_expand ARGS((char *));
-EXTERN char *util_tempnam ARGS((char *, char *));
-EXTERN FILE *util_tmpfile ARGS((void));
-EXTERN void util_srandom ARGS((long));
-EXTERN long util_random ARGS(());
-EXTERN int getSoftDataLimit ARGS(());
-
-/*
- * Global variables for util_getopt()
- */
-
-extern int util_optind;
-extern char *util_optarg;
-
-/**AutomaticStart*************************************************************/
-
-/*---------------------------------------------------------------------------*/
-/* Function prototypes */
-/*---------------------------------------------------------------------------*/
-
-/**AutomaticEnd***************************************************************/
-
-#endif /* _UTIL */
diff --git a/src/misc/util/util_hack.h b/src/misc/util/util_hack.h
new file mode 100644
index 00000000..71c77321
--- /dev/null
+++ b/src/misc/util/util_hack.h
@@ -0,0 +1,95 @@
+/**CFile****************************************************************
+
+ FileName [util_hack.h]
+
+ SystemName [ABC: Logic synthesis and verification system.]
+
+ PackageName [This file is used to simulate the presence of "util.h".]
+
+ Synopsis [External declarations.]
+
+ Author [Alan Mishchenko]
+
+ Affiliation [UC Berkeley]
+
+ Date [Ver. 1.0. Started - June 20, 2005.]
+
+ Revision [$Id: util_hack.h,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#ifndef __UTIL_HACK_H__
+#define __UTIL_HACK_H__
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <assert.h>
+#include <time.h>
+#include <math.h>
+
+#define EXTERN extern
+#define NIL(type) ((type *) 0)
+#define random rand
+#define srandom srand
+
+#define util_cpu_time Extra_CpuTime
+#define getSoftDataLimit Extra_GetSoftDataLimit
+#define util_getopt_reset Extra_UtilGetoptReset
+#define util_getopt Extra_UtilGetopt
+#define util_print_time Extra_UtilPrintTime
+#define util_strsav Extra_UtilStrsav
+#define util_tilde_expand Extra_UtilTildeExpand
+#define util_file_search Extra_UtilFileSearch
+#define MMoutOfMemory Extra_UtilMMoutOfMemory
+
+#define util_optarg globalUtilOptarg
+#define util_optind globalUtilOptind
+
+#ifndef ARGS
+# ifdef __STDC__
+# define ARGS(args) args
+# else
+# define ARGS(args) ()
+# endif
+#endif
+
+#ifndef ABS
+# define ABS(a) ((a) < 0 ? -(a) : (a))
+#endif
+
+#ifndef MAX
+# define MAX(a,b) ((a) > (b) ? (a) : (b))
+#endif
+
+#ifndef MIN
+# define MIN(a,b) ((a) < (b) ? (a) : (b))
+#endif
+
+#define ALLOC(type, num) ((type *) malloc(sizeof(type) * (num)))
+#define FREE(obj) ((obj) ? (free((char *) (obj)), (obj) = 0) : 0)
+#define REALLOC(type, obj, num) \
+ ((obj) ? ((type *) realloc((char *)(obj), sizeof(type) * (num))) : \
+ ((type *) malloc(sizeof(type) * (num))))
+
+extern long Extra_CpuTime();
+extern int Extra_GetSoftDataLimit();
+extern void Extra_UtilGetoptReset();
+extern int Extra_UtilGetopt( int argc, char *argv[], char *optstring );
+extern char * Extra_UtilPrintTime( long t );
+extern char * Extra_UtilStrsav( char *s );
+extern char * Extra_UtilTildeExpand( char *fname );
+extern char * Extra_UtilFileSearch( char *file, char *path, char *mode );
+
+extern char * globalUtilOptarg;
+extern int globalUtilOptind;
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/src/misc/vec/vec.h b/src/misc/vec/vec.h
index 48c4b3c3..a4bd4771 100644
--- a/src/misc/vec/vec.h
+++ b/src/misc/vec/vec.h
@@ -21,19 +21,81 @@
#ifndef __VEC_H__
#define __VEC_H__
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#ifdef _WIN32
+#define inline __inline // compatible with MS VS 6.0
+#pragma warning(disable : 4152) // warning C4152: nonstandard extension, function/data pointer conversion in expression
+#pragma warning(disable : 4244) // warning C4244: '+=' : conversion from 'int ' to 'unsigned short ', possible loss of data
+#pragma warning(disable : 4514) // warning C4514: 'Vec_StrPop' : unreferenced inline function has been removed
+#pragma warning(disable : 4710) // warning C4710: function 'Vec_PtrGrow' not inlined
+#endif
+
+#ifndef SINT64
+#define SINT64
+
+#ifdef _WIN32
+typedef signed __int64 sint64; // compatible with MS VS 6.0
+#else
+typedef long long sint64;
+#endif
+
+#endif
+
////////////////////////////////////////////////////////////////////////
/// INCLUDES ///
////////////////////////////////////////////////////////////////////////
-#ifdef _WIN32
-#define inline __inline // compatible with MS VS 6.0
+// this include should be the first one in the list
+// it is used to catch memory leaks on Windows
+#include "leaks.h"
+
+////////////////////////////////////////////////////////////////////////
+/// MACRO DEFINITIONS ///
+////////////////////////////////////////////////////////////////////////
+
+#ifndef ABS
+#define ABS(a) ((a) < 0 ? -(a) : (a))
+#endif
+
+#ifndef MAX
+#define MAX(a,b) ((a) > (b) ? (a) : (b))
+#endif
+
+#ifndef MIN
+#define MIN(a,b) ((a) < (b) ? (a) : (b))
+#endif
+
+#ifndef ALLOC
+#define ALLOC(type, num) ((type *) malloc(sizeof(type) * (num)))
+#endif
+
+#ifndef FREE
+#define FREE(obj) ((obj) ? (free((char *) (obj)), (obj) = 0) : 0)
+#endif
+
+#ifndef REALLOC
+#define REALLOC(type, obj, num) \
+ ((obj) ? ((type *) realloc((char *)(obj), sizeof(type) * (num))) : \
+ ((type *) malloc(sizeof(type) * (num))))
+#endif
+
+#ifndef PRT
+#define PRT(a,t) printf("%s = ", (a)); printf("%6.2f sec\n", (float)(t)/(float)(CLOCKS_PER_SEC))
+#endif
+
+#ifndef PRTP
+#define PRTP(a,t,T) printf("%s = ", (a)); printf("%6.2f sec (%6.2f %%)\n", (float)(t)/(float)(CLOCKS_PER_SEC), (T)? 100.0*(t)/(T) : 0.0)
#endif
-#include "vecFan.h"
#include "vecInt.h"
+#include "vecFlt.h"
#include "vecStr.h"
#include "vecPtr.h"
#include "vecVec.h"
+#include "vecAtt.h"
////////////////////////////////////////////////////////////////////////
/// PARAMETERS ///
@@ -44,16 +106,16 @@
////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////
-/// MACRO DEFITIONS ///
-////////////////////////////////////////////////////////////////////////
-
-////////////////////////////////////////////////////////////////////////
/// FUNCTION DECLARATIONS ///
////////////////////////////////////////////////////////////////////////
+#ifdef __cplusplus
+}
+#endif
+
+#endif
+
////////////////////////////////////////////////////////////////////////
/// END OF FILE ///
////////////////////////////////////////////////////////////////////////
-#endif
-
diff --git a/src/abc8/vec2/vecAtt.h b/src/misc/vec/vecAtt.h
index da7a8445..da7a8445 100644
--- a/src/abc8/vec2/vecAtt.h
+++ b/src/misc/vec/vecAtt.h
diff --git a/src/misc/vec/vecFan.h b/src/misc/vec/vecFan.h
deleted file mode 100644
index 08d1d734..00000000
--- a/src/misc/vec/vecFan.h
+++ /dev/null
@@ -1,374 +0,0 @@
-/**CFile****************************************************************
-
- FileName [vecFan.h]
-
- SystemName [ABC: Logic synthesis and verification system.]
-
- PackageName [Resizable arrays.]
-
- Synopsis [Resizable arrays of integers (fanins/fanouts) with memory management.]
-
- Author [Alan Mishchenko]
-
- Affiliation [UC Berkeley]
-
- Date [Ver. 1.0. Started - June 20, 2005.]
-
- Revision [$Id: vecFan.h,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
-
-***********************************************************************/
-
-#ifndef __VEC_FAN_H__
-#define __VEC_FAN_H__
-
-////////////////////////////////////////////////////////////////////////
-/// INCLUDES ///
-////////////////////////////////////////////////////////////////////////
-
-#include <stdio.h>
-#include "extra.h"
-
-////////////////////////////////////////////////////////////////////////
-/// PARAMETERS ///
-////////////////////////////////////////////////////////////////////////
-
-////////////////////////////////////////////////////////////////////////
-/// BASIC TYPES ///
-////////////////////////////////////////////////////////////////////////
-
-typedef struct Abc_Fan_t_ Abc_Fan_t;
-struct Abc_Fan_t_ // 1 word
-{
- unsigned iFan : 24; // the ID of the object
- unsigned nLats : 7; // the number of latches (up to 31)
- unsigned fCompl : 1; // the complemented attribute
-};
-
-typedef struct Vec_Fan_t_ Vec_Fan_t;
-struct Vec_Fan_t_
-{
- int nCap;
- int nSize;
- Abc_Fan_t * pArray;
-};
-
-////////////////////////////////////////////////////////////////////////
-/// MACRO DEFITIONS ///
-////////////////////////////////////////////////////////////////////////
-
-#define Vec_FanForEachEntry( vVec, Entry, i ) \
- for ( i = 0; (i < Vec_FanSize(vVec)) && (((Entry) = Vec_FanEntry(vVec, i)), 1); i++ )
-
-////////////////////////////////////////////////////////////////////////
-/// FUNCTION DEFITIONS ///
-////////////////////////////////////////////////////////////////////////
-
-/**Function*************************************************************
-
- Synopsis [Converts an integer into the simple fanin structure.]
-
- Description []
-
- SideEffects []
-
- SeeAlso []
-
-***********************************************************************/
-static inline Abc_Fan_t Vec_Int2Fan( int iFan )
-{
- return *((Abc_Fan_t *)&iFan);
-}
-
-/**Function*************************************************************
-
- Synopsis []
-
- Description []
-
- SideEffects []
-
- SeeAlso []
-
-***********************************************************************/
-static inline Abc_Fan_t * Vec_FanArray( Vec_Fan_t * p )
-{
- return p->pArray;
-}
-
-/**Function*************************************************************
-
- Synopsis []
-
- Description []
-
- SideEffects []
-
- SeeAlso []
-
-***********************************************************************/
-static inline int Vec_FanSize( Vec_Fan_t * p )
-{
- return p->nSize;
-}
-
-/**Function*************************************************************
-
- Synopsis []
-
- Description []
-
- SideEffects []
-
- SeeAlso []
-
-***********************************************************************/
-static inline Abc_Fan_t Vec_FanEntry( Vec_Fan_t * p, int i )
-{
- assert( i >= 0 && i < p->nSize );
- return p->pArray[i];
-}
-
-/**Function*************************************************************
-
- Synopsis []
-
- Description []
-
- SideEffects []
-
- SeeAlso []
-
-***********************************************************************/
-static inline void Vec_FanWriteEntry( Vec_Fan_t * p, int i, Abc_Fan_t Entry )
-{
- assert( i >= 0 && i < p->nSize );
- p->pArray[i] = Entry;
-}
-
-/**Function*************************************************************
-
- Synopsis []
-
- Description []
-
- SideEffects []
-
- SeeAlso []
-
-***********************************************************************/
-static inline Abc_Fan_t Vec_FanEntryLast( Vec_Fan_t * p )
-{
- return p->pArray[p->nSize-1];
-}
-
-/**Function*************************************************************
-
- Synopsis []
-
- Description []
-
- SideEffects []
-
- SeeAlso []
-
-***********************************************************************/
-static inline void Vec_FanShrink( Vec_Fan_t * p, int nSizeNew )
-{
- assert( p->nSize >= nSizeNew );
- p->nSize = nSizeNew;
-}
-
-/**Function*************************************************************
-
- Synopsis []
-
- Description []
-
- SideEffects []
-
- SeeAlso []
-
-***********************************************************************/
-static inline void Vec_FanClear( Vec_Fan_t * p )
-{
- p->nSize = 0;
-}
-
-/**Function*************************************************************
-
- Synopsis []
-
- Description []
-
- SideEffects []
-
- SeeAlso []
-
-***********************************************************************/
-static inline void Vec_FanPush( Extra_MmStep_t * pMemMan, Vec_Fan_t * p, Abc_Fan_t Entry )
-{
- if ( p->nSize == p->nCap )
- {
- Abc_Fan_t * pArray;
- int i;
-
- if ( p->nSize == 0 )
- p->nCap = 1;
- pArray = (Abc_Fan_t *)Extra_MmStepEntryFetch( pMemMan, p->nCap * 8 );
-// pArray = ALLOC( int, p->nCap * 2 );
- if ( p->pArray )
- {
- for ( i = 0; i < p->nSize; i++ )
- pArray[i] = p->pArray[i];
- Extra_MmStepEntryRecycle( pMemMan, (char *)p->pArray, p->nCap * 4 );
-// free( p->pArray );
- }
- p->nCap *= 2;
- p->pArray = pArray;
- }
- p->pArray[p->nSize++] = Entry;
-}
-
-/**Function*************************************************************
-
- Synopsis [Returns the last entry and removes it from the list.]
-
- Description []
-
- SideEffects []
-
- SeeAlso []
-
-***********************************************************************/
-static inline Abc_Fan_t Vec_FanPop( Vec_Fan_t * p )
-{
- assert( p->nSize > 0 );
- return p->pArray[--p->nSize];
-}
-
-/**Function*************************************************************
-
- Synopsis [Find entry.]
-
- Description []
-
- SideEffects []
-
- SeeAlso []
-
-***********************************************************************/
-static inline int Vec_FanFindEntry( Vec_Fan_t * p, unsigned iFan )
-{
- int i;
- for ( i = 0; i < p->nSize; i++ )
- if ( p->pArray[i].iFan == iFan )
- return i;
- return -1;
-}
-
-/**Function*************************************************************
-
- Synopsis [Deletes entry.]
-
- Description []
-
- SideEffects []
-
- SeeAlso []
-
-***********************************************************************/
-static inline int Vec_FanDeleteEntry( Vec_Fan_t * p, unsigned iFan )
-{
-/*
- int i, k, fFound = 0;
- for ( i = k = 0; i < p->nSize; i++ )
- {
- if ( p->pArray[i].iFan == iFan )
- fFound = 1;
- else
- p->pArray[k++] = p->pArray[i];
- }
- p->nSize = k;
- return fFound;
-*/
- int i;
- for ( i = 0; i < p->nSize; i++ )
- if ( p->pArray[i].iFan == iFan )
- break;
- if ( i == p->nSize )
- return 0;
- for ( i++; i < p->nSize; i++ )
- p->pArray[i-1] = p->pArray[i];
- p->nSize--;
- return 1;
-}
-
-/**Function*************************************************************
-
- Synopsis [Comparison procedure for two integers.]
-
- Description []
-
- SideEffects []
-
- SeeAlso []
-
-***********************************************************************/
-static inline int Vec_FanSortCompare1( int * pp1, int * pp2 )
-{
- // for some reason commenting out lines (as shown) led to crashing of the release version
- if ( *pp1 < *pp2 )
- return -1;
- if ( *pp1 > *pp2 ) //
- return 1;
- return 0; //
-}
-
-/**Function*************************************************************
-
- Synopsis [Comparison procedure for two integers.]
-
- Description []
-
- SideEffects []
-
- SeeAlso []
-
-***********************************************************************/
-static inline int Vec_FanSortCompare2( int * pp1, int * pp2 )
-{
- // for some reason commenting out lines (as shown) led to crashing of the release version
- if ( *pp1 > *pp2 )
- return -1;
- if ( *pp1 < *pp2 ) //
- return 1;
- return 0; //
-}
-
-/**Function*************************************************************
-
- Synopsis [Sorting the entries by their integer value.]
-
- Description []
-
- SideEffects []
-
- SeeAlso []
-
-***********************************************************************/
-static inline void Vec_FanSort( Vec_Fan_t * p, int fReverse )
-{
- if ( fReverse )
- qsort( (void *)p->pArray, p->nSize, sizeof(int),
- (int (*)(const void *, const void *)) Vec_FanSortCompare2 );
- else
- qsort( (void *)p->pArray, p->nSize, sizeof(int),
- (int (*)(const void *, const void *)) Vec_FanSortCompare1 );
-}
-
-////////////////////////////////////////////////////////////////////////
-/// END OF FILE ///
-////////////////////////////////////////////////////////////////////////
-
-#endif
-
diff --git a/src/abc8/vec2/vecFlt.h b/src/misc/vec/vecFlt.h
index 6b36ce84..6b36ce84 100644
--- a/src/abc8/vec2/vecFlt.h
+++ b/src/misc/vec/vecFlt.h
diff --git a/src/misc/vec/vecInt.h b/src/misc/vec/vecInt.h
index 7556dd87..082ebe70 100644
--- a/src/misc/vec/vecInt.h
+++ b/src/misc/vec/vecInt.h
@@ -26,7 +26,6 @@
////////////////////////////////////////////////////////////////////////
#include <stdio.h>
-#include "extra.h"
////////////////////////////////////////////////////////////////////////
/// PARAMETERS ///
@@ -45,16 +44,20 @@ struct Vec_Int_t_
};
////////////////////////////////////////////////////////////////////////
-/// MACRO DEFITIONS ///
+/// MACRO DEFINITIONS ///
////////////////////////////////////////////////////////////////////////
#define Vec_IntForEachEntry( vVec, Entry, i ) \
for ( i = 0; (i < Vec_IntSize(vVec)) && (((Entry) = Vec_IntEntry(vVec, i)), 1); i++ )
#define Vec_IntForEachEntryStart( vVec, Entry, i, Start ) \
for ( i = Start; (i < Vec_IntSize(vVec)) && (((Entry) = Vec_IntEntry(vVec, i)), 1); i++ )
+#define Vec_IntForEachEntryStartStop( vVec, Entry, i, Start, Stop ) \
+ for ( i = Start; (i < Stop) && (((Entry) = Vec_IntEntry(vVec, i)), 1); i++ )
+#define Vec_IntForEachEntryReverse( vVec, pEntry, i ) \
+ for ( i = Vec_IntSize(vVec) - 1; (i >= 0) && (((pEntry) = Vec_IntEntry(vVec, i)), 1); i-- )
////////////////////////////////////////////////////////////////////////
-/// FUNCTION DEFITIONS ///
+/// FUNCTION DEFINITIONS ///
////////////////////////////////////////////////////////////////////////
/**Function*************************************************************
@@ -102,6 +105,28 @@ static inline Vec_Int_t * Vec_IntStart( int nSize )
/**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 []
@@ -159,7 +184,7 @@ static inline Vec_Int_t * Vec_IntDup( Vec_Int_t * pVec )
Vec_Int_t * p;
p = ALLOC( Vec_Int_t, 1 );
p->nSize = pVec->nSize;
- p->nCap = pVec->nCap;
+ p->nCap = pVec->nSize;
p->pArray = p->nCap? ALLOC( int, p->nCap ) : NULL;
memcpy( p->pArray, pVec->pArray, sizeof(int) * pVec->nSize );
return p;
@@ -303,8 +328,26 @@ static inline void Vec_IntWriteEntry( Vec_Int_t * p, int i, int Entry )
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];
}
@@ -324,6 +367,7 @@ static inline void Vec_IntGrow( Vec_Int_t * p, int nCapMin )
if ( p->nCap >= nCapMin )
return;
p->pArray = REALLOC( int, p->pArray, nCapMin );
+ assert( p->pArray );
p->nCap = nCapMin;
}
@@ -436,6 +480,33 @@ static inline void Vec_IntPush( Vec_Int_t * p, int Entry )
SeeAlso []
***********************************************************************/
+static inline void Vec_IntPushFirst( Vec_Int_t * p, int Entry )
+{
+ int i;
+ if ( p->nSize == p->nCap )
+ {
+ if ( p->nCap < 16 )
+ Vec_IntGrow( p, 16 );
+ else
+ Vec_IntGrow( p, 2 * p->nCap );
+ }
+ p->nSize++;
+ for ( i = p->nSize - 1; i >= 1; i-- )
+ p->pArray[i] = p->pArray[i-1];
+ p->pArray[0] = Entry;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Inserts the entry while preserving the increasing order.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
static inline void Vec_IntPushOrder( Vec_Int_t * p, int Entry )
{
int i;
@@ -457,6 +528,27 @@ static inline void Vec_IntPushOrder( Vec_Int_t * p, int Entry )
/**Function*************************************************************
+ Synopsis [Inserts the entry while preserving the increasing order.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+static inline int Vec_IntPushUniqueOrder( Vec_Int_t * p, int Entry )
+{
+ int i;
+ for ( i = 0; i < p->nSize; i++ )
+ if ( p->pArray[i] == Entry )
+ return 1;
+ Vec_IntPushOrder( p, Entry );
+ return 0;
+}
+
+/**Function*************************************************************
+
Synopsis []
Description []
@@ -478,6 +570,31 @@ static inline int Vec_IntPushUnique( Vec_Int_t * p, int Entry )
/**Function*************************************************************
+ Synopsis [Returns the pointer to the next nWords entries in the vector.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+static inline unsigned * Vec_IntFetch( Vec_Int_t * p, int nWords )
+{
+ if ( nWords == 0 )
+ return NULL;
+ assert( nWords > 0 );
+ p->nSize += nWords;
+ if ( p->nSize > p->nCap )
+ {
+// Vec_IntGrow( p, 2 * p->nSize );
+ return NULL;
+ }
+ return ((unsigned *)p->pArray) + p->nSize - nWords;
+}
+
+/**Function*************************************************************
+
Synopsis [Returns the last entry and removes it from the list.]
Description []
@@ -495,6 +612,26 @@ static inline int Vec_IntPop( Vec_Int_t * p )
/**Function*************************************************************
+ Synopsis [Find entry.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+static inline int Vec_IntFind( Vec_Int_t * p, int Entry )
+{
+ int i;
+ for ( i = 0; i < p->nSize; i++ )
+ if ( p->pArray[i] == Entry )
+ return i;
+ return -1;
+}
+
+/**Function*************************************************************
+
Synopsis []
Description []
@@ -504,16 +641,19 @@ static inline int Vec_IntPop( Vec_Int_t * p )
SeeAlso []
***********************************************************************/
-static inline void Vec_IntRemove( Vec_Int_t * p, int Entry )
+static inline int Vec_IntRemove( Vec_Int_t * p, int Entry )
{
int i;
for ( i = 0; i < p->nSize; i++ )
if ( p->pArray[i] == Entry )
break;
+ if ( i == p->nSize )
+ return 0;
assert( i < p->nSize );
for ( i++; i < p->nSize; i++ )
p->pArray[i-1] = p->pArray[i];
p->nSize--;
+ return 1;
}
/**Function*************************************************************
@@ -617,9 +757,78 @@ static inline void Vec_IntSortUnsigned( Vec_Int_t * p )
(int (*)(const void *, const void *)) Vec_IntSortCompareUnsigned );
}
+/**Function*************************************************************
+
+ Synopsis [Returns the number of common entries.]
+
+ Description [Assumes that the vectors are sorted in the increasing order.]
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+static inline int Vec_IntTwoCountCommon( Vec_Int_t * vArr1, Vec_Int_t * vArr2 )
+{
+ int * pBeg1 = vArr1->pArray;
+ int * pBeg2 = vArr2->pArray;
+ int * pEnd1 = vArr1->pArray + vArr1->nSize;
+ int * pEnd2 = vArr2->pArray + vArr2->nSize;
+ int Counter = 0;
+ while ( pBeg1 < pEnd1 && pBeg2 < pEnd2 )
+ {
+ if ( *pBeg1 == *pBeg2 )
+ pBeg1++, pBeg2++, Counter++;
+ else if ( *pBeg1 < *pBeg2 )
+ pBeg1++;
+ else
+ pBeg2++;
+ }
+ return Counter;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Returns the result of merging the two vectors.]
+
+ Description [Assumes that the vectors are sorted in the increasing order.]
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+static inline Vec_Int_t * Vec_IntTwoMerge( Vec_Int_t * vArr1, Vec_Int_t * vArr2 )
+{
+ Vec_Int_t * vArr = Vec_IntAlloc( vArr1->nSize + vArr2->nSize );
+ int * pBeg = vArr->pArray;
+ int * pBeg1 = vArr1->pArray;
+ int * pBeg2 = vArr2->pArray;
+ int * pEnd1 = vArr1->pArray + vArr1->nSize;
+ int * pEnd2 = vArr2->pArray + vArr2->nSize;
+ while ( pBeg1 < pEnd1 && pBeg2 < pEnd2 )
+ {
+ if ( *pBeg1 == *pBeg2 )
+ *pBeg++ = *pBeg1++, pBeg2++;
+ else if ( *pBeg1 < *pBeg2 )
+ *pBeg++ = *pBeg1++;
+ else
+ *pBeg++ = *pBeg2++;
+ }
+ while ( pBeg1 < pEnd1 )
+ *pBeg++ = *pBeg1++;
+ while ( pBeg2 < pEnd2 )
+ *pBeg++ = *pBeg2++;
+ vArr->nSize = pBeg - vArr->pArray;
+ assert( vArr->nSize <= vArr->nCap );
+ assert( vArr->nSize >= vArr1->nSize );
+ assert( vArr->nSize >= vArr2->nSize );
+ return vArr;
+}
+
+#endif
+
////////////////////////////////////////////////////////////////////////
/// END OF FILE ///
////////////////////////////////////////////////////////////////////////
-#endif
-
diff --git a/src/misc/vec/vecPtr.h b/src/misc/vec/vecPtr.h
index b1776441..9595bc72 100644
--- a/src/misc/vec/vecPtr.h
+++ b/src/misc/vec/vecPtr.h
@@ -26,7 +26,6 @@
////////////////////////////////////////////////////////////////////////
#include <stdio.h>
-#include "extra.h"
////////////////////////////////////////////////////////////////////////
/// PARAMETERS ///
@@ -45,7 +44,7 @@ struct Vec_Ptr_t_
};
////////////////////////////////////////////////////////////////////////
-/// MACRO DEFITIONS ///
+/// MACRO DEFINITIONS ///
////////////////////////////////////////////////////////////////////////
// iterators through entries
@@ -53,11 +52,15 @@ struct Vec_Ptr_t_
for ( i = 0; (i < Vec_PtrSize(vVec)) && (((pEntry) = Vec_PtrEntry(vVec, i)), 1); i++ )
#define Vec_PtrForEachEntryStart( vVec, pEntry, i, Start ) \
for ( i = Start; (i < Vec_PtrSize(vVec)) && (((pEntry) = Vec_PtrEntry(vVec, i)), 1); i++ )
+#define Vec_PtrForEachEntryStop( vVec, pEntry, i, Stop ) \
+ for ( i = 0; (i < Stop) && (((pEntry) = Vec_PtrEntry(vVec, i)), 1); i++ )
+#define Vec_PtrForEachEntryStartStop( vVec, pEntry, i, Start, Stop ) \
+ for ( i = Start; (i < Stop) && (((pEntry) = Vec_PtrEntry(vVec, i)), 1); i++ )
#define Vec_PtrForEachEntryReverse( vVec, pEntry, i ) \
for ( i = Vec_PtrSize(vVec) - 1; (i >= 0) && (((pEntry) = Vec_PtrEntry(vVec, i)), 1); i-- )
////////////////////////////////////////////////////////////////////////
-/// FUNCTION DEFITIONS ///
+/// FUNCTION DEFINITIONS ///
////////////////////////////////////////////////////////////////////////
/**Function*************************************************************
@@ -289,6 +292,23 @@ static inline void * Vec_PtrEntry( Vec_Ptr_t * p, int i )
SeeAlso []
***********************************************************************/
+static inline void ** Vec_PtrEntryP( Vec_Ptr_t * p, int i )
+{
+ assert( i >= 0 && i < p->nSize );
+ return p->pArray + i;
+}
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
static inline void Vec_PtrWriteEntry( Vec_Ptr_t * p, int i, void * Entry )
{
assert( i >= 0 && i < p->nSize );
@@ -308,6 +328,7 @@ static inline void Vec_PtrWriteEntry( Vec_Ptr_t * p, int i, void * Entry )
***********************************************************************/
static inline void * Vec_PtrEntryLast( Vec_Ptr_t * p )
{
+ assert( p->nSize > 0 );
return p->pArray[p->nSize-1];
}
@@ -366,7 +387,11 @@ static inline void Vec_PtrFillExtra( Vec_Ptr_t * p, int nSize, void * Entry )
int i;
if ( p->nSize >= nSize )
return;
- Vec_PtrGrow( p, nSize );
+ assert( p->nSize < nSize );
+ if ( 2 * p->nSize > nSize )
+ Vec_PtrGrow( p, 2 * nSize );
+ else
+ Vec_PtrGrow( p, nSize );
for ( i = p->nSize; i < nSize; i++ )
p->pArray[i] = Entry;
p->nSize = nSize;
@@ -374,6 +399,40 @@ static inline void Vec_PtrFillExtra( Vec_Ptr_t * p, int nSize, void * Entry )
/**Function*************************************************************
+ Synopsis [Returns the entry even if the place not exist.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+static inline void * Vec_PtrGetEntry( Vec_Ptr_t * p, int i )
+{
+ Vec_PtrFillExtra( p, i + 1, NULL );
+ return Vec_PtrEntry( p, i );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Inserts the entry even if the place does not exist.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+static inline void Vec_PtrSetEntry( Vec_Ptr_t * p, int i, void * Entry )
+{
+ Vec_PtrFillExtra( p, i + 1, NULL );
+ Vec_PtrWriteEntry( p, i, Entry );
+}
+
+/**Function*************************************************************
+
Synopsis []
Description []
@@ -407,6 +466,25 @@ static inline void Vec_PtrClear( Vec_Ptr_t * p )
/**Function*************************************************************
+ Synopsis [Copies the interger array.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+static inline void Vec_PtrCopy( Vec_Ptr_t * pDest, Vec_Ptr_t * pSour )
+{
+ pDest->nSize = 0;
+ Vec_PtrGrow( pDest, pSour->nSize );
+ memcpy( pDest->pArray, pSour->pArray, sizeof(void *) * pSour->nSize );
+ pDest->nSize = pSour->nSize;
+}
+
+/**Function*************************************************************
+
Synopsis []
Description []
@@ -468,6 +546,26 @@ static inline void * Vec_PtrPop( Vec_Ptr_t * p )
/**Function*************************************************************
+ Synopsis [Find entry.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+static inline int Vec_PtrFind( Vec_Ptr_t * p, void * Entry )
+{
+ int i;
+ for ( i = 0; i < p->nSize; i++ )
+ if ( p->pArray[i] == Entry )
+ return i;
+ return -1;
+}
+
+/**Function*************************************************************
+
Synopsis []
Description []
@@ -480,10 +578,18 @@ static inline void * Vec_PtrPop( Vec_Ptr_t * p )
static inline void Vec_PtrRemove( Vec_Ptr_t * p, void * Entry )
{
int i;
+ // delete assuming that it is closer to the end
+ for ( i = p->nSize - 1; i >= 0; i-- )
+ if ( p->pArray[i] == Entry )
+ break;
+ assert( i >= 0 );
+/*
+ // delete assuming that it is closer to the beginning
for ( i = 0; i < p->nSize; i++ )
if ( p->pArray[i] == Entry )
break;
assert( i < p->nSize );
+*/
for ( i++; i < p->nSize; i++ )
p->pArray[i-1] = p->pArray[i];
p->nSize--;
@@ -521,14 +627,186 @@ static inline void Vec_PtrReorder( Vec_Ptr_t * p, int nItems )
***********************************************************************/
static inline void Vec_PtrSort( Vec_Ptr_t * p, int (*Vec_PtrSortCompare)() )
{
+ if ( p->nSize < 2 )
+ return;
qsort( (void *)p->pArray, p->nSize, sizeof(void *),
(int (*)(const void *, const void *)) Vec_PtrSortCompare );
}
+/**Function*************************************************************
+
+ Synopsis [Sorting the entries by their integer value.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+static inline void Vec_PtrUniqify( Vec_Ptr_t * p, int (*Vec_PtrSortCompare)() )
+{
+ int i, k;
+ if ( p->nSize < 2 )
+ return;
+ qsort( (void *)p->pArray, p->nSize, sizeof(void *),
+ (int (*)(const void *, const void *)) Vec_PtrSortCompare );
+ for ( i = k = 1; i < p->nSize; i++ )
+ if ( p->pArray[i] != p->pArray[i-1] )
+ p->pArray[k++] = p->pArray[i];
+ p->nSize = k;
+}
+
+
+
+/**Function*************************************************************
+
+ Synopsis [Allocates the array of simulation info.]
+
+ Description [Allocates the array containing given number of entries,
+ each of which contains given number of unsigned words of simulation data.
+ The resulting array can be freed using regular procedure Vec_PtrFree().
+ It is the responsibility of the user to ensure this array is never grown.]
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+static inline Vec_Ptr_t * Vec_PtrAllocSimInfo( int nEntries, int nWords )
+{
+ void ** pMemory;
+ unsigned * pInfo;
+ int i;
+ pMemory = (void **)ALLOC( char, (sizeof(void *) + sizeof(unsigned) * nWords) * nEntries );
+ pInfo = (unsigned *)(pMemory + nEntries);
+ for ( i = 0; i < nEntries; i++ )
+ pMemory[i] = pInfo + i * nWords;
+ return Vec_PtrAllocArray( pMemory, nEntries );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Cleans simulation info of each entry beginning with iWord.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+static inline void Vec_PtrCleanSimInfo( Vec_Ptr_t * vInfo, int iWord, int nWords )
+{
+ int i;
+ for ( i = 0; i < vInfo->nSize; i++ )
+ memset( (char*)Vec_PtrEntry(vInfo,i) + 4*iWord, 0, 4*(nWords-iWord) );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Resizes the array of simulation info.]
+
+ Description [Doubles the number of objects for which siminfo is allocated.]
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+static inline void Vec_PtrDoubleSimInfo( Vec_Ptr_t * vInfo )
+{
+ Vec_Ptr_t * vInfoNew;
+ int nWords;
+ assert( Vec_PtrSize(vInfo) > 1 );
+ // get the new array
+ nWords = (unsigned *)Vec_PtrEntry(vInfo,1) - (unsigned *)Vec_PtrEntry(vInfo,0);
+ vInfoNew = Vec_PtrAllocSimInfo( 2*Vec_PtrSize(vInfo), nWords );
+ // copy the simulation info
+ memcpy( Vec_PtrEntry(vInfoNew,0), Vec_PtrEntry(vInfo,0), Vec_PtrSize(vInfo) * nWords * 4 );
+ // replace the array
+ free( vInfo->pArray );
+ vInfo->pArray = vInfoNew->pArray;
+ vInfo->nSize *= 2;
+ vInfo->nCap *= 2;
+ // free the old array
+ vInfoNew->pArray = NULL;
+ free( vInfoNew );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Resizes the array of simulation info.]
+
+ Description [Doubles the number of simulation patterns stored for each object.]
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+static inline void Vec_PtrReallocSimInfo( Vec_Ptr_t * vInfo )
+{
+ Vec_Ptr_t * vInfoNew;
+ int nWords, i;
+ assert( Vec_PtrSize(vInfo) > 1 );
+ // get the new array
+ nWords = (unsigned *)Vec_PtrEntry(vInfo,1) - (unsigned *)Vec_PtrEntry(vInfo,0);
+ vInfoNew = Vec_PtrAllocSimInfo( Vec_PtrSize(vInfo), 2*nWords );
+ // copy the simulation info
+ for ( i = 0; i < vInfo->nSize; i++ )
+ memcpy( Vec_PtrEntry(vInfoNew,i), Vec_PtrEntry(vInfo,i), nWords * 4 );
+ // replace the array
+ free( vInfo->pArray );
+ vInfo->pArray = vInfoNew->pArray;
+ // free the old array
+ vInfoNew->pArray = NULL;
+ free( vInfoNew );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Allocates the array of truth tables for the given number of vars.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+static inline Vec_Ptr_t * Vec_PtrAllocTruthTables( int nVars )
+{
+ Vec_Ptr_t * p;
+ unsigned Masks[5] = { 0xAAAAAAAA, 0xCCCCCCCC, 0xF0F0F0F0, 0xFF00FF00, 0xFFFF0000 };
+ unsigned * pTruth;
+ int i, k, nWords;
+ nWords = (nVars <= 5 ? 1 : (1 << (nVars - 5)));
+ p = Vec_PtrAllocSimInfo( nVars, nWords );
+ for ( i = 0; i < nVars; i++ )
+ {
+ pTruth = (unsigned *)p->pArray[i];
+ if ( i < 5 )
+ {
+ for ( k = 0; k < nWords; k++ )
+ pTruth[k] = Masks[i];
+ }
+ else
+ {
+ for ( k = 0; k < nWords; k++ )
+ if ( k & (1 << (i-5)) )
+ pTruth[k] = ~(unsigned)0;
+ else
+ pTruth[k] = 0;
+ }
+ }
+ return p;
+}
+
+#endif
+
////////////////////////////////////////////////////////////////////////
/// END OF FILE ///
////////////////////////////////////////////////////////////////////////
-#endif
-
diff --git a/src/misc/vec/vecStr.h b/src/misc/vec/vecStr.h
index 311bda91..47367bc6 100644
--- a/src/misc/vec/vecStr.h
+++ b/src/misc/vec/vecStr.h
@@ -26,7 +26,6 @@
////////////////////////////////////////////////////////////////////////
#include <stdio.h>
-#include "extra.h"
////////////////////////////////////////////////////////////////////////
/// PARAMETERS ///
@@ -45,14 +44,14 @@ struct Vec_Str_t_
};
////////////////////////////////////////////////////////////////////////
-/// MACRO DEFITIONS ///
+/// MACRO DEFINITIONS ///
////////////////////////////////////////////////////////////////////////
#define Vec_StrForEachEntry( vVec, Entry, i ) \
for ( i = 0; (i < Vec_StrSize(vVec)) && (((Entry) = Vec_StrEntry(vVec, i)), 1); i++ )
////////////////////////////////////////////////////////////////////////
-/// FUNCTION DEFITIONS ///
+/// FUNCTION DEFINITIONS ///
////////////////////////////////////////////////////////////////////////
/**Function*************************************************************
@@ -303,6 +302,7 @@ static inline void Vec_StrWriteEntry( Vec_Str_t * p, int i, char Entry )
***********************************************************************/
static inline char Vec_StrEntryLast( Vec_Str_t * p )
{
+ assert( p->nSize > 0 );
return p->pArray[p->nSize-1];
}
@@ -401,6 +401,80 @@ static inline void Vec_StrPush( Vec_Str_t * p, char Entry )
p->pArray[p->nSize++] = Entry;
}
+/**Function********************************************************************
+
+ Synopsis [Finds the smallest integer larger of equal than the logarithm.]
+
+ Description [Returns [Log10(Num)].]
+
+ SideEffects []
+
+ SeeAlso []
+
+******************************************************************************/
+static inline int Vec_StrBase10Log( unsigned Num )
+{
+ int Res;
+ assert( Num >= 0 );
+ if ( Num == 0 ) return 0;
+ if ( Num == 1 ) return 1;
+ for ( Res = 0, Num--; Num; Num /= 10, Res++ );
+ return Res;
+} /* end of Extra_Base2Log */
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+static inline void Vec_StrPrintNum( Vec_Str_t * p, int Num )
+{
+ int i, nDigits;
+ if ( Num < 0 )
+ {
+ Vec_StrPush( p, '-' );
+ Num = -Num;
+ }
+ if ( Num < 10 )
+ {
+ Vec_StrPush( p, (char)('0' + Num) );
+ return;
+ }
+ nDigits = Vec_StrBase10Log( Num );
+ Vec_StrGrow( p, p->nSize + nDigits );
+ for ( i = nDigits - 1; i >= 0; i-- )
+ {
+ Vec_StrWriteEntry( p, p->nSize + i, (char)('0' + Num % 10) );
+ Num /= 10;
+ }
+ assert( Num == 0 );
+ p->nSize += nDigits;
+}
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+static inline void Vec_StrPrintStr( Vec_Str_t * p, char * pStr )
+{
+ int i, Length = strlen(pStr);
+ for ( i = 0; i < Length; i++ )
+ Vec_StrPush( p, pStr[i] );
+}
+
/**Function*************************************************************
Synopsis [Appends the string to the char vector.]
@@ -494,16 +568,16 @@ static inline int Vec_StrSortCompare2( char * pp1, char * pp2 )
static inline void Vec_StrSort( Vec_Str_t * p, int fReverse )
{
if ( fReverse )
- qsort( (void *)p->pArray, p->nSize, sizeof(int),
+ qsort( (void *)p->pArray, p->nSize, sizeof(char),
(int (*)(const void *, const void *)) Vec_StrSortCompare2 );
else
- qsort( (void *)p->pArray, p->nSize, sizeof(int),
+ qsort( (void *)p->pArray, p->nSize, sizeof(char),
(int (*)(const void *, const void *)) Vec_StrSortCompare1 );
}
+#endif
+
////////////////////////////////////////////////////////////////////////
/// END OF FILE ///
////////////////////////////////////////////////////////////////////////
-#endif
-
diff --git a/src/misc/vec/vecVec.h b/src/misc/vec/vecVec.h
index 0ad5fd1e..55ffdf4f 100644
--- a/src/misc/vec/vecVec.h
+++ b/src/misc/vec/vecVec.h
@@ -26,7 +26,6 @@
////////////////////////////////////////////////////////////////////////
#include <stdio.h>
-#include "extra.h"
////////////////////////////////////////////////////////////////////////
/// PARAMETERS ///
@@ -45,23 +44,27 @@ struct Vec_Vec_t_
};
////////////////////////////////////////////////////////////////////////
-/// MACRO DEFITIONS ///
+/// MACRO DEFINITIONS ///
////////////////////////////////////////////////////////////////////////
// iterators through levels
#define Vec_VecForEachLevel( vGlob, vVec, i ) \
- for ( i = 0; (i < Vec_VecSize(vGlob)) && (((vVec) = Vec_VecEntry(vGlob, i)), 1); i++ )
+ for ( i = 0; (i < Vec_VecSize(vGlob)) && (((vVec) = (Vec_Ptr_t*)Vec_VecEntry(vGlob, i)), 1); i++ )
#define Vec_VecForEachLevelStart( vGlob, vVec, i, LevelStart ) \
- for ( i = LevelStart; (i < Vec_VecSize(vGlob)) && (((vVec) = Vec_VecEntry(vGlob, i)), 1); i++ )
+ for ( i = LevelStart; (i < Vec_VecSize(vGlob)) && (((vVec) = (Vec_Ptr_t*)Vec_VecEntry(vGlob, i)), 1); i++ )
#define Vec_VecForEachLevelStartStop( vGlob, vVec, i, LevelStart, LevelStop ) \
- for ( i = LevelStart; (i <= LevelStop) && (((vVec) = Vec_VecEntry(vGlob, i)), 1); i++ )
+ for ( i = LevelStart; (i <= LevelStop) && (((vVec) = (Vec_Ptr_t*)Vec_VecEntry(vGlob, i)), 1); i++ )
#define Vec_VecForEachLevelReverse( vGlob, vVec, i ) \
- for ( i = Vec_VecSize(vGlob) - 1; (i >= 0) && (((vVec) = Vec_VecEntry(vGlob, i)), 1); i-- )
+ for ( i = Vec_VecSize(vGlob) - 1; (i >= 0) && (((vVec) = (Vec_Ptr_t*)Vec_VecEntry(vGlob, i)), 1); i-- )
+#define Vec_VecForEachLevelReverseStartStop( vGlob, vVec, i, LevelStart, LevelStop ) \
+ for ( i = LevelStart; (i >= LevelStop) && (((vVec) = (Vec_Ptr_t*)Vec_VecEntry(vGlob, i)), 1); i-- )
// iteratores through entries
#define Vec_VecForEachEntry( vGlob, pEntry, i, k ) \
for ( i = 0; i < Vec_VecSize(vGlob); i++ ) \
Vec_PtrForEachEntry( Vec_VecEntry(vGlob, i), pEntry, k )
+#define Vec_VecForEachEntryLevel( vGlob, pEntry, i, Level ) \
+ Vec_PtrForEachEntry( Vec_VecEntry(vGlob, Level), pEntry, i )
#define Vec_VecForEachEntryStart( vGlob, pEntry, i, k, LevelStart ) \
for ( i = LevelStart; i < Vec_VecSize(vGlob); i++ ) \
Vec_PtrForEachEntry( Vec_VecEntry(vGlob, i), pEntry, k )
@@ -71,9 +74,15 @@ struct Vec_Vec_t_
#define Vec_VecForEachEntryReverse( vGlob, pEntry, i, k ) \
for ( i = 0; i < Vec_VecSize(vGlob); i++ ) \
Vec_PtrForEachEntryReverse( Vec_VecEntry(vGlob, i), pEntry, k )
+#define Vec_VecForEachEntryReverseReverse( vGlob, pEntry, i, k ) \
+ for ( i = Vec_VecSize(vGlob) - 1; i >= 0; i-- ) \
+ Vec_PtrForEachEntryReverse( Vec_VecEntry(vGlob, i), pEntry, k )
+#define Vec_VecForEachEntryReverseStart( vGlob, pEntry, i, k, LevelStart ) \
+ for ( i = LevelStart; i >= 0; i-- ) \
+ Vec_PtrForEachEntry( Vec_VecEntry(vGlob, i), pEntry, k )
////////////////////////////////////////////////////////////////////////
-/// FUNCTION DEFITIONS ///
+/// FUNCTION DEFINITIONS ///
////////////////////////////////////////////////////////////////////////
/**Function*************************************************************
@@ -123,6 +132,28 @@ static inline Vec_Vec_t * Vec_VecStart( int nSize )
/**Function*************************************************************
+ Synopsis [Allocates a vector with the given capacity.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+static inline void Vec_VecExpand( Vec_Vec_t * p, int Level )
+{
+ int i;
+ if ( p->nSize >= Level + 1 )
+ return;
+ Vec_PtrGrow( (Vec_Ptr_t *)p, Level + 1 );
+ for ( i = p->nSize; i <= Level; i++ )
+ p->pArray[i] = Vec_PtrAlloc( 0 );
+ p->nSize = Level + 1;
+}
+
+/**Function*************************************************************
+
Synopsis []
Description []
@@ -234,7 +265,7 @@ static inline void Vec_VecPush( Vec_Vec_t * p, int Level, void * Entry )
p->pArray[i] = Vec_PtrAlloc( 0 );
p->nSize = Level + 1;
}
- Vec_PtrPush( p->pArray[Level], Entry );
+ Vec_PtrPush( (Vec_Ptr_t*)p->pArray[Level], Entry );
}
/**Function*************************************************************
@@ -253,12 +284,73 @@ static inline void Vec_VecPushUnique( Vec_Vec_t * p, int Level, void * Entry )
if ( p->nSize < Level + 1 )
Vec_VecPush( p, Level, Entry );
else
- Vec_PtrPushUnique( p->pArray[Level], Entry );
+ Vec_PtrPushUnique( (Vec_Ptr_t*)p->pArray[Level], Entry );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Comparison procedure for two arrays.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+static inline int Vec_VecSortCompare1( Vec_Ptr_t ** pp1, Vec_Ptr_t ** pp2 )
+{
+ if ( Vec_PtrSize(*pp1) < Vec_PtrSize(*pp2) )
+ return -1;
+ if ( Vec_PtrSize(*pp1) > Vec_PtrSize(*pp2) )
+ return 1;
+ return 0;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Comparison procedure for two integers.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+static inline int Vec_VecSortCompare2( Vec_Ptr_t ** pp1, Vec_Ptr_t ** pp2 )
+{
+ if ( Vec_PtrSize(*pp1) > Vec_PtrSize(*pp2) )
+ return -1;
+ if ( Vec_PtrSize(*pp1) < Vec_PtrSize(*pp2) )
+ return 1;
+ return 0;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Sorting the entries by their integer value.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+static inline void Vec_VecSort( Vec_Vec_t * p, int fReverse )
+{
+ if ( fReverse )
+ qsort( (void *)p->pArray, p->nSize, sizeof(void *),
+ (int (*)(const void *, const void *)) Vec_VecSortCompare2 );
+ else
+ qsort( (void *)p->pArray, p->nSize, sizeof(void *),
+ (int (*)(const void *, const void *)) Vec_VecSortCompare1 );
}
+#endif
+
////////////////////////////////////////////////////////////////////////
/// END OF FILE ///
////////////////////////////////////////////////////////////////////////
-#endif
-
diff --git a/src/opt/cut/abcCut.c b/src/opt/cut/abcCut.c
new file mode 100644
index 00000000..9bbd5790
--- /dev/null
+++ b/src/opt/cut/abcCut.c
@@ -0,0 +1,492 @@
+/**CFile****************************************************************
+
+ FileName [abcCut.c]
+
+ SystemName [ABC: Logic synthesis and verification system.]
+
+ PackageName [Network and node package.]
+
+ Synopsis [Interface to cut computation.]
+
+ Author [Alan Mishchenko]
+
+ Affiliation [UC Berkeley]
+
+ Date [Ver. 1.0. Started - June 20, 2005.]
+
+ Revision [$Id: abcCut.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "abc.h"
+#include "cut.h"
+
+////////////////////////////////////////////////////////////////////////
+/// DECLARATIONS ///
+////////////////////////////////////////////////////////////////////////
+
+static void Abc_NtkPrintCuts( void * p, Abc_Ntk_t * pNtk, int fSeq );
+static void Abc_NtkPrintCuts_( void * p, Abc_Ntk_t * pNtk, int fSeq );
+
+
+extern int nTotal, nGood, nEqual;
+
+// temporary
+//Vec_Int_t * Abc_NtkGetNodeAttributes( Abc_Ntk_t * pNtk ) { return NULL; }
+Vec_Int_t * Abc_NtkGetNodeAttributes( Abc_Ntk_t * pNtk )
+{
+ Vec_Int_t * vAttrs = Vec_IntStart( Abc_NtkObjNumMax(pNtk) + 1 );
+ int i;
+ Abc_Obj_t * pObj;
+
+// Abc_NtkForEachCi( pNtk, pObj, i )
+// Vec_IntWriteEntry( vAttrs, pObj->Id, 1 );
+
+ Abc_NtkForEachObj( pNtk, pObj, i )
+ {
+// if ( Abc_ObjIsNode(pObj) && (rand() % 4 == 0) )
+ if ( Abc_ObjIsNode(pObj) && Abc_ObjFanoutNum(pObj) > 1 && !Abc_NodeIsMuxControlType(pObj) && (rand() % 3 == 0) )
+ Vec_IntWriteEntry( vAttrs, pObj->Id, 1 );
+ }
+ return vAttrs;
+}
+
+////////////////////////////////////////////////////////////////////////
+/// FUNCTION DEFINITIONS ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+ Synopsis [Computes the cuts for the network.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Cut_Man_t * Abc_NtkCuts( Abc_Ntk_t * pNtk, Cut_Params_t * pParams )
+{
+ ProgressBar * pProgress;
+ Cut_Man_t * p;
+ Abc_Obj_t * pObj, * pNode;
+ Vec_Ptr_t * vNodes;
+ Vec_Int_t * vChoices;
+ int i;
+ int clk = clock();
+
+ extern void Abc_NtkBalanceAttach( Abc_Ntk_t * pNtk );
+ extern void Abc_NtkBalanceDetach( Abc_Ntk_t * pNtk );
+
+ nTotal = nGood = nEqual = 0;
+
+ assert( Abc_NtkIsStrash(pNtk) );
+ // start the manager
+ pParams->nIdsMax = Abc_NtkObjNumMax( pNtk );
+ p = Cut_ManStart( pParams );
+ // compute node attributes if local or global cuts are requested
+ if ( pParams->fGlobal || pParams->fLocal )
+ {
+ extern Vec_Int_t * Abc_NtkGetNodeAttributes( Abc_Ntk_t * pNtk );
+ Cut_ManSetNodeAttrs( p, Abc_NtkGetNodeAttributes(pNtk) );
+ }
+ // prepare for cut dropping
+ if ( pParams->fDrop )
+ Cut_ManSetFanoutCounts( p, Abc_NtkFanoutCounts(pNtk) );
+ // set cuts for PIs
+ Abc_NtkForEachCi( pNtk, pObj, i )
+ if ( Abc_ObjFanoutNum(pObj) > 0 )
+ Cut_NodeSetTriv( p, pObj->Id );
+ // compute cuts for internal nodes
+ vNodes = Abc_AigDfs( pNtk, 0, 1 ); // collects POs
+ vChoices = Vec_IntAlloc( 100 );
+ pProgress = Extra_ProgressBarStart( stdout, Vec_PtrSize(vNodes) );
+ Vec_PtrForEachEntry( vNodes, pObj, i )
+ {
+ // when we reached a CO, it is time to deallocate the cuts
+ if ( Abc_ObjIsCo(pObj) )
+ {
+ if ( pParams->fDrop )
+ Cut_NodeTryDroppingCuts( p, Abc_ObjFaninId0(pObj) );
+ continue;
+ }
+ // skip constant node, it has no cuts
+// if ( Abc_NodeIsConst(pObj) )
+// continue;
+ Extra_ProgressBarUpdate( pProgress, i, NULL );
+ // compute the cuts to the internal node
+ Abc_NodeGetCuts( p, pObj, pParams->fDag, pParams->fTree );
+ // consider dropping the fanins cuts
+ if ( pParams->fDrop )
+ {
+ Cut_NodeTryDroppingCuts( p, Abc_ObjFaninId0(pObj) );
+ Cut_NodeTryDroppingCuts( p, Abc_ObjFaninId1(pObj) );
+ }
+ // add cuts due to choices
+ if ( Abc_AigNodeIsChoice(pObj) )
+ {
+ Vec_IntClear( vChoices );
+ for ( pNode = pObj; pNode; pNode = pNode->pData )
+ Vec_IntPush( vChoices, pNode->Id );
+ Cut_NodeUnionCuts( p, vChoices );
+ }
+ }
+ Extra_ProgressBarStop( pProgress );
+ Vec_PtrFree( vNodes );
+ Vec_IntFree( vChoices );
+PRT( "Total", clock() - clk );
+//Abc_NtkPrintCuts( p, pNtk, 0 );
+// Cut_ManPrintStatsToFile( p, pNtk->pSpec, clock() - clk );
+
+ // temporary printout of stats
+ if ( nTotal )
+ printf( "Total cuts = %d. Good cuts = %d. Ratio = %5.2f\n", nTotal, nGood, ((double)nGood)/nTotal );
+ return p;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Cut computation using the oracle.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Abc_NtkCutsOracle( Abc_Ntk_t * pNtk, Cut_Oracle_t * p )
+{
+ Abc_Obj_t * pObj;
+ Vec_Ptr_t * vNodes;
+ int i, clk = clock();
+ int fDrop = Cut_OracleReadDrop(p);
+
+ assert( Abc_NtkIsStrash(pNtk) );
+
+ // prepare cut droppping
+ if ( fDrop )
+ Cut_OracleSetFanoutCounts( p, Abc_NtkFanoutCounts(pNtk) );
+
+ // set cuts for PIs
+ Abc_NtkForEachCi( pNtk, pObj, i )
+ if ( Abc_ObjFanoutNum(pObj) > 0 )
+ Cut_OracleNodeSetTriv( p, pObj->Id );
+
+ // compute cuts for internal nodes
+ vNodes = Abc_AigDfs( pNtk, 0, 1 ); // collects POs
+ Vec_PtrForEachEntry( vNodes, pObj, i )
+ {
+ // when we reached a CO, it is time to deallocate the cuts
+ if ( Abc_ObjIsCo(pObj) )
+ {
+ if ( fDrop )
+ Cut_OracleTryDroppingCuts( p, Abc_ObjFaninId0(pObj) );
+ continue;
+ }
+ // skip constant node, it has no cuts
+// if ( Abc_NodeIsConst(pObj) )
+// continue;
+ // compute the cuts to the internal node
+ Cut_OracleComputeCuts( p, pObj->Id, Abc_ObjFaninId0(pObj), Abc_ObjFaninId1(pObj),
+ Abc_ObjFaninC0(pObj), Abc_ObjFaninC1(pObj) );
+ // consider dropping the fanins cuts
+ if ( fDrop )
+ {
+ Cut_OracleTryDroppingCuts( p, Abc_ObjFaninId0(pObj) );
+ Cut_OracleTryDroppingCuts( p, Abc_ObjFaninId1(pObj) );
+ }
+ }
+ Vec_PtrFree( vNodes );
+//PRT( "Total", clock() - clk );
+//Abc_NtkPrintCuts_( p, pNtk, 0 );
+}
+
+
+/**Function*************************************************************
+
+ Synopsis [Computes the cuts for the network.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Cut_Man_t * Abc_NtkSeqCuts( Abc_Ntk_t * pNtk, Cut_Params_t * pParams )
+{
+/*
+ Cut_Man_t * p;
+ Abc_Obj_t * pObj, * pNode;
+ int i, nIters, fStatus;
+ Vec_Int_t * vChoices;
+ int clk = clock();
+
+ assert( Abc_NtkIsSeq(pNtk) );
+ assert( pParams->fSeq );
+// assert( Abc_NtkIsDfsOrdered(pNtk) );
+
+ // start the manager
+ pParams->nIdsMax = Abc_NtkObjNumMax( pNtk );
+ pParams->nCutSet = Abc_NtkCutSetNodeNum( pNtk );
+ p = Cut_ManStart( pParams );
+
+ // set cuts for the constant node and the PIs
+ pObj = Abc_AigConst1(pNtk);
+ if ( Abc_ObjFanoutNum(pObj) > 0 )
+ Cut_NodeSetTriv( p, pObj->Id );
+ Abc_NtkForEachPi( pNtk, pObj, i )
+ {
+//printf( "Setting trivial cut %d.\n", pObj->Id );
+ Cut_NodeSetTriv( p, pObj->Id );
+ }
+ // label the cutset nodes and set their number in the array
+ // assign the elementary cuts to the cutset nodes
+ Abc_SeqForEachCutsetNode( pNtk, pObj, i )
+ {
+ assert( pObj->fMarkC == 0 );
+ pObj->fMarkC = 1;
+ pObj->pCopy = (Abc_Obj_t *)i;
+ Cut_NodeSetTriv( p, pObj->Id );
+//printf( "Setting trivial cut %d.\n", pObj->Id );
+ }
+
+ // process the nodes
+ vChoices = Vec_IntAlloc( 100 );
+ for ( nIters = 0; nIters < 10; nIters++ )
+ {
+//printf( "ITERATION %d:\n", nIters );
+ // compute the cuts for the internal nodes
+ Abc_AigForEachAnd( pNtk, pObj, i )
+ {
+ Abc_NodeGetCutsSeq( p, pObj, nIters==0 );
+ // add cuts due to choices
+ if ( Abc_AigNodeIsChoice(pObj) )
+ {
+ Vec_IntClear( vChoices );
+ for ( pNode = pObj; pNode; pNode = pNode->pData )
+ Vec_IntPush( vChoices, pNode->Id );
+ Cut_NodeUnionCutsSeq( p, vChoices, (pObj->fMarkC ? (int)pObj->pCopy : -1), nIters==0 );
+ }
+ }
+ // merge the new cuts with the old cuts
+ Abc_NtkForEachPi( pNtk, pObj, i )
+ Cut_NodeNewMergeWithOld( p, pObj->Id );
+ Abc_AigForEachAnd( pNtk, pObj, i )
+ Cut_NodeNewMergeWithOld( p, pObj->Id );
+ // for the cutset, transfer temp cuts to new cuts
+ fStatus = 0;
+ Abc_SeqForEachCutsetNode( pNtk, pObj, i )
+ fStatus |= Cut_NodeTempTransferToNew( p, pObj->Id, i );
+ if ( fStatus == 0 )
+ break;
+ }
+ Vec_IntFree( vChoices );
+
+ // if the status is not finished, transfer new to old for the cutset
+ Abc_SeqForEachCutsetNode( pNtk, pObj, i )
+ Cut_NodeNewMergeWithOld( p, pObj->Id );
+
+ // transfer the old cuts to the new positions
+ Abc_NtkForEachObj( pNtk, pObj, i )
+ Cut_NodeOldTransferToNew( p, pObj->Id );
+
+ // unlabel the cutset nodes
+ Abc_SeqForEachCutsetNode( pNtk, pObj, i )
+ pObj->fMarkC = 0;
+if ( pParams->fVerbose )
+{
+PRT( "Total", clock() - clk );
+printf( "Converged after %d iterations.\n", nIters );
+}
+//Abc_NtkPrintCuts( p, pNtk, 1 );
+ return p;
+*/
+}
+
+/**Function*************************************************************
+
+ Synopsis [Computes the cuts for the network.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void * Abc_NodeGetCutsRecursive( void * p, Abc_Obj_t * pObj, int fDag, int fTree )
+{
+ void * pList;
+ if ( pList = Abc_NodeReadCuts( p, pObj ) )
+ return pList;
+ Abc_NodeGetCutsRecursive( p, Abc_ObjFanin0(pObj), fDag, fTree );
+ Abc_NodeGetCutsRecursive( p, Abc_ObjFanin1(pObj), fDag, fTree );
+ return Abc_NodeGetCuts( p, pObj, fDag, fTree );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Computes the cuts for the network.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void * Abc_NodeGetCuts( void * p, Abc_Obj_t * pObj, int fDag, int fTree )
+{
+ Abc_Obj_t * pFanin;
+ int fDagNode, fTriv, TreeCode = 0;
+// assert( Abc_NtkIsStrash(pObj->pNtk) );
+ assert( Abc_ObjFaninNum(pObj) == 2 );
+
+
+ // check if the node is a DAG node
+ fDagNode = (Abc_ObjFanoutNum(pObj) > 1 && !Abc_NodeIsMuxControlType(pObj));
+ // increment the counter of DAG nodes
+ if ( fDagNode ) Cut_ManIncrementDagNodes( p );
+ // add the trivial cut if the node is a DAG node, or if we compute all cuts
+ fTriv = fDagNode || !fDag;
+ // check if fanins are DAG nodes
+ if ( fTree )
+ {
+ pFanin = Abc_ObjFanin0(pObj);
+ TreeCode |= (Abc_ObjFanoutNum(pFanin) > 1 && !Abc_NodeIsMuxControlType(pFanin));
+ pFanin = Abc_ObjFanin1(pObj);
+ TreeCode |= ((Abc_ObjFanoutNum(pFanin) > 1 && !Abc_NodeIsMuxControlType(pFanin)) << 1);
+ }
+
+
+ // changes due to the global/local cut computation
+ {
+ Cut_Params_t * pParams = Cut_ManReadParams(p);
+ if ( pParams->fLocal )
+ {
+ Vec_Int_t * vNodeAttrs = Cut_ManReadNodeAttrs(p);
+ fDagNode = Vec_IntEntry( vNodeAttrs, pObj->Id );
+ if ( fDagNode ) Cut_ManIncrementDagNodes( p );
+// fTriv = fDagNode || !pParams->fGlobal;
+ fTriv = !Vec_IntEntry( vNodeAttrs, pObj->Id );
+ TreeCode = 0;
+ pFanin = Abc_ObjFanin0(pObj);
+ TreeCode |= Vec_IntEntry( vNodeAttrs, pFanin->Id );
+ pFanin = Abc_ObjFanin1(pObj);
+ TreeCode |= (Vec_IntEntry( vNodeAttrs, pFanin->Id ) << 1);
+ }
+ }
+ return Cut_NodeComputeCuts( p, pObj->Id, Abc_ObjFaninId0(pObj), Abc_ObjFaninId1(pObj),
+ Abc_ObjFaninC0(pObj), Abc_ObjFaninC1(pObj), fTriv, TreeCode );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Computes the cuts for the network.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Abc_NodeGetCutsSeq( void * p, Abc_Obj_t * pObj, int fTriv )
+{
+ int CutSetNum;
+ assert( Abc_NtkIsSeq(pObj->pNtk) );
+ assert( Abc_ObjFaninNum(pObj) == 2 );
+ fTriv = pObj->fMarkC ? 0 : fTriv;
+ CutSetNum = pObj->fMarkC ? (int)pObj->pCopy : -1;
+ Cut_NodeComputeCutsSeq( p, pObj->Id, Abc_ObjFaninId0(pObj), Abc_ObjFaninId1(pObj),
+ Abc_ObjFaninC0(pObj), Abc_ObjFaninC1(pObj), Seq_ObjFaninL0(pObj), Seq_ObjFaninL1(pObj), fTriv, CutSetNum );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Computes the cuts for the network.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void * Abc_NodeReadCuts( void * p, Abc_Obj_t * pObj )
+{
+ return Cut_NodeReadCutsNew( p, pObj->Id );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Computes the cuts for the network.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Abc_NodeFreeCuts( void * p, Abc_Obj_t * pObj )
+{
+ Cut_NodeFreeCuts( p, pObj->Id );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Computes the cuts for the network.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Abc_NtkPrintCuts( void * p, Abc_Ntk_t * pNtk, int fSeq )
+{
+ Cut_Man_t * pMan = p;
+ Cut_Cut_t * pList;
+ Abc_Obj_t * pObj;
+ int i;
+ printf( "Cuts of the network:\n" );
+ Abc_NtkForEachObj( pNtk, pObj, i )
+ {
+ pList = Abc_NodeReadCuts( p, pObj );
+ printf( "Node %s:\n", Abc_ObjName(pObj) );
+ Cut_CutPrintList( pList, fSeq );
+ }
+}
+
+/**Function*************************************************************
+
+ Synopsis [Computes the cuts for the network.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Abc_NtkPrintCuts_( void * p, Abc_Ntk_t * pNtk, int fSeq )
+{
+ Cut_Man_t * pMan = p;
+ Cut_Cut_t * pList;
+ Abc_Obj_t * pObj;
+ pObj = Abc_NtkObj( pNtk, 2 * Abc_NtkObjNum(pNtk) / 3 );
+ pList = Abc_NodeReadCuts( p, pObj );
+ printf( "Node %s:\n", Abc_ObjName(pObj) );
+ Cut_CutPrintList( pList, fSeq );
+}
+
+////////////////////////////////////////////////////////////////////////
+/// END OF FILE ///
+////////////////////////////////////////////////////////////////////////
+
+
diff --git a/src/opt/cut/cut.h b/src/opt/cut/cut.h
index 6719ed4d..dee05dfc 100644
--- a/src/opt/cut/cut.h
+++ b/src/opt/cut/cut.h
@@ -21,6 +21,10 @@
#ifndef __CUT_H__
#define __CUT_H__
+#ifdef __cplusplus
+extern "C" {
+#endif
+
////////////////////////////////////////////////////////////////////////
/// INCLUDES ///
////////////////////////////////////////////////////////////////////////
@@ -29,81 +33,133 @@
/// PARAMETERS ///
////////////////////////////////////////////////////////////////////////
+#define CUT_SIZE_MIN 3 // the min K of the K-feasible cut computation
+#define CUT_SIZE_MAX 12 // the max K of the K-feasible cut computation
+
+#define CUT_SHIFT 8 // the number of bits for storing latch number in the cut leaves
+#define CUT_MASK 0xFF // the mask to get the stored latch number
+
////////////////////////////////////////////////////////////////////////
/// BASIC TYPES ///
////////////////////////////////////////////////////////////////////////
typedef struct Cut_ManStruct_t_ Cut_Man_t;
+typedef struct Cut_OracleStruct_t_ Cut_Oracle_t;
typedef struct Cut_CutStruct_t_ Cut_Cut_t;
typedef struct Cut_ParamsStruct_t_ Cut_Params_t;
struct Cut_ParamsStruct_t_
{
- int nVarsMax; // the max cut size ("k" of the k-feasible cuts)
- int nKeepMax; // the max number of cuts kept at a node
- int nIdsMax; // the max number of IDs of cut objects
- int fTruth; // compute truth tables
- int fHash; // hash cuts to detect unique
- int fFilter; // filter dominated cuts
- int fSeq; // compute sequential cuts
- int fDrop; // drop cuts on the fly
- int fVerbose; // the verbosiness flag
+ int nVarsMax; // the max cut size ("k" of the k-feasible cuts)
+ int nKeepMax; // the max number of cuts kept at a node
+ int nIdsMax; // the max number of IDs of cut objects
+ int nBitShift; // the number of bits used for the latch counter of an edge
+ int nCutSet; // the number of nodes in the cut set
+ int fTruth; // compute truth tables
+ int fFilter; // filter dominated cuts
+ int fSeq; // compute sequential cuts
+ int fDrop; // drop cuts on the fly
+ int fDag; // compute only DAG cuts
+ int fTree; // compute only tree cuts
+ int fGlobal; // compute only global cuts
+ int fLocal; // compute only local cuts
+ int fRecord; // record the cut computation flow
+ int fFancy; // perform fancy computations
+ int fMap; // computes delay of FPGA mapping with cuts
+ int fVerbose; // the verbosiness flag
};
struct Cut_CutStruct_t_
{
- unsigned uTruth : 16; // truth table for 4-input cuts
- unsigned uPhase : 7; // the phase when mapping into a canonical form
+ unsigned Num0 : 11; // temporary number
+ unsigned Num1 : 11; // temporary number
unsigned fSimul : 1; // the value of cut's output at 000.. pattern
unsigned fCompl : 1; // the cut is complemented
- unsigned fSeq : 1; // the cut is sequential
- unsigned nVarsMax : 3; // the max number of vars [4-6]
- unsigned nLeaves : 3; // the number of leaves [4-6]
+ unsigned nVarsMax : 4; // the max number of vars [4-6]
+ unsigned nLeaves : 4; // the number of leaves [4-6]
+ unsigned uSign; // the signature
+ unsigned uCanon0; // the canonical form
+ unsigned uCanon1; // the canonical form
Cut_Cut_t * pNext; // the next cut in the list
- void * pData; // the user data
int pLeaves[0]; // the array of leaves
};
-static inline unsigned * Cut_CutReadTruth( Cut_Cut_t * p ) { if ( p->nVarsMax == 4 ) return (unsigned *)p; return (unsigned *)(p->pLeaves + p->nVarsMax + p->fSeq); }
-static inline unsigned Cut_CutReadPhase( Cut_Cut_t * p ) { return p->uPhase; }
static inline int Cut_CutReadLeaveNum( Cut_Cut_t * p ) { return p->nLeaves; }
static inline int * Cut_CutReadLeaves( Cut_Cut_t * p ) { return p->pLeaves; }
-static inline void * Cut_CutReadData( Cut_Cut_t * p ) { return p->pData; }
-
-static inline void Cut_CutWriteData( Cut_Cut_t * p, void * pData ) { p->pData = pData; }
+static inline unsigned * Cut_CutReadTruth( Cut_Cut_t * p ) { return (unsigned *)(p->pLeaves + p->nVarsMax); }
static inline void Cut_CutWriteTruth( Cut_Cut_t * p, unsigned * puTruth ) {
- if ( p->nVarsMax == 4 ) { p->uTruth = *puTruth; return; }
- p->pLeaves[p->nVarsMax + p->fSeq] = (int)puTruth[0];
- if ( p->nVarsMax == 6 ) p->pLeaves[p->nVarsMax + p->fSeq + 1] = (int)puTruth[1];
+ int i;
+ for ( i = (p->nVarsMax <= 5) ? 0 : ((1 << (p->nVarsMax - 5)) - 1); i >= 0; i-- )
+ p->pLeaves[p->nVarsMax + i] = (int)puTruth[i];
}
////////////////////////////////////////////////////////////////////////
-/// MACRO DEFITIONS ///
+/// MACRO DEFINITIONS ///
////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////
/// FUNCTION DECLARATIONS ///
////////////////////////////////////////////////////////////////////////
+/*=== cutApi.c ==========================================================*/
+extern Cut_Cut_t * Cut_NodeReadCutsNew( Cut_Man_t * p, int Node );
+extern Cut_Cut_t * Cut_NodeReadCutsOld( Cut_Man_t * p, int Node );
+extern Cut_Cut_t * Cut_NodeReadCutsTemp( Cut_Man_t * p, int Node );
+extern void Cut_NodeWriteCutsNew( Cut_Man_t * p, int Node, Cut_Cut_t * pList );
+extern void Cut_NodeWriteCutsOld( Cut_Man_t * p, int Node, Cut_Cut_t * pList );
+extern void Cut_NodeWriteCutsTemp( Cut_Man_t * p, int Node, Cut_Cut_t * pList );
+extern void Cut_NodeSetTriv( Cut_Man_t * p, int Node );
+extern void Cut_NodeTryDroppingCuts( Cut_Man_t * p, int Node );
+extern void Cut_NodeFreeCuts( Cut_Man_t * p, int Node );
+/*=== cutCut.c ==========================================================*/
+extern void Cut_CutPrint( Cut_Cut_t * pCut, int fSeq );
+extern void Cut_CutPrintList( Cut_Cut_t * pList, int fSeq );
+extern int Cut_CutCountList( Cut_Cut_t * pList );
/*=== cutMan.c ==========================================================*/
extern Cut_Man_t * Cut_ManStart( Cut_Params_t * pParams );
extern void Cut_ManStop( Cut_Man_t * p );
extern void Cut_ManPrintStats( Cut_Man_t * p );
+extern void Cut_ManPrintStatsToFile( Cut_Man_t * p, char * pFileName, int TimeTotal );
extern void Cut_ManSetFanoutCounts( Cut_Man_t * p, Vec_Int_t * vFanCounts );
+extern void Cut_ManSetNodeAttrs( Cut_Man_t * p, Vec_Int_t * vFanCounts );
+extern int Cut_ManReadVarsMax( Cut_Man_t * p );
+extern Cut_Params_t * Cut_ManReadParams( Cut_Man_t * p );
+extern Vec_Int_t * Cut_ManReadNodeAttrs( Cut_Man_t * p );
+extern void Cut_ManIncrementDagNodes( Cut_Man_t * p );
/*=== cutNode.c ==========================================================*/
-extern void Cut_NodeSetTriv( Cut_Man_t * p, int Node );
-extern Cut_Cut_t * Cut_NodeComputeCuts( Cut_Man_t * p, int Node, int Node0, int Node1, int fCompl0, int fCompl1 );
+extern Cut_Cut_t * Cut_NodeComputeCuts( Cut_Man_t * p, int Node, int Node0, int Node1, int fCompl0, int fCompl1, int fTriv, int TreeCode );
extern Cut_Cut_t * Cut_NodeUnionCuts( Cut_Man_t * p, Vec_Int_t * vNodes );
-extern Cut_Cut_t * Cut_NodeReadCuts( Cut_Man_t * p, int Node );
-extern void Cut_NodeWriteCuts( Cut_Man_t * p, int Node, Cut_Cut_t * pList );
-extern void Cut_NodeFreeCuts( Cut_Man_t * p, int Node );
-extern void Cut_NodeSetComputedAsNew( Cut_Man_t * p, int Node );
-extern void Cut_NodeTryDroppingCuts( Cut_Man_t * p, int Node );
-extern void Cut_CutPrint( Cut_Cut_t * pCut );
+extern Cut_Cut_t * Cut_NodeUnionCutsSeq( Cut_Man_t * p, Vec_Int_t * vNodes, int CutSetNum, int fFirst );
+extern int Cut_ManMappingArea_rec( Cut_Man_t * p, int Node );
+/*=== cutSeq.c ==========================================================*/
+extern void Cut_NodeComputeCutsSeq( Cut_Man_t * p, int Node, int Node0, int Node1, int fCompl0, int fCompl1, int nLat0, int nLat1, int fTriv, int CutSetNum );
+extern void Cut_NodeNewMergeWithOld( Cut_Man_t * p, int Node );
+extern int Cut_NodeTempTransferToNew( Cut_Man_t * p, int Node, int CutSetNum );
+extern void Cut_NodeOldTransferToNew( Cut_Man_t * p, int Node );
+/*=== cutOracle.c ==========================================================*/
+extern Cut_Oracle_t * Cut_OracleStart( Cut_Man_t * pMan );
+extern void Cut_OracleStop( Cut_Oracle_t * p );
+extern void Cut_OracleSetFanoutCounts( Cut_Oracle_t * p, Vec_Int_t * vFanCounts );
+extern int Cut_OracleReadDrop( Cut_Oracle_t * p );
+extern void Cut_OracleNodeSetTriv( Cut_Oracle_t * p, int Node );
+extern Cut_Cut_t * Cut_OracleComputeCuts( Cut_Oracle_t * p, int Node, int Node0, int Node1, int fCompl0, int fCompl1 );
+extern void Cut_OracleTryDroppingCuts( Cut_Oracle_t * p, int Node );
+/*=== cutTruth.c ==========================================================*/
+extern void Cut_TruthNCanonicize( Cut_Cut_t * pCut );
+/*=== cutPre22.c ==========================================================*/
+extern void Cut_CellPrecompute();
+extern void Cut_CellLoad();
+extern int Cut_CellIsRunning();
+extern void Cut_CellDumpToFile();
+extern int Cut_CellTruthLookup( unsigned * pTruth, int nVars );
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
////////////////////////////////////////////////////////////////////////
/// END OF FILE ///
////////////////////////////////////////////////////////////////////////
-#endif
-
diff --git a/src/opt/cut/cutApi.c b/src/opt/cut/cutApi.c
new file mode 100644
index 00000000..980c6b12
--- /dev/null
+++ b/src/opt/cut/cutApi.c
@@ -0,0 +1,197 @@
+/**CFile****************************************************************
+
+ FileName [cutNode.c]
+
+ SystemName [ABC: Logic synthesis and verification system.]
+
+ PackageName [K-feasible cut computation package.]
+
+ Synopsis [Procedures to compute cuts for a node.]
+
+ Author [Alan Mishchenko]
+
+ Affiliation [UC Berkeley]
+
+ Date [Ver. 1.0. Started - June 20, 2005.]
+
+ Revision [$Id: cutNode.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "cutInt.h"
+
+////////////////////////////////////////////////////////////////////////
+/// DECLARATIONS ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+/// FUNCTION DEFINITIONS ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+ Synopsis [Returns the pointer to the linked list of cuts.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Cut_Cut_t * Cut_NodeReadCutsNew( Cut_Man_t * p, int Node )
+{
+ if ( Node >= p->vCutsNew->nSize )
+ return NULL;
+ return Vec_PtrEntry( p->vCutsNew, Node );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Returns the pointer to the linked list of cuts.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Cut_Cut_t * Cut_NodeReadCutsOld( Cut_Man_t * p, int Node )
+{
+ assert( Node < p->vCutsOld->nSize );
+ return Vec_PtrEntry( p->vCutsOld, Node );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Returns the pointer to the linked list of cuts.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Cut_Cut_t * Cut_NodeReadCutsTemp( Cut_Man_t * p, int Node )
+{
+ assert( Node < p->vCutsTemp->nSize );
+ return Vec_PtrEntry( p->vCutsTemp, Node );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Returns the pointer to the linked list of cuts.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Cut_NodeWriteCutsNew( Cut_Man_t * p, int Node, Cut_Cut_t * pList )
+{
+ Vec_PtrWriteEntry( p->vCutsNew, Node, pList );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Returns the pointer to the linked list of cuts.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Cut_NodeWriteCutsOld( Cut_Man_t * p, int Node, Cut_Cut_t * pList )
+{
+ Vec_PtrWriteEntry( p->vCutsOld, Node, pList );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Returns the pointer to the linked list of cuts.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Cut_NodeWriteCutsTemp( Cut_Man_t * p, int Node, Cut_Cut_t * pList )
+{
+ Vec_PtrWriteEntry( p->vCutsTemp, Node, pList );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Sets the trivial cut for the node.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Cut_NodeSetTriv( Cut_Man_t * p, int Node )
+{
+ assert( Cut_NodeReadCutsNew(p, Node) == NULL );
+ Cut_NodeWriteCutsNew( p, Node, Cut_CutCreateTriv(p, Node) );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Consider dropping cuts if they are useless by now.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Cut_NodeTryDroppingCuts( Cut_Man_t * p, int Node )
+{
+ int nFanouts;
+ assert( p->vFanCounts );
+ nFanouts = Vec_IntEntry( p->vFanCounts, Node );
+ assert( nFanouts > 0 );
+ if ( --nFanouts == 0 )
+ Cut_NodeFreeCuts( p, Node );
+ Vec_IntWriteEntry( p->vFanCounts, Node, nFanouts );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Deallocates the cuts at the node.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Cut_NodeFreeCuts( Cut_Man_t * p, int Node )
+{
+ Cut_Cut_t * pList, * pCut, * pCut2;
+ pList = Cut_NodeReadCutsNew( p, Node );
+ if ( pList == NULL )
+ return;
+ Cut_ListForEachCutSafe( pList, pCut, pCut2 )
+ Cut_CutRecycle( p, pCut );
+ Cut_NodeWriteCutsNew( p, Node, NULL );
+}
+
+
+////////////////////////////////////////////////////////////////////////
+/// END OF FILE ///
+////////////////////////////////////////////////////////////////////////
+
+
diff --git a/src/opt/cut/cutCut.c b/src/opt/cut/cutCut.c
new file mode 100644
index 00000000..94147278
--- /dev/null
+++ b/src/opt/cut/cutCut.c
@@ -0,0 +1,359 @@
+/**CFile****************************************************************
+
+ FileName [cutNode.c]
+
+ SystemName [ABC: Logic synthesis and verification system.]
+
+ PackageName [K-feasible cut computation package.]
+
+ Synopsis [Procedures to compute cuts for a node.]
+
+ Author [Alan Mishchenko]
+
+ Affiliation [UC Berkeley]
+
+ Date [Ver. 1.0. Started - June 20, 2005.]
+
+ Revision [$Id: cutNode.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "cutInt.h"
+
+////////////////////////////////////////////////////////////////////////
+/// DECLARATIONS ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+/// FUNCTION DEFINITIONS ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+ Synopsis [Allocates the cut.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Cut_Cut_t * Cut_CutAlloc( Cut_Man_t * p )
+{
+ Cut_Cut_t * pCut;
+ // cut allocation
+ pCut = (Cut_Cut_t *)Extra_MmFixedEntryFetch( p->pMmCuts );
+ memset( pCut, 0, sizeof(Cut_Cut_t) );
+ pCut->nVarsMax = p->pParams->nVarsMax;
+ pCut->fSimul = p->fSimul;
+ // statistics
+ p->nCutsAlloc++;
+ p->nCutsCur++;
+ if ( p->nCutsPeak < p->nCutsAlloc - p->nCutsDealloc )
+ p->nCutsPeak = p->nCutsAlloc - p->nCutsDealloc;
+ return pCut;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Recybles the cut.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Cut_CutRecycle( Cut_Man_t * p, Cut_Cut_t * pCut )
+{
+ p->nCutsDealloc++;
+ p->nCutsCur--;
+ if ( pCut->nLeaves == 1 )
+ p->nCutsTriv--;
+ Extra_MmFixedEntryRecycle( p->pMmCuts, (char *)pCut );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Compares two cuts.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Cut_CutCompare( Cut_Cut_t * pCut1, Cut_Cut_t * pCut2 )
+{
+ int i;
+ if ( pCut1->nLeaves < pCut2->nLeaves )
+ return -1;
+ if ( pCut1->nLeaves > pCut2->nLeaves )
+ return 1;
+ for ( i = 0; i < (int)pCut1->nLeaves; i++ )
+ {
+ if ( pCut1->pLeaves[i] < pCut2->pLeaves[i] )
+ return -1;
+ if ( pCut1->pLeaves[i] > pCut2->pLeaves[i] )
+ return 1;
+ }
+ return 0;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Duplicates the list.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Cut_Cut_t * Cut_CutDupList( Cut_Man_t * p, Cut_Cut_t * pList )
+{
+ Cut_Cut_t * pHead = NULL, ** ppTail = &pHead;
+ Cut_Cut_t * pTemp, * pCopy;
+ if ( pList == NULL )
+ return NULL;
+ Cut_ListForEachCut( pList, pTemp )
+ {
+ pCopy = (Cut_Cut_t *)Extra_MmFixedEntryFetch( p->pMmCuts );
+ memcpy( pCopy, pTemp, p->EntrySize );
+ *ppTail = pCopy;
+ ppTail = &pCopy->pNext;
+ }
+ *ppTail = NULL;
+ return pHead;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Recycles the list.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Cut_CutRecycleList( Cut_Man_t * p, Cut_Cut_t * pList )
+{
+ Cut_Cut_t * pCut, * pCut2;
+ Cut_ListForEachCutSafe( pList, pCut, pCut2 )
+ Extra_MmFixedEntryRecycle( p->pMmCuts, (char *)pCut );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Counts the number of cuts in the list.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Cut_CutCountList( Cut_Cut_t * pList )
+{
+ int Counter = 0;
+ Cut_ListForEachCut( pList, pList )
+ Counter++;
+ return Counter;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Merges two NULL-terminated linked lists.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Cut_Cut_t * Cut_CutMergeLists( Cut_Cut_t * pList1, Cut_Cut_t * pList2 )
+{
+ Cut_Cut_t * pList = NULL, ** ppTail = &pList;
+ Cut_Cut_t * pCut;
+ while ( pList1 && pList2 )
+ {
+ if ( Cut_CutCompare(pList1, pList2) < 0 )
+ {
+ pCut = pList1;
+ pList1 = pList1->pNext;
+ }
+ else
+ {
+ pCut = pList2;
+ pList2 = pList2->pNext;
+ }
+ *ppTail = pCut;
+ ppTail = &pCut->pNext;
+ }
+ *ppTail = pList1? pList1: pList2;
+ return pList;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Sets the number of the cuts in the list.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Cut_CutNumberList( Cut_Cut_t * pList )
+{
+ Cut_Cut_t * pCut;
+ int i = 0;
+ Cut_ListForEachCut( pList, pCut )
+ pCut->Num0 = i++;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Creates the trivial cut.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Cut_Cut_t * Cut_CutCreateTriv( Cut_Man_t * p, int Node )
+{
+ Cut_Cut_t * pCut;
+ if ( p->pParams->fSeq )
+ Node <<= CUT_SHIFT;
+ pCut = Cut_CutAlloc( p );
+ pCut->nLeaves = 1;
+ pCut->pLeaves[0] = Node;
+ pCut->uSign = Cut_NodeSign( Node );
+ if ( p->pParams->fTruth )
+ {
+/*
+ if ( pCut->nVarsMax == 4 )
+ Cut_CutWriteTruth( pCut, p->uTruthVars[0] );
+ else
+ Extra_BitCopy( pCut->nLeaves, p->uTruths[0], (uint8*)Cut_CutReadTruth(pCut) );
+*/
+ unsigned * pTruth = Cut_CutReadTruth(pCut);
+ int i;
+ for ( i = 0; i < p->nTruthWords; i++ )
+ pTruth[i] = 0xAAAAAAAA;
+ }
+ p->nCutsTriv++;
+ return pCut;
+}
+
+
+/**Function*************************************************************
+
+ Synopsis [Print the cut.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Cut_CutPrint( Cut_Cut_t * pCut, int fSeq )
+{
+ int i;
+ assert( pCut->nLeaves > 0 );
+ printf( "%d : {", pCut->nLeaves );
+ for ( i = 0; i < (int)pCut->nLeaves; i++ )
+ {
+ if ( fSeq )
+ {
+ printf( " %d", pCut->pLeaves[i] >> CUT_SHIFT );
+ if ( pCut->pLeaves[i] & CUT_MASK )
+ printf( "(%d)", pCut->pLeaves[i] & CUT_MASK );
+ }
+ else
+ printf( " %d", pCut->pLeaves[i] );
+ }
+ printf( " }" );
+// printf( "\nSign = " );
+// Extra_PrintBinary( stdout, &pCut->uSign, 32 );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Print the cut.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Cut_CutPrintList( Cut_Cut_t * pList, int fSeq )
+{
+ Cut_Cut_t * pCut;
+ for ( pCut = pList; pCut; pCut = pCut->pNext )
+ Cut_CutPrint( pCut, fSeq ), printf( "\n" );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Consider dropping cuts if they are useless by now.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Cut_CutPrintMerge( Cut_Cut_t * pCut, Cut_Cut_t * pCut0, Cut_Cut_t * pCut1 )
+{
+ printf( "\n" );
+ printf( "%d : %5d %5d %5d %5d %5d\n",
+ pCut0->nLeaves,
+ pCut0->nLeaves > 0 ? pCut0->pLeaves[0] : -1,
+ pCut0->nLeaves > 1 ? pCut0->pLeaves[1] : -1,
+ pCut0->nLeaves > 2 ? pCut0->pLeaves[2] : -1,
+ pCut0->nLeaves > 3 ? pCut0->pLeaves[3] : -1,
+ pCut0->nLeaves > 4 ? pCut0->pLeaves[4] : -1
+ );
+ printf( "%d : %5d %5d %5d %5d %5d\n",
+ pCut1->nLeaves,
+ pCut1->nLeaves > 0 ? pCut1->pLeaves[0] : -1,
+ pCut1->nLeaves > 1 ? pCut1->pLeaves[1] : -1,
+ pCut1->nLeaves > 2 ? pCut1->pLeaves[2] : -1,
+ pCut1->nLeaves > 3 ? pCut1->pLeaves[3] : -1,
+ pCut1->nLeaves > 4 ? pCut1->pLeaves[4] : -1
+ );
+ if ( pCut == NULL )
+ printf( "Cannot merge\n" );
+ else
+ printf( "%d : %5d %5d %5d %5d %5d\n",
+ pCut->nLeaves,
+ pCut->nLeaves > 0 ? pCut->pLeaves[0] : -1,
+ pCut->nLeaves > 1 ? pCut->pLeaves[1] : -1,
+ pCut->nLeaves > 2 ? pCut->pLeaves[2] : -1,
+ pCut->nLeaves > 3 ? pCut->pLeaves[3] : -1,
+ pCut->nLeaves > 4 ? pCut->pLeaves[4] : -1
+ );
+}
+
+////////////////////////////////////////////////////////////////////////
+/// END OF FILE ///
+////////////////////////////////////////////////////////////////////////
+
+
diff --git a/src/opt/cut/cutExpand.c b/src/opt/cut/cutExpand.c
new file mode 100644
index 00000000..d389ef7a
--- /dev/null
+++ b/src/opt/cut/cutExpand.c
@@ -0,0 +1,184 @@
+/**CFile****************************************************************
+
+ FileName [cutExpand.c]
+
+ SystemName [ABC: Logic synthesis and verification system.]
+
+ PackageName [K-feasible cut computation package.]
+
+ Synopsis [Computes the truth table of the cut after expansion.]
+
+ Author [Alan Mishchenko]
+
+ Affiliation [UC Berkeley]
+
+ Date [Ver. 1.0. Started - June 20, 2005.]
+
+ Revision [$Id: cutExpand.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "cutInt.h"
+
+////////////////////////////////////////////////////////////////////////
+/// DECLARATIONS ///
+////////////////////////////////////////////////////////////////////////
+
+#define CUT_CELL_MVAR 9
+
+////////////////////////////////////////////////////////////////////////
+/// FUNCTION DEFINITIONS ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+ Synopsis [Computes the stretching phase of the cut w.r.t. the merged cut.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+static inline unsigned Cut_TruthPhase( Cut_Cut_t * pCut, Cut_Cut_t * pCut1 )
+{
+ unsigned uPhase = 0;
+ int i, k;
+ for ( i = k = 0; i < (int)pCut->nLeaves; i++ )
+ {
+ if ( k == (int)pCut1->nLeaves )
+ break;
+ if ( pCut->pLeaves[i] < pCut1->pLeaves[k] )
+ continue;
+ assert( pCut->pLeaves[i] == pCut1->pLeaves[k] );
+ uPhase |= (1 << i);
+ k++;
+ }
+ return uPhase;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Computes the truth table of the composition of cuts.]
+
+ Description [Inputs are:
+ - a factor cut (truth table is stored inside)
+ - a node in the factor cut
+ - a tree cut to be substituted (truth table is stored inside)
+ - the resulting cut (truth table will be filled in).
+ Note that all cuts, including the resulting one, should be already
+ computed and the nodes should be stored in the ascending order.]
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Cut_TruthCompose( Cut_Cut_t * pCutF, int Node, Cut_Cut_t * pCutT, Cut_Cut_t * pCutRes )
+{
+ static unsigned uCof0[1<<(CUT_CELL_MVAR-5)];
+ static unsigned uCof1[1<<(CUT_CELL_MVAR-5)];
+ static unsigned uTemp[1<<(CUT_CELL_MVAR-5)];
+ unsigned * pIn, * pOut, * pTemp;
+ unsigned uPhase;
+ int NodeIndex, i, k;
+
+ // sanity checks
+ assert( pCutF->nVarsMax == pCutT->nVarsMax );
+ assert( pCutF->nVarsMax == pCutRes->nVarsMax );
+ assert( pCutF->nVarsMax <= CUT_CELL_MVAR );
+ // the factor cut (pCutF) should have its nodes sorted in the ascending order
+ assert( pCutF->nLeaves <= pCutF->nVarsMax );
+ for ( i = 0; i < (int)pCutF->nLeaves - 1; i++ )
+ assert( pCutF->pLeaves[i] < pCutF->pLeaves[i+1] );
+ // the tree cut (pCutT) should have its nodes sorted in the ascending order
+ assert( pCutT->nLeaves <= pCutT->nVarsMax );
+ for ( i = 0; i < (int)pCutT->nLeaves - 1; i++ )
+ assert( pCutT->pLeaves[i] < pCutT->pLeaves[i+1] );
+ // the resulting cut (pCutRes) should have its nodes sorted in the ascending order
+ assert( pCutRes->nLeaves <= pCutRes->nVarsMax );
+ for ( i = 0; i < (int)pCutRes->nLeaves - 1; i++ )
+ assert( pCutRes->pLeaves[i] < pCutRes->pLeaves[i+1] );
+ // make sure that every node in pCutF (except Node) appears in pCutRes
+ for ( i = 0; i < (int)pCutF->nLeaves; i++ )
+ {
+ if ( pCutF->pLeaves[i] == Node )
+ continue;
+ for ( k = 0; k < (int)pCutRes->nLeaves; k++ )
+ if ( pCutF->pLeaves[i] == pCutRes->pLeaves[k] )
+ break;
+ assert( k < (int)pCutRes->nLeaves ); // node i from pCutF is not found in pCutRes!!!
+ }
+ // make sure that every node in pCutT appears in pCutRes
+ for ( i = 0; i < (int)pCutT->nLeaves; i++ )
+ {
+ for ( k = 0; k < (int)pCutRes->nLeaves; k++ )
+ if ( pCutT->pLeaves[i] == pCutRes->pLeaves[k] )
+ break;
+ assert( k < (int)pCutRes->nLeaves ); // node i from pCutT is not found in pCutRes!!!
+ }
+
+
+ // find the index of the given node in the factor cut
+ NodeIndex = -1;
+ for ( NodeIndex = 0; NodeIndex < (int)pCutF->nLeaves; NodeIndex++ )
+ if ( pCutF->pLeaves[NodeIndex] == Node )
+ break;
+ assert( NodeIndex >= 0 ); // Node should be in pCutF
+
+ // copy the truth table
+ Extra_TruthCopy( uTemp, Cut_CutReadTruth(pCutF), pCutF->nLeaves );
+
+ // bubble-move the NodeIndex variable to be the last one (the most significant one)
+ pIn = uTemp; pOut = uCof0; // uCof0 is used for temporary storage here
+ for ( i = NodeIndex; i < (int)pCutF->nLeaves - 1; i++ )
+ {
+ Extra_TruthSwapAdjacentVars( pOut, pIn, pCutF->nLeaves, i );
+ pTemp = pIn; pIn = pOut; pOut = pTemp;
+ }
+ if ( (pCutF->nLeaves - 1 - NodeIndex) & 1 )
+ Extra_TruthCopy( pOut, pIn, pCutF->nLeaves );
+ // the result of stretching is in uTemp
+
+ // cofactor the factor cut with respect to the node
+ Extra_TruthCopy( uCof0, uTemp, pCutF->nLeaves );
+ Extra_TruthCofactor0( uCof0, pCutF->nLeaves, pCutF->nLeaves-1 );
+ Extra_TruthCopy( uCof1, uTemp, pCutF->nLeaves );
+ Extra_TruthCofactor1( uCof1, pCutF->nLeaves, pCutF->nLeaves-1 );
+
+ // temporarily shrink the factor cut's variables by removing Node
+ for ( i = NodeIndex; i < (int)pCutF->nLeaves - 1; i++ )
+ pCutF->pLeaves[i] = pCutF->pLeaves[i+1];
+ pCutF->nLeaves--;
+
+ // spread out the cofactors' truth tables to the same var order as the resulting cut
+ uPhase = Cut_TruthPhase(pCutRes, pCutF);
+ assert( Extra_WordCountOnes(uPhase) == (int)pCutF->nLeaves );
+ Extra_TruthStretch( uTemp, uCof0, pCutF->nLeaves, pCutF->nVarsMax, uPhase );
+ Extra_TruthCopy( uCof0, uTemp, pCutF->nVarsMax );
+ Extra_TruthStretch( uTemp, uCof1, pCutF->nLeaves, pCutF->nVarsMax, uPhase );
+ Extra_TruthCopy( uCof1, uTemp, pCutF->nVarsMax );
+
+ // spread out the tree cut's truth table to the same var order as the resulting cut
+ uPhase = Cut_TruthPhase(pCutRes, pCutT);
+ assert( Extra_WordCountOnes(uPhase) == (int)pCutT->nLeaves );
+ Extra_TruthStretch( uTemp, Cut_CutReadTruth(pCutT), pCutT->nLeaves, pCutT->nVarsMax, uPhase );
+
+ // create the resulting truth table
+ pTemp = Cut_CutReadTruth(pCutRes);
+ for ( i = Extra_TruthWordNum(pCutRes->nLeaves)-1; i >= 0; i-- )
+ pTemp[i] = (uCof0[i] & ~uTemp[i]) | (uCof1[i] & uTemp[i]);
+
+ // undo the removal of the node from the cut
+ for ( i = (int)pCutF->nLeaves - 1; i >= NodeIndex; --i )
+ pCutF->pLeaves[i+1] = pCutF->pLeaves[i];
+ pCutF->pLeaves[NodeIndex] = Node;
+ pCutF->nLeaves++;
+}
+
+////////////////////////////////////////////////////////////////////////
+/// END OF FILE ///
+////////////////////////////////////////////////////////////////////////
+
+
diff --git a/src/opt/cut/cutInt.h b/src/opt/cut/cutInt.h
index fe5080b4..17f268c7 100644
--- a/src/opt/cut/cutInt.h
+++ b/src/opt/cut/cutInt.h
@@ -29,6 +29,7 @@
#include "extra.h"
#include "vec.h"
#include "cut.h"
+#include "cutList.h"
////////////////////////////////////////////////////////////////////////
/// PARAMETERS ///
@@ -41,56 +42,103 @@
typedef struct Cut_HashTableStruct_t_ Cut_HashTable_t;
struct Cut_ManStruct_t_
-{
+{
// user preferences
Cut_Params_t * pParams; // computation parameters
Vec_Int_t * vFanCounts; // the array of fanout counters
+ Vec_Int_t * vNodeAttrs; // node attributes (1 = global; 0 = local)
// storage for cuts
- Vec_Ptr_t * vCuts; // cuts by ID
- Vec_Ptr_t * vCutsNew; // cuts by ID
- Cut_HashTable_t * tTable; // cuts by their leaves (and root)
+ Vec_Ptr_t * vCutsNew; // new cuts by node ID
+ Vec_Ptr_t * vCutsOld; // old cuts by node ID
+ Vec_Ptr_t * vCutsTemp; // temp cuts for cutset nodes by cutset node number
// memory management
Extra_MmFixed_t * pMmCuts;
int EntrySize;
+ int nTruthWords;
// temporary variables
Cut_Cut_t * pReady;
Vec_Ptr_t * vTemp;
int fCompl0;
int fCompl1;
int fSimul;
- // precomputations
- unsigned uTruthVars[6][2];
- unsigned short ** pPerms43;
- unsigned ** pPerms53;
- unsigned ** pPerms54;
+ int nNodeCuts;
+ Cut_Cut_t * pStore0[2];
+ Cut_Cut_t * pStore1[2];
+ Cut_Cut_t * pCompareOld;
+ Cut_Cut_t * pCompareNew;
+ unsigned * puTemp[4];
+ // record of the cut computation
+ Vec_Int_t * vNodeCuts; // the number of cuts for each node
+ Vec_Int_t * vNodeStarts; // the number of the starting cut of each node
+ Vec_Int_t * vCutPairs; // the pairs of parent cuts for each cut
+ // minimum delay mapping with the given cuts
+ Vec_Ptr_t * vCutsMax;
+ Vec_Int_t * vDelays;
+ Vec_Int_t * vDelays2;
+ int nDelayMin;
// statistics
int nCutsCur;
int nCutsAlloc;
int nCutsDealloc;
int nCutsPeak;
int nCutsTriv;
- int nCutsNode;
+ int nCutsFilter;
+ int nCutsLimit;
int nNodes;
+ int nNodesDag;
+ int nNodesNoCuts;
// runtime
int timeMerge;
int timeUnion;
int timeTruth;
int timeFilter;
int timeHash;
+ int timeMap;
};
+// iterator through all the cuts of the list
+#define Cut_ListForEachCut( pList, pCut ) \
+ for ( pCut = pList; \
+ pCut; \
+ pCut = pCut->pNext )
+#define Cut_ListForEachCutStop( pList, pCut, pStop ) \
+ for ( pCut = pList; \
+ pCut != pStop; \
+ pCut = pCut->pNext )
+#define Cut_ListForEachCutSafe( pList, pCut, pCut2 ) \
+ for ( pCut = pList, \
+ pCut2 = pCut? pCut->pNext: NULL; \
+ pCut; \
+ pCut = pCut2, \
+ pCut2 = pCut? pCut->pNext: NULL )
+
////////////////////////////////////////////////////////////////////////
-/// MACRO DEFITIONS ///
+/// MACRO DEFINITIONS ///
////////////////////////////////////////////////////////////////////////
+// computes signature of the node
+static inline unsigned Cut_NodeSign( int Node ) { return (1 << (Node % 31)); }
+static inline int Cut_TruthWords( int nVarsMax ) { return nVarsMax <= 5 ? 1 : (1 << (nVarsMax - 5)); }
+
////////////////////////////////////////////////////////////////////////
/// FUNCTION DECLARATIONS ///
////////////////////////////////////////////////////////////////////////
+/*=== cutCut.c ==========================================================*/
+extern Cut_Cut_t * Cut_CutAlloc( Cut_Man_t * p );
+extern void Cut_CutRecycle( Cut_Man_t * p, Cut_Cut_t * pCut );
+extern int Cut_CutCompare( Cut_Cut_t * pCut1, Cut_Cut_t * pCut2 );
+extern Cut_Cut_t * Cut_CutDupList( Cut_Man_t * p, Cut_Cut_t * pList );
+extern void Cut_CutRecycleList( Cut_Man_t * p, Cut_Cut_t * pList );
+extern Cut_Cut_t * Cut_CutMergeLists( Cut_Cut_t * pList1, Cut_Cut_t * pList2 );
+extern void Cut_CutNumberList( Cut_Cut_t * pList );
+extern Cut_Cut_t * Cut_CutCreateTriv( Cut_Man_t * p, int Node );
+extern void Cut_CutPrintMerge( Cut_Cut_t * pCut, Cut_Cut_t * pCut0, Cut_Cut_t * pCut1 );
/*=== cutMerge.c ==========================================================*/
extern Cut_Cut_t * Cut_CutMergeTwo( Cut_Man_t * p, Cut_Cut_t * pCut0, Cut_Cut_t * pCut1 );
/*=== cutNode.c ==========================================================*/
-extern Cut_Cut_t * Cut_CutAlloc( Cut_Man_t * p );
+extern void Cut_NodeDoComputeCuts( Cut_Man_t * p, Cut_List_t * pSuper, int Node, int fCompl0, int fCompl1, Cut_Cut_t * pList0, Cut_Cut_t * pList1, int fTriv, int TreeCode );
+extern int Cut_CutListVerify( Cut_Cut_t * pList );
/*=== cutTable.c ==========================================================*/
extern Cut_HashTable_t * Cut_TableStart( int Size );
extern void Cut_TableStop( Cut_HashTable_t * pTable );
@@ -98,11 +146,12 @@ extern int Cut_TableLookup( Cut_HashTable_t * pTable, Cut_Cut_t
extern void Cut_TableClear( Cut_HashTable_t * pTable );
extern int Cut_TableReadTime( Cut_HashTable_t * pTable );
/*=== cutTruth.c ==========================================================*/
-extern void Cut_TruthCompute( Cut_Man_t * p, Cut_Cut_t * pCut, Cut_Cut_t * pCut0, Cut_Cut_t * pCut1 );
+extern void Cut_TruthComputeOld( Cut_Cut_t * pCut, Cut_Cut_t * pCut0, Cut_Cut_t * pCut1, int fCompl0, int fCompl1 );
+extern void Cut_TruthCompute( Cut_Man_t * p, Cut_Cut_t * pCut, Cut_Cut_t * pCut0, Cut_Cut_t * pCut1, int fCompl0, int fCompl1 );
+
+#endif
////////////////////////////////////////////////////////////////////////
/// END OF FILE ///
////////////////////////////////////////////////////////////////////////
-#endif
-
diff --git a/src/opt/cut/cutList.h b/src/opt/cut/cutList.h
index eb008ef9..a03ec9d5 100644
--- a/src/opt/cut/cutList.h
+++ b/src/opt/cut/cutList.h
@@ -36,12 +36,12 @@
typedef struct Cut_ListStruct_t_ Cut_List_t;
struct Cut_ListStruct_t_
{
- Cut_Cut_t * pHead[7];
- Cut_Cut_t ** ppTail[7];
+ Cut_Cut_t * pHead[CUT_SIZE_MAX+1];
+ Cut_Cut_t ** ppTail[CUT_SIZE_MAX+1];
};
////////////////////////////////////////////////////////////////////////
-/// MACRO DEFITIONS ///
+/// MACRO DEFINITIONS ///
////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////
@@ -50,7 +50,7 @@ struct Cut_ListStruct_t_
/**Function*************************************************************
- Synopsis []
+ Synopsis [Start the cut list.]
Description []
@@ -62,7 +62,7 @@ struct Cut_ListStruct_t_
static inline void Cut_ListStart( Cut_List_t * p )
{
int i;
- for ( i = 1; i <= 6; i++ )
+ for ( i = 1; i <= CUT_SIZE_MAX; i++ )
{
p->pHead[i] = 0;
p->ppTail[i] = &p->pHead[i];
@@ -71,7 +71,7 @@ static inline void Cut_ListStart( Cut_List_t * p )
/**Function*************************************************************
- Synopsis []
+ Synopsis [Adds one cut to the cut list.]
Description []
@@ -82,14 +82,100 @@ static inline void Cut_ListStart( Cut_List_t * p )
***********************************************************************/
static inline void Cut_ListAdd( Cut_List_t * p, Cut_Cut_t * pCut )
{
- assert( pCut->nLeaves > 0 && pCut->nLeaves < 7 );
+ assert( pCut->nLeaves > 0 && pCut->nLeaves <= CUT_SIZE_MAX );
*p->ppTail[pCut->nLeaves] = pCut;
p->ppTail[pCut->nLeaves] = &pCut->pNext;
}
/**Function*************************************************************
- Synopsis []
+ Synopsis [Adds one cut to the cut list while preserving order.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+static inline void Cut_ListAdd2( Cut_List_t * p, Cut_Cut_t * pCut )
+{
+ extern int Cut_CutCompare( Cut_Cut_t * pCut1, Cut_Cut_t * pCut2 );
+ Cut_Cut_t * pTemp, ** ppSpot;
+ assert( pCut->nLeaves > 0 && pCut->nLeaves <= CUT_SIZE_MAX );
+ if ( p->pHead[pCut->nLeaves] != NULL )
+ {
+ ppSpot = &p->pHead[pCut->nLeaves];
+ for ( pTemp = p->pHead[pCut->nLeaves]; pTemp; pTemp = pTemp->pNext )
+ {
+ if ( Cut_CutCompare(pCut, pTemp) < 0 )
+ {
+ *ppSpot = pCut;
+ pCut->pNext = pTemp;
+ return;
+ }
+ else
+ ppSpot = &pTemp->pNext;
+ }
+ }
+ *p->ppTail[pCut->nLeaves] = pCut;
+ p->ppTail[pCut->nLeaves] = &pCut->pNext;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Derive the super list from the linked list of cuts.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+static inline void Cut_ListDerive( Cut_List_t * p, Cut_Cut_t * pList )
+{
+ Cut_Cut_t * pPrev;
+ int nLeaves;
+ Cut_ListStart( p );
+ while ( pList != NULL )
+ {
+ nLeaves = pList->nLeaves;
+ p->pHead[nLeaves] = pList;
+ for ( pPrev = pList, pList = pList->pNext; pList; pPrev = pList, pList = pList->pNext )
+ if ( nLeaves < (int)pList->nLeaves )
+ break;
+ p->ppTail[nLeaves] = &pPrev->pNext;
+ pPrev->pNext = NULL;
+ }
+}
+
+/**Function*************************************************************
+
+ Synopsis [Adds the second list to the first list.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+static inline void Cut_ListAddList( Cut_List_t * pOld, Cut_List_t * pNew )
+{
+ int i;
+ for ( i = 1; i <= CUT_SIZE_MAX; i++ )
+ {
+ if ( pNew->pHead[i] == NULL )
+ continue;
+ *pOld->ppTail[i] = pNew->pHead[i];
+ pOld->ppTail[i] = pNew->ppTail[i];
+ }
+}
+
+/**Function*************************************************************
+
+ Synopsis [Returns the cut list linked into one sequence of cuts.]
Description []
@@ -100,16 +186,22 @@ static inline void Cut_ListAdd( Cut_List_t * p, Cut_Cut_t * pCut )
***********************************************************************/
static inline Cut_Cut_t * Cut_ListFinish( Cut_List_t * p )
{
+ Cut_Cut_t * pHead = NULL, ** ppTail = &pHead;
int i;
- for ( i = 1; i < 6; i++ )
- *p->ppTail[i] = p->pHead[i+1];
- *p->ppTail[6] = NULL;
- return p->pHead[1];
+ for ( i = 1; i <= CUT_SIZE_MAX; i++ )
+ {
+ if ( p->pHead[i] == NULL )
+ continue;
+ *ppTail = p->pHead[i];
+ ppTail = p->ppTail[i];
+ }
+ *ppTail = NULL;
+ return pHead;
}
+#endif
+
////////////////////////////////////////////////////////////////////////
/// END OF FILE ///
////////////////////////////////////////////////////////////////////////
-#endif
-
diff --git a/src/opt/cut/cutMan.c b/src/opt/cut/cutMan.c
index 4ad3a66a..8593ef93 100644
--- a/src/opt/cut/cutMan.c
+++ b/src/opt/cut/cutMan.c
@@ -24,8 +24,10 @@
/// DECLARATIONS ///
////////////////////////////////////////////////////////////////////////
+extern void Npn_StartTruth8( uint8 uTruths[][32] );
+
////////////////////////////////////////////////////////////////////////
-/// FUNCTION DEFITIONS ///
+/// FUNCTION DEFINITIONS ///
////////////////////////////////////////////////////////////////////////
/**Function*************************************************************
@@ -43,47 +45,65 @@ Cut_Man_t * Cut_ManStart( Cut_Params_t * pParams )
{
Cut_Man_t * p;
int clk = clock();
- assert( pParams->nVarsMax >= 4 && pParams->nVarsMax <= 6 );
+// extern int nTruthDsd;
+// nTruthDsd = 0;
+ assert( pParams->nVarsMax >= 3 && pParams->nVarsMax <= CUT_SIZE_MAX );
p = ALLOC( Cut_Man_t, 1 );
memset( p, 0, sizeof(Cut_Man_t) );
// set and correct parameters
p->pParams = pParams;
- if ( p->pParams->fSeq )
- p->pParams->fHash = 1;
- // space for cuts
- p->vCuts = Vec_PtrAlloc( pParams->nIdsMax );
- Vec_PtrFill( p->vCuts, pParams->nIdsMax, NULL );
+ // prepare storage for cuts
+ p->vCutsNew = Vec_PtrAlloc( pParams->nIdsMax );
+ Vec_PtrFill( p->vCutsNew, pParams->nIdsMax, NULL );
+ // prepare storage for sequential cuts
if ( pParams->fSeq )
{
- p->vCutsNew = Vec_PtrAlloc( pParams->nIdsMax );
- Vec_PtrFill( p->vCuts, pParams->nIdsMax, NULL );
+ p->pParams->fFilter = 1;
+ p->vCutsOld = Vec_PtrAlloc( pParams->nIdsMax );
+ Vec_PtrFill( p->vCutsOld, pParams->nIdsMax, NULL );
+ p->vCutsTemp = Vec_PtrAlloc( pParams->nCutSet );
+ Vec_PtrFill( p->vCutsTemp, pParams->nCutSet, NULL );
+ if ( pParams->fTruth && pParams->nVarsMax > 5 )
+ {
+ pParams->fTruth = 0;
+ printf( "Skipping computation of truth tables for sequential cuts with more than 5 inputs.\n" );
+ }
}
- // hash tables
- if ( pParams->fHash )
- p->tTable = Cut_TableStart( p->pParams->nKeepMax );
// entry size
- p->EntrySize = sizeof(Cut_Cut_t) + (pParams->nVarsMax + pParams->fSeq) * sizeof(int);
- if ( pParams->nVarsMax == 5 )
- p->EntrySize += sizeof(unsigned);
- else if ( pParams->nVarsMax == 6 )
- p->EntrySize += 2 * sizeof(unsigned);
+ p->EntrySize = sizeof(Cut_Cut_t) + pParams->nVarsMax * sizeof(int);
+ if ( pParams->fTruth )
+ {
+ if ( pParams->nVarsMax > 14 )
+ {
+ pParams->fTruth = 0;
+ printf( "Skipping computation of truth table for more than %d inputs.\n", 14 );
+ }
+ else
+ {
+ p->nTruthWords = Cut_TruthWords( pParams->nVarsMax );
+ p->EntrySize += p->nTruthWords * sizeof(unsigned);
+ }
+ p->puTemp[0] = ALLOC( unsigned, 4 * p->nTruthWords );
+ p->puTemp[1] = p->puTemp[0] + p->nTruthWords;
+ p->puTemp[2] = p->puTemp[1] + p->nTruthWords;
+ p->puTemp[3] = p->puTemp[2] + p->nTruthWords;
+ }
+ // enable cut computation recording
+ if ( pParams->fRecord )
+ {
+ p->vNodeCuts = Vec_IntStart( pParams->nIdsMax );
+ p->vNodeStarts = Vec_IntStart( pParams->nIdsMax );
+ p->vCutPairs = Vec_IntAlloc( 0 );
+ }
+ // allocate storage for delays
+ if ( pParams->fMap && !p->pParams->fSeq )
+ {
+ p->vDelays = Vec_IntStart( pParams->nIdsMax );
+ p->vDelays2 = Vec_IntStart( pParams->nIdsMax );
+ p->vCutsMax = Vec_PtrStart( pParams->nIdsMax );
+ }
// memory for cuts
p->pMmCuts = Extra_MmFixedStart( p->EntrySize );
- // precomputations
-// if ( pParams->fTruth && pParams->nVarsMax == 4 )
-// p->pPerms43 = Extra_TruthPerm43();
-// else if ( pParams->fTruth )
-// {
-// p->pPerms53 = Extra_TruthPerm53();
-// p->pPerms54 = Extra_TruthPerm54();
-// }
- p->uTruthVars[0][1] = p->uTruthVars[0][0] = 0xAAAAAAAA; // 1010 1010 1010 1010 1010 1010 1010 1010
- p->uTruthVars[1][1] = p->uTruthVars[1][0] = 0xCCCCCCCC; // 1010 1010 1010 1010 1010 1010 1010 1010
- p->uTruthVars[2][1] = p->uTruthVars[2][0] = 0xF0F0F0F0; // 1111 0000 1111 0000 1111 0000 1111 0000
- p->uTruthVars[3][1] = p->uTruthVars[3][0] = 0xFF00FF00; // 1111 1111 0000 0000 1111 1111 0000 0000
- p->uTruthVars[4][1] = p->uTruthVars[4][0] = 0xFFFF0000; // 1111 1111 1111 1111 0000 0000 0000 0000
- p->uTruthVars[5][0] = 0x00000000;
- p->uTruthVars[5][1] = 0xFFFFFFFF;
p->vTemp = Vec_PtrAlloc( 100 );
return p;
}
@@ -103,23 +123,29 @@ void Cut_ManStop( Cut_Man_t * p )
{
Cut_Cut_t * pCut;
int i;
- Vec_PtrForEachEntry( p->vCuts, pCut, i )
- {
+// extern int nTruthDsd;
+// printf( "Decomposable cuts = %d.\n", nTruthDsd );
+
+ Vec_PtrForEachEntry( p->vCutsNew, pCut, i )
if ( pCut != NULL )
{
int k = 0;
}
- }
-
- if ( p->vCutsNew ) Vec_PtrFree( p->vCutsNew );
- if ( p->vCuts ) Vec_PtrFree( p->vCuts );
- if ( p->vFanCounts ) Vec_IntFree( p->vFanCounts );
- if ( p->pPerms43 ) free( p->pPerms43 );
- if ( p->pPerms53 ) free( p->pPerms53 );
- if ( p->pPerms54 ) free( p->pPerms54 );
- if ( p->vTemp ) Vec_PtrFree( p->vTemp );
- if ( p->tTable ) Cut_TableStop( p->tTable );
- Extra_MmFixedStop( p->pMmCuts, 0 );
+ if ( p->vCutsNew ) Vec_PtrFree( p->vCutsNew );
+ if ( p->vCutsOld ) Vec_PtrFree( p->vCutsOld );
+ if ( p->vCutsTemp ) Vec_PtrFree( p->vCutsTemp );
+ if ( p->vFanCounts ) Vec_IntFree( p->vFanCounts );
+ if ( p->vTemp ) Vec_PtrFree( p->vTemp );
+
+ if ( p->vCutsMax ) Vec_PtrFree( p->vCutsMax );
+ if ( p->vDelays ) Vec_IntFree( p->vDelays );
+ if ( p->vDelays2 ) Vec_IntFree( p->vDelays2 );
+ if ( p->vNodeCuts ) Vec_IntFree( p->vNodeCuts );
+ if ( p->vNodeStarts ) Vec_IntFree( p->vNodeStarts );
+ if ( p->vCutPairs ) Vec_IntFree( p->vCutPairs );
+ if ( p->puTemp[0] ) free( p->puTemp[0] );
+
+ Extra_MmFixedStop( p->pMmCuts );
free( p );
}
@@ -136,21 +162,66 @@ void Cut_ManStop( Cut_Man_t * p )
***********************************************************************/
void Cut_ManPrintStats( Cut_Man_t * p )
{
+ if ( p->pReady )
+ {
+ Cut_CutRecycle( p, p->pReady );
+ p->pReady = NULL;
+ }
printf( "Cut computation statistics:\n" );
printf( "Current cuts = %8d. (Trivial = %d.)\n", p->nCutsCur-p->nCutsTriv, p->nCutsTriv );
printf( "Peak cuts = %8d.\n", p->nCutsPeak );
printf( "Total allocated = %8d.\n", p->nCutsAlloc );
printf( "Total deallocated = %8d.\n", p->nCutsDealloc );
+ printf( "Cuts filtered = %8d.\n", p->nCutsFilter );
+ printf( "Nodes saturated = %8d. (Max cuts = %d.)\n", p->nCutsLimit, p->pParams->nKeepMax );
printf( "Cuts per node = %8.1f\n", ((float)(p->nCutsCur-p->nCutsTriv))/p->nNodes );
printf( "The cut size = %8d bytes.\n", p->EntrySize );
printf( "Peak memory = %8.2f Mb.\n", (float)p->nCutsPeak * p->EntrySize / (1<<20) );
+ printf( "Total nodes = %8d.\n", p->nNodes );
+ if ( p->pParams->fDag || p->pParams->fTree )
+ {
+ printf( "DAG nodes = %8d.\n", p->nNodesDag );
+ printf( "Tree nodes = %8d.\n", p->nNodes - p->nNodesDag );
+ }
+ printf( "Nodes w/o cuts = %8d.\n", p->nNodesNoCuts );
+ if ( p->pParams->fMap && !p->pParams->fSeq )
+ printf( "Mapping delay = %8d.\n", p->nDelayMin );
+
PRT( "Merge ", p->timeMerge );
PRT( "Union ", p->timeUnion );
- PRT( "Hash ", Cut_TableReadTime(p->tTable) );
PRT( "Filter", p->timeFilter );
PRT( "Truth ", p->timeTruth );
+ PRT( "Map ", p->timeMap );
+// printf( "Nodes = %d. Multi = %d. Cuts = %d. Multi = %d.\n",
+// p->nNodes, p->nNodesMulti, p->nCutsCur-p->nCutsTriv, p->nCutsMulti );
+// printf( "Count0 = %d. Count1 = %d. Count2 = %d.\n\n", p->Count0, p->Count1, p->Count2 );
}
+
+/**Function*************************************************************
+
+ Synopsis [Prints some interesting stats.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Cut_ManPrintStatsToFile( Cut_Man_t * p, char * pFileName, int TimeTotal )
+{
+ FILE * pTable;
+ pTable = fopen( "cut_stats.txt", "a+" );
+ fprintf( pTable, "%-20s ", pFileName );
+ fprintf( pTable, "%8d ", p->nNodes );
+ fprintf( pTable, "%6.1f ", ((float)(p->nCutsCur))/p->nNodes );
+ fprintf( pTable, "%6.2f ", ((float)(100.0 * p->nCutsLimit))/p->nNodes );
+ fprintf( pTable, "%6.2f ", (float)p->nCutsPeak * p->EntrySize / (1<<20) );
+ fprintf( pTable, "%6.2f ", (float)(TimeTotal)/(float)(CLOCKS_PER_SEC) );
+ fprintf( pTable, "\n" );
+ fclose( pTable );
+}
/**Function*************************************************************
@@ -168,6 +239,86 @@ void Cut_ManSetFanoutCounts( Cut_Man_t * p, Vec_Int_t * vFanCounts )
p->vFanCounts = vFanCounts;
}
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Cut_ManSetNodeAttrs( Cut_Man_t * p, Vec_Int_t * vNodeAttrs )
+{
+ p->vNodeAttrs = vNodeAttrs;
+}
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Cut_ManReadVarsMax( Cut_Man_t * p )
+{
+ return p->pParams->nVarsMax;
+}
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Cut_Params_t * Cut_ManReadParams( Cut_Man_t * p )
+{
+ return p->pParams;
+}
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Vec_Int_t * Cut_ManReadNodeAttrs( Cut_Man_t * p )
+{
+ return p->vNodeAttrs;
+}
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Cut_ManIncrementDagNodes( Cut_Man_t * p )
+{
+ p->nNodesDag++;
+}
+
////////////////////////////////////////////////////////////////////////
/// END OF FILE ///
////////////////////////////////////////////////////////////////////////
diff --git a/src/opt/cut/cutMerge.c b/src/opt/cut/cutMerge.c
index ba1afce4..d8a9989c 100644
--- a/src/opt/cut/cutMerge.c
+++ b/src/opt/cut/cutMerge.c
@@ -25,7 +25,7 @@
////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////
-/// FUNCTION DEFITIONS ///
+/// FUNCTION DEFINITIONS ///
////////////////////////////////////////////////////////////////////////
/**Function*************************************************************
@@ -39,7 +39,7 @@
SeeAlso []
***********************************************************************/
-Cut_Cut_t * Cut_CutMergeTwo( Cut_Man_t * p, Cut_Cut_t * pCut0, Cut_Cut_t * pCut1 )
+Cut_Cut_t * Cut_CutMergeTwo2( Cut_Man_t * p, Cut_Cut_t * pCut0, Cut_Cut_t * pCut1 )
{
static int M[7][3] = {{0},{0},{0},{0},{0},{0},{0}};
Cut_Cut_t * pRes;
@@ -164,7 +164,7 @@ Cut_Cut_t * Cut_CutMergeTwo( Cut_Man_t * p, Cut_Cut_t * pCut0, Cut_Cut_t * pCut1
SeeAlso []
***********************************************************************/
-Cut_Cut_t * Cut_CutMergeTwo2( Cut_Man_t * p, Cut_Cut_t * pCut0, Cut_Cut_t * pCut1 )
+Cut_Cut_t * Cut_CutMergeTwo( Cut_Man_t * p, Cut_Cut_t * pCut0, Cut_Cut_t * pCut1 )
{
Cut_Cut_t * pRes;
int * pLeaves;
@@ -526,7 +526,7 @@ Cut_Cut_t * Cut_CutMergeTwo5( Cut_Man_t * p, Cut_Cut_t * pCut0, Cut_Cut_t * pCut
return NULL;
}
pRes = Cut_CutAlloc( p );
- pRes->uTruth = (uSign1 << 8);
+ pRes->Num1 = uSign1;
}
for ( i = 0; i < (int)pCut0->nLeaves; i++ )
pRes->pLeaves[i] = pCut0->pLeaves[i];
@@ -645,7 +645,8 @@ Cut_Cut_t * Cut_CutMergeTwo5( Cut_Man_t * p, Cut_Cut_t * pCut0, Cut_Cut_t * pCut
}
assert( Count == nNodes );
pRes->nLeaves = nNodes;
- pRes->uTruth = (uSign1 << 8) | uSign0;
+ pRes->Num1 = uSign1;
+ pRes->Num0 = uSign0;
return pRes;
}
diff --git a/src/opt/cut/cutNode.c b/src/opt/cut/cutNode.c
index 8d16ac8a..1f93b14b 100644
--- a/src/opt/cut/cutNode.c
+++ b/src/opt/cut/cutNode.c
@@ -19,42 +19,21 @@
***********************************************************************/
#include "cutInt.h"
-#include "cutList.h"
////////////////////////////////////////////////////////////////////////
/// DECLARATIONS ///
////////////////////////////////////////////////////////////////////////
-static inline Cut_Cut_t * Cut_CutCreateTriv( Cut_Man_t * p, int Node );
-static inline void Cut_CutRecycle( Cut_Man_t * p, Cut_Cut_t * pCut );
-static inline int Cut_CutProcessTwo( Cut_Man_t * p, int Root, Cut_Cut_t * pCut0, Cut_Cut_t * pCut1, Cut_List_t * pSuperList );
-
-static void Cut_CutPrintMerge( Cut_Cut_t * pCut, Cut_Cut_t * pCut0, Cut_Cut_t * pCut1 );
-static void Cut_CutFilter( Cut_Man_t * p, Cut_Cut_t * pList );
-
-// iterator through all the cuts of the list
-#define Cut_ListForEachCut( pList, pCut ) \
- for ( pCut = pList; \
- pCut; \
- pCut = pCut->pNext )
-#define Cut_ListForEachCutStop( pList, pCut, pStop ) \
- for ( pCut = pList; \
- pCut != pStop; \
- pCut = pCut->pNext )
-#define Cut_ListForEachCutSafe( pList, pCut, pCut2 ) \
- for ( pCut = pList, \
- pCut2 = pCut? pCut->pNext: NULL; \
- pCut; \
- pCut = pCut2, \
- pCut2 = pCut? pCut->pNext: NULL )
+static int Cut_NodeMapping( Cut_Man_t * p, Cut_Cut_t * pCuts, int Node, int Node0, int Node1 );
+static int Cut_NodeMapping2( Cut_Man_t * p, Cut_Cut_t * pCuts, int Node, int Node0, int Node1 );
////////////////////////////////////////////////////////////////////////
-/// FUNCTION DEFITIONS ///
+/// FUNCTION DEFINITIONS ///
////////////////////////////////////////////////////////////////////////
/**Function*************************************************************
- Synopsis [Returns the pointer to the linked list of cuts.]
+ Synopsis [Returns 1 if pDom is contained in pCut.]
Description []
@@ -63,16 +42,24 @@ static void Cut_CutFilter( Cut_Man_t * p, Cut_Cut_t * pList );
SeeAlso []
***********************************************************************/
-Cut_Cut_t * Cut_NodeReadCuts( Cut_Man_t * p, int Node )
+static inline int Cut_CutCheckDominance( Cut_Cut_t * pDom, Cut_Cut_t * pCut )
{
- if ( Node >= p->vCuts->nSize )
- return NULL;
- return Vec_PtrEntry( p->vCuts, Node );
+ int i, k;
+ for ( i = 0; i < (int)pDom->nLeaves; i++ )
+ {
+ for ( k = 0; k < (int)pCut->nLeaves; k++ )
+ if ( pDom->pLeaves[i] == pCut->pLeaves[k] )
+ break;
+ if ( k == (int)pCut->nLeaves ) // node i in pDom is not contained in pCut
+ return 0;
+ }
+ // every node in pDom is contained in pCut
+ return 1;
}
/**Function*************************************************************
- Synopsis [Returns the pointer to the linked list of cuts.]
+ Synopsis [Filters cuts using dominance.]
Description []
@@ -81,14 +68,293 @@ Cut_Cut_t * Cut_NodeReadCuts( Cut_Man_t * p, int Node )
SeeAlso []
***********************************************************************/
-void Cut_NodeWriteCuts( Cut_Man_t * p, int Node, Cut_Cut_t * pList )
+static inline void Cut_CutFilter( Cut_Man_t * p, Cut_Cut_t * pList )
+{
+ Cut_Cut_t * pListR, ** ppListR = &pListR;
+ Cut_Cut_t * pCut, * pCut2, * pDom, * pPrev;
+ // save the first cut
+ *ppListR = pList, ppListR = &pList->pNext;
+ // try to filter out other cuts
+ pPrev = pList;
+ Cut_ListForEachCutSafe( pList->pNext, pCut, pCut2 )
+ {
+ assert( pCut->nLeaves > 1 );
+ // go through all the previous cuts up to pCut
+ Cut_ListForEachCutStop( pList->pNext, pDom, pCut )
+ {
+ if ( pDom->nLeaves > pCut->nLeaves )
+ continue;
+ if ( (pDom->uSign & pCut->uSign) != pDom->uSign )
+ continue;
+ if ( Cut_CutCheckDominance( pDom, pCut ) )
+ break;
+ }
+ if ( pDom != pCut ) // pDom is contained in pCut - recycle pCut
+ {
+ // make sure cuts are connected after removing
+ pPrev->pNext = pCut->pNext;
+ // recycle the cut
+ Cut_CutRecycle( p, pCut );
+ }
+ else // pDom is NOT contained in pCut - save pCut
+ {
+ *ppListR = pCut, ppListR = &pCut->pNext;
+ pPrev = pCut;
+ }
+ }
+ *ppListR = NULL;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Checks equality of one cut.]
+
+ Description [Returns 1 if the cut is removed.]
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+static inline int Cut_CutFilterOneEqual( Cut_Man_t * p, Cut_List_t * pSuperList, Cut_Cut_t * pCut )
{
- Vec_PtrWriteEntry( p->vCuts, Node, pList );
+ Cut_Cut_t * pTemp;
+ Cut_ListForEachCut( pSuperList->pHead[pCut->nLeaves], pTemp )
+ {
+ // skip the non-contained cuts
+ if ( pCut->uSign != pTemp->uSign )
+ continue;
+ // check containment seriously
+ if ( Cut_CutCheckDominance( pTemp, pCut ) )
+ {
+ p->nCutsFilter++;
+ Cut_CutRecycle( p, pCut );
+ return 1;
+ }
+ }
+ return 0;
}
/**Function*************************************************************
- Synopsis [Sets the trivial cut for the node.]
+ Synopsis [Checks containment for one cut.]
+
+ Description [Returns 1 if the cut is removed.]
+
+ SideEffects [May remove other cuts in the set.]
+
+ SeeAlso []
+
+***********************************************************************/
+static inline int Cut_CutFilterOne( Cut_Man_t * p, Cut_List_t * pSuperList, Cut_Cut_t * pCut )
+{
+ Cut_Cut_t * pTemp, * pTemp2, ** ppTail;
+ int a;
+
+ // check if this cut is filtered out by smaller cuts
+ for ( a = 2; a <= (int)pCut->nLeaves; a++ )
+ {
+ Cut_ListForEachCut( pSuperList->pHead[a], pTemp )
+ {
+ // skip the non-contained cuts
+ if ( (pTemp->uSign & pCut->uSign) != pTemp->uSign )
+ continue;
+ // check containment seriously
+ if ( Cut_CutCheckDominance( pTemp, pCut ) )
+ {
+ p->nCutsFilter++;
+ Cut_CutRecycle( p, pCut );
+ return 1;
+ }
+ }
+ }
+
+ // filter out other cuts using this one
+ for ( a = pCut->nLeaves + 1; a <= (int)pCut->nVarsMax; a++ )
+ {
+ ppTail = pSuperList->pHead + a;
+ Cut_ListForEachCutSafe( pSuperList->pHead[a], pTemp, pTemp2 )
+ {
+ // skip the non-contained cuts
+ if ( (pTemp->uSign & pCut->uSign) != pCut->uSign )
+ {
+ ppTail = &pTemp->pNext;
+ continue;
+ }
+ // check containment seriously
+ if ( Cut_CutCheckDominance( pCut, pTemp ) )
+ {
+ p->nCutsFilter++;
+ p->nNodeCuts--;
+ // move the head
+ if ( pSuperList->pHead[a] == pTemp )
+ pSuperList->pHead[a] = pTemp->pNext;
+ // move the tail
+ if ( pSuperList->ppTail[a] == &pTemp->pNext )
+ pSuperList->ppTail[a] = ppTail;
+ // skip the given cut in the list
+ *ppTail = pTemp->pNext;
+ // recycle pTemp
+ Cut_CutRecycle( p, pTemp );
+ }
+ else
+ ppTail = &pTemp->pNext;
+ }
+ assert( ppTail == pSuperList->ppTail[a] );
+ assert( *ppTail == NULL );
+ }
+
+ return 0;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Checks if the cut is local and can be removed.]
+
+ Description [Returns 1 if the cut is removed.]
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+static inline int Cut_CutFilterGlobal( Cut_Man_t * p, Cut_Cut_t * pCut )
+{
+ int a;
+ if ( pCut->nLeaves == 1 )
+ return 0;
+ for ( a = 0; a < (int)pCut->nLeaves; a++ )
+ if ( Vec_IntEntry( p->vNodeAttrs, pCut->pLeaves[a] ) ) // global
+ return 0;
+ // there is no global nodes, the cut should be removed
+ p->nCutsFilter++;
+ Cut_CutRecycle( p, pCut );
+ return 1;
+}
+
+
+/**Function*************************************************************
+
+ Synopsis [Checks containment for one cut.]
+
+ Description [Returns 1 if the cut is removed.]
+
+ SideEffects [May remove other cuts in the set.]
+
+ SeeAlso []
+
+***********************************************************************/
+static inline int Cut_CutFilterOld( Cut_Man_t * p, Cut_Cut_t * pList, Cut_Cut_t * pCut )
+{
+ Cut_Cut_t * pPrev, * pTemp, * pTemp2, ** ppTail;
+
+ // check if this cut is filtered out by smaller cuts
+ pPrev = NULL;
+ Cut_ListForEachCut( pList, pTemp )
+ {
+ if ( pTemp->nLeaves > pCut->nLeaves )
+ break;
+ pPrev = pTemp;
+ // skip the non-contained cuts
+ if ( (pTemp->uSign & pCut->uSign) != pTemp->uSign )
+ continue;
+ // check containment seriously
+ if ( Cut_CutCheckDominance( pTemp, pCut ) )
+ {
+ p->nCutsFilter++;
+ Cut_CutRecycle( p, pCut );
+ return 1;
+ }
+ }
+ assert( pPrev->pNext == pTemp );
+
+ // filter out other cuts using this one
+ ppTail = &pPrev->pNext;
+ Cut_ListForEachCutSafe( pTemp, pTemp, pTemp2 )
+ {
+ // skip the non-contained cuts
+ if ( (pTemp->uSign & pCut->uSign) != pCut->uSign )
+ {
+ ppTail = &pTemp->pNext;
+ continue;
+ }
+ // check containment seriously
+ if ( Cut_CutCheckDominance( pCut, pTemp ) )
+ {
+ p->nCutsFilter++;
+ p->nNodeCuts--;
+ // skip the given cut in the list
+ *ppTail = pTemp->pNext;
+ // recycle pTemp
+ Cut_CutRecycle( p, pTemp );
+ }
+ else
+ ppTail = &pTemp->pNext;
+ }
+ assert( *ppTail == NULL );
+ return 0;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Processes two cuts.]
+
+ Description [Returns 1 if the limit has been reached.]
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+static inline int Cut_CutProcessTwo( Cut_Man_t * p, Cut_Cut_t * pCut0, Cut_Cut_t * pCut1, Cut_List_t * pSuperList )
+{
+ Cut_Cut_t * pCut;
+ // merge the cuts
+ if ( pCut0->nLeaves >= pCut1->nLeaves )
+ pCut = Cut_CutMergeTwo( p, pCut0, pCut1 );
+ else
+ pCut = Cut_CutMergeTwo( p, pCut1, pCut0 );
+ if ( pCut == NULL )
+ return 0;
+ assert( p->pParams->fSeq || pCut->nLeaves > 1 );
+ // set the signature
+ pCut->uSign = pCut0->uSign | pCut1->uSign;
+ if ( p->pParams->fRecord )
+ pCut->Num0 = pCut0->Num0, pCut->Num1 = pCut1->Num0;
+ // check containment
+ if ( p->pParams->fFilter )
+ {
+ if ( Cut_CutFilterOne(p, pSuperList, pCut) )
+// if ( Cut_CutFilterOneEqual(p, pSuperList, pCut) )
+ return 0;
+ if ( p->pParams->fSeq )
+ {
+ if ( p->pCompareOld && Cut_CutFilterOld(p, p->pCompareOld, pCut) )
+ return 0;
+ if ( p->pCompareNew && Cut_CutFilterOld(p, p->pCompareNew, pCut) )
+ return 0;
+ }
+ }
+
+ if ( p->pParams->fGlobal )
+ {
+ assert( p->vNodeAttrs != NULL );
+ if ( Cut_CutFilterGlobal( p, pCut ) )
+ return 0;
+ }
+
+ // compute the truth table
+ if ( p->pParams->fTruth )
+ Cut_TruthCompute( p, pCut, pCut0, pCut1, p->fCompl0, p->fCompl1 );
+ // add to the list
+ Cut_ListAdd( pSuperList, pCut );
+ // return status (0 if okay; 1 if exceeded the limit)
+ return ++p->nNodeCuts == p->pParams->nKeepMax;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Computes the cuts by merging cuts at two nodes.]
Description []
@@ -97,15 +363,68 @@ void Cut_NodeWriteCuts( Cut_Man_t * p, int Node, Cut_Cut_t * pList )
SeeAlso []
***********************************************************************/
-void Cut_NodeSetTriv( Cut_Man_t * p, int Node )
+Cut_Cut_t * Cut_NodeComputeCuts( Cut_Man_t * p, int Node, int Node0, int Node1, int fCompl0, int fCompl1, int fTriv, int TreeCode )
{
- assert( Cut_NodeReadCuts(p, Node) == NULL );
- Cut_NodeWriteCuts( p, Node, Cut_CutCreateTriv(p, Node) );
+ Cut_List_t Super, * pSuper = &Super;
+ Cut_Cut_t * pList, * pCut;
+ int clk;
+ // start the number of cuts at the node
+ p->nNodes++;
+ p->nNodeCuts = 0;
+ // prepare information for recording
+ if ( p->pParams->fRecord )
+ {
+ Cut_CutNumberList( Cut_NodeReadCutsNew(p, Node0) );
+ Cut_CutNumberList( Cut_NodeReadCutsNew(p, Node1) );
+ }
+ // compute the cuts
+clk = clock();
+ Cut_ListStart( pSuper );
+ Cut_NodeDoComputeCuts( p, pSuper, Node, fCompl0, fCompl1, Cut_NodeReadCutsNew(p, Node0), Cut_NodeReadCutsNew(p, Node1), fTriv, TreeCode );
+ pList = Cut_ListFinish( pSuper );
+p->timeMerge += clock() - clk;
+ // verify the result of cut computation
+// Cut_CutListVerify( pList );
+ // performing the recording
+ if ( p->pParams->fRecord )
+ {
+ Vec_IntWriteEntry( p->vNodeStarts, Node, Vec_IntSize(p->vCutPairs) );
+ Cut_ListForEachCut( pList, pCut )
+ Vec_IntPush( p->vCutPairs, ((pCut->Num1 << 16) | pCut->Num0) );
+ Vec_IntWriteEntry( p->vNodeCuts, Node, Vec_IntSize(p->vCutPairs) - Vec_IntEntry(p->vNodeStarts, Node) );
+ }
+ // check if the node is over the list
+ if ( p->nNodeCuts == p->pParams->nKeepMax )
+ p->nCutsLimit++;
+ // set the list at the node
+ Vec_PtrFillExtra( p->vCutsNew, Node + 1, NULL );
+ assert( Cut_NodeReadCutsNew(p, Node) == NULL );
+ /////
+// pList->pNext = NULL;
+ /////
+ Cut_NodeWriteCutsNew( p, Node, pList );
+ // filter the cuts
+//clk = clock();
+// if ( p->pParams->fFilter )
+// Cut_CutFilter( p, pList0 );
+//p->timeFilter += clock() - clk;
+ // perform mapping of this node with these cuts
+clk = clock();
+ if ( p->pParams->fMap && !p->pParams->fSeq )
+ {
+// int Delay1, Delay2;
+// Delay1 = Cut_NodeMapping( p, pList, Node, Node0, Node1 );
+// Delay2 = Cut_NodeMapping2( p, pList, Node, Node0, Node1 );
+// assert( Delay1 >= Delay2 );
+ Cut_NodeMapping( p, pList, Node, Node0, Node1 );
+ }
+p->timeMap += clock() - clk;
+ return pList;
}
/**Function*************************************************************
- Synopsis [Deallocates the cuts at the node.]
+ Synopsis [Returns optimum delay mapping.]
Description []
@@ -114,21 +433,96 @@ void Cut_NodeSetTriv( Cut_Man_t * p, int Node )
SeeAlso []
***********************************************************************/
-void Cut_NodeFreeCuts( Cut_Man_t * p, int Node )
+int Cut_NodeMapping2( Cut_Man_t * p, Cut_Cut_t * pCuts, int Node, int Node0, int Node1 )
{
- Cut_Cut_t * pList, * pCut, * pCut2;
- pList = Cut_NodeReadCuts( p, Node );
- if ( pList == NULL )
- return;
- Cut_ListForEachCutSafe( pList, pCut, pCut2 )
- Cut_CutRecycle( p, pCut );
- Cut_NodeWriteCuts( p, Node, NULL );
+ Cut_Cut_t * pCut;
+ int DelayMin, DelayCur, i;
+ if ( pCuts == NULL )
+ p->nDelayMin = -1;
+ if ( p->nDelayMin == -1 )
+ return -1;
+ DelayMin = 1000000;
+ Cut_ListForEachCut( pCuts, pCut )
+ {
+ if ( pCut->nLeaves == 1 )
+ continue;
+ DelayCur = 0;
+ for ( i = 0; i < (int)pCut->nLeaves; i++ )
+ if ( DelayCur < Vec_IntEntry(p->vDelays, pCut->pLeaves[i]) )
+ DelayCur = Vec_IntEntry(p->vDelays, pCut->pLeaves[i]);
+ if ( DelayMin > DelayCur )
+ DelayMin = DelayCur;
+ }
+ if ( DelayMin == 1000000 )
+ {
+ p->nDelayMin = -1;
+ return -1;
+ }
+ DelayMin++;
+ Vec_IntWriteEntry( p->vDelays, Node, DelayMin );
+ if ( p->nDelayMin < DelayMin )
+ p->nDelayMin = DelayMin;
+ return DelayMin;
}
+/**Function*************************************************************
+
+ Synopsis [Returns optimum delay mapping using the largest cut.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Cut_NodeMapping( Cut_Man_t * p, Cut_Cut_t * pCuts, int Node, int Node0, int Node1 )
+{
+ Cut_Cut_t * pCut0, * pCut1, * pCut;
+ int Delay0, Delay1, Delay;
+ // get the fanin cuts
+ Delay0 = Vec_IntEntry( p->vDelays2, Node0 );
+ Delay1 = Vec_IntEntry( p->vDelays2, Node1 );
+ pCut0 = (Delay0 == 0) ? Vec_PtrEntry( p->vCutsNew, Node0 ) : Vec_PtrEntry( p->vCutsMax, Node0 );
+ pCut1 = (Delay1 == 0) ? Vec_PtrEntry( p->vCutsNew, Node1 ) : Vec_PtrEntry( p->vCutsMax, Node1 );
+ if ( Delay0 == Delay1 )
+ Delay = (Delay0 == 0) ? Delay0 + 1: Delay0;
+ else if ( Delay0 > Delay1 )
+ {
+ Delay = Delay0;
+ pCut1 = Vec_PtrEntry( p->vCutsNew, Node1 );
+ assert( pCut1->nLeaves == 1 );
+ }
+ else // if ( Delay0 < Delay1 )
+ {
+ Delay = Delay1;
+ pCut0 = Vec_PtrEntry( p->vCutsNew, Node0 );
+ assert( pCut0->nLeaves == 1 );
+ }
+ // merge the cuts
+ if ( pCut0->nLeaves < pCut1->nLeaves )
+ pCut = Cut_CutMergeTwo( p, pCut1, pCut0 );
+ else
+ pCut = Cut_CutMergeTwo( p, pCut0, pCut1 );
+ if ( pCut == NULL )
+ {
+ Delay++;
+ pCut = Cut_CutAlloc( p );
+ pCut->nLeaves = 2;
+ pCut->pLeaves[0] = Node0 < Node1 ? Node0 : Node1;
+ pCut->pLeaves[1] = Node0 < Node1 ? Node1 : Node0;
+ }
+ assert( Delay > 0 );
+ Vec_IntWriteEntry( p->vDelays2, Node, Delay );
+ Vec_PtrWriteEntry( p->vCutsMax, Node, pCut );
+ if ( p->nDelayMin < Delay )
+ p->nDelayMin = Delay;
+ return Delay;
+}
/**Function*************************************************************
- Synopsis []
+ Synopsis [Computes area after mapping.]
Description []
@@ -137,10 +531,23 @@ void Cut_NodeFreeCuts( Cut_Man_t * p, int Node )
SeeAlso []
***********************************************************************/
-void Cut_NodeSetComputedAsNew( Cut_Man_t * p, int Node )
+int Cut_ManMappingArea_rec( Cut_Man_t * p, int Node )
{
+ Cut_Cut_t * pCut;
+ int i, Counter;
+ if ( p->vCutsMax == NULL )
+ return 0;
+ pCut = Vec_PtrEntry( p->vCutsMax, Node );
+ if ( pCut == NULL || pCut->nLeaves == 1 )
+ return 0;
+ Counter = 0;
+ for ( i = 0; i < (int)pCut->nLeaves; i++ )
+ Counter += Cut_ManMappingArea_rec( p, pCut->pLeaves[i] );
+ Vec_PtrWriteEntry( p->vCutsMax, Node, NULL );
+ return 1 + Counter;
}
+
/**Function*************************************************************
Synopsis [Computes the cuts by merging cuts at two nodes.]
@@ -152,24 +559,43 @@ void Cut_NodeSetComputedAsNew( Cut_Man_t * p, int Node )
SeeAlso []
***********************************************************************/
-Cut_Cut_t * Cut_NodeComputeCuts( Cut_Man_t * p, int Node, int Node0, int Node1, int fCompl0, int fCompl1 )
+void Cut_NodeDoComputeCuts( Cut_Man_t * p, Cut_List_t * pSuper, int Node, int fCompl0, int fCompl1, Cut_Cut_t * pList0, Cut_Cut_t * pList1, int fTriv, int TreeCode )
{
- Cut_List_t SuperList;
- Cut_Cut_t * pList0, * pList1, * pStop0, * pStop1, * pTemp0, * pTemp1;
- int i, Limit = p->pParams->nVarsMax;
- int clk = clock();
- assert( p->pParams->nVarsMax <= 6 );
- // start the new list
- Cut_ListStart( &SuperList );
+ Cut_Cut_t * pStop0, * pStop1, * pTemp0, * pTemp1, * pStore0, * pStore1;
+ int i, nCutsOld, Limit;
+ // start with the elementary cut
+ if ( fTriv )
+ {
+// printf( "Creating trivial cut %d.\n", Node );
+ pTemp0 = Cut_CutCreateTriv( p, Node );
+ Cut_ListAdd( pSuper, pTemp0 );
+ p->nNodeCuts++;
+ }
// get the cut lists of children
- pList0 = Cut_NodeReadCuts( p, Node0 );
- pList1 = Cut_NodeReadCuts( p, Node1 );
- assert( pList0 && pList1 );
+ if ( pList0 == NULL || pList1 == NULL || (p->pParams->fLocal && TreeCode) )
+ return;
+
+ // remember the old number of cuts
+ nCutsOld = p->nCutsCur;
+ Limit = p->pParams->nVarsMax;
// get the simultation bit of the node
p->fSimul = (fCompl0 ^ pList0->fSimul) & (fCompl1 ^ pList1->fSimul);
// set temporary variables
p->fCompl0 = fCompl0;
p->fCompl1 = fCompl1;
+ // if tree cuts are computed, make sure only the unit cuts propagate over the DAG nodes
+ if ( TreeCode & 1 )
+ {
+ assert( pList0->nLeaves == 1 );
+ pStore0 = pList0->pNext;
+ pList0->pNext = NULL;
+ }
+ if ( TreeCode & 2 )
+ {
+ assert( pList1->nLeaves == 1 );
+ pStore1 = pList1->pNext;
+ pList1->pNext = NULL;
+ }
// find the point in the list where the max-var cuts begin
Cut_ListForEachCut( pList0, pStop0 )
if ( pStop0->nLeaves == (unsigned)Limit )
@@ -177,101 +603,54 @@ Cut_Cut_t * Cut_NodeComputeCuts( Cut_Man_t * p, int Node, int Node0, int Node1,
Cut_ListForEachCut( pList1, pStop1 )
if ( pStop1->nLeaves == (unsigned)Limit )
break;
- // start with the elementary cut
- pTemp0 = Cut_CutCreateTriv( p, Node );
- Cut_ListAdd( &SuperList, pTemp0 );
- p->nCutsNode = 1;
+
// small by small
Cut_ListForEachCutStop( pList0, pTemp0, pStop0 )
Cut_ListForEachCutStop( pList1, pTemp1, pStop1 )
- if ( Cut_CutProcessTwo( p, Node, pTemp0, pTemp1, &SuperList ) )
- goto finish;
- // all by large
- Cut_ListForEachCut( pList0, pTemp0 )
+ {
+ if ( Cut_CutProcessTwo( p, pTemp0, pTemp1, pSuper ) )
+ goto Quits;
+ }
+ // small by large
+ Cut_ListForEachCutStop( pList0, pTemp0, pStop0 )
Cut_ListForEachCut( pStop1, pTemp1 )
- if ( Cut_CutProcessTwo( p, Node, pTemp0, pTemp1, &SuperList ) )
- goto finish;
- // all by large
- Cut_ListForEachCut( pList1, pTemp1 )
+ {
+ if ( (pTemp0->uSign & pTemp1->uSign) != pTemp0->uSign )
+ continue;
+ if ( Cut_CutProcessTwo( p, pTemp0, pTemp1, pSuper ) )
+ goto Quits;
+ }
+ // small by large
+ Cut_ListForEachCutStop( pList1, pTemp1, pStop1 )
Cut_ListForEachCut( pStop0, pTemp0 )
- if ( Cut_CutProcessTwo( p, Node, pTemp0, pTemp1, &SuperList ) )
- goto finish;
+ {
+ if ( (pTemp0->uSign & pTemp1->uSign) != pTemp1->uSign )
+ continue;
+ if ( Cut_CutProcessTwo( p, pTemp0, pTemp1, pSuper ) )
+ goto Quits;
+ }
// large by large
Cut_ListForEachCut( pStop0, pTemp0 )
Cut_ListForEachCut( pStop1, pTemp1 )
{
assert( pTemp0->nLeaves == (unsigned)Limit && pTemp1->nLeaves == (unsigned)Limit );
+ if ( pTemp0->uSign != pTemp1->uSign )
+ continue;
for ( i = 0; i < Limit; i++ )
if ( pTemp0->pLeaves[i] != pTemp1->pLeaves[i] )
break;
if ( i < Limit )
continue;
- if ( Cut_CutProcessTwo( p, Node, pTemp0, pTemp1, &SuperList ) )
- goto finish;
- }
-finish :
- // set the list at the node
- Vec_PtrFillExtra( p->vCuts, Node + 1, NULL );
- assert( Cut_NodeReadCuts(p, Node) == NULL );
- pList0 = Cut_ListFinish( &SuperList );
- Cut_NodeWriteCuts( p, Node, pList0 );
- // clear the hash table
- if ( p->pParams->fHash && !p->pParams->fSeq )
- Cut_TableClear( p->tTable );
- // consider dropping the fanins cuts
- if ( p->pParams->fDrop )
- {
- Cut_NodeTryDroppingCuts( p, Node0 );
- Cut_NodeTryDroppingCuts( p, Node1 );
- }
-p->timeMerge += clock() - clk;
- // filter the cuts
-clk = clock();
- if ( p->pParams->fFilter )
- Cut_CutFilter( p, pList0 );
-p->timeFilter += clock() - clk;
- p->nNodes++;
- return pList0;
-}
-
-/**Function*************************************************************
-
- Synopsis [Processes two cuts.]
-
- Description [Returns 1 if the limit has been reached.]
-
- SideEffects []
-
- SeeAlso []
-
-***********************************************************************/
-int Cut_CutProcessTwo( Cut_Man_t * p, int Root, Cut_Cut_t * pCut0, Cut_Cut_t * pCut1, Cut_List_t * pSuperList )
-{
- Cut_Cut_t * pCut;
- // merge the cuts
- if ( pCut0->nLeaves >= pCut1->nLeaves )
- pCut = Cut_CutMergeTwo( p, pCut0, pCut1 );
- else
- pCut = Cut_CutMergeTwo( p, pCut1, pCut0 );
- if ( pCut == NULL )
- return 0;
- assert( pCut->nLeaves > 1 );
- // add the root if sequential
- if ( p->pParams->fSeq )
- pCut->pLeaves[pCut->nLeaves] = Root;
- // check the lookup table
- if ( p->pParams->fHash && Cut_TableLookup( p->tTable, pCut, !p->pParams->fSeq ) )
- {
- Cut_CutRecycle( p, pCut );
- return 0;
- }
- // compute the truth table
- if ( p->pParams->fTruth )
- Cut_TruthCompute( p, pCut, pCut0, pCut1 );
- // add to the list
- Cut_ListAdd( pSuperList, pCut );
- // return status (0 if okay; 1 if exceeded the limit)
- return ++p->nCutsNode == p->pParams->nKeepMax;
+ if ( Cut_CutProcessTwo( p, pTemp0, pTemp1, pSuper ) )
+ goto Quits;
+ }
+ if ( p->nNodeCuts == 0 )
+ p->nNodesNoCuts++;
+Quits:
+ if ( TreeCode & 1 )
+ pList0->pNext = pStore0;
+ if ( TreeCode & 2 )
+ pList1->pNext = pStore1;
}
/**Function*************************************************************
@@ -287,33 +666,32 @@ int Cut_CutProcessTwo( Cut_Man_t * p, int Root, Cut_Cut_t * pCut0, Cut_Cut_t * p
***********************************************************************/
Cut_Cut_t * Cut_NodeUnionCuts( Cut_Man_t * p, Vec_Int_t * vNodes )
{
- Cut_List_t SuperList;
+ Cut_List_t Super, * pSuper = &Super;
Cut_Cut_t * pList, * pListStart, * pCut, * pCut2, * pTop;
int i, k, Node, Root, Limit = p->pParams->nVarsMax;
int clk = clock();
- assert( p->pParams->nVarsMax <= 6 );
-
// start the new list
- Cut_ListStart( &SuperList );
+ Cut_ListStart( pSuper );
// remember the root node to save the resulting cuts
Root = Vec_IntEntry( vNodes, 0 );
- p->nCutsNode = 1;
+ p->nNodeCuts = 1;
// collect small cuts first
Vec_PtrClear( p->vTemp );
Vec_IntForEachEntry( vNodes, Node, i )
{
// get the cuts of this node
- pList = Cut_NodeReadCuts( p, Node );
- Cut_NodeWriteCuts( p, Node, NULL );
+ pList = Cut_NodeReadCutsNew( p, Node );
+ Cut_NodeWriteCutsNew( p, Node, NULL );
assert( pList );
// remember the starting point
pListStart = pList->pNext;
+ pList->pNext = NULL;
// save or recycle the elementary cut
if ( i == 0 )
- Cut_ListAdd( &SuperList, pList ), pTop = pList;
+ Cut_ListAdd( pSuper, pList ), pTop = pList;
else
Cut_CutRecycle( p, pList );
// save all the cuts that are smaller than the limit
@@ -324,20 +702,19 @@ Cut_Cut_t * Cut_NodeUnionCuts( Cut_Man_t * p, Vec_Int_t * vNodes )
Vec_PtrPush( p->vTemp, pCut );
break;
}
- // check hash tables
- if ( p->pParams->fHash && Cut_TableLookup( p->tTable, pCut, !p->pParams->fSeq ) )
- {
- Cut_CutRecycle( p, pCut );
+ // check containment
+ if ( p->pParams->fFilter && Cut_CutFilterOne( p, pSuper, pCut ) )
continue;
- }
// set the complemented bit by comparing the first cut with the current cut
pCut->fCompl = pTop->fSimul ^ pCut->fSimul;
+ pListStart = pCut->pNext;
+ pCut->pNext = NULL;
// add to the list
- Cut_ListAdd( &SuperList, pCut );
- if ( ++p->nCutsNode == p->pParams->nKeepMax )
+ Cut_ListAdd( pSuper, pCut );
+ if ( ++p->nNodeCuts == p->pParams->nKeepMax )
{
// recycle the rest of the cuts of this node
- Cut_ListForEachCutSafe( pCut->pNext, pCut, pCut2 )
+ Cut_ListForEachCutSafe( pListStart, pCut, pCut2 )
Cut_CutRecycle( p, pCut );
// recycle all cuts of other nodes
Vec_IntForEachEntryStart( vNodes, Node, k, i+1 )
@@ -349,25 +726,25 @@ Cut_Cut_t * Cut_NodeUnionCuts( Cut_Man_t * p, Vec_Int_t * vNodes )
goto finish;
}
}
- }
+ }
// collect larger cuts next
Vec_PtrForEachEntry( p->vTemp, pList, i )
{
Cut_ListForEachCutSafe( pList, pCut, pCut2 )
{
- if ( p->pParams->fHash && Cut_TableLookup( p->tTable, pCut, !p->pParams->fSeq ) )
- {
- Cut_CutRecycle( p, pCut );
+ // check containment
+ if ( p->pParams->fFilter && Cut_CutFilterOne( p, pSuper, pCut ) )
continue;
- }
// set the complemented bit
pCut->fCompl = pTop->fSimul ^ pCut->fSimul;
+ pListStart = pCut->pNext;
+ pCut->pNext = NULL;
// add to the list
- Cut_ListAdd( &SuperList, pCut );
- if ( ++p->nCutsNode == p->pParams->nKeepMax )
+ Cut_ListAdd( pSuper, pCut );
+ if ( ++p->nNodeCuts == p->pParams->nKeepMax )
{
// recycle the rest of the cuts
- Cut_ListForEachCutSafe( pCut->pNext, pCut, pCut2 )
+ Cut_ListForEachCutSafe( pListStart, pCut, pCut2 )
Cut_CutRecycle( p, pCut );
// recycle the saved cuts of other nodes
Vec_PtrForEachEntryStart( p->vTemp, pList, k, i+1 )
@@ -379,97 +756,22 @@ Cut_Cut_t * Cut_NodeUnionCuts( Cut_Man_t * p, Vec_Int_t * vNodes )
}
finish :
// set the cuts at the node
- assert( Cut_NodeReadCuts(p, Root) == NULL );
- pList = Cut_ListFinish( &SuperList );
- Cut_NodeWriteCuts( p, Root, pList );
- // clear the hash table
- if ( p->pParams->fHash && !p->pParams->fSeq )
- Cut_TableClear( p->tTable );
+ assert( Cut_NodeReadCutsNew(p, Root) == NULL );
+ pList = Cut_ListFinish( pSuper );
+ Cut_NodeWriteCutsNew( p, Root, pList );
p->timeUnion += clock() - clk;
// filter the cuts
-clk = clock();
- if ( p->pParams->fFilter )
- Cut_CutFilter( p, pList );
-p->timeFilter += clock() - clk;
+//clk = clock();
+// if ( p->pParams->fFilter )
+// Cut_CutFilter( p, pList );
+//p->timeFilter += clock() - clk;
p->nNodes -= vNodes->nSize - 1;
return pList;
}
/**Function*************************************************************
- Synopsis [Start the cut computation.]
-
- Description []
-
- SideEffects []
-
- SeeAlso []
-
-***********************************************************************/
-Cut_Cut_t * Cut_CutAlloc( Cut_Man_t * p )
-{
- Cut_Cut_t * pCut;
- // cut allocation
- pCut = (Cut_Cut_t *)Extra_MmFixedEntryFetch( p->pMmCuts );
- memset( pCut, 0, sizeof(Cut_Cut_t) );
- pCut->nVarsMax = p->pParams->nVarsMax;
- pCut->fSeq = p->pParams->fSeq;
- pCut->fSimul = p->fSimul;
- // statistics
- p->nCutsAlloc++;
- p->nCutsCur++;
- if ( p->nCutsPeak < p->nCutsAlloc - p->nCutsDealloc )
- p->nCutsPeak = p->nCutsAlloc - p->nCutsDealloc;
- return pCut;
-}
-
-/**Function*************************************************************
-
- Synopsis [Start the cut computation.]
-
- Description []
-
- SideEffects []
-
- SeeAlso []
-
-***********************************************************************/
-Cut_Cut_t * Cut_CutCreateTriv( Cut_Man_t * p, int Node )
-{
- Cut_Cut_t * pCut;
- pCut = Cut_CutAlloc( p );
- pCut->nLeaves = 1;
- pCut->pLeaves[0] = Node;
- if ( p->pParams->fTruth )
- Cut_CutWriteTruth( pCut, p->uTruthVars[0] );
- p->nCutsTriv++;
- return pCut;
-}
-
-/**Function*************************************************************
-
- Synopsis [Start the cut computation.]
-
- Description []
-
- SideEffects []
-
- SeeAlso []
-
-***********************************************************************/
-void Cut_CutRecycle( Cut_Man_t * p, Cut_Cut_t * pCut )
-{
- p->nCutsDealloc++;
- p->nCutsCur--;
- if ( pCut->nLeaves == 1 )
- p->nCutsTriv--;
- Extra_MmFixedEntryRecycle( p->pMmCuts, (char *)pCut );
-}
-
-
-/**Function*************************************************************
-
- Synopsis [Consider dropping cuts if they are useless by now.]
+ Synopsis [Computes the cuts by unioning cuts at a choice node.]
Description []
@@ -478,85 +780,182 @@ void Cut_CutRecycle( Cut_Man_t * p, Cut_Cut_t * pCut )
SeeAlso []
***********************************************************************/
-void Cut_NodeTryDroppingCuts( Cut_Man_t * p, int Node )
+Cut_Cut_t * Cut_NodeUnionCutsSeq( Cut_Man_t * p, Vec_Int_t * vNodes, int CutSetNum, int fFirst )
{
- int nFanouts;
- assert( p->vFanCounts );
- nFanouts = Vec_IntEntry( p->vFanCounts, Node );
- assert( nFanouts > 0 );
- if ( --nFanouts == 0 )
- Cut_NodeFreeCuts( p, Node );
- Vec_IntWriteEntry( p->vFanCounts, Node, nFanouts );
-}
+ Cut_List_t Super, * pSuper = &Super;
+ Cut_Cut_t * pList, * pListStart, * pCut, * pCut2, * pTop;
+ int i, k, Node, Root, Limit = p->pParams->nVarsMax;
+ int clk = clock();
-/**Function*************************************************************
+ // start the new list
+ Cut_ListStart( pSuper );
- Synopsis [Print the cut.]
+ // remember the root node to save the resulting cuts
+ Root = Vec_IntEntry( vNodes, 0 );
+ p->nNodeCuts = 1;
- Description []
-
- SideEffects []
+ // store the original lists for comparison
+ p->pCompareOld = Cut_NodeReadCutsOld( p, Root );
+ p->pCompareNew = (CutSetNum >= 0)? Cut_NodeReadCutsNew( p, Root ) : NULL;
- SeeAlso []
+ // get the topmost cut
+ pTop = NULL;
+ if ( (pTop = Cut_NodeReadCutsOld( p, Root )) == NULL )
+ pTop = Cut_NodeReadCutsNew( p, Root );
+ assert( pTop != NULL );
-***********************************************************************/
-void Cut_CutPrint( Cut_Cut_t * pCut )
-{
- int i;
- assert( pCut->nLeaves > 0 );
- printf( "%d : {", pCut->nLeaves );
- for ( i = 0; i < (int)pCut->nLeaves; i++ )
- printf( " %d", pCut->pLeaves[i] );
- printf( " }" );
-}
+ // collect small cuts first
+ Vec_PtrClear( p->vTemp );
+ Vec_IntForEachEntry( vNodes, Node, i )
+ {
+ // get the cuts of this node
+ if ( i == 0 && CutSetNum >= 0 )
+ {
+ pList = Cut_NodeReadCutsTemp( p, CutSetNum );
+ Cut_NodeWriteCutsTemp( p, CutSetNum, NULL );
+ }
+ else
+ {
+ pList = Cut_NodeReadCutsNew( p, Node );
+ Cut_NodeWriteCutsNew( p, Node, NULL );
+ }
+ if ( pList == NULL )
+ continue;
-/**Function*************************************************************
+ // process the cuts
+ if ( fFirst )
+ {
+ // remember the starting point
+ pListStart = pList->pNext;
+ pList->pNext = NULL;
+ // save or recycle the elementary cut
+ if ( i == 0 )
+ Cut_ListAdd( pSuper, pList );
+ else
+ Cut_CutRecycle( p, pList );
+ }
+ else
+ pListStart = pList;
- Synopsis [Consider dropping cuts if they are useless by now.]
+ // save all the cuts that are smaller than the limit
+ Cut_ListForEachCutSafe( pListStart, pCut, pCut2 )
+ {
+ if ( pCut->nLeaves == (unsigned)Limit )
+ {
+ Vec_PtrPush( p->vTemp, pCut );
+ break;
+ }
+ // check containment
+// if ( p->pParams->fFilter && Cut_CutFilterOne( p, pSuper, pCut ) )
+// continue;
+ if ( p->pParams->fFilter )
+ {
+ if ( Cut_CutFilterOne(p, pSuper, pCut) )
+ continue;
+ if ( p->pParams->fSeq )
+ {
+ if ( p->pCompareOld && Cut_CutFilterOld(p, p->pCompareOld, pCut) )
+ continue;
+ if ( p->pCompareNew && Cut_CutFilterOld(p, p->pCompareNew, pCut) )
+ continue;
+ }
+ }
- Description []
-
- SideEffects []
+ // set the complemented bit by comparing the first cut with the current cut
+ pCut->fCompl = pTop->fSimul ^ pCut->fSimul;
+ pListStart = pCut->pNext;
+ pCut->pNext = NULL;
+ // add to the list
+ Cut_ListAdd( pSuper, pCut );
+ if ( ++p->nNodeCuts == p->pParams->nKeepMax )
+ {
+ // recycle the rest of the cuts of this node
+ Cut_ListForEachCutSafe( pListStart, pCut, pCut2 )
+ Cut_CutRecycle( p, pCut );
+ // recycle all cuts of other nodes
+ Vec_IntForEachEntryStart( vNodes, Node, k, i+1 )
+ Cut_NodeFreeCuts( p, Node );
+ // recycle the saved cuts of other nodes
+ Vec_PtrForEachEntry( p->vTemp, pList, k )
+ Cut_ListForEachCutSafe( pList, pCut, pCut2 )
+ Cut_CutRecycle( p, pCut );
+ goto finish;
+ }
+ }
+ }
+ // collect larger cuts next
+ Vec_PtrForEachEntry( p->vTemp, pList, i )
+ {
+ Cut_ListForEachCutSafe( pList, pCut, pCut2 )
+ {
+ // check containment
+// if ( p->pParams->fFilter && Cut_CutFilterOne( p, pSuper, pCut ) )
+// continue;
+ if ( p->pParams->fFilter )
+ {
+ if ( Cut_CutFilterOne(p, pSuper, pCut) )
+ continue;
+ if ( p->pParams->fSeq )
+ {
+ if ( p->pCompareOld && Cut_CutFilterOld(p, p->pCompareOld, pCut) )
+ continue;
+ if ( p->pCompareNew && Cut_CutFilterOld(p, p->pCompareNew, pCut) )
+ continue;
+ }
+ }
- SeeAlso []
+ // set the complemented bit
+ pCut->fCompl = pTop->fSimul ^ pCut->fSimul;
+ pListStart = pCut->pNext;
+ pCut->pNext = NULL;
+ // add to the list
+ Cut_ListAdd( pSuper, pCut );
+ if ( ++p->nNodeCuts == p->pParams->nKeepMax )
+ {
+ // recycle the rest of the cuts
+ Cut_ListForEachCutSafe( pListStart, pCut, pCut2 )
+ Cut_CutRecycle( p, pCut );
+ // recycle the saved cuts of other nodes
+ Vec_PtrForEachEntryStart( p->vTemp, pList, k, i+1 )
+ Cut_ListForEachCutSafe( pList, pCut, pCut2 )
+ Cut_CutRecycle( p, pCut );
+ goto finish;
+ }
+ }
+ }
+finish :
+ // set the cuts at the node
+ pList = Cut_ListFinish( pSuper );
-***********************************************************************/
-void Cut_CutPrintMerge( Cut_Cut_t * pCut, Cut_Cut_t * pCut0, Cut_Cut_t * pCut1 )
-{
- printf( "\n" );
- printf( "%d : %5d %5d %5d %5d %5d\n",
- pCut0->nLeaves,
- pCut0->nLeaves > 0 ? pCut0->pLeaves[0] : -1,
- pCut0->nLeaves > 1 ? pCut0->pLeaves[1] : -1,
- pCut0->nLeaves > 2 ? pCut0->pLeaves[2] : -1,
- pCut0->nLeaves > 3 ? pCut0->pLeaves[3] : -1,
- pCut0->nLeaves > 4 ? pCut0->pLeaves[4] : -1
- );
- printf( "%d : %5d %5d %5d %5d %5d\n",
- pCut1->nLeaves,
- pCut1->nLeaves > 0 ? pCut1->pLeaves[0] : -1,
- pCut1->nLeaves > 1 ? pCut1->pLeaves[1] : -1,
- pCut1->nLeaves > 2 ? pCut1->pLeaves[2] : -1,
- pCut1->nLeaves > 3 ? pCut1->pLeaves[3] : -1,
- pCut1->nLeaves > 4 ? pCut1->pLeaves[4] : -1
- );
- if ( pCut == NULL )
- printf( "Cannot merge\n" );
+ // set the lists at the node
+// assert( Cut_NodeReadCutsNew(p, Root) == NULL );
+// Cut_NodeWriteCutsNew( p, Root, pList );
+ if ( CutSetNum >= 0 )
+ {
+ assert( Cut_NodeReadCutsTemp(p, CutSetNum) == NULL );
+ Cut_NodeWriteCutsTemp( p, CutSetNum, pList );
+ }
else
- printf( "%d : %5d %5d %5d %5d %5d\n",
- pCut->nLeaves,
- pCut->nLeaves > 0 ? pCut->pLeaves[0] : -1,
- pCut->nLeaves > 1 ? pCut->pLeaves[1] : -1,
- pCut->nLeaves > 2 ? pCut->pLeaves[2] : -1,
- pCut->nLeaves > 3 ? pCut->pLeaves[3] : -1,
- pCut->nLeaves > 4 ? pCut->pLeaves[4] : -1
- );
+ {
+ assert( Cut_NodeReadCutsNew(p, Root) == NULL );
+ Cut_NodeWriteCutsNew( p, Root, pList );
+ }
+
+p->timeUnion += clock() - clk;
+ // filter the cuts
+//clk = clock();
+// if ( p->pParams->fFilter )
+// Cut_CutFilter( p, pList );
+//p->timeFilter += clock() - clk;
+// if ( fFirst )
+// p->nNodes -= vNodes->nSize - 1;
+ return pList;
}
/**Function*************************************************************
- Synopsis [Filter the cuts using dominance.]
+ Synopsis [Verifies that the list contains only non-dominated cuts.]
Description []
@@ -565,62 +964,27 @@ void Cut_CutPrintMerge( Cut_Cut_t * pCut, Cut_Cut_t * pCut0, Cut_Cut_t * pCut1 )
SeeAlso []
***********************************************************************/
-void Cut_CutFilter( Cut_Man_t * p, Cut_Cut_t * pList )
+int Cut_CutListVerify( Cut_Cut_t * pList )
{
- Cut_Cut_t * pListR, ** ppListR = &pListR;
- Cut_Cut_t * pCut, * pCut2, * pDom, * pPrev;
- int i, k;
- // save the first cut
- *ppListR = pList, ppListR = &pList->pNext;
- // try to filter out other cuts
- pPrev = pList;
- Cut_ListForEachCutSafe( pList->pNext, pCut, pCut2 )
+ Cut_Cut_t * pCut, * pDom;
+ Cut_ListForEachCut( pList, pCut )
{
- assert( pCut->nLeaves > 1 );
- // go through all the previous cuts up to pCut
- Cut_ListForEachCutStop( pList->pNext, pDom, pCut )
+ Cut_ListForEachCutStop( pList, pDom, pCut )
{
- if ( pDom->nLeaves >= pCut->nLeaves )
- continue;
- // check if every node in pDom is contained in pCut
- for ( i = 0; i < (int)pDom->nLeaves; i++ )
+ if ( Cut_CutCheckDominance( pDom, pCut ) )
{
- for ( k = 0; k < (int)pCut->nLeaves; k++ )
- if ( pDom->pLeaves[i] == pCut->pLeaves[k] )
- break;
- if ( k == (int)pCut->nLeaves ) // node i in pDom is not contained in pCut
- break;
+ int x = 0;
+ printf( "******************* These are contained cuts:\n" );
+ Cut_CutPrint( pDom, 1 );
+ Cut_CutPrint( pDom, 1 );
+
+ return 0;
}
- if ( i == (int)pDom->nLeaves ) // every node in pDom is contained in pCut
- break;
- }
- if ( pDom != pCut ) // pDom is contained in pCut - recycle pCut
- {
- // make sure cuts are connected after removing
- pPrev->pNext = pCut->pNext;
-/*
- // report
- printf( "Recycling cut: " );
- Cut_CutPrint( pCut );
- printf( "\n" );
- printf( "As contained in: " );
- Cut_CutPrint( pDom );
- printf( "\n" );
-*/
- // recycle the cut
- Cut_CutRecycle( p, pCut );
- }
- else // pDom is NOT contained in pCut - save pCut
- {
- *ppListR = pCut, ppListR = &pCut->pNext;
- pPrev = pCut;
}
}
- *ppListR = NULL;
+ return 1;
}
-
-
////////////////////////////////////////////////////////////////////////
/// END OF FILE ///
////////////////////////////////////////////////////////////////////////
diff --git a/src/opt/cut/cutOracle.c b/src/opt/cut/cutOracle.c
new file mode 100644
index 00000000..3eb4462b
--- /dev/null
+++ b/src/opt/cut/cutOracle.c
@@ -0,0 +1,428 @@
+/**CFile****************************************************************
+
+ FileName [cutOracle.c]
+
+ SystemName [ABC: Logic synthesis and verification system.]
+
+ PackageName [K-feasible cut computation package.]
+
+ Synopsis [Procedures to compute cuts for a node using the oracle.]
+
+ Author [Alan Mishchenko]
+
+ Affiliation [UC Berkeley]
+
+ Date [Ver. 1.0. Started - June 20, 2005.]
+
+ Revision [$Id: cutOracle.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "cutInt.h"
+
+////////////////////////////////////////////////////////////////////////
+/// DECLARATIONS ///
+////////////////////////////////////////////////////////////////////////
+
+struct Cut_OracleStruct_t_
+{
+ // cut comptupatation parameters
+ Cut_Params_t * pParams;
+ Vec_Int_t * vFanCounts;
+ int fSimul;
+ // storage for cuts
+ Vec_Ptr_t * vCutsNew;
+ Vec_Ptr_t * vCuts0;
+ Vec_Ptr_t * vCuts1;
+ // oracle info
+ Vec_Int_t * vNodeCuts;
+ Vec_Int_t * vNodeStarts;
+ Vec_Int_t * vCutPairs;
+ // memory management
+ Extra_MmFixed_t * pMmCuts;
+ int EntrySize;
+ int nTruthWords;
+ // stats
+ int timeTotal;
+ int nCuts;
+ int nCutsTriv;
+};
+
+static Cut_Cut_t * Cut_CutStart( Cut_Oracle_t * p );
+static Cut_Cut_t * Cut_CutTriv( Cut_Oracle_t * p, int Node );
+static Cut_Cut_t * Cut_CutMerge( Cut_Oracle_t * p, Cut_Cut_t * pCut0, Cut_Cut_t * pCut1 );
+
+////////////////////////////////////////////////////////////////////////
+/// FUNCTION DEFINITIONS ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+ Synopsis [Starts the cut oracle.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Cut_Oracle_t * Cut_OracleStart( Cut_Man_t * pMan )
+{
+ Cut_Oracle_t * p;
+ int clk = clock();
+
+ assert( pMan->pParams->nVarsMax >= 3 && pMan->pParams->nVarsMax <= CUT_SIZE_MAX );
+ assert( pMan->pParams->fRecord );
+
+ p = ALLOC( Cut_Oracle_t, 1 );
+ memset( p, 0, sizeof(Cut_Oracle_t) );
+
+ // set and correct parameters
+ p->pParams = pMan->pParams;
+
+ // transfer the recording info
+ p->vNodeCuts = pMan->vNodeCuts; pMan->vNodeCuts = NULL;
+ p->vNodeStarts = pMan->vNodeStarts; pMan->vNodeStarts = NULL;
+ p->vCutPairs = pMan->vCutPairs; pMan->vCutPairs = NULL;
+
+ // prepare storage for cuts
+ p->vCutsNew = Vec_PtrAlloc( p->pParams->nIdsMax );
+ Vec_PtrFill( p->vCutsNew, p->pParams->nIdsMax, NULL );
+ p->vCuts0 = Vec_PtrAlloc( 100 );
+ p->vCuts1 = Vec_PtrAlloc( 100 );
+
+ // entry size
+ p->EntrySize = sizeof(Cut_Cut_t) + p->pParams->nVarsMax * sizeof(int);
+ if ( p->pParams->fTruth )
+ {
+ if ( p->pParams->nVarsMax > 8 )
+ {
+ p->pParams->fTruth = 0;
+ printf( "Skipping computation of truth table for more than 8 inputs.\n" );
+ }
+ else
+ {
+ p->nTruthWords = Cut_TruthWords( p->pParams->nVarsMax );
+ p->EntrySize += p->nTruthWords * sizeof(unsigned);
+ }
+ }
+ // memory for cuts
+ p->pMmCuts = Extra_MmFixedStart( p->EntrySize );
+ return p;
+}
+/**Function*************************************************************
+
+ Synopsis [Stop the cut oracle.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Cut_OracleStop( Cut_Oracle_t * p )
+{
+ Cut_Cut_t * pCut;
+ int i;
+
+// if ( p->pParams->fVerbose )
+ {
+ printf( "Cut computation statistics with oracle:\n" );
+ printf( "Current cuts = %8d. (Trivial = %d.)\n", p->nCuts-p->nCutsTriv, p->nCutsTriv );
+ PRT( "Total time ", p->timeTotal );
+ }
+
+ Vec_PtrForEachEntry( p->vCutsNew, pCut, i )
+ if ( pCut != NULL )
+ {
+ int k = 0;
+ }
+ if ( p->vCuts0 ) Vec_PtrFree( p->vCuts0 );
+ if ( p->vCuts1 ) Vec_PtrFree( p->vCuts1 );
+ if ( p->vCutsNew ) Vec_PtrFree( p->vCutsNew );
+ if ( p->vFanCounts ) Vec_IntFree( p->vFanCounts );
+
+ if ( p->vNodeCuts ) Vec_IntFree( p->vNodeCuts );
+ if ( p->vNodeStarts ) Vec_IntFree( p->vNodeStarts );
+ if ( p->vCutPairs ) Vec_IntFree( p->vCutPairs );
+
+ Extra_MmFixedStop( p->pMmCuts );
+ free( p );
+}
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Cut_OracleSetFanoutCounts( Cut_Oracle_t * p, Vec_Int_t * vFanCounts )
+{
+ p->vFanCounts = vFanCounts;
+}
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Cut_OracleReadDrop( Cut_Oracle_t * p )
+{
+ return p->pParams->fDrop;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Sets the trivial cut for the node.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Cut_OracleNodeSetTriv( Cut_Oracle_t * p, int Node )
+{
+ assert( Vec_PtrEntry( p->vCutsNew, Node ) == NULL );
+ Vec_PtrWriteEntry( p->vCutsNew, Node, Cut_CutTriv(p, Node) );
+}
+
+
+
+/**Function*************************************************************
+
+ Synopsis [Allocates the cut.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Cut_Cut_t * Cut_CutStart( Cut_Oracle_t * p )
+{
+ Cut_Cut_t * pCut;
+ // cut allocation
+ pCut = (Cut_Cut_t *)Extra_MmFixedEntryFetch( p->pMmCuts );
+ memset( pCut, 0, sizeof(Cut_Cut_t) );
+ pCut->nVarsMax = p->pParams->nVarsMax;
+ pCut->fSimul = p->fSimul;
+ p->nCuts++;
+ return pCut;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Creates the trivial cut.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Cut_Cut_t * Cut_CutTriv( Cut_Oracle_t * p, int Node )
+{
+ Cut_Cut_t * pCut;
+ pCut = Cut_CutStart( p );
+ pCut->nLeaves = 1;
+ pCut->pLeaves[0] = Node;
+ if ( p->pParams->fTruth )
+ {
+ unsigned * pTruth = Cut_CutReadTruth(pCut);
+ int i;
+ for ( i = 0; i < p->nTruthWords; i++ )
+ pTruth[i] = 0xAAAAAAAA;
+ }
+ p->nCutsTriv++;
+ return pCut;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Merges two cuts.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Cut_Cut_t * Cut_CutMerge( Cut_Oracle_t * p, Cut_Cut_t * pCut0, Cut_Cut_t * pCut1 )
+{
+ Cut_Cut_t * pCut;
+ int Limit, i, k, c;
+ // create the leaves of the new cut
+ pCut = Cut_CutStart( p );
+ Limit = p->pParams->nVarsMax;
+ for ( i = k = c = 0; c < Limit; c++ )
+ {
+ if ( k == (int)pCut1->nLeaves )
+ {
+ if ( i == (int)pCut0->nLeaves )
+ {
+ pCut->nLeaves = c;
+ return pCut;
+ }
+ pCut->pLeaves[c] = pCut0->pLeaves[i++];
+ continue;
+ }
+ if ( i == (int)pCut0->nLeaves )
+ {
+ if ( k == (int)pCut1->nLeaves )
+ {
+ pCut->nLeaves = c;
+ return pCut;
+ }
+ pCut->pLeaves[c] = pCut1->pLeaves[k++];
+ continue;
+ }
+ if ( pCut0->pLeaves[i] < pCut1->pLeaves[k] )
+ {
+ pCut->pLeaves[c] = pCut0->pLeaves[i++];
+ continue;
+ }
+ if ( pCut0->pLeaves[i] > pCut1->pLeaves[k] )
+ {
+ pCut->pLeaves[c] = pCut1->pLeaves[k++];
+ continue;
+ }
+ pCut->pLeaves[c] = pCut0->pLeaves[i++];
+ k++;
+ }
+ assert( i == (int)pCut0->nLeaves && k == (int)pCut1->nLeaves );
+ pCut->nLeaves = c;
+ return pCut;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Reconstruct the cuts of the node.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Cut_Cut_t * Cut_OracleComputeCuts( Cut_Oracle_t * p, int Node, int Node0, int Node1, int fCompl0, int fCompl1 )
+{
+ Cut_Cut_t * pList = NULL, ** ppTail = &pList;
+ Cut_Cut_t * pCut, * pCut0, * pCut1, * pList0, * pList1;
+ int iCutStart, nCuts, i, Entry;
+ int clk = clock();
+
+ // get the cuts of the children
+ pList0 = Vec_PtrEntry( p->vCutsNew, Node0 );
+ pList1 = Vec_PtrEntry( p->vCutsNew, Node1 );
+ assert( pList0 && pList1 );
+
+ // get the complemented attribute of the cut
+ p->fSimul = (fCompl0 ^ pList0->fSimul) & (fCompl1 ^ pList1->fSimul);
+
+ // collect the cuts
+ Vec_PtrClear( p->vCuts0 );
+ Cut_ListForEachCut( pList0, pCut )
+ Vec_PtrPush( p->vCuts0, pCut );
+ Vec_PtrClear( p->vCuts1 );
+ Cut_ListForEachCut( pList1, pCut )
+ Vec_PtrPush( p->vCuts1, pCut );
+
+ // get the first and last cuts of this node
+ nCuts = Vec_IntEntry(p->vNodeCuts, Node);
+ iCutStart = Vec_IntEntry(p->vNodeStarts, Node);
+
+ // create trivial cut
+ assert( Vec_IntEntry(p->vCutPairs, iCutStart) == 0 );
+ pCut = Cut_CutTriv( p, Node );
+ *ppTail = pCut;
+ ppTail = &pCut->pNext;
+ // create other cuts
+ for ( i = 1; i < nCuts; i++ )
+ {
+ Entry = Vec_IntEntry( p->vCutPairs, iCutStart + i );
+ pCut0 = Vec_PtrEntry( p->vCuts0, Entry & 0xFFFF );
+ pCut1 = Vec_PtrEntry( p->vCuts1, Entry >> 16 );
+ pCut = Cut_CutMerge( p, pCut0, pCut1 );
+ *ppTail = pCut;
+ ppTail = &pCut->pNext;
+ // compute the truth table
+ if ( p->pParams->fTruth )
+ Cut_TruthComputeOld( pCut, pCut0, pCut1, fCompl0, fCompl1 );
+ }
+ *ppTail = NULL;
+
+ // write the new cut
+ assert( Vec_PtrEntry( p->vCutsNew, Node ) == NULL );
+ Vec_PtrWriteEntry( p->vCutsNew, Node, pList );
+p->timeTotal += clock() - clk;
+ return pList;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Deallocates the cuts at the node.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Cut_OracleFreeCuts( Cut_Oracle_t * p, int Node )
+{
+ Cut_Cut_t * pList, * pCut, * pCut2;
+ pList = Vec_PtrEntry( p->vCutsNew, Node );
+ if ( pList == NULL )
+ return;
+ Cut_ListForEachCutSafe( pList, pCut, pCut2 )
+ Extra_MmFixedEntryRecycle( p->pMmCuts, (char *)pCut );
+ Vec_PtrWriteEntry( p->vCutsNew, Node, pList );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Consider dropping cuts if they are useless by now.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Cut_OracleTryDroppingCuts( Cut_Oracle_t * p, int Node )
+{
+ int nFanouts;
+ assert( p->vFanCounts );
+ nFanouts = Vec_IntEntry( p->vFanCounts, Node );
+ assert( nFanouts > 0 );
+ if ( --nFanouts == 0 )
+ Cut_OracleFreeCuts( p, Node );
+ Vec_IntWriteEntry( p->vFanCounts, Node, nFanouts );
+}
+
+////////////////////////////////////////////////////////////////////////
+/// END OF FILE ///
+////////////////////////////////////////////////////////////////////////
+
+
diff --git a/src/opt/cut/cutPre22.c b/src/opt/cut/cutPre22.c
new file mode 100644
index 00000000..5cb87a9c
--- /dev/null
+++ b/src/opt/cut/cutPre22.c
@@ -0,0 +1,988 @@
+/**CFile****************************************************************
+
+ FileName [cutPre22.c]
+
+ SystemName [ABC: Logic synthesis and verification system.]
+
+ PackageName [Network and node package.]
+
+ Synopsis [Precomputes truth tables for the 2x2 macro cell.]
+
+ Author [Alan Mishchenko]
+
+ Affiliation [UC Berkeley]
+
+ Date [Ver. 1.0. Started - June 20, 2005.]
+
+ Revision [$Id: cutPre22.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "cutInt.h"
+
+////////////////////////////////////////////////////////////////////////
+/// DECLARATIONS ///
+////////////////////////////////////////////////////////////////////////
+
+#define CUT_CELL_MVAR 9
+
+typedef struct Cut_Cell_t_ Cut_Cell_t;
+typedef struct Cut_CMan_t_ Cut_CMan_t;
+
+struct Cut_Cell_t_
+{
+ Cut_Cell_t * pNext; // pointer to the next cell in the table
+ Cut_Cell_t * pNextVar; // pointer to the next cell of this support size
+ Cut_Cell_t * pParent; // pointer to the cell used to derive this one
+ int nUsed; // the number of times the cell is used
+ char Box[4]; // functions in the boxes
+ unsigned nVars : 4; // the number of variables
+ unsigned CrossBar0 : 4; // the variable set equal
+ unsigned CrossBar1 : 4; // the variable set equal
+ unsigned CrossBarPhase : 2; // the phase of the cross bar (0, 1, or 2)
+ unsigned CanonPhase : 18; // the canonical phase
+ char CanonPerm[CUT_CELL_MVAR+3]; // semicanonical permutation
+ short Store[2*CUT_CELL_MVAR]; // minterm counts in the cofactors
+ unsigned uTruth[1<<(CUT_CELL_MVAR-5)]; // the current truth table
+};
+
+struct Cut_CMan_t_
+{
+ // storage for canonical cells
+ Extra_MmFixed_t * pMem;
+ st_table * tTable;
+ Cut_Cell_t * pSameVar[CUT_CELL_MVAR+1];
+ // elementary truth tables
+ unsigned uInputs[CUT_CELL_MVAR][1<<(CUT_CELL_MVAR-5)];
+ // temporary truth tables
+ unsigned uTemp1[22][1<<(CUT_CELL_MVAR-5)];
+ unsigned uTemp2[22][1<<(CUT_CELL_MVAR-5)];
+ unsigned uTemp3[22][1<<(CUT_CELL_MVAR-5)];
+ unsigned uFinal[1<<(CUT_CELL_MVAR-5)];
+ unsigned puAux[1<<(CUT_CELL_MVAR-5)];
+ // statistical variables
+ int nTotal;
+ int nGood;
+ int nVarCounts[CUT_CELL_MVAR+1];
+ int nSymGroups[CUT_CELL_MVAR+1];
+ int nSymGroupsE[CUT_CELL_MVAR+1];
+ int timeCanon;
+ int timeSupp;
+ int timeTable;
+ int nCellFound;
+ int nCellNotFound;
+};
+
+// NP-classes of functions of 3 variables (22)
+static char * s_NP3[22] = {
+ " 0\n", // 00 const 0 // 0 vars
+ " 1\n", // 01 const 1 // 0 vars
+ "1 1\n", // 02 a // 1 vars
+ "11 1\n", // 03 ab // 2 vars
+ "11 0\n", // 04 (ab)' // 2 vars
+ "10 1\n01 1\n", // 05 a<+>b // 2 vars
+ "111 1\n", // 06 0s abc // 3 vars
+ "111 0\n", // 07 (abc)' //
+ "11- 1\n1-1 1\n", // 08 1p a(b+c) //
+ "11- 0\n1-1 0\n", // 09 (a(b+c))' //
+ "111 1\n100 1\n010 1\n001 1\n", // 10 2s a<+>b<+>c //
+ "10- 0\n1-0 0\n011 0\n", // 11 3p a<+>bc //
+ "101 1\n110 1\n", // 12 4p a(b<+>c) //
+ "101 0\n110 0\n", // 13 (a(b<+>c))' //
+ "11- 1\n1-1 1\n-11 1\n", // 14 5s ab+bc+ac //
+ "111 1\n000 1\n", // 15 6s abc+a'b'c' //
+ "111 0\n000 0\n", // 16 (abc+a'b'c')' //
+ "11- 1\n-11 1\n0-1 1\n", // 17 7 ab+bc+a'c //
+ "011 1\n101 1\n110 1\n", // 18 8s a'bc+ab'c+abc' //
+ "011 0\n101 0\n110 0\n", // 19 (a'bc+ab'c+abc')' //
+ "100 1\n-11 1\n", // 20 9p ab'c'+bc //
+ "100 0\n-11 0\n" // 21 (ab'c'+bc)' //
+};
+
+// NP-classes of functions of 3 variables (22)
+static char * s_NP3Names[22] = {
+ " const 0 ",
+ " const 1 ",
+ " a ",
+ " ab ",
+ " (ab)' ",
+ " a<+>b ",
+ "0s abc ",
+ " (abc)' ",
+ "1p a(b+c) ",
+ " (a(b+c))' ",
+ "2s a<+>b<+>c ",
+ "3p a<+>bc ",
+ "4p a(b<+>c) ",
+ " (a(b<+>c))' ",
+ "5s ab+bc+ac ",
+ "6s abc+a'b'c' ",
+ " (abc+a'b'c')' ",
+ "7 ab+bc+a'c ",
+ "8s a'bc+ab'c+abc' ",
+ " (a'bc+ab'c+abc')' ",
+ "9p ab'c'+bc ",
+ " (ab'c'+bc)' "
+};
+
+// the number of variables in each function
+static int s_NP3VarNums[22] = { 0, 0, 1, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3 };
+
+// NPN classes of functions of exactly 3 inputs (10)
+static int s_NPNe3[10] = { 6, 8, 10, 11, 12, 14, 15, 17, 18, 20 };
+
+// NPN classes of functions of exactly 3 inputs that are symmetric (5)
+static int s_NPNe3s[10] = { 6, 10, 14, 15, 18 };
+
+// NPN classes of functions of exactly 3 inputs (4)
+static int s_NPNe3p[10] = { 8, 11, 12, 20 };
+
+static Cut_CMan_t * Cut_CManStart();
+static void Cut_CManStop( Cut_CMan_t * p );
+static void Cut_CellTruthElem( unsigned * InA, unsigned * InB, unsigned * InC, unsigned * pOut, int nVars, int Type );
+static void Cut_CellCanonicize( Cut_CMan_t * p, Cut_Cell_t * pCell );
+static int Cut_CellTableLookup( Cut_CMan_t * p, Cut_Cell_t * pCell );
+static void Cut_CellSuppMin( Cut_Cell_t * pCell );
+static void Cut_CellCrossBar( Cut_Cell_t * pCell );
+
+
+static Cut_CMan_t * s_pCMan = NULL;
+
+////////////////////////////////////////////////////////////////////////
+/// FUNCTION DEFINITIONS ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+ Synopsis [Start the precomputation manager.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Cut_CellLoad()
+{
+ FILE * pFile;
+ char * pFileName = "cells22_daomap_iwls.txt";
+ char pString[1000];
+ Cut_CMan_t * p;
+ Cut_Cell_t * pCell;
+ int Length; //, i;
+ pFile = fopen( pFileName, "r" );
+ if ( pFile == NULL )
+ {
+ printf( "Cannot open file \"%s\".\n", pFileName );
+ return;
+ }
+ // start the manager
+ p = Cut_CManStart();
+ // load truth tables
+ while ( fgets(pString, 1000, pFile) )
+ {
+ Length = strlen(pString);
+ pString[Length--] = 0;
+ if ( Length == 0 )
+ continue;
+ // derive the cell
+ pCell = (Cut_Cell_t *)Extra_MmFixedEntryFetch( p->pMem );
+ memset( pCell, 0, sizeof(Cut_Cell_t) );
+ pCell->nVars = Extra_Base2Log(Length*4);
+ pCell->nUsed = 1;
+// Extra_TruthCopy( pCell->uTruth, pTruth, nVars );
+ Extra_ReadHexadecimal( pCell->uTruth, pString, pCell->nVars );
+ Cut_CellSuppMin( pCell );
+/*
+ // set the elementary permutation
+ for ( i = 0; i < (int)pCell->nVars; i++ )
+ pCell->CanonPerm[i] = i;
+ // canonicize
+ pCell->CanonPhase = Extra_TruthSemiCanonicize( pCell->uTruth, p->puAux, pCell->nVars, pCell->CanonPerm, pCell->Store );
+*/
+ // add to the table
+ p->nTotal++;
+
+// Extra_PrintHexadecimal( stdout, pCell->uTruth, pCell->nVars ); printf( "\n" );
+// if ( p->nTotal == 500 )
+// break;
+
+ if ( !Cut_CellTableLookup( p, pCell ) ) // new cell
+ p->nGood++;
+ }
+ printf( "Read %d cells from file \"%s\". Added %d cells to the table.\n", p->nTotal, pFileName, p->nGood );
+ fclose( pFile );
+// return p;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Precomputes truth tables for the 2x2 macro cell.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Cut_CellPrecompute()
+{
+ Cut_CMan_t * p;
+ Cut_Cell_t * pCell, * pTemp;
+ int i1, i2, i3, i, j, k, c, clk = clock(), clk2 = clock();
+
+ p = Cut_CManStart();
+
+ // precompute truth tables
+ for ( i = 0; i < 22; i++ )
+ Cut_CellTruthElem( p->uInputs[0], p->uInputs[1], p->uInputs[2], p->uTemp1[i], 9, i );
+ for ( i = 0; i < 22; i++ )
+ Cut_CellTruthElem( p->uInputs[3], p->uInputs[4], p->uInputs[5], p->uTemp2[i], 9, i );
+ for ( i = 0; i < 22; i++ )
+ Cut_CellTruthElem( p->uInputs[6], p->uInputs[7], p->uInputs[8], p->uTemp3[i], 9, i );
+/*
+ if ( k == 8 && ((i1 == 6 && i2 == 14 && i3 == 20) || (i1 == 20 && i2 == 6 && i3 == 14)) )
+ {
+ Extra_PrintBinary( stdout, &pCell->CanonPhase, pCell->nVars+1 ); printf( " : " );
+ for ( i = 0; i < pCell->nVars; i++ )
+ printf( "%d=%d/%d ", pCell->CanonPerm[i], pCell->Store[2*i], pCell->Store[2*i+1] );
+ Extra_PrintHexadecimal( stdout, pCell->uTruth, pCell->nVars );
+ printf( "\n" );
+ }
+*/
+/*
+ // go through symmetric roots
+ for ( k = 0; k < 5; k++ )
+ for ( i1 = 0; i1 < 22; i1++ )
+ for ( i2 = i1; i2 < 22; i2++ )
+ for ( i3 = i2; i3 < 22; i3++ )
+ {
+ // derive the cell
+ pCell = (Cut_Cell_t *)Extra_MmFixedEntryFetch( p->pMem );
+ memset( pCell, 0, sizeof(Cut_Cell_t) );
+ pCell->nVars = 9;
+ pCell->Box[0] = s_NPNe3s[k];
+ pCell->Box[1] = i1;
+ pCell->Box[2] = i2;
+ pCell->Box[3] = i3;
+ // fill in the truth table
+ Cut_CellTruthElem( p->uTemp1[i1], p->uTemp2[i2], p->uTemp3[i3], pCell->uTruth, 9, s_NPNe3s[k] );
+ // canonicize
+ Cut_CellCanonicize( pCell );
+
+ // add to the table
+ p->nTotal++;
+ if ( Cut_CellTableLookup( p, pCell ) ) // already exists
+ Extra_MmFixedEntryRecycle( p->pMem, (char *)pCell );
+ else
+ p->nGood++;
+ }
+
+ // go through partially symmetric roots
+ for ( k = 0; k < 4; k++ )
+ for ( i1 = 0; i1 < 22; i1++ )
+ for ( i2 = 0; i2 < 22; i2++ )
+ for ( i3 = i2; i3 < 22; i3++ )
+ {
+ // derive the cell
+ pCell = (Cut_Cell_t *)Extra_MmFixedEntryFetch( p->pMem );
+ memset( pCell, 0, sizeof(Cut_Cell_t) );
+ pCell->nVars = 9;
+ pCell->Box[0] = s_NPNe3p[k];
+ pCell->Box[1] = i1;
+ pCell->Box[2] = i2;
+ pCell->Box[3] = i3;
+ // fill in the truth table
+ Cut_CellTruthElem( p->uTemp1[i1], p->uTemp2[i2], p->uTemp3[i3], pCell->uTruth, 9, s_NPNe3p[k] );
+ // canonicize
+ Cut_CellCanonicize( pCell );
+
+ // add to the table
+ p->nTotal++;
+ if ( Cut_CellTableLookup( p, pCell ) ) // already exists
+ Extra_MmFixedEntryRecycle( p->pMem, (char *)pCell );
+ else
+ p->nGood++;
+ }
+
+ // go through non-symmetric functions
+ for ( i1 = 0; i1 < 22; i1++ )
+ for ( i2 = 0; i2 < 22; i2++ )
+ for ( i3 = 0; i3 < 22; i3++ )
+ {
+ // derive the cell
+ pCell = (Cut_Cell_t *)Extra_MmFixedEntryFetch( p->pMem );
+ memset( pCell, 0, sizeof(Cut_Cell_t) );
+ pCell->nVars = 9;
+ pCell->Box[0] = 17;
+ pCell->Box[1] = i1;
+ pCell->Box[2] = i2;
+ pCell->Box[3] = i3;
+ // fill in the truth table
+ Cut_CellTruthElem( p->uTemp1[i1], p->uTemp2[i2], p->uTemp3[i3], pCell->uTruth, 9, 17 );
+ // canonicize
+ Cut_CellCanonicize( pCell );
+
+ // add to the table
+ p->nTotal++;
+ if ( Cut_CellTableLookup( p, pCell ) ) // already exists
+ Extra_MmFixedEntryRecycle( p->pMem, (char *)pCell );
+ else
+ p->nGood++;
+ }
+*/
+
+ // go through non-symmetric functions
+ for ( k = 0; k < 10; k++ )
+ for ( i1 = 0; i1 < 22; i1++ )
+ for ( i2 = 0; i2 < 22; i2++ )
+ for ( i3 = 0; i3 < 22; i3++ )
+ {
+ // derive the cell
+ pCell = (Cut_Cell_t *)Extra_MmFixedEntryFetch( p->pMem );
+ memset( pCell, 0, sizeof(Cut_Cell_t) );
+ pCell->nVars = 9;
+ pCell->Box[0] = s_NPNe3[k];
+ pCell->Box[1] = i1;
+ pCell->Box[2] = i2;
+ pCell->Box[3] = i3;
+ // set the elementary permutation
+ for ( i = 0; i < (int)pCell->nVars; i++ )
+ pCell->CanonPerm[i] = i;
+ // fill in the truth table
+ Cut_CellTruthElem( p->uTemp1[i1], p->uTemp2[i2], p->uTemp3[i3], pCell->uTruth, 9, s_NPNe3[k] );
+ // minimize the support
+ Cut_CellSuppMin( pCell );
+
+ // canonicize
+ pCell->CanonPhase = Extra_TruthSemiCanonicize( pCell->uTruth, p->puAux, pCell->nVars, pCell->CanonPerm, pCell->Store );
+
+ // add to the table
+ p->nTotal++;
+ if ( Cut_CellTableLookup( p, pCell ) ) // already exists
+ Extra_MmFixedEntryRecycle( p->pMem, (char *)pCell );
+ else
+ {
+ p->nGood++;
+ p->nVarCounts[pCell->nVars]++;
+
+ if ( pCell->nVars )
+ for ( i = 0; i < (int)pCell->nVars-1; i++ )
+ {
+ if ( pCell->Store[2*i] != pCell->Store[2*(i+1)] ) // i and i+1 cannot be symmetric
+ continue;
+ // i and i+1 can be symmetric
+ // find the end of this group
+ for ( j = i+1; j < (int)pCell->nVars; j++ )
+ if ( pCell->Store[2*i] != pCell->Store[2*j] )
+ break;
+
+ if ( pCell->Store[2*i] == pCell->Store[2*i+1] )
+ p->nSymGroupsE[j-i]++;
+ else
+ p->nSymGroups[j-i]++;
+ i = j - 1;
+ }
+/*
+ if ( pCell->nVars == 3 )
+ {
+ Extra_PrintBinary( stdout, pCell->uTruth, 32 ); printf( "\n" );
+ for ( i = 0; i < (int)pCell->nVars; i++ )
+ printf( "%d=%d/%d ", pCell->CanonPerm[i], pCell->Store[2*i], pCell->Store[2*i+1] );
+ printf( "\n" );
+ }
+*/
+ }
+ }
+
+ printf( "BASIC: Total = %d. Good = %d. Entry = %d. ", p->nTotal, p->nGood, sizeof(Cut_Cell_t) );
+ PRT( "Time", clock() - clk );
+ printf( "Cells: " );
+ for ( i = 0; i <= 9; i++ )
+ printf( "%d=%d ", i, p->nVarCounts[i] );
+ printf( "\nDiffs: " );
+ for ( i = 0; i <= 9; i++ )
+ printf( "%d=%d ", i, p->nSymGroups[i] );
+ printf( "\nEquals: " );
+ for ( i = 0; i <= 9; i++ )
+ printf( "%d=%d ", i, p->nSymGroupsE[i] );
+ printf( "\n" );
+
+ // continue adding new cells using support
+ for ( k = CUT_CELL_MVAR; k > 3; k-- )
+ {
+ for ( pTemp = p->pSameVar[k]; pTemp; pTemp = pTemp->pNextVar )
+ for ( i1 = 0; i1 < k; i1++ )
+ for ( i2 = i1+1; i2 < k; i2++ )
+ for ( c = 0; c < 3; c++ )
+ {
+ // derive the cell
+ pCell = (Cut_Cell_t *)Extra_MmFixedEntryFetch( p->pMem );
+ memset( pCell, 0, sizeof(Cut_Cell_t) );
+ pCell->nVars = pTemp->nVars;
+ pCell->pParent = pTemp;
+ // set the elementary permutation
+ for ( i = 0; i < (int)pCell->nVars; i++ )
+ pCell->CanonPerm[i] = i;
+ // fill in the truth table
+ Extra_TruthCopy( pCell->uTruth, pTemp->uTruth, pTemp->nVars );
+ // create the cross-bar
+ pCell->CrossBar0 = i1;
+ pCell->CrossBar1 = i2;
+ pCell->CrossBarPhase = c;
+ Cut_CellCrossBar( pCell );
+ // minimize the support
+//clk2 = clock();
+ Cut_CellSuppMin( pCell );
+//p->timeSupp += clock() - clk2;
+ // canonicize
+//clk2 = clock();
+ pCell->CanonPhase = Extra_TruthSemiCanonicize( pCell->uTruth, p->puAux, pCell->nVars, pCell->CanonPerm, pCell->Store );
+//p->timeCanon += clock() - clk2;
+
+ // add to the table
+//clk2 = clock();
+ p->nTotal++;
+ if ( Cut_CellTableLookup( p, pCell ) ) // already exists
+ Extra_MmFixedEntryRecycle( p->pMem, (char *)pCell );
+ else
+ {
+ p->nGood++;
+ p->nVarCounts[pCell->nVars]++;
+
+ for ( i = 0; i < (int)pCell->nVars-1; i++ )
+ {
+ if ( pCell->Store[2*i] != pCell->Store[2*(i+1)] ) // i and i+1 cannot be symmetric
+ continue;
+ // i and i+1 can be symmetric
+ // find the end of this group
+ for ( j = i+1; j < (int)pCell->nVars; j++ )
+ if ( pCell->Store[2*i] != pCell->Store[2*j] )
+ break;
+
+ if ( pCell->Store[2*i] == pCell->Store[2*i+1] )
+ p->nSymGroupsE[j-i]++;
+ else
+ p->nSymGroups[j-i]++;
+ i = j - 1;
+ }
+/*
+ if ( pCell->nVars == 3 )
+ {
+ Extra_PrintBinary( stdout, pCell->uTruth, 32 ); printf( "\n" );
+ for ( i = 0; i < (int)pCell->nVars; i++ )
+ printf( "%d=%d/%d ", pCell->CanonPerm[i], pCell->Store[2*i], pCell->Store[2*i+1] );
+ printf( "\n" );
+ }
+*/
+ }
+//p->timeTable += clock() - clk2;
+ }
+
+ printf( "VAR %d: Total = %d. Good = %d. Entry = %d. ", k, p->nTotal, p->nGood, sizeof(Cut_Cell_t) );
+ PRT( "Time", clock() - clk );
+ printf( "Cells: " );
+ for ( i = 0; i <= 9; i++ )
+ printf( "%d=%d ", i, p->nVarCounts[i] );
+ printf( "\nDiffs: " );
+ for ( i = 0; i <= 9; i++ )
+ printf( "%d=%d ", i, p->nSymGroups[i] );
+ printf( "\nEquals: " );
+ for ( i = 0; i <= 9; i++ )
+ printf( "%d=%d ", i, p->nSymGroupsE[i] );
+ printf( "\n" );
+ }
+// printf( "\n" );
+ PRT( "Supp ", p->timeSupp );
+ PRT( "Canon", p->timeCanon );
+ PRT( "Table", p->timeTable );
+// Cut_CManStop( p );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Check the table.]
+
+ Description [Returns 1 if such a truth table already exists.]
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Cut_CellTableLookup( Cut_CMan_t * p, Cut_Cell_t * pCell )
+{
+ Cut_Cell_t ** pSlot, * pTemp;
+ unsigned Hash;
+ Hash = Extra_TruthHash( pCell->uTruth, Extra_TruthWordNum( pCell->nVars ) );
+ if ( !st_find_or_add( p->tTable, (char *)Hash, (char ***)&pSlot ) )
+ *pSlot = NULL;
+ for ( pTemp = *pSlot; pTemp; pTemp = pTemp->pNext )
+ {
+ if ( pTemp->nVars != pCell->nVars )
+ continue;
+ if ( Extra_TruthIsEqual(pTemp->uTruth, pCell->uTruth, pCell->nVars) )
+ return 1;
+ }
+ // the entry is new
+ pCell->pNext = *pSlot;
+ *pSlot = pCell;
+ // add it to the variable support list
+ pCell->pNextVar = p->pSameVar[pCell->nVars];
+ p->pSameVar[pCell->nVars] = pCell;
+ return 0;
+}
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Cut_CellSuppMin( Cut_Cell_t * pCell )
+{
+ static unsigned uTemp[1<<(CUT_CELL_MVAR-5)];
+ unsigned * pIn, * pOut, * pTemp;
+ int i, k, Counter, Temp;
+
+ // go backward through the support variables and remove redundant
+ for ( k = pCell->nVars - 1; k >= 0; k-- )
+ if ( !Extra_TruthVarInSupport(pCell->uTruth, pCell->nVars, k) )
+ {
+ // shift all the variables above this one
+ Counter = 0;
+ pIn = pCell->uTruth; pOut = uTemp;
+ for ( i = k; i < (int)pCell->nVars - 1; i++ )
+ {
+ Extra_TruthSwapAdjacentVars( pOut, pIn, pCell->nVars, i );
+ pTemp = pIn; pIn = pOut; pOut = pTemp;
+ // swap the support vars
+ Temp = pCell->CanonPerm[i];
+ pCell->CanonPerm[i] = pCell->CanonPerm[i+1];
+ pCell->CanonPerm[i+1] = Temp;
+ Counter++;
+ }
+ // return the function back into its place
+ if ( Counter & 1 )
+ Extra_TruthCopy( pOut, pIn, pCell->nVars );
+ // remove one variable
+ pCell->nVars--;
+// Extra_PrintBinary( stdout, pCell->uTruth, (1<<pCell->nVars) ); printf( "\n" );
+ }
+}
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Cut_CellCrossBar( Cut_Cell_t * pCell )
+{
+ static unsigned uTemp0[1<<(CUT_CELL_MVAR-5)];
+ static unsigned uTemp1[1<<(CUT_CELL_MVAR-5)];
+ Extra_TruthCopy( uTemp0, pCell->uTruth, pCell->nVars );
+ Extra_TruthCopy( uTemp1, pCell->uTruth, pCell->nVars );
+ if ( pCell->CanonPhase == 0 )
+ {
+ Extra_TruthCofactor0( uTemp0, pCell->nVars, pCell->CrossBar0 );
+ Extra_TruthCofactor0( uTemp0, pCell->nVars, pCell->CrossBar1 );
+ Extra_TruthCofactor1( uTemp1, pCell->nVars, pCell->CrossBar0 );
+ Extra_TruthCofactor1( uTemp1, pCell->nVars, pCell->CrossBar1 );
+ }
+ else if ( pCell->CanonPhase == 1 )
+ {
+ Extra_TruthCofactor1( uTemp0, pCell->nVars, pCell->CrossBar0 );
+ Extra_TruthCofactor0( uTemp0, pCell->nVars, pCell->CrossBar1 );
+ Extra_TruthCofactor0( uTemp1, pCell->nVars, pCell->CrossBar0 );
+ Extra_TruthCofactor1( uTemp1, pCell->nVars, pCell->CrossBar1 );
+ }
+ else if ( pCell->CanonPhase == 2 )
+ {
+ Extra_TruthCofactor0( uTemp0, pCell->nVars, pCell->CrossBar0 );
+ Extra_TruthCofactor1( uTemp0, pCell->nVars, pCell->CrossBar1 );
+ Extra_TruthCofactor1( uTemp1, pCell->nVars, pCell->CrossBar0 );
+ Extra_TruthCofactor0( uTemp1, pCell->nVars, pCell->CrossBar1 );
+ }
+ else assert( 0 );
+ Extra_TruthMux( pCell->uTruth, uTemp0, uTemp1, pCell->nVars, pCell->CrossBar0 );
+}
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Cut_CellTruthElem( unsigned * InA, unsigned * InB, unsigned * InC, unsigned * pOut, int nVars, int Type )
+{
+ int nWords = Extra_TruthWordNum( nVars );
+ int i;
+
+ assert( Type < 22 );
+ switch ( Type )
+ {
+ // " 0\n", // 00 const 0
+ case 0:
+ for ( i = 0; i < nWords; i++ )
+ pOut[i] = 0;
+ return;
+ // " 1\n", // 01 const 1
+ case 1:
+ for ( i = 0; i < nWords; i++ )
+ pOut[i] = 0xFFFFFFFF;
+ return;
+ // "1 1\n", // 02 a
+ case 2:
+ for ( i = 0; i < nWords; i++ )
+ pOut[i] = InA[i];
+ return;
+ // "11 1\n", // 03 ab
+ case 3:
+ for ( i = 0; i < nWords; i++ )
+ pOut[i] = InA[i] & InB[i];
+ return;
+ // "11 0\n", // 04 (ab)'
+ case 4:
+ for ( i = 0; i < nWords; i++ )
+ pOut[i] = ~(InA[i] & InB[i]);
+ return;
+ // "10 1\n01 1\n", // 05 a<+>b
+ case 5:
+ for ( i = 0; i < nWords; i++ )
+ pOut[i] = InA[i] ^ InB[i];
+ return;
+ // "111 1\n", // 06 + abc
+ case 6:
+ for ( i = 0; i < nWords; i++ )
+ pOut[i] = InA[i] & InB[i] & InC[i];
+ return;
+ // "111 0\n", // 07 (abc)'
+ case 7:
+ for ( i = 0; i < nWords; i++ )
+ pOut[i] = ~(InA[i] & InB[i] & InC[i]);
+ return;
+ // "11- 1\n1-1 1\n", // 08 + a(b+c)
+ case 8:
+ for ( i = 0; i < nWords; i++ )
+ pOut[i] = InA[i] & (InB[i] | InC[i]);
+ return;
+ // "11- 0\n1-1 0\n", // 09 (a(b+c))'
+ case 9:
+ for ( i = 0; i < nWords; i++ )
+ pOut[i] = ~(InA[i] & (InB[i] | InC[i]));
+ return;
+ // "111 1\n100 1\n010 1\n001 1\n", // 10 + a<+>b<+>c
+ case 10:
+ for ( i = 0; i < nWords; i++ )
+ pOut[i] = InA[i] ^ InB[i] ^ InC[i];
+ return;
+ // "10- 0\n1-0 0\n011 0\n", // 11 + a<+>bc
+ case 11:
+ for ( i = 0; i < nWords; i++ )
+ pOut[i] = InA[i] ^ (InB[i] & InC[i]);
+ return;
+ // "101 1\n110 1\n", // 12 + a(b<+>c)
+ case 12:
+ for ( i = 0; i < nWords; i++ )
+ pOut[i] = InA[i] & (InB[i] ^ InC[i]);
+ return;
+ // "101 0\n110 0\n", // 13 (a(b<+>c))'
+ case 13:
+ for ( i = 0; i < nWords; i++ )
+ pOut[i] = ~(InA[i] & (InB[i] ^ InC[i]));
+ return;
+ // "11- 1\n1-1 1\n-11 1\n", // 14 + ab+bc+ac
+ case 14:
+ for ( i = 0; i < nWords; i++ )
+ pOut[i] = (InA[i] & InB[i]) | (InB[i] & InC[i]) | (InA[i] & InC[i]);
+ return;
+ // "111 1\n000 1\n", // 15 + abc+a'b'c'
+ case 15:
+ for ( i = 0; i < nWords; i++ )
+ pOut[i] = (InA[i] & InB[i] & InC[i]) | (~InA[i] & ~InB[i] & ~InC[i]);
+ return;
+ // "111 0\n000 0\n", // 16 (abc+a'b'c')'
+ case 16:
+ for ( i = 0; i < nWords; i++ )
+ pOut[i] = ~((InA[i] & InB[i] & InC[i]) | (~InA[i] & ~InB[i] & ~InC[i]));
+ return;
+ // "11- 1\n-11 1\n0-1 1\n", // 17 + ab+bc+a'c
+ case 17:
+ for ( i = 0; i < nWords; i++ )
+ pOut[i] = (InA[i] & InB[i]) | (InB[i] & InC[i]) | (~InA[i] & InC[i]);
+ return;
+ // "011 1\n101 1\n110 1\n", // 18 + a'bc+ab'c+abc'
+ case 18:
+ for ( i = 0; i < nWords; i++ )
+ pOut[i] = (~InA[i] & InB[i] & InC[i]) | (InA[i] & ~InB[i] & InC[i]) | (InA[i] & InB[i] & ~InC[i]);
+ return;
+ // "011 0\n101 0\n110 0\n", // 19 (a'bc+ab'c+abc')'
+ case 19:
+ for ( i = 0; i < nWords; i++ )
+ pOut[i] = ~((~InA[i] & InB[i] & InC[i]) | (InA[i] & ~InB[i] & InC[i]) | (InA[i] & InB[i] & ~InC[i]));
+ return;
+ // "100 1\n-11 1\n", // 20 + ab'c'+bc
+ case 20:
+ for ( i = 0; i < nWords; i++ )
+ pOut[i] = (InA[i] & ~InB[i] & ~InC[i]) | (InB[i] & InC[i]);
+ return;
+ // "100 0\n-11 0\n" // 21 (ab'c'+bc)'
+ case 21:
+ for ( i = 0; i < nWords; i++ )
+ pOut[i] = ~((InA[i] & ~InB[i] & ~InC[i]) | (InB[i] & InC[i]));
+ return;
+ }
+}
+
+
+/**Function*************************************************************
+
+ Synopsis [Start the precomputation manager.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Cut_CMan_t * Cut_CManStart()
+{
+ Cut_CMan_t * p;
+ int i, k;
+ // start the manager
+ assert( sizeof(unsigned) == 4 );
+ p = ALLOC( Cut_CMan_t, 1 );
+ memset( p, 0, sizeof(Cut_CMan_t) );
+ // start the table and the memory manager
+ p->tTable = st_init_table(st_ptrcmp,st_ptrhash);
+ p->pMem = Extra_MmFixedStart( sizeof(Cut_Cell_t) );
+ // set elementary truth tables
+ for ( k = 0; k < CUT_CELL_MVAR; k++ )
+ for ( i = 0; i < (1<<CUT_CELL_MVAR); i++ )
+ if ( i & (1 << k) )
+ p->uInputs[k][i>>5] |= (1 << (i&31));
+ s_pCMan = p;
+ return p;
+}
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Cut_CManStop( Cut_CMan_t * p )
+{
+ st_free_table( p->tTable );
+ Extra_MmFixedStop( p->pMem );
+ free( p );
+}
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Cut_CellIsRunning()
+{
+ return s_pCMan != NULL;
+}
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Cut_CellDumpToFile()
+{
+ FILE * pFile;
+ Cut_CMan_t * p = s_pCMan;
+ Cut_Cell_t * pTemp;
+ char * pFileName = "celllib22.txt";
+ int NumUsed[10][5] = {{0}};
+ int BoxUsed[22][5] = {{0}};
+ int i, k, Counter;
+ int clk = clock();
+
+ if ( p == NULL )
+ {
+ printf( "Cut_CellDumpToFile: Cell manager is not defined.\n" );
+ return;
+ }
+
+ // count the number of cells used
+ for ( k = CUT_CELL_MVAR; k >= 0; k-- )
+ {
+ for ( pTemp = p->pSameVar[k]; pTemp; pTemp = pTemp->pNextVar )
+ {
+ if ( pTemp->nUsed == 0 )
+ NumUsed[k][0]++;
+ else if ( pTemp->nUsed < 10 )
+ NumUsed[k][1]++;
+ else if ( pTemp->nUsed < 100 )
+ NumUsed[k][2]++;
+ else if ( pTemp->nUsed < 1000 )
+ NumUsed[k][3]++;
+ else
+ NumUsed[k][4]++;
+
+ for ( i = 0; i < 4; i++ )
+ if ( pTemp->nUsed == 0 )
+ BoxUsed[ pTemp->Box[i] ][0]++;
+ else if ( pTemp->nUsed < 10 )
+ BoxUsed[ pTemp->Box[i] ][1]++;
+ else if ( pTemp->nUsed < 100 )
+ BoxUsed[ pTemp->Box[i] ][2]++;
+ else if ( pTemp->nUsed < 1000 )
+ BoxUsed[ pTemp->Box[i] ][3]++;
+ else
+ BoxUsed[ pTemp->Box[i] ][4]++;
+ }
+ }
+
+ printf( "Functions found = %10d. Functions not found = %10d.\n", p->nCellFound, p->nCellNotFound );
+ for ( k = 0; k <= CUT_CELL_MVAR; k++ )
+ {
+ printf( "%3d : ", k );
+ for ( i = 0; i < 5; i++ )
+ printf( "%8d ", NumUsed[k][i] );
+ printf( "\n" );
+ }
+ printf( "Box usage:\n" );
+ for ( k = 0; k < 22; k++ )
+ {
+ printf( "%3d : ", k );
+ for ( i = 0; i < 5; i++ )
+ printf( "%8d ", BoxUsed[k][i] );
+ printf( " %s", s_NP3Names[k] );
+ printf( "\n" );
+ }
+
+ pFile = fopen( pFileName, "w" );
+ if ( pFile == NULL )
+ {
+ printf( "Cut_CellDumpToFile: Cannout open output file.\n" );
+ return;
+ }
+
+ Counter = 0;
+ for ( k = 0; k <= CUT_CELL_MVAR; k++ )
+ {
+ for ( pTemp = p->pSameVar[k]; pTemp; pTemp = pTemp->pNextVar )
+ if ( pTemp->nUsed > 0 )
+ {
+ Extra_PrintHexadecimal( pFile, pTemp->uTruth, (k <= 5? 5 : k) );
+ fprintf( pFile, "\n" );
+ Counter++;
+ }
+ fprintf( pFile, "\n" );
+ }
+ fclose( pFile );
+
+ printf( "Library composed of %d functions is written into file \"%s\". ", Counter, pFileName );
+
+ PRT( "Time", clock() - clk );
+}
+
+
+/**Function*************************************************************
+
+ Synopsis [Looks up if the given function exists in the hash table.]
+
+ Description [If the function exists, returns 1, meaning that it can be
+ implemented using two levels of 3-input LUTs. If the function does not
+ exist, return 0.]
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Cut_CellTruthLookup( unsigned * pTruth, int nVars )
+{
+ Cut_CMan_t * p = s_pCMan;
+ Cut_Cell_t * pTemp;
+ Cut_Cell_t Cell, * pCell = &Cell;
+ unsigned Hash;
+ int i;
+
+ // cell manager is not defined
+ if ( p == NULL )
+ {
+ printf( "Cut_CellTruthLookup: Cell manager is not defined.\n" );
+ return 0;
+ }
+
+ // canonicize
+ memset( pCell, 0, sizeof(Cut_Cell_t) );
+ pCell->nVars = nVars;
+ Extra_TruthCopy( pCell->uTruth, pTruth, nVars );
+ Cut_CellSuppMin( pCell );
+ // set the elementary permutation
+ for ( i = 0; i < (int)pCell->nVars; i++ )
+ pCell->CanonPerm[i] = i;
+ // canonicize
+ pCell->CanonPhase = Extra_TruthSemiCanonicize( pCell->uTruth, p->puAux, pCell->nVars, pCell->CanonPerm, pCell->Store );
+
+
+ // check if the cell exists
+ Hash = Extra_TruthHash( pCell->uTruth, Extra_TruthWordNum(pCell->nVars) );
+ if ( st_lookup( p->tTable, (char *)Hash, (char **)&pTemp ) )
+ {
+ for ( ; pTemp; pTemp = pTemp->pNext )
+ {
+ if ( pTemp->nVars != pCell->nVars )
+ continue;
+ if ( Extra_TruthIsEqual(pTemp->uTruth, pCell->uTruth, pCell->nVars) )
+ {
+ pTemp->nUsed++;
+ p->nCellFound++;
+ return 1;
+ }
+ }
+ }
+ p->nCellNotFound++;
+ return 0;
+}
+
+
+////////////////////////////////////////////////////////////////////////
+/// END OF FILE ///
+////////////////////////////////////////////////////////////////////////
+
+
diff --git a/src/opt/cut/cutSeq.c b/src/opt/cut/cutSeq.c
index 869bd7b3..d36f94f7 100644
--- a/src/opt/cut/cutSeq.c
+++ b/src/opt/cut/cutSeq.c
@@ -25,12 +25,12 @@
////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////
-/// FUNCTION DEFITIONS ///
+/// FUNCTION DEFINITIONS ///
////////////////////////////////////////////////////////////////////////
/**Function*************************************************************
- Synopsis []
+ Synopsis [Shifts all cut leaves of the node by the given number of latches.]
Description []
@@ -39,6 +39,186 @@
SeeAlso []
***********************************************************************/
+static inline void Cut_NodeShiftCutLeaves( Cut_Cut_t * pList, int nLat )
+{
+ Cut_Cut_t * pTemp;
+ int i;
+ // shift the cuts by as many latches
+ Cut_ListForEachCut( pList, pTemp )
+ {
+ pTemp->uSign = 0;
+ for ( i = 0; i < (int)pTemp->nLeaves; i++ )
+ {
+ pTemp->pLeaves[i] += nLat;
+ pTemp->uSign |= Cut_NodeSign( pTemp->pLeaves[i] );
+ }
+ }
+}
+
+/**Function*************************************************************
+
+ Synopsis [Computes sequential cuts for the node from its fanins.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Cut_NodeComputeCutsSeq( Cut_Man_t * p, int Node, int Node0, int Node1, int fCompl0, int fCompl1, int nLat0, int nLat1, int fTriv, int CutSetNum )
+{
+ Cut_List_t Super, * pSuper = &Super;
+ Cut_Cut_t * pListNew;
+ int clk;
+
+ // get the number of cuts at the node
+ p->nNodeCuts = Cut_CutCountList( Cut_NodeReadCutsOld(p, Node) );
+ if ( p->nNodeCuts >= p->pParams->nKeepMax )
+ return;
+
+ // count only the first visit
+ if ( p->nNodeCuts == 0 )
+ p->nNodes++;
+
+ // store the fanin lists
+ p->pStore0[0] = Cut_NodeReadCutsOld( p, Node0 );
+ p->pStore0[1] = Cut_NodeReadCutsNew( p, Node0 );
+ p->pStore1[0] = Cut_NodeReadCutsOld( p, Node1 );
+ p->pStore1[1] = Cut_NodeReadCutsNew( p, Node1 );
+
+ // duplicate the cut lists if fanin nodes are non-standard
+ if ( Node == Node0 || Node == Node1 || Node0 == Node1 )
+ {
+ p->pStore0[0] = Cut_CutDupList( p, p->pStore0[0] );
+ p->pStore0[1] = Cut_CutDupList( p, p->pStore0[1] );
+ p->pStore1[0] = Cut_CutDupList( p, p->pStore1[0] );
+ p->pStore1[1] = Cut_CutDupList( p, p->pStore1[1] );
+ }
+
+ // shift the cuts by as many latches and recompute signatures
+ if ( nLat0 ) Cut_NodeShiftCutLeaves( p->pStore0[0], nLat0 );
+ if ( nLat0 ) Cut_NodeShiftCutLeaves( p->pStore0[1], nLat0 );
+ if ( nLat1 ) Cut_NodeShiftCutLeaves( p->pStore1[0], nLat1 );
+ if ( nLat1 ) Cut_NodeShiftCutLeaves( p->pStore1[1], nLat1 );
+
+ // store the original lists for comparison
+ p->pCompareOld = Cut_NodeReadCutsOld( p, Node );
+ p->pCompareNew = Cut_NodeReadCutsNew( p, Node );
+
+ // merge the old and the new
+clk = clock();
+ Cut_ListStart( pSuper );
+ Cut_NodeDoComputeCuts( p, pSuper, Node, fCompl0, fCompl1, p->pStore0[0], p->pStore1[1], 0, 0 );
+ Cut_NodeDoComputeCuts( p, pSuper, Node, fCompl0, fCompl1, p->pStore0[1], p->pStore1[0], 0, 0 );
+ Cut_NodeDoComputeCuts( p, pSuper, Node, fCompl0, fCompl1, p->pStore0[1], p->pStore1[1], fTriv, 0 );
+ pListNew = Cut_ListFinish( pSuper );
+p->timeMerge += clock() - clk;
+
+ // shift the cuts by as many latches and recompute signatures
+ if ( Node == Node0 || Node == Node1 || Node0 == Node1 )
+ {
+ Cut_CutRecycleList( p, p->pStore0[0] );
+ Cut_CutRecycleList( p, p->pStore0[1] );
+ Cut_CutRecycleList( p, p->pStore1[0] );
+ Cut_CutRecycleList( p, p->pStore1[1] );
+ }
+ else
+ {
+ if ( nLat0 ) Cut_NodeShiftCutLeaves( p->pStore0[0], -nLat0 );
+ if ( nLat0 ) Cut_NodeShiftCutLeaves( p->pStore0[1], -nLat0 );
+ if ( nLat1 ) Cut_NodeShiftCutLeaves( p->pStore1[0], -nLat1 );
+ if ( nLat1 ) Cut_NodeShiftCutLeaves( p->pStore1[1], -nLat1 );
+ }
+
+ // set the lists at the node
+ if ( CutSetNum >= 0 )
+ {
+ assert( Cut_NodeReadCutsTemp(p, CutSetNum) == NULL );
+ Cut_NodeWriteCutsTemp( p, CutSetNum, pListNew );
+ }
+ else
+ {
+ assert( Cut_NodeReadCutsNew(p, Node) == NULL );
+ Cut_NodeWriteCutsNew( p, Node, pListNew );
+ }
+
+ // mark the node if we exceeded the number of cuts
+ if ( p->nNodeCuts >= p->pParams->nKeepMax )
+ p->nCutsLimit++;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Merges the new cuts with the old cuts.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Cut_NodeNewMergeWithOld( Cut_Man_t * p, int Node )
+{
+ Cut_Cut_t * pListOld, * pListNew, * pList;
+ // get the new cuts
+ pListNew = Cut_NodeReadCutsNew( p, Node );
+ if ( pListNew == NULL )
+ return;
+ Cut_NodeWriteCutsNew( p, Node, NULL );
+ // get the old cuts
+ pListOld = Cut_NodeReadCutsOld( p, Node );
+ if ( pListOld == NULL )
+ {
+ Cut_NodeWriteCutsOld( p, Node, pListNew );
+ return;
+ }
+ // merge the lists
+ pList = Cut_CutMergeLists( pListOld, pListNew );
+ Cut_NodeWriteCutsOld( p, Node, pList );
+}
+
+
+/**Function*************************************************************
+
+ Synopsis [Transfers the temporary cuts to be the new cuts.]
+
+ Description [Returns 1 if something was transferred.]
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Cut_NodeTempTransferToNew( Cut_Man_t * p, int Node, int CutSetNum )
+{
+ Cut_Cut_t * pList;
+ pList = Cut_NodeReadCutsTemp( p, CutSetNum );
+ Cut_NodeWriteCutsTemp( p, CutSetNum, NULL );
+ Cut_NodeWriteCutsNew( p, Node, pList );
+ return pList != NULL;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Transfers the old cuts to be the new cuts.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Cut_NodeOldTransferToNew( Cut_Man_t * p, int Node )
+{
+ Cut_Cut_t * pList;
+ pList = Cut_NodeReadCutsOld( p, Node );
+ Cut_NodeWriteCutsOld( p, Node, NULL );
+ Cut_NodeWriteCutsNew( p, Node, pList );
+// Cut_CutListVerify( pList );
+}
////////////////////////////////////////////////////////////////////////
/// END OF FILE ///
diff --git a/src/opt/cut/cutTable.c b/src/opt/cut/cutTable.c
deleted file mode 100644
index 5dfaca7b..00000000
--- a/src/opt/cut/cutTable.c
+++ /dev/null
@@ -1,253 +0,0 @@
-/**CFile****************************************************************
-
- FileName [cutTable.c]
-
- SystemName [ABC: Logic synthesis and verification system.]
-
- PackageName [K-feasible cut computation package.]
-
- Synopsis [Hashing cuts to prevent duplication.]
-
- Author [Alan Mishchenko]
-
- Affiliation [UC Berkeley]
-
- Date [Ver. 1.0. Started - June 20, 2005.]
-
- Revision [$Id: cutTable.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
-
-***********************************************************************/
-
-#include "cutInt.h"
-
-////////////////////////////////////////////////////////////////////////
-/// DECLARATIONS ///
-////////////////////////////////////////////////////////////////////////
-
-struct Cut_HashTableStruct_t_
-{
- int nBins;
- Cut_Cut_t ** pBins;
- int nEntries;
- int * pPlaces;
- int nPlaces;
- int timeLookup;
-};
-
-// iterator through all the cuts of the list
-#define Cut_TableListForEachCut( pList, pCut ) \
- for ( pCut = pList; \
- pCut; \
- pCut = pCut->pData )
-#define Cut_TableListForEachCutSafe( pList, pCut, pCut2 ) \
- for ( pCut = pList, \
- pCut2 = pCut? pCut->pData: NULL; \
- pCut; \
- pCut = pCut2, \
- pCut2 = pCut? pCut->pData: NULL )
-
-// primes used to compute the hash key
-static int s_HashPrimes[10] = { 109, 499, 557, 619, 631, 709, 797, 881, 907, 991 };
-
-// hashing function
-static inline unsigned Cut_HashKey( Cut_Cut_t * pCut )
-{
- unsigned i, uRes = pCut->nLeaves * s_HashPrimes[9];
- for ( i = 0; i < pCut->nLeaves + pCut->fSeq; i++ )
- uRes += s_HashPrimes[i] * pCut->pLeaves[i];
- return uRes;
-}
-
-// hashing function
-static inline int Cut_CompareTwo( Cut_Cut_t * pCut1, Cut_Cut_t * pCut2 )
-{
- unsigned i;
- if ( pCut1->nLeaves != pCut2->nLeaves )
- return 1;
- for ( i = 0; i < pCut1->nLeaves; i++ )
- if ( pCut1->pLeaves[i] != pCut2->pLeaves[i] )
- return 1;
- return 0;
-}
-
-static void Cut_TableResize( Cut_HashTable_t * pTable );
-
-////////////////////////////////////////////////////////////////////////
-/// FUNCTION DEFITIONS ///
-////////////////////////////////////////////////////////////////////////
-
-/**Function*************************************************************
-
- Synopsis [Starts the hash table.]
-
- Description []
-
- SideEffects []
-
- SeeAlso []
-
-***********************************************************************/
-Cut_HashTable_t * Cut_TableStart( int Size )
-{
- Cut_HashTable_t * pTable;
- pTable = ALLOC( Cut_HashTable_t, 1 );
- memset( pTable, 0, sizeof(Cut_HashTable_t) );
- // allocate the table
- pTable->nBins = Cudd_PrimeCopy( Size );
- pTable->pBins = ALLOC( Cut_Cut_t *, pTable->nBins );
- memset( pTable->pBins, 0, sizeof(Cut_Cut_t *) * pTable->nBins );
- pTable->pPlaces = ALLOC( int, pTable->nBins );
- return pTable;
-}
-
-/**Function*************************************************************
-
- Synopsis [Stops the hash table.]
-
- Description []
-
- SideEffects []
-
- SeeAlso []
-
-***********************************************************************/
-void Cut_TableStop( Cut_HashTable_t * pTable )
-{
- FREE( pTable->pPlaces );
- free( pTable->pBins );
- free( pTable );
-}
-
-/**Function*************************************************************
-
- Synopsis [Check the existence of a cut in the lookup table]
-
- Description [Returns 1 if the entry is found.]
-
- SideEffects []
-
- SeeAlso []
-
-***********************************************************************/
-int Cut_TableLookup( Cut_HashTable_t * pTable, Cut_Cut_t * pCut, int fStore )
-{
- Cut_Cut_t * pEnt;
- unsigned Key;
- int clk = clock();
-
- Key = Cut_HashKey(pCut) % pTable->nBins;
- Cut_TableListForEachCut( pTable->pBins[Key], pEnt )
- {
- if ( !Cut_CompareTwo( pEnt, pCut ) )
- {
-pTable->timeLookup += clock() - clk;
- return 1;
- }
- }
- if ( pTable->nEntries > 2 * pTable->nBins )
- {
- Cut_TableResize( pTable );
- Key = Cut_HashKey(pCut) % pTable->nBins;
- }
- // remember the place
- if ( fStore && pTable->pBins[Key] == NULL )
- pTable->pPlaces[ pTable->nPlaces++ ] = Key;
- // add the cut to the table
- pCut->pData = pTable->pBins[Key];
- pTable->pBins[Key] = pCut;
- pTable->nEntries++;
-pTable->timeLookup += clock() - clk;
- return 0;
-}
-
-
-/**Function*************************************************************
-
- Synopsis [Stops the hash table.]
-
- Description []
-
- SideEffects []
-
- SeeAlso []
-
-***********************************************************************/
-void Cut_TableClear( Cut_HashTable_t * pTable )
-{
- int i;
- assert( pTable->nPlaces <= pTable->nBins );
- for ( i = 0; i < pTable->nPlaces; i++ )
- {
- assert( pTable->pBins[ pTable->pPlaces[i] ] );
- pTable->pBins[ pTable->pPlaces[i] ] = NULL;
- }
- pTable->nPlaces = 0;
- pTable->nEntries = 0;
-}
-
-/**Function*************************************************************
-
- Synopsis []
-
- Description []
-
- SideEffects []
-
- SeeAlso []
-
-***********************************************************************/
-void Cut_TableResize( Cut_HashTable_t * pTable )
-{
- Cut_Cut_t ** pBinsNew;
- Cut_Cut_t * pEnt, * pEnt2;
- int nBinsNew, Counter, i, clk;
- unsigned Key;
-
-clk = clock();
- // get the new table size
- nBinsNew = Cudd_PrimeCopy( 3 * pTable->nBins );
- // allocate a new array
- pBinsNew = ALLOC( Cut_Cut_t *, nBinsNew );
- memset( pBinsNew, 0, sizeof(Cut_Cut_t *) * nBinsNew );
- // rehash the entries from the old table
- Counter = 0;
- for ( i = 0; i < pTable->nBins; i++ )
- Cut_TableListForEachCutSafe( pTable->pBins[i], pEnt, pEnt2 )
- {
- Key = Cut_HashKey(pEnt) % nBinsNew;
- pEnt->pData = pBinsNew[Key];
- pBinsNew[Key] = pEnt;
- Counter++;
- }
- assert( Counter == pTable->nEntries );
-// printf( "Increasing the structural table size from %6d to %6d. ", pMan->nBins, nBinsNew );
-// PRT( "Time", clock() - clk );
- // replace the table and the parameters
- free( pTable->pBins );
- pTable->pBins = pBinsNew;
- pTable->nBins = nBinsNew;
-}
-
-/**Function*************************************************************
-
- Synopsis [Stops the hash table.]
-
- Description []
-
- SideEffects []
-
- SeeAlso []
-
-***********************************************************************/
-int Cut_TableReadTime( Cut_HashTable_t * pTable )
-{
- if ( pTable == NULL )
- return 0;
- return pTable->timeLookup;
-}
-
-////////////////////////////////////////////////////////////////////////
-/// END OF FILE ///
-////////////////////////////////////////////////////////////////////////
-
-
diff --git a/src/opt/cut/cutTruth.c b/src/opt/cut/cutTruth.c
index efacd456..c3514ad7 100644
--- a/src/opt/cut/cutTruth.c
+++ b/src/opt/cut/cutTruth.c
@@ -20,21 +20,27 @@
#include "cutInt.h"
+/*
+ Truth tables computed in this package are represented as bit-strings
+ stored in the cut data structure. Cuts of any number of inputs have
+ the truth table with 2^k bits, where k is the max number of cut inputs.
+*/
+
////////////////////////////////////////////////////////////////////////
/// DECLARATIONS ///
////////////////////////////////////////////////////////////////////////
-static void Cut_TruthCompute4( Cut_Man_t * p, Cut_Cut_t * pCut, Cut_Cut_t * pCut0, Cut_Cut_t * pCut1 );
-static void Cut_TruthCompute5( Cut_Man_t * p, Cut_Cut_t * pCut, Cut_Cut_t * pCut0, Cut_Cut_t * pCut1 );
-static void Cut_TruthCompute6( Cut_Man_t * p, Cut_Cut_t * pCut, Cut_Cut_t * pCut0, Cut_Cut_t * pCut1 );
+extern int nTotal = 0;
+extern int nGood = 0;
+extern int nEqual = 0;
////////////////////////////////////////////////////////////////////////
-/// FUNCTION DEFITIONS ///
+/// FUNCTION DEFINITIONS ///
////////////////////////////////////////////////////////////////////////
/**Function*************************************************************
- Synopsis [Performs truth table computation.]
+ Synopsis [Computes the stretching phase of the cut w.r.t. the merged cut.]
Description []
@@ -64,58 +70,42 @@ static inline unsigned Cut_TruthPhase( Cut_Cut_t * pCut, Cut_Cut_t * pCut1 )
Synopsis [Performs truth table computation.]
- Description []
-
- SideEffects []
-
- SeeAlso []
-
-***********************************************************************/
-void Cut_TruthCompute( Cut_Man_t * p, Cut_Cut_t * pCut, Cut_Cut_t * pCut0, Cut_Cut_t * pCut1 )
-{
-int clk = clock();
- if ( pCut->nVarsMax == 4 )
- Cut_TruthCompute4( p, pCut, pCut0, pCut1 );
- else if ( pCut->nVarsMax == 5 )
- Cut_TruthCompute5( p, pCut, pCut0, pCut1 );
- else // if ( pCut->nVarsMax == 6 )
- Cut_TruthCompute6( p, pCut, pCut0, pCut1 );
-p->timeTruth += clock() - clk;
-}
-
-/**Function*************************************************************
-
- Synopsis [Performs truth table computation.]
-
- Description []
+ Description [This procedure cannot be used while recording oracle
+ because it will overwrite Num0 and Num1.]
SideEffects []
SeeAlso []
***********************************************************************/
-void Cut_TruthCompute4( Cut_Man_t * p, Cut_Cut_t * pCut, Cut_Cut_t * pCut0, Cut_Cut_t * pCut1 )
+void Cut_TruthNCanonicize( Cut_Cut_t * pCut )
{
- unsigned * puTruthCut0, * puTruthCut1;
- unsigned uTruth0, uTruth1, uPhase;
-
- puTruthCut0 = Cut_CutReadTruth(pCut0);
- puTruthCut1 = Cut_CutReadTruth(pCut1);
-
- uPhase = Cut_TruthPhase( pCut, pCut0 );
- uTruth0 = Extra_TruthPerm4One( *puTruthCut0, uPhase );
- uTruth0 = p->fCompl0? ~uTruth0: uTruth0;
-
- uPhase = Cut_TruthPhase( pCut, pCut1 );
- uTruth1 = Extra_TruthPerm4One( *puTruthCut1, uPhase );
- uTruth1 = p->fCompl1? ~uTruth1: uTruth1;
+ unsigned uTruth;
+ unsigned * uCanon2;
+ char * pPhases2;
+ assert( pCut->nVarsMax < 6 );
- uTruth1 = uTruth0 & uTruth1;
- if ( pCut->fCompl )
- uTruth1 = ~uTruth1;
- if ( pCut->nVarsMax == 4 )
- uTruth1 &= 0xFFFF;
- Cut_CutWriteTruth( pCut, &uTruth1 );
+ // get the direct truth table
+ uTruth = *Cut_CutReadTruth(pCut);
+
+ // compute the direct truth table
+ Extra_TruthCanonFastN( pCut->nVarsMax, pCut->nLeaves, &uTruth, &uCanon2, &pPhases2 );
+// uCanon[0] = uCanon2[0];
+// uCanon[1] = (p->nVarsMax == 6)? uCanon2[1] : uCanon2[0];
+// uPhases[0] = pPhases2[0];
+ pCut->uCanon0 = uCanon2[0];
+ pCut->Num0 = pPhases2[0];
+
+ // get the complemented truth table
+ uTruth = ~*Cut_CutReadTruth(pCut);
+
+ // compute the direct truth table
+ Extra_TruthCanonFastN( pCut->nVarsMax, pCut->nLeaves, &uTruth, &uCanon2, &pPhases2 );
+// uCanon[0] = uCanon2[0];
+// uCanon[1] = (p->nVarsMax == 6)? uCanon2[1] : uCanon2[0];
+// uPhases[0] = pPhases2[0];
+ pCut->uCanon1 = uCanon2[0];
+ pCut->Num1 = pPhases2[0];
}
/**Function*************************************************************
@@ -129,26 +119,44 @@ void Cut_TruthCompute4( Cut_Man_t * p, Cut_Cut_t * pCut, Cut_Cut_t * pCut0, Cut_
SeeAlso []
***********************************************************************/
-void Cut_TruthCompute5( Cut_Man_t * p, Cut_Cut_t * pCut, Cut_Cut_t * pCut0, Cut_Cut_t * pCut1 )
+void Cut_TruthComputeOld( Cut_Cut_t * pCut, Cut_Cut_t * pCut0, Cut_Cut_t * pCut1, int fCompl0, int fCompl1 )
{
- unsigned * puTruthCut0, * puTruthCut1;
- unsigned uTruth0, uTruth1, uPhase;
+ static unsigned uTruth0[8], uTruth1[8];
+ int nTruthWords = Cut_TruthWords( pCut->nVarsMax );
+ unsigned * pTruthRes;
+ int i, uPhase;
- puTruthCut0 = Cut_CutReadTruth(pCut0);
- puTruthCut1 = Cut_CutReadTruth(pCut1);
+ // permute the first table
+ uPhase = Cut_TruthPhase( pCut, pCut0 );
+ Extra_TruthExpand( pCut->nVarsMax, nTruthWords, Cut_CutReadTruth(pCut0), uPhase, uTruth0 );
+ if ( fCompl0 )
+ {
+ for ( i = 0; i < nTruthWords; i++ )
+ uTruth0[i] = ~uTruth0[i];
+ }
- uPhase = Cut_TruthPhase( pCut, pCut0 );
- uTruth0 = Extra_TruthPerm5One( *puTruthCut0, uPhase );
- uTruth0 = p->fCompl0? ~uTruth0: uTruth0;
+ // permute the second table
+ uPhase = Cut_TruthPhase( pCut, pCut1 );
+ Extra_TruthExpand( pCut->nVarsMax, nTruthWords, Cut_CutReadTruth(pCut1), uPhase, uTruth1 );
+ if ( fCompl1 )
+ {
+ for ( i = 0; i < nTruthWords; i++ )
+ uTruth1[i] = ~uTruth1[i];
+ }
- uPhase = Cut_TruthPhase( pCut, pCut1 );
- uTruth1 = Extra_TruthPerm5One( *puTruthCut1, uPhase );
- uTruth1 = p->fCompl1? ~uTruth1: uTruth1;
+ // write the resulting table
+ pTruthRes = Cut_CutReadTruth(pCut);
- uTruth1 = uTruth0 & uTruth1;
if ( pCut->fCompl )
- uTruth1 = ~uTruth1;
- Cut_CutWriteTruth( pCut, &uTruth1 );
+ {
+ for ( i = 0; i < nTruthWords; i++ )
+ pTruthRes[i] = ~(uTruth0[i] & uTruth1[i]);
+ }
+ else
+ {
+ for ( i = 0; i < nTruthWords; i++ )
+ pTruthRes[i] = uTruth0[i] & uTruth1[i];
+ }
}
/**Function*************************************************************
@@ -162,158 +170,54 @@ void Cut_TruthCompute5( Cut_Man_t * p, Cut_Cut_t * pCut, Cut_Cut_t * pCut0, Cut_
SeeAlso []
***********************************************************************/
-void Cut_TruthCompute6( Cut_Man_t * p, Cut_Cut_t * pCut, Cut_Cut_t * pCut0, Cut_Cut_t * pCut1 )
+void Cut_TruthCompute( Cut_Man_t * p, Cut_Cut_t * pCut, Cut_Cut_t * pCut0, Cut_Cut_t * pCut1, int fCompl0, int fCompl1 )
{
- unsigned * puTruthCut0, * puTruthCut1;
- unsigned uTruth0[2], uTruth1[2], uPhase;
-
- puTruthCut0 = Cut_CutReadTruth(pCut0);
- puTruthCut1 = Cut_CutReadTruth(pCut1);
-
- uPhase = Cut_TruthPhase( pCut, pCut0 );
- Extra_TruthPerm6One( puTruthCut0, uPhase, uTruth0 );
- uTruth0[0] = p->fCompl0? ~uTruth0[0]: uTruth0[0];
- uTruth0[1] = p->fCompl0? ~uTruth0[1]: uTruth0[1];
-
- uPhase = Cut_TruthPhase( pCut, pCut1 );
- Extra_TruthPerm6One( puTruthCut1, uPhase, uTruth1 );
- uTruth1[0] = p->fCompl1? ~uTruth1[0]: uTruth1[0];
- uTruth1[1] = p->fCompl1? ~uTruth1[1]: uTruth1[1];
-
- uTruth1[0] = uTruth0[0] & uTruth1[0];
- uTruth1[1] = uTruth0[1] & uTruth1[1];
+ // permute the first table
+ if ( fCompl0 )
+ Extra_TruthNot( p->puTemp[0], Cut_CutReadTruth(pCut0), pCut->nVarsMax );
+ else
+ Extra_TruthCopy( p->puTemp[0], Cut_CutReadTruth(pCut0), pCut->nVarsMax );
+ Extra_TruthStretch( p->puTemp[2], p->puTemp[0], pCut0->nLeaves, pCut->nVarsMax, Cut_TruthPhase(pCut, pCut0) );
+ // permute the second table
+ if ( fCompl1 )
+ Extra_TruthNot( p->puTemp[1], Cut_CutReadTruth(pCut1), pCut->nVarsMax );
+ else
+ Extra_TruthCopy( p->puTemp[1], Cut_CutReadTruth(pCut1), pCut->nVarsMax );
+ Extra_TruthStretch( p->puTemp[3], p->puTemp[1], pCut1->nLeaves, pCut->nVarsMax, Cut_TruthPhase(pCut, pCut1) );
+ // produce the resulting table
if ( pCut->fCompl )
- {
- uTruth1[0] = ~uTruth0[0];
- uTruth1[1] = ~uTruth0[1];
- }
- Cut_CutWriteTruth( pCut, uTruth1 );
-}
-
+ Extra_TruthNand( Cut_CutReadTruth(pCut), p->puTemp[2], p->puTemp[3], pCut->nVarsMax );
+ else
+ Extra_TruthAnd( Cut_CutReadTruth(pCut), p->puTemp[2], p->puTemp[3], pCut->nVarsMax );
+// Ivy_TruthTestOne( *Cut_CutReadTruth(pCut) );
+ // quit if no fancy computation is needed
+ if ( !p->pParams->fFancy )
+ return;
+ if ( pCut->nLeaves != 7 )
+ return;
+ // count the total number of truth tables computed
+ nTotal++;
-/**Function*************************************************************
-
- Synopsis [Performs truth table computation.]
-
- Description []
-
- SideEffects []
+ // MAPPING INTO ALTERA 6-2 LOGIC BLOCKS
+ // call this procedure to find the minimum number of common variables in the cofactors
+ // if this number is less or equal than 3, the cut can be implemented using the 6-2 logic block
+ if ( Extra_TruthMinCofSuppOverlap( Cut_CutReadTruth(pCut), pCut->nVarsMax, NULL ) <= 4 )
+ nGood++;
- SeeAlso []
+ // MAPPING INTO ACTEL 2x2 CELLS
+ // call this procedure to see if a semi-canonical form can be found in the lookup table
+ // (if it exists, then a two-level 3-input LUT implementation of the cut exists)
+ // Before this procedure is called, cell manager should be defined by calling
+ // Cut_CellLoad (make sure file "cells22_daomap_iwls.txt" is available in the working dir)
+// if ( Cut_CellIsRunning() && pCut->nVarsMax <= 9 )
+// nGood += Cut_CellTruthLookup( Cut_CutReadTruth(pCut), pCut->nVarsMax );
+}
-***********************************************************************/
-void Cut_TruthComputeOld( Cut_Man_t * p, Cut_Cut_t * pCut, Cut_Cut_t * pCut0, Cut_Cut_t * pCut1 )
-{
- unsigned uTruth0, uTruth1, uPhase;
- int clk = clock();
- assert( pCut->nVarsMax < 6 );
-
- // assign the truth table
- if ( pCut0->nLeaves == pCut->nLeaves )
- uTruth0 = *Cut_CutReadTruth(pCut0);
- else
- {
- assert( pCut0->nLeaves < pCut->nLeaves );
- uPhase = Cut_TruthPhase( pCut, pCut0 );
- if ( pCut->nVarsMax == 4 )
- {
- assert( pCut0->nLeaves < 4 );
- assert( uPhase < 16 );
- uTruth0 = p->pPerms43[pCut0->uTruth & 0xFF][uPhase];
- }
- else
- {
- assert( pCut->nVarsMax == 5 );
- assert( pCut0->nLeaves < 5 );
- assert( uPhase < 32 );
- if ( pCut0->nLeaves == 4 )
- {
-// Count4++;
-/*
- if ( uPhase == 31-16 ) // 01111
- uTruth0 = pCut0->uTruth;
- else if ( uPhase == 31-8 ) // 10111
- uTruth0 = p->pPerms54[pCut0->uTruth & 0xFFFF][0];
- else if ( uPhase == 31-4 ) // 11011
- uTruth0 = p->pPerms54[pCut0->uTruth & 0xFFFF][1];
- else if ( uPhase == 31-2 ) // 11101
- uTruth0 = p->pPerms54[pCut0->uTruth & 0xFFFF][2];
- else if ( uPhase == 31-1 ) // 11110
- uTruth0 = p->pPerms54[pCut0->uTruth & 0xFFFF][3];
- else
- assert( 0 );
-*/
- uTruth0 = Extra_TruthPerm5One( *Cut_CutReadTruth(pCut0), uPhase );
- }
- else
- {
-// Count5++;
-// uTruth0 = p->pPerms53[pCut0->uTruth & 0xFF][uPhase];
- uTruth0 = Extra_TruthPerm5One( *Cut_CutReadTruth(pCut0), uPhase );
- }
- }
- }
- uTruth0 = p->fCompl0? ~uTruth0: uTruth0;
-
- // assign the truth table
- if ( pCut1->nLeaves == pCut->nLeaves )
- uTruth0 = *Cut_CutReadTruth(pCut1);
- else
- {
- assert( pCut1->nLeaves < pCut->nLeaves );
- uPhase = Cut_TruthPhase( pCut, pCut1 );
- if ( pCut->nVarsMax == 4 )
- {
- assert( pCut1->nLeaves < 4 );
- assert( uPhase < 16 );
- uTruth1 = p->pPerms43[pCut1->uTruth & 0xFF][uPhase];
- }
- else
- {
- assert( pCut->nVarsMax == 5 );
- assert( pCut1->nLeaves < 5 );
- assert( uPhase < 32 );
- if ( pCut1->nLeaves == 4 )
- {
-// Count4++;
-/*
- if ( uPhase == 31-16 ) // 01111
- uTruth1 = pCut1->uTruth;
- else if ( uPhase == 31-8 ) // 10111
- uTruth1 = p->pPerms54[pCut1->uTruth & 0xFFFF][0];
- else if ( uPhase == 31-4 ) // 11011
- uTruth1 = p->pPerms54[pCut1->uTruth & 0xFFFF][1];
- else if ( uPhase == 31-2 ) // 11101
- uTruth1 = p->pPerms54[pCut1->uTruth & 0xFFFF][2];
- else if ( uPhase == 31-1 ) // 11110
- uTruth1 = p->pPerms54[pCut1->uTruth & 0xFFFF][3];
- else
- assert( 0 );
-*/
- uTruth1 = Extra_TruthPerm5One( *Cut_CutReadTruth(pCut1), uPhase );
- }
- else
- {
-// Count5++;
-// uTruth1 = p->pPerms53[pCut1->uTruth & 0xFF][uPhase];
- uTruth1 = Extra_TruthPerm5One( *Cut_CutReadTruth(pCut1), uPhase );
- }
- }
- }
- uTruth1 = p->fCompl1? ~uTruth1: uTruth1;
- uTruth1 = uTruth0 & uTruth1;
- if ( pCut->fCompl )
- uTruth1 = ~uTruth1;
- if ( pCut->nVarsMax == 4 )
- uTruth1 &= 0xFFFF;
- Cut_CutWriteTruth( pCut, &uTruth1 );
-p->timeTruth += clock() - clk;
-}
////////////////////////////////////////////////////////////////////////
/// END OF FILE ///
diff --git a/src/opt/cut/module.make b/src/opt/cut/module.make
index 1175b3f2..132e730b 100644
--- a/src/opt/cut/module.make
+++ b/src/opt/cut/module.make
@@ -1,6 +1,9 @@
-SRC += src/opt/cut/cutMan.c \
+SRC += src/opt/cut/cutApi.c \
+ src/opt/cut/cutCut.c \
+ src/opt/cut/cutMan.c \
src/opt/cut/cutMerge.c \
src/opt/cut/cutNode.c \
+ src/opt/cut/cutOracle.c \
+ src/opt/cut/cutPre22.c \
src/opt/cut/cutSeq.c \
- src/opt/cut/cutTable.c \
src/opt/cut/cutTruth.c
diff --git a/src/opt/dec/dec.h b/src/opt/dec/dec.h
index 6ecc9678..d0d9981d 100644
--- a/src/opt/dec/dec.h
+++ b/src/opt/dec/dec.h
@@ -21,6 +21,10 @@
#ifndef __DEC_H__
#define __DEC_H__
+#ifdef __cplusplus
+extern "C" {
+#endif
+
////////////////////////////////////////////////////////////////////////
/// INCLUDES ///
////////////////////////////////////////////////////////////////////////
@@ -47,11 +51,15 @@ struct Dec_Node_t_
Dec_Edge_t eEdge1; // the right child of the node
// other info
void * pFunc; // the function of the node (BDD or AIG)
- unsigned Level : 16; // the level of this node in the global 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;
@@ -95,9 +103,6 @@ struct Dec_Man_t_
////////////////////////////////////////////////////////////////////////
/*=== decAbc.c ========================================================*/
-extern Abc_Obj_t * Dec_GraphToNetwork( Abc_Aig_t * pMan, Dec_Graph_t * pGraph );
-extern int Dec_GraphToNetworkCount( Abc_Obj_t * pRoot, Dec_Graph_t * pGraph, int NodeMax, int LevelMax );
-extern void Dec_GraphUpdateNetwork( Abc_Obj_t * pRoot, Dec_Graph_t * pGraph, int nGain );
/*=== decFactor.c ========================================================*/
extern Dec_Graph_t * Dec_Factor( char * pSop );
/*=== decMan.c ========================================================*/
@@ -106,11 +111,10 @@ extern void Dec_ManStop( Dec_Man_t * p );
/*=== decPrint.c ========================================================*/
extern void Dec_GraphPrint( FILE * pFile, Dec_Graph_t * pGraph, char * pNamesIn[], char * pNameOut );
/*=== decUtil.c ========================================================*/
-extern DdNode * Dec_GraphDeriveBdd( DdManager * dd, Dec_Graph_t * pGraph );
extern unsigned Dec_GraphDeriveTruth( Dec_Graph_t * pGraph );
////////////////////////////////////////////////////////////////////////
-/// FUNCTION DEFITIONS ///
+/// FUNCTION DEFINITIONS ///
////////////////////////////////////////////////////////////////////////
/**Function*************************************************************
@@ -308,7 +312,7 @@ static inline void Dec_GraphFree( Dec_Graph_t * pGraph )
SeeAlso []
***********************************************************************/
-static inline bool Dec_GraphIsConst( Dec_Graph_t * pGraph )
+static inline int Dec_GraphIsConst( Dec_Graph_t * pGraph )
{
return pGraph->fConst;
}
@@ -324,7 +328,7 @@ static inline bool Dec_GraphIsConst( Dec_Graph_t * pGraph )
SeeAlso []
***********************************************************************/
-static inline bool Dec_GraphIsConst0( Dec_Graph_t * pGraph )
+static inline int Dec_GraphIsConst0( Dec_Graph_t * pGraph )
{
return pGraph->fConst && pGraph->eRoot.fCompl;
}
@@ -340,7 +344,7 @@ static inline bool Dec_GraphIsConst0( Dec_Graph_t * pGraph )
SeeAlso []
***********************************************************************/
-static inline bool Dec_GraphIsConst1( Dec_Graph_t * pGraph )
+static inline int Dec_GraphIsConst1( Dec_Graph_t * pGraph )
{
return pGraph->fConst && !pGraph->eRoot.fCompl;
}
@@ -356,7 +360,7 @@ static inline bool Dec_GraphIsConst1( Dec_Graph_t * pGraph )
SeeAlso []
***********************************************************************/
-static inline bool Dec_GraphIsComplement( Dec_Graph_t * pGraph )
+static inline int Dec_GraphIsComplement( Dec_Graph_t * pGraph )
{
return pGraph->eRoot.fCompl;
}
@@ -469,7 +473,7 @@ static inline int Dec_GraphNodeInt( Dec_Graph_t * pGraph, Dec_Node_t * pNode )
SeeAlso []
***********************************************************************/
-static inline bool Dec_GraphIsVar( Dec_Graph_t * pGraph )
+static inline int Dec_GraphIsVar( Dec_Graph_t * pGraph )
{
return pGraph->eRoot.Node < (unsigned)pGraph->nLeaves;
}
@@ -485,7 +489,7 @@ static inline bool Dec_GraphIsVar( Dec_Graph_t * pGraph )
SeeAlso []
***********************************************************************/
-static inline bool Dec_GraphNodeIsVar( Dec_Graph_t * pGraph, Dec_Node_t * pNode )
+static inline int Dec_GraphNodeIsVar( Dec_Graph_t * pGraph, Dec_Node_t * pNode )
{
return Dec_GraphNodeInt(pGraph,pNode) < pGraph->nLeaves;
}
@@ -627,24 +631,84 @@ static inline Dec_Edge_t Dec_GraphAddNodeOr( Dec_Graph_t * pGraph, Dec_Edge_t eE
SeeAlso []
***********************************************************************/
-static inline Dec_Edge_t Dec_GraphAddNodeXor( Dec_Graph_t * pGraph, Dec_Edge_t eEdge0, Dec_Edge_t eEdge1 )
-{
- Dec_Edge_t eNode0, eNode1;
- // derive the first AND
- eEdge0.fCompl = !eEdge0.fCompl;
- eNode0 = Dec_GraphAddNodeAnd( pGraph, eEdge0, eEdge1 );
- eEdge0.fCompl = !eEdge0.fCompl;
- // derive the second AND
- eEdge1.fCompl = !eEdge1.fCompl;
- eNode1 = Dec_GraphAddNodeAnd( pGraph, eEdge0, eEdge1 );
- eEdge1.fCompl = !eEdge1.fCompl;
- // derive the final OR
- return Dec_GraphAddNodeOr( pGraph, eNode0, eNode1 );
+static inline Dec_Edge_t Dec_GraphAddNodeXor( Dec_Graph_t * pGraph, Dec_Edge_t eEdge0, Dec_Edge_t eEdge1, int Type )
+{
+ Dec_Edge_t eNode0, eNode1, eNode;
+ if ( Type == 0 )
+ {
+ // derive the first AND
+ eEdge0.fCompl ^= 1;
+ eNode0 = Dec_GraphAddNodeAnd( pGraph, eEdge0, eEdge1 );
+ eEdge0.fCompl ^= 1;
+ // derive the second AND
+ eEdge1.fCompl ^= 1;
+ eNode1 = Dec_GraphAddNodeAnd( pGraph, eEdge0, eEdge1 );
+ // derive the final OR
+ eNode = Dec_GraphAddNodeOr( pGraph, eNode0, eNode1 );
+ }
+ else
+ {
+ // derive the first AND
+ eNode0 = Dec_GraphAddNodeAnd( pGraph, eEdge0, eEdge1 );
+ // derive the second AND
+ eEdge0.fCompl ^= 1;
+ eEdge1.fCompl ^= 1;
+ eNode1 = Dec_GraphAddNodeAnd( pGraph, eEdge0, eEdge1 );
+ // derive the final OR
+ eNode = Dec_GraphAddNodeOr( pGraph, eNode0, eNode1 );
+ eNode.fCompl ^= 1;
+ }
+ return eNode;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Creates an XOR node.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+static inline Dec_Edge_t Dec_GraphAddNodeMux( Dec_Graph_t * pGraph, Dec_Edge_t eEdgeC, Dec_Edge_t eEdgeT, Dec_Edge_t eEdgeE, int Type )
+{
+ Dec_Edge_t eNode0, eNode1, eNode;
+ if ( Type == 0 )
+ {
+ // derive the first AND
+ eNode0 = Dec_GraphAddNodeAnd( pGraph, eEdgeC, eEdgeT );
+ // derive the second AND
+ eEdgeC.fCompl ^= 1;
+ eNode1 = Dec_GraphAddNodeAnd( pGraph, eEdgeC, eEdgeE );
+ // derive the final OR
+ eNode = Dec_GraphAddNodeOr( pGraph, eNode0, eNode1 );
+ }
+ else
+ {
+ // complement the arguments
+ eEdgeT.fCompl ^= 1;
+ eEdgeE.fCompl ^= 1;
+ // derive the first AND
+ eNode0 = Dec_GraphAddNodeAnd( pGraph, eEdgeC, eEdgeT );
+ // derive the second AND
+ eEdgeC.fCompl ^= 1;
+ eNode1 = Dec_GraphAddNodeAnd( pGraph, eEdgeC, eEdgeE );
+ // derive the final OR
+ eNode = Dec_GraphAddNodeOr( pGraph, eNode0, eNode1 );
+ eNode.fCompl ^= 1;
+ }
+ return eNode;
+}
+
+#ifdef __cplusplus
}
+#endif
+
+#endif
////////////////////////////////////////////////////////////////////////
/// END OF FILE ///
////////////////////////////////////////////////////////////////////////
-#endif
-
diff --git a/src/opt/dec/decAbc.c b/src/opt/dec/decAbc.c
index 9931b136..6adb0f98 100644
--- a/src/opt/dec/decAbc.c
+++ b/src/opt/dec/decAbc.c
@@ -18,13 +18,14 @@
#include "abc.h"
#include "dec.h"
+#include "ivy.h"
////////////////////////////////////////////////////////////////////////
/// DECLARATIONS ///
////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////
-/// FUNCTION DEFITIONS ///
+/// FUNCTION DEFINITIONS ///
////////////////////////////////////////////////////////////////////////
/**Function*************************************************************
@@ -39,14 +40,14 @@
SeeAlso []
***********************************************************************/
-Abc_Obj_t * Dec_GraphToNetwork( Abc_Aig_t * pMan, Dec_Graph_t * pGraph )
+Abc_Obj_t * Dec_GraphToNetwork( Abc_Ntk_t * pNtk, Dec_Graph_t * pGraph )
{
Abc_Obj_t * pAnd0, * pAnd1;
Dec_Node_t * pNode;
int i;
// check for constant function
if ( Dec_GraphIsConst(pGraph) )
- return Abc_ObjNotCond( Abc_AigConst1(pMan), Dec_GraphIsComplement(pGraph) );
+ return Abc_ObjNotCond( Abc_AigConst1(pNtk), Dec_GraphIsComplement(pGraph) );
// check for a literal
if ( Dec_GraphIsVar(pGraph) )
return Abc_ObjNotCond( Dec_GraphVar(pGraph)->pFunc, Dec_GraphIsComplement(pGraph) );
@@ -55,7 +56,45 @@ Abc_Obj_t * Dec_GraphToNetwork( Abc_Aig_t * pMan, Dec_Graph_t * pGraph )
{
pAnd0 = Abc_ObjNotCond( Dec_GraphNode(pGraph, pNode->eEdge0.Node)->pFunc, pNode->eEdge0.fCompl );
pAnd1 = Abc_ObjNotCond( Dec_GraphNode(pGraph, pNode->eEdge1.Node)->pFunc, pNode->eEdge1.fCompl );
- pNode->pFunc = Abc_AigAnd( pMan, pAnd0, pAnd1 );
+ pNode->pFunc = Abc_AigAnd( pNtk->pManFunc, pAnd0, pAnd1 );
+ }
+ // complement the result if necessary
+ return Abc_ObjNotCond( pNode->pFunc, Dec_GraphIsComplement(pGraph) );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Transforms the decomposition graph into the AIG.]
+
+ Description [AIG nodes for the fanins should be assigned to pNode->pFunc
+ of the leaves of the graph before calling this procedure.]
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Abc_Obj_t * Dec_GraphToNetworkNoStrash( Abc_Ntk_t * pNtk, Dec_Graph_t * pGraph )
+{
+ Abc_Obj_t * pAnd, * pAnd0, * pAnd1;
+ Dec_Node_t * pNode;
+ int i;
+ // check for constant function
+ if ( Dec_GraphIsConst(pGraph) )
+ return Abc_ObjNotCond( Abc_AigConst1(pNtk), Dec_GraphIsComplement(pGraph) );
+ // check for a literal
+ if ( Dec_GraphIsVar(pGraph) )
+ return Abc_ObjNotCond( Dec_GraphVar(pGraph)->pFunc, Dec_GraphIsComplement(pGraph) );
+ // build the AIG nodes corresponding to the AND gates of the graph
+ Dec_GraphForEachNode( pGraph, pNode, i )
+ {
+ pAnd0 = Abc_ObjNotCond( Dec_GraphNode(pGraph, pNode->eEdge0.Node)->pFunc, pNode->eEdge0.fCompl );
+ pAnd1 = Abc_ObjNotCond( Dec_GraphNode(pGraph, pNode->eEdge1.Node)->pFunc, pNode->eEdge1.fCompl );
+// pNode->pFunc = Abc_AigAnd( pNtk->pManFunc, pAnd0, pAnd1 );
+ pAnd = Abc_NtkCreateNode( pNtk );
+ Abc_ObjAddFanin( pAnd, pAnd0 );
+ Abc_ObjAddFanin( pAnd, pAnd1 );
+ pNode->pFunc = pAnd;
}
// complement the result if necessary
return Abc_ObjNotCond( pNode->pFunc, Dec_GraphIsComplement(pGraph) );
@@ -119,14 +158,14 @@ int Dec_GraphToNetworkCount( Abc_Obj_t * pRoot, Dec_Graph_t * pGraph, int NodeMa
LevelNew = 1 + ABC_MAX( pNode0->Level, pNode1->Level );
if ( pAnd )
{
- if ( Abc_ObjRegular(pAnd) == Abc_AigConst1(pMan) )
+ 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 );
+// assert( LevelNew == LevelOld );
}
if ( LevelNew > LevelMax )
return -1;
@@ -148,21 +187,118 @@ int Dec_GraphToNetworkCount( Abc_Obj_t * pRoot, Dec_Graph_t * pGraph, int NodeMa
SeeAlso []
***********************************************************************/
-void Dec_GraphUpdateNetwork( Abc_Obj_t * pRoot, Dec_Graph_t * pGraph, int nGain )
+void Dec_GraphUpdateNetwork( Abc_Obj_t * pRoot, Dec_Graph_t * pGraph, bool 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->pManFunc, pGraph );
+ pRootNew = Dec_GraphToNetwork( pNtk, pGraph );
// remove the old nodes
- Abc_AigReplace( pNtk->pManFunc, pRoot, pRootNew );
+ Abc_AigReplace( pNtk->pManFunc, pRoot, pRootNew, fUpdateLevel );
// compare the gains
nNodesNew = Abc_NtkNodeNum(pNtk);
assert( nGain <= nNodesOld - nNodesNew );
}
+
+/**Function*************************************************************
+
+ Synopsis [Transforms the decomposition graph into the AIG.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Hop_Obj_t * Dec_GraphToNetworkAig( Hop_Man_t * pMan, Dec_Graph_t * pGraph )
+{
+ Dec_Node_t * pNode;
+ Hop_Obj_t * pAnd0, * pAnd1;
+ int i;
+ // check for constant function
+ if ( Dec_GraphIsConst(pGraph) )
+ return Hop_NotCond( Hop_ManConst1(pMan), Dec_GraphIsComplement(pGraph) );
+ // check for a literal
+ if ( Dec_GraphIsVar(pGraph) )
+ return Hop_NotCond( Dec_GraphVar(pGraph)->pFunc, Dec_GraphIsComplement(pGraph) );
+ // build the AIG nodes corresponding to the AND gates of the graph
+ Dec_GraphForEachNode( pGraph, pNode, i )
+ {
+ pAnd0 = Hop_NotCond( Dec_GraphNode(pGraph, pNode->eEdge0.Node)->pFunc, pNode->eEdge0.fCompl );
+ pAnd1 = Hop_NotCond( Dec_GraphNode(pGraph, pNode->eEdge1.Node)->pFunc, pNode->eEdge1.fCompl );
+ pNode->pFunc = Hop_And( pMan, pAnd0, pAnd1 );
+ }
+ // complement the result if necessary
+ return Hop_NotCond( pNode->pFunc, Dec_GraphIsComplement(pGraph) );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Strashes one logic node using its SOP.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Hop_Obj_t * Dec_GraphFactorSop( Hop_Man_t * pMan, char * pSop )
+{
+ Hop_Obj_t * pFunc;
+ Dec_Graph_t * pFForm;
+ Dec_Node_t * pNode;
+ int i;
+ // perform factoring
+ pFForm = Dec_Factor( pSop );
+ // collect the fanins
+ Dec_GraphForEachLeaf( pFForm, pNode, i )
+ pNode->pFunc = Hop_IthVar( pMan, i );
+ // perform strashing
+ pFunc = Dec_GraphToNetworkAig( pMan, pFForm );
+ Dec_GraphFree( pFForm );
+ return pFunc;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Transforms the decomposition graph into the AIG.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Ivy_Obj_t * Dec_GraphToNetworkIvy( Ivy_Man_t * pMan, Dec_Graph_t * pGraph )
+{
+ Dec_Node_t * pNode;
+ Ivy_Obj_t * pAnd0, * pAnd1;
+ int i;
+ // check for constant function
+ if ( Dec_GraphIsConst(pGraph) )
+ return Ivy_NotCond( Ivy_ManConst1(pMan), Dec_GraphIsComplement(pGraph) );
+ // check for a literal
+ if ( Dec_GraphIsVar(pGraph) )
+ return Ivy_NotCond( Dec_GraphVar(pGraph)->pFunc, Dec_GraphIsComplement(pGraph) );
+ // build the AIG nodes corresponding to the AND gates of the graph
+ Dec_GraphForEachNode( pGraph, pNode, i )
+ {
+ pAnd0 = Ivy_NotCond( Dec_GraphNode(pGraph, pNode->eEdge0.Node)->pFunc, pNode->eEdge0.fCompl );
+ pAnd1 = Ivy_NotCond( Dec_GraphNode(pGraph, pNode->eEdge1.Node)->pFunc, pNode->eEdge1.fCompl );
+ pNode->pFunc = Ivy_And( pMan, pAnd0, pAnd1 );
+ }
+ // complement the result if necessary
+ return Ivy_NotCond( pNode->pFunc, Dec_GraphIsComplement(pGraph) );
+}
+
+
////////////////////////////////////////////////////////////////////////
/// END OF FILE ///
////////////////////////////////////////////////////////////////////////
diff --git a/src/opt/dec/decFactor.c b/src/opt/dec/decFactor.c
index f6654476..768dcd9b 100644
--- a/src/opt/dec/decFactor.c
+++ b/src/opt/dec/decFactor.c
@@ -34,7 +34,7 @@ static int Dec_FactorVerify( char * pSop, Dec_Graph_t * pFForm );
static Mvc_Cover_t * Dec_ConvertSopToMvc( char * pSop );
////////////////////////////////////////////////////////////////////////
-/// FUNCTION DEFITIONS ///
+/// FUNCTION DEFINITIONS ///
////////////////////////////////////////////////////////////////////////
/**Function*************************************************************
@@ -183,7 +183,7 @@ Dec_Edge_t Dec_Factor_rec( Dec_Graph_t * pFForm, Mvc_Cover_t * pCover )
***********************************************************************/
Dec_Edge_t Dec_FactorLF_rec( Dec_Graph_t * pFForm, Mvc_Cover_t * pCover, Mvc_Cover_t * pSimple )
{
- Dec_Man_t * pManDec = Abc_FrameReadManDec(Abc_FrameGetGlobalFrame());
+ Dec_Man_t * pManDec = Abc_FrameReadManDec();
Vec_Int_t * vEdgeLits = pManDec->vLits;
Mvc_Cover_t * pDiv, * pQuo, * pRem;
Dec_Edge_t eNodeDiv, eNodeQuo, eNodeRem;
@@ -228,7 +228,7 @@ Dec_Edge_t Dec_FactorLF_rec( Dec_Graph_t * pFForm, Mvc_Cover_t * pCover, Mvc_Cov
***********************************************************************/
Dec_Edge_t Dec_FactorTrivial( Dec_Graph_t * pFForm, Mvc_Cover_t * pCover )
{
- Dec_Man_t * pManDec = Abc_FrameReadManDec(Abc_FrameGetGlobalFrame());
+ Dec_Man_t * pManDec = Abc_FrameReadManDec();
Vec_Int_t * vEdgeCubes = pManDec->vCubes;
Vec_Int_t * vEdgeLits = pManDec->vLits;
Mvc_Manager_t * pMem = pManDec->pMvcMem;
@@ -258,16 +258,15 @@ Dec_Edge_t Dec_FactorTrivial( Dec_Graph_t * pFForm, Mvc_Cover_t * pCover )
***********************************************************************/
Dec_Edge_t Dec_FactorTrivialCube( Dec_Graph_t * pFForm, Mvc_Cover_t * pCover, Mvc_Cube_t * pCube, Vec_Int_t * vEdgeLits )
{
-// Dec_Edge_t eNode;
+ Dec_Edge_t eNode;
int iBit, Value;
// create the factored form for each literal
Vec_IntClear( vEdgeLits );
Mvc_CubeForEachBit( pCover, pCube, iBit, Value )
if ( Value )
{
-// eNode = Dec_EdgeCreate( iBit/2, iBit%2 ); // CST
-// Vec_IntPush( vEdgeLits, Dec_EdgeToInt_(eNode) );
- Vec_IntPush( vEdgeLits, iBit );
+ 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 );
@@ -323,7 +322,7 @@ Dec_Edge_t Dec_FactorTrivialTree_rec( Dec_Graph_t * pFForm, Dec_Edge_t * peNodes
***********************************************************************/
Mvc_Cover_t * Dec_ConvertSopToMvc( char * pSop )
{
- Dec_Man_t * pManDec = Abc_FrameReadManDec(Abc_FrameGetGlobalFrame());
+ Dec_Man_t * pManDec = Abc_FrameReadManDec();
Mvc_Manager_t * pMem = pManDec->pMvcMem;
Mvc_Cover_t * pMvc;
Mvc_Cube_t * pMvcCube;
@@ -365,7 +364,8 @@ Mvc_Cover_t * Dec_ConvertSopToMvc( char * pSop )
***********************************************************************/
int Dec_FactorVerify( char * pSop, Dec_Graph_t * pFForm )
{
- DdManager * dd = Abc_FrameReadManDd( Abc_FrameGetGlobalFrame() );
+ extern DdNode * Dec_GraphDeriveBdd( DdManager * dd, Dec_Graph_t * pGraph );
+ DdManager * dd = Abc_FrameReadManDd();
DdNode * bFunc1, * bFunc2;
int RetValue;
bFunc1 = Abc_ConvertSopToBdd( dd, pSop ); Cudd_Ref( bFunc1 );
diff --git a/src/opt/dec/decMan.c b/src/opt/dec/decMan.c
index 1d44d5cb..65857461 100644
--- a/src/opt/dec/decMan.c
+++ b/src/opt/dec/decMan.c
@@ -25,7 +25,7 @@
////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////
-/// FUNCTION DEFITIONS ///
+/// FUNCTION DEFINITIONS ///
////////////////////////////////////////////////////////////////////////
/**Function*************************************************************
diff --git a/src/opt/dec/decPrint.c b/src/opt/dec/decPrint.c
index 6fb20327..2d8f09b3 100644
--- a/src/opt/dec/decPrint.c
+++ b/src/opt/dec/decPrint.c
@@ -29,7 +29,7 @@ static void Dec_GraphPrintUpdatePos( FILE * pFile, int * pPos, int LitSizeMax
static int Dec_GraphPrintOutputName( FILE * pFile, char * pNameOut, int fCompl );
////////////////////////////////////////////////////////////////////////
-/// FUNCTION DEFITIONS ///
+/// FUNCTION DEFINITIONS ///
////////////////////////////////////////////////////////////////////////
/**Function*************************************************************
@@ -101,7 +101,7 @@ void Dec_GraphPrint( FILE * pFile, Dec_Graph_t * pGraph, char * pNamesIn[], char
SeeAlso []
***********************************************************************/
-void Dec_GraphPrint_rec( FILE * pFile, Dec_Graph_t * pGraph, Dec_Node_t * pNode, int fCompl, char * pNamesIn[], int * pPos, int LitSizeMax )
+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);
@@ -165,6 +165,69 @@ void Dec_GraphPrint_rec( FILE * pFile, Dec_Graph_t * pGraph, Dec_Node_t * pNode,
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];
diff --git a/src/opt/dec/decUtil.c b/src/opt/dec/decUtil.c
index 02c3346e..463bc7e2 100644
--- a/src/opt/dec/decUtil.c
+++ b/src/opt/dec/decUtil.c
@@ -24,7 +24,7 @@
////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////
-/// FUNCTION DEFITIONS ///
+/// FUNCTION DEFINITIONS ///
////////////////////////////////////////////////////////////////////////
/**Function*************************************************************
diff --git a/src/opt/fret/fretFlow.c b/src/opt/fret/fretFlow.c
new file mode 100644
index 00000000..a9cef327
--- /dev/null
+++ b/src/opt/fret/fretFlow.c
@@ -0,0 +1,696 @@
+/**CFile****************************************************************
+
+ FileName [fretFlow.c]
+
+ SystemName [ABC: Logic synthesis and verification system.]
+
+ PackageName [Flow-based retiming package.]
+
+ Synopsis [Max-flow computation.]
+
+ Author [Aaron Hurst]
+
+ Affiliation [UC Berkeley]
+
+ Date [Ver. 1.0. Started - January 1, 2008.]
+
+ Revision [$Id: fretFlow.c,v 1.00 2008/01/01 00:00:00 ahurst Exp $]
+
+***********************************************************************/
+
+#include "abc.h"
+#include "vec.h"
+#include "fretime.h"
+
+////////////////////////////////////////////////////////////////////////
+/// DECLARATIONS ///
+////////////////////////////////////////////////////////////////////////
+
+static void dfsfast_e_retreat( Abc_Obj_t *pObj );
+static void dfsfast_r_retreat( Abc_Obj_t *pObj );
+
+#define FDIST(xn, xe, yn, ye) (FDATA(xn)->xe##_dist == (FDATA(yn)->ye##_dist + 1))
+
+////////////////////////////////////////////////////////////////////////
+/// FUNCTION DEFINITIONS ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+ Synopsis [Fast DFS.]
+
+ Description [Uses sink-distance-histogram heuristic. May not find all
+ flow paths: this occurs in a small number of cases where
+ the flow predecessor points to a non-adjacent node and
+ the distance ordering is perturbed.]
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+
+void dfsfast_preorder( Abc_Ntk_t *pNtk ) {
+ Abc_Obj_t *pObj, *pNext;
+ Vec_Ptr_t *vTimeIn, *qn = Vec_PtrAlloc(Abc_NtkObjNum(pNtk));
+ Vec_Int_t *qe = Vec_IntAlloc(Abc_NtkObjNum(pNtk));
+ int i, j, d = 0, end;
+ int qpos = 0;
+
+ // create reverse timing edges for backward traversal
+#if !defined(IGNORE_TIMING)
+ if (pManMR->maxDelay) {
+ Abc_NtkForEachObj( pNtk, pObj, i ) {
+ Vec_PtrForEachEntry( FTIMEEDGES(pObj), pNext, j ) {
+ vTimeIn = FDATA(pNext)->vNodes;
+ if (!vTimeIn) {
+ vTimeIn = FDATA(pNext)->vNodes = Vec_PtrAlloc(2);
+ }
+ Vec_PtrPush(vTimeIn, pObj);
+ }
+ }
+ }
+#endif
+
+ // clear histogram
+ memset(Vec_IntArray(pManMR->vSinkDistHist), 0, sizeof(int)*Vec_IntSize(pManMR->vSinkDistHist));
+
+ // seed queue : latches, PIOs, and blocks
+ Abc_NtkForEachObj( pNtk, pObj, i )
+ if (Abc_ObjIsPo(pObj) ||
+ Abc_ObjIsLatch(pObj) ||
+ (pManMR->fIsForward && FTEST(pObj, BLOCK_OR_CONS) & pManMR->constraintMask)) {
+ Vec_PtrPush(qn, pObj);
+ Vec_IntPush(qe, 'r');
+ FDATA(pObj)->r_dist = 1;
+ } else if (Abc_ObjIsPi(pObj) ||
+ (!pManMR->fIsForward && FTEST(pObj, BLOCK_OR_CONS) & pManMR->constraintMask)) {
+ Vec_PtrPush(qn, pObj);
+ Vec_IntPush(qe, 'e');
+ FDATA(pObj)->e_dist = 1;
+ }
+
+ // until queue is empty...
+ while(qpos < Vec_PtrSize(qn)) {
+ pObj = (Abc_Obj_t *)Vec_PtrEntry(qn, qpos);
+ assert(pObj);
+ end = Vec_IntEntry(qe, qpos);
+ qpos++;
+
+ if (end == 'r') {
+ d = FDATA(pObj)->r_dist;
+
+ // 1. structural edges
+ if (pManMR->fIsForward) {
+ Abc_ObjForEachFanin( pObj, pNext, i )
+ if (!FDATA(pNext)->e_dist) {
+ FDATA(pNext)->e_dist = d+1;
+ Vec_PtrPush(qn, pNext);
+ Vec_IntPush(qe, 'e');
+ }
+ } else
+ Abc_ObjForEachFanout( pObj, pNext, i )
+ if (!FDATA(pNext)->e_dist) {
+ FDATA(pNext)->e_dist = d+1;
+ Vec_PtrPush(qn, pNext);
+ Vec_IntPush(qe, 'e');
+ }
+
+ if (d == 1) continue;
+
+ // 2. reverse edges (forward retiming only)
+ if (pManMR->fIsForward) {
+ Abc_ObjForEachFanout( pObj, pNext, i )
+ if (!FDATA(pNext)->r_dist && !Abc_ObjIsLatch(pNext)) {
+ FDATA(pNext)->r_dist = d+1;
+ Vec_PtrPush(qn, pNext);
+ Vec_IntPush(qe, 'r');
+ }
+
+ // 3. timimg edges (forward retiming only)
+#if !defined(IGNORE_TIMING)
+ if (pManMR->maxDelay && FDATA(pObj)->vNodes)
+ Vec_PtrForEachEntry( FDATA(pObj)->vNodes, pNext, i ) {
+ if (!FDATA(pNext)->r_dist) {
+ FDATA(pNext)->r_dist = d+1;
+ Vec_PtrPush(qn, pNext);
+ Vec_IntPush(qe, 'r');
+ }
+ }
+#endif
+ }
+
+ } else { // if 'e'
+ if (Abc_ObjIsLatch(pObj)) continue;
+
+ d = FDATA(pObj)->e_dist;
+
+ // 1. through node
+ if (!FDATA(pObj)->r_dist) {
+ FDATA(pObj)->r_dist = d+1;
+ Vec_PtrPush(qn, pObj);
+ Vec_IntPush(qe, 'r');
+ }
+
+ // 2. reverse edges (backward retiming only)
+ if (!pManMR->fIsForward) {
+ Abc_ObjForEachFanin( pObj, pNext, i )
+ if (!FDATA(pNext)->e_dist && !Abc_ObjIsLatch(pNext)) {
+ FDATA(pNext)->e_dist = d+1;
+ Vec_PtrPush(qn, pNext);
+ Vec_IntPush(qe, 'e');
+ }
+
+ // 3. timimg edges (backward retiming only)
+#if !defined(IGNORE_TIMING)
+ if (pManMR->maxDelay && FDATA(pObj)->vNodes)
+ Vec_PtrForEachEntry( FDATA(pObj)->vNodes, pNext, i ) {
+ if (!FDATA(pNext)->e_dist) {
+ FDATA(pNext)->e_dist = d+1;
+ Vec_PtrPush(qn, pNext);
+ Vec_IntPush(qe, 'e');
+ }
+ }
+#endif
+ }
+ }
+ }
+
+ // free time edges
+#if !defined(IGNORE_TIMING)
+ if (pManMR->maxDelay) {
+ Abc_NtkForEachObj( pNtk, pObj, i ) {
+ vTimeIn = FDATA(pObj)->vNodes;
+ if (vTimeIn) {
+ Vec_PtrFree(vTimeIn);
+ FDATA(pObj)->vNodes = 0;
+ }
+ }
+ }
+#endif
+
+ Abc_NtkForEachObj( pNtk, pObj, i ) {
+ Vec_IntAddToEntry(pManMR->vSinkDistHist, FDATA(pObj)->r_dist, 1);
+ Vec_IntAddToEntry(pManMR->vSinkDistHist, FDATA(pObj)->e_dist, 1);
+
+#ifdef DEBUG_PREORDER
+ printf("node %d\t: r=%d\te=%d\n", Abc_ObjId(pObj), FDATA(pObj)->r_dist, FDATA(pObj)->e_dist);
+#endif
+ }
+
+ // printf("\t\tpre-ordered (max depth=%d)\n", d+1);
+
+ // deallocate
+ Vec_PtrFree( qn );
+ Vec_IntFree( qe );
+}
+
+int dfsfast_e( Abc_Obj_t *pObj, Abc_Obj_t *pPred ) {
+ int i;
+ Abc_Obj_t *pNext;
+
+ if (pManMR->fSinkDistTerminate) return 0;
+
+ // have we reached the sink?
+ if(FTEST(pObj, BLOCK_OR_CONS) & pManMR->constraintMask ||
+ Abc_ObjIsPi(pObj)) {
+ assert(pPred);
+ assert(!pManMR->fIsForward);
+ return 1;
+ }
+
+ FSET(pObj, VISITED_E);
+
+#ifdef DEBUG_VISITED
+ printf("(%de=%d) ", Abc_ObjId(pObj), FDATA(pObj)->e_dist);
+#endif
+
+ // 1. structural edges
+ if (pManMR->fIsForward)
+ Abc_ObjForEachFanout( pObj, pNext, i ) {
+ if (!FTEST(pNext, VISITED_R) &&
+ FDIST(pObj, e, pNext, r) &&
+ dfsfast_r(pNext, pPred)) {
+#ifdef DEBUG_PRINT_FLOWS
+ printf("o");
+#endif
+ goto found;
+ }
+ }
+ else
+ Abc_ObjForEachFanin( pObj, pNext, i ) {
+ if (!FTEST(pNext, VISITED_R) &&
+ FDIST(pObj, e, pNext, r) &&
+ dfsfast_r(pNext, pPred)) {
+#ifdef DEBUG_PRINT_FLOWS
+ printf("o");
+#endif
+ goto found;
+ }
+ }
+
+ if (Abc_ObjIsLatch(pObj))
+ goto not_found;
+
+ // 2. reverse edges (backward retiming only)
+ if (!pManMR->fIsForward) {
+ Abc_ObjForEachFanout( pObj, pNext, i ) {
+ if (!FTEST(pNext, VISITED_E) &&
+ FDIST(pObj, e, pNext, e) &&
+ dfsfast_e(pNext, pPred)) {
+#ifdef DEBUG_PRINT_FLOWS
+ printf("i");
+#endif
+ goto found;
+ }
+ }
+
+ // 3. timing edges (backward retiming only)
+#if !defined(IGNORE_TIMING)
+ if (pManMR->maxDelay)
+ Vec_PtrForEachEntry( FTIMEEDGES(pObj), pNext, i) {
+ if (!FTEST(pNext, VISITED_E) &&
+ FDIST(pObj, e, pNext, e) &&
+ dfsfast_e(pNext, pPred)) {
+#ifdef DEBUG_PRINT_FLOWS
+ printf("o");
+#endif
+ goto found;
+ }
+ }
+#endif
+ }
+
+ // unwind
+ if (FTEST(pObj, FLOW) &&
+ !FTEST(pObj, VISITED_R) &&
+ FDIST(pObj, e, pObj, r) &&
+ dfsfast_r(pObj, FGETPRED(pObj))) {
+
+ FUNSET(pObj, FLOW);
+ FSETPRED(pObj, NULL);
+#ifdef DEBUG_PRINT_FLOWS
+ printf("u");
+#endif
+ goto found;
+ }
+
+ not_found:
+ FUNSET(pObj, VISITED_E);
+ dfsfast_e_retreat(pObj);
+ return 0;
+
+ found:
+#ifdef DEBUG_PRINT_FLOWS
+ printf("%d ", Abc_ObjId(pObj));
+#endif
+ FUNSET(pObj, VISITED_E);
+ return 1;
+}
+
+int dfsfast_r( Abc_Obj_t *pObj, Abc_Obj_t *pPred ) {
+ int i;
+ Abc_Obj_t *pNext, *pOldPred;
+
+ if (pManMR->fSinkDistTerminate) return 0;
+
+#ifdef DEBUG_VISITED
+ printf("(%dr=%d) ", Abc_ObjId(pObj), FDATA(pObj)->r_dist);
+#endif
+
+ // have we reached the sink?
+ if (Abc_ObjIsLatch(pObj) ||
+ (pManMR->fIsForward && Abc_ObjIsPo(pObj)) ||
+ (pManMR->fIsForward && FTEST(pObj, BLOCK_OR_CONS) & pManMR->constraintMask)) {
+ assert(pPred);
+ return 1;
+ }
+
+ FSET(pObj, VISITED_R);
+
+ if (FTEST(pObj, FLOW)) {
+
+ pOldPred = FGETPRED(pObj);
+ if (pOldPred &&
+ !FTEST(pOldPred, VISITED_E) &&
+ FDIST(pObj, r, pOldPred, e) &&
+ dfsfast_e(pOldPred, pOldPred)) {
+
+ FSETPRED(pObj, pPred);
+
+#ifdef DEBUG_PRINT_FLOWS
+ printf("fr");
+#endif
+ goto found;
+ }
+
+ } else {
+
+ if (!FTEST(pObj, VISITED_E) &&
+ FDIST(pObj, r, pObj, e) &&
+ dfsfast_e(pObj, pObj)) {
+
+ FSET(pObj, FLOW);
+ FSETPRED(pObj, pPred);
+
+#ifdef DEBUG_PRINT_FLOWS
+ printf("f");
+#endif
+ goto found;
+ }
+ }
+
+ // 2. reverse edges (forward retiming only)
+ if (pManMR->fIsForward) {
+ Abc_ObjForEachFanin( pObj, pNext, i ) {
+ if (!FTEST(pNext, VISITED_R) &&
+ FDIST(pObj, r, pNext, r) &&
+ !Abc_ObjIsLatch(pNext) &&
+ dfsfast_r(pNext, pPred)) {
+#ifdef DEBUG_PRINT_FLOWS
+ printf("i");
+#endif
+ goto found;
+ }
+ }
+
+ // 3. timing edges (forward retiming only)
+#if !defined(IGNORE_TIMING)
+ if (pManMR->maxDelay)
+ Vec_PtrForEachEntry( FTIMEEDGES(pObj), pNext, i) {
+ if (!FTEST(pNext, VISITED_R) &&
+ FDIST(pObj, r, pNext, r) &&
+ dfsfast_r(pNext, pPred)) {
+#ifdef DEBUG_PRINT_FLOWS
+ printf("o");
+#endif
+ goto found;
+ }
+ }
+#endif
+ }
+
+ FUNSET(pObj, VISITED_R);
+ dfsfast_r_retreat(pObj);
+ return 0;
+
+ found:
+#ifdef DEBUG_PRINT_FLOWS
+ printf("%d ", Abc_ObjId(pObj));
+#endif
+ FUNSET(pObj, VISITED_R);
+ return 1;
+}
+
+void
+dfsfast_e_retreat(Abc_Obj_t *pObj) {
+ Abc_Obj_t *pNext;
+ int i, *h;
+ int old_dist = FDATA(pObj)->e_dist;
+ int adj_dist, min_dist = MAX_DIST;
+
+ // 1. structural edges
+ if (pManMR->fIsForward)
+ Abc_ObjForEachFanout( pObj, pNext, i ) {
+ adj_dist = FDATA(pNext)->r_dist;
+ if (adj_dist) min_dist = MIN(min_dist, adj_dist);
+ }
+ else
+ Abc_ObjForEachFanin( pObj, pNext, i ) {
+ adj_dist = FDATA(pNext)->r_dist;
+ if (adj_dist) min_dist = MIN(min_dist, adj_dist);
+ }
+
+ if (Abc_ObjIsLatch(pObj)) goto update;
+
+ // 2. through
+ if (FTEST(pObj, FLOW)) {
+ adj_dist = FDATA(pObj)->r_dist;
+ if (adj_dist) min_dist = MIN(min_dist, adj_dist);
+ }
+
+ // 3. reverse edges (backward retiming only)
+ if (!pManMR->fIsForward) {
+ Abc_ObjForEachFanout( pObj, pNext, i ) {
+ adj_dist = FDATA(pNext)->e_dist;
+ if (adj_dist) min_dist = MIN(min_dist, adj_dist);
+ }
+
+ // 4. timing edges (backward retiming only)
+#if !defined(IGNORE_TIMING)
+ if (pManMR->maxDelay)
+ Vec_PtrForEachEntry( FTIMEEDGES(pObj), pNext, i) {
+ adj_dist = FDATA(pNext)->e_dist;
+ if (adj_dist) min_dist = MIN(min_dist, adj_dist);
+ }
+#endif
+ }
+
+ update:
+ ++min_dist;
+ if (min_dist >= MAX_DIST) min_dist = 0;
+ // printf("[%de=%d->%d] ", Abc_ObjId(pObj), old_dist, min_dist+1);
+ FDATA(pObj)->e_dist = min_dist;
+
+ assert(min_dist < Vec_IntSize(pManMR->vSinkDistHist));
+ h = Vec_IntArray(pManMR->vSinkDistHist);
+ h[old_dist]--;
+ h[min_dist]++;
+ if (!h[old_dist]) {
+ pManMR->fSinkDistTerminate = 1;
+ }
+}
+
+void
+dfsfast_r_retreat(Abc_Obj_t *pObj) {
+ Abc_Obj_t *pNext;
+ int i, *h;
+ int old_dist = FDATA(pObj)->r_dist;
+ int adj_dist, min_dist = MAX_DIST;
+
+ // 1. through or pred
+ if (FTEST(pObj, FLOW)) {
+ if (FGETPRED(pObj)) {
+ adj_dist = FDATA(FGETPRED(pObj))->e_dist;
+ if (adj_dist) min_dist = MIN(min_dist, adj_dist);
+ }
+ } else {
+ adj_dist = FDATA(pObj)->e_dist;
+ if (adj_dist) min_dist = MIN(min_dist, adj_dist);
+ }
+
+ // 2. reverse edges (forward retiming only)
+ if (pManMR->fIsForward) {
+ Abc_ObjForEachFanin( pObj, pNext, i )
+ if (!Abc_ObjIsLatch(pNext)) {
+ adj_dist = FDATA(pNext)->r_dist;
+ if (adj_dist) min_dist = MIN(min_dist, adj_dist);
+ }
+
+ // 3. timing edges (forward retiming only)
+#if !defined(IGNORE_TIMING)
+ if (pManMR->maxDelay)
+ Vec_PtrForEachEntry( FTIMEEDGES(pObj), pNext, i) {
+ adj_dist = FDATA(pNext)->r_dist;
+ if (adj_dist) min_dist = MIN(min_dist, adj_dist);
+ }
+#endif
+ }
+
+ ++min_dist;
+ if (min_dist >= MAX_DIST) min_dist = 0;
+ //printf("[%dr=%d->%d] ", Abc_ObjId(pObj), old_dist, min_dist+1);
+ FDATA(pObj)->r_dist = min_dist;
+
+ assert(min_dist < Vec_IntSize(pManMR->vSinkDistHist));
+ h = Vec_IntArray(pManMR->vSinkDistHist);
+ h[old_dist]--;
+ h[min_dist]++;
+ if (!h[old_dist]) {
+ pManMR->fSinkDistTerminate = 1;
+ }
+}
+
+/**Function*************************************************************
+
+ Synopsis [Plain DFS.]
+
+ Description [Does not use sink-distance-histogram heuristic.]
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+
+int dfsplain_e( Abc_Obj_t *pObj, Abc_Obj_t *pPred ) {
+ int i;
+ Abc_Obj_t *pNext;
+
+ if (FTEST(pObj, BLOCK_OR_CONS) & pManMR->constraintMask ||
+ Abc_ObjIsPi(pObj)) {
+ assert(pPred);
+ assert(!pManMR->fIsForward);
+ return 1;
+ }
+
+ FSET(pObj, VISITED_E);
+
+ // printf(" %de\n", Abc_ObjId(pObj));
+
+ // 1. structural edges
+ if (pManMR->fIsForward)
+ Abc_ObjForEachFanout( pObj, pNext, i ) {
+ if (!FTEST(pNext, VISITED_R) &&
+ dfsplain_r(pNext, pPred)) {
+#ifdef DEBUG_PRINT_FLOWS
+ printf("o");
+#endif
+ goto found;
+ }
+ }
+ else
+ Abc_ObjForEachFanin( pObj, pNext, i ) {
+ if (!FTEST(pNext, VISITED_R) &&
+ dfsplain_r(pNext, pPred)) {
+#ifdef DEBUG_PRINT_FLOWS
+ printf("o");
+#endif
+ goto found;
+ }
+ }
+
+ if (Abc_ObjIsLatch(pObj))
+ return 0;
+
+ // 2. reverse edges (backward retiming only)
+ if (!pManMR->fIsForward) {
+ Abc_ObjForEachFanout( pObj, pNext, i ) {
+ if (!FTEST(pNext, VISITED_E) &&
+ dfsplain_e(pNext, pPred)) {
+#ifdef DEBUG_PRINT_FLOWS
+ printf("i");
+#endif
+ goto found;
+ }
+ }
+
+ // 3. timing edges (backward retiming only)
+#if !defined(IGNORE_TIMING)
+ if (pManMR->maxDelay)
+ Vec_PtrForEachEntry( FTIMEEDGES(pObj), pNext, i) {
+ if (!FTEST(pNext, VISITED_E) &&
+ dfsplain_e(pNext, pPred)) {
+#ifdef DEBUG_PRINT_FLOWS
+ printf("o");
+#endif
+ goto found;
+ }
+ }
+#endif
+ }
+
+ // unwind
+ if (FTEST(pObj, FLOW) &&
+ !FTEST(pObj, VISITED_R) &&
+ dfsplain_r(pObj, FGETPRED(pObj))) {
+ FUNSET(pObj, FLOW);
+ FSETPRED(pObj, NULL);
+#ifdef DEBUG_PRINT_FLOWS
+ printf("u");
+#endif
+ goto found;
+ }
+
+ return 0;
+
+ found:
+#ifdef DEBUG_PRINT_FLOWS
+ printf("%d ", Abc_ObjId(pObj));
+#endif
+
+ return 1;
+}
+
+int dfsplain_r( Abc_Obj_t *pObj, Abc_Obj_t *pPred ) {
+ int i;
+ Abc_Obj_t *pNext, *pOldPred;
+
+ // have we reached the sink?
+ if (Abc_ObjIsLatch(pObj) ||
+ (pManMR->fIsForward && Abc_ObjIsPo(pObj)) ||
+ (pManMR->fIsForward && FTEST(pObj, BLOCK_OR_CONS) & pManMR->constraintMask)) {
+ assert(pPred);
+ return 1;
+ }
+
+ FSET(pObj, VISITED_R);
+
+ // printf(" %dr\n", Abc_ObjId(pObj));
+
+ if (FTEST(pObj, FLOW)) {
+
+ pOldPred = FGETPRED(pObj);
+ if (pOldPred &&
+ !FTEST(pOldPred, VISITED_E) &&
+ dfsplain_e(pOldPred, pOldPred)) {
+
+ FSETPRED(pObj, pPred);
+
+#ifdef DEBUG_PRINT_FLOWS
+ printf("fr");
+#endif
+ goto found;
+ }
+
+ } else {
+
+ if (!FTEST(pObj, VISITED_E) &&
+ dfsplain_e(pObj, pObj)) {
+
+ FSET(pObj, FLOW);
+ FSETPRED(pObj, pPred);
+
+#ifdef DEBUG_PRINT_FLOWS
+ printf("f");
+#endif
+ goto found;
+ }
+ }
+
+ // 2. follow reverse edges
+ if (pManMR->fIsForward) { // forward retiming only
+ Abc_ObjForEachFanin( pObj, pNext, i ) {
+ if (!FTEST(pNext, VISITED_R) &&
+ !Abc_ObjIsLatch(pNext) &&
+ dfsplain_r(pNext, pPred)) {
+#ifdef DEBUG_PRINT_FLOWS
+ printf("i");
+#endif
+ goto found;
+ }
+ }
+
+ // 3. timing edges (forward only)
+#if !defined(IGNORE_TIMING)
+ if (pManMR->maxDelay)
+ Vec_PtrForEachEntry( FTIMEEDGES(pObj), pNext, i) {
+ if (!FTEST(pNext, VISITED_R) &&
+ dfsplain_r(pNext, pPred)) {
+#ifdef DEBUG_PRINT_FLOWS
+ printf("o");
+#endif
+ goto found;
+ }
+ }
+#endif
+ }
+
+ return 0;
+
+ found:
+#ifdef DEBUG_PRINT_FLOWS
+ printf("%d ", Abc_ObjId(pObj));
+#endif
+ return 1;
+}
diff --git a/src/opt/fret/fretInit.c b/src/opt/fret/fretInit.c
new file mode 100644
index 00000000..53df7386
--- /dev/null
+++ b/src/opt/fret/fretInit.c
@@ -0,0 +1,762 @@
+/**CFile****************************************************************
+
+ FileName [fretInit.c]
+
+ SystemName [ABC: Logic synthesis and verification system.]
+
+ PackageName [Flow-based retiming package.]
+
+ Synopsis [Initialization for retiming package.]
+
+ Author [Aaron Hurst]
+
+ Affiliation [UC Berkeley]
+
+ Date [Ver. 1.0. Started - January 1, 2008.]
+
+ Revision [$Id: fretInit.c,v 1.00 2008/01/01 00:00:00 ahurst Exp $]
+
+***********************************************************************/
+
+#include "abc.h"
+#include "vec.h"
+#include "io.h"
+#include "fretime.h"
+#include "mio.h"
+
+////////////////////////////////////////////////////////////////////////
+/// FUNCTION PROTOTYPES ///
+////////////////////////////////////////////////////////////////////////
+
+static void Abc_FlowRetime_UpdateForwardInit_rec( Abc_Obj_t * pObj );
+static void Abc_FlowRetime_VerifyBackwardInit( Abc_Ntk_t * pNtk );
+static void Abc_FlowRetime_VerifyBackwardInit_rec( Abc_Obj_t * pObj );
+static Abc_Obj_t* Abc_FlowRetime_UpdateBackwardInit_rec( Abc_Obj_t *pOrigObj,
+ Abc_Obj_t *pUseThisPi, Vec_Ptr_t *vOtherPis,
+ int recurse);
+static void Abc_FlowRetime_SimulateNode( Abc_Obj_t * pObj );
+static void Abc_FlowRetime_SimulateSop( Abc_Obj_t * pObj, char *pSop );
+
+extern void * Abc_FrameReadLibGen();
+extern Abc_Ntk_t * Abc_NtkRestrash( Abc_Ntk_t * pNtk, bool fCleanup );
+
+
+////////////////////////////////////////////////////////////////////////
+/// FUNCTION DEFINITIONS ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+ Synopsis [Updates initial state information.]
+
+ Description [Assumes latch boxes in original position, latches in
+ new positions.]
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void
+Abc_FlowRetime_InitState( Abc_Ntk_t * pNtk ) {
+
+ if (!pManMR->fComputeInitState) return;
+
+ if (pManMR->fIsForward)
+ Abc_FlowRetime_UpdateForwardInit( pNtk );
+ else {
+ Abc_FlowRetime_UpdateBackwardInit( pNtk );
+ }
+}
+
+
+/**Function*************************************************************
+
+ Synopsis [Prints initial state information.]
+
+ Description [Prints distribution of 0,1,and X initial states.]
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void
+Abc_FlowRetime_PrintInitStateInfo( Abc_Ntk_t * pNtk ) {
+ int i, n0=0, n1=0, nDC=0, nOther=0;
+ Abc_Obj_t *pLatch;
+
+ Abc_NtkForEachLatch( pNtk, pLatch, i ) {
+ if (Abc_LatchIsInit0(pLatch)) n0++;
+ else if (Abc_LatchIsInit1(pLatch)) n1++;
+ else if (Abc_LatchIsInitDc(pLatch)) nDC++;
+ else nOther++;
+ }
+
+ printf("\tinitial states {0,1,x} = {%d, %d, %d}", n0, n1, nDC);
+ if (nOther)
+ printf(" + %d UNKNOWN", nOther);
+ printf("\n");
+}
+
+
+/**Function*************************************************************
+
+ Synopsis [Computes initial state after forward retiming.]
+
+ Description [Assumes box outputs in old positions stored w/ init values.
+ Uses three-value simulation to preserve don't cares.]
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Abc_FlowRetime_UpdateForwardInit( Abc_Ntk_t * pNtk ) {
+ Abc_Obj_t *pObj, *pFanin;
+ int i;
+
+ vprintf("\t\tupdating init state\n");
+
+ Abc_NtkIncrementTravId( pNtk );
+
+ Abc_NtkForEachLatch( pNtk, pObj, i ) {
+ pFanin = Abc_ObjFanin0(pObj);
+ Abc_FlowRetime_UpdateForwardInit_rec( pFanin );
+
+ if (FTEST(pFanin, INIT_0))
+ Abc_LatchSetInit0( pObj );
+ else if (FTEST(pFanin, INIT_1))
+ Abc_LatchSetInit1( pObj );
+ else
+ Abc_LatchSetInitDc( pObj );
+ }
+}
+
+void Abc_FlowRetime_UpdateForwardInit_rec( Abc_Obj_t * pObj ) {
+ Abc_Obj_t *pNext;
+ int i;
+
+ assert(!Abc_ObjIsPi(pObj)); // should never reach the inputs
+
+ if (Abc_ObjIsBo(pObj)) return;
+
+ // visited?
+ if (Abc_NodeIsTravIdCurrent(pObj)) return;
+ Abc_NodeSetTravIdCurrent(pObj);
+
+ Abc_ObjForEachFanin( pObj, pNext, i ) {
+ Abc_FlowRetime_UpdateForwardInit_rec( pNext );
+ }
+
+ Abc_FlowRetime_SimulateNode( pObj );
+}
+
+
+/**Function*************************************************************
+
+ Synopsis [Sets initial value flags.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+static inline void Abc_FlowRetime_SetInitValue( Abc_Obj_t * pObj,
+ int val, int dc ) {
+
+ // store init value
+ FUNSET(pObj, INIT_CARE);
+ if (!dc){
+ if (val) {
+ FSET(pObj, INIT_1);
+ } else {
+ FSET(pObj, INIT_0);
+ }
+ }
+}
+
+
+/**Function*************************************************************
+
+ Synopsis [Propogates initial state through a logic node.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Abc_FlowRetime_SimulateNode( Abc_Obj_t * pObj ) {
+ Abc_Ntk_t *pNtk = Abc_ObjNtk(pObj);
+ Abc_Obj_t * pFanin;
+ int i, rAnd, rVar, dcAnd, dcVar;
+ DdManager * dd = pNtk->pManFunc;
+ DdNode *pBdd = pObj->pData, *pVar;
+
+ assert(!Abc_ObjIsLatch(pObj));
+
+ // (i) constant nodes
+ if (Abc_NtkHasAig(pNtk) && Abc_AigNodeIsConst(pObj)) {
+ Abc_FlowRetime_SetInitValue(pObj, 1, 0);
+ return;
+ }
+ if (!Abc_NtkIsStrash( pNtk ) && Abc_ObjIsNode(pObj)) {
+ if (Abc_NodeIsConst0(pObj)) {
+ Abc_FlowRetime_SetInitValue(pObj, 0, 0);
+ return;
+ } else if (Abc_NodeIsConst1(pObj)) {
+ Abc_FlowRetime_SetInitValue(pObj, 1, 0);
+ return;
+ }
+ }
+
+ // (ii) terminal nodes
+ if (!Abc_ObjIsNode(pObj)) {
+ pFanin = Abc_ObjFanin0(pObj);
+
+ Abc_FlowRetime_SetInitValue(pObj,
+ (FTEST(pFanin, INIT_1) ? 1 : 0) ^ pObj->fCompl0,
+ !FTEST(pFanin, INIT_CARE));
+ return;
+ }
+
+ // (iii) logic nodes
+
+ // ------ SOP network
+ if ( Abc_NtkHasSop( pNtk )) {
+ Abc_FlowRetime_SimulateSop( pObj, (char *)Abc_ObjData(pObj) );
+ return;
+ }
+
+ // ------ BDD network
+ else if ( Abc_NtkHasBdd( pNtk )) {
+ assert(dd);
+ assert(pBdd);
+
+ // cofactor for 0,1 inputs
+ // do nothing for X values
+ Abc_ObjForEachFanin(pObj, pFanin, i) {
+ pVar = Cudd_bddIthVar( dd, i );
+ if (FTEST(pFanin, INIT_CARE)) {
+ if (FTEST(pFanin, INIT_0))
+ pBdd = Cudd_Cofactor( dd, pBdd, Cudd_Not(pVar) );
+ else
+ pBdd = Cudd_Cofactor( dd, pBdd, pVar );
+ }
+ }
+
+ // if function has not been reduced to
+ // a constant, propagate an X
+ rVar = (pBdd == Cudd_ReadOne(dd));
+ dcVar = !Cudd_IsConstant(pBdd);
+
+ Abc_FlowRetime_SetInitValue(pObj, rVar, dcVar);
+ return;
+ }
+
+ // ------ AIG network
+ else if ( Abc_NtkHasAig( pNtk )) {
+
+ assert(Abc_AigNodeIsAnd(pObj));
+ dcAnd = 0, rAnd = 1;
+
+ pFanin = Abc_ObjFanin0(pObj);
+ dcAnd |= FTEST(pFanin, INIT_CARE) ? 0 : 1;
+ rVar = FTEST(pFanin, INIT_0) ? 0 : 1;
+ if (pObj->fCompl0) rVar ^= 1; // complimented?
+ rAnd &= rVar;
+
+ pFanin = Abc_ObjFanin1(pObj);
+ dcAnd |= FTEST(pFanin, INIT_CARE) ? 0 : 1;
+ rVar = FTEST(pFanin, INIT_0) ? 0 : 1;
+ if (pObj->fCompl1) rVar ^= 1; // complimented?
+ rAnd &= rVar;
+
+ if (!rAnd) dcAnd = 0; /* controlling value */
+
+ Abc_FlowRetime_SetInitValue(pObj, rAnd, dcAnd);
+ return;
+ }
+
+ // ------ MAPPED network
+ else if ( Abc_NtkHasMapping( pNtk )) {
+ Abc_FlowRetime_SimulateSop( pObj, (char *)Mio_GateReadSop(pObj->pData) );
+ return;
+ }
+
+ assert(0);
+}
+
+
+/**Function*************************************************************
+
+ Synopsis [Propogates initial state through a SOP node.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Abc_FlowRetime_SimulateSop( Abc_Obj_t * pObj, char *pSop ) {
+ Abc_Obj_t * pFanin;
+ char *pCube;
+ int i, j, rAnd, rOr, rVar, dcAnd, dcOr, v;
+
+ assert( pSop && !Abc_SopIsExorType(pSop) );
+
+ rOr = 0, dcOr = 0;
+
+ i = Abc_SopGetVarNum(pSop);
+ Abc_SopForEachCube( pSop, i, pCube ) {
+ rAnd = 1, dcAnd = 0;
+ Abc_CubeForEachVar( pCube, v, j ) {
+ pFanin = Abc_ObjFanin(pObj, j);
+ if ( v == '0' )
+ rVar = FTEST(pFanin, INIT_0) ? 1 : 0;
+ else if ( v == '1' )
+ rVar = FTEST(pFanin, INIT_1) ? 1 : 0;
+ else
+ continue;
+
+ if (FTEST(pFanin, INIT_CARE))
+ rAnd &= rVar;
+ else
+ dcAnd = 1;
+ }
+ if (!rAnd) dcAnd = 0; /* controlling value */
+ if (dcAnd)
+ dcOr = 1;
+ else
+ rOr |= rAnd;
+ }
+ if (rOr) dcOr = 0; /* controlling value */
+
+ // complement the result if necessary
+ if ( !Abc_SopGetPhase(pSop) )
+ rOr ^= 1;
+
+ Abc_FlowRetime_SetInitValue(pObj, rOr, dcOr);
+}
+
+/**Function*************************************************************
+
+ Synopsis [Sets up backward initial state computation.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Abc_FlowRetime_SetupBackwardInit( Abc_Ntk_t * pNtk ) {
+ Abc_Obj_t *pLatch, *pObj, *pPi;
+ int i;
+ Vec_Ptr_t *vObj = Vec_PtrAlloc(100);
+
+ // create the network used for the initial state computation
+ if (Abc_NtkHasMapping(pNtk))
+ pManMR->pInitNtk = Abc_NtkAlloc( pNtk->ntkType, ABC_FUNC_SOP, 1 );
+ else
+ pManMR->pInitNtk = Abc_NtkAlloc( pNtk->ntkType, pNtk->ntkFunc, 1 );
+
+ // mitre inputs
+ Abc_NtkForEachLatch( pNtk, pLatch, i ) {
+ // map latch to initial state network
+ pPi = Abc_NtkCreatePi( pManMR->pInitNtk );
+
+ // has initial state requirement?
+ if (Abc_LatchIsInit0(pLatch)) {
+
+ if (Abc_NtkHasAig(pNtk))
+ pObj = Abc_ObjNot( pPi );
+ else
+ pObj = Abc_NtkCreateNodeInv( pManMR->pInitNtk, pPi );
+
+ Vec_PtrPush(vObj, pObj);
+ }
+ else if (Abc_LatchIsInit1(pLatch)) {
+ Vec_PtrPush(vObj, pPi);
+ }
+
+ Abc_ObjSetData( pLatch, pPi ); // if not verifying init state
+ // FDATA(pLatch)->pInitObj = pPi; // if verifying init state
+ }
+
+ // are there any nodes not DC?
+ if (!Vec_PtrSize(vObj)) {
+ pManMR->fSolutionIsDc = 1;
+ return;
+ } else
+ pManMR->fSolutionIsDc = 0;
+
+ // mitre output
+ if (Abc_NtkHasAig(pNtk)) {
+ // create AND-by-AND
+ pObj = Vec_PtrPop( vObj );
+ while( Vec_PtrSize(vObj) )
+ pObj = Abc_AigAnd( pManMR->pInitNtk->pManFunc, pObj, Vec_PtrPop( vObj ) );
+ } else
+ // create n-input AND gate
+ pObj = Abc_NtkCreateNodeAnd( pManMR->pInitNtk, vObj );
+
+ Abc_ObjAddFanin( Abc_NtkCreatePo( pManMR->pInitNtk ), pObj );
+
+ Vec_PtrFree( vObj );
+}
+
+
+/**Function*************************************************************
+
+ Synopsis [Solves backward initial state computation.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Abc_FlowRetime_SolveBackwardInit( Abc_Ntk_t * pNtk ) {
+ int i;
+ Abc_Obj_t *pObj, *pInitObj;
+ Vec_Ptr_t *vDelete = Vec_PtrAlloc(0);
+ int result;
+
+ assert(pManMR->pInitNtk);
+
+ // is the solution entirely DC's?
+ if (pManMR->fSolutionIsDc) {
+ Abc_NtkDelete(pManMR->pInitNtk);
+ Vec_PtrFree(vDelete);
+ Abc_NtkForEachLatch( pNtk, pObj, i ) Abc_LatchSetInitDc( pObj );
+ vprintf("\tno init state computation: all-don't-care solution\n");
+ return 1;
+ }
+
+ // check that network is combinational
+ // mark superfluous BI nodes for deletion
+ Abc_NtkForEachObj( pManMR->pInitNtk, pObj, i ) {
+ assert(!Abc_ObjIsLatch(pObj));
+ assert(!Abc_ObjIsBo(pObj));
+
+ if (Abc_ObjIsBi(pObj)) {
+ Abc_ObjBetterTransferFanout( pObj, Abc_ObjFanin0(pObj), Abc_ObjFaninC0(pObj) );
+ Vec_PtrPush( vDelete, pObj );
+ }
+ }
+
+ // delete superfluous nodes
+ while(Vec_PtrSize( vDelete )) {
+ pObj = (Abc_Obj_t *)Vec_PtrPop( vDelete );
+ Abc_NtkDeleteObj( pObj );
+ }
+ Vec_PtrFree(vDelete);
+
+ // do some final cleanup on the network
+ Abc_NtkAddDummyPoNames(pManMR->pInitNtk);
+ Abc_NtkAddDummyPiNames(pManMR->pInitNtk);
+ if (Abc_NtkIsLogic(pManMR->pInitNtk))
+ Abc_NtkCleanup(pManMR->pInitNtk, 0);
+ else if (Abc_NtkIsStrash(pManMR->pInitNtk)) {
+ Abc_NtkReassignIds(pManMR->pInitNtk);
+ }
+
+ vprintf("\tsolving for init state (%d nodes)... ", Abc_NtkObjNum(pManMR->pInitNtk));
+ fflush(stdout);
+
+ // convert SOPs to BDD
+ if (Abc_NtkHasSop(pManMR->pInitNtk))
+ Abc_NtkSopToBdd( pManMR->pInitNtk );
+
+ // solve
+ result = Abc_NtkMiterSat( pManMR->pInitNtk, (sint64)500000, (sint64)50000000, 0, NULL, NULL );
+
+ if (!result) {
+ vprintf("SUCCESS\n");
+ } else {
+ vprintf("FAILURE\n");
+ printf("WARNING: no equivalent init state. setting all initial states to don't-cares\n");
+ Abc_NtkForEachLatch( pNtk, pObj, i ) Abc_LatchSetInitDc( pObj );
+ Abc_NtkDelete(pManMR->pInitNtk);
+ return 0;
+ }
+
+ // clear initial values, associate PIs to latches
+ Abc_NtkForEachPi( pManMR->pInitNtk, pInitObj, i ) Abc_ObjSetCopy( pInitObj, NULL );
+ Abc_NtkForEachLatch( pNtk, pObj, i ) {
+ pInitObj = Abc_ObjData( pObj );
+ assert( Abc_ObjIsPi( pInitObj ));
+ Abc_ObjSetCopy( pInitObj, pObj );
+ Abc_LatchSetInitNone( pObj );
+ }
+
+ // copy solution from PIs to latches
+ assert(pManMR->pInitNtk->pModel);
+ Abc_NtkForEachPi( pManMR->pInitNtk, pInitObj, i ) {
+ if ((pObj = Abc_ObjCopy( pInitObj ))) {
+ if ( pManMR->pInitNtk->pModel[i] )
+ Abc_LatchSetInit1( pObj );
+ else
+ Abc_LatchSetInit0( pObj );
+ }
+ }
+
+#if defined(DEBUG_CHECK)
+ // check that all latches have initial state
+ Abc_NtkForEachLatch( pNtk, pObj, i ) assert( !Abc_LatchIsInitNone( pObj ) );
+#endif
+
+ // deallocate
+ Abc_NtkDelete( pManMR->pInitNtk );
+
+ return 1;
+}
+
+
+/**Function*************************************************************
+
+ Synopsis [Updates backward initial state computation problem.]
+
+ Description [Assumes box outputs in old positions stored w/ init values.]
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Abc_FlowRetime_UpdateBackwardInit( Abc_Ntk_t * pNtk ) {
+ Abc_Obj_t *pOrigObj, *pInitObj;
+ Vec_Ptr_t *vBo = Vec_PtrAlloc(100);
+ Vec_Ptr_t *vOldPis = Vec_PtrAlloc(100);
+ int i;
+
+ // remove PIs from network (from BOs)
+ Abc_NtkForEachObj( pNtk, pOrigObj, i )
+ if (Abc_ObjIsBo(pOrigObj)) {
+ pInitObj = FDATA(pOrigObj)->pInitObj;
+ assert(Abc_ObjIsPi(pInitObj));
+ Vec_PtrPush(vBo, pOrigObj);
+
+ Abc_FlowRetime_UpdateBackwardInit_rec( Abc_ObjFanin0( pOrigObj ), pInitObj, vOldPis, 0 );
+ }
+
+ // add PIs to network (at latches)
+ Abc_NtkForEachLatch( pNtk, pOrigObj, i )
+ Abc_FlowRetime_UpdateBackwardInit_rec( pOrigObj, NULL, vOldPis, 0 );
+
+ // connect nodes in init state network
+ Vec_PtrForEachEntry( vBo, pOrigObj, i )
+ Abc_FlowRetime_UpdateBackwardInit_rec( Abc_ObjFanin0( pOrigObj ), NULL, NULL, 1 );
+
+ // clear flags
+ Abc_NtkForEachObj( pNtk, pOrigObj, i )
+ pOrigObj->fMarkA = pOrigObj->fMarkB = 0;
+
+ // deallocate
+ Vec_PtrFree( vBo );
+ Vec_PtrFree( vOldPis );
+}
+
+
+/**Function*************************************************************
+
+ Synopsis [Updates backward initial state computation problem.]
+
+ Description [Creates a duplicate node in the initial state network
+ corresponding to a node in the original circuit. If
+ fRecurse is set, the procedure recurses on and connects
+ the new node to its fan-ins. A latch in the original
+ circuit corresponds to a PI in the initial state network.
+ An existing PI may be supplied by pUseThisPi, and if the
+ node is a latch, it will be used; otherwise the PI is
+ saved in the list vOtherPis and subsequently used for
+ another latch.]
+
+ SideEffects [Nodes that have a corresponding initial state node
+ are marked with fMarkA. Nodes that have been fully
+ connected in the initial state network are marked with
+ fMarkB.]
+
+ SeeAlso []
+
+***********************************************************************/
+Abc_Obj_t* Abc_FlowRetime_UpdateBackwardInit_rec( Abc_Obj_t *pOrigObj,
+ Abc_Obj_t *pUseThisPi, Vec_Ptr_t *vOtherPis,
+ int fRecurse) {
+ Abc_Obj_t *pInitObj, *pOrigFanin, *pInitFanin;
+ void *pData;
+ int i;
+ Abc_Ntk_t *pNtk = Abc_ObjNtk( pOrigObj );
+
+ // should never reach primary IOs
+ assert(!Abc_ObjIsPi(pOrigObj));
+ assert(!Abc_ObjIsPo(pOrigObj));
+
+ // if fanin is latch, it becomes a primary input
+ if (Abc_ObjIsLatch( pOrigObj )) {
+ if (pOrigObj->fMarkA) return FDATA(pOrigObj)->pInitObj;
+
+ assert(vOtherPis);
+
+ if (pUseThisPi) {
+ // reuse curent PI
+ pInitObj = pUseThisPi; }
+ else {
+ // reuse previous PI
+ pInitObj = (Abc_Obj_t*)Vec_PtrPop(vOtherPis);
+ }
+
+ // remember link from original node to init ntk
+ Abc_ObjSetData( pOrigObj, pInitObj );
+
+ pOrigObj->fMarkA = 1;
+ return (FDATA(pOrigObj)->pInitObj = pInitObj);
+ }
+
+ // does an init node already exist?
+ if(!pOrigObj->fMarkA) {
+
+ if (Abc_NtkHasMapping( pNtk )) {
+ if (!pOrigObj->pData) {
+ // assume terminal...
+ assert(Abc_ObjFaninNum(pOrigObj) == 1);
+ pInitObj = Abc_NtkCreateNodeBuf( pManMR->pInitNtk, NULL );
+ } else {
+ pInitObj = Abc_NtkCreateObj( pManMR->pInitNtk, Abc_ObjType(pOrigObj) );
+ pData = Mio_GateReadSop(pOrigObj->pData);
+ assert( Abc_SopGetVarNum(pData) == Abc_ObjFaninNum(pOrigObj) );
+
+ pInitObj->pData = Abc_SopRegister( pManMR->pInitNtk->pManFunc, pData );
+ }
+ } else {
+ pData = Abc_ObjCopy( pOrigObj ); // save ptr to flow data
+ if (Abc_NtkIsStrash( pNtk ) && Abc_AigNodeIsConst( pOrigObj ))
+ pInitObj = Abc_AigConst1( pManMR->pInitNtk );
+ else
+ pInitObj = Abc_NtkDupObj( pManMR->pInitNtk, pOrigObj, 0 );
+ Abc_ObjSetCopy( pOrigObj, pData ); // restore ptr to flow data
+
+ // copy complementation
+ pInitObj->fCompl0 = pOrigObj->fCompl0;
+ pInitObj->fCompl1 = pOrigObj->fCompl1;
+ pInitObj->fPhase = pOrigObj->fPhase;
+ }
+
+ // if we didn't use given PI, immediately transfer fanouts
+ // and add to list for later reuse
+ if (pUseThisPi) {
+ Abc_ObjBetterTransferFanout( pUseThisPi, pInitObj, 0 );
+ Vec_PtrPush( vOtherPis, pUseThisPi );
+ }
+
+ pOrigObj->fMarkA = 1;
+ FDATA(pOrigObj)->pInitObj = pInitObj;
+ } else {
+ pInitObj = FDATA(pOrigObj)->pInitObj;
+ }
+
+ // have we already connected this object?
+ if (fRecurse && !pOrigObj->fMarkB) {
+
+ // create and/or connect fanins
+ Abc_ObjForEachFanin( pOrigObj, pOrigFanin, i ) {
+ pInitFanin = Abc_FlowRetime_UpdateBackwardInit_rec( pOrigFanin, NULL, NULL, fRecurse );
+ Abc_ObjAddFanin( pInitObj, pInitFanin );
+ }
+
+ pOrigObj->fMarkB = 1;
+ }
+
+ return pInitObj;
+}
+
+
+/**Function*************************************************************
+
+ Synopsis [Verifies backward init state computation.]
+
+ Description [This procedure requires the BOs to store the original
+ latch values and the latches to store the new values:
+ both in the INIT_0 and INIT_1 flags in the Flow_Data
+ structure. (This is not currently the case in the rest
+ of the code.) Also, can not verify backward state
+ computations that span multiple combinational frames.]
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Abc_FlowRetime_VerifyBackwardInit( Abc_Ntk_t * pNtk ) {
+ Abc_Obj_t *pObj, *pFanin;
+ int i;
+
+ vprintf("\t\tupdating init state\n");
+
+ Abc_NtkIncrementTravId( pNtk );
+
+ Abc_NtkForEachObj( pNtk, pObj, i )
+ if (Abc_ObjIsBo( pObj )) {
+ pFanin = Abc_ObjFanin0(pObj);
+ Abc_FlowRetime_VerifyBackwardInit_rec( pFanin );
+
+ if (FTEST(pObj, INIT_CARE)) {
+ if(FTEST(pObj, INIT_CARE) != FTEST(pFanin, INIT_CARE)) {
+ printf("ERROR: expected val=%d care=%d and got val=%d care=%d\n",
+ FTEST(pObj, INIT_1)?1:0, FTEST(pObj, INIT_CARE)?1:0,
+ FTEST(pFanin, INIT_1)?1:0, FTEST(pFanin, INIT_CARE)?1:0 );
+
+ }
+ }
+ }
+}
+
+void Abc_FlowRetime_VerifyBackwardInit_rec( Abc_Obj_t * pObj ) {
+ Abc_Obj_t *pNext;
+ int i;
+
+ assert(!Abc_ObjIsBo(pObj)); // should never reach the inputs
+ assert(!Abc_ObjIsPi(pObj)); // should never reach the inputs
+
+ // visited?
+ if (Abc_NodeIsTravIdCurrent(pObj)) return;
+ Abc_NodeSetTravIdCurrent(pObj);
+
+ if (Abc_ObjIsLatch(pObj)) {
+ FUNSET(pObj, INIT_CARE);
+ if (Abc_LatchIsInit0(pObj))
+ FSET(pObj, INIT_0);
+ else if (Abc_LatchIsInit1(pObj))
+ FSET(pObj, INIT_1);
+ return;
+ }
+
+ Abc_ObjForEachFanin( pObj, pNext, i ) {
+ Abc_FlowRetime_VerifyBackwardInit_rec( pNext );
+ }
+
+ Abc_FlowRetime_SimulateNode( pObj );
+}
+
+
+/**Function*************************************************************
+
+ Synopsis [Constrains backward retiming for initializability.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Abc_FlowRetime_ConstrainInit( ) {
+ // unimplemented
+}
diff --git a/src/opt/fret/fretMain.c b/src/opt/fret/fretMain.c
new file mode 100644
index 00000000..780c1f6f
--- /dev/null
+++ b/src/opt/fret/fretMain.c
@@ -0,0 +1,1059 @@
+/**CFile****************************************************************
+
+ FileName [fretMain.c]
+
+ SystemName [ABC: Logic synthesis and verification system.]
+
+ PackageName [Flow-based retiming package.]
+
+ Synopsis [Main file for retiming package.]
+
+ Author [Aaron Hurst]
+
+ Affiliation [UC Berkeley]
+
+ Date [Ver. 1.0. Started - January 1, 2008.]
+
+ Revision [$Id: fretMain.c,v 1.00 2008/01/01 00:00:00 ahurst Exp $]
+
+***********************************************************************/
+
+#include "abc.h"
+#include "vec.h"
+#include "fretime.h"
+
+////////////////////////////////////////////////////////////////////////
+/// DECLARATIONS ///
+////////////////////////////////////////////////////////////////////////
+
+static void Abc_FlowRetime_AddDummyFanin( Abc_Obj_t * pObj );
+
+static void Abc_FlowRetime_MainLoop( );
+
+static void Abc_FlowRetime_MarkBlocks( Abc_Ntk_t * pNtk );
+static void Abc_FlowRetime_MarkReachable_rec( Abc_Obj_t * pObj, char end );
+static int Abc_FlowRetime_ImplementCut( Abc_Ntk_t * pNtk );
+static void Abc_FlowRetime_RemoveLatchBubbles( Abc_Obj_t * pLatch );
+
+static void Abc_FlowRetime_VerifyPathLatencies( Abc_Ntk_t * pNtk );
+static int Abc_FlowRetime_VerifyPathLatencies_rec( Abc_Obj_t * pObj, int markD );
+
+extern void Abc_NtkMarkCone_rec( Abc_Obj_t * pObj, int fForward );
+extern Abc_Ntk_t * Abc_NtkRestrash( Abc_Ntk_t * pNtk, bool fCleanup );
+
+void
+print_node3(Abc_Obj_t *pObj);
+
+MinRegMan_t *pManMR;
+
+int fPathError = 0;
+
+////////////////////////////////////////////////////////////////////////
+/// FUNCTION DEFINITIONS ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+ Synopsis [Performs minimum-register retiming.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Abc_Ntk_t *
+Abc_FlowRetime_MinReg( Abc_Ntk_t * pNtk, int fVerbose, int fComputeInitState,
+ int fForwardOnly, int fBackwardOnly, int nMaxIters,
+ int maxDelay, int fFastButConservative ) {
+
+ int i;
+ Abc_Obj_t *pObj, *pNext;
+
+ // create manager
+ pManMR = ALLOC( MinRegMan_t, 1 );
+
+ pManMR->pNtk = pNtk;
+ pManMR->fVerbose = fVerbose;
+ pManMR->fComputeInitState = fComputeInitState;
+ pManMR->fGuaranteeInitState = 0;
+ pManMR->fForwardOnly = fForwardOnly;
+ pManMR->fBackwardOnly = fBackwardOnly;
+ pManMR->nMaxIters = nMaxIters;
+ pManMR->maxDelay = maxDelay;
+ pManMR->fComputeInitState = fComputeInitState;
+ pManMR->fConservTimingOnly = fFastButConservative;
+ pManMR->vNodes = Vec_PtrAlloc(100);
+
+ vprintf("Flow-based minimum-register retiming...\n");
+
+ if (!Abc_NtkHasOnlyLatchBoxes(pNtk)) {
+ printf("\tERROR: Can not retime with black/white boxes\n");
+ return pNtk;
+ }
+
+ if (maxDelay) {
+ vprintf("\tmax delay constraint = %d\n", maxDelay);
+ if (maxDelay < (i = Abc_NtkLevel(pNtk))) {
+ printf("ERROR: max delay constraint must be > current max delay (%d)\n", i);
+ return pNtk;
+ }
+ }
+
+ // print info about type of network
+ vprintf("\tnetlist type = ");
+ if (Abc_NtkIsNetlist( pNtk )) { vprintf("netlist/"); }
+ else if (Abc_NtkIsLogic( pNtk )) { vprintf("logic/"); }
+ else if (Abc_NtkIsStrash( pNtk )) { vprintf("strash/"); }
+ else { vprintf("***unknown***/"); }
+ if (Abc_NtkHasSop( pNtk )) { vprintf("sop\n"); }
+ else if (Abc_NtkHasBdd( pNtk )) { vprintf("bdd\n"); }
+ else if (Abc_NtkHasAig( pNtk )) { vprintf("aig\n"); }
+ else if (Abc_NtkHasMapping( pNtk )) { vprintf("mapped\n"); }
+ else { vprintf("***unknown***\n"); }
+
+ vprintf("\tinitial reg count = %d\n", Abc_NtkLatchNum(pNtk));
+ vprintf("\tinitial levels = %d\n", Abc_NtkLevel(pNtk));
+
+ // remove bubbles from latch boxes
+ if (pManMR->fVerbose) Abc_FlowRetime_PrintInitStateInfo(pNtk);
+ vprintf("\tpushing bubbles out of latch boxes\n");
+ Abc_NtkForEachLatch( pNtk, pObj, i )
+ Abc_FlowRetime_RemoveLatchBubbles(pObj);
+ if (pManMR->fVerbose) Abc_FlowRetime_PrintInitStateInfo(pNtk);
+
+ // check for box inputs/outputs
+ Abc_NtkForEachLatch( pNtk, pObj, i ) {
+ assert(Abc_ObjFaninNum(pObj) == 1);
+ assert(Abc_ObjFanoutNum(pObj) == 1);
+ assert(!Abc_ObjFaninC0(pObj));
+
+ pNext = Abc_ObjFanin0(pObj);
+ assert(Abc_ObjIsBi(pNext));
+ assert(Abc_ObjFaninNum(pNext) <= 1);
+ if(Abc_ObjFaninNum(pNext) == 0) // every Bi should have a fanin
+ Abc_FlowRetime_AddDummyFanin( pNext );
+
+ pNext = Abc_ObjFanout0(pObj);
+ assert(Abc_ObjIsBo(pNext));
+ assert(Abc_ObjFaninNum(pNext) == 1);
+ assert(!Abc_ObjFaninC0(pNext));
+ }
+
+ pManMR->nLatches = Abc_NtkLatchNum( pNtk );
+ pManMR->nNodes = Abc_NtkObjNumMax( pNtk )+1;
+
+ // build histogram
+ pManMR->vSinkDistHist = Vec_IntStart( pManMR->nNodes*2+10 );
+
+ // initialize timing
+ if (maxDelay)
+ Abc_FlowRetime_InitTiming( pNtk );
+
+ // create Flow_Data structure
+ pManMR->pDataArray = ALLOC( Flow_Data_t, pManMR->nNodes );
+ Abc_FlowRetime_ClearFlows( 1 );
+ Abc_NtkForEachObj( pNtk, pObj, i )
+ Abc_ObjSetCopy( pObj, (void *)(&pManMR->pDataArray[i]) );
+
+ // main loop!
+ Abc_FlowRetime_MainLoop();
+
+ // clear pCopy field
+ Abc_NtkForEachObj( pNtk, pObj, i ) {
+ Abc_ObjSetCopy( pObj, NULL );
+
+ // if not computing init state, set all latches to DC
+ if (!fComputeInitState && Abc_ObjIsLatch(pObj))
+ Abc_LatchSetInitDc(pObj);
+ }
+
+ // deallocate space
+ FREE( pManMR->pDataArray );
+ if (pManMR->vNodes) Vec_PtrFree(pManMR->vNodes);
+ if (pManMR->vSinkDistHist) Vec_IntFree(pManMR->vSinkDistHist);
+ if (pManMR->maxDelay) Abc_FlowRetime_FreeTiming( pNtk );
+
+ // restrash if necessary
+ if (Abc_NtkIsStrash(pNtk)) {
+ Abc_NtkReassignIds( pNtk );
+ pNtk = Abc_NtkRestrash( pNtk, 1 );
+ }
+
+ vprintf("\tfinal reg count = %d\n", Abc_NtkLatchNum(pNtk));
+ vprintf("\tfinal levels = %d\n", Abc_NtkLevel(pNtk));
+
+#if defined(DEBUG_CHECK)
+ Abc_NtkDoCheck( pNtk );
+#endif
+
+ // free manager
+ FREE( pManMR );
+
+ return pNtk;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Main loop.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void
+Abc_FlowRetime_MainLoop( ) {
+ Abc_Ntk_t *pNtk = pManMR->pNtk;
+ // Abc_Obj_t *pObj; int i;
+ int last, flow = 0, cut;
+
+ // (i) forward retiming loop
+ pManMR->fIsForward = 1;
+ pManMR->iteration = 0;
+
+ if (!pManMR->fBackwardOnly) do {
+ if (pManMR->iteration == pManMR->nMaxIters) break;
+ pManMR->subIteration = 0;
+
+ vprintf("\tforward iteration %d\n", pManMR->iteration);
+ last = Abc_NtkLatchNum( pNtk );
+
+ Abc_FlowRetime_MarkBlocks( pNtk );
+
+ if (pManMR->maxDelay) {
+ // timing-constrained loop
+ Abc_FlowRetime_ConstrainConserv( pNtk );
+ while(Abc_FlowRetime_RefineConstraints( )) {
+ pManMR->subIteration++;
+ Abc_FlowRetime_ClearFlows( 0 );
+ }
+ } else {
+ flow = Abc_FlowRetime_PushFlows( pNtk, 1 );
+ }
+
+ cut = Abc_FlowRetime_ImplementCut( pNtk );
+
+ vprintf("\t\tlevels = %d\n", Abc_NtkLevel(pNtk));
+
+#if 0
+ Abc_NtkForEachObj( pNtk, pObj, i ) pObj->Level = 0;
+
+ Abc_NtkLevel(pNtk);
+ Abc_NtkForEachObj( pNtk, pObj, i )
+ if (pObj->Level > pManMR->maxDelay) {
+ print_node( pObj );
+ Vec_PtrForEachEntry( FTIMEEDGES(pObj), p2,j ) {
+ printf(":%d ", p2->Id);
+ }
+ }
+ Abc_NtkLevelReverse(pNtk);
+ Abc_NtkForEachObj( pNtk, pObj, i )
+ if (pObj->Level > pManMR->maxDelay) {
+ print_node( pObj );
+ }
+#endif
+
+ Abc_FlowRetime_ClearFlows( 1 );
+
+ pManMR->iteration++;
+ } while( cut != last );
+
+ // print info about initial states
+ if (pManMR->fComputeInitState && pManMR->fVerbose)
+ Abc_FlowRetime_PrintInitStateInfo( pNtk );
+
+ // (ii) backward retiming loop
+ pManMR->fIsForward = 0;
+ pManMR->iteration = 0;
+
+ if (!pManMR->fForwardOnly) do {
+ // initializability loop
+
+ if (pManMR->fComputeInitState) {
+ Abc_FlowRetime_SetupBackwardInit( pNtk );
+ }
+
+ do {
+ if (pManMR->iteration == pManMR->nMaxIters) break;
+ pManMR->subIteration = 0;
+
+ vprintf("\tbackward iteration %d\n", pManMR->iteration);
+ last = Abc_NtkLatchNum( pNtk );
+
+ Abc_FlowRetime_MarkBlocks( pNtk );
+
+ if (pManMR->maxDelay) {
+ // timing-constrained loop
+ Abc_FlowRetime_ConstrainConserv( pNtk );
+ while(Abc_FlowRetime_RefineConstraints( )) {
+ pManMR->subIteration++;
+ Abc_FlowRetime_ClearFlows( 0 );
+ }
+ } else {
+ flow = Abc_FlowRetime_PushFlows( pNtk, 1 );
+ }
+
+ cut = Abc_FlowRetime_ImplementCut( pNtk );
+
+ vprintf("\t\tlevels = %d\n", Abc_NtkLevelReverse(pNtk));
+
+#if 0
+ Abc_NtkForEachObj( pNtk, pObj, i ) pObj->Level = 0;
+
+ Abc_NtkLevel(pNtk);
+ Abc_NtkForEachObj( pNtk, pObj, i )
+ if (pObj->Level > pManMR->maxDelay) {
+ print_node( pObj );
+ }
+ Abc_NtkLevelReverse(pNtk);
+ Abc_NtkForEachObj( pNtk, pObj, i )
+ if (pObj->Level > pManMR->maxDelay) {
+ print_node( pObj );
+ }
+#endif
+
+ Abc_FlowRetime_ClearFlows( 1 );
+
+ pManMR->iteration++;
+ } while( cut != last );
+
+ // compute initial states
+ if (!pManMR->fComputeInitState) break;
+
+ if (Abc_FlowRetime_SolveBackwardInit( pNtk )) {
+ if (pManMR->fVerbose) Abc_FlowRetime_PrintInitStateInfo( pNtk );
+ break;
+ } else {
+ if (!pManMR->fGuaranteeInitState) break;
+ Abc_FlowRetime_ConstrainInit( );
+ }
+ } while(1);
+}
+
+
+/**Function*************************************************************
+
+ Synopsis [Pushes latch bubbles outside of box.]
+
+ Description [If network is an AIG, a fCompl0 is allowed to remain on
+ the BI node.]
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void
+Abc_FlowRetime_RemoveLatchBubbles( Abc_Obj_t * pLatch ) {
+ int bubble = 0;
+ Abc_Ntk_t *pNtk = pManMR->pNtk;
+ Abc_Obj_t *pBi, *pBo, *pInv;
+
+ pBi = Abc_ObjFanin0(pLatch);
+ pBo = Abc_ObjFanout0(pLatch);
+ assert(!Abc_ObjIsComplement(pBi));
+ assert(!Abc_ObjIsComplement(pBo));
+
+ // push bubbles on BO into latch box
+ if (Abc_ObjFaninC0(pBo) && Abc_ObjFanoutNum(pBo) > 0) {
+ bubble = 1;
+ if (Abc_LatchIsInit0(pLatch)) Abc_LatchSetInit1(pLatch);
+ else if (Abc_LatchIsInit1(pLatch)) Abc_LatchSetInit0(pLatch);
+ }
+
+ // absorb bubbles on BI
+ pBi->fCompl0 ^= bubble ^ Abc_ObjFaninC0(pLatch);
+
+ // convert bubble to INV if not AIG
+ if (!Abc_NtkHasAig( pNtk ) && Abc_ObjFaninC0(pBi)) {
+ pBi->fCompl0 = 0;
+ pInv = Abc_NtkCreateNodeInv( pNtk, Abc_ObjFanin0(pBi) );
+ Abc_ObjPatchFanin( pBi, Abc_ObjFanin0(pBi), pInv );
+ }
+
+ pBo->fCompl0 = 0;
+ pLatch->fCompl0 = 0;
+}
+
+
+/**Function*************************************************************
+
+ Synopsis [Marks nodes in TFO/TFI of PI/PO.]
+
+ Description [Sets flow data flag BLOCK appropriately.]
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void
+Abc_FlowRetime_MarkBlocks( Abc_Ntk_t * pNtk ) {
+ int i;
+ Abc_Obj_t *pObj;
+
+ if (pManMR->fIsForward){
+ // mark the frontier
+ Abc_NtkForEachPo( pNtk, pObj, i )
+ pObj->fMarkA = 1;
+ Abc_NtkForEachLatch( pNtk, pObj, i )
+ {
+ pObj->fMarkA = 1;
+ }
+ // mark the nodes reachable from the PIs
+ Abc_NtkForEachPi( pNtk, pObj, i )
+ Abc_NtkMarkCone_rec( pObj, pManMR->fIsForward );
+ } else {
+ // mark the frontier
+ Abc_NtkForEachPi( pNtk, pObj, i )
+ pObj->fMarkA = 1;
+ Abc_NtkForEachLatch( pNtk, pObj, i )
+ {
+ pObj->fMarkA = 1;
+ }
+ // mark the nodes reachable from the POs
+ Abc_NtkForEachPo( pNtk, pObj, i )
+ Abc_NtkMarkCone_rec( pObj, pManMR->fIsForward );
+ }
+
+ // copy marks
+ Abc_NtkForEachObj( pNtk, pObj, i ) {
+ if (pObj->fMarkA) {
+ pObj->fMarkA = 0;
+ if (!Abc_ObjIsLatch(pObj) /* && !Abc_ObjIsPi(pObj) */ )
+ FSET(pObj, BLOCK);
+ }
+ }
+}
+
+
+/**Function*************************************************************
+
+ Synopsis [Computes maximum flow.]
+
+ Description []
+
+ SideEffects [Leaves VISITED flags on source-reachable nodes.]
+
+ SeeAlso []
+
+***********************************************************************/
+int
+Abc_FlowRetime_PushFlows( Abc_Ntk_t * pNtk, bool fVerbose ) {
+ int i, j, flow = 0, last, srcDist = 0;
+ Abc_Obj_t *pObj, *pObj2;
+
+ pManMR->constraintMask |= BLOCK;
+
+ pManMR->fSinkDistTerminate = 0;
+ dfsfast_preorder( pNtk );
+
+ // (i) fast max-flow computation
+ while(!pManMR->fSinkDistTerminate && srcDist < MAX_DIST) {
+ srcDist = MAX_DIST;
+ Abc_NtkForEachLatch( pNtk, pObj, i )
+ if (FDATA(pObj)->e_dist)
+ srcDist = MIN(srcDist, FDATA(pObj)->e_dist);
+
+ Abc_NtkForEachLatch( pNtk, pObj, i ) {
+ if (srcDist == FDATA(pObj)->e_dist &&
+ dfsfast_e( pObj, NULL )) {
+#ifdef DEBUG_PRINT_FLOWS
+ printf("\n\n");
+#endif
+ flow++;
+ }
+ }
+ }
+
+ if (fVerbose) vprintf("\t\tmax-flow1 = %d \t", flow);
+
+ // (ii) complete max-flow computation
+ // also, marks source-reachable nodes
+ do {
+ last = flow;
+ Abc_NtkForEachLatch( pNtk, pObj, i ) {
+ if (dfsplain_e( pObj, NULL )) {
+#ifdef DEBUG_PRINT_FLOWS
+ printf("\n\n");
+#endif
+ flow++;
+ Abc_NtkForEachObj( pNtk, pObj2, j )
+ FUNSET( pObj2, VISITED );
+ }
+ }
+ } while (flow > last);
+
+ if (fVerbose) vprintf("max-flow2 = %d\n", flow);
+
+ return flow;
+}
+
+
+/**Function*************************************************************
+
+ Synopsis [Restores latch boxes.]
+
+ Description [Latchless BI/BO nodes are removed. Latch boxes are
+ restored around remaining latches.]
+
+ SideEffects [Deletes nodes as appropriate.]
+
+ SeeAlso []
+
+***********************************************************************/
+void
+Abc_FlowRetime_FixLatchBoxes( Abc_Ntk_t *pNtk, Vec_Ptr_t *vBoxIns ) {
+ int i;
+ Abc_Obj_t *pObj, *pBo = NULL, *pBi = NULL;
+ Vec_Ptr_t *vFreeBi = Vec_PtrAlloc( 100 );
+ Vec_Ptr_t *vFreeBo = Vec_PtrAlloc( 100 );
+
+ // 1. remove empty bi/bo pairs
+ while(Vec_PtrSize( vBoxIns )) {
+ pBi = (Abc_Obj_t *)Vec_PtrPop( vBoxIns );
+ assert(Abc_ObjIsBi(pBi));
+ assert(Abc_ObjFanoutNum(pBi) == 1);
+ assert(Abc_ObjFaninNum(pBi) == 1);
+ pBo = Abc_ObjFanout0(pBi);
+ assert(!Abc_ObjFaninC0(pBo));
+
+ if (Abc_ObjIsBo(pBo)) {
+ // an empty bi/bo pair
+
+ Abc_ObjRemoveFanins( pBo );
+ // transfer complement from BI, if present
+ assert(!Abc_ObjIsComplement(Abc_ObjFanin0(pBi)));
+ Abc_ObjBetterTransferFanout( pBo, Abc_ObjFanin0(pBi), Abc_ObjFaninC0(pBi) );
+
+ Abc_ObjRemoveFanins( pBi );
+ pBi->fCompl0 = 0;
+ Vec_PtrPush( vFreeBi, pBi );
+ Vec_PtrPush( vFreeBo, pBo );
+
+ // free names
+ if (Nm_ManFindNameById(pNtk->pManName, Abc_ObjId(pBi)))
+ Nm_ManDeleteIdName( pNtk->pManName, Abc_ObjId(pBi));
+ if (Nm_ManFindNameById(pNtk->pManName, Abc_ObjId(pBo)))
+ Nm_ManDeleteIdName( pNtk->pManName, Abc_ObjId(pBo));
+
+ // check for complete detachment
+ assert(Abc_ObjFaninNum(pBi) == 0);
+ assert(Abc_ObjFanoutNum(pBi) == 0);
+ assert(Abc_ObjFaninNum(pBo) == 0);
+ assert(Abc_ObjFanoutNum(pBo) == 0);
+ } else assert(Abc_ObjIsLatch(pBo));
+ }
+
+ // 2. add bi/bos as necessary for latches
+ Abc_NtkForEachLatch( pNtk, pObj, i ) {
+ assert(Abc_ObjFaninNum(pObj) == 1);
+ if (Abc_ObjFanoutNum(pObj))
+ pBo = Abc_ObjFanout0(pObj);
+ else pBo = NULL;
+ pBi = Abc_ObjFanin0(pObj);
+
+ // add BO
+ if (!pBo || !Abc_ObjIsBo(pBo)) {
+ pBo = (Abc_Obj_t *)Vec_PtrPop( vFreeBo );
+ if (Abc_ObjFanoutNum(pObj)) Abc_ObjTransferFanout( pObj, pBo );
+ Abc_ObjAddFanin( pBo, pObj );
+ }
+ // add BI
+ if (!Abc_ObjIsBi(pBi)) {
+ pBi = (Abc_Obj_t *)Vec_PtrPop( vFreeBi );
+ assert(Abc_ObjFaninNum(pBi) == 0);
+ Abc_ObjAddFanin( pBi, Abc_ObjFanin0(pObj) );
+ pBi->fCompl0 = pObj->fCompl0;
+ Abc_ObjRemoveFanins( pObj );
+ Abc_ObjAddFanin( pObj, pBi );
+ }
+ }
+
+ // delete remaining BIs and BOs
+ while(Vec_PtrSize( vFreeBi )) {
+ pObj = (Abc_Obj_t *)Vec_PtrPop( vFreeBi );
+ Abc_NtkDeleteObj( pObj );
+ }
+ while(Vec_PtrSize( vFreeBo )) {
+ pObj = (Abc_Obj_t *)Vec_PtrPop( vFreeBo );
+ Abc_NtkDeleteObj( pObj );
+ }
+
+#if defined(DEBUG_CHECK)
+ Abc_NtkForEachObj( pNtk, pObj, i ) {
+ if (Abc_ObjIsBo(pObj)) {
+ assert(Abc_ObjFaninNum(pObj) == 1);
+ assert(Abc_ObjIsLatch(Abc_ObjFanin0(pObj)));
+ }
+ if (Abc_ObjIsBi(pObj)) {
+ assert(Abc_ObjFaninNum(pObj) == 1);
+ assert(Abc_ObjFanoutNum(pObj) == 1);
+ assert(Abc_ObjIsLatch(Abc_ObjFanout0(pObj)));
+ }
+ if (Abc_ObjIsLatch(pObj)) {
+ assert(Abc_ObjFanoutNum(pObj) == 1);
+ assert(Abc_ObjFaninNum(pObj) == 1);
+ }
+ }
+#endif
+
+ Vec_PtrFree( vFreeBi );
+ Vec_PtrFree( vFreeBo );
+}
+
+
+/**Function*************************************************************
+
+ Synopsis [Checks register count along all combinational paths.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void
+Abc_FlowRetime_VerifyPathLatencies( Abc_Ntk_t * pNtk ) {
+ int i;
+ Abc_Obj_t *pObj;
+ fPathError = 0;
+
+ vprintf("\t\tVerifying latency along all paths...");
+
+ Abc_NtkForEachObj( pNtk, pObj, i ) {
+ if (Abc_ObjIsBo(pObj)) {
+ Abc_FlowRetime_VerifyPathLatencies_rec( pObj, 0 );
+ } else if (!pManMR->fIsForward && Abc_ObjIsPi(pObj)) {
+ Abc_FlowRetime_VerifyPathLatencies_rec( pObj, 0 );
+ }
+
+ if (fPathError) {
+ if (Abc_ObjFaninNum(pObj) > 0) {
+ printf("fanin ");
+ print_node(Abc_ObjFanin0(pObj));
+ }
+ printf("\n");
+ exit(0);
+ }
+ }
+
+ vprintf(" ok\n");
+
+ Abc_NtkForEachObj( pNtk, pObj, i ) {
+ pObj->fMarkA = 0;
+ pObj->fMarkB = 0;
+ pObj->fMarkC = 0;
+ }
+}
+
+
+int
+Abc_FlowRetime_VerifyPathLatencies_rec( Abc_Obj_t * pObj, int markD ) {
+ int i, j;
+ Abc_Obj_t *pNext;
+ int fCare = 0;
+ int markC = pObj->fMarkC;
+
+ if (!pObj->fMarkB) {
+ pObj->fMarkB = 1; // visited
+
+ if (Abc_ObjIsLatch(pObj))
+ markC = 1; // latch in output
+
+ if (!pManMR->fIsForward && !Abc_ObjIsPo(pObj) && !Abc_ObjFanoutNum(pObj))
+ return -1; // dangling non-PO outputs : don't care what happens
+
+ Abc_ObjForEachFanout( pObj, pNext, i ) {
+ // reached end of cycle?
+ if ( Abc_ObjIsBo(pNext) ||
+ (pManMR->fIsForward && Abc_ObjIsPo(pNext)) ) {
+ if (!markD && !Abc_ObjIsLatch(pObj)) {
+ printf("\nERROR: no-latch path (end)\n");
+ print_node(pNext);
+ printf("\n");
+ fPathError = 1;
+ }
+ } else if (!pManMR->fIsForward && Abc_ObjIsPo(pNext)) {
+ if (markD || Abc_ObjIsLatch(pObj)) {
+ printf("\nERROR: extra-latch path to outputs\n");
+ print_node(pNext);
+ printf("\n");
+ fPathError = 1;
+ }
+ } else {
+ j = Abc_FlowRetime_VerifyPathLatencies_rec( pNext, markD || Abc_ObjIsLatch(pObj) );
+ if (j >= 0) {
+ markC |= j;
+ fCare = 1;
+ }
+ }
+
+ if (fPathError) {
+ print_node(pObj);
+ printf("\n");
+ return 0;
+ }
+ }
+ }
+
+ if (!fCare) return -1;
+
+ if (markC && markD) {
+ printf("\nERROR: mult-latch path\n");
+ print_node(pObj);
+ printf("\n");
+ fPathError = 1;
+ }
+ if (!markC && !markD) {
+ printf("\nERROR: no-latch path (inter)\n");
+ print_node(pObj);
+ printf("\n");
+ fPathError = 1;
+ }
+
+ return (pObj->fMarkC = markC);
+}
+
+
+/**Function*************************************************************
+
+ Synopsis [Copies initial state from latches to BO nodes.]
+
+ Description [Initial states are marked on BO nodes with INIT_0 and
+ INIT_1 flags in their Flow_Data structures.]
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void
+Abc_FlowRetime_CopyInitState( Abc_Obj_t * pSrc, Abc_Obj_t * pDest ) {
+ Abc_Obj_t *pObj;
+
+ if (!pManMR->fComputeInitState) return;
+
+ assert(Abc_ObjIsLatch(pSrc));
+ assert(Abc_ObjFanin0(pDest) == pSrc);
+ assert(!Abc_ObjFaninC0(pDest));
+
+ FUNSET(pDest, INIT_CARE);
+ if (Abc_LatchIsInit0(pSrc)) {
+ FSET(pDest, INIT_0);
+ } else if (Abc_LatchIsInit1(pSrc)) {
+ FSET(pDest, INIT_1);
+ }
+
+ if (!pManMR->fIsForward) {
+ pObj = Abc_ObjData(pSrc);
+ assert(Abc_ObjIsPi(pObj));
+ FDATA(pDest)->pInitObj = pObj;
+ }
+}
+
+
+/**Function*************************************************************
+
+ Synopsis [Implements min-cut.]
+
+ Description [Requires source-reachable nodes to be marked VISITED.]
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int
+Abc_FlowRetime_ImplementCut( Abc_Ntk_t * pNtk ) {
+ int i, j, cut = 0, unmoved = 0;
+ Abc_Obj_t *pObj, *pReg, *pNext, *pBo = NULL, *pBi = NULL;
+ Vec_Ptr_t *vFreeRegs = Vec_PtrAlloc( Abc_NtkLatchNum(pNtk) );
+ Vec_Ptr_t *vBoxIns = Vec_PtrAlloc( Abc_NtkLatchNum(pNtk) );
+ Vec_Ptr_t *vMove = Vec_PtrAlloc( 100 );
+
+ // remove latches from netlist
+ Abc_NtkForEachLatch( pNtk, pObj, i ) {
+ pBo = Abc_ObjFanout0(pObj);
+ pBi = Abc_ObjFanin0(pObj);
+ assert(Abc_ObjIsBo(pBo) && Abc_ObjIsBi(pBi));
+ Vec_PtrPush( vBoxIns, pBi );
+
+ // copy initial state values to BO
+ Abc_FlowRetime_CopyInitState( pObj, pBo );
+
+ // re-use latch elsewhere
+ Vec_PtrPush( vFreeRegs, pObj );
+ FSET(pBo, CROSS_BOUNDARY);
+
+ // cut out of netlist
+ Abc_ObjPatchFanin( pBo, pObj, pBi );
+ Abc_ObjRemoveFanins( pObj );
+
+ // free name
+ if (Nm_ManFindNameById(pNtk->pManName, Abc_ObjId(pObj)))
+ Nm_ManDeleteIdName( pNtk->pManName, Abc_ObjId(pObj));
+ }
+
+ // insert latches into netlist
+ Abc_NtkForEachObj( pNtk, pObj, i ) {
+ if (Abc_ObjIsLatch( pObj )) continue;
+
+ // a latch is required on every node that lies across the min-cit
+ assert(!pManMR->fIsForward || !FTEST(pObj, VISITED_E) || FTEST(pObj, VISITED_R));
+ if (FTEST(pObj, VISITED_R) && !FTEST(pObj, VISITED_E)) {
+ assert(FTEST(pObj, FLOW));
+
+ // count size of cut
+ cut++;
+ if ((pManMR->fIsForward && Abc_ObjIsBo(pObj)) ||
+ (!pManMR->fIsForward && Abc_ObjIsBi(pObj)))
+ unmoved++;
+
+ // only insert latch between fanouts that lie across min-cut
+ // some fanout paths may be cut at deeper points
+ Abc_ObjForEachFanout( pObj, pNext, j )
+ if (Abc_FlowRetime_IsAcrossCut( pObj, pNext ))
+ Vec_PtrPush(vMove, pNext);
+
+ // check that move-set is non-zero
+ if (Vec_PtrSize(vMove) == 0)
+ print_node(pObj);
+ assert(Vec_PtrSize(vMove) > 0);
+
+ // insert one of re-useable registers
+ assert(Vec_PtrSize( vFreeRegs ));
+ pReg = (Abc_Obj_t *)Vec_PtrPop( vFreeRegs );
+
+ Abc_ObjAddFanin(pReg, pObj);
+ while(Vec_PtrSize( vMove )) {
+ pNext = (Abc_Obj_t *)Vec_PtrPop( vMove );
+ Abc_ObjPatchFanin( pNext, pObj, pReg );
+ if (Abc_ObjIsBi(pNext)) assert(Abc_ObjFaninNum(pNext) == 1);
+
+ }
+ if (Abc_ObjIsBi(pObj)) assert(Abc_ObjFaninNum(pObj) == 1);
+ }
+ }
+
+#if defined(DEBUG_CHECK)
+ Abc_FlowRetime_VerifyPathLatencies( pNtk );
+#endif
+
+ // delete remaining latches
+ while(Vec_PtrSize( vFreeRegs )) {
+ pReg = (Abc_Obj_t *)Vec_PtrPop( vFreeRegs );
+ Abc_NtkDeleteObj( pReg );
+ }
+
+ // update initial states
+ Abc_FlowRetime_InitState( pNtk );
+
+ // restore latch boxes
+ Abc_FlowRetime_FixLatchBoxes( pNtk, vBoxIns );
+
+ Vec_PtrFree( vFreeRegs );
+ Vec_PtrFree( vMove );
+ Vec_PtrFree( vBoxIns );
+
+ vprintf("\t\tmin-cut = %d (unmoved = %d)\n", cut, unmoved);
+ return cut;
+}
+
+
+/**Function*************************************************************
+
+ Synopsis [Adds dummy fanin.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void
+Abc_FlowRetime_AddDummyFanin( Abc_Obj_t * pObj ) {
+ Abc_Ntk_t *pNtk = Abc_ObjNtk( pObj );
+
+ if (Abc_NtkHasAig(pNtk))
+ Abc_ObjAddFanin(pObj, Abc_AigConst1( pNtk ));
+ else
+ Abc_ObjAddFanin(pObj, Abc_NtkCreateNodeConst0( pNtk ));
+}
+
+
+/**Function*************************************************************
+
+ Synopsis [Prints information about a node.]
+
+ Description [Debuging.]
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void
+print_node(Abc_Obj_t *pObj) {
+ int i;
+ Abc_Obj_t * pNext;
+ char m[6];
+
+ m[0] = 0;
+ if (pObj->fMarkA)
+ strcat(m, "A");
+ if (pObj->fMarkB)
+ strcat(m, "B");
+ if (pObj->fMarkC)
+ strcat(m, "C");
+
+ printf("node %d type=%d lev=%d tedge=%d (%x%s) fanouts {", Abc_ObjId(pObj), Abc_ObjType(pObj),
+ pObj->Level, Vec_PtrSize(FTIMEEDGES(pObj)), FDATA(pObj)->mark, m);
+ Abc_ObjForEachFanout( pObj, pNext, i )
+ printf("%d[%d](%d),", Abc_ObjId(pNext), Abc_ObjType(pNext), FDATA(pNext)->mark);
+ printf("} fanins {");
+ Abc_ObjForEachFanin( pObj, pNext, i )
+ printf("%d[%d](%d),", Abc_ObjId(pNext), Abc_ObjType(pNext), FDATA(pNext)->mark);
+ printf("}\n");
+}
+
+void
+print_node2(Abc_Obj_t *pObj) {
+ int i;
+ Abc_Obj_t * pNext;
+ char m[6];
+
+ m[0] = 0;
+ if (pObj->fMarkA)
+ strcat(m, "A");
+ if (pObj->fMarkB)
+ strcat(m, "B");
+ if (pObj->fMarkC)
+ strcat(m, "C");
+
+ printf("node %d type=%d %s fanouts {", Abc_ObjId(pObj), Abc_ObjType(pObj), m);
+ Abc_ObjForEachFanout( pObj, pNext, i )
+ printf("%d ,", Abc_ObjId(pNext));
+ printf("} fanins {");
+ Abc_ObjForEachFanin( pObj, pNext, i )
+ printf("%d ,", Abc_ObjId(pNext));
+ printf("} ");
+}
+
+void
+print_node3(Abc_Obj_t *pObj) {
+ int i;
+ Abc_Obj_t * pNext;
+ char m[6];
+
+ m[0] = 0;
+ if (pObj->fMarkA)
+ strcat(m, "A");
+ if (pObj->fMarkB)
+ strcat(m, "B");
+ if (pObj->fMarkC)
+ strcat(m, "C");
+
+ printf("\nnode %d type=%d mark=%d %s\n", Abc_ObjId(pObj), Abc_ObjType(pObj), FDATA(pObj)->mark, m);
+ printf("fanouts\n");
+ Abc_ObjForEachFanout( pObj, pNext, i ) {
+ print_node(pNext);
+ printf("\n");
+ }
+ printf("fanins\n");
+ Abc_ObjForEachFanin( pObj, pNext, i ) {
+ print_node(pNext);
+ printf("\n");
+ }
+}
+
+
+/**Function*************************************************************
+
+ Synopsis [Transfers fanout.]
+
+ Description [Does not produce an error if there is no fanout.
+ Complements as necessary.]
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void
+Abc_ObjBetterTransferFanout( Abc_Obj_t * pFrom, Abc_Obj_t * pTo, int compl ) {
+ Abc_Obj_t *pNext;
+
+ while(Abc_ObjFanoutNum(pFrom) > 0) {
+ pNext = Abc_ObjFanout0(pFrom);
+ Abc_ObjPatchFanin( pNext, pFrom, Abc_ObjNotCond(pTo, compl) );
+ }
+}
+
+
+/**Function*************************************************************
+
+ Synopsis [Returns true is a connection spans the min-cut.]
+
+ Description [pNext is a direct fanout of pObj.]
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+bool
+Abc_FlowRetime_IsAcrossCut( Abc_Obj_t *pObj, Abc_Obj_t *pNext ) {
+
+ if (FTEST(pObj, VISITED_R) && !FTEST(pObj, VISITED_E)) {
+ if (pManMR->fIsForward) {
+ if (!FTEST(pNext, VISITED_R) ||
+ (FTEST(pNext, BLOCK_OR_CONS) & pManMR->constraintMask)||
+ FTEST(pNext, CROSS_BOUNDARY) ||
+ Abc_ObjIsLatch(pNext))
+ return 1;
+ } else {
+ if (FTEST(pNext, VISITED_E) ||
+ FTEST(pNext, CROSS_BOUNDARY))
+ return 1;
+ }
+ }
+
+ return 0;
+}
+
+
+/**Function*************************************************************
+
+ Synopsis [Resets flow problem]
+
+ Description [If fClearAll is true, all marks will be cleared; this is
+ typically appropriate after the circuit structure has
+ been modified.]
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Abc_FlowRetime_ClearFlows( bool fClearAll ) {
+ int i;
+
+ if (fClearAll)
+ memset(pManMR->pDataArray, 0, sizeof(Flow_Data_t)*pManMR->nNodes);
+ else {
+ // clear only data related to flow problem
+ for(i=0; i<pManMR->nNodes; i++) {
+ pManMR->pDataArray[i].mark &= ~(VISITED | FLOW );
+ pManMR->pDataArray[i].e_dist = 0;
+ pManMR->pDataArray[i].r_dist = 0;
+ pManMR->pDataArray[i].pred = NULL;
+ }
+ }
+}
diff --git a/src/opt/fret/fretTime.c b/src/opt/fret/fretTime.c
new file mode 100644
index 00000000..f497df60
--- /dev/null
+++ b/src/opt/fret/fretTime.c
@@ -0,0 +1,763 @@
+/**CFile****************************************************************
+
+ FileName [fretTime.c]
+
+ SystemName [ABC: Logic synthesis and verification system.]
+
+ PackageName [Flow-based retiming package.]
+
+ Synopsis [Delay-constrained retiming code.]
+
+ Author [Aaron Hurst]
+
+ Affiliation [UC Berkeley]
+
+ Date [Ver. 1.0. Started - January 1, 2008.]
+
+ Revision [$Id: fretTime.c,v 1.00 2008/01/01 00:00:00 ahurst Exp $]
+
+***********************************************************************/
+
+#include "abc.h"
+#include "vec.h"
+#include "fretime.h"
+
+////////////////////////////////////////////////////////////////////////
+/// DECLARATIONS ///
+////////////////////////////////////////////////////////////////////////
+
+static void Abc_FlowRetime_Dfs_forw( Abc_Obj_t * pObj, Vec_Ptr_t *vNodes );
+static void Abc_FlowRetime_Dfs_back( Abc_Obj_t * pObj, Vec_Ptr_t *vNodes );
+
+static void Abc_FlowRetime_ConstrainExact_forw( Abc_Obj_t * pObj );
+static void Abc_FlowRetime_ConstrainExact_back( Abc_Obj_t * pObj );
+static void Abc_FlowRetime_ConstrainConserv_forw( Abc_Ntk_t * pNtk );
+static void Abc_FlowRetime_ConstrainConserv_back( Abc_Ntk_t * pNtk );
+
+
+void trace2(Abc_Obj_t *pObj) {
+ Abc_Obj_t *pNext;
+ int i;
+
+ print_node(pObj);
+ Abc_ObjForEachFanin(pObj, pNext, i)
+ if (pNext->Level >= pObj->Level - 1) {
+ trace2(pNext);
+ break;
+ }
+}
+
+////////////////////////////////////////////////////////////////////////
+/// FUNCTION DEFINITIONS ///
+////////////////////////////////////////////////////////////////////////
+
+
+/**Function*************************************************************
+
+ Synopsis [Initializes timing]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Abc_FlowRetime_InitTiming( Abc_Ntk_t *pNtk ) {
+
+ pManMR->nConservConstraints = pManMR->nExactConstraints = 0;
+
+ pManMR->vExactNodes = Vec_PtrAlloc(1000);
+
+ pManMR->vTimeEdges = ALLOC( Vec_Ptr_t, Abc_NtkObjNumMax(pNtk)+1 );
+ assert(pManMR->vTimeEdges);
+ memset(pManMR->vTimeEdges, 0, (Abc_NtkObjNumMax(pNtk)+1) * sizeof(Vec_Ptr_t) );
+}
+
+
+/**Function*************************************************************
+
+ Synopsis [Marks nodes with conservative constraints.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Abc_FlowRetime_ConstrainConserv( Abc_Ntk_t * pNtk ) {
+ Abc_Obj_t *pObj;
+ int i;
+ void *pArray;
+
+ // clear all exact constraints
+ pManMR->nExactConstraints = 0;
+ while( Vec_PtrSize( pManMR->vExactNodes )) {
+ pObj = Vec_PtrPop( pManMR->vExactNodes );
+
+ if ( Vec_PtrSize( FTIMEEDGES(pObj) )) {
+ pArray = Vec_PtrReleaseArray( FTIMEEDGES(pObj) );
+ FREE( pArray );
+ }
+ }
+
+#if !defined(IGNORE_TIMING)
+ if (pManMR->fIsForward) {
+ Abc_FlowRetime_ConstrainConserv_forw(pNtk);
+ } else {
+ Abc_FlowRetime_ConstrainConserv_back(pNtk);
+ }
+#endif
+
+ Abc_NtkForEachObj( pNtk, pObj, i)
+ assert( !Vec_PtrSize(FTIMEEDGES(pObj)) );
+}
+
+
+void Abc_FlowRetime_ConstrainConserv_forw( Abc_Ntk_t * pNtk ) {
+ Vec_Ptr_t *vNodes = pManMR->vNodes;
+ Abc_Obj_t *pObj, *pNext, *pBi, *pBo;
+ int i, j;
+
+ assert(!Vec_PtrSize( vNodes ));
+ pManMR->nConservConstraints = 0;
+
+ // 1. hard constraints
+
+ // (i) collect TFO of PIs
+ Abc_NtkIncrementTravId(pNtk);
+ Abc_NtkForEachPi(pNtk, pObj, i)
+ Abc_FlowRetime_Dfs_forw( pObj, vNodes );
+
+ // ... propagate values
+ Vec_PtrForEachEntryReverse(vNodes, pObj, i) {
+ pObj->Level = 0;
+ Abc_ObjForEachFanin( pObj, pNext, j )
+ {
+ if ( Abc_NodeIsTravIdCurrent(pNext) &&
+ pObj->Level < pNext->Level )
+ pObj->Level = pNext->Level;
+ }
+ pObj->Level += Abc_ObjIsNode(pObj) ? 1 : 0;
+
+ if ( Abc_ObjIsBi(pObj) )
+ pObj->fMarkA = 1;
+
+ assert(pObj->Level <= pManMR->maxDelay);
+ }
+
+ // collect TFO of latches
+ // seed arrival times from BIs
+ Vec_PtrClear(vNodes);
+ Abc_NtkIncrementTravId(pNtk);
+ Abc_NtkForEachLatch(pNtk, pObj, i) {
+ pBo = Abc_ObjFanout0( pObj );
+ pBi = Abc_ObjFanin0( pObj );
+
+ Abc_NodeSetTravIdCurrent( pObj );
+ Abc_FlowRetime_Dfs_forw( pBo, vNodes );
+
+ if (pBi->fMarkA) {
+ pBi->fMarkA = 0;
+ pObj->Level = pBi->Level;
+ assert(pObj->Level <= pManMR->maxDelay);
+ } else
+ pObj->Level = 0;
+ }
+
+#if defined(DEBUG_CHECK)
+ // DEBUG: check DFS ordering
+ Vec_PtrForEachEntryReverse(vNodes, pObj, i) {
+ pObj->fMarkB = 1;
+
+ Abc_ObjForEachFanin( pObj, pNext, j )
+ if ( Abc_NodeIsTravIdCurrent(pNext) && !Abc_ObjIsLatch(pNext))
+ assert(pNext->fMarkB);
+ }
+ Vec_PtrForEachEntryReverse(vNodes, pObj, i)
+ pObj->fMarkB = 0;
+#endif
+
+ // ... propagate values
+ Vec_PtrForEachEntryReverse(vNodes, pObj, i) {
+ pObj->Level = 0;
+ Abc_ObjForEachFanin( pObj, pNext, j )
+ {
+ if ( Abc_NodeIsTravIdCurrent(pNext) &&
+ pObj->Level < pNext->Level )
+ pObj->Level = pNext->Level;
+ }
+ pObj->Level += Abc_ObjIsNode(pObj) ? 1 : 0;
+
+ if (pObj->Level > pManMR->maxDelay) {
+ FSET(pObj, BLOCK);
+ }
+ }
+
+ // 2. conservative constraints
+
+ // first pass: seed latches with T=0
+ Abc_NtkForEachLatch(pNtk, pObj, i) {
+ pObj->Level = 0;
+ }
+
+ // ... propagate values
+ Vec_PtrForEachEntryReverse(vNodes, pObj, i) {
+ pObj->Level = 0;
+ Abc_ObjForEachFanin( pObj, pNext, j ) {
+ if ( Abc_NodeIsTravIdCurrent(pNext) &&
+ pObj->Level < pNext->Level )
+ pObj->Level = pNext->Level;
+ }
+ pObj->Level += Abc_ObjIsNode(pObj) ? 1 : 0;
+
+ if ( Abc_ObjIsBi(pObj) )
+ pObj->fMarkA = 1;
+
+ assert(pObj->Level <= pManMR->maxDelay);
+ }
+
+ Abc_NtkForEachLatch(pNtk, pObj, i) {
+ pBo = Abc_ObjFanout0( pObj );
+ pBi = Abc_ObjFanin0( pObj );
+
+ if (pBi->fMarkA) {
+ pBi->fMarkA = 0;
+ pObj->Level = pBi->Level;
+ assert(pObj->Level <= pManMR->maxDelay);
+ } else
+ pObj->Level = 0;
+ }
+
+ // ... propagate values
+ Vec_PtrForEachEntryReverse(vNodes, pObj, i) {
+ pObj->Level = 0;
+ Abc_ObjForEachFanin( pObj, pNext, j ) {
+ if ( Abc_NodeIsTravIdCurrent(pNext) &&
+ pObj->Level < pNext->Level )
+ pObj->Level = pNext->Level;
+ }
+ pObj->Level += Abc_ObjIsNode(pObj) ? 1 : 0;
+
+ // constrained?
+ if (pObj->Level > pManMR->maxDelay) {
+ FSET( pObj, CONSERVATIVE );
+ pManMR->nConservConstraints++;
+ } else
+ FUNSET( pObj, CONSERVATIVE );
+ }
+
+ Vec_PtrClear( vNodes );
+}
+
+
+void Abc_FlowRetime_ConstrainConserv_back( Abc_Ntk_t * pNtk ) {
+ Vec_Ptr_t *vNodes = pManMR->vNodes;
+ Abc_Obj_t *pObj, *pNext, *pBi, *pBo;
+ int i, j, l;
+
+ assert(!Vec_PtrSize(vNodes));
+
+ pManMR->nConservConstraints = 0;
+
+ // 1. hard constraints
+
+ // (i) collect TFO of POs
+ Abc_NtkIncrementTravId(pNtk);
+ Abc_NtkForEachPo(pNtk, pObj, i)
+ Abc_FlowRetime_Dfs_back( pObj, vNodes );
+
+ // ... propagate values
+ Vec_PtrForEachEntryReverse(vNodes, pObj, i) {
+ pObj->Level = 0;
+ Abc_ObjForEachFanout( pObj, pNext, j )
+ {
+ l = pNext->Level + (Abc_ObjIsNode(pObj) ? 1 : 0);
+ if ( Abc_NodeIsTravIdCurrent(pNext) &&
+ pObj->Level < l )
+ pObj->Level = l;
+ }
+
+ if ( Abc_ObjIsBo(pObj) )
+ pObj->fMarkA = 1;
+
+ assert(pObj->Level <= pManMR->maxDelay);
+ }
+
+ // collect TFO of latches
+ // seed arrival times from BIs
+ Vec_PtrClear(vNodes);
+ Abc_NtkIncrementTravId(pNtk);
+ Abc_NtkForEachLatch(pNtk, pObj, i) {
+ pBo = Abc_ObjFanout0( pObj );
+ pBi = Abc_ObjFanin0( pObj );
+
+ Abc_NodeSetTravIdCurrent( pObj );
+ Abc_FlowRetime_Dfs_back( pBi, vNodes );
+
+ if (pBo->fMarkA) {
+ pBo->fMarkA = 0;
+ pObj->Level = pBo->Level;
+ assert(pObj->Level <= pManMR->maxDelay);
+ } else
+ pObj->Level = 0;
+ }
+
+#if defined(DEBUG_CHECK)
+ // DEBUG: check DFS ordering
+ Vec_PtrForEachEntryReverse(vNodes, pObj, i) {
+ pObj->fMarkB = 1;
+
+ Abc_ObjForEachFanout( pObj, pNext, j )
+ if ( Abc_NodeIsTravIdCurrent(pNext) && !Abc_ObjIsLatch(pNext))
+ assert(pNext->fMarkB);
+ }
+ Vec_PtrForEachEntryReverse(vNodes, pObj, i)
+ pObj->fMarkB = 0;
+#endif
+
+ // ... propagate values
+ Vec_PtrForEachEntryReverse(vNodes, pObj, i) {
+ pObj->Level = 0;
+ Abc_ObjForEachFanout( pObj, pNext, j )
+ {
+ l = pNext->Level + (Abc_ObjIsNode(pObj) ? 1 : 0);
+ if ( Abc_NodeIsTravIdCurrent(pNext) &&
+ pObj->Level < l )
+ pObj->Level = l;
+ }
+
+ if (pObj->Level + (Abc_ObjIsNode(pObj)?1:0) > pManMR->maxDelay) {
+ FSET(pObj, BLOCK);
+ }
+ }
+
+ // 2. conservative constraints
+
+ // first pass: seed latches with T=0
+ Abc_NtkForEachLatch(pNtk, pObj, i) {
+ pObj->Level = 0;
+ }
+
+ // ... propagate values
+ Vec_PtrForEachEntryReverse(vNodes, pObj, i) {
+ pObj->Level = 0;
+ Abc_ObjForEachFanout( pObj, pNext, j ) {
+ l = pNext->Level + (Abc_ObjIsNode(pObj) ? 1 : 0);
+ if ( Abc_NodeIsTravIdCurrent(pNext) &&
+ pObj->Level < l )
+ pObj->Level = l;
+ }
+
+ if ( Abc_ObjIsBo(pObj) ) {
+ pObj->fMarkA = 1;
+ }
+
+ assert(pObj->Level <= pManMR->maxDelay);
+ }
+
+ Abc_NtkForEachLatch(pNtk, pObj, i) {
+ pBo = Abc_ObjFanout0( pObj );
+ assert(Abc_ObjIsBo(pBo));
+ pBi = Abc_ObjFanin0( pObj );
+ assert(Abc_ObjIsBi(pBi));
+
+ if (pBo->fMarkA) {
+ pBo->fMarkA = 0;
+ pObj->Level = pBo->Level;
+ } else
+ pObj->Level = 0;
+ }
+
+ // ... propagate values
+ Vec_PtrForEachEntryReverse(vNodes, pObj, i) {
+ pObj->Level = 0;
+ Abc_ObjForEachFanout( pObj, pNext, j ) {
+ l = pNext->Level + (Abc_ObjIsNode(pObj) ? 1 : 0);
+ if ( Abc_NodeIsTravIdCurrent(pNext) &&
+ pObj->Level < l )
+ pObj->Level = l;
+ }
+
+ // constrained?
+ if (pObj->Level > pManMR->maxDelay) {
+ FSET( pObj, CONSERVATIVE );
+ pManMR->nConservConstraints++;
+ } else
+ FUNSET( pObj, CONSERVATIVE );
+ }
+
+ Vec_PtrClear( vNodes );
+}
+
+
+/**Function*************************************************************
+
+ Synopsis [Introduces exact timing constraints for a node.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Abc_FlowRetime_ConstrainExact( Abc_Obj_t * pObj ) {
+
+ if (FTEST( pObj, CONSERVATIVE )) {
+ pManMR->nConservConstraints--;
+ FUNSET( pObj, CONSERVATIVE );
+ }
+
+#if !defined(IGNORE_TIMING)
+ if (pManMR->fIsForward) {
+ Abc_FlowRetime_ConstrainExact_forw(pObj);
+ } else {
+ Abc_FlowRetime_ConstrainExact_back(pObj);
+ }
+#endif
+}
+
+void Abc_FlowRetime_ConstrainExact_forw_rec( Abc_Obj_t * pObj, Vec_Ptr_t *vNodes, int latch ) {
+ Abc_Obj_t *pNext;
+ int i;
+
+ // terminate?
+ if (Abc_ObjIsLatch(pObj)) {
+ if (latch) return;
+ latch = 1;
+ }
+
+ // already visited?
+ if (!latch) {
+ if (pObj->fMarkA) return;
+ pObj->fMarkA = 1;
+ } else {
+ if (pObj->fMarkB) return;
+ pObj->fMarkB = 1;
+ }
+
+ // recurse
+ Abc_ObjForEachFanin(pObj, pNext, i) {
+ Abc_FlowRetime_ConstrainExact_forw_rec( pNext, vNodes, latch );
+ }
+
+ // add
+ pObj->Level = 0;
+ Vec_PtrPush(vNodes, Abc_ObjNotCond(pObj, latch));
+}
+
+void Abc_FlowRetime_ConstrainExact_forw( Abc_Obj_t * pObj ) {
+ Vec_Ptr_t *vNodes = pManMR->vNodes;
+ Abc_Obj_t *pNext, *pCur, *pReg;
+ // Abc_Ntk_t *pNtk = pManMR->pNtk;
+ int i, j;
+
+ assert( !Vec_PtrSize(vNodes) );
+ assert( !Abc_ObjIsLatch(pObj) );
+ assert( !Vec_PtrSize( FTIMEEDGES(pObj) ));
+ Vec_PtrPush( pManMR->vExactNodes, pObj );
+
+ // rev topo order
+ Abc_FlowRetime_ConstrainExact_forw_rec( pObj, vNodes, 0 );
+
+ Vec_PtrForEachEntryReverse( vNodes, pCur, i) {
+ pReg = Abc_ObjRegular( pCur );
+
+ if (pReg == pCur) {
+ assert(!Abc_ObjIsLatch(pReg));
+ Abc_ObjForEachFanin(pReg, pNext, j)
+ pNext->Level = MAX( pNext->Level, pReg->Level + (Abc_ObjIsNode(pReg)?1:0));
+ assert(pReg->Level <= pManMR->maxDelay);
+ pReg->Level = 0;
+ pReg->fMarkA = pReg->fMarkB = 0;
+ }
+ }
+ Vec_PtrForEachEntryReverse( vNodes, pCur, i) {
+ pReg = Abc_ObjRegular( pCur );
+ if (pReg != pCur) {
+ Abc_ObjForEachFanin(pReg, pNext, j)
+ if (!Abc_ObjIsLatch(pNext))
+ pNext->Level = MAX( pNext->Level, pReg->Level + (Abc_ObjIsNode(pReg)?1:0));
+
+ if (pReg->Level == pManMR->maxDelay) {
+ Vec_PtrPush( FTIMEEDGES(pObj), pReg);
+ pManMR->nExactConstraints++;
+ }
+ pReg->Level = 0;
+ pReg->fMarkA = pReg->fMarkB = 0;
+ }
+ }
+
+ Vec_PtrClear( vNodes );
+}
+
+void Abc_FlowRetime_ConstrainExact_back_rec( Abc_Obj_t * pObj, Vec_Ptr_t *vNodes, int latch ) {
+ Abc_Obj_t *pNext;
+ int i;
+
+ // terminate?
+ if (Abc_ObjIsLatch(pObj)) {
+ if (latch) return;
+ latch = 1;
+ }
+
+ // already visited?
+ if (!latch) {
+ if (pObj->fMarkA) return;
+ pObj->fMarkA = 1;
+ } else {
+ if (pObj->fMarkB) return;
+ pObj->fMarkB = 1;
+ }
+
+ // recurse
+ Abc_ObjForEachFanout(pObj, pNext, i) {
+ Abc_FlowRetime_ConstrainExact_back_rec( pNext, vNodes, latch );
+ }
+
+ // add
+ pObj->Level = 0;
+ Vec_PtrPush(vNodes, Abc_ObjNotCond(pObj, latch));
+}
+
+
+void Abc_FlowRetime_ConstrainExact_back( Abc_Obj_t * pObj ) {
+ Vec_Ptr_t *vNodes = pManMR->vNodes;
+ Abc_Obj_t *pNext, *pCur, *pReg;
+ // Abc_Ntk_t *pNtk = pManMR->pNtk;
+ int i, j;
+
+ assert( !Vec_PtrSize( vNodes ));
+ assert( !Abc_ObjIsLatch(pObj) );
+ assert( !Vec_PtrSize( FTIMEEDGES(pObj) ));
+ Vec_PtrPush( pManMR->vExactNodes, pObj );
+
+ // rev topo order
+ Abc_FlowRetime_ConstrainExact_back_rec( pObj, vNodes, 0 );
+
+ Vec_PtrForEachEntryReverse( vNodes, pCur, i) {
+ pReg = Abc_ObjRegular( pCur );
+
+ if (pReg == pCur) {
+ assert(!Abc_ObjIsLatch(pReg));
+ Abc_ObjForEachFanout(pReg, pNext, j)
+ pNext->Level = MAX( pNext->Level, pReg->Level + (Abc_ObjIsNode(pReg)?1:0));
+ assert(pReg->Level <= pManMR->maxDelay);
+ pReg->Level = 0;
+ pReg->fMarkA = pReg->fMarkB = 0;
+ }
+ }
+ Vec_PtrForEachEntryReverse( vNodes, pCur, i) {
+ pReg = Abc_ObjRegular( pCur );
+ if (pReg != pCur) {
+ Abc_ObjForEachFanout(pReg, pNext, j)
+ if (!Abc_ObjIsLatch(pNext))
+ pNext->Level = MAX( pNext->Level, pReg->Level + (Abc_ObjIsNode(pReg)?1:0));
+
+ if (pReg->Level == pManMR->maxDelay) {
+ Vec_PtrPush( FTIMEEDGES(pObj), pReg);
+ pManMR->nExactConstraints++;
+ }
+ pReg->Level = 0;
+ pReg->fMarkA = pReg->fMarkB = 0;
+ }
+ }
+
+ Vec_PtrClear( vNodes );
+}
+
+
+/**Function*************************************************************
+
+ Synopsis [Introduces all exact timing constraints in a network]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Abc_FlowRetime_ConstrainExactAll( Abc_Ntk_t * pNtk ) {
+ int i;
+ Abc_Obj_t *pObj;
+ void *pArray;
+
+ // free existing constraints
+ Abc_NtkForEachObj( pNtk, pObj, i )
+ if ( Vec_PtrSize( FTIMEEDGES(pObj) )) {
+ pArray = Vec_PtrReleaseArray( FTIMEEDGES(pObj) );
+ FREE( pArray );
+ }
+ pManMR->nExactConstraints = 0;
+
+ // generate all constraints
+ Abc_NtkForEachObj(pNtk, pObj, i)
+ if (!Abc_ObjIsLatch(pObj) && FTEST( pObj, CONSERVATIVE ) && !FTEST( pObj, BLOCK ))
+ if (!Vec_PtrSize( FTIMEEDGES( pObj ) ))
+ Abc_FlowRetime_ConstrainExact( pObj );
+}
+
+
+
+/**Function*************************************************************
+
+ Synopsis [Deallocates exact constraints.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Abc_FlowRetime_FreeTiming( Abc_Ntk_t *pNtk ) {
+ Abc_Obj_t *pObj;
+ void *pArray;
+
+ while( Vec_PtrSize( pManMR->vExactNodes )) {
+ pObj = Vec_PtrPop( pManMR->vExactNodes );
+
+ if ( Vec_PtrSize( FTIMEEDGES(pObj) )) {
+ pArray = Vec_PtrReleaseArray( FTIMEEDGES(pObj) );
+ FREE( pArray );
+ }
+ }
+
+ Vec_PtrFree(pManMR->vExactNodes);
+ FREE( pManMR->vTimeEdges );
+}
+
+
+/**Function*************************************************************
+
+ Synopsis [DFS order.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Abc_FlowRetime_Dfs_forw( Abc_Obj_t * pObj, Vec_Ptr_t *vNodes ) {
+ Abc_Obj_t *pNext;
+ int i;
+
+ if (Abc_ObjIsLatch(pObj)) return;
+
+ Abc_NodeSetTravIdCurrent( pObj );
+
+ Abc_ObjForEachFanout( pObj, pNext, i )
+ if (!Abc_NodeIsTravIdCurrent( pNext ))
+ Abc_FlowRetime_Dfs_forw( pNext, vNodes );
+
+ Vec_PtrPush( vNodes, pObj );
+}
+
+
+void Abc_FlowRetime_Dfs_back( Abc_Obj_t * pObj, Vec_Ptr_t *vNodes ) {
+ Abc_Obj_t *pNext;
+ int i;
+
+ if (Abc_ObjIsLatch(pObj)) return;
+
+ Abc_NodeSetTravIdCurrent( pObj );
+
+ Abc_ObjForEachFanin( pObj, pNext, i )
+ if (!Abc_NodeIsTravIdCurrent( pNext ))
+ Abc_FlowRetime_Dfs_back( pNext, vNodes );
+
+ Vec_PtrPush( vNodes, pObj );
+}
+
+
+/**Function*************************************************************
+
+ Synopsis [Main timing-constrained routine.]
+
+ Description [Refines constraints that are limiting area improvement.
+ These are identified by computing
+ the min-cuts both with and without the conservative
+ constraints: these two situation represent an
+ over- and under-constrained version of the timing.]
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+bool Abc_FlowRetime_RefineConstraints( ) {
+ Abc_Ntk_t *pNtk = pManMR->pNtk;
+ int i, flow, count = 0;
+ Abc_Obj_t *pObj;
+ int maxTighten = 99999;
+
+ vprintf("\t\tsubiter %d : constraints = {cons, exact} = %d, %d\n",
+ pManMR->subIteration, pManMR->nConservConstraints, pManMR->nExactConstraints);
+
+ // 1. overconstrained
+ pManMR->constraintMask = BLOCK | CONSERVATIVE;
+ vprintf("\t\trefinement: over ");
+ fflush(stdout);
+ flow = Abc_FlowRetime_PushFlows( pNtk, 0 );
+ vprintf("= %d ", flow);
+
+ // remember nodes
+ if (pManMR->fIsForward) {
+ Abc_NtkForEachObj( pNtk, pObj, i )
+ if (!FTEST(pObj, VISITED_R))
+ pObj->fMarkC = 1;
+ } else {
+ Abc_NtkForEachObj( pNtk, pObj, i )
+ if (!FTEST(pObj, VISITED_E))
+ pObj->fMarkC = 1;
+ }
+
+ if (pManMR->fConservTimingOnly) {
+ vprintf(" done\n");
+ return 0;
+ }
+
+ // 2. underconstrained
+ pManMR->constraintMask = BLOCK;
+ Abc_FlowRetime_ClearFlows( 0 );
+ vprintf("under = ");
+ fflush(stdout);
+ flow = Abc_FlowRetime_PushFlows( pNtk, 0 );
+ vprintf("%d refined nodes = ", flow);
+ fflush(stdout);
+
+ // find area-limiting constraints
+ if (pManMR->fIsForward) {
+ Abc_NtkForEachObj( pNtk, pObj, i ) {
+ if (pObj->fMarkC &&
+ FTEST(pObj, VISITED_R) &&
+ FTEST(pObj, CONSERVATIVE) &&
+ count < maxTighten) {
+ count++;
+ Abc_FlowRetime_ConstrainExact( pObj );
+ }
+ pObj->fMarkC = 0;
+ }
+ } else {
+ Abc_NtkForEachObj( pNtk, pObj, i ) {
+ if (pObj->fMarkC &&
+ FTEST(pObj, VISITED_E) &&
+ FTEST(pObj, CONSERVATIVE) &&
+ count < maxTighten) {
+ count++;
+ Abc_FlowRetime_ConstrainExact( pObj );
+ }
+ pObj->fMarkC = 0;
+ }
+ }
+
+ vprintf("%d\n", count);
+
+ return (count > 0);
+}
+
+
diff --git a/src/opt/fret/fretime.h b/src/opt/fret/fretime.h
new file mode 100644
index 00000000..167543ce
--- /dev/null
+++ b/src/opt/fret/fretime.h
@@ -0,0 +1,165 @@
+/**CFile****************************************************************
+
+ FileName [fretime.h]
+
+ SystemName [ABC: Logic synthesis and verification system.]
+
+ PackageName [Flow-based retiming package.]
+
+ Synopsis [Header file for retiming package.]
+
+ Author [Aaron Hurst]
+
+ Affiliation [UC Berkeley]
+
+ Date [Ver. 1.0. Started - January 1, 2008.]
+
+ Revision [$Id: fretime.h,v 1.00 2008/01/01 00:00:00 ahurst Exp $]
+
+***********************************************************************/
+
+#if !defined(RETIME_H_)
+#define RETIME_H_
+
+#include "abc.h"
+
+// #define IGNORE_TIMING
+// #define DEBUG_PRINT_FLOWS
+// #define DEBUG_VISITED
+// #define DEBUG_PREORDER
+// #define DEBUG_CHECK
+
+////////////////////////////////////////////////////////////////////////
+/// DECLARATIONS ///
+////////////////////////////////////////////////////////////////////////
+
+#define MAX_DIST 30000
+
+// flags in Flow_Data structure...
+#define VISITED_E 0x01
+#define VISITED_R 0x02
+#define VISITED (VISITED_E | VISITED_R)
+#define FLOW 0x04
+#define CROSS_BOUNDARY 0x08
+#define BLOCK 0x10
+#define INIT_0 0x20
+#define INIT_1 0x40
+#define INIT_CARE (INIT_0 | INIT_1)
+#define CONSERVATIVE 0x80
+#define BLOCK_OR_CONS (BLOCK | CONSERVATIVE)
+
+typedef struct Flow_Data_t_ {
+ unsigned int mark : 16;
+
+ union {
+ Abc_Obj_t *pred;
+ /* unsigned int var; */
+ Abc_Obj_t *pInitObj;
+ Vec_Ptr_t *vNodes;
+ };
+
+ unsigned int e_dist : 16;
+ unsigned int r_dist : 16;
+} Flow_Data_t;
+
+// useful macros for manipulating Flow_Data structure...
+#define FDATA( x ) ((Flow_Data_t *)Abc_ObjCopy(x))
+#define FSET( x, y ) ((Flow_Data_t *)Abc_ObjCopy(x))->mark |= y
+#define FUNSET( x, y ) ((Flow_Data_t *)Abc_ObjCopy(x))->mark &= ~y
+#define FTEST( x, y ) (((Flow_Data_t *)Abc_ObjCopy(x))->mark & y)
+#define FTIMEEDGES( x ) &(pManMR->vTimeEdges[Abc_ObjId( x )])
+
+static inline void FSETPRED(Abc_Obj_t *pObj, Abc_Obj_t *pPred) {
+ assert(!Abc_ObjIsLatch(pObj)); // must preserve field to maintain init state linkage
+ FDATA(pObj)->pred = pPred;
+}
+static inline Abc_Obj_t * FGETPRED(Abc_Obj_t *pObj) {
+ return FDATA(pObj)->pred;
+}
+
+
+typedef struct MinRegMan_t_ {
+
+ // problem description:
+ int maxDelay;
+ bool fComputeInitState, fGuaranteeInitState;
+ int nNodes, nLatches;
+ bool fForwardOnly, fBackwardOnly;
+ bool fConservTimingOnly;
+ int nMaxIters;
+ bool fVerbose;
+ Abc_Ntk_t *pNtk;
+
+ int nPreRefine;
+
+ // problem state
+ bool fIsForward;
+ bool fSinkDistTerminate;
+ int nExactConstraints, nConservConstraints;
+ int fSolutionIsDc;
+ int constraintMask;
+ int iteration, subIteration;
+
+ // problem data
+ Vec_Int_t *vSinkDistHist;
+ Flow_Data_t *pDataArray;
+ Vec_Ptr_t *vTimeEdges;
+ Vec_Ptr_t *vExactNodes;
+ Abc_Ntk_t *pInitNtk;
+ Vec_Ptr_t *vNodes; // re-useable struct
+
+} MinRegMan_t ;
+
+#define vprintf if (pManMR->fVerbose) printf
+
+/*=== fretMain.c ==========================================================*/
+
+extern MinRegMan_t *pManMR;
+
+Abc_Ntk_t * Abc_FlowRetime_MinReg( Abc_Ntk_t * pNtk, int fVerbose, int fComputeInitState,
+ int fForward, int fBackward, int nMaxIters,
+ int maxDelay, int fFastButConservative);
+
+void print_node(Abc_Obj_t *pObj);
+
+void Abc_ObjBetterTransferFanout( Abc_Obj_t * pFrom, Abc_Obj_t * pTo, int compl );
+
+int Abc_FlowRetime_PushFlows( Abc_Ntk_t * pNtk, bool fVerbose );
+bool Abc_FlowRetime_IsAcrossCut( Abc_Obj_t *pCur, Abc_Obj_t *pNext );
+void Abc_FlowRetime_ClearFlows( bool fClearAll );
+
+/*=== fretFlow.c ==========================================================*/
+
+int dfsplain_e( Abc_Obj_t *pObj, Abc_Obj_t *pPred );
+int dfsplain_r( Abc_Obj_t *pObj, Abc_Obj_t *pPred );
+
+void dfsfast_preorder( Abc_Ntk_t *pNtk );
+int dfsfast_e( Abc_Obj_t *pObj, Abc_Obj_t *pPred );
+int dfsfast_r( Abc_Obj_t *pObj, Abc_Obj_t *pPred );
+
+/*=== fretInit.c ==========================================================*/
+
+void Abc_FlowRetime_PrintInitStateInfo( Abc_Ntk_t * pNtk );
+
+void Abc_FlowRetime_InitState( Abc_Ntk_t * pNtk );
+
+void Abc_FlowRetime_UpdateForwardInit( Abc_Ntk_t * pNtk );
+void Abc_FlowRetime_UpdateBackwardInit( Abc_Ntk_t * pNtk );
+
+void Abc_FlowRetime_SetupBackwardInit( Abc_Ntk_t * pNtk );
+int Abc_FlowRetime_SolveBackwardInit( Abc_Ntk_t * pNtk );
+
+void Abc_FlowRetime_ConstrainInit( );
+
+/*=== fretTime.c ==========================================================*/
+
+void Abc_FlowRetime_InitTiming( Abc_Ntk_t *pNtk );
+void Abc_FlowRetime_FreeTiming( Abc_Ntk_t *pNtk );
+
+bool Abc_FlowRetime_RefineConstraints( );
+
+void Abc_FlowRetime_ConstrainConserv( Abc_Ntk_t * pNtk );
+void Abc_FlowRetime_ConstrainExact( Abc_Obj_t * pObj );
+void Abc_FlowRetime_ConstrainExactAll( Abc_Ntk_t * pNtk );
+
+#endif
diff --git a/src/opt/fret/module.make b/src/opt/fret/module.make
new file mode 100644
index 00000000..fda6a73d
--- /dev/null
+++ b/src/opt/fret/module.make
@@ -0,0 +1,5 @@
+SRC += src/opt/fret/fretMain.c \
+ src/opt/fret/fretFlow.c \
+ src/opt/fret/fretInit.c \
+ src/opt/fret/fretTime.c
+
diff --git a/src/opt/fxu/fxu.c b/src/opt/fxu/fxu.c
index 46f7ca1a..d11fd793 100644
--- a/src/opt/fxu/fxu.c
+++ b/src/opt/fxu/fxu.c
@@ -17,7 +17,6 @@
***********************************************************************/
#include "fxuInt.h"
-//#include "mvc.h"
#include "fxu.h"
////////////////////////////////////////////////////////////////////////
@@ -32,7 +31,7 @@ static int s_MemoryTotal;
static int s_MemoryPeak;
////////////////////////////////////////////////////////////////////////
-/// FUNCTION DEFITIONS ///
+/// FUNCTION DEFINITIONS ///
////////////////////////////////////////////////////////////////////////
/**Function*************************************************************
@@ -59,6 +58,7 @@ int Fxu_FastExtract( Fxu_Data_t * pData )
Fxu_Single * pSingle;
Fxu_Double * pDouble;
int Weight1, Weight2, Weight3;
+ int Counter = 0;
s_MemoryTotal = 0;
s_MemoryPeak = 0;
@@ -78,7 +78,7 @@ int Fxu_FastExtract( Fxu_Data_t * pData )
{
Weight1 = Fxu_HeapSingleReadMaxWeight( p->pHeapSingle );
if ( pData->fVerbose )
- printf( "Best single = %3d.\n", Weight1 );
+ printf( "Div %5d : Best single = %5d.\r", Counter++, Weight1 );
if ( Weight1 > 0 || Weight1 == 0 && pData->fUse0 )
Fxu_UpdateSingle( p );
else
@@ -93,7 +93,7 @@ int Fxu_FastExtract( Fxu_Data_t * pData )
{
Weight2 = Fxu_HeapDoubleReadMaxWeight( p->pHeapDouble );
if ( pData->fVerbose )
- printf( "Best double = %3d.\n", Weight2 );
+ printf( "Div %5d : Best double = %5d.\r", Counter++, Weight2 );
if ( Weight2 > 0 || Weight2 == 0 && pData->fUse0 )
Fxu_UpdateDouble( p );
else
@@ -110,7 +110,7 @@ int Fxu_FastExtract( Fxu_Data_t * pData )
Weight2 = Fxu_HeapDoubleReadMaxWeight( p->pHeapDouble );
if ( pData->fVerbose )
- printf( "Best double = %3d. Best single = %3d.\n", Weight2, Weight1 );
+ printf( "Div %5d : Best double = %5d. Best single = %5d.\r", Counter++, Weight2, Weight1 );
//Fxu_Select( p, &pSingle, &pDouble );
if ( Weight1 >= Weight2 )
@@ -141,8 +141,8 @@ int Fxu_FastExtract( Fxu_Data_t * pData )
// select the best single and double
Weight3 = Fxu_Select( p, &pSingle, &pDouble );
if ( pData->fVerbose )
- printf( "Best double = %3d. Best single = %3d. Best complement = %3d.\n",
- Weight2, Weight1, Weight3 );
+ printf( "Div %5d : Best double = %5d. Best single = %5d. Best complement = %5d.\r",
+ Counter++, Weight2, Weight1, Weight3 );
if ( Weight3 > 0 || Weight3 == 0 && pData->fUse0 )
Fxu_Update( p, pSingle, pDouble );
@@ -153,13 +153,14 @@ int Fxu_FastExtract( Fxu_Data_t * pData )
}
if ( pData->fVerbose )
- printf( "Total single = %3d. Total double = %3d. Total compl = %3d.\n", p->nDivs1, p->nDivs2, p->nDivs3 );
+ printf( "Total single = %3d. Total double = %3d. Total compl = %3d. \n",
+ p->nDivs1, p->nDivs2, p->nDivs3 );
// create the new covers
if ( pData->nNodesNew )
Fxu_CreateCovers( p, pData );
Fxu_MatrixDelete( p );
-// printf( "Memory usage after delocation: Total = %d. Peak = %d.\n", s_MemoryTotal, s_MemoryPeak );
+// printf( "Memory usage after deallocation: Total = %d. Peak = %d.\n", s_MemoryTotal, s_MemoryPeak );
if ( pData->nNodesNew == pData->nNodesExt )
printf( "Warning: The limit on the number of extracted divisors has been reached.\n" );
return pData->nNodesNew;
diff --git a/src/opt/fxu/fxu.h b/src/opt/fxu/fxu.h
index e9f63ea3..e6d0b69e 100644
--- a/src/opt/fxu/fxu.h
+++ b/src/opt/fxu/fxu.h
@@ -19,6 +19,10 @@
#ifndef __FXU_H__
#define __FXU_H__
+#ifdef __cplusplus
+extern "C" {
+#endif
+
////////////////////////////////////////////////////////////////////////
/// INCLUDES ///
////////////////////////////////////////////////////////////////////////
@@ -33,9 +37,11 @@
/// STRUCTURE DEFINITIONS ///
////////////////////////////////////////////////////////////////////////
+#ifndef __cplusplus
#ifndef bool
#define bool int
#endif
+#endif
typedef struct FxuDataStruct Fxu_Data_t;
@@ -49,7 +55,8 @@ struct FxuDataStruct
bool fUseCompl; // set to 1 to have complement taken into account
bool fVerbose; // set to 1 to have verbose output
int nNodesExt; // the number of divisors to extract
- int nPairsMax; // the maximum number of cube pairs to consider
+ int nSingleMax; // the max number of single-cube divisors to consider
+ int nPairsMax; // the max number of double-cube divisors to consider
// the input information
Vec_Ptr_t * vSops; // the SOPs for each node in the network
Vec_Ptr_t * vFanins; // the fanins of each node in the network
@@ -64,19 +71,23 @@ struct FxuDataStruct
};
////////////////////////////////////////////////////////////////////////
-/// MACRO DEFITIONS ///
+/// MACRO DEFINITIONS ///
////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////
-/// FUNCTION DEFITIONS ///
+/// FUNCTION DEFINITIONS ///
////////////////////////////////////////////////////////////////////////
/*===== fxu.c ==========================================================*/
extern int Fxu_FastExtract( Fxu_Data_t * pData );
+#ifdef __cplusplus
+}
+#endif
+
+#endif
+
////////////////////////////////////////////////////////////////////////
/// END OF FILE ///
////////////////////////////////////////////////////////////////////////
-#endif
-
diff --git a/src/opt/fxu/fxuCreate.c b/src/opt/fxu/fxuCreate.c
index b061f53d..55026b27 100644
--- a/src/opt/fxu/fxuCreate.c
+++ b/src/opt/fxu/fxuCreate.c
@@ -24,16 +24,16 @@
/// DECLARATIONS ///
////////////////////////////////////////////////////////////////////////
-static void Fxu_CreateMatrixAddCube( Fxu_Matrix * p, Fxu_Cube * pCube, char * pSopCube, Vec_Fan_t * vFanins, int * pOrder );
+static void Fxu_CreateMatrixAddCube( Fxu_Matrix * p, Fxu_Cube * pCube, char * pSopCube, Vec_Int_t * vFanins, int * pOrder );
static int Fxu_CreateMatrixLitCompare( int * ptrX, int * ptrY );
static void Fxu_CreateCoversNode( Fxu_Matrix * p, Fxu_Data_t * pData, int iNode, Fxu_Cube * pCubeFirst, Fxu_Cube * pCubeNext );
static Fxu_Cube * Fxu_CreateCoversFirstCube( Fxu_Matrix * p, Fxu_Data_t * pData, int iNode );
-static Abc_Fan_t * s_pLits;
+static int * s_pLits;
extern int Fxu_PreprocessCubePairs( Fxu_Matrix * p, Vec_Ptr_t * vCovers, int nPairsTotal, int nPairsMax );
////////////////////////////////////////////////////////////////////////
-/// FUNCTION DEFITIONS ///
+/// FUNCTION DEFINITIONS ///
////////////////////////////////////////////////////////////////////////
/**Function*************************************************************
@@ -53,7 +53,7 @@ Fxu_Matrix * Fxu_CreateMatrix( Fxu_Data_t * pData )
Fxu_Var * pVar;
Fxu_Cube * pCubeFirst, * pCubeNew;
Fxu_Cube * pCube1, * pCube2;
- Vec_Fan_t * vFanins;
+ Vec_Int_t * vFanins;
char * pSopCover;
char * pSopCube;
int * pOrder, nBitsMax;
@@ -69,7 +69,7 @@ Fxu_Matrix * Fxu_CreateMatrix( Fxu_Data_t * pData )
nCubesTotal = 0;
nPairsTotal = 0;
nPairsStore = 0;
- nBitsMax = -1;
+ nBitsMax = -1;
for ( i = 0; i < pData->nNodesOld; i++ )
if ( pSopCover = pData->vSops->pArray[i] )
{
@@ -89,7 +89,7 @@ Fxu_Matrix * Fxu_CreateMatrix( Fxu_Data_t * pData )
return NULL;
}
- if ( nPairsStore > 10000000 )
+ if ( nPairsStore > 50000000 )
{
printf( "The problem is too large to be solved by \"fxu\" (%d cubes and %d cube pairs)\n", nCubesTotal, nPairsStore );
return NULL;
@@ -151,7 +151,7 @@ Fxu_Matrix * Fxu_CreateMatrix( Fxu_Data_t * pData )
pOrder[v] = v;
// reorder the fanins
qsort( (void *)pOrder, nFanins, sizeof(int),(int (*)(const void *, const void *))Fxu_CreateMatrixLitCompare);
- assert( s_pLits[ pOrder[0] ].iFan < s_pLits[ pOrder[nFanins-1] ].iFan );
+ assert( s_pLits[ pOrder[0] ] < s_pLits[ pOrder[nFanins-1] ] );
// create the corresponding cubes in the matrix
pCubeFirst = NULL;
c = 0;
@@ -178,11 +178,26 @@ Fxu_Matrix * Fxu_CreateMatrix( Fxu_Data_t * pData )
// consider the case when cube pairs should be preprocessed
// before adding them to the set of divisors
+// if ( pData->fVerbose )
+// printf( "The total number of cube pairs is %d.\n", nPairsTotal );
+ if ( nPairsTotal > 10000000 )
+ {
+ printf( "The total number of cube pairs of the network is more than 10,000,000.\n" );
+ printf( "Command \"fx\" takes a long time to run in such cases. It is suggested\n" );
+ printf( "that the user changes the network by reducing the size of logic node and\n" );
+ printf( "consequently the number of cube pairs to be processed by this command.\n" );
+ printf( "One way to achieve this is to run the commands \"st; multi -m -F <num>\"\n" );
+ printf( "as a proprocessing step, while selecting <num> as approapriate.\n" );
+ return NULL;
+ }
if ( nPairsTotal > pData->nPairsMax )
- Fxu_PreprocessCubePairs( p, pData->vSops, nPairsTotal, pData->nPairsMax );
+ if ( !Fxu_PreprocessCubePairs( p, pData->vSops, nPairsTotal, pData->nPairsMax ) )
+ return NULL;
+// if ( pData->fVerbose )
+// printf( "Only %d best cube pairs will be used by the fast extract command.\n", pData->nPairsMax );
// add the var pairs to the heap
- Fxu_MatrixComputeSingles( p );
+ Fxu_MatrixComputeSingles( p, pData->fUse0, pData->nSingleMax );
// print stats
if ( pData->fVerbose )
@@ -193,9 +208,8 @@ Fxu_Matrix * Fxu_CreateMatrix( Fxu_Data_t * pData )
p->lVars.nItems, p->lCubes.nItems );
fprintf( stdout, "Lits = %d Density = %.5f%%\n",
p->nEntries, Density );
- fprintf( stdout, "1-cube divisors = %6d. ", p->lSingles.nItems );
- fprintf( stdout, "2-cube divisors = %6d. ", p->nDivsTotal );
- fprintf( stdout, "Cube pairs = %6d.", nPairsTotal );
+ fprintf( stdout, "1-cube divs = %6d. (Total = %6d) ", p->lSingles.nItems, p->nSingleTotal );
+ fprintf( stdout, "2-cube divs = %6d. (Total = %6d)", p->nDivsTotal, nPairsTotal );
fprintf( stdout, "\n" );
}
// Fxu_MatrixPrint( stdout, p );
@@ -214,7 +228,7 @@ Fxu_Matrix * Fxu_CreateMatrix( Fxu_Data_t * pData )
SeeAlso []
***********************************************************************/
-void Fxu_CreateMatrixAddCube( Fxu_Matrix * p, Fxu_Cube * pCube, char * pSopCube, Vec_Fan_t * vFanins, int * pOrder )
+void Fxu_CreateMatrixAddCube( Fxu_Matrix * p, Fxu_Cube * pCube, char * pSopCube, Vec_Int_t * vFanins, int * pOrder )
{
Fxu_Var * pVar;
int Value, i;
@@ -224,12 +238,12 @@ void Fxu_CreateMatrixAddCube( Fxu_Matrix * p, Fxu_Cube * pCube, char * pSopCube,
Value = pSopCube[pOrder[i]];
if ( Value == '0' )
{
- pVar = p->ppVars[ 2 * vFanins->pArray[pOrder[i]].iFan + 1 ]; // CST
+ pVar = p->ppVars[ 2 * vFanins->pArray[pOrder[i]] + 1 ]; // CST
Fxu_MatrixAddLiteral( p, pCube, pVar );
}
else if ( Value == '1' )
{
- pVar = p->ppVars[ 2 * vFanins->pArray[pOrder[i]].iFan ]; // CST
+ pVar = p->ppVars[ 2 * vFanins->pArray[pOrder[i]] ]; // CST
Fxu_MatrixAddLiteral( p, pCube, pVar );
}
}
@@ -409,7 +423,7 @@ Fxu_Cube * Fxu_CreateCoversFirstCube( Fxu_Matrix * p, Fxu_Data_t * pData, int iV
***********************************************************************/
int Fxu_CreateMatrixLitCompare( int * ptrX, int * ptrY )
{
- return s_pLits[*ptrX].iFan - s_pLits[*ptrY].iFan;
+ return s_pLits[*ptrX] - s_pLits[*ptrY];
}
////////////////////////////////////////////////////////////////////////
diff --git a/src/opt/fxu/fxuHeapD.c b/src/opt/fxu/fxuHeapD.c
index 7c123249..c81ad818 100644
--- a/src/opt/fxu/fxuHeapD.c
+++ b/src/opt/fxu/fxuHeapD.c
@@ -38,7 +38,7 @@ static void Fxu_HeapDoubleMoveUp( Fxu_HeapDouble * p, Fxu_Double * pDiv );
static void Fxu_HeapDoubleMoveDn( Fxu_HeapDouble * p, Fxu_Double * pDiv );
////////////////////////////////////////////////////////////////////////
-/// FUNCTION DEFITIONS ///
+/// FUNCTION DEFINITIONS ///
////////////////////////////////////////////////////////////////////////
/**Function*************************************************************
diff --git a/src/opt/fxu/fxuHeapS.c b/src/opt/fxu/fxuHeapS.c
index dbd66055..eaca8363 100644
--- a/src/opt/fxu/fxuHeapS.c
+++ b/src/opt/fxu/fxuHeapS.c
@@ -38,7 +38,7 @@ static void Fxu_HeapSingleMoveUp( Fxu_HeapSingle * p, Fxu_Single * pSingle );
static void Fxu_HeapSingleMoveDn( Fxu_HeapSingle * p, Fxu_Single * pSingle );
////////////////////////////////////////////////////////////////////////
-/// FUNCTION DEFITIONS ///
+/// FUNCTION DEFINITIONS ///
////////////////////////////////////////////////////////////////////////
/**Function*************************************************************
diff --git a/src/opt/fxu/fxuInt.h b/src/opt/fxu/fxuInt.h
index 59b2df6d..ea85cb79 100644
--- a/src/opt/fxu/fxuInt.h
+++ b/src/opt/fxu/fxuInt.h
@@ -23,7 +23,6 @@
/// INCLUDES ///
////////////////////////////////////////////////////////////////////////
-#include "util.h"
#include "extra.h"
#include "vec.h"
@@ -173,6 +172,8 @@ struct FxuMatrix // ~ 30 words
// the single cube divisors
Fxu_ListSingle lSingles; // the linked list of single cube divisors
Fxu_HeapSingle * pHeapSingle; // the heap of variables by the number of literals in the matrix
+ int nWeightLimit;// the limit on weight of single cube divisors collected
+ int nSingleTotal;// the total number of single cube divisors
// storage for cube pairs
Fxu_Pair *** pppPairs;
Fxu_Pair ** ppPairs;
@@ -272,7 +273,7 @@ struct FxuSingle // 7 words
};
////////////////////////////////////////////////////////////////////////
-/// MACRO DEFITIONS ///
+/// MACRO DEFINITIONS ///
////////////////////////////////////////////////////////////////////////
// minimum/maximum
@@ -430,7 +431,7 @@ extern void Fxu_MatrixRingVarsUnmark( Fxu_Matrix * p );
#endif
////////////////////////////////////////////////////////////////////////
-/// FUNCTION DEFITIONS ///
+/// FUNCTION DEFINITIONS ///
////////////////////////////////////////////////////////////////////////
/*===== fxu.c ====================================================*/
@@ -460,7 +461,7 @@ extern void Fxu_PairClearStorage( Fxu_Cube * pCube );
extern Fxu_Pair * Fxu_PairAlloc( Fxu_Matrix * p, Fxu_Cube * pCube1, Fxu_Cube * pCube2 );
extern void Fxu_PairAdd( Fxu_Pair * pPair );
/*===== fxuSingle.c ====================================================*/
-extern void Fxu_MatrixComputeSingles( Fxu_Matrix * p );
+extern void Fxu_MatrixComputeSingles( Fxu_Matrix * p, int fUse0, int nSingleMax );
extern void Fxu_MatrixComputeSinglesOne( Fxu_Matrix * p, Fxu_Var * pVar );
extern int Fxu_SingleCountCoincidence( Fxu_Matrix * p, Fxu_Var * pVar1, Fxu_Var * pVar2 );
/*===== fxuMatrix.c ====================================================*/
@@ -530,8 +531,9 @@ extern int Fxu_HeapSingleReadMaxWeight( Fxu_HeapSingle * p );
extern Fxu_Single * Fxu_HeapSingleReadMax( Fxu_HeapSingle * p );
extern Fxu_Single * Fxu_HeapSingleGetMax( Fxu_HeapSingle * p );
+#endif
+
////////////////////////////////////////////////////////////////////////
/// END OF FILE ///
////////////////////////////////////////////////////////////////////////
-#endif
diff --git a/src/opt/fxu/fxuList.c b/src/opt/fxu/fxuList.c
index bb081d80..52995804 100644
--- a/src/opt/fxu/fxuList.c
+++ b/src/opt/fxu/fxuList.c
@@ -23,7 +23,7 @@
////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////
-/// FUNCTION DEFITIONS ///
+/// FUNCTION DEFINITIONS ///
////////////////////////////////////////////////////////////////////////
// matrix -> var
diff --git a/src/opt/fxu/fxuMatrix.c b/src/opt/fxu/fxuMatrix.c
index 503ba2f1..93ec7b90 100644
--- a/src/opt/fxu/fxuMatrix.c
+++ b/src/opt/fxu/fxuMatrix.c
@@ -25,7 +25,7 @@
extern unsigned int Cudd_Prime( unsigned int p );
////////////////////////////////////////////////////////////////////////
-/// FUNCTION DEFITIONS ///
+/// FUNCTION DEFINITIONS ///
////////////////////////////////////////////////////////////////////////
/**Function*************************************************************
@@ -130,7 +130,7 @@ void Fxu_MatrixDelete( Fxu_Matrix * p )
MEM_FREE_FXU( p, Fxu_Var, 1, pVar );
}
#else
- Extra_MmFixedStop( p->pMemMan, 0 );
+ Extra_MmFixedStop( p->pMemMan );
#endif
Vec_PtrFree( p->vPairs );
diff --git a/src/opt/fxu/fxuPair.c b/src/opt/fxu/fxuPair.c
index be6be5e9..3c031ce8 100644
--- a/src/opt/fxu/fxuPair.c
+++ b/src/opt/fxu/fxuPair.c
@@ -55,7 +55,7 @@ static s_Primes[MAX_PRIMES] =
};
////////////////////////////////////////////////////////////////////////
-/// FUNCTION DEFITIONS ///
+/// FUNCTION DEFINITIONS ///
////////////////////////////////////////////////////////////////////////
/**Function*************************************************************
diff --git a/src/opt/fxu/fxuPrint.c b/src/opt/fxu/fxuPrint.c
index 2d25c0e9..232b109a 100644
--- a/src/opt/fxu/fxuPrint.c
+++ b/src/opt/fxu/fxuPrint.c
@@ -23,7 +23,7 @@
////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////
-/// FUNCTION DEFITIONS ///
+/// FUNCTION DEFINITIONS ///
////////////////////////////////////////////////////////////////////////
/**Function*************************************************************
diff --git a/src/opt/fxu/fxuReduce.c b/src/opt/fxu/fxuReduce.c
index 652d807b..0ab8a157 100644
--- a/src/opt/fxu/fxuReduce.c
+++ b/src/opt/fxu/fxuReduce.c
@@ -27,7 +27,7 @@
static int Fxu_CountPairDiffs( char * pCover, unsigned char pDiffs[] );
////////////////////////////////////////////////////////////////////////
-/// FUNCTION DEFITIONS ///
+/// FUNCTION DEFINITIONS ///
////////////////////////////////////////////////////////////////////////
/**Function*************************************************************
@@ -90,6 +90,16 @@ int Fxu_PreprocessCubePairs( Fxu_Matrix * p, Vec_Ptr_t * vCovers, int nPairsTota
pnPairCounters[ pnLitsDiff[k] ]++;
// determine what pairs to take starting from the lower
// so that there would be exactly pPairsMax pairs
+ if ( pnPairCounters[0] != 0 )
+ {
+ printf( "The SOPs of the nodes are not cube-free. Run \"bdd; sop\" before \"fx\".\n" );
+ return 0;
+ }
+ if ( pnPairCounters[1] != 0 )
+ {
+ printf( "The SOPs of the nodes are not SCC-free. Run \"bdd; sop\" before \"fx\".\n" );
+ return 0;
+ }
assert( pnPairCounters[0] == 0 ); // otherwise, covers are not dup-free
assert( pnPairCounters[1] == 0 ); // otherwise, covers are not SCC-free
nSum = 0;
diff --git a/src/opt/fxu/fxuSelect.c b/src/opt/fxu/fxuSelect.c
index b56407a9..b9265487 100644
--- a/src/opt/fxu/fxuSelect.c
+++ b/src/opt/fxu/fxuSelect.c
@@ -37,7 +37,7 @@ void Fxu_MatrixGetDoubleVars( Fxu_Matrix * p, Fxu_Double * pDouble,
////////////////////////////////////////////////////////////////////////
-/// FUNCTION DEFITIONS ///
+/// FUNCTION DEFINITIONS ///
////////////////////////////////////////////////////////////////////////
/**Function*************************************************************
diff --git a/src/opt/fxu/fxuSingle.c b/src/opt/fxu/fxuSingle.c
index 5af5c341..73d9a76c 100644
--- a/src/opt/fxu/fxuSingle.c
+++ b/src/opt/fxu/fxuSingle.c
@@ -17,13 +17,16 @@
***********************************************************************/
#include "fxuInt.h"
+#include "vec.h"
////////////////////////////////////////////////////////////////////////
/// DECLARATIONS ///
////////////////////////////////////////////////////////////////////////
+static void Fxu_MatrixComputeSinglesOneCollect( Fxu_Matrix * p, Fxu_Var * pVar, Vec_Ptr_t * vSingles );
+
////////////////////////////////////////////////////////////////////////
-/// FUNCTION DEFITIONS ///
+/// FUNCTION DEFINITIONS ///
////////////////////////////////////////////////////////////////////////
/**Function*************************************************************
@@ -38,12 +41,130 @@
SeeAlso []
***********************************************************************/
-void Fxu_MatrixComputeSingles( Fxu_Matrix * p )
+void Fxu_MatrixComputeSingles( Fxu_Matrix * p, int fUse0, int nSingleMax )
{
Fxu_Var * pVar;
- // iterate through the columns in the matrix
+ Vec_Ptr_t * vSingles;
+ int i, k;
+ // set the weight limit
+ p->nWeightLimit = 1 - fUse0;
+ // iterate through columns in the matrix and collect single-cube divisors
+ vSingles = Vec_PtrAlloc( 10000 );
Fxu_MatrixForEachVariable( p, pVar )
- Fxu_MatrixComputeSinglesOne( p, pVar );
+ Fxu_MatrixComputeSinglesOneCollect( p, pVar, vSingles );
+ p->nSingleTotal = Vec_PtrSize(vSingles) / 3;
+ // check if divisors should be filtered
+ if ( Vec_PtrSize(vSingles) > nSingleMax )
+ {
+ int * pWeigtCounts, nDivCount, Weight, i, c;;
+ assert( Vec_PtrSize(vSingles) % 3 == 0 );
+ // count how many divisors have the given weight
+ pWeigtCounts = ALLOC( int, 1000 );
+ memset( pWeigtCounts, 0, sizeof(int) * 1000 );
+ for ( i = 2; i < Vec_PtrSize(vSingles); i += 3 )
+ {
+ Weight = (int)Vec_PtrEntry(vSingles, i);
+ if ( Weight >= 999 )
+ pWeigtCounts[999]++;
+ else
+ pWeigtCounts[Weight]++;
+ }
+ // select the bound on the weight (above this bound, singles will be included)
+ nDivCount = 0;
+ for ( c = 999; c >= 0; c-- )
+ {
+ nDivCount += pWeigtCounts[c];
+ if ( nDivCount >= nSingleMax )
+ break;
+ }
+ free( pWeigtCounts );
+ // collect singles with the given costs
+ k = 0;
+ for ( i = 2; i < Vec_PtrSize(vSingles); i += 3 )
+ {
+ Weight = (int)Vec_PtrEntry(vSingles, i);
+ if ( Weight < c )
+ continue;
+ Vec_PtrWriteEntry( vSingles, k++, Vec_PtrEntry(vSingles, i-2) );
+ Vec_PtrWriteEntry( vSingles, k++, Vec_PtrEntry(vSingles, i-1) );
+ Vec_PtrWriteEntry( vSingles, k++, Vec_PtrEntry(vSingles, i) );
+ if ( k/3 == nSingleMax )
+ break;
+ }
+ Vec_PtrShrink( vSingles, k );
+ // adjust the weight limit
+ p->nWeightLimit = c;
+ }
+ // collect the selected divisors
+ assert( Vec_PtrSize(vSingles) % 3 == 0 );
+ for ( i = 0; i < Vec_PtrSize(vSingles); i += 3 )
+ {
+ Fxu_MatrixAddSingle( p,
+ Vec_PtrEntry(vSingles,i),
+ Vec_PtrEntry(vSingles,i+1),
+ (int)Vec_PtrEntry(vSingles,i+2) );
+ }
+ Vec_PtrFree( vSingles );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Adds the single-cube divisors associated with a new column.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Fxu_MatrixComputeSinglesOneCollect( Fxu_Matrix * p, Fxu_Var * pVar, Vec_Ptr_t * vSingles )
+{
+ Fxu_Lit * pLitV, * pLitH;
+ Fxu_Var * pVar2;
+ int Coin;
+ int WeightCur;
+
+ // start collecting the affected vars
+ Fxu_MatrixRingVarsStart( p );
+ // go through all the literals of this variable
+ for ( pLitV = pVar->lLits.pHead; pLitV; pLitV = pLitV->pVNext )
+ // for this literal, go through all the horizontal literals
+ for ( pLitH = pLitV->pHPrev; pLitH; pLitH = pLitH->pHPrev )
+ {
+ // get another variable
+ pVar2 = pLitH->pVar;
+ // skip the var if it is already used
+ if ( pVar2->pOrder )
+ continue;
+ // skip the var if it belongs to the same node
+// if ( pValue2Node[pVar->iVar] == pValue2Node[pVar2->iVar] )
+// continue;
+ // collect the var
+ Fxu_MatrixRingVarsAdd( p, pVar2 );
+ }
+ // stop collecting the selected vars
+ Fxu_MatrixRingVarsStop( p );
+
+ // iterate through the selected vars
+ Fxu_MatrixForEachVarInRing( p, pVar2 )
+ {
+ // count the coincidence
+ Coin = Fxu_SingleCountCoincidence( p, pVar2, pVar );
+ assert( Coin > 0 );
+ // get the new weight
+ WeightCur = Coin - 2;
+ // peformance fix (August 24, 2007)
+ if ( WeightCur >= p->nWeightLimit )
+ {
+ Vec_PtrPush( vSingles, pVar2 );
+ Vec_PtrPush( vSingles, pVar );
+ Vec_PtrPush( vSingles, (void *)WeightCur );
+ }
+ }
+
+ // unmark the vars
+ Fxu_MatrixRingVarsUnmark( p );
}
/**Function*************************************************************
@@ -59,12 +180,9 @@ void Fxu_MatrixComputeSingles( Fxu_Matrix * p )
***********************************************************************/
void Fxu_MatrixComputeSinglesOne( Fxu_Matrix * p, Fxu_Var * pVar )
{
-// int * pValue2Node = p->pValue2Node;
Fxu_Lit * pLitV, * pLitH;
Fxu_Var * pVar2;
int Coin;
-// int CounterAll;
-// int CounterTest;
int WeightCur;
// start collecting the affected vars
@@ -76,7 +194,6 @@ void Fxu_MatrixComputeSinglesOne( Fxu_Matrix * p, Fxu_Var * pVar )
{
// get another variable
pVar2 = pLitH->pVar;
-// CounterAll++;
// skip the var if it is already used
if ( pVar2->pOrder )
continue;
@@ -92,16 +209,17 @@ void Fxu_MatrixComputeSinglesOne( Fxu_Matrix * p, Fxu_Var * pVar )
// iterate through the selected vars
Fxu_MatrixForEachVarInRing( p, pVar2 )
{
-// CounterTest++;
// count the coincidence
Coin = Fxu_SingleCountCoincidence( p, pVar2, pVar );
assert( Coin > 0 );
// get the new weight
WeightCur = Coin - 2;
- if ( WeightCur >= 0 )
+ // peformance fix (August 24, 2007)
+// if ( WeightCur >= 0 )
+// Fxu_MatrixAddSingle( p, pVar2, pVar, WeightCur );
+ if ( WeightCur >= p->nWeightLimit )
Fxu_MatrixAddSingle( p, pVar2, pVar, WeightCur );
}
-
// unmark the vars
Fxu_MatrixRingVarsUnmark( p );
}
diff --git a/src/opt/fxu/fxuUpdate.c b/src/opt/fxu/fxuUpdate.c
index 4006bc76..274f79f6 100644
--- a/src/opt/fxu/fxuUpdate.c
+++ b/src/opt/fxu/fxuUpdate.c
@@ -37,7 +37,7 @@ static void Fxu_UpdateCleanOldSingles( Fxu_Matrix * p );
static void Fxu_UpdateAddNewSingles( Fxu_Matrix * p, Fxu_Var * pVar );
////////////////////////////////////////////////////////////////////////
-/// FUNCTION DEFITIONS ///
+/// FUNCTION DEFINITIONS ///
////////////////////////////////////////////////////////////////////////
/**Function*************************************************************
@@ -757,12 +757,14 @@ void Fxu_UpdateCleanOldSingles( Fxu_Matrix * p )
{
Fxu_Single * pSingle, * pSingle2;
int WeightNew;
+ int Counter = 0;
Fxu_MatrixForEachSingleSafe( p, pSingle, pSingle2 )
{
// if at least one of the variables is marked, recalculate
if ( pSingle->pVar1->pOrder || pSingle->pVar2->pOrder )
{
+ Counter++;
// get the new weight
WeightNew = -2 + Fxu_SingleCountCoincidence( p, pSingle->pVar1, pSingle->pVar2 );
if ( WeightNew >= 0 )
@@ -778,6 +780,7 @@ void Fxu_UpdateCleanOldSingles( Fxu_Matrix * p )
}
}
}
+// printf( "Called procedure %d times.\n", Counter );
}
/**Function*************************************************************
diff --git a/src/opt/lpk/lpk.h b/src/opt/lpk/lpk.h
new file mode 100644
index 00000000..2a642db2
--- /dev/null
+++ b/src/opt/lpk/lpk.h
@@ -0,0 +1,84 @@
+/**CFile****************************************************************
+
+ FileName [lpk.h]
+
+ SystemName [ABC: Logic synthesis and verification system.]
+
+ PackageName [Fast Boolean matching for LUT structures.]
+
+ Synopsis [External declarations.]
+
+ Author [Alan Mishchenko]
+
+ Affiliation [UC Berkeley]
+
+ Date [Ver. 1.0. Started - April 28, 2007.]
+
+ Revision [$Id: lpk.h,v 1.00 2007/04/28 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#ifndef __LPK_H__
+#define __LPK_H__
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+////////////////////////////////////////////////////////////////////////
+/// INCLUDES ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+/// PARAMETERS ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+/// BASIC TYPES ///
+////////////////////////////////////////////////////////////////////////
+
+typedef struct Lpk_Par_t_ Lpk_Par_t;
+struct Lpk_Par_t_
+{
+ // user-controlled parameters
+ int nLutsMax; // (N) the maximum number of LUTs in the structure
+ int nLutsOver; // (Q) the maximum number of LUTs not in the MFFC
+ int nVarsShared; // (S) the maximum number of shared variables (crossbars)
+ int nGrowthLevel; // (L) the maximum increase in the node level after resynthesis
+ int fSatur; // iterate till saturation
+ int fZeroCost; // accept zero-cost replacements
+ int fFirst; // use root node and first cut only
+ int fOldAlgo; // use old algorithm
+ int fVerbose; // the verbosiness flag
+ int fVeryVerbose; // additional verbose info printout
+ // internal parameters
+ int nLutSize; // (K) the LUT size (determined by the input network)
+ int nVarsMax; // (V) the largest number of variables: V = N * (K-1) + 1
+};
+
+////////////////////////////////////////////////////////////////////////
+/// MACRO DEFINITIONS ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+/// ITERATORS ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+/// FUNCTION DECLARATIONS ///
+////////////////////////////////////////////////////////////////////////
+
+/*=== lpkCore.c ========================================================*/
+extern int Lpk_Resynthesize( Abc_Ntk_t * pNtk, Lpk_Par_t * pPars );
+
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
+
+////////////////////////////////////////////////////////////////////////
+/// END OF FILE ///
+////////////////////////////////////////////////////////////////////////
+
diff --git a/src/opt/lpk/lpkAbcDec.c b/src/opt/lpk/lpkAbcDec.c
new file mode 100644
index 00000000..aa2d4bc0
--- /dev/null
+++ b/src/opt/lpk/lpkAbcDec.c
@@ -0,0 +1,290 @@
+/**CFile****************************************************************
+
+ FileName [lpkAbcDec.c]
+
+ SystemName [ABC: Logic synthesis and verification system.]
+
+ PackageName [Fast Boolean matching for LUT structures.]
+
+ Synopsis [The new core procedure.]
+
+ Author [Alan Mishchenko]
+
+ Affiliation [UC Berkeley]
+
+ Date [Ver. 1.0. Started - April 28, 2007.]
+
+ Revision [$Id: lpkAbcDec.c,v 1.00 2007/04/28 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "lpkInt.h"
+
+////////////////////////////////////////////////////////////////////////
+/// DECLARATIONS ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+/// FUNCTION DEFINITIONS ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+ Synopsis [Implements the function.]
+
+ Description [Returns the node implementing this function.]
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Abc_Obj_t * Lpk_ImplementFun( Lpk_Man_t * pMan, Abc_Ntk_t * pNtk, Vec_Ptr_t * vLeaves, Lpk_Fun_t * p )
+{
+ extern Hop_Obj_t * Kit_TruthToHop( Hop_Man_t * pMan, unsigned * pTruth, int nVars, Vec_Int_t * vMemory );
+ unsigned * pTruth;
+ Abc_Obj_t * pObjNew;
+ int i;
+ if ( p->fMark )
+ pMan->nMuxes++;
+ else
+ pMan->nDsds++;
+ // create the new node
+ pObjNew = Abc_NtkCreateNode( pNtk );
+ for ( i = 0; i < (int)p->nVars; i++ )
+ Abc_ObjAddFanin( pObjNew, Abc_ObjRegular(Vec_PtrEntry(vLeaves, p->pFanins[i])) );
+ Abc_ObjSetLevel( pObjNew, Abc_ObjLevelNew(pObjNew) );
+ // assign the node's function
+ pTruth = Lpk_FunTruth(p, 0);
+ if ( p->nVars == 0 )
+ {
+ pObjNew->pData = Hop_NotCond( Hop_ManConst1(pNtk->pManFunc), !(pTruth[0] & 1) );
+ return pObjNew;
+ }
+ if ( p->nVars == 1 )
+ {
+ pObjNew->pData = Hop_NotCond( Hop_ManPi(pNtk->pManFunc, 0), (pTruth[0] & 1) );
+ return pObjNew;
+ }
+ // create the logic function
+ pObjNew->pData = Kit_TruthToHop( pNtk->pManFunc, pTruth, p->nVars, NULL );
+ return pObjNew;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Implements the function.]
+
+ Description [Returns the node implementing this function.]
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Abc_Obj_t * Lpk_Implement_rec( Lpk_Man_t * pMan, Abc_Ntk_t * pNtk, Vec_Ptr_t * vLeaves, Lpk_Fun_t * pFun )
+{
+ Abc_Obj_t * pFanin, * pRes;
+ int i;
+ // prepare the leaves of the function
+ for ( i = 0; i < (int)pFun->nVars; i++ )
+ {
+ pFanin = Vec_PtrEntry( vLeaves, pFun->pFanins[i] );
+ if ( !Abc_ObjIsComplement(pFanin) )
+ Lpk_Implement_rec( pMan, pNtk, vLeaves, (Lpk_Fun_t *)pFanin );
+ pFanin = Vec_PtrEntry( vLeaves, pFun->pFanins[i] );
+ assert( Abc_ObjIsComplement(pFanin) );
+ }
+ // construct the function
+ pRes = Lpk_ImplementFun( pMan, pNtk, vLeaves, pFun );
+ // replace the function
+ Vec_PtrWriteEntry( vLeaves, pFun->Id, Abc_ObjNot(pRes) );
+ Lpk_FunFree( pFun );
+ return pRes;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Implements the function.]
+
+ Description [Returns the node implementing this function.]
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Abc_Obj_t * Lpk_Implement( Lpk_Man_t * pMan, Abc_Ntk_t * pNtk, Vec_Ptr_t * vLeaves, int nLeavesOld )
+{
+ Abc_Obj_t * pFanin, * pRes;
+ int i;
+ assert( nLeavesOld < Vec_PtrSize(vLeaves) );
+ // mark implemented nodes
+ Vec_PtrForEachEntryStop( vLeaves, pFanin, i, nLeavesOld )
+ Vec_PtrWriteEntry( vLeaves, i, Abc_ObjNot(pFanin) );
+ // recursively construct starting from the first entry
+ pRes = Lpk_Implement_rec( pMan, pNtk, vLeaves, Vec_PtrEntry( vLeaves, nLeavesOld ) );
+ Vec_PtrShrink( vLeaves, nLeavesOld );
+ return pRes;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Decomposes the function using recursive MUX decomposition.]
+
+ Description [Returns the ID of the top-most decomposition node
+ implementing this function, or 0 if there is no decomposition satisfying
+ the constraints on area and delay.]
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Lpk_Decompose_rec( Lpk_Man_t * pMan, Lpk_Fun_t * p )
+{
+ static Lpk_Res_t Res0, * pRes0 = &Res0;
+ Lpk_Res_t * pResMux, * pResDsd;
+ Lpk_Fun_t * p2;
+ int clk;
+
+ // is only called for non-trivial blocks
+ assert( p->nLutK >= 3 && p->nLutK <= 6 );
+ assert( p->nVars > p->nLutK );
+ // skip if area bound is exceeded
+ if ( Lpk_LutNumLuts(p->nVars, p->nLutK) > (int)p->nAreaLim )
+ return 0;
+ // skip if delay bound is exceeded
+ if ( Lpk_SuppDelay(p->uSupp, p->pDelays) > (int)p->nDelayLim )
+ return 0;
+
+ // compute supports if needed
+ if ( !p->fSupports )
+ Lpk_FunComputeCofSupps( p );
+
+ // check DSD decomposition
+clk = clock();
+ pResDsd = Lpk_DsdAnalize( pMan, p, pMan->pPars->nVarsShared );
+pMan->timeEvalDsdAn += clock() - clk;
+ if ( pResDsd && (pResDsd->nBSVars == (int)p->nLutK || pResDsd->nBSVars == (int)p->nLutK - 1) &&
+ pResDsd->AreaEst <= (int)p->nAreaLim && pResDsd->DelayEst <= (int)p->nDelayLim )
+ {
+clk = clock();
+ p2 = Lpk_DsdSplit( pMan, p, pResDsd->pCofVars, pResDsd->nCofVars, pResDsd->BSVars );
+pMan->timeEvalDsdSp += clock() - clk;
+ assert( p2->nVars <= (int)p->nLutK );
+ if ( p->nVars > p->nLutK && !Lpk_Decompose_rec( pMan, p ) )
+ return 0;
+ return 1;
+ }
+
+ // check MUX decomposition
+clk = clock();
+ pResMux = Lpk_MuxAnalize( pMan, p );
+pMan->timeEvalMuxAn += clock() - clk;
+// pResMux = NULL;
+ assert( !pResMux || (pResMux->DelayEst <= (int)p->nDelayLim && pResMux->AreaEst <= (int)p->nAreaLim) );
+ // accept MUX decomposition if it is "good"
+ if ( pResMux && pResMux->nSuppSizeS <= (int)p->nLutK && pResMux->nSuppSizeL <= (int)p->nLutK )
+ pResDsd = NULL;
+ else if ( pResMux && pResDsd )
+ {
+ // compare two decompositions
+ if ( pResMux->AreaEst < pResDsd->AreaEst ||
+ (pResMux->AreaEst == pResDsd->AreaEst && pResMux->nSuppSizeL < pResDsd->nSuppSizeL) ||
+ (pResMux->AreaEst == pResDsd->AreaEst && pResMux->nSuppSizeL == pResDsd->nSuppSizeL && pResMux->DelayEst < pResDsd->DelayEst) )
+ pResDsd = NULL;
+ else
+ pResMux = NULL;
+ }
+ assert( pResMux == NULL || pResDsd == NULL );
+ if ( pResMux )
+ {
+clk = clock();
+ p2 = Lpk_MuxSplit( pMan, p, pResMux->Variable, pResMux->Polarity );
+pMan->timeEvalMuxSp += clock() - clk;
+ if ( p2->nVars > p->nLutK && !Lpk_Decompose_rec( pMan, p2 ) )
+ return 0;
+ if ( p->nVars > p->nLutK && !Lpk_Decompose_rec( pMan, p ) )
+ return 0;
+ return 1;
+ }
+ if ( pResDsd )
+ {
+clk = clock();
+ p2 = Lpk_DsdSplit( pMan, p, pResDsd->pCofVars, pResDsd->nCofVars, pResDsd->BSVars );
+pMan->timeEvalDsdSp += clock() - clk;
+ assert( p2->nVars <= (int)p->nLutK );
+ if ( p->nVars > p->nLutK && !Lpk_Decompose_rec( pMan, p ) )
+ return 0;
+ return 1;
+ }
+ return 0;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Removes decomposed nodes from the array of fanins.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Lpk_DecomposeClean( Vec_Ptr_t * vLeaves, int nLeavesOld )
+{
+ Lpk_Fun_t * pFunc;
+ int i;
+ Vec_PtrForEachEntryStart( vLeaves, pFunc, i, nLeavesOld )
+ Lpk_FunFree( pFunc );
+ Vec_PtrShrink( vLeaves, nLeavesOld );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Decomposes the function using recursive MUX decomposition.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Abc_Obj_t * Lpk_Decompose( Lpk_Man_t * p, Abc_Ntk_t * pNtk, Vec_Ptr_t * vLeaves, unsigned * pTruth, unsigned * puSupps, int nLutK, int AreaLim, int DelayLim )
+{
+ Lpk_Fun_t * pFun;
+ Abc_Obj_t * pObjNew = NULL;
+ int nLeaves = Vec_PtrSize( vLeaves );
+ pFun = Lpk_FunCreate( pNtk, vLeaves, pTruth, nLutK, AreaLim, DelayLim );
+ if ( puSupps[0] || puSupps[1] )
+ {
+/*
+ int i;
+ Lpk_FunComputeCofSupps( pFun );
+ for ( i = 0; i < nLeaves; i++ )
+ {
+ assert( pFun->puSupps[2*i+0] == puSupps[2*i+0] );
+ assert( pFun->puSupps[2*i+1] == puSupps[2*i+1] );
+ }
+*/
+ memcpy( pFun->puSupps, puSupps, sizeof(unsigned) * 2 * nLeaves );
+ pFun->fSupports = 1;
+ }
+ Lpk_FunSuppMinimize( pFun );
+ if ( pFun->nVars <= pFun->nLutK )
+ pObjNew = Lpk_ImplementFun( p, pNtk, vLeaves, pFun );
+ else if ( Lpk_Decompose_rec(p, pFun) )
+ pObjNew = Lpk_Implement( p, pNtk, vLeaves, nLeaves );
+ Lpk_DecomposeClean( vLeaves, nLeaves );
+ return pObjNew;
+}
+
+
+////////////////////////////////////////////////////////////////////////
+/// END OF FILE ///
+////////////////////////////////////////////////////////////////////////
+
+
diff --git a/src/opt/lpk/lpkAbcDsd.c b/src/opt/lpk/lpkAbcDsd.c
new file mode 100644
index 00000000..f4095914
--- /dev/null
+++ b/src/opt/lpk/lpkAbcDsd.c
@@ -0,0 +1,603 @@
+/**CFile****************************************************************
+
+ FileName [lpkAbcDsd.c]
+
+ SystemName [ABC: Logic synthesis and verification system.]
+
+ PackageName [Fast Boolean matching for LUT structures.]
+
+ Synopsis [LUT-decomposition based on recursive DSD.]
+
+ Author [Alan Mishchenko]
+
+ Affiliation [UC Berkeley]
+
+ Date [Ver. 1.0. Started - April 28, 2007.]
+
+ Revision [$Id: lpkAbcDsd.c,v 1.00 2007/04/28 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "lpkInt.h"
+
+////////////////////////////////////////////////////////////////////////
+/// DECLARATIONS ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+/// FUNCTION DEFINITIONS ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+ Synopsis [Cofactors TTs w.r.t. all vars and finds the best var.]
+
+ Description [The best variable is the variable with the minimum
+ sum total of the support sizes of all truth tables. This procedure
+ computes and returns cofactors w.r.t. the best variable.]
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Lpk_FunComputeMinSuppSizeVar( Lpk_Fun_t * p, unsigned ** ppTruths, int nTruths, unsigned ** ppCofs, unsigned uNonDecSupp )
+{
+ int i, Var, VarBest, nSuppSize0, nSuppSize1, nSuppTotalMin, nSuppTotalCur, nSuppMaxMin, nSuppMaxCur;
+ assert( nTruths > 0 );
+ VarBest = -1;
+ Lpk_SuppForEachVar( p->uSupp, Var )
+ {
+ if ( (uNonDecSupp & (1 << Var)) == 0 )
+ continue;
+ nSuppMaxCur = 0;
+ nSuppTotalCur = 0;
+ for ( i = 0; i < nTruths; i++ )
+ {
+ if ( nTruths == 1 )
+ {
+ nSuppSize0 = Kit_WordCountOnes( p->puSupps[2*Var+0] );
+ nSuppSize1 = Kit_WordCountOnes( p->puSupps[2*Var+1] );
+ }
+ else
+ {
+ Kit_TruthCofactor0New( ppCofs[2*i+0], ppTruths[i], p->nVars, Var );
+ Kit_TruthCofactor1New( ppCofs[2*i+1], ppTruths[i], p->nVars, Var );
+ nSuppSize0 = Kit_TruthSupportSize( ppCofs[2*i+0], p->nVars );
+ nSuppSize1 = Kit_TruthSupportSize( ppCofs[2*i+1], p->nVars );
+ }
+ nSuppMaxCur = ABC_MAX( nSuppMaxCur, nSuppSize0 );
+ nSuppMaxCur = ABC_MAX( nSuppMaxCur, nSuppSize1 );
+ nSuppTotalCur += nSuppSize0 + nSuppSize1;
+ }
+ if ( VarBest == -1 || nSuppMaxMin > nSuppMaxCur ||
+ (nSuppMaxMin == nSuppMaxCur && nSuppTotalMin > nSuppTotalCur) )
+ {
+ VarBest = Var;
+ nSuppMaxMin = nSuppMaxCur;
+ nSuppTotalMin = nSuppTotalCur;
+ }
+ }
+ // recompute cofactors for the best var
+ for ( i = 0; i < nTruths; i++ )
+ {
+ Kit_TruthCofactor0New( ppCofs[2*i+0], ppTruths[i], p->nVars, VarBest );
+ Kit_TruthCofactor1New( ppCofs[2*i+1], ppTruths[i], p->nVars, VarBest );
+ }
+ return VarBest;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Recursively computes decomposable subsets.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+unsigned Lpk_ComputeBoundSets_rec( Kit_DsdNtk_t * p, int iLit, Vec_Int_t * vSets, int nSizeMax )
+{
+ unsigned i, iLitFanin, uSupport, uSuppCur;
+ Kit_DsdObj_t * pObj;
+ // consider the case of simple gate
+ pObj = Kit_DsdNtkObj( p, Kit_DsdLit2Var(iLit) );
+ if ( pObj == NULL )
+ return (1 << Kit_DsdLit2Var(iLit));
+ if ( pObj->Type == KIT_DSD_AND || pObj->Type == KIT_DSD_XOR )
+ {
+ unsigned uSupps[16], Limit, s;
+ uSupport = 0;
+ Kit_DsdObjForEachFanin( p, pObj, iLitFanin, i )
+ {
+ uSupps[i] = Lpk_ComputeBoundSets_rec( p, iLitFanin, vSets, nSizeMax );
+ uSupport |= uSupps[i];
+ }
+ // create all subsets, except empty and full
+ Limit = (1 << pObj->nFans) - 1;
+ for ( s = 1; s < Limit; s++ )
+ {
+ uSuppCur = 0;
+ for ( i = 0; i < pObj->nFans; i++ )
+ if ( s & (1 << i) )
+ uSuppCur |= uSupps[i];
+ if ( Kit_WordCountOnes(uSuppCur) <= nSizeMax )
+ Vec_IntPush( vSets, uSuppCur );
+ }
+ return uSupport;
+ }
+ assert( pObj->Type == KIT_DSD_PRIME );
+ // get the cumulative support of all fanins
+ uSupport = 0;
+ Kit_DsdObjForEachFanin( p, pObj, iLitFanin, i )
+ {
+ uSuppCur = Lpk_ComputeBoundSets_rec( p, iLitFanin, vSets, nSizeMax );
+ uSupport |= uSuppCur;
+ if ( Kit_WordCountOnes(uSuppCur) <= nSizeMax )
+ Vec_IntPush( vSets, uSuppCur );
+ }
+ return uSupport;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Computes the set of subsets of decomposable variables.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Vec_Int_t * Lpk_ComputeBoundSets( Kit_DsdNtk_t * p, int nSizeMax )
+{
+ Vec_Int_t * vSets;
+ unsigned uSupport, Entry;
+ int Number, i;
+ assert( p->nVars <= 16 );
+ vSets = Vec_IntAlloc( 100 );
+ Vec_IntPush( vSets, 0 );
+ if ( Kit_DsdNtkRoot(p)->Type == KIT_DSD_CONST1 )
+ return vSets;
+ if ( Kit_DsdNtkRoot(p)->Type == KIT_DSD_VAR )
+ {
+ uSupport = ( 1 << Kit_DsdLit2Var(Kit_DsdNtkRoot(p)->pFans[0]) );
+ if ( Kit_WordCountOnes(uSupport) <= nSizeMax )
+ Vec_IntPush( vSets, uSupport );
+ return vSets;
+ }
+ uSupport = Lpk_ComputeBoundSets_rec( p, p->Root, vSets, nSizeMax );
+ assert( (uSupport & 0xFFFF0000) == 0 );
+ // add the total support of the network
+ if ( Kit_WordCountOnes(uSupport) <= nSizeMax )
+ Vec_IntPush( vSets, uSupport );
+ // set the remaining variables
+ Vec_IntForEachEntry( vSets, Number, i )
+ {
+ Entry = Number;
+ Vec_IntWriteEntry( vSets, i, Entry | ((uSupport & ~Entry) << 16) );
+ }
+ return vSets;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Prints the sets of subsets.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+static void Lpk_PrintSetOne( int uSupport )
+{
+ unsigned k;
+ for ( k = 0; k < 16; k++ )
+ if ( uSupport & (1<<k) )
+ printf( "%c", 'a'+k );
+ printf( " " );
+}
+/**Function*************************************************************
+
+ Synopsis [Prints the sets of subsets.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+static void Lpk_PrintSets( Vec_Int_t * vSets )
+{
+ unsigned uSupport;
+ int Number, i;
+ printf( "Subsets(%d): ", Vec_IntSize(vSets) );
+ Vec_IntForEachEntry( vSets, Number, i )
+ {
+ uSupport = Number;
+ Lpk_PrintSetOne( uSupport );
+ }
+ printf( "\n" );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Merges two bound sets.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Vec_Int_t * Lpk_MergeBoundSets( Vec_Int_t * vSets0, Vec_Int_t * vSets1, int nSizeMax )
+{
+ Vec_Int_t * vSets;
+ int Entry0, Entry1, Entry;
+ int i, k;
+ vSets = Vec_IntAlloc( 100 );
+ Vec_IntForEachEntry( vSets0, Entry0, i )
+ Vec_IntForEachEntry( vSets1, Entry1, k )
+ {
+ Entry = Entry0 | Entry1;
+ if ( (Entry & (Entry >> 16)) )
+ continue;
+ if ( Kit_WordCountOnes(Entry & 0xffff) <= nSizeMax )
+ Vec_IntPush( vSets, Entry );
+ }
+ return vSets;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Performs DSD-based decomposition of the function.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Lpk_FunCompareBoundSets( Lpk_Fun_t * p, Vec_Int_t * vBSets, int nCofDepth, unsigned uNonDecSupp, unsigned uLateArrSupp, Lpk_Res_t * pRes )
+{
+ int fVerbose = 0;
+ unsigned uBoundSet;
+ int i, nVarsBS, nVarsRem, Delay, Area;
+
+ // compare the resulting boundsets
+ memset( pRes, 0, sizeof(Lpk_Res_t) );
+ Vec_IntForEachEntry( vBSets, uBoundSet, i )
+ {
+ if ( (uBoundSet & 0xFFFF) == 0 ) // skip empty boundset
+ continue;
+ if ( (uBoundSet & uNonDecSupp) == 0 ) // skip those boundsets that are not in the domain of interest
+ continue;
+ if ( (uBoundSet & uLateArrSupp) ) // skip those boundsets that are late arriving
+ continue;
+if ( fVerbose )
+Lpk_PrintSetOne( uBoundSet );
+ assert( (uBoundSet & (uBoundSet >> 16)) == 0 );
+ nVarsBS = Kit_WordCountOnes( uBoundSet & 0xFFFF );
+ if ( nVarsBS == 1 )
+ continue;
+ assert( nVarsBS <= (int)p->nLutK - nCofDepth );
+ nVarsRem = p->nVars - nVarsBS + 1;
+ Area = 1 + Lpk_LutNumLuts( nVarsRem, p->nLutK );
+ Delay = 1 + Lpk_SuppDelay( uBoundSet & 0xFFFF, p->pDelays );
+if ( fVerbose )
+printf( "area = %d limit = %d delay = %d limit = %d\n", Area, (int)p->nAreaLim, Delay, (int)p->nDelayLim );
+ if ( Area > (int)p->nAreaLim || Delay > (int)p->nDelayLim )
+ continue;
+ if ( pRes->BSVars == 0 || pRes->nSuppSizeL > nVarsRem || (pRes->nSuppSizeL == nVarsRem && pRes->DelayEst > Delay) )
+ {
+ pRes->nBSVars = nVarsBS;
+ pRes->BSVars = (uBoundSet & 0xFFFF);
+ pRes->nSuppSizeS = nVarsBS + nCofDepth;
+ pRes->nSuppSizeL = nVarsRem;
+ pRes->DelayEst = Delay;
+ pRes->AreaEst = Area;
+ }
+ }
+if ( fVerbose )
+{
+if ( pRes->BSVars )
+{
+printf( "Found bound set " );
+Lpk_PrintSetOne( pRes->BSVars );
+printf( "\n" );
+}
+else
+printf( "Did not find boundsets.\n" );
+printf( "\n" );
+}
+ if ( pRes->BSVars )
+ {
+ assert( pRes->DelayEst <= (int)p->nDelayLim );
+ assert( pRes->AreaEst <= (int)p->nAreaLim );
+ }
+}
+
+
+/**Function*************************************************************
+
+ Synopsis [Finds late arriving inputs, which cannot be in the bound set.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+unsigned Lpk_DsdLateArriving( Lpk_Fun_t * p )
+{
+ unsigned i, uLateArrSupp = 0;
+ Lpk_SuppForEachVar( p->uSupp, i )
+ if ( p->pDelays[i] > (int)p->nDelayLim - 2 )
+ uLateArrSupp |= (1 << i);
+ return uLateArrSupp;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Performs DSD-based decomposition of the function.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Lpk_DsdAnalizeOne( Lpk_Fun_t * p, unsigned * ppTruths[5][16], Kit_DsdNtk_t * pNtks[], char pCofVars[], int nCofDepth, Lpk_Res_t * pRes )
+{
+ int fVerbose = 0;
+ Vec_Int_t * pvBSets[4][8];
+ unsigned uNonDecSupp, uLateArrSupp;
+ int i, k, nNonDecSize, nNonDecSizeMax;
+ assert( nCofDepth >= 1 && nCofDepth <= 3 );
+ assert( nCofDepth < (int)p->nLutK - 1 );
+ assert( p->fSupports );
+
+ // find the support of the largest non-DSD block
+ nNonDecSizeMax = 0;
+ uNonDecSupp = p->uSupp;
+ for ( i = 0; i < (1<<(nCofDepth-1)); i++ )
+ {
+ nNonDecSize = Kit_DsdNonDsdSizeMax( pNtks[i] );
+ if ( nNonDecSizeMax < nNonDecSize )
+ {
+ nNonDecSizeMax = nNonDecSize;
+ uNonDecSupp = Kit_DsdNonDsdSupports( pNtks[i] );
+ }
+ else if ( nNonDecSizeMax == nNonDecSize )
+ uNonDecSupp |= Kit_DsdNonDsdSupports( pNtks[i] );
+ }
+
+ // remove those variables that cannot be used because of delay constraints
+ // if variables arrival time is more than p->DelayLim - 2, it cannot be used
+ uLateArrSupp = Lpk_DsdLateArriving( p );
+ if ( (uNonDecSupp & ~uLateArrSupp) == 0 )
+ {
+ memset( pRes, 0, sizeof(Lpk_Res_t) );
+ return 0;
+ }
+
+ // find the next cofactoring variable
+ pCofVars[nCofDepth-1] = Lpk_FunComputeMinSuppSizeVar( p, ppTruths[nCofDepth-1], 1<<(nCofDepth-1), ppTruths[nCofDepth], uNonDecSupp & ~uLateArrSupp );
+
+ // derive decomposed networks
+ for ( i = 0; i < (1<<nCofDepth); i++ )
+ {
+ if ( pNtks[i] )
+ Kit_DsdNtkFree( pNtks[i] );
+ pNtks[i] = Kit_DsdDecomposeExpand( ppTruths[nCofDepth][i], p->nVars );
+if ( fVerbose )
+Kit_DsdPrint( stdout, pNtks[i] );
+ pvBSets[nCofDepth][i] = Lpk_ComputeBoundSets( pNtks[i], p->nLutK - nCofDepth ); // try restricting to those in uNonDecSupp!!!
+ }
+
+ // derive the set of feasible boundsets
+ for ( i = nCofDepth - 1; i >= 0; i-- )
+ for ( k = 0; k < (1<<i); k++ )
+ pvBSets[i][k] = Lpk_MergeBoundSets( pvBSets[i+1][2*k+0], pvBSets[i+1][2*k+1], p->nLutK - nCofDepth );
+ // compare bound-sets
+ Lpk_FunCompareBoundSets( p, pvBSets[0][0], nCofDepth, uNonDecSupp, uLateArrSupp, pRes );
+ // free the bound sets
+ for ( i = nCofDepth; i >= 0; i-- )
+ for ( k = 0; k < (1<<i); k++ )
+ Vec_IntFree( pvBSets[i][k] );
+
+ // copy the cofactoring variables
+ if ( pRes->BSVars )
+ {
+ pRes->nCofVars = nCofDepth;
+ for ( i = 0; i < nCofDepth; i++ )
+ pRes->pCofVars[i] = pCofVars[i];
+ }
+ return 1;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Performs DSD-based decomposition of the function.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Lpk_Res_t * Lpk_DsdAnalize( Lpk_Man_t * pMan, Lpk_Fun_t * p, int nShared )
+{
+ static Lpk_Res_t Res0, * pRes0 = &Res0;
+ static Lpk_Res_t Res1, * pRes1 = &Res1;
+ static Lpk_Res_t Res2, * pRes2 = &Res2;
+ static Lpk_Res_t Res3, * pRes3 = &Res3;
+ int fUseBackLooking = 1;
+ Lpk_Res_t * pRes = NULL;
+ Vec_Int_t * vBSets;
+ Kit_DsdNtk_t * pNtks[8] = {NULL};
+ char pCofVars[5];
+ int i;
+
+ assert( p->nLutK >= 3 );
+ assert( nShared >= 0 && nShared <= 3 );
+ assert( p->uSupp == Kit_BitMask(p->nVars) );
+
+ // try decomposition without cofactoring
+ pNtks[0] = Kit_DsdDecomposeExpand( Lpk_FunTruth( p, 0 ), p->nVars );
+ if ( pMan->pPars->fVerbose )
+ pMan->nBlocks[ Kit_DsdNonDsdSizeMax(pNtks[0]) ]++;
+ vBSets = Lpk_ComputeBoundSets( pNtks[0], p->nLutK );
+ Lpk_FunCompareBoundSets( p, vBSets, 0, 0xFFFF, Lpk_DsdLateArriving(p), pRes0 );
+ Vec_IntFree( vBSets );
+
+ // check the result
+ if ( pRes0->nBSVars == (int)p->nLutK )
+ { pRes = pRes0; goto finish; }
+ if ( pRes0->nBSVars == (int)p->nLutK - 1 )
+ { pRes = pRes0; goto finish; }
+ if ( nShared == 0 )
+ goto finish;
+
+ // prepare storage
+ Kit_TruthCopy( pMan->ppTruths[0][0], Lpk_FunTruth( p, 0 ), p->nVars );
+
+ // cofactor 1 time
+ if ( !Lpk_DsdAnalizeOne( p, pMan->ppTruths, pNtks, pCofVars, 1, pRes1 ) )
+ goto finish;
+ assert( pRes1->nBSVars <= (int)p->nLutK - 1 );
+ if ( pRes1->nBSVars == (int)p->nLutK - 1 )
+ { pRes = pRes1; goto finish; }
+ if ( pRes0->nBSVars == (int)p->nLutK - 2 )
+ { pRes = pRes0; goto finish; }
+ if ( pRes1->nBSVars == (int)p->nLutK - 2 )
+ { pRes = pRes1; goto finish; }
+ if ( nShared == 1 )
+ goto finish;
+
+ // cofactor 2 times
+ if ( p->nLutK >= 4 )
+ {
+ if ( !Lpk_DsdAnalizeOne( p, pMan->ppTruths, pNtks, pCofVars, 2, pRes2 ) )
+ goto finish;
+ assert( pRes2->nBSVars <= (int)p->nLutK - 2 );
+ if ( pRes2->nBSVars == (int)p->nLutK - 2 )
+ { pRes = pRes2; goto finish; }
+ if ( fUseBackLooking )
+ {
+ if ( pRes0->nBSVars == (int)p->nLutK - 3 )
+ { pRes = pRes0; goto finish; }
+ if ( pRes1->nBSVars == (int)p->nLutK - 3 )
+ { pRes = pRes1; goto finish; }
+ }
+ if ( pRes2->nBSVars == (int)p->nLutK - 3 )
+ { pRes = pRes2; goto finish; }
+ if ( nShared == 2 )
+ goto finish;
+ assert( nShared == 3 );
+ }
+
+ // cofactor 3 times
+ if ( p->nLutK >= 5 )
+ {
+ if ( !Lpk_DsdAnalizeOne( p, pMan->ppTruths, pNtks, pCofVars, 3, pRes3 ) )
+ goto finish;
+ assert( pRes3->nBSVars <= (int)p->nLutK - 3 );
+ if ( pRes3->nBSVars == (int)p->nLutK - 3 )
+ { pRes = pRes3; goto finish; }
+ if ( fUseBackLooking )
+ {
+ if ( pRes0->nBSVars == (int)p->nLutK - 4 )
+ { pRes = pRes0; goto finish; }
+ if ( pRes1->nBSVars == (int)p->nLutK - 4 )
+ { pRes = pRes1; goto finish; }
+ if ( pRes2->nBSVars == (int)p->nLutK - 4 )
+ { pRes = pRes2; goto finish; }
+ }
+ if ( pRes3->nBSVars == (int)p->nLutK - 4 )
+ { pRes = pRes3; goto finish; }
+ }
+
+finish:
+ // free the networks
+ for ( i = 0; i < (1<<nShared); i++ )
+ if ( pNtks[i] )
+ Kit_DsdNtkFree( pNtks[i] );
+ // choose the best under these conditions
+ return pRes;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Splits the function into two subfunctions using DSD.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Lpk_Fun_t * Lpk_DsdSplit( Lpk_Man_t * pMan, Lpk_Fun_t * p, char * pCofVars, int nCofVars, unsigned uBoundSet )
+{
+ Lpk_Fun_t * pNew;
+ Kit_DsdNtk_t * pNtkDec;
+ int i, k, iVacVar, nCofs;
+ // prepare storage
+ Kit_TruthCopy( pMan->ppTruths[0][0], Lpk_FunTruth(p, 0), p->nVars );
+ // get the vacuous variable
+ iVacVar = Kit_WordFindFirstBit( uBoundSet );
+ // compute the cofactors
+ for ( i = 0; i < nCofVars; i++ )
+ for ( k = 0; k < (1<<i); k++ )
+ {
+ Kit_TruthCofactor0New( pMan->ppTruths[i+1][2*k+0], pMan->ppTruths[i][k], p->nVars, pCofVars[i] );
+ Kit_TruthCofactor1New( pMan->ppTruths[i+1][2*k+1], pMan->ppTruths[i][k], p->nVars, pCofVars[i] );
+ }
+ // decompose each cofactor w.r.t. the bound set
+ nCofs = (1<<nCofVars);
+ for ( k = 0; k < nCofs; k++ )
+ {
+ pNtkDec = Kit_DsdDecomposeExpand( pMan->ppTruths[nCofVars][k], p->nVars );
+ Kit_DsdTruthPartialTwo( pMan->pDsdMan, pNtkDec, uBoundSet, iVacVar, pMan->ppTruths[nCofVars+1][k], pMan->ppTruths[nCofVars+1][nCofs+k] );
+ Kit_DsdNtkFree( pNtkDec );
+ }
+ // compute the composition/decomposition functions (they will be in pMan->ppTruths[1][0]/pMan->ppTruths[1][1])
+ for ( i = nCofVars; i >= 1; i-- )
+ for ( k = 0; k < (1<<i); k++ )
+ Kit_TruthMuxVar( pMan->ppTruths[i][k], pMan->ppTruths[i+1][2*k+0], pMan->ppTruths[i+1][2*k+1], p->nVars, pCofVars[i-1] );
+
+ // derive the new component (decomposition function)
+ pNew = Lpk_FunDup( p, pMan->ppTruths[1][1] );
+ // update the old component (composition function)
+ Kit_TruthCopy( Lpk_FunTruth(p, 0), pMan->ppTruths[1][0], p->nVars );
+ p->uSupp = Kit_TruthSupport( Lpk_FunTruth(p, 0), p->nVars );
+ p->pFanins[iVacVar] = pNew->Id;
+ p->pDelays[iVacVar] = Lpk_SuppDelay( pNew->uSupp, pNew->pDelays );
+ // support minimize both
+ p->fSupports = 0;
+ Lpk_FunSuppMinimize( p );
+ Lpk_FunSuppMinimize( pNew );
+ // update delay and area requirements
+ pNew->nDelayLim = p->pDelays[iVacVar];
+ pNew->nAreaLim = 1;
+ p->nAreaLim = p->nAreaLim - 1;
+ return pNew;
+}
+
+////////////////////////////////////////////////////////////////////////
+/// END OF FILE ///
+////////////////////////////////////////////////////////////////////////
+
+
diff --git a/src/opt/lpk/lpkAbcMux.c b/src/opt/lpk/lpkAbcMux.c
new file mode 100644
index 00000000..d6f579ee
--- /dev/null
+++ b/src/opt/lpk/lpkAbcMux.c
@@ -0,0 +1,235 @@
+/**CFile****************************************************************
+
+ FileName [lpkAbcMux.c]
+
+ SystemName [ABC: Logic synthesis and verification system.]
+
+ PackageName [Fast Boolean matching for LUT structures.]
+
+ Synopsis [LUT-decomposition based on recursive MUX decomposition.]
+
+ Author [Alan Mishchenko]
+
+ Affiliation [UC Berkeley]
+
+ Date [Ver. 1.0. Started - April 28, 2007.]
+
+ Revision [$Id: lpkAbcMux.c,v 1.00 2007/04/28 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "lpkInt.h"
+
+////////////////////////////////////////////////////////////////////////
+/// DECLARATIONS ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+/// FUNCTION DEFINITIONS ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+ Synopsis [Checks the possibility of MUX decomposition.]
+
+ Description [Returns the best variable to use for MUX decomposition.]
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Lpk_Res_t * Lpk_MuxAnalize( Lpk_Man_t * pMan, Lpk_Fun_t * p )
+{
+ static Lpk_Res_t Res, * pRes = &Res;
+ int nSuppSize0, nSuppSize1, nSuppSizeS, nSuppSizeL;
+ int Var, Area, Polarity, Delay, Delay0, Delay1, DelayA, DelayB;
+ memset( pRes, 0, sizeof(Lpk_Res_t) );
+ assert( p->uSupp == Kit_BitMask(p->nVars) );
+ assert( p->fSupports );
+ // derive the delay and area after MUX-decomp with each var - and find the best var
+ pRes->Variable = -1;
+ Lpk_SuppForEachVar( p->uSupp, Var )
+ {
+ nSuppSize0 = Kit_WordCountOnes(p->puSupps[2*Var+0]);
+ nSuppSize1 = Kit_WordCountOnes(p->puSupps[2*Var+1]);
+ assert( nSuppSize0 < (int)p->nVars );
+ assert( nSuppSize1 < (int)p->nVars );
+ if ( nSuppSize0 < 1 || nSuppSize1 < 1 )
+ continue;
+//printf( "%d %d ", nSuppSize0, nSuppSize1 );
+ if ( nSuppSize0 <= (int)p->nLutK - 2 && nSuppSize1 <= (int)p->nLutK - 2 )
+ {
+ // include cof var into 0-block
+ DelayA = Lpk_SuppDelay( p->puSupps[2*Var+0] | (1<<Var), p->pDelays );
+ DelayB = Lpk_SuppDelay( p->puSupps[2*Var+1] , p->pDelays );
+ Delay0 = ABC_MAX( DelayA, DelayB + 1 );
+ // include cof var into 1-block
+ DelayA = Lpk_SuppDelay( p->puSupps[2*Var+1] | (1<<Var), p->pDelays );
+ DelayB = Lpk_SuppDelay( p->puSupps[2*Var+0] , p->pDelays );
+ Delay1 = ABC_MAX( DelayA, DelayB + 1 );
+ // get the best delay
+ Delay = ABC_MIN( Delay0, Delay1 );
+ Area = 2;
+ Polarity = (int)(Delay == Delay1);
+ }
+ else if ( nSuppSize0 <= (int)p->nLutK - 2 )
+ {
+ DelayA = Lpk_SuppDelay( p->puSupps[2*Var+0] | (1<<Var), p->pDelays );
+ DelayB = Lpk_SuppDelay( p->puSupps[2*Var+1] , p->pDelays );
+ Delay = ABC_MAX( DelayA, DelayB + 1 );
+ Area = 1 + Lpk_LutNumLuts( nSuppSize1, p->nLutK );
+ Polarity = 0;
+ }
+ else if ( nSuppSize1 <= (int)p->nLutK - 2 )
+ {
+ DelayA = Lpk_SuppDelay( p->puSupps[2*Var+1] | (1<<Var), p->pDelays );
+ DelayB = Lpk_SuppDelay( p->puSupps[2*Var+0] , p->pDelays );
+ Delay = ABC_MAX( DelayA, DelayB + 1 );
+ Area = 1 + Lpk_LutNumLuts( nSuppSize0, p->nLutK );
+ Polarity = 1;
+ }
+ else if ( nSuppSize0 <= (int)p->nLutK )
+ {
+ DelayA = Lpk_SuppDelay( p->puSupps[2*Var+1] | (1<<Var), p->pDelays );
+ DelayB = Lpk_SuppDelay( p->puSupps[2*Var+0] , p->pDelays );
+ Delay = ABC_MAX( DelayA, DelayB + 1 );
+ Area = 1 + Lpk_LutNumLuts( nSuppSize1+2, p->nLutK );
+ Polarity = 1;
+ }
+ else if ( nSuppSize1 <= (int)p->nLutK )
+ {
+ DelayA = Lpk_SuppDelay( p->puSupps[2*Var+0] | (1<<Var), p->pDelays );
+ DelayB = Lpk_SuppDelay( p->puSupps[2*Var+1] , p->pDelays );
+ Delay = ABC_MAX( DelayA, DelayB + 1 );
+ Area = 1 + Lpk_LutNumLuts( nSuppSize0+2, p->nLutK );
+ Polarity = 0;
+ }
+ else
+ {
+ // include cof var into 0-block
+ DelayA = Lpk_SuppDelay( p->puSupps[2*Var+0] | (1<<Var), p->pDelays );
+ DelayB = Lpk_SuppDelay( p->puSupps[2*Var+1] , p->pDelays );
+ Delay0 = ABC_MAX( DelayA, DelayB + 1 );
+ // include cof var into 1-block
+ DelayA = Lpk_SuppDelay( p->puSupps[2*Var+1] | (1<<Var), p->pDelays );
+ DelayB = Lpk_SuppDelay( p->puSupps[2*Var+0] , p->pDelays );
+ Delay1 = ABC_MAX( DelayA, DelayB + 1 );
+ // get the best delay
+ Delay = ABC_MIN( Delay0, Delay1 );
+ if ( Delay == Delay0 )
+ Area = Lpk_LutNumLuts( nSuppSize0+2, p->nLutK ) + Lpk_LutNumLuts( nSuppSize1, p->nLutK );
+ else
+ Area = Lpk_LutNumLuts( nSuppSize1+2, p->nLutK ) + Lpk_LutNumLuts( nSuppSize0, p->nLutK );
+ Polarity = (int)(Delay == Delay1);
+ }
+ // find the best variable
+ if ( Delay > (int)p->nDelayLim )
+ continue;
+ if ( Area > (int)p->nAreaLim )
+ continue;
+ nSuppSizeS = ABC_MIN( nSuppSize0 + 2 *!Polarity, nSuppSize1 + 2 * Polarity );
+ nSuppSizeL = ABC_MAX( nSuppSize0 + 2 *!Polarity, nSuppSize1 + 2 * Polarity );
+ if ( nSuppSizeL > (int)p->nVars )
+ continue;
+ if ( pRes->Variable == -1 || pRes->AreaEst > Area ||
+ (pRes->AreaEst == Area && pRes->nSuppSizeS + pRes->nSuppSizeL > nSuppSizeS + nSuppSizeL) ||
+ (pRes->AreaEst == Area && pRes->nSuppSizeS + pRes->nSuppSizeL == nSuppSizeS + nSuppSizeL && pRes->DelayEst > Delay) )
+ {
+ pRes->Variable = Var;
+ pRes->Polarity = Polarity;
+ pRes->AreaEst = Area;
+ pRes->DelayEst = Delay;
+ pRes->nSuppSizeS = nSuppSizeS;
+ pRes->nSuppSizeL = nSuppSizeL;
+ }
+ }
+ return pRes->Variable == -1 ? NULL : pRes;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Transforms the function decomposed by the MUX decomposition.]
+
+ Description [Returns the best variable to use for MUX decomposition.]
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Lpk_Fun_t * Lpk_MuxSplit( Lpk_Man_t * pMan, Lpk_Fun_t * p, int Var, int Pol )
+{
+ Lpk_Fun_t * pNew;
+ unsigned * pTruth = Lpk_FunTruth( p, 0 );
+ unsigned * pTruth0 = Lpk_FunTruth( p, 1 );
+ unsigned * pTruth1 = Lpk_FunTruth( p, 2 );
+// unsigned uSupp;
+ int iVarVac;
+ assert( Var >= 0 && Var < (int)p->nVars );
+ assert( p->nAreaLim >= 2 );
+ assert( p->uSupp == Kit_BitMask(p->nVars) );
+ Kit_TruthCofactor0New( pTruth0, pTruth, p->nVars, Var );
+ Kit_TruthCofactor1New( pTruth1, pTruth, p->nVars, Var );
+/*
+uSupp = Kit_TruthSupport( pTruth, p->nVars );
+Extra_PrintBinary( stdout, &uSupp, 16 ); printf( "\n" );
+uSupp = Kit_TruthSupport( pTruth0, p->nVars );
+Extra_PrintBinary( stdout, &uSupp, 16 ); printf( "\n" );
+uSupp = Kit_TruthSupport( pTruth1, p->nVars );
+Extra_PrintBinary( stdout, &uSupp, 16 ); printf( "\n\n" );
+*/
+ // derive the new component
+ pNew = Lpk_FunDup( p, Pol ? pTruth0 : pTruth1 );
+ // update the support of the old component
+ p->uSupp = Kit_TruthSupport( Pol ? pTruth1 : pTruth0, p->nVars );
+ p->uSupp |= (1 << Var);
+ // update the truth table of the old component
+ iVarVac = Kit_WordFindFirstBit( ~p->uSupp );
+ assert( iVarVac < (int)p->nVars );
+ p->uSupp |= (1 << iVarVac);
+ Kit_TruthIthVar( pTruth, p->nVars, iVarVac );
+ if ( Pol )
+ Kit_TruthMuxVar( pTruth, pTruth, pTruth1, p->nVars, Var );
+ else
+ Kit_TruthMuxVar( pTruth, pTruth0, pTruth, p->nVars, Var );
+ assert( p->uSupp == Kit_TruthSupport(pTruth, p->nVars) );
+ // set the decomposed variable
+ p->pFanins[iVarVac] = pNew->Id;
+ p->pDelays[iVarVac] = p->nDelayLim - 1;
+ // support minimize both
+ p->fSupports = 0;
+ Lpk_FunSuppMinimize( p );
+ Lpk_FunSuppMinimize( pNew );
+ // update delay and area requirements
+ pNew->nDelayLim = p->nDelayLim - 1;
+ if ( pNew->nVars <= pNew->nLutK )
+ {
+ pNew->nAreaLim = 1;
+ p->nAreaLim = p->nAreaLim - 1;
+ }
+ else if ( p->nVars <= p->nLutK )
+ {
+ pNew->nAreaLim = p->nAreaLim - 1;
+ p->nAreaLim = 1;
+ }
+ else if ( p->nVars < pNew->nVars )
+ {
+ pNew->nAreaLim = p->nAreaLim / 2 + p->nAreaLim % 2;
+ p->nAreaLim = p->nAreaLim / 2 - p->nAreaLim % 2;
+ }
+ else // if ( pNew->nVars < p->nVars )
+ {
+ pNew->nAreaLim = p->nAreaLim / 2 - p->nAreaLim % 2;
+ p->nAreaLim = p->nAreaLim / 2 + p->nAreaLim % 2;
+ }
+ pNew->fMark = 1;
+ return pNew;
+}
+
+
+////////////////////////////////////////////////////////////////////////
+/// END OF FILE ///
+////////////////////////////////////////////////////////////////////////
+
+
diff --git a/src/opt/lpk/lpkAbcUtil.c b/src/opt/lpk/lpkAbcUtil.c
new file mode 100644
index 00000000..3f917ce2
--- /dev/null
+++ b/src/opt/lpk/lpkAbcUtil.c
@@ -0,0 +1,244 @@
+/**CFile****************************************************************
+
+ FileName [lpkAbcUtil.c]
+
+ SystemName [ABC: Logic synthesis and verification system.]
+
+ PackageName [Fast Boolean matching for LUT structures.]
+
+ Synopsis [Procedures working on decomposed functions.]
+
+ Author [Alan Mishchenko]
+
+ Affiliation [UC Berkeley]
+
+ Date [Ver. 1.0. Started - April 28, 2007.]
+
+ Revision [$Id: lpkAbcUtil.c,v 1.00 2007/04/28 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "lpkInt.h"
+
+////////////////////////////////////////////////////////////////////////
+/// DECLARATIONS ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+/// FUNCTION DEFINITIONS ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+ Synopsis [Allocates the function.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Lpk_Fun_t * Lpk_FunAlloc( int nVars )
+{
+ Lpk_Fun_t * p;
+ p = (Lpk_Fun_t *)malloc( sizeof(Lpk_Fun_t) + sizeof(unsigned) * Kit_TruthWordNum(nVars) * 3 );
+ memset( p, 0, sizeof(Lpk_Fun_t) );
+ return p;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Deletes the function]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Lpk_FunFree( Lpk_Fun_t * p )
+{
+ free( p );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Creates the starting function.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Lpk_Fun_t * Lpk_FunCreate( Abc_Ntk_t * pNtk, Vec_Ptr_t * vLeaves, unsigned * pTruth, int nLutK, int AreaLim, int DelayLim )
+{
+ Lpk_Fun_t * p;
+ Abc_Obj_t * pNode;
+ int i;
+ p = Lpk_FunAlloc( Vec_PtrSize(vLeaves) );
+ p->Id = Vec_PtrSize(vLeaves);
+ p->vNodes = vLeaves;
+ p->nVars = Vec_PtrSize(vLeaves);
+ p->nLutK = nLutK;
+ p->nAreaLim = AreaLim;
+ p->nDelayLim = DelayLim;
+ p->uSupp = Kit_TruthSupport( pTruth, p->nVars );
+ Kit_TruthCopy( Lpk_FunTruth(p,0), pTruth, p->nVars );
+ Vec_PtrForEachEntry( vLeaves, pNode, i )
+ {
+ p->pFanins[i] = i;
+ p->pDelays[i] = pNode->Level;
+ }
+ Vec_PtrPush( p->vNodes, p );
+ return p;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Creates the new function with the given truth table.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Lpk_Fun_t * Lpk_FunDup( Lpk_Fun_t * p, unsigned * pTruth )
+{
+ Lpk_Fun_t * pNew;
+ pNew = Lpk_FunAlloc( p->nVars );
+ pNew->Id = Vec_PtrSize(p->vNodes);
+ pNew->vNodes = p->vNodes;
+ pNew->nVars = p->nVars;
+ pNew->nLutK = p->nLutK;
+ pNew->nAreaLim = p->nAreaLim;
+ pNew->nDelayLim = p->nDelayLim;
+ pNew->uSupp = Kit_TruthSupport( pTruth, p->nVars );
+ Kit_TruthCopy( Lpk_FunTruth(pNew,0), pTruth, p->nVars );
+ memcpy( pNew->pFanins, p->pFanins, 16 );
+ memcpy( pNew->pDelays, p->pDelays, 16 );
+ Vec_PtrPush( p->vNodes, pNew );
+ return pNew;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Minimizes support of the function.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Lpk_FunSuppMinimize( Lpk_Fun_t * p )
+{
+ int i, k, nVarsNew;
+ // compress the truth table
+ if ( p->uSupp == Kit_BitMask(p->nVars) )
+ return 0;
+ // invalidate support info
+ p->fSupports = 0;
+//Extra_PrintBinary( stdout, &p->uSupp, p->nVars ); printf( "\n" );
+ // minimize support
+ nVarsNew = Kit_WordCountOnes(p->uSupp);
+ Kit_TruthShrink( Lpk_FunTruth(p, 1), Lpk_FunTruth(p, 0), nVarsNew, p->nVars, p->uSupp, 1 );
+ k = 0;
+ Lpk_SuppForEachVar( p->uSupp, i )
+ {
+ p->pFanins[k] = p->pFanins[i];
+ p->pDelays[k] = p->pDelays[i];
+/*
+ if ( p->fSupports )
+ {
+ p->puSupps[2*k+0] = p->puSupps[2*i+0];
+ p->puSupps[2*k+1] = p->puSupps[2*i+1];
+ }
+*/
+ k++;
+ }
+ assert( k == nVarsNew );
+ p->nVars = k;
+ p->uSupp = Kit_BitMask(p->nVars);
+ return 1;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Computes cofactors w.r.t. each variable.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Lpk_FunComputeCofSupps( Lpk_Fun_t * p )
+{
+ unsigned * pTruth = Lpk_FunTruth( p, 0 );
+ unsigned * pTruth0 = Lpk_FunTruth( p, 1 );
+ unsigned * pTruth1 = Lpk_FunTruth( p, 2 );
+ int Var;
+ assert( p->fSupports == 0 );
+// Lpk_SuppForEachVar( p->uSupp, Var )
+ for ( Var = 0; Var < (int)p->nVars; Var++ )
+ {
+ Kit_TruthCofactor0New( pTruth0, pTruth, p->nVars, Var );
+ Kit_TruthCofactor1New( pTruth1, pTruth, p->nVars, Var );
+ p->puSupps[2*Var+0] = Kit_TruthSupport( pTruth0, p->nVars );
+ p->puSupps[2*Var+1] = Kit_TruthSupport( pTruth1, p->nVars );
+ }
+ p->fSupports = 1;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Get the delay of the bound set.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Lpk_SuppDelay( unsigned uSupp, char * pDelays )
+{
+ int Delay, Var;
+ Delay = 0;
+ Lpk_SuppForEachVar( uSupp, Var )
+ Delay = ABC_MAX( Delay, pDelays[Var] );
+ return Delay + 1;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Converts support into variables.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Lpk_SuppToVars( unsigned uBoundSet, char * pVars )
+{
+ int i, nVars = 0;
+ Lpk_SuppForEachVar( uBoundSet, i )
+ pVars[nVars++] = i;
+ return nVars;
+}
+
+////////////////////////////////////////////////////////////////////////
+/// END OF FILE ///
+////////////////////////////////////////////////////////////////////////
+
+
diff --git a/src/opt/lpk/lpkCore.c b/src/opt/lpk/lpkCore.c
new file mode 100644
index 00000000..e819a7fb
--- /dev/null
+++ b/src/opt/lpk/lpkCore.c
@@ -0,0 +1,659 @@
+/**CFile****************************************************************
+
+ FileName [lpkCore.c]
+
+ SystemName [ABC: Logic synthesis and verification system.]
+
+ PackageName [Fast Boolean matching for LUT structures.]
+
+ Synopsis []
+
+ Author [Alan Mishchenko]
+
+ Affiliation [UC Berkeley]
+
+ Date [Ver. 1.0. Started - April 28, 2007.]
+
+ Revision [$Id: lpkCore.c,v 1.00 2007/04/28 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "lpkInt.h"
+#include "cloud.h"
+
+////////////////////////////////////////////////////////////////////////
+/// DECLARATIONS ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+/// FUNCTION DEFINITIONS ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+ Synopsis [Prepares the mapping manager.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Lpk_IfManStart( Lpk_Man_t * p )
+{
+ If_Par_t * pPars;
+ assert( p->pIfMan == NULL );
+ // set defaults
+ pPars = ALLOC( If_Par_t, 1 );
+ memset( pPars, 0, sizeof(If_Par_t) );
+ // user-controlable paramters
+ pPars->nLutSize = p->pPars->nLutSize;
+ pPars->nCutsMax = 16;
+ pPars->nFlowIters = 0; // 1
+ pPars->nAreaIters = 0; // 1
+ pPars->DelayTarget = -1;
+ pPars->fPreprocess = 0;
+ pPars->fArea = 1;
+ pPars->fFancy = 0;
+ pPars->fExpRed = 0; //
+ pPars->fLatchPaths = 0;
+ pPars->fSeqMap = 0;
+ pPars->fVerbose = 0;
+ // internal parameters
+ pPars->fTruth = 1;
+ pPars->fUsePerm = 0;
+ pPars->nLatches = 0;
+ pPars->pLutLib = NULL; // Abc_FrameReadLibLut();
+ pPars->pTimesArr = NULL;
+ pPars->pTimesArr = NULL;
+ pPars->fUseBdds = 0;
+ pPars->fUseSops = 0;
+ pPars->fUseCnfs = 0;
+ pPars->fUseMv = 0;
+ // start the mapping manager and set its parameters
+ p->pIfMan = If_ManStart( pPars );
+ If_ManSetupSetAll( p->pIfMan, 1000 );
+ p->pIfMan->pPars->pTimesArr = ALLOC( float, 32 );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Returns 1 if at least one entry has changed.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Lpk_NodeHasChanged( Lpk_Man_t * p, int iNode )
+{
+ Vec_Ptr_t * vNodes;
+ Abc_Obj_t * pTemp;
+ int i;
+ vNodes = Vec_VecEntry( p->vVisited, iNode );
+ if ( Vec_PtrSize(vNodes) == 0 )
+ return 1;
+ Vec_PtrForEachEntry( vNodes, pTemp, i )
+ {
+ // check if the node has changed
+ pTemp = Abc_NtkObj( p->pNtk, (int)pTemp );
+ if ( pTemp == NULL )
+ return 1;
+ // check if the number of fanouts has changed
+// if ( Abc_ObjFanoutNum(pTemp) != (int)Vec_PtrEntry(vNodes, i+1) )
+// return 1;
+ i++;
+ }
+ return 0;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Prepares the mapping manager.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Lpk_ExploreCut( Lpk_Man_t * p, Lpk_Cut_t * pCut, Kit_DsdNtk_t * pNtk )
+{
+ extern Abc_Obj_t * Abc_NodeFromIf_rec( Abc_Ntk_t * pNtkNew, If_Man_t * pIfMan, If_Obj_t * pIfObj, Vec_Int_t * vCover );
+ Kit_DsdObj_t * pRoot;
+ If_Obj_t * pDriver, * ppLeaves[16];
+ Abc_Obj_t * pLeaf, * pObjNew;
+ int nGain, i, clk;
+ int nNodesBef;
+// int nOldShared;
+
+ // check special cases
+ pRoot = Kit_DsdNtkRoot( pNtk );
+ if ( pRoot->Type == KIT_DSD_CONST1 )
+ {
+ if ( Kit_DsdLitIsCompl(pNtk->Root) )
+ pObjNew = Abc_NtkCreateNodeConst0( p->pNtk );
+ else
+ pObjNew = Abc_NtkCreateNodeConst1( p->pNtk );
+ Abc_NtkUpdate( p->pObj, pObjNew, p->vLevels );
+ p->nGainTotal += pCut->nNodes - pCut->nNodesDup;
+ return 1;
+ }
+ if ( pRoot->Type == KIT_DSD_VAR )
+ {
+ pObjNew = Abc_NtkObj( p->pNtk, pCut->pLeaves[ Kit_DsdLit2Var(pRoot->pFans[0]) ] );
+ if ( Kit_DsdLitIsCompl(pNtk->Root) ^ Kit_DsdLitIsCompl(pRoot->pFans[0]) )
+ pObjNew = Abc_NtkCreateNodeInv( p->pNtk, pObjNew );
+ Abc_NtkUpdate( p->pObj, pObjNew, p->vLevels );
+ p->nGainTotal += pCut->nNodes - pCut->nNodesDup;
+ return 1;
+ }
+ assert( pRoot->Type == KIT_DSD_AND || pRoot->Type == KIT_DSD_XOR || pRoot->Type == KIT_DSD_PRIME );
+
+ // start the mapping manager
+ if ( p->pIfMan == NULL )
+ Lpk_IfManStart( p );
+
+ // prepare the mapping manager
+ If_ManRestart( p->pIfMan );
+ // create the PI variables
+ for ( i = 0; i < p->pPars->nVarsMax; i++ )
+ ppLeaves[i] = If_ManCreateCi( p->pIfMan );
+ // set the arrival times
+ Lpk_CutForEachLeaf( p->pNtk, pCut, pLeaf, i )
+ p->pIfMan->pPars->pTimesArr[i] = (float)pLeaf->Level;
+ // prepare the PI cuts
+ If_ManSetupCiCutSets( p->pIfMan );
+ // create the internal nodes
+ p->fCalledOnce = 0;
+ p->nCalledSRed = 0;
+ pDriver = Lpk_MapTree_rec( p, pNtk, ppLeaves, pNtk->Root, NULL );
+ if ( pDriver == NULL )
+ return 0;
+ // create the PO node
+ If_ManCreateCo( p->pIfMan, If_Regular(pDriver) );
+
+ // perform mapping
+ p->pIfMan->pPars->fAreaOnly = 1;
+clk = clock();
+ If_ManPerformMappingComb( p->pIfMan );
+p->timeMap += clock() - clk;
+
+ // compute the gain in area
+ nGain = pCut->nNodes - pCut->nNodesDup - (int)p->pIfMan->AreaGlo;
+ if ( p->pPars->fVeryVerbose )
+ printf( " Mffc = %2d. Mapped = %2d. Gain = %3d. Depth increase = %d. SReds = %d.\n",
+ pCut->nNodes - pCut->nNodesDup, (int)p->pIfMan->AreaGlo, nGain, (int)p->pIfMan->RequiredGlo - (int)p->pObj->Level, p->nCalledSRed );
+
+ // quit if there is no gain
+ if ( !(nGain > 0 || (p->pPars->fZeroCost && nGain == 0)) )
+ return 0;
+
+ // quit if depth increases too much
+ if ( (int)p->pIfMan->RequiredGlo > Abc_ObjRequiredLevel(p->pObj) )
+ return 0;
+
+ // perform replacement
+ p->nGainTotal += nGain;
+ p->nChanges++;
+ if ( p->nCalledSRed )
+ p->nBenefited++;
+
+ nNodesBef = Abc_NtkNodeNum(p->pNtk);
+ // prepare the mapping manager
+ If_ManCleanNodeCopy( p->pIfMan );
+ If_ManCleanCutData( p->pIfMan );
+ // set the PIs of the cut
+ Lpk_CutForEachLeaf( p->pNtk, pCut, pLeaf, i )
+ If_ObjSetCopy( If_ManCi(p->pIfMan, i), pLeaf );
+ // get the area of mapping
+ pObjNew = Abc_NodeFromIf_rec( p->pNtk, p->pIfMan, If_Regular(pDriver), p->vCover );
+ pObjNew->pData = Hop_NotCond( pObjNew->pData, If_IsComplement(pDriver) );
+ // perform replacement
+ Abc_NtkUpdate( p->pObj, pObjNew, p->vLevels );
+//printf( "%3d : %d-%d=%d(%d) \n", p->nChanges, nNodesBef, Abc_NtkNodeNum(p->pNtk), nNodesBef-Abc_NtkNodeNum(p->pNtk), nGain );
+ return 1;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Performs resynthesis for one node.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Lpk_ResynthesizeNode( Lpk_Man_t * p )
+{
+ static int Count = 0;
+ Kit_DsdNtk_t * pDsdNtk;
+ Lpk_Cut_t * pCut;
+ unsigned * pTruth;
+ int i, k, nSuppSize, nCutNodes, RetValue, clk;
+
+ // compute the cuts
+clk = clock();
+ if ( !Lpk_NodeCuts( p ) )
+ {
+p->timeCuts += clock() - clk;
+ return 0;
+ }
+p->timeCuts += clock() - clk;
+
+//return 0;
+
+ if ( p->pPars->fVeryVerbose )
+ printf( "Node %5d : Mffc size = %5d. Cuts = %5d.\n", p->pObj->Id, p->nMffc, p->nEvals );
+ // try the good cuts
+ p->nCutsTotal += p->nCuts;
+ p->nCutsUseful += p->nEvals;
+ for ( i = 0; i < p->nEvals; i++ )
+ {
+ // get the cut
+ pCut = p->pCuts + p->pEvals[i];
+ if ( p->pPars->fFirst && i == 1 )
+ break;
+
+ // skip bad cuts
+// printf( "Mffc size = %d. ", Abc_NodeMffcLabel(p->pObj) );
+ for ( k = 0; k < (int)pCut->nLeaves; k++ )
+ Abc_NtkObj(p->pNtk, pCut->pLeaves[k])->vFanouts.nSize++;
+ nCutNodes = Abc_NodeMffcLabel(p->pObj);
+// printf( "Mffc with cut = %d. ", nCutNodes );
+ for ( k = 0; k < (int)pCut->nLeaves; k++ )
+ Abc_NtkObj(p->pNtk, pCut->pLeaves[k])->vFanouts.nSize--;
+// printf( "Mffc cut = %d. ", (int)pCut->nNodes - (int)pCut->nNodesDup );
+// printf( "\n" );
+ if ( nCutNodes != (int)pCut->nNodes - (int)pCut->nNodesDup )
+ continue;
+
+ // compute the truth table
+clk = clock();
+ pTruth = Lpk_CutTruth( p, pCut, 0 );
+ nSuppSize = Extra_TruthSupportSize(pTruth, pCut->nLeaves);
+p->timeTruth += clock() - clk;
+
+ pDsdNtk = Kit_DsdDecompose( pTruth, pCut->nLeaves );
+// Kit_DsdVerify( pDsdNtk, pTruth, pCut->nLeaves );
+ // skip 16-input non-DSD because ISOP will not work
+ if ( Kit_DsdNtkRoot(pDsdNtk)->nFans == 16 )
+ {
+ Kit_DsdNtkFree( pDsdNtk );
+ continue;
+ }
+
+ // if DSD has nodes that require splitting to fit them into LUTs
+ // we can skip those cuts that cannot lead to improvement
+ // (a full DSD network requires V = Nmin * (K-1) + 1 for improvement)
+ if ( Kit_DsdNonDsdSizeMax(pDsdNtk) > p->pPars->nLutSize &&
+ nSuppSize >= ((int)pCut->nNodes - (int)pCut->nNodesDup - 1) * (p->pPars->nLutSize - 1) + 1 )
+ {
+ Kit_DsdNtkFree( pDsdNtk );
+ continue;
+ }
+
+ if ( p->pPars->fVeryVerbose )
+ {
+// char * pFileName;
+ printf( " C%02d: L= %2d/%2d V= %2d/%d N= %d W= %4.2f ",
+ i, pCut->nLeaves, nSuppSize, pCut->nNodes, pCut->nNodesDup, pCut->nLuts, pCut->Weight );
+ Kit_DsdPrint( stdout, pDsdNtk );
+ Kit_DsdPrintFromTruth( pTruth, pCut->nLeaves );
+// pFileName = Kit_TruthDumpToFile( pTruth, pCut->nLeaves, Count++ );
+// printf( "Saved truth table in file \"%s\".\n", pFileName );
+ }
+
+ // update the network
+clk = clock();
+ RetValue = Lpk_ExploreCut( p, pCut, pDsdNtk );
+p->timeEval += clock() - clk;
+ Kit_DsdNtkFree( pDsdNtk );
+ if ( RetValue )
+ break;
+ }
+ return 1;
+}
+
+
+/**Function*************************************************************
+
+ Synopsis [Computes supports of the cofactors of the function.]
+
+ Description [This procedure should be called after Lpk_CutTruth(p,pCut,0)]
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Lpk_ComputeSupports( Lpk_Man_t * p, Lpk_Cut_t * pCut, unsigned * pTruth )
+{
+ unsigned * pTruthInv;
+ int RetValue1, RetValue2;
+ pTruthInv = Lpk_CutTruth( p, pCut, 1 );
+ RetValue1 = Kit_CreateCloudFromTruth( p->pDsdMan->dd, pTruth, pCut->nLeaves, p->vBddDir );
+ RetValue2 = Kit_CreateCloudFromTruth( p->pDsdMan->dd, pTruthInv, pCut->nLeaves, p->vBddInv );
+ if ( RetValue1 && RetValue2 )
+ Kit_TruthCofSupports( p->vBddDir, p->vBddInv, pCut->nLeaves, p->vMemory, p->puSupps );
+ else
+ p->puSupps[0] = p->puSupps[1] = 0;
+}
+
+
+/**Function*************************************************************
+
+ Synopsis [Performs resynthesis for one node.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Lpk_ResynthesizeNodeNew( Lpk_Man_t * p )
+{
+ static int Count = 0;
+ Abc_Obj_t * pObjNew, * pLeaf;
+ Lpk_Cut_t * pCut;
+ unsigned * pTruth;
+ int nNodesBef, nNodesAft, nCutNodes;
+ int i, k, clk;
+ int Required = Abc_ObjRequiredLevel(p->pObj);
+// CloudNode * pFun2;//, * pFun1;
+
+ // compute the cuts
+clk = clock();
+ if ( !Lpk_NodeCuts( p ) )
+ {
+p->timeCuts += clock() - clk;
+ return 0;
+ }
+p->timeCuts += clock() - clk;
+
+ if ( p->pPars->fVeryVerbose )
+ printf( "Node %5d : Mffc size = %5d. Cuts = %5d. Level = %2d. Req = %2d.\n",
+ p->pObj->Id, p->nMffc, p->nEvals, p->pObj->Level, Required );
+ // try the good cuts
+ p->nCutsTotal += p->nCuts;
+ p->nCutsUseful += p->nEvals;
+ for ( i = 0; i < p->nEvals; i++ )
+ {
+ // get the cut
+ pCut = p->pCuts + p->pEvals[i];
+ if ( p->pPars->fFirst && i == 1 )
+ break;
+// if ( pCut->Weight < 1.05 )
+// continue;
+
+ // skip bad cuts
+// printf( "Mffc size = %d. ", Abc_NodeMffcLabel(p->pObj) );
+ for ( k = 0; k < (int)pCut->nLeaves; k++ )
+ Abc_NtkObj(p->pNtk, pCut->pLeaves[k])->vFanouts.nSize++;
+ nCutNodes = Abc_NodeMffcLabel(p->pObj);
+// printf( "Mffc with cut = %d. ", nCutNodes );
+ for ( k = 0; k < (int)pCut->nLeaves; k++ )
+ Abc_NtkObj(p->pNtk, pCut->pLeaves[k])->vFanouts.nSize--;
+// printf( "Mffc cut = %d. ", (int)pCut->nNodes - (int)pCut->nNodesDup );
+// printf( "\n" );
+ if ( nCutNodes != (int)pCut->nNodes - (int)pCut->nNodesDup )
+ continue;
+
+ // collect nodes into the array
+ Vec_PtrClear( p->vLeaves );
+ for ( k = 0; k < (int)pCut->nLeaves; k++ )
+ Vec_PtrPush( p->vLeaves, Abc_NtkObj(p->pNtk, pCut->pLeaves[k]) );
+
+ // compute the truth table
+clk = clock();
+ pTruth = Lpk_CutTruth( p, pCut, 0 );
+p->timeTruth += clock() - clk;
+clk = clock();
+ Lpk_ComputeSupports( p, pCut, pTruth );
+p->timeSupps += clock() - clk;
+//clk = clock();
+// pFun1 = Lpk_CutTruthBdd( p, pCut );
+//p->timeTruth2 += clock() - clk;
+/*
+clk = clock();
+ Cloud_Restart( p->pDsdMan->dd );
+ pFun2 = Kit_TruthToCloud( p->pDsdMan->dd, pTruth, pCut->nLeaves );
+ RetValue = Kit_CreateCloud( p->pDsdMan->dd, pFun2, p->vBddNodes );
+p->timeTruth3 += clock() - clk;
+*/
+// if ( pFun1 != pFun2 )
+// printf( "Truth tables do not agree!\n" );
+// else
+// printf( "Fine!\n" );
+
+ if ( p->pPars->fVeryVerbose )
+ {
+// char * pFileName;
+ int nSuppSize = Extra_TruthSupportSize( pTruth, pCut->nLeaves );
+ printf( " C%02d: L= %2d/%2d V= %2d/%d N= %d W= %4.2f ",
+ i, pCut->nLeaves, nSuppSize, pCut->nNodes, pCut->nNodesDup, pCut->nLuts, pCut->Weight );
+ Vec_PtrForEachEntry( p->vLeaves, pLeaf, k )
+ printf( "%c=%d ", 'a'+k, Abc_ObjLevel(pLeaf) );
+ printf( "\n" );
+ Kit_DsdPrintFromTruth( pTruth, pCut->nLeaves );
+// pFileName = Kit_TruthDumpToFile( pTruth, pCut->nLeaves, Count++ );
+// printf( "Saved truth table in file \"%s\".\n", pFileName );
+ }
+
+ // update the network
+ nNodesBef = Abc_NtkNodeNum(p->pNtk);
+clk = clock();
+ pObjNew = Lpk_Decompose( p, p->pNtk, p->vLeaves, pTruth, p->puSupps, p->pPars->nLutSize,
+ (int)pCut->nNodes - (int)pCut->nNodesDup - 1 + (int)(p->pPars->fZeroCost > 0), Required );
+p->timeEval += clock() - clk;
+ nNodesAft = Abc_NtkNodeNum(p->pNtk);
+
+ // perform replacement
+ if ( pObjNew )
+ {
+ int nGain = (int)pCut->nNodes - (int)pCut->nNodesDup - (nNodesAft - nNodesBef);
+ assert( nGain >= 1 - p->pPars->fZeroCost );
+ assert( Abc_ObjLevel(pObjNew) <= Required );
+/*
+ if ( nGain <= 0 )
+ {
+ int x = 0;
+ }
+ if ( Abc_ObjLevel(pObjNew) > Required )
+ {
+ int x = 0;
+ }
+*/
+ p->nGainTotal += nGain;
+ p->nChanges++;
+ if ( p->pPars->fVeryVerbose )
+ printf( "Performed resynthesis: Gain = %2d. Level = %2d. Req = %2d.\n", nGain, Abc_ObjLevel(pObjNew), Required );
+ Abc_NtkUpdate( p->pObj, pObjNew, p->vLevels );
+//printf( "%3d : %d-%d=%d(%d) \n", p->nChanges, nNodesBef, Abc_NtkNodeNum(p->pNtk), nNodesBef-Abc_NtkNodeNum(p->pNtk), nGain );
+ break;
+ }
+ }
+ return 1;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Performs resynthesis for one network.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Lpk_Resynthesize( Abc_Ntk_t * pNtk, Lpk_Par_t * pPars )
+{
+ ProgressBar * pProgress;
+ Lpk_Man_t * p;
+ Abc_Obj_t * pObj;
+ double Delta;
+ int i, Iter, nNodes, nNodesPrev, clk = clock();
+ assert( Abc_NtkIsLogic(pNtk) );
+
+ // sweep dangling nodes as a preprocessing step
+ Abc_NtkSweep( pNtk, 0 );
+
+ // get the number of inputs
+ pPars->nLutSize = Abc_NtkGetFaninMax( pNtk );
+ if ( pPars->nLutSize > 6 )
+ pPars->nLutSize = 6;
+ if ( pPars->nLutSize < 3 )
+ pPars->nLutSize = 3;
+ // adjust the number of crossbars based on LUT size
+ if ( pPars->nVarsShared > pPars->nLutSize - 2 )
+ pPars->nVarsShared = pPars->nLutSize - 2;
+ // get the max number of LUTs tried
+ pPars->nVarsMax = pPars->nLutsMax * (pPars->nLutSize - 1) + 1; // V = N * (K-1) + 1
+ while ( pPars->nVarsMax > 16 )
+ {
+ pPars->nLutsMax--;
+ pPars->nVarsMax = pPars->nLutsMax * (pPars->nLutSize - 1) + 1;
+
+ }
+ if ( pPars->fVerbose )
+ {
+ printf( "Resynthesis for %d %d-LUTs with %d non-MFFC LUTs, %d crossbars, and %d-input cuts.\n",
+ pPars->nLutsMax, pPars->nLutSize, pPars->nLutsOver, pPars->nVarsShared, pPars->nVarsMax );
+ }
+
+
+ // convert into the AIG
+ if ( !Abc_NtkToAig(pNtk) )
+ {
+ fprintf( stdout, "Converting to BDD has failed.\n" );
+ return 0;
+ }
+ assert( Abc_NtkHasAig(pNtk) );
+
+ // set the number of levels
+ Abc_NtkLevel( pNtk );
+ Abc_NtkStartReverseLevels( pNtk, pPars->nGrowthLevel );
+
+ // start the manager
+ p = Lpk_ManStart( pPars );
+ p->pNtk = pNtk;
+ p->nNodesTotal = Abc_NtkNodeNum(pNtk);
+ p->vLevels = Vec_VecStart( pNtk->LevelMax );
+ if ( p->pPars->fSatur )
+ p->vVisited = Vec_VecStart( 0 );
+ if ( pPars->fVerbose )
+ {
+ p->nTotalNets = Abc_NtkGetTotalFanins(pNtk);
+ p->nTotalNodes = Abc_NtkNodeNum(pNtk);
+ }
+
+ // iterate over the network
+ nNodesPrev = p->nNodesTotal;
+ for ( Iter = 1; ; Iter++ )
+ {
+ // expand storage for changed nodes
+ if ( p->pPars->fSatur )
+ Vec_VecExpand( p->vVisited, Abc_NtkObjNumMax(pNtk) + 1 );
+
+ // consider all nodes
+ nNodes = Abc_NtkObjNumMax(pNtk);
+ if ( !pPars->fVeryVerbose )
+ pProgress = Extra_ProgressBarStart( stdout, nNodes );
+ Abc_NtkForEachNode( pNtk, pObj, i )
+ {
+ // skip all except the final node
+ if ( pPars->fFirst )
+ {
+ if ( !Abc_ObjIsCo(Abc_ObjFanout0(pObj)) )
+ continue;
+ }
+ if ( i >= nNodes )
+ break;
+ if ( !pPars->fVeryVerbose )
+ Extra_ProgressBarUpdate( pProgress, i, NULL );
+ // skip the nodes that did not change
+ if ( p->pPars->fSatur && !Lpk_NodeHasChanged(p, pObj->Id) )
+ continue;
+ // resynthesize
+ p->pObj = pObj;
+ if ( p->pPars->fOldAlgo )
+ Lpk_ResynthesizeNode( p );
+ else
+ Lpk_ResynthesizeNodeNew( p );
+ }
+ if ( !pPars->fVeryVerbose )
+ Extra_ProgressBarStop( pProgress );
+
+ // check the increase
+ Delta = 100.00 * (nNodesPrev - Abc_NtkNodeNum(pNtk)) / p->nNodesTotal;
+ if ( Delta < 0.05 )
+ break;
+ nNodesPrev = Abc_NtkNodeNum(pNtk);
+ if ( !p->pPars->fSatur )
+ break;
+
+ if ( pPars->fFirst )
+ break;
+ }
+ Abc_NtkStopReverseLevels( pNtk );
+
+ if ( pPars->fVerbose )
+ {
+// Cloud_PrintInfo( p->pDsdMan->dd );
+ p->nTotalNets2 = Abc_NtkGetTotalFanins(pNtk);
+ p->nTotalNodes2 = Abc_NtkNodeNum(pNtk);
+ printf( "Node gain = %5d. (%.2f %%) ",
+ p->nTotalNodes-p->nTotalNodes2, 100.0*(p->nTotalNodes-p->nTotalNodes2)/p->nTotalNodes );
+ printf( "Edge gain = %5d. (%.2f %%) ",
+ p->nTotalNets-p->nTotalNets2, 100.0*(p->nTotalNets-p->nTotalNets2)/p->nTotalNets );
+ printf( "Muxes = %4d. Dsds = %4d.", p->nMuxes, p->nDsds );
+ printf( "\n" );
+ printf( "Nodes = %5d (%3d) Cuts = %5d (%4d) Changes = %5d Iter = %2d Benefit = %d.\n",
+ p->nNodesTotal, p->nNodesOver, p->nCutsTotal, p->nCutsUseful, p->nChanges, Iter, p->nBenefited );
+
+ printf( "Non-DSD:" );
+ for ( i = 3; i <= pPars->nVarsMax; i++ )
+ if ( p->nBlocks[i] )
+ printf( " %d=%d", i, p->nBlocks[i] );
+ printf( "\n" );
+
+ p->timeTotal = clock() - clk;
+ p->timeEval = p->timeEval - p->timeMap;
+ p->timeOther = p->timeTotal - p->timeCuts - p->timeTruth - p->timeEval - p->timeMap;
+ PRTP( "Cuts ", p->timeCuts, p->timeTotal );
+ PRTP( "Truth ", p->timeTruth, p->timeTotal );
+ PRTP( "CSupps", p->timeSupps, p->timeTotal );
+ PRTP( "Eval ", p->timeEval, p->timeTotal );
+ PRTP( " MuxAn", p->timeEvalMuxAn, p->timeEval );
+ PRTP( " MuxSp", p->timeEvalMuxSp, p->timeEval );
+ PRTP( " DsdAn", p->timeEvalDsdAn, p->timeEval );
+ PRTP( " DsdSp", p->timeEvalDsdSp, p->timeEval );
+ PRTP( " Other", p->timeEval-p->timeEvalMuxAn-p->timeEvalMuxSp-p->timeEvalDsdAn-p->timeEvalDsdSp, p->timeEval );
+ PRTP( "Map ", p->timeMap, p->timeTotal );
+ PRTP( "Other ", p->timeOther, p->timeTotal );
+ PRTP( "TOTAL ", p->timeTotal, p->timeTotal );
+ }
+
+ Lpk_ManStop( p );
+ // check the resulting network
+ if ( !Abc_NtkCheck( pNtk ) )
+ {
+ printf( "Lpk_Resynthesize: The network check has failed.\n" );
+ return 0;
+ }
+ return 1;
+}
+
+////////////////////////////////////////////////////////////////////////
+/// END OF FILE ///
+////////////////////////////////////////////////////////////////////////
+
+
diff --git a/src/opt/lpk/lpkCut.c b/src/opt/lpk/lpkCut.c
new file mode 100644
index 00000000..facd330b
--- /dev/null
+++ b/src/opt/lpk/lpkCut.c
@@ -0,0 +1,683 @@
+/**CFile****************************************************************
+
+ FileName [lpkCut.c]
+
+ SystemName [ABC: Logic synthesis and verification system.]
+
+ PackageName [Fast Boolean matching for LUT structures.]
+
+ Synopsis []
+
+ Author [Alan Mishchenko]
+
+ Affiliation [UC Berkeley]
+
+ Date [Ver. 1.0. Started - April 28, 2007.]
+
+ Revision [$Id: lpkCut.c,v 1.00 2007/04/28 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "lpkInt.h"
+#include "cloud.h"
+
+////////////////////////////////////////////////////////////////////////
+/// DECLARATIONS ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+/// FUNCTION DEFINITIONS ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+ Synopsis [Computes the truth table of one cut.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+CloudNode * Lpk_CutTruthBdd_rec( CloudManager * dd, Hop_Man_t * pMan, Hop_Obj_t * pObj, int nVars )
+{
+ CloudNode * pTruth, * pTruth0, * pTruth1;
+ assert( !Hop_IsComplement(pObj) );
+ if ( pObj->pData )
+ {
+ assert( ((unsigned)pObj->pData) & 0xffff0000 );
+ return pObj->pData;
+ }
+ // get the plan for a new truth table
+ if ( Hop_ObjIsConst1(pObj) )
+ pTruth = dd->one;
+ else
+ {
+ assert( Hop_ObjIsAnd(pObj) );
+ // compute the truth tables of the fanins
+ pTruth0 = Lpk_CutTruthBdd_rec( dd, pMan, Hop_ObjFanin0(pObj), nVars );
+ pTruth1 = Lpk_CutTruthBdd_rec( dd, pMan, Hop_ObjFanin1(pObj), nVars );
+ pTruth0 = Cloud_NotCond( pTruth0, Hop_ObjFaninC0(pObj) );
+ pTruth1 = Cloud_NotCond( pTruth1, Hop_ObjFaninC1(pObj) );
+ // creat the truth table of the node
+ pTruth = Cloud_bddAnd( dd, pTruth0, pTruth1 );
+ }
+ pObj->pData = pTruth;
+ return pTruth;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Verifies that the factoring is correct.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+CloudNode * Lpk_CutTruthBdd( Lpk_Man_t * p, Lpk_Cut_t * pCut )
+{
+ CloudManager * dd = p->pDsdMan->dd;
+ Hop_Man_t * pManHop = p->pNtk->pManFunc;
+ Hop_Obj_t * pObjHop;
+ Abc_Obj_t * pObj, * pFanin;
+ CloudNode * pTruth;
+ int i, k, iCount = 0;
+
+// return NULL;
+// Lpk_NodePrintCut( p, pCut );
+ // initialize the leaves
+ Lpk_CutForEachLeaf( p->pNtk, pCut, pObj, i )
+ pObj->pCopy = (Abc_Obj_t *)dd->vars[pCut->nLeaves-1-i];
+
+ // construct truth table in the topological order
+ Lpk_CutForEachNodeReverse( p->pNtk, pCut, pObj, i )
+ {
+ // get the local AIG
+ pObjHop = Hop_Regular(pObj->pData);
+ // clean the data field of the nodes in the AIG subgraph
+ Hop_ObjCleanData_rec( pObjHop );
+ // set the initial truth tables at the fanins
+ Abc_ObjForEachFanin( pObj, pFanin, k )
+ {
+ assert( ((unsigned)pFanin->pCopy) & 0xffff0000 );
+ Hop_ManPi( pManHop, k )->pData = pFanin->pCopy;
+ }
+ // compute the truth table of internal nodes
+ pTruth = Lpk_CutTruthBdd_rec( dd, pManHop, pObjHop, pCut->nLeaves );
+ if ( Hop_IsComplement(pObj->pData) )
+ pTruth = Cloud_Not(pTruth);
+ // set the truth table at the node
+ pObj->pCopy = (Abc_Obj_t *)pTruth;
+
+ }
+
+// Cloud_bddPrint( dd, pTruth );
+// printf( "Bdd size = %d. Total nodes = %d.\n", Cloud_DagSize( dd, pTruth ), dd->nNodesCur-dd->nVars-1 );
+ return pTruth;
+}
+
+
+/**Function*************************************************************
+
+ Synopsis [Computes the truth table of one cut.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+unsigned * Lpk_CutTruth_rec( Hop_Man_t * pMan, Hop_Obj_t * pObj, int nVars, Vec_Ptr_t * vTtNodes, int * piCount )
+{
+ unsigned * pTruth, * pTruth0, * pTruth1;
+ assert( !Hop_IsComplement(pObj) );
+ if ( pObj->pData )
+ {
+ assert( ((unsigned)pObj->pData) & 0xffff0000 );
+ return pObj->pData;
+ }
+ // get the plan for a new truth table
+ pTruth = Vec_PtrEntry( vTtNodes, (*piCount)++ );
+ if ( Hop_ObjIsConst1(pObj) )
+ Kit_TruthFill( pTruth, nVars );
+ else
+ {
+ assert( Hop_ObjIsAnd(pObj) );
+ // compute the truth tables of the fanins
+ pTruth0 = Lpk_CutTruth_rec( pMan, Hop_ObjFanin0(pObj), nVars, vTtNodes, piCount );
+ pTruth1 = Lpk_CutTruth_rec( pMan, Hop_ObjFanin1(pObj), nVars, vTtNodes, piCount );
+ // creat the truth table of the node
+ Kit_TruthAndPhase( pTruth, pTruth0, pTruth1, nVars, Hop_ObjFaninC0(pObj), Hop_ObjFaninC1(pObj) );
+ }
+ pObj->pData = pTruth;
+ return pTruth;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Computes the truth able of one cut.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+unsigned * Lpk_CutTruth( Lpk_Man_t * p, Lpk_Cut_t * pCut, int fInv )
+{
+ Hop_Man_t * pManHop = p->pNtk->pManFunc;
+ Hop_Obj_t * pObjHop;
+ Abc_Obj_t * pObj, * pFanin;
+ unsigned * pTruth;
+ int i, k, iCount = 0;
+// Lpk_NodePrintCut( p, pCut );
+ assert( pCut->nNodes > 0 );
+
+ // initialize the leaves
+ Lpk_CutForEachLeaf( p->pNtk, pCut, pObj, i )
+ pObj->pCopy = Vec_PtrEntry( p->vTtElems, fInv? pCut->nLeaves-1-i : i );
+
+ // construct truth table in the topological order
+ Lpk_CutForEachNodeReverse( p->pNtk, pCut, pObj, i )
+ {
+ // get the local AIG
+ pObjHop = Hop_Regular(pObj->pData);
+ // clean the data field of the nodes in the AIG subgraph
+ Hop_ObjCleanData_rec( pObjHop );
+ // set the initial truth tables at the fanins
+ Abc_ObjForEachFanin( pObj, pFanin, k )
+ {
+ assert( ((unsigned)pFanin->pCopy) & 0xffff0000 );
+ Hop_ManPi( pManHop, k )->pData = pFanin->pCopy;
+ }
+ // compute the truth table of internal nodes
+ pTruth = Lpk_CutTruth_rec( pManHop, pObjHop, pCut->nLeaves, p->vTtNodes, &iCount );
+ if ( Hop_IsComplement(pObj->pData) )
+ Kit_TruthNot( pTruth, pTruth, pCut->nLeaves );
+ // set the truth table at the node
+ pObj->pCopy = (Abc_Obj_t *)pTruth;
+ }
+
+ // make sure direct truth table is stored elsewhere (assuming the first call for direct truth!!!)
+ if ( fInv == 0 )
+ {
+ pTruth = Vec_PtrEntry( p->vTtNodes, iCount++ );
+ Kit_TruthCopy( pTruth, (unsigned *)pObj->pCopy, pCut->nLeaves );
+ }
+ assert( iCount <= Vec_PtrSize(p->vTtNodes) );
+ return pTruth;
+}
+
+
+/**Function*************************************************************
+
+ Synopsis [Returns 1 if at least one entry has changed.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Lpk_NodeRecordImpact( Lpk_Man_t * p )
+{
+ Lpk_Cut_t * pCut;
+ Vec_Ptr_t * vNodes = Vec_VecEntry( p->vVisited, p->pObj->Id );
+ Abc_Obj_t * pNode;
+ int i, k;
+ // collect the nodes that impact the given node
+ Vec_PtrClear( vNodes );
+ for ( i = 0; i < p->nCuts; i++ )
+ {
+ pCut = p->pCuts + i;
+ for ( k = 0; k < (int)pCut->nLeaves; k++ )
+ {
+ pNode = Abc_NtkObj( p->pNtk, pCut->pLeaves[k] );
+ if ( pNode->fMarkC )
+ continue;
+ pNode->fMarkC = 1;
+ Vec_PtrPush( vNodes, (void *)pNode->Id );
+ Vec_PtrPush( vNodes, (void *)Abc_ObjFanoutNum(pNode) );
+ }
+ }
+ // clear the marks
+ Vec_PtrForEachEntry( vNodes, pNode, i )
+ {
+ pNode = Abc_NtkObj( p->pNtk, (int)pNode );
+ pNode->fMarkC = 0;
+ i++;
+ }
+//printf( "%d ", Vec_PtrSize(vNodes) );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Returns 1 if the cut has structural DSD.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Lpk_NodeCutsCheckDsd( Lpk_Man_t * p, Lpk_Cut_t * pCut )
+{
+ Abc_Obj_t * pObj, * pFanin;
+ int i, k, nCands, fLeavesOnly, RetValue;
+ assert( pCut->nLeaves > 0 );
+ // clear ref counters
+ memset( p->pRefs, 0, sizeof(int) * pCut->nLeaves );
+ // mark cut leaves
+ Lpk_CutForEachLeaf( p->pNtk, pCut, pObj, i )
+ {
+ assert( pObj->fMarkA == 0 );
+ pObj->fMarkA = 1;
+ pObj->pCopy = (void *)i;
+ }
+ // ref leaves pointed from the internal nodes
+ nCands = 0;
+ Lpk_CutForEachNode( p->pNtk, pCut, pObj, i )
+ {
+ fLeavesOnly = 1;
+ Abc_ObjForEachFanin( pObj, pFanin, k )
+ if ( pFanin->fMarkA )
+ p->pRefs[(int)pFanin->pCopy]++;
+ else
+ fLeavesOnly = 0;
+ if ( fLeavesOnly )
+ p->pCands[nCands++] = pObj->Id;
+ }
+ // look at the nodes that only point to the leaves
+ RetValue = 0;
+ for ( i = 0; i < nCands; i++ )
+ {
+ pObj = Abc_NtkObj( p->pNtk, p->pCands[i] );
+ Abc_ObjForEachFanin( pObj, pFanin, k )
+ {
+ assert( pFanin->fMarkA == 1 );
+ if ( p->pRefs[(int)pFanin->pCopy] > 1 )
+ break;
+ }
+ if ( k == Abc_ObjFaninNum(pObj) )
+ {
+ RetValue = 1;
+ break;
+ }
+ }
+ // unmark cut leaves
+ Lpk_CutForEachLeaf( p->pNtk, pCut, pObj, i )
+ pObj->fMarkA = 0;
+ return RetValue;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Returns 1 if pDom is contained in pCut.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+static inline int Lpk_NodeCutsOneDominance( Lpk_Cut_t * pDom, Lpk_Cut_t * pCut )
+{
+ int i, k;
+ for ( i = 0; i < (int)pDom->nLeaves; i++ )
+ {
+ for ( k = 0; k < (int)pCut->nLeaves; k++ )
+ if ( pDom->pLeaves[i] == pCut->pLeaves[k] )
+ break;
+ if ( k == (int)pCut->nLeaves ) // node i in pDom is not contained in pCut
+ return 0;
+ }
+ // every node in pDom is contained in pCut
+ return 1;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Check if the cut exists.]
+
+ Description [Returns 1 if the cut exists.]
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Lpk_NodeCutsOneFilter( Lpk_Cut_t * pCuts, int nCuts, Lpk_Cut_t * pCutNew )
+{
+ Lpk_Cut_t * pCut;
+ int i, k;
+ assert( pCutNew->uSign[0] || pCutNew->uSign[1] );
+ // try to find the cut
+ for ( i = 0; i < nCuts; i++ )
+ {
+ pCut = pCuts + i;
+ if ( pCut->nLeaves == 0 )
+ continue;
+ if ( pCut->nLeaves == pCutNew->nLeaves )
+ {
+ if ( pCut->uSign[0] == pCutNew->uSign[0] && pCut->uSign[1] == pCutNew->uSign[1] )
+ {
+ for ( k = 0; k < (int)pCutNew->nLeaves; k++ )
+ if ( pCut->pLeaves[k] != pCutNew->pLeaves[k] )
+ break;
+ if ( k == (int)pCutNew->nLeaves )
+ return 1;
+ }
+ continue;
+ }
+ if ( pCut->nLeaves < pCutNew->nLeaves )
+ {
+ // skip the non-contained cuts
+ if ( (pCut->uSign[0] & pCutNew->uSign[0]) != pCut->uSign[0] )
+ continue;
+ if ( (pCut->uSign[1] & pCutNew->uSign[1]) != pCut->uSign[1] )
+ continue;
+ // check containment seriously
+ if ( Lpk_NodeCutsOneDominance( pCut, pCutNew ) )
+ return 1;
+ continue;
+ }
+ // check potential containment of other cut
+
+ // skip the non-contained cuts
+ if ( (pCut->uSign[0] & pCutNew->uSign[0]) != pCutNew->uSign[0] )
+ continue;
+ if ( (pCut->uSign[1] & pCutNew->uSign[1]) != pCutNew->uSign[1] )
+ continue;
+ // check containment seriously
+ if ( Lpk_NodeCutsOneDominance( pCutNew, pCut ) )
+ pCut->nLeaves = 0; // removed
+ }
+ return 0;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Prints the given cut.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Lpk_NodePrintCut( Lpk_Man_t * p, Lpk_Cut_t * pCut, int fLeavesOnly )
+{
+ Abc_Obj_t * pObj;
+ int i;
+ if ( !fLeavesOnly )
+ printf( "LEAVES:\n" );
+ Lpk_CutForEachLeaf( p->pNtk, pCut, pObj, i )
+ printf( "%d,", pObj->Id );
+ if ( !fLeavesOnly )
+ {
+ printf( "\nNODES:\n" );
+ Lpk_CutForEachNode( p->pNtk, pCut, pObj, i )
+ {
+ printf( "%d,", pObj->Id );
+ assert( Abc_ObjIsNode(pObj) );
+ }
+ printf( "\n" );
+ }
+}
+
+/**Function*************************************************************
+
+ Synopsis [Set the cut signature.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Lpk_NodeCutSignature( Lpk_Cut_t * pCut )
+{
+ unsigned i;
+ pCut->uSign[0] = pCut->uSign[1] = 0;
+ for ( i = 0; i < pCut->nLeaves; i++ )
+ {
+ pCut->uSign[(pCut->pLeaves[i] & 32) > 0] |= (1 << (pCut->pLeaves[i] & 31));
+ if ( i != pCut->nLeaves - 1 )
+ assert( pCut->pLeaves[i] < pCut->pLeaves[i+1] );
+ }
+}
+
+
+/**Function*************************************************************
+
+ Synopsis [Computes the set of all cuts.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Lpk_NodeCutsOne( Lpk_Man_t * p, Lpk_Cut_t * pCut, int Node )
+{
+ Lpk_Cut_t * pCutNew;
+ Abc_Obj_t * pObj, * pFanin;
+ int i, k, j, nLeavesNew;
+/*
+ printf( "Exploring cut " );
+ Lpk_NodePrintCut( p, pCut, 1 );
+ printf( "with node %d\n", Node );
+*/
+ // check if the cut can stand adding one more internal node
+ if ( pCut->nNodes == LPK_SIZE_MAX )
+ return;
+
+ // if the node is a PI, quit
+ pObj = Abc_NtkObj( p->pNtk, Node );
+ if ( Abc_ObjIsCi(pObj) )
+ return;
+ assert( Abc_ObjIsNode(pObj) );
+// assert( Abc_ObjFaninNum(pObj) <= p->pPars->nLutSize );
+
+ // if the node is not in the MFFC, check the limit
+ if ( !Abc_NodeIsTravIdCurrent(pObj) )
+ {
+ if ( (int)pCut->nNodesDup == p->pPars->nLutsOver )
+ return;
+ assert( (int)pCut->nNodesDup < p->pPars->nLutsOver );
+ }
+
+ // check the possibility of adding this node using the signature
+ nLeavesNew = pCut->nLeaves - 1;
+ Abc_ObjForEachFanin( pObj, pFanin, i )
+ {
+ if ( (pCut->uSign[(pFanin->Id & 32) > 0] & (1 << (pFanin->Id & 31))) )
+ continue;
+ if ( ++nLeavesNew > p->pPars->nVarsMax )
+ return;
+ }
+
+ // initialize the set of leaves to the nodes in the cut
+ assert( p->nCuts < LPK_CUTS_MAX );
+ pCutNew = p->pCuts + p->nCuts;
+ pCutNew->nLeaves = 0;
+ for ( i = 0; i < (int)pCut->nLeaves; i++ )
+ if ( pCut->pLeaves[i] != Node )
+ pCutNew->pLeaves[pCutNew->nLeaves++] = pCut->pLeaves[i];
+
+ // add new nodes
+ Abc_ObjForEachFanin( pObj, pFanin, i )
+ {
+ // find the place where this node belongs
+ for ( k = 0; k < (int)pCutNew->nLeaves; k++ )
+ if ( pCutNew->pLeaves[k] >= pFanin->Id )
+ break;
+ if ( k < (int)pCutNew->nLeaves && pCutNew->pLeaves[k] == pFanin->Id )
+ continue;
+ // check if there is room
+ if ( (int)pCutNew->nLeaves == p->pPars->nVarsMax )
+ return;
+ // move all the nodes
+ for ( j = pCutNew->nLeaves; j > k; j-- )
+ pCutNew->pLeaves[j] = pCutNew->pLeaves[j-1];
+ pCutNew->pLeaves[k] = pFanin->Id;
+ pCutNew->nLeaves++;
+ assert( pCutNew->nLeaves <= LPK_SIZE_MAX );
+
+ }
+ // skip the contained cuts
+ Lpk_NodeCutSignature( pCutNew );
+ if ( Lpk_NodeCutsOneFilter( p->pCuts, p->nCuts, pCutNew ) )
+ return;
+
+ // update the set of internal nodes
+ assert( pCut->nNodes < LPK_SIZE_MAX );
+ memcpy( pCutNew->pNodes, pCut->pNodes, pCut->nNodes * sizeof(int) );
+ pCutNew->nNodes = pCut->nNodes;
+ pCutNew->nNodesDup = pCut->nNodesDup;
+
+ // check if the node is already there
+ // if so, move the node to be the last
+ for ( i = 0; i < (int)pCutNew->nNodes; i++ )
+ if ( pCutNew->pNodes[i] == Node )
+ {
+ for ( k = i; k < (int)pCutNew->nNodes - 1; k++ )
+ pCutNew->pNodes[k] = pCutNew->pNodes[k+1];
+ pCutNew->pNodes[k] = Node;
+ break;
+ }
+ if ( i == (int)pCutNew->nNodes ) // new node
+ {
+ pCutNew->pNodes[ pCutNew->nNodes++ ] = Node;
+ pCutNew->nNodesDup += !Abc_NodeIsTravIdCurrent(pObj);
+ }
+ // the number of nodes does not exceed MFFC plus duplications
+ assert( pCutNew->nNodes <= p->nMffc + pCutNew->nNodesDup );
+ // add the cut to storage
+ assert( p->nCuts < LPK_CUTS_MAX );
+ p->nCuts++;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Computes the set of all cuts.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Lpk_NodeCuts( Lpk_Man_t * p )
+{
+ Lpk_Cut_t * pCut, * pCut2;
+ int i, k, Temp, nMffc, fChanges;
+
+ // mark the MFFC of the node with the current trav ID
+ nMffc = p->nMffc = Abc_NodeMffcLabel( p->pObj );
+ assert( nMffc > 0 );
+ if ( nMffc == 1 )
+ return 0;
+
+ // initialize the first cut
+ pCut = p->pCuts; p->nCuts = 1;
+ pCut->nNodes = 0;
+ pCut->nNodesDup = 0;
+ pCut->nLeaves = 1;
+ pCut->pLeaves[0] = p->pObj->Id;
+ // assign the signature
+ Lpk_NodeCutSignature( pCut );
+
+ // perform the cut computation
+ for ( i = 0; i < p->nCuts; i++ )
+ {
+ pCut = p->pCuts + i;
+ if ( pCut->nLeaves == 0 )
+ continue;
+
+ // try to expand the fanins of this cut
+ for ( k = 0; k < (int)pCut->nLeaves; k++ )
+ {
+ // create a new cut
+ Lpk_NodeCutsOne( p, pCut, pCut->pLeaves[k] );
+ // quit if the number of cuts has exceeded the limit
+ if ( p->nCuts == LPK_CUTS_MAX )
+ break;
+ }
+ if ( p->nCuts == LPK_CUTS_MAX )
+ break;
+ }
+ if ( p->nCuts == LPK_CUTS_MAX )
+ p->nNodesOver++;
+
+ // record the impact of this node
+ if ( p->pPars->fSatur )
+ Lpk_NodeRecordImpact( p );
+
+ // compress the cuts by removing empty ones, those with negative Weight, and decomposable ones
+ p->nEvals = 0;
+ for ( i = 0; i < p->nCuts; i++ )
+ {
+ pCut = p->pCuts + i;
+ if ( pCut->nLeaves < 2 )
+ continue;
+ // compute the minimum number of LUTs needed to implement this cut
+ // V = N * (K-1) + 1 ~~~~~ N = Ceiling[(V-1)/(K-1)] = (V-1)/(K-1) + [(V-1)%(K-1) > 0]
+ pCut->nLuts = Lpk_LutNumLuts( pCut->nLeaves, p->pPars->nLutSize );
+// pCut->Weight = (float)1.0 * (pCut->nNodes - pCut->nNodesDup - 1) / pCut->nLuts; //p->pPars->nLutsMax;
+ pCut->Weight = (float)1.0 * (pCut->nNodes - pCut->nNodesDup) / pCut->nLuts; //p->pPars->nLutsMax;
+ if ( pCut->Weight <= 1.001 )
+// if ( pCut->Weight <= 0.999 )
+ continue;
+ pCut->fHasDsd = Lpk_NodeCutsCheckDsd( p, pCut );
+ if ( pCut->fHasDsd )
+ continue;
+ p->pEvals[p->nEvals++] = i;
+ }
+ if ( p->nEvals == 0 )
+ return 0;
+
+ // sort the cuts by Weight
+ do {
+ fChanges = 0;
+ for ( i = 0; i < p->nEvals - 1; i++ )
+ {
+ pCut = p->pCuts + p->pEvals[i];
+ pCut2 = p->pCuts + p->pEvals[i+1];
+ if ( pCut->Weight >= pCut2->Weight - 0.001 )
+ continue;
+ Temp = p->pEvals[i];
+ p->pEvals[i] = p->pEvals[i+1];
+ p->pEvals[i+1] = Temp;
+ fChanges = 1;
+ }
+ } while ( fChanges );
+/*
+ for ( i = 0; i < p->nEvals; i++ )
+ {
+ pCut = p->pCuts + p->pEvals[i];
+ printf( "Cut %3d : W = %5.2f.\n", i, pCut->Weight );
+ }
+ printf( "\n" );
+*/
+ return 1;
+}
+
+////////////////////////////////////////////////////////////////////////
+/// END OF FILE ///
+////////////////////////////////////////////////////////////////////////
+
+
diff --git a/src/opt/lpk/lpkInt.h b/src/opt/lpk/lpkInt.h
new file mode 100644
index 00000000..960599e4
--- /dev/null
+++ b/src/opt/lpk/lpkInt.h
@@ -0,0 +1,246 @@
+/**CFile****************************************************************
+
+ FileName [lpkInt.h]
+
+ SystemName [ABC: Logic synthesis and verification system.]
+
+ PackageName [Fast Boolean matching for LUT structures.]
+
+ Synopsis [Internal declarations.]
+
+ Author [Alan Mishchenko]
+
+ Affiliation [UC Berkeley]
+
+ Date [Ver. 1.0. Started - April 28, 2007.]
+
+ Revision [$Id: lpkInt.h,v 1.00 2007/04/28 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#ifndef __LPK_INT_H__
+#define __LPK_INT_H__
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+////////////////////////////////////////////////////////////////////////
+/// INCLUDES ///
+////////////////////////////////////////////////////////////////////////
+
+#include "abc.h"
+#include "kit.h"
+#include "if.h"
+#include "lpk.h"
+
+////////////////////////////////////////////////////////////////////////
+/// PARAMETERS ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+/// BASIC TYPES ///
+////////////////////////////////////////////////////////////////////////
+
+#define LPK_SIZE_MAX 24 // the largest size of the function
+#define LPK_CUTS_MAX 512 // the largest number of cuts considered
+
+typedef struct Lpk_Man_t_ Lpk_Man_t;
+typedef struct Lpk_Cut_t_ Lpk_Cut_t;
+
+struct Lpk_Cut_t_
+{
+ unsigned nLeaves : 6; // (L) the number of leaves
+ unsigned nNodes : 6; // (M) the number of nodes
+ unsigned nNodesDup : 6; // (Q) nodes outside of MFFC
+ unsigned nLuts : 6; // (N) the number of LUTs to try
+ unsigned unused : 6; // unused
+ unsigned fHasDsd : 1; // set to 1 if the cut has structural DSD (and so cannot be used)
+ unsigned fMark : 1; // multipurpose mark
+ unsigned uSign[2]; // the signature
+ float Weight; // the weight of the cut: (M - Q)/N(V) (the larger the better)
+ int Gain; // the gain achieved using this cut
+ int pLeaves[LPK_SIZE_MAX]; // the leaves of the cut
+ int pNodes[LPK_SIZE_MAX]; // the nodes of the cut
+};
+
+struct Lpk_Man_t_
+{
+ // parameters
+ Lpk_Par_t * pPars; // the set of parameters
+ // current representation
+ Abc_Ntk_t * pNtk; // the network
+ Abc_Obj_t * pObj; // the node to resynthesize
+ // cut representation
+ int nMffc; // the size of MFFC of the node
+ int nCuts; // the total number of cuts
+ int nCutsMax; // the largest possible number of cuts
+ int nEvals; // the number of good cuts
+ Lpk_Cut_t pCuts[LPK_CUTS_MAX]; // the storage for cuts
+ int pEvals[LPK_CUTS_MAX]; // the good cuts
+ // visited nodes
+ Vec_Vec_t * vVisited;
+ // mapping manager
+ If_Man_t * pIfMan;
+ Vec_Int_t * vCover;
+ Vec_Vec_t * vLevels;
+ // temporary variables
+ int fCofactoring; // working in the cofactoring mode
+ int fCalledOnce; // limits the depth of MUX cofactoring
+ int nCalledSRed; // the number of called to SRed
+ int pRefs[LPK_SIZE_MAX]; // fanin reference counters
+ int pCands[LPK_SIZE_MAX]; // internal nodes pointing only to the leaves
+ Vec_Ptr_t * vLeaves;
+ // truth table representation
+ Vec_Ptr_t * vTtElems; // elementary truth tables
+ Vec_Ptr_t * vTtNodes; // storage for temporary truth tables of the nodes
+ Vec_Int_t * vMemory;
+ Vec_Int_t * vBddDir;
+ Vec_Int_t * vBddInv;
+ unsigned puSupps[32]; // the supports of the cofactors
+ unsigned * ppTruths[5][16];
+ // variable sets
+ Vec_Int_t * vSets[8];
+ Kit_DsdMan_t* pDsdMan;
+ // statistics
+ int nNodesTotal; // total number of nodes
+ int nNodesOver; // nodes with cuts over the limit
+ int nCutsTotal; // total number of cuts
+ int nCutsUseful; // useful cuts
+ int nGainTotal; // the gain in LUTs
+ int nChanges; // the number of changed nodes
+ int nBenefited; // the number of gainful that benefited from decomposition
+ int nMuxes;
+ int nDsds;
+ int nTotalNets;
+ int nTotalNets2;
+ int nTotalNodes;
+ int nTotalNodes2;
+ // counter of non-DSD blocks
+ int nBlocks[17];
+ // runtime
+ int timeCuts;
+ int timeTruth;
+ int timeSupps;
+ int timeTruth2;
+ int timeTruth3;
+ int timeEval;
+ int timeMap;
+ int timeOther;
+ int timeTotal;
+ // runtime of eval
+ int timeEvalMuxAn;
+ int timeEvalMuxSp;
+ int timeEvalDsdAn;
+ int timeEvalDsdSp;
+
+};
+
+
+// internal representation of the function to be decomposed
+typedef struct Lpk_Fun_t_ Lpk_Fun_t;
+struct Lpk_Fun_t_
+{
+ Vec_Ptr_t * vNodes; // the array of leaves and decomposition nodes
+ unsigned Id : 7; // the ID of this node
+ unsigned nVars : 5; // the number of variables
+ unsigned nLutK : 4; // the number of LUT inputs
+ unsigned nAreaLim : 5; // the area limit (the largest allowed)
+ unsigned nDelayLim : 9; // the delay limit (the largest allowed)
+ unsigned fSupports : 1; // supports of cofactors were precomputed
+ unsigned fMark : 1; // marks the MUX-based dec
+ unsigned uSupp; // the support of this component
+ unsigned puSupps[32]; // the supports of the cofactors
+ char pDelays[16]; // the delays of the inputs
+ char pFanins[16]; // the fanins of this function
+ unsigned pTruth[0]; // the truth table (contains room for three truth tables)
+};
+
+// preliminary decomposition result
+typedef struct Lpk_Res_t_ Lpk_Res_t;
+struct Lpk_Res_t_
+{
+ int nBSVars; // the number of bound set variables
+ unsigned BSVars; // the bound set
+ int nCofVars; // the number of cofactoring variables
+ char pCofVars[4]; // the cofactoring variables
+ int nSuppSizeS; // support size of the smaller (decomposed) function
+ int nSuppSizeL; // support size of the larger (composition) function
+ int DelayEst; // estimated delay of the decomposition
+ int AreaEst; // estimated area of the decomposition
+ int Variable; // variable in MUX decomposition
+ int Polarity; // polarity in MUX decomposition
+};
+
+static inline int Lpk_LutNumVars( int nLutsLim, int nLutK ) { return nLutsLim * (nLutK - 1) + 1; }
+static inline int Lpk_LutNumLuts( int nVarsMax, int nLutK ) { return (nVarsMax - 1) / (nLutK - 1) + (int)((nVarsMax - 1) % (nLutK - 1) > 0); }
+static inline unsigned * Lpk_FunTruth( Lpk_Fun_t * p, int Num ) { assert( Num < 3 ); return p->pTruth + Kit_TruthWordNum(p->nVars) * Num; }
+
+////////////////////////////////////////////////////////////////////////
+/// MACRO DEFINITIONS ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+/// ITERATORS ///
+////////////////////////////////////////////////////////////////////////
+
+#define Lpk_CutForEachLeaf( pNtk, pCut, pObj, i ) \
+ for ( i = 0; (i < (int)(pCut)->nLeaves) && (((pObj) = Abc_NtkObj(pNtk, (pCut)->pLeaves[i])), 1); i++ )
+#define Lpk_CutForEachNode( pNtk, pCut, pObj, i ) \
+ for ( i = 0; (i < (int)(pCut)->nNodes) && (((pObj) = Abc_NtkObj(pNtk, (pCut)->pNodes[i])), 1); i++ )
+#define Lpk_CutForEachNodeReverse( pNtk, pCut, pObj, i ) \
+ for ( i = (int)(pCut)->nNodes - 1; (i >= 0) && (((pObj) = Abc_NtkObj(pNtk, (pCut)->pNodes[i])), 1); i-- )
+#define Lpk_SuppForEachVar( Supp, Var )\
+ for ( Var = 0; Var < 16; Var++ )\
+ if ( !(Supp & (1<<Var)) ) {} else
+
+////////////////////////////////////////////////////////////////////////
+/// FUNCTION DECLARATIONS ///
+////////////////////////////////////////////////////////////////////////
+
+/*=== lpkAbcDec.c ============================================================*/
+extern Abc_Obj_t * Lpk_Decompose( Lpk_Man_t * pMan, Abc_Ntk_t * pNtk, Vec_Ptr_t * vLeaves, unsigned * pTruth, unsigned * puSupps, int nLutK, int AreaLim, int DelayLim );
+/*=== lpkAbcDsd.c ============================================================*/
+extern Lpk_Res_t * Lpk_DsdAnalize( Lpk_Man_t * pMan, Lpk_Fun_t * p, int nShared );
+extern Lpk_Fun_t * Lpk_DsdSplit( Lpk_Man_t * pMan, Lpk_Fun_t * p, char * pCofVars, int nCofVars, unsigned uBoundSet );
+/*=== lpkAbcMux.c ============================================================*/
+extern Lpk_Res_t * Lpk_MuxAnalize( Lpk_Man_t * pMan, Lpk_Fun_t * p );
+extern Lpk_Fun_t * Lpk_MuxSplit( Lpk_Man_t * pMan, Lpk_Fun_t * p, int Var, int Pol );
+/*=== lpkAbcUtil.c ============================================================*/
+extern Lpk_Fun_t * Lpk_FunAlloc( int nVars );
+extern void Lpk_FunFree( Lpk_Fun_t * p );
+extern Lpk_Fun_t * Lpk_FunCreate( Abc_Ntk_t * pNtk, Vec_Ptr_t * vLeaves, unsigned * pTruth, int nLutK, int AreaLim, int DelayLim );
+extern Lpk_Fun_t * Lpk_FunDup( Lpk_Fun_t * p, unsigned * pTruth );
+extern int Lpk_FunSuppMinimize( Lpk_Fun_t * p );
+extern void Lpk_FunComputeCofSupps( Lpk_Fun_t * p );
+extern int Lpk_SuppDelay( unsigned uSupp, char * pDelays );
+extern int Lpk_SuppToVars( unsigned uBoundSet, char * pVars );
+
+
+/*=== lpkCut.c =========================================================*/
+extern unsigned * Lpk_CutTruth( Lpk_Man_t * p, Lpk_Cut_t * pCut, int fInv );
+extern int Lpk_NodeCuts( Lpk_Man_t * p );
+/*=== lpkMap.c =========================================================*/
+extern Lpk_Man_t * Lpk_ManStart( Lpk_Par_t * pPars );
+extern void Lpk_ManStop( Lpk_Man_t * p );
+/*=== lpkMap.c =========================================================*/
+extern If_Obj_t * Lpk_MapPrime( Lpk_Man_t * p, unsigned * pTruth, int nVars, If_Obj_t ** ppLeaves );
+extern If_Obj_t * Lpk_MapTree_rec( Lpk_Man_t * p, Kit_DsdNtk_t * pNtk, If_Obj_t ** ppLeaves, int iLit, If_Obj_t * pResult );
+/*=== lpkMulti.c =======================================================*/
+extern If_Obj_t * Lpk_MapTreeMulti( Lpk_Man_t * p, unsigned * pTruth, int nLeaves, If_Obj_t ** ppLeaves );
+/*=== lpkMux.c =========================================================*/
+extern If_Obj_t * Lpk_MapTreeMux_rec( Lpk_Man_t * p, unsigned * pTruth, int nVars, If_Obj_t ** ppLeaves );
+extern If_Obj_t * Lpk_MapSuppRedDec_rec( Lpk_Man_t * p, unsigned * pTruth, int nVars, If_Obj_t ** ppLeaves );
+/*=== lpkSets.c =========================================================*/
+extern unsigned Lpk_MapSuppRedDecSelect( Lpk_Man_t * p, unsigned * pTruth, int nVars, int * piVar, int * piVarReused );
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
+
+////////////////////////////////////////////////////////////////////////
+/// END OF FILE ///
+////////////////////////////////////////////////////////////////////////
+
diff --git a/src/opt/lpk/lpkMan.c b/src/opt/lpk/lpkMan.c
new file mode 100644
index 00000000..af6a5307
--- /dev/null
+++ b/src/opt/lpk/lpkMan.c
@@ -0,0 +1,122 @@
+/**CFile****************************************************************
+
+ FileName [lpkMan.c]
+
+ SystemName [ABC: Logic synthesis and verification system.]
+
+ PackageName [Fast Boolean matching for LUT structures.]
+
+ Synopsis []
+
+ Author [Alan Mishchenko]
+
+ Affiliation [UC Berkeley]
+
+ Date [Ver. 1.0. Started - April 28, 2007.]
+
+ Revision [$Id: lpkMan.c,v 1.00 2007/04/28 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "lpkInt.h"
+
+////////////////////////////////////////////////////////////////////////
+/// DECLARATIONS ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+/// FUNCTION DEFINITIONS ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Lpk_Man_t * Lpk_ManStart( Lpk_Par_t * pPars )
+{
+ Lpk_Man_t * p;
+ int i, nWords;
+ assert( pPars->nLutsMax <= 16 );
+ assert( pPars->nVarsMax > 0 && pPars->nVarsMax <= 16 );
+ p = ALLOC( Lpk_Man_t, 1 );
+ memset( p, 0, sizeof(Lpk_Man_t) );
+ p->pPars = pPars;
+ p->nCutsMax = LPK_CUTS_MAX;
+ p->vTtElems = Vec_PtrAllocTruthTables( pPars->nVarsMax );
+ p->vTtNodes = Vec_PtrAllocSimInfo( 1024, Abc_TruthWordNum(pPars->nVarsMax) );
+ p->vCover = Vec_IntAlloc( 1 << 12 );
+ p->vLeaves = Vec_PtrAlloc( 32 );
+ for ( i = 0; i < 8; i++ )
+ p->vSets[i] = Vec_IntAlloc(100);
+ p->pDsdMan = Kit_DsdManAlloc( pPars->nVarsMax, 64 );
+ p->vMemory = Vec_IntAlloc( 1024 * 32 );
+ p->vBddDir = Vec_IntAlloc( 256 );
+ p->vBddInv = Vec_IntAlloc( 256 );
+ // allocate temporary storage for truth tables
+ nWords = Kit_TruthWordNum(pPars->nVarsMax);
+ p->ppTruths[0][0] = ALLOC( unsigned, 32 * nWords );
+ p->ppTruths[1][0] = p->ppTruths[0][0] + 1 * nWords;
+ for ( i = 1; i < 2; i++ )
+ p->ppTruths[1][i] = p->ppTruths[1][0] + i * nWords;
+ p->ppTruths[2][0] = p->ppTruths[1][0] + 2 * nWords;
+ for ( i = 1; i < 4; i++ )
+ p->ppTruths[2][i] = p->ppTruths[2][0] + i * nWords;
+ p->ppTruths[3][0] = p->ppTruths[2][0] + 4 * nWords;
+ for ( i = 1; i < 8; i++ )
+ p->ppTruths[3][i] = p->ppTruths[3][0] + i * nWords;
+ p->ppTruths[4][0] = p->ppTruths[3][0] + 8 * nWords;
+ for ( i = 1; i < 16; i++ )
+ p->ppTruths[4][i] = p->ppTruths[4][0] + i * nWords;
+ return p;
+}
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Lpk_ManStop( Lpk_Man_t * p )
+{
+ int i;
+ free( p->ppTruths[0][0] );
+ Vec_IntFree( p->vBddDir );
+ Vec_IntFree( p->vBddInv );
+ Vec_IntFree( p->vMemory );
+ Kit_DsdManFree( p->pDsdMan );
+ for ( i = 0; i < 8; i++ )
+ Vec_IntFree(p->vSets[i]);
+ if ( p->pIfMan )
+ {
+ void * pPars = p->pIfMan->pPars;
+ If_ManStop( p->pIfMan );
+ free( pPars );
+ }
+ if ( p->vLevels )
+ Vec_VecFree( p->vLevels );
+ if ( p->vVisited )
+ Vec_VecFree( p->vVisited );
+ Vec_PtrFree( p->vLeaves );
+ Vec_IntFree( p->vCover );
+ Vec_PtrFree( p->vTtElems );
+ Vec_PtrFree( p->vTtNodes );
+ free( p );
+}
+
+////////////////////////////////////////////////////////////////////////
+/// END OF FILE ///
+////////////////////////////////////////////////////////////////////////
+
+
diff --git a/src/opt/lpk/lpkMap.c b/src/opt/lpk/lpkMap.c
new file mode 100644
index 00000000..698aeea1
--- /dev/null
+++ b/src/opt/lpk/lpkMap.c
@@ -0,0 +1,205 @@
+/**CFile****************************************************************
+
+ FileName [lpkMap.c]
+
+ SystemName [ABC: Logic synthesis and verification system.]
+
+ PackageName [Fast Boolean matching for LUT structures.]
+
+ Synopsis []
+
+ Author [Alan Mishchenko]
+
+ Affiliation [UC Berkeley]
+
+ Date [Ver. 1.0. Started - April 28, 2007.]
+
+ Revision [$Id: lpkMap.c,v 1.00 2007/04/28 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "lpkInt.h"
+
+////////////////////////////////////////////////////////////////////////
+/// DECLARATIONS ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+/// FUNCTION DEFINITIONS ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+ Synopsis [Transforms the decomposition graph into the AIG.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+If_Obj_t * Lpk_MapPrimeInternal( If_Man_t * pIfMan, Kit_Graph_t * pGraph )
+{
+ Kit_Node_t * pNode;
+ If_Obj_t * pAnd0, * pAnd1;
+ int i;
+ // check for constant function
+ if ( Kit_GraphIsConst(pGraph) )
+ return If_ManConst1(pIfMan);
+ // check for a literal
+ if ( Kit_GraphIsVar(pGraph) )
+ return Kit_GraphVar(pGraph)->pFunc;
+ // build the AIG nodes corresponding to the AND gates of the graph
+ Kit_GraphForEachNode( pGraph, pNode, i )
+ {
+ pAnd0 = Kit_GraphNode(pGraph, pNode->eEdge0.Node)->pFunc;
+ pAnd1 = Kit_GraphNode(pGraph, pNode->eEdge1.Node)->pFunc;
+ pNode->pFunc = If_ManCreateAnd( pIfMan,
+ If_NotCond( If_Regular(pAnd0), If_IsComplement(pAnd0) ^ pNode->eEdge0.fCompl ),
+ If_NotCond( If_Regular(pAnd1), If_IsComplement(pAnd1) ^ pNode->eEdge1.fCompl ) );
+ }
+ return pNode->pFunc;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Strashes one logic node using its SOP.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+If_Obj_t * Lpk_MapPrime( Lpk_Man_t * p, unsigned * pTruth, int nVars, If_Obj_t ** ppLeaves )
+{
+ Kit_Graph_t * pGraph;
+ Kit_Node_t * pNode;
+ If_Obj_t * pRes;
+ int i;
+ // derive the factored form
+ pGraph = Kit_TruthToGraph( pTruth, nVars, p->vCover );
+ if ( pGraph == NULL )
+ return NULL;
+ // collect the fanins
+ Kit_GraphForEachLeaf( pGraph, pNode, i )
+ pNode->pFunc = ppLeaves[i];
+ // perform strashing
+ pRes = Lpk_MapPrimeInternal( p->pIfMan, pGraph );
+ pRes = If_NotCond( pRes, Kit_GraphIsComplement(pGraph) );
+ Kit_GraphFree( pGraph );
+ return pRes;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Prepares the mapping manager.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+If_Obj_t * Lpk_MapTree_rec( Lpk_Man_t * p, Kit_DsdNtk_t * pNtk, If_Obj_t ** ppLeaves, int iLit, If_Obj_t * pResult )
+{
+ Kit_DsdObj_t * pObj;
+ If_Obj_t * pObjNew = NULL, * pObjNew2 = NULL, * pFansNew[16];
+ unsigned i, iLitFanin;
+
+ assert( iLit >= 0 );
+
+ // consider the case of a gate
+ pObj = Kit_DsdNtkObj( pNtk, Kit_DsdLit2Var(iLit) );
+ if ( pObj == NULL )
+ {
+ pObjNew = ppLeaves[Kit_DsdLit2Var(iLit)];
+ return If_NotCond( pObjNew, Kit_DsdLitIsCompl(iLit) );
+ }
+ if ( pObj->Type == KIT_DSD_CONST1 )
+ {
+ return If_NotCond( If_ManConst1(p->pIfMan), Kit_DsdLitIsCompl(iLit) );
+ }
+ if ( pObj->Type == KIT_DSD_VAR )
+ {
+ pObjNew = ppLeaves[Kit_DsdLit2Var(pObj->pFans[0])];
+ return If_NotCond( pObjNew, Kit_DsdLitIsCompl(iLit) ^ Kit_DsdLitIsCompl(pObj->pFans[0]) );
+ }
+ if ( pObj->Type == KIT_DSD_AND )
+ {
+ assert( pObj->nFans == 2 );
+ pFansNew[0] = Lpk_MapTree_rec( p, pNtk, ppLeaves, pObj->pFans[0], NULL );
+ pFansNew[1] = pResult? pResult : Lpk_MapTree_rec( p, pNtk, ppLeaves, pObj->pFans[1], NULL );
+ if ( pFansNew[0] == NULL || pFansNew[1] == NULL )
+ return NULL;
+ pObjNew = If_ManCreateAnd( p->pIfMan, pFansNew[0], pFansNew[1] );
+ return If_NotCond( pObjNew, Kit_DsdLitIsCompl(iLit) );
+ }
+ if ( pObj->Type == KIT_DSD_XOR )
+ {
+ int fCompl = Kit_DsdLitIsCompl(iLit);
+ assert( pObj->nFans == 2 );
+ pFansNew[0] = Lpk_MapTree_rec( p, pNtk, ppLeaves, pObj->pFans[0], NULL );
+ pFansNew[1] = pResult? pResult : Lpk_MapTree_rec( p, pNtk, ppLeaves, pObj->pFans[1], NULL );
+ if ( pFansNew[0] == NULL || pFansNew[1] == NULL )
+ return NULL;
+ fCompl ^= If_IsComplement(pFansNew[0]) ^ If_IsComplement(pFansNew[1]);
+ pObjNew = If_ManCreateXor( p->pIfMan, If_Regular(pFansNew[0]), If_Regular(pFansNew[1]) );
+ return If_NotCond( pObjNew, fCompl );
+ }
+ assert( pObj->Type == KIT_DSD_PRIME );
+ p->nBlocks[pObj->nFans]++;
+
+ // solve for the inputs
+ Kit_DsdObjForEachFanin( pNtk, pObj, iLitFanin, i )
+ {
+ if ( i == 0 )
+ pFansNew[i] = pResult? pResult : Lpk_MapTree_rec( p, pNtk, ppLeaves, iLitFanin, NULL );
+ else
+ pFansNew[i] = Lpk_MapTree_rec( p, pNtk, ppLeaves, iLitFanin, NULL );
+ if ( pFansNew[i] == NULL )
+ return NULL;
+ }
+/*
+ if ( !p->fCofactoring && p->pPars->nVarsShared > 0 && (int)pObj->nFans > p->pPars->nLutSize )
+ {
+ pObjNew = Lpk_MapTreeMulti( p, Kit_DsdObjTruth(pObj), pObj->nFans, pFansNew );
+ return If_NotCond( pObjNew, Kit_DsdLitIsCompl(iLit) );
+ }
+*/
+/*
+ if ( (int)pObj->nFans > p->pPars->nLutSize )
+ {
+ pObjNew2 = Lpk_MapTreeMux_rec( p, Kit_DsdObjTruth(pObj), pObj->nFans, pFansNew );
+// if ( pObjNew2 )
+// return If_NotCond( pObjNew2, Kit_DsdLitIsCompl(iLit) );
+ }
+*/
+
+ // find best cofactoring variable
+ if ( p->pPars->nVarsShared > 0 && (int)pObj->nFans > p->pPars->nLutSize )
+ {
+ pObjNew2 = Lpk_MapSuppRedDec_rec( p, Kit_DsdObjTruth(pObj), pObj->nFans, pFansNew );
+ if ( pObjNew2 )
+ return If_NotCond( pObjNew2, Kit_DsdLitIsCompl(iLit) );
+ }
+
+ pObjNew = Lpk_MapPrime( p, Kit_DsdObjTruth(pObj), pObj->nFans, pFansNew );
+
+ // add choice
+ if ( pObjNew && pObjNew2 )
+ {
+ If_ObjSetChoice( If_Regular(pObjNew), If_Regular(pObjNew2) );
+ If_ManCreateChoice( p->pIfMan, If_Regular(pObjNew) );
+ }
+ return If_NotCond( pObjNew, Kit_DsdLitIsCompl(iLit) );
+}
+
+////////////////////////////////////////////////////////////////////////
+/// END OF FILE ///
+////////////////////////////////////////////////////////////////////////
+
+
diff --git a/src/opt/lpk/lpkMulti.c b/src/opt/lpk/lpkMulti.c
new file mode 100644
index 00000000..82cf3578
--- /dev/null
+++ b/src/opt/lpk/lpkMulti.c
@@ -0,0 +1,495 @@
+/**CFile****************************************************************
+
+ FileName [lpkMulti.c]
+
+ SystemName [ABC: Logic synthesis and verification system.]
+
+ PackageName [Fast Boolean matching for LUT structures.]
+
+ Synopsis []
+
+ Author [Alan Mishchenko]
+
+ Affiliation [UC Berkeley]
+
+ Date [Ver. 1.0. Started - April 28, 2007.]
+
+ Revision [$Id: lpkMulti.c,v 1.00 2007/04/28 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "lpkInt.h"
+
+////////////////////////////////////////////////////////////////////////
+/// DECLARATIONS ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+/// FUNCTION DEFINITIONS ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+ Synopsis [Records variable order.]
+
+ Description [Increaments Order[x][y] by 1 if x should be above y in the DSD.]
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Lpk_CreateVarOrder( Kit_DsdNtk_t * pNtk, char pTable[][16] )
+{
+ Kit_DsdObj_t * pObj;
+ unsigned uSuppFanins, k;
+ int Above[16], Below[16];
+ int nAbove, nBelow, iFaninLit, i, x, y;
+ // iterate through the nodes
+ Kit_DsdNtkForEachObj( pNtk, pObj, i )
+ {
+ // collect fanin support of this node
+ nAbove = 0;
+ uSuppFanins = 0;
+ Kit_DsdObjForEachFanin( pNtk, pObj, iFaninLit, k )
+ {
+ if ( Kit_DsdLitIsLeaf( pNtk, iFaninLit ) )
+ Above[nAbove++] = Kit_DsdLit2Var(iFaninLit);
+ else
+ uSuppFanins |= Kit_DsdLitSupport( pNtk, iFaninLit );
+ }
+ // find the below variables
+ nBelow = 0;
+ for ( y = 0; y < 16; y++ )
+ if ( uSuppFanins & (1 << y) )
+ Below[nBelow++] = y;
+ // create all pairs
+ for ( x = 0; x < nAbove; x++ )
+ for ( y = 0; y < nBelow; y++ )
+ pTable[Above[x]][Below[y]]++;
+ }
+}
+
+/**Function*************************************************************
+
+ Synopsis [Creates commmon variable order.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Lpk_CreateCommonOrder( char pTable[][16], int piCofVar[], int nCBars, int pPrios[], int nVars, int fVerbose )
+{
+ int Score[16] = {0}, pPres[16];
+ int i, y, x, iVarBest, ScoreMax, PrioCount;
+
+ // mark the present variables
+ for ( i = 0; i < nVars; i++ )
+ pPres[i] = 1;
+ // remove cofactored variables
+ for ( i = 0; i < nCBars; i++ )
+ pPres[piCofVar[i]] = 0;
+
+ // compute scores for each leaf
+ for ( i = 0; i < nVars; i++ )
+ {
+ if ( pPres[i] == 0 )
+ continue;
+ for ( y = 0; y < nVars; y++ )
+ Score[i] += pTable[i][y];
+ for ( x = 0; x < nVars; x++ )
+ Score[i] -= pTable[x][i];
+ }
+
+ // print the scores
+ if ( fVerbose )
+ {
+ printf( "Scores: " );
+ for ( i = 0; i < nVars; i++ )
+ printf( "%c=%d ", 'a'+i, Score[i] );
+ printf( " " );
+ printf( "Prios: " );
+ }
+
+ // derive variable priority
+ // variables with equal score receive the same priority
+ for ( i = 0; i < nVars; i++ )
+ pPrios[i] = 16;
+
+ // iterate until variables remain
+ for ( PrioCount = 1; ; PrioCount++ )
+ {
+ // find the present variable with the highest score
+ iVarBest = -1;
+ ScoreMax = -100000;
+ for ( i = 0; i < nVars; i++ )
+ {
+ if ( pPres[i] == 0 )
+ continue;
+ if ( ScoreMax < Score[i] )
+ {
+ ScoreMax = Score[i];
+ iVarBest = i;
+ }
+ }
+ if ( iVarBest == -1 )
+ break;
+ // give the next priority to all vars having this score
+ if ( fVerbose )
+ printf( "%d=", PrioCount );
+ for ( i = 0; i < nVars; i++ )
+ {
+ if ( pPres[i] == 0 )
+ continue;
+ if ( Score[i] == ScoreMax )
+ {
+ pPrios[i] = PrioCount;
+ pPres[i] = 0;
+ if ( fVerbose )
+ printf( "%c", 'a'+i );
+ }
+ }
+ if ( fVerbose )
+ printf( " " );
+ }
+ if ( fVerbose )
+ printf( "\n" );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Finds components with the highest priority.]
+
+ Description [Returns the number of components selected.]
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Lpk_FindHighest( Kit_DsdNtk_t ** ppNtks, int * piLits, int nSize, int * pPrio, int * pDecision )
+{
+ Kit_DsdObj_t * pObj;
+ unsigned uSupps[8], uSuppFanin, uSuppTotal, uSuppLarge;
+ int i, pTriv[8], PrioMin, iVarMax, nComps, fOneNonTriv;
+
+ // find individual support and total support
+ uSuppTotal = 0;
+ for ( i = 0; i < nSize; i++ )
+ {
+ pTriv[i] = 1;
+ if ( piLits[i] < 0 )
+ uSupps[i] = 0;
+ else if ( Kit_DsdLitIsLeaf(ppNtks[i], piLits[i]) )
+ uSupps[i] = Kit_DsdLitSupport( ppNtks[i], piLits[i] );
+ else
+ {
+ pObj = Kit_DsdNtkObj( ppNtks[i], Kit_DsdLit2Var(piLits[i]) );
+ if ( pObj->Type == KIT_DSD_PRIME )
+ {
+ pTriv[i] = 0;
+ uSuppFanin = Kit_DsdLitSupport( ppNtks[i], pObj->pFans[0] );
+ }
+ else
+ {
+ assert( pObj->nFans == 2 );
+ if ( !Kit_DsdLitIsLeaf(ppNtks[i], pObj->pFans[0]) )
+ pTriv[i] = 0;
+ uSuppFanin = Kit_DsdLitSupport( ppNtks[i], pObj->pFans[1] );
+ }
+ uSupps[i] = Kit_DsdLitSupport( ppNtks[i], piLits[i] ) & ~uSuppFanin;
+ }
+ assert( uSupps[i] <= 0xFFFF );
+ uSuppTotal |= uSupps[i];
+ }
+ if ( uSuppTotal == 0 )
+ return 0;
+
+ // find one support variable with the highest priority
+ PrioMin = ABC_INFINITY;
+ iVarMax = -1;
+ for ( i = 0; i < 16; i++ )
+ if ( uSuppTotal & (1 << i) )
+ if ( PrioMin > pPrio[i] )
+ {
+ PrioMin = pPrio[i];
+ iVarMax = i;
+ }
+ assert( iVarMax != -1 );
+
+ // select components, which have this variable
+ nComps = 0;
+ fOneNonTriv = 0;
+ uSuppLarge = 0;
+ for ( i = 0; i < nSize; i++ )
+ if ( uSupps[i] & (1<<iVarMax) )
+ {
+ if ( pTriv[i] || !fOneNonTriv )
+ {
+ if ( !pTriv[i] )
+ {
+ uSuppLarge = uSupps[i];
+ fOneNonTriv = 1;
+ }
+ pDecision[i] = 1;
+ nComps++;
+ }
+ else
+ pDecision[i] = 0;
+ }
+ else
+ pDecision[i] = 0;
+
+ // add other non-trivial not-taken components whose support is contained in the current large component support
+ if ( fOneNonTriv )
+ for ( i = 0; i < nSize; i++ )
+ if ( !pTriv[i] && pDecision[i] == 0 && (uSupps[i] & ~uSuppLarge) == 0 )
+ {
+ pDecision[i] = 1;
+ nComps++;
+ }
+
+ return nComps;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Prepares the mapping manager.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+If_Obj_t * Lpk_MapTreeMulti_rec( Lpk_Man_t * p, Kit_DsdNtk_t ** ppNtks, int * piLits, int * piCofVar, int nCBars, If_Obj_t ** ppLeaves, int nLeaves, int * pPrio )
+{
+ Kit_DsdObj_t * pObj;
+ If_Obj_t * pObjsNew[4][8], * pResPrev;
+ int piLitsNew[8], pDecision[8];
+ int i, k, nComps, nSize;
+
+ // find which of the variables is highest in the order
+ nSize = (1 << nCBars);
+ nComps = Lpk_FindHighest( ppNtks, piLits, nSize, pPrio, pDecision );
+ if ( nComps == 0 )
+ return If_Not( If_ManConst1(p->pIfMan) );
+
+ // iterate over the nodes
+ if ( p->pPars->fVeryVerbose )
+ printf( "Decision: " );
+ for ( i = 0; i < nSize; i++ )
+ {
+ if ( pDecision[i] )
+ {
+ if ( p->pPars->fVeryVerbose )
+ printf( "%d ", i );
+ assert( piLits[i] >= 0 );
+ pObj = Kit_DsdNtkObj( ppNtks[i], Kit_DsdLit2Var(piLits[i]) );
+ if ( pObj == NULL )
+ piLitsNew[i] = -2;
+ else if ( pObj->Type == KIT_DSD_PRIME )
+ piLitsNew[i] = pObj->pFans[0];
+ else
+ piLitsNew[i] = pObj->pFans[1];
+ }
+ else
+ piLitsNew[i] = piLits[i];
+ }
+ if ( p->pPars->fVeryVerbose )
+ printf( "\n" );
+
+ // call again
+ pResPrev = Lpk_MapTreeMulti_rec( p, ppNtks, piLitsNew, piCofVar, nCBars, ppLeaves, nLeaves, pPrio );
+
+ // create new set of nodes
+ for ( i = 0; i < nSize; i++ )
+ {
+ if ( pDecision[i] )
+ pObjsNew[nCBars][i] = Lpk_MapTree_rec( p, ppNtks[i], ppLeaves, piLits[i], pResPrev );
+ else if ( piLits[i] == -1 )
+ pObjsNew[nCBars][i] = If_ManConst1(p->pIfMan);
+ else if ( piLits[i] == -2 )
+ pObjsNew[nCBars][i] = If_Not( If_ManConst1(p->pIfMan) );
+ else
+ pObjsNew[nCBars][i] = pResPrev;
+ }
+
+ // create MUX using these outputs
+ for ( k = nCBars; k > 0; k-- )
+ {
+ nSize /= 2;
+ for ( i = 0; i < nSize; i++ )
+ pObjsNew[k-1][i] = If_ManCreateMux( p->pIfMan, pObjsNew[k][2*i+0], pObjsNew[k][2*i+1], ppLeaves[piCofVar[k-1]] );
+ }
+ assert( nSize == 1 );
+ return pObjsNew[0][0];
+}
+
+/**Function*************************************************************
+
+ Synopsis [Prepares the mapping manager.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+If_Obj_t * Lpk_MapTreeMulti( Lpk_Man_t * p, unsigned * pTruth, int nVars, If_Obj_t ** ppLeaves )
+{
+ static Counter = 0;
+ If_Obj_t * pResult;
+ Kit_DsdNtk_t * ppNtks[8] = {0}, * pTemp;
+ Kit_DsdObj_t * pRoot;
+ int piCofVar[4], pPrios[16], pFreqs[16] = {0}, piLits[16];
+ int i, k, nCBars, nSize, nMemSize;
+ unsigned * ppCofs[4][8], uSupport;
+ char pTable[16][16] = {0};
+ int fVerbose = p->pPars->fVeryVerbose;
+
+ Counter++;
+// printf( "Run %d.\n", Counter );
+
+ // allocate storage for cofactors
+ nMemSize = Kit_TruthWordNum(nVars);
+ ppCofs[0][0] = ALLOC( unsigned, 32 * nMemSize );
+ nSize = 0;
+ for ( i = 0; i < 4; i++ )
+ for ( k = 0; k < 8; k++ )
+ ppCofs[i][k] = ppCofs[0][0] + nMemSize * nSize++;
+ assert( nSize == 32 );
+
+ // find the best cofactoring variables
+ nCBars = Kit_DsdCofactoring( pTruth, nVars, piCofVar, p->pPars->nVarsShared, 0 );
+// nCBars = 2;
+// piCofVar[0] = 0;
+// piCofVar[1] = 1;
+
+
+ // copy the function
+ Kit_TruthCopy( ppCofs[0][0], pTruth, nVars );
+
+ // decompose w.r.t. these variables
+ for ( k = 0; k < nCBars; k++ )
+ {
+ nSize = (1 << k);
+ for ( i = 0; i < nSize; i++ )
+ {
+ Kit_TruthCofactor0New( ppCofs[k+1][2*i+0], ppCofs[k][i], nVars, piCofVar[k] );
+ Kit_TruthCofactor1New( ppCofs[k+1][2*i+1], ppCofs[k][i], nVars, piCofVar[k] );
+ }
+ }
+ nSize = (1 << nCBars);
+ // compute DSD networks
+ for ( i = 0; i < nSize; i++ )
+ {
+ ppNtks[i] = Kit_DsdDecompose( ppCofs[nCBars][i], nVars );
+ ppNtks[i] = Kit_DsdExpand( pTemp = ppNtks[i] );
+ Kit_DsdNtkFree( pTemp );
+ if ( fVerbose )
+ {
+ printf( "Cof%d%d: ", nCBars, i );
+ Kit_DsdPrint( stdout, ppNtks[i] );
+ }
+ }
+
+ // compute variable frequences
+ for ( i = 0; i < nSize; i++ )
+ {
+ uSupport = Kit_TruthSupport( ppCofs[nCBars][i], nVars );
+ for ( k = 0; k < nVars; k++ )
+ if ( uSupport & (1<<k) )
+ pFreqs[k]++;
+ }
+
+ // find common variable order
+ for ( i = 0; i < nSize; i++ )
+ {
+ Kit_DsdGetSupports( ppNtks[i] );
+ Lpk_CreateVarOrder( ppNtks[i], pTable );
+ }
+ Lpk_CreateCommonOrder( pTable, piCofVar, nCBars, pPrios, nVars, fVerbose );
+ // update priorities with frequences
+ for ( i = 0; i < nVars; i++ )
+ pPrios[i] = pPrios[i] * 256 + (16 - pFreqs[i]) * 16 + i;
+
+ if ( fVerbose )
+ printf( "After restructuring with priority:\n" );
+
+ if ( Counter == 1 )
+ {
+ int x = 0;
+ }
+ // transform all networks according to the variable order
+ for ( i = 0; i < nSize; i++ )
+ {
+ ppNtks[i] = Kit_DsdShrink( pTemp = ppNtks[i], pPrios );
+ Kit_DsdNtkFree( pTemp );
+ Kit_DsdGetSupports( ppNtks[i] );
+ assert( ppNtks[i]->pSupps[0] <= 0xFFFF );
+ // undec nodes should be rotated in such a way that the first input has as many shared inputs as possible
+ Kit_DsdRotate( ppNtks[i], pFreqs );
+ // print the resulting networks
+ if ( fVerbose )
+ {
+ printf( "Cof%d%d: ", nCBars, i );
+ Kit_DsdPrint( stdout, ppNtks[i] );
+ }
+ }
+
+ for ( i = 0; i < nSize; i++ )
+ {
+ // collect the roots
+ pRoot = Kit_DsdNtkRoot(ppNtks[i]);
+ if ( pRoot->Type == KIT_DSD_CONST1 )
+ piLits[i] = Kit_DsdLitIsCompl(ppNtks[i]->Root)? -2: -1;
+ else if ( pRoot->Type == KIT_DSD_VAR )
+ piLits[i] = Kit_DsdLitNotCond( pRoot->pFans[0], Kit_DsdLitIsCompl(ppNtks[i]->Root) );
+ else
+ piLits[i] = ppNtks[i]->Root;
+ }
+
+
+ // recursively construct AIG for mapping
+ p->fCofactoring = 1;
+ pResult = Lpk_MapTreeMulti_rec( p, ppNtks, piLits, piCofVar, nCBars, ppLeaves, nVars, pPrios );
+ p->fCofactoring = 0;
+
+ if ( fVerbose )
+ printf( "\n" );
+
+ // verify the transformations
+ nSize = (1 << nCBars);
+ for ( i = 0; i < nSize; i++ )
+ Kit_DsdTruth( ppNtks[i], ppCofs[nCBars][i] );
+ // mux the truth tables
+ for ( k = nCBars-1; k >= 0; k-- )
+ {
+ nSize = (1 << k);
+ for ( i = 0; i < nSize; i++ )
+ Kit_TruthMuxVar( ppCofs[k][i], ppCofs[k+1][2*i+0], ppCofs[k+1][2*i+1], nVars, piCofVar[k] );
+ }
+ if ( !Extra_TruthIsEqual( pTruth, ppCofs[0][0], nVars ) )
+ printf( "Verification failed.\n" );
+
+
+ // free the networks
+ for ( i = 0; i < 8; i++ )
+ if ( ppNtks[i] )
+ Kit_DsdNtkFree( ppNtks[i] );
+ free( ppCofs[0][0] );
+
+ return pResult;
+}
+
+////////////////////////////////////////////////////////////////////////
+/// END OF FILE ///
+////////////////////////////////////////////////////////////////////////
+
+
diff --git a/src/opt/lpk/lpkMux.c b/src/opt/lpk/lpkMux.c
new file mode 100644
index 00000000..ed046ad7
--- /dev/null
+++ b/src/opt/lpk/lpkMux.c
@@ -0,0 +1,247 @@
+/**CFile****************************************************************
+
+ FileName [lpkMux.c]
+
+ SystemName [ABC: Logic synthesis and verification system.]
+
+ PackageName [Fast Boolean matching for LUT structures.]
+
+ Synopsis []
+
+ Author [Alan Mishchenko]
+
+ Affiliation [UC Berkeley]
+
+ Date [Ver. 1.0. Started - April 28, 2007.]
+
+ Revision [$Id: lpkMux.c,v 1.00 2007/04/28 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "lpkInt.h"
+
+////////////////////////////////////////////////////////////////////////
+/// DECLARATIONS ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+/// FUNCTION DEFINITIONS ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+ Synopsis [Find the best cofactoring variable.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Lpk_MapTreeBestCofVar( Lpk_Man_t * p, unsigned * pTruth, int nVars, unsigned * pCof0, unsigned * pCof1 )
+{
+ int i, iBestVar, nSuppSizeCur0, nSuppSizeCur1, nSuppSizeCur, nSuppSizeMin;
+ // iterate through variables
+ iBestVar = -1;
+ nSuppSizeMin = KIT_INFINITY;
+ for ( i = 0; i < nVars; i++ )
+ {
+ // cofactor the functiona and get support sizes
+ Kit_TruthCofactor0New( pCof0, pTruth, nVars, i );
+ Kit_TruthCofactor1New( pCof1, pTruth, nVars, i );
+ nSuppSizeCur0 = Kit_TruthSupportSize( pCof0, nVars );
+ nSuppSizeCur1 = Kit_TruthSupportSize( pCof1, nVars );
+ nSuppSizeCur = nSuppSizeCur0 + nSuppSizeCur1;
+ // skip cofactoring that goes above the limit
+ if ( nSuppSizeCur0 > p->pPars->nLutSize || nSuppSizeCur1 > p->pPars->nLutSize )
+ continue;
+ // compare this variable with other variables
+ if ( nSuppSizeMin > nSuppSizeCur )
+ {
+ nSuppSizeMin = nSuppSizeCur;
+ iBestVar = i;
+ }
+ }
+ // cofactor w.r.t. this variable
+ if ( iBestVar != -1 )
+ {
+ Kit_TruthCofactor0New( pCof0, pTruth, nVars, iBestVar );
+ Kit_TruthCofactor1New( pCof1, pTruth, nVars, iBestVar );
+ }
+ return iBestVar;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Maps the function by the best cofactoring.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+If_Obj_t * Lpk_MapTreeMux_rec( Lpk_Man_t * p, unsigned * pTruth, int nVars, If_Obj_t ** ppLeaves )
+{
+ unsigned * pCof0 = Vec_PtrEntry( p->vTtNodes, 0 );
+ unsigned * pCof1 = Vec_PtrEntry( p->vTtNodes, 1 );
+ If_Obj_t * pObj0, * pObj1;
+ Kit_DsdNtk_t * ppNtks[2];
+ int iBestVar;
+ assert( nVars > 3 );
+ p->fCalledOnce = 1;
+ // cofactor w.r.t. the best variable
+ iBestVar = Lpk_MapTreeBestCofVar( p, pTruth, nVars, pCof0, pCof1 );
+ if ( iBestVar == -1 )
+ return NULL;
+ // decompose the functions
+ ppNtks[0] = Kit_DsdDecompose( pCof0, nVars );
+ ppNtks[1] = Kit_DsdDecompose( pCof1, nVars );
+ if ( p->pPars->fVeryVerbose )
+ {
+ printf( "Cofactoring w.r.t. var %c (%d -> %d+%d supp vars):\n",
+ 'a'+iBestVar, nVars, Kit_TruthSupportSize(pCof0, nVars), Kit_TruthSupportSize(pCof1, nVars) );
+ Kit_DsdPrintExpanded( ppNtks[0] );
+ Kit_DsdPrintExpanded( ppNtks[1] );
+ }
+ // map the DSD structures
+ pObj0 = Lpk_MapTree_rec( p, ppNtks[0], ppLeaves, ppNtks[0]->Root, NULL );
+ pObj1 = Lpk_MapTree_rec( p, ppNtks[1], ppLeaves, ppNtks[1]->Root, NULL );
+ Kit_DsdNtkFree( ppNtks[0] );
+ Kit_DsdNtkFree( ppNtks[1] );
+ return If_ManCreateMux( p->pIfMan, pObj0, pObj1, ppLeaves[iBestVar] );
+}
+
+
+
+/**Function*************************************************************
+
+ Synopsis [Implements support-reducing decomposition.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+If_Obj_t * Lpk_MapSuppRedDec_rec( Lpk_Man_t * p, unsigned * pTruth, int nVars, If_Obj_t ** ppLeaves )
+{
+ Kit_DsdNtk_t * pNtkDec, * pNtkComp, * ppNtks[2], * pTemp;
+ If_Obj_t * pObjNew;
+ unsigned * pCof0 = Vec_PtrEntry( p->vTtNodes, 0 );
+ unsigned * pCof1 = Vec_PtrEntry( p->vTtNodes, 1 );
+ unsigned * pDec0 = Vec_PtrEntry( p->vTtNodes, 2 );
+ unsigned * pDec1 = Vec_PtrEntry( p->vTtNodes, 3 );
+ unsigned * pDec = Vec_PtrEntry( p->vTtNodes, 4 );
+ unsigned * pCo00 = Vec_PtrEntry( p->vTtNodes, 5 );
+ unsigned * pCo01 = Vec_PtrEntry( p->vTtNodes, 6 );
+ unsigned * pCo10 = Vec_PtrEntry( p->vTtNodes, 7 );
+ unsigned * pCo11 = Vec_PtrEntry( p->vTtNodes, 8 );
+ unsigned * pCo0 = Vec_PtrEntry( p->vTtNodes, 9 );
+ unsigned * pCo1 = Vec_PtrEntry( p->vTtNodes, 10 );
+ unsigned * pCo = Vec_PtrEntry( p->vTtNodes, 11 );
+ int TrueMint0, TrueMint1, FalseMint0, FalseMint1;
+ int uSubsets, uSubset0, uSubset1, iVar, iVarReused, i;
+
+ // determine if supp-red decomposition exists
+ uSubsets = Lpk_MapSuppRedDecSelect( p, pTruth, nVars, &iVar, &iVarReused );
+ if ( uSubsets == 0 )
+ return NULL;
+ p->nCalledSRed++;
+
+ // get the cofactors
+ Kit_TruthCofactor0New( pCof0, pTruth, nVars, iVar );
+ Kit_TruthCofactor1New( pCof1, pTruth, nVars, iVar );
+
+ // get the bound sets
+ uSubset0 = uSubsets & 0xFFFF;
+ uSubset1 = uSubsets >> 16;
+
+ // compute the decomposed functions
+ ppNtks[0] = Kit_DsdDecompose( pCof0, nVars );
+ ppNtks[1] = Kit_DsdDecompose( pCof1, nVars );
+ ppNtks[0] = Kit_DsdExpand( pTemp = ppNtks[0] ); Kit_DsdNtkFree( pTemp );
+ ppNtks[1] = Kit_DsdExpand( pTemp = ppNtks[1] ); Kit_DsdNtkFree( pTemp );
+ Kit_DsdTruthPartial( p->pDsdMan, ppNtks[0], pDec0, uSubset0 );
+ Kit_DsdTruthPartial( p->pDsdMan, ppNtks[1], pDec1, uSubset1 );
+// Kit_DsdTruthPartialTwo( p->pDsdMan, ppNtks[0], uSubset0, iVarReused, pCo0, pDec0 );
+// Kit_DsdTruthPartialTwo( p->pDsdMan, ppNtks[1], uSubset1, iVarReused, pCo1, pDec1 );
+ Kit_DsdNtkFree( ppNtks[0] );
+ Kit_DsdNtkFree( ppNtks[1] );
+//Kit_DsdPrintFromTruth( pDec0, nVars );
+//Kit_DsdPrintFromTruth( pDec1, nVars );
+ // get the decomposed function
+ Kit_TruthMuxVar( pDec, pDec0, pDec1, nVars, iVar );
+
+ // find any true assignments of the decomposed functions
+ TrueMint0 = Kit_TruthFindFirstBit( pDec0, nVars );
+ TrueMint1 = Kit_TruthFindFirstBit( pDec1, nVars );
+ assert( TrueMint0 >= 0 && TrueMint1 >= 0 );
+ // find any false assignments of the decomposed functions
+ FalseMint0 = Kit_TruthFindFirstZero( pDec0, nVars );
+ FalseMint1 = Kit_TruthFindFirstZero( pDec1, nVars );
+ assert( FalseMint0 >= 0 && FalseMint1 >= 0 );
+
+ // cofactor the cofactors according to these minterms
+ Kit_TruthCopy( pCo00, pCof0, nVars );
+ Kit_TruthCopy( pCo01, pCof0, nVars );
+ for ( i = 0; i < nVars; i++ )
+ if ( uSubset0 & (1 << i) )
+ {
+ if ( FalseMint0 & (1 << i) )
+ Kit_TruthCofactor1( pCo00, nVars, i );
+ else
+ Kit_TruthCofactor0( pCo00, nVars, i );
+ if ( TrueMint0 & (1 << i) )
+ Kit_TruthCofactor1( pCo01, nVars, i );
+ else
+ Kit_TruthCofactor0( pCo01, nVars, i );
+ }
+ Kit_TruthCopy( pCo10, pCof1, nVars );
+ Kit_TruthCopy( pCo11, pCof1, nVars );
+ for ( i = 0; i < nVars; i++ )
+ if ( uSubset1 & (1 << i) )
+ {
+ if ( FalseMint1 & (1 << i) )
+ Kit_TruthCofactor1( pCo10, nVars, i );
+ else
+ Kit_TruthCofactor0( pCo10, nVars, i );
+ if ( TrueMint1 & (1 << i) )
+ Kit_TruthCofactor1( pCo11, nVars, i );
+ else
+ Kit_TruthCofactor0( pCo11, nVars, i );
+ }
+
+ // derive the functions by composing them with the new variable (iVarReused)
+ Kit_TruthMuxVar( pCo0, pCo00, pCo01, nVars, iVarReused );
+ Kit_TruthMuxVar( pCo1, pCo10, pCo11, nVars, iVarReused );
+//Kit_DsdPrintFromTruth( pCo0, nVars );
+//Kit_DsdPrintFromTruth( pCo1, nVars );
+
+ // derive the composition function
+ Kit_TruthMuxVar( pCo , pCo0 , pCo1 , nVars, iVar );
+
+ // process the decomposed function
+ pNtkDec = Kit_DsdDecompose( pDec, nVars );
+ pNtkComp = Kit_DsdDecompose( pCo, nVars );
+//Kit_DsdPrint( stdout, pNtkDec );
+//Kit_DsdPrint( stdout, pNtkComp );
+//printf( "cofactored variable %c\n", 'a' + iVar );
+//printf( "reused variable %c\n", 'a' + iVarReused );
+
+ ppLeaves[iVarReused] = Lpk_MapTree_rec( p, pNtkDec, ppLeaves, pNtkDec->Root, NULL );
+ pObjNew = Lpk_MapTree_rec( p, pNtkComp, ppLeaves, pNtkComp->Root, NULL );
+
+ Kit_DsdNtkFree( pNtkDec );
+ Kit_DsdNtkFree( pNtkComp );
+ return pObjNew;
+}
+
+////////////////////////////////////////////////////////////////////////
+/// END OF FILE ///
+////////////////////////////////////////////////////////////////////////
+
+
diff --git a/src/opt/lpk/lpkSets.c b/src/opt/lpk/lpkSets.c
new file mode 100644
index 00000000..90e46863
--- /dev/null
+++ b/src/opt/lpk/lpkSets.c
@@ -0,0 +1,440 @@
+/**CFile****************************************************************
+
+ FileName [lpkSets.c]
+
+ SystemName [ABC: Logic synthesis and verification system.]
+
+ PackageName [Fast Boolean matching for LUT structures.]
+
+ Synopsis []
+
+ Author [Alan Mishchenko]
+
+ Affiliation [UC Berkeley]
+
+ Date [Ver. 1.0. Started - April 28, 2007.]
+
+ Revision [$Id: lpkSets.c,v 1.00 2007/04/28 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "lpkInt.h"
+
+////////////////////////////////////////////////////////////////////////
+/// DECLARATIONS ///
+////////////////////////////////////////////////////////////////////////
+
+typedef struct Lpk_Set_t_ Lpk_Set_t;
+struct Lpk_Set_t_
+{
+ char iVar; // the cofactoring variable
+ char Over; // the overlap in supports
+ char SRed; // the support reduction
+ char Size; // the size of the boundset
+ unsigned uSubset0; // the first subset (with removed)
+ unsigned uSubset1; // the second subset (with removed)
+};
+
+////////////////////////////////////////////////////////////////////////
+/// FUNCTION DEFINITIONS ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+ Synopsis [Recursively computes decomposable subsets.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+unsigned Lpk_ComputeSets_rec( Kit_DsdNtk_t * p, int iLit, Vec_Int_t * vSets )
+{
+ unsigned i, iLitFanin, uSupport, uSuppCur;
+ Kit_DsdObj_t * pObj;
+ // consider the case of simple gate
+ pObj = Kit_DsdNtkObj( p, Kit_DsdLit2Var(iLit) );
+ if ( pObj == NULL )
+ return (1 << Kit_DsdLit2Var(iLit));
+ if ( pObj->Type == KIT_DSD_AND || pObj->Type == KIT_DSD_XOR )
+ {
+ unsigned uSupps[16], Limit, s;
+ uSupport = 0;
+ Kit_DsdObjForEachFanin( p, pObj, iLitFanin, i )
+ {
+ uSupps[i] = Lpk_ComputeSets_rec( p, iLitFanin, vSets );
+ uSupport |= uSupps[i];
+ }
+ // create all subsets, except empty and full
+ Limit = (1 << pObj->nFans) - 1;
+ for ( s = 1; s < Limit; s++ )
+ {
+ uSuppCur = 0;
+ for ( i = 0; i < pObj->nFans; i++ )
+ if ( s & (1 << i) )
+ uSuppCur |= uSupps[i];
+ Vec_IntPush( vSets, uSuppCur );
+ }
+ return uSupport;
+ }
+ assert( pObj->Type == KIT_DSD_PRIME );
+ // get the cumulative support of all fanins
+ uSupport = 0;
+ Kit_DsdObjForEachFanin( p, pObj, iLitFanin, i )
+ {
+ uSuppCur = Lpk_ComputeSets_rec( p, iLitFanin, vSets );
+ uSupport |= uSuppCur;
+ Vec_IntPush( vSets, uSuppCur );
+ }
+ return uSupport;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Computes the set of subsets of decomposable variables.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+unsigned Lpk_ComputeSets( Kit_DsdNtk_t * p, Vec_Int_t * vSets )
+{
+ unsigned uSupport, Entry;
+ int Number, i;
+ assert( p->nVars <= 16 );
+ Vec_IntClear( vSets );
+ Vec_IntPush( vSets, 0 );
+ if ( Kit_DsdNtkRoot(p)->Type == KIT_DSD_CONST1 )
+ return 0;
+ if ( Kit_DsdNtkRoot(p)->Type == KIT_DSD_VAR )
+ {
+ uSupport = ( 1 << Kit_DsdLit2Var(Kit_DsdNtkRoot(p)->pFans[0]) );
+ Vec_IntPush( vSets, uSupport );
+ return uSupport;
+ }
+ uSupport = Lpk_ComputeSets_rec( p, p->Root, vSets );
+ assert( (uSupport & 0xFFFF0000) == 0 );
+ Vec_IntPush( vSets, uSupport );
+ // set the remaining variables
+ Vec_IntForEachEntry( vSets, Number, i )
+ {
+ Entry = Number;
+ Vec_IntWriteEntry( vSets, i, Entry | ((uSupport & ~Entry) << 16) );
+ }
+ return uSupport;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Prints the sets of subsets.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+static void Lpk_PrintSetOne( int uSupport )
+{
+ unsigned k;
+ for ( k = 0; k < 16; k++ )
+ if ( uSupport & (1<<k) )
+ printf( "%c", 'a'+k );
+ printf( " " );
+}
+/**Function*************************************************************
+
+ Synopsis [Prints the sets of subsets.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+static void Lpk_PrintSets( Vec_Int_t * vSets )
+{
+ unsigned uSupport;
+ int Number, i;
+ printf( "Subsets(%d): ", Vec_IntSize(vSets) );
+ Vec_IntForEachEntry( vSets, Number, i )
+ {
+ uSupport = Number;
+ Lpk_PrintSetOne( uSupport );
+ }
+ printf( "\n" );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Computes maximal support reducing bound-sets.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Lpk_ComposeSets( Vec_Int_t * vSets0, Vec_Int_t * vSets1, int nVars, int iCofVar,
+ Lpk_Set_t * pStore, int * pSize, int nSizeLimit )
+{
+ static int nTravId = 0; // the number of the times this is visited
+ static int TravId[1<<16] = {0}; // last visited
+ static char SRed[1<<16]; // best support reduction
+ static char Over[1<<16]; // best overlaps
+ static unsigned Parents[1<<16]; // best set of parents
+ static unsigned short Used[1<<16]; // storage for used subsets
+ int nSuppSize, nSuppOver, nSuppRed, nUsed, nMinOver, i, k, s;
+ unsigned Entry, Entry0, Entry1;
+ unsigned uSupp, uSupp0, uSupp1, uSuppTotal;
+ Lpk_Set_t * pEntry;
+
+ if ( nTravId == (1 << 30) )
+ memset( TravId, 0, sizeof(int) * (1 << 16) );
+
+ // collect support reducing subsets
+ nUsed = 0;
+ nTravId++;
+ uSuppTotal = Kit_BitMask(nVars) & ~(1<<iCofVar);
+ Vec_IntForEachEntry( vSets0, Entry0, i )
+ Vec_IntForEachEntry( vSets1, Entry1, k )
+ {
+ uSupp0 = (Entry0 & 0xFFFF);
+ uSupp1 = (Entry1 & 0xFFFF);
+ // skip trivial
+ if ( uSupp0 == 0 || uSupp1 == 0 || (uSupp0 | uSupp1) == uSuppTotal )
+ continue;
+ if ( Kit_WordHasOneBit(uSupp0) && Kit_WordHasOneBit(uSupp1) )
+ continue;
+ // get the entry
+ Entry = Entry0 | Entry1;
+ uSupp = Entry & 0xFFFF;
+ // set the bound set size
+ nSuppSize = Kit_WordCountOnes( uSupp );
+ // get the number of overlapping vars
+ nSuppOver = Kit_WordCountOnes( Entry & (Entry >> 16) );
+ // get the support reduction
+ nSuppRed = nSuppSize - 1 - nSuppOver;
+ // only consider support-reducing subsets
+ if ( nSuppRed <= 0 )
+ continue;
+ // check if this support is already used
+ if ( TravId[uSupp] < nTravId )
+ {
+ Used[nUsed++] = uSupp;
+
+ TravId[uSupp] = nTravId;
+ SRed[uSupp] = nSuppRed;
+ Over[uSupp] = nSuppOver;
+ Parents[uSupp] = (k << 16) | i;
+ }
+ else if ( TravId[uSupp] == nTravId && SRed[uSupp] < nSuppRed )
+ {
+ TravId[uSupp] = nTravId;
+ SRed[uSupp] = nSuppRed;
+ Over[uSupp] = nSuppOver;
+ Parents[uSupp] = (k << 16) | i;
+ }
+ }
+
+ // find the minimum overlap
+ nMinOver = 1000;
+ for ( s = 0; s < nUsed; s++ )
+ if ( nMinOver > Over[Used[s]] )
+ nMinOver = Over[Used[s]];
+
+
+ // collect the accumulated ones
+ for ( s = 0; s < nUsed; s++ )
+ if ( Over[Used[s]] == nMinOver )
+ {
+ // save the entry
+ if ( *pSize == nSizeLimit )
+ return;
+ pEntry = pStore + (*pSize)++;
+
+ i = Parents[Used[s]] & 0xFFFF;
+ k = Parents[Used[s]] >> 16;
+
+ pEntry->uSubset0 = Vec_IntEntry(vSets0, i);
+ pEntry->uSubset1 = Vec_IntEntry(vSets1, k);
+ Entry = pEntry->uSubset0 | pEntry->uSubset1;
+
+ // record the cofactoring variable
+ pEntry->iVar = iCofVar;
+ // set the bound set size
+ pEntry->Size = Kit_WordCountOnes( Entry & 0xFFFF );
+ // get the number of overlapping vars
+ pEntry->Over = Kit_WordCountOnes( Entry & (Entry >> 16) );
+ // get the support reduction
+ pEntry->SRed = pEntry->Size - 1 - pEntry->Over;
+ assert( pEntry->SRed > 0 );
+ }
+}
+
+/**Function*************************************************************
+
+ Synopsis [Prints one set.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Lpk_MapSuppPrintSet( Lpk_Set_t * pSet, int i )
+{
+ unsigned Entry;
+ Entry = pSet->uSubset0 | pSet->uSubset1;
+ printf( "%2d : ", i );
+ printf( "Var = %c ", 'a' + pSet->iVar );
+ printf( "Size = %2d ", pSet->Size );
+ printf( "Over = %2d ", pSet->Over );
+ printf( "SRed = %2d ", pSet->SRed );
+ Lpk_PrintSetOne( Entry );
+ printf( " " );
+ Lpk_PrintSetOne( Entry >> 16 );
+ printf( "\n" );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Evaluates the cofactors.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+unsigned Lpk_MapSuppRedDecSelect( Lpk_Man_t * p, unsigned * pTruth, int nVars, int * piVar, int * piVarReused )
+{
+ static int nStoreSize = 256;
+ static Lpk_Set_t pStore[256], * pSet, * pSetBest;
+ Kit_DsdNtk_t * ppNtks[2], * pTemp;
+ Vec_Int_t * vSets0 = p->vSets[0];
+ Vec_Int_t * vSets1 = p->vSets[1];
+ unsigned * pCof0 = Vec_PtrEntry( p->vTtNodes, 0 );
+ unsigned * pCof1 = Vec_PtrEntry( p->vTtNodes, 1 );
+ int nSets, i, SizeMax;//, SRedMax;
+ unsigned Entry;
+ int fVerbose = p->pPars->fVeryVerbose;
+// int fVerbose = 0;
+
+ // collect decomposable subsets for each pair of cofactors
+ if ( fVerbose )
+ {
+ printf( "\nExploring support-reducing bound-sets of function:\n" );
+ Kit_DsdPrintFromTruth( pTruth, nVars );
+ }
+ nSets = 0;
+ for ( i = 0; i < nVars; i++ )
+ {
+ if ( fVerbose )
+ printf( "Evaluating variable %c:\n", 'a'+i );
+ // evaluate the cofactor pair
+ Kit_TruthCofactor0New( pCof0, pTruth, nVars, i );
+ Kit_TruthCofactor1New( pCof1, pTruth, nVars, i );
+ // decompose and expand
+ ppNtks[0] = Kit_DsdDecompose( pCof0, nVars );
+ ppNtks[1] = Kit_DsdDecompose( pCof1, nVars );
+ ppNtks[0] = Kit_DsdExpand( pTemp = ppNtks[0] ); Kit_DsdNtkFree( pTemp );
+ ppNtks[1] = Kit_DsdExpand( pTemp = ppNtks[1] ); Kit_DsdNtkFree( pTemp );
+ if ( fVerbose )
+ Kit_DsdPrint( stdout, ppNtks[0] );
+ if ( fVerbose )
+ Kit_DsdPrint( stdout, ppNtks[1] );
+ // compute subsets
+ Lpk_ComputeSets( ppNtks[0], vSets0 );
+ Lpk_ComputeSets( ppNtks[1], vSets1 );
+ // print subsets
+ if ( fVerbose )
+ Lpk_PrintSets( vSets0 );
+ if ( fVerbose )
+ Lpk_PrintSets( vSets1 );
+ // free the networks
+ Kit_DsdNtkFree( ppNtks[0] );
+ Kit_DsdNtkFree( ppNtks[1] );
+ // evaluate the pair
+ Lpk_ComposeSets( vSets0, vSets1, nVars, i, pStore, &nSets, nStoreSize );
+ }
+
+ // print the results
+ if ( fVerbose )
+ printf( "\n" );
+ if ( fVerbose )
+ for ( i = 0; i < nSets; i++ )
+ Lpk_MapSuppPrintSet( pStore + i, i );
+
+ // choose the best subset
+ SizeMax = 0;
+ pSetBest = NULL;
+ for ( i = 0; i < nSets; i++ )
+ {
+ pSet = pStore + i;
+ if ( pSet->Size > p->pPars->nLutSize - 1 )
+ continue;
+ if ( SizeMax < pSet->Size )
+ {
+ pSetBest = pSet;
+ SizeMax = pSet->Size;
+ }
+ }
+/*
+ // if the best is not choosen, select the one with largest reduction
+ SRedMax = 0;
+ if ( pSetBest == NULL )
+ {
+ for ( i = 0; i < nSets; i++ )
+ {
+ pSet = pStore + i;
+ if ( SRedMax < pSet->SRed )
+ {
+ pSetBest = pSet;
+ SRedMax = pSet->SRed;
+ }
+ }
+ }
+*/
+ if ( pSetBest == NULL )
+ {
+ if ( fVerbose )
+ printf( "Could not select a subset.\n" );
+ return 0;
+ }
+ else
+ {
+ if ( fVerbose )
+ printf( "Selected the following subset:\n" );
+ if ( fVerbose )
+ Lpk_MapSuppPrintSet( pSetBest, pSetBest - pStore );
+ }
+
+ // prepare the return result
+ // get the remaining variables
+ Entry = ((pSetBest->uSubset0 >> 16) | (pSetBest->uSubset1 >> 16));
+ // get the variables to be removed
+ Entry = Kit_BitMask(nVars) & ~(1<<pSetBest->iVar) & ~Entry;
+ // make sure there are some - otherwise it is not supp-red
+ assert( Entry );
+ // remember the first such variable
+ *piVarReused = Kit_WordFindFirstBit( Entry );
+ *piVar = pSetBest->iVar;
+ return (pSetBest->uSubset1 << 16) | (pSetBest->uSubset0 & 0xFFFF);
+}
+
+////////////////////////////////////////////////////////////////////////
+/// END OF FILE ///
+////////////////////////////////////////////////////////////////////////
+
+
diff --git a/src/opt/lpk/lpk_.c b/src/opt/lpk/lpk_.c
new file mode 100644
index 00000000..d8555e08
--- /dev/null
+++ b/src/opt/lpk/lpk_.c
@@ -0,0 +1,48 @@
+/**CFile****************************************************************
+
+ FileName [lpk_.c]
+
+ SystemName [ABC: Logic synthesis and verification system.]
+
+ PackageName [Fast Boolean matching for LUT structures.]
+
+ Synopsis []
+
+ Author [Alan Mishchenko]
+
+ Affiliation [UC Berkeley]
+
+ Date [Ver. 1.0. Started - April 28, 2007.]
+
+ Revision [$Id: lpk_.c,v 1.00 2007/04/28 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "lpkInt.h"
+
+////////////////////////////////////////////////////////////////////////
+/// DECLARATIONS ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+/// FUNCTION DEFINITIONS ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+
+
+////////////////////////////////////////////////////////////////////////
+/// END OF FILE ///
+////////////////////////////////////////////////////////////////////////
+
+
diff --git a/src/opt/lpk/module.make b/src/opt/lpk/module.make
new file mode 100644
index 00000000..26a54894
--- /dev/null
+++ b/src/opt/lpk/module.make
@@ -0,0 +1,11 @@
+SRC += src/opt/lpk/lpkCore.c \
+ src/opt/lpk/lpkAbcDec.c \
+ src/opt/lpk/lpkAbcMux.c \
+ src/opt/lpk/lpkAbcDsd.c \
+ src/opt/lpk/lpkAbcUtil.c \
+ src/opt/lpk/lpkCut.c \
+ src/opt/lpk/lpkMan.c \
+ src/opt/lpk/lpkMap.c \
+ src/opt/lpk/lpkMulti.c \
+ src/opt/lpk/lpkMux.c \
+ src/opt/lpk/lpkSets.c
diff --git a/src/opt/res/module.make b/src/opt/res/module.make
new file mode 100644
index 00000000..52d8a315
--- /dev/null
+++ b/src/opt/res/module.make
@@ -0,0 +1,7 @@
+SRC += src/opt/res/resCore.c \
+ src/opt/res/resDivs.c \
+ src/opt/res/resFilter.c \
+ src/opt/res/resSat.c \
+ src/opt/res/resSim.c \
+ src/opt/res/resStrash.c \
+ src/opt/res/resWin.c
diff --git a/src/opt/res/res.h b/src/opt/res/res.h
new file mode 100644
index 00000000..3c3431bf
--- /dev/null
+++ b/src/opt/res/res.h
@@ -0,0 +1,75 @@
+/**CFile****************************************************************
+
+ FileName [res.h]
+
+ SystemName [ABC: Logic synthesis and verification system.]
+
+ PackageName [Resynthesis package.]
+
+ Synopsis [External declarations.]
+
+ Author [Alan Mishchenko]
+
+ Affiliation [UC Berkeley]
+
+ Date [Ver. 1.0. Started - January 15, 2007.]
+
+ Revision [$Id: res.h,v 1.00 2007/01/15 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#ifndef __RES_H__
+#define __RES_H__
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+////////////////////////////////////////////////////////////////////////
+/// INCLUDES ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+/// PARAMETERS ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+/// BASIC TYPES ///
+////////////////////////////////////////////////////////////////////////
+
+typedef struct Res_Par_t_ Res_Par_t;
+struct Res_Par_t_
+{
+ // general parameters
+ int nWindow; // window size
+ int nGrowthLevel; // the maximum allowed growth in level after one iteration of resynthesis
+ int nSimWords; // the number of simulation words
+ int nCands; // the number of candidates to try
+ int fArea; // performs optimization for area
+ int fDelay; // performs optimization for delay
+ int fVerbose; // enable basic stats
+ int fVeryVerbose; // enable detailed stats
+};
+
+////////////////////////////////////////////////////////////////////////
+/// MACRO DEFINITIONS ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+/// FUNCTION DECLARATIONS ///
+////////////////////////////////////////////////////////////////////////
+
+/*=== resCore.c ==========================================================*/
+extern int Abc_NtkResynthesize( Abc_Ntk_t * pNtk, Res_Par_t * pPars );
+
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
+
+////////////////////////////////////////////////////////////////////////
+/// END OF FILE ///
+////////////////////////////////////////////////////////////////////////
+
diff --git a/src/opt/res/resCore.c b/src/opt/res/resCore.c
new file mode 100644
index 00000000..cb448fc0
--- /dev/null
+++ b/src/opt/res/resCore.c
@@ -0,0 +1,419 @@
+/**CFile****************************************************************
+
+ FileName [resCore.c]
+
+ SystemName [ABC: Logic synthesis and verification system.]
+
+ PackageName [Resynthesis package.]
+
+ Synopsis [Top-level resynthesis procedure.]
+
+ Author [Alan Mishchenko]
+
+ Affiliation [UC Berkeley]
+
+ Date [Ver. 1.0. Started - January 15, 2007.]
+
+ Revision [$Id: resCore.c,v 1.00 2007/01/15 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "abc.h"
+#include "resInt.h"
+#include "kit.h"
+#include "satStore.h"
+
+////////////////////////////////////////////////////////////////////////
+/// DECLARATIONS ///
+////////////////////////////////////////////////////////////////////////
+
+typedef struct Res_Man_t_ Res_Man_t;
+struct Res_Man_t_
+{
+ // general parameters
+ Res_Par_t * pPars;
+ // specialized manager
+ Res_Win_t * pWin; // windowing manager
+ Abc_Ntk_t * pAig; // the strashed window
+ Res_Sim_t * pSim; // simulation manager
+ Sto_Man_t * pCnf; // the CNF of the SAT problem
+ Int_Man_t * pMan; // interpolation manager;
+ Vec_Int_t * vMem; // memory for intermediate SOPs
+ Vec_Vec_t * vResubs; // resubstitution candidates of the AIG
+ Vec_Vec_t * vResubsW; // resubstitution candidates of the window
+ Vec_Vec_t * vLevels; // levelized structure for updating
+ // statistics
+ int nWins; // the number of windows tried
+ int nWinNodes; // the total number of window nodes
+ int nDivNodes; // the total number of divisors
+ int nWinsTriv; // the total number of trivial windows
+ int nWinsUsed; // the total number of useful windows (with at least one candidate)
+ int nConstsUsed; // the total number of constant nodes under ODC
+ int nCandSets; // the total number of candidates
+ int nProvedSets; // the total number of proved groups
+ int nSimEmpty; // the empty simulation info
+ int nTotalNets; // the total number of nets
+ int nTotalNodes; // the total number of nodess
+ int nTotalNets2; // the total number of nets
+ int nTotalNodes2; // the total number of nodess
+ // runtime
+ int timeWin; // windowing
+ int timeDiv; // divisors
+ int timeAig; // strashing
+ int timeSim; // simulation
+ int timeCand; // resubstitution candidates
+ int timeSatTotal; // SAT solving total
+ int timeSatSat; // SAT solving (sat calls)
+ int timeSatUnsat; // SAT solving (unsat calls)
+ int timeSatSim; // SAT solving (simulation)
+ int timeInt; // interpolation
+ int timeUpd; // updating
+ int timeTotal; // total runtime
+};
+
+extern Hop_Obj_t * Kit_GraphToHop( Hop_Man_t * pMan, Kit_Graph_t * pGraph );
+
+extern int s_ResynTime;
+
+////////////////////////////////////////////////////////////////////////
+/// FUNCTION DEFINITIONS ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+ Synopsis [Allocate resynthesis manager.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Res_Man_t * Res_ManAlloc( Res_Par_t * pPars )
+{
+ Res_Man_t * p;
+ p = ALLOC( Res_Man_t, 1 );
+ memset( p, 0, sizeof(Res_Man_t) );
+ assert( pPars->nWindow > 0 && pPars->nWindow < 100 );
+ assert( pPars->nCands > 0 && pPars->nCands < 100 );
+ p->pPars = pPars;
+ p->pWin = Res_WinAlloc();
+ p->pSim = Res_SimAlloc( pPars->nSimWords );
+ p->pMan = Int_ManAlloc();
+ p->vMem = Vec_IntAlloc( 0 );
+ p->vResubs = Vec_VecStart( pPars->nCands );
+ p->vResubsW = Vec_VecStart( pPars->nCands );
+ p->vLevels = Vec_VecStart( 32 );
+ return p;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Deallocate resynthesis manager.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Res_ManFree( Res_Man_t * p )
+{
+ if ( p->pPars->fVerbose )
+ {
+ printf( "Reduction in nodes = %5d. (%.2f %%) ",
+ p->nTotalNodes-p->nTotalNodes2,
+ 100.0*(p->nTotalNodes-p->nTotalNodes2)/p->nTotalNodes );
+ printf( "Reduction in edges = %5d. (%.2f %%) ",
+ p->nTotalNets-p->nTotalNets2,
+ 100.0*(p->nTotalNets-p->nTotalNets2)/p->nTotalNets );
+ printf( "\n" );
+
+ printf( "Winds = %d. ", p->nWins );
+ printf( "Nodes = %d. (Ave = %5.1f) ", p->nWinNodes, 1.0*p->nWinNodes/p->nWins );
+ printf( "Divs = %d. (Ave = %5.1f) ", p->nDivNodes, 1.0*p->nDivNodes/p->nWins );
+ printf( "\n" );
+ printf( "WinsTriv = %d. ", p->nWinsTriv );
+ printf( "SimsEmpt = %d. ", p->nSimEmpty );
+ printf( "Const = %d. ", p->nConstsUsed );
+ printf( "WindUsed = %d. ", p->nWinsUsed );
+ printf( "Cands = %d. ", p->nCandSets );
+ printf( "Proved = %d.", p->nProvedSets );
+ printf( "\n" );
+
+ PRTP( "Windowing ", p->timeWin, p->timeTotal );
+ PRTP( "Divisors ", p->timeDiv, p->timeTotal );
+ PRTP( "Strashing ", p->timeAig, p->timeTotal );
+ PRTP( "Simulation ", p->timeSim, p->timeTotal );
+ PRTP( "Candidates ", p->timeCand, p->timeTotal );
+ PRTP( "SAT solver ", p->timeSatTotal, p->timeTotal );
+ PRTP( " sat ", p->timeSatSat, p->timeTotal );
+ PRTP( " unsat ", p->timeSatUnsat, p->timeTotal );
+ PRTP( " simul ", p->timeSatSim, p->timeTotal );
+ PRTP( "Interpol ", p->timeInt, p->timeTotal );
+ PRTP( "Undating ", p->timeUpd, p->timeTotal );
+ PRTP( "TOTAL ", p->timeTotal, p->timeTotal );
+ }
+ Res_WinFree( p->pWin );
+ if ( p->pAig ) Abc_NtkDelete( p->pAig );
+ Res_SimFree( p->pSim );
+ if ( p->pCnf ) Sto_ManFree( p->pCnf );
+ Int_ManFree( p->pMan );
+ Vec_IntFree( p->vMem );
+ Vec_VecFree( p->vResubs );
+ Vec_VecFree( p->vResubsW );
+ Vec_VecFree( p->vLevels );
+ free( p );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Incrementally updates level of the nodes.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Res_UpdateNetwork( Abc_Obj_t * pObj, Vec_Ptr_t * vFanins, Hop_Obj_t * pFunc, Vec_Vec_t * vLevels )
+{
+ Abc_Obj_t * pObjNew, * pFanin;
+ int k;
+ // create the new node
+ pObjNew = Abc_NtkCreateNode( pObj->pNtk );
+ pObjNew->pData = pFunc;
+ Vec_PtrForEachEntry( vFanins, pFanin, k )
+ Abc_ObjAddFanin( pObjNew, pFanin );
+ // replace the old node by the new node
+ // update the level of the node
+ Abc_NtkUpdate( pObj, pObjNew, vLevels );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Entrace into the resynthesis package.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Abc_NtkResynthesize( Abc_Ntk_t * pNtk, Res_Par_t * pPars )
+{
+ ProgressBar * pProgress;
+ Res_Man_t * p;
+ Abc_Obj_t * pObj;
+ Hop_Obj_t * pFunc;
+ Kit_Graph_t * pGraph;
+ Vec_Ptr_t * vFanins;
+ unsigned * puTruth;
+ int i, k, RetValue, nNodesOld, nFanins, nFaninsMax;
+ int clk, clkTotal = clock();
+
+ // start the manager
+ p = Res_ManAlloc( pPars );
+ p->nTotalNets = Abc_NtkGetTotalFanins(pNtk);
+ p->nTotalNodes = Abc_NtkNodeNum(pNtk);
+ nFaninsMax = Abc_NtkGetFaninMax(pNtk);
+ if ( nFaninsMax > 8 )
+ nFaninsMax = 8;
+
+ // perform the network sweep
+ Abc_NtkSweep( pNtk, 0 );
+
+ // convert into the AIG
+ if ( !Abc_NtkToAig(pNtk) )
+ {
+ fprintf( stdout, "Converting to BDD has failed.\n" );
+ Res_ManFree( p );
+ return 0;
+ }
+ assert( Abc_NtkHasAig(pNtk) );
+
+ // set the number of levels
+ Abc_NtkLevel( pNtk );
+ Abc_NtkStartReverseLevels( pNtk, pPars->nGrowthLevel );
+
+ // try resynthesizing nodes in the topological order
+ nNodesOld = Abc_NtkObjNumMax(pNtk);
+ pProgress = Extra_ProgressBarStart( stdout, nNodesOld );
+ Abc_NtkForEachObj( pNtk, pObj, i )
+ {
+ Extra_ProgressBarUpdate( pProgress, i, NULL );
+ if ( !Abc_ObjIsNode(pObj) )
+ continue;
+ if ( Abc_ObjFaninNum(pObj) > 8 )
+ continue;
+ if ( pObj->Id > nNodesOld )
+ break;
+
+ // create the window for this node
+clk = clock();
+ RetValue = Res_WinCompute( pObj, p->pPars->nWindow/10, p->pPars->nWindow%10, p->pWin );
+p->timeWin += clock() - clk;
+ if ( !RetValue )
+ continue;
+ p->nWinsTriv += Res_WinIsTrivial( p->pWin );
+
+ if ( p->pPars->fVeryVerbose )
+ {
+ printf( "%5d (lev=%2d) : ", pObj->Id, pObj->Level );
+ printf( "Win = %3d/%3d/%4d/%3d ",
+ Vec_PtrSize(p->pWin->vLeaves),
+ Vec_PtrSize(p->pWin->vBranches),
+ Vec_PtrSize(p->pWin->vNodes),
+ Vec_PtrSize(p->pWin->vRoots) );
+ }
+
+ // collect the divisors
+clk = clock();
+ Res_WinDivisors( p->pWin, Abc_ObjRequiredLevel(pObj) - 1 );
+p->timeDiv += clock() - clk;
+
+ p->nWins++;
+ p->nWinNodes += Vec_PtrSize(p->pWin->vNodes);
+ p->nDivNodes += Vec_PtrSize( p->pWin->vDivs);
+
+ if ( p->pPars->fVeryVerbose )
+ {
+ printf( "D = %3d ", Vec_PtrSize(p->pWin->vDivs) );
+ printf( "D+ = %3d ", p->pWin->nDivsPlus );
+ }
+
+ // create the AIG for the window
+clk = clock();
+ if ( p->pAig ) Abc_NtkDelete( p->pAig );
+ p->pAig = Res_WndStrash( p->pWin );
+p->timeAig += clock() - clk;
+
+ if ( p->pPars->fVeryVerbose )
+ {
+ printf( "AIG = %4d ", Abc_NtkNodeNum(p->pAig) );
+ printf( "\n" );
+ }
+
+ // prepare simulation info
+clk = clock();
+ RetValue = Res_SimPrepare( p->pSim, p->pAig, Vec_PtrSize(p->pWin->vLeaves), 0 ); //p->pPars->fVerbose );
+p->timeSim += clock() - clk;
+ if ( !RetValue )
+ {
+ p->nSimEmpty++;
+ continue;
+ }
+
+ // consider the case of constant node
+ if ( p->pSim->fConst0 || p->pSim->fConst1 )
+ {
+ p->nConstsUsed++;
+
+ pFunc = p->pSim->fConst1? Hop_ManConst1(pNtk->pManFunc) : Hop_ManConst0(pNtk->pManFunc);
+ vFanins = Vec_VecEntry( p->vResubsW, 0 );
+ Vec_PtrClear( vFanins );
+ Res_UpdateNetwork( pObj, vFanins, pFunc, p->vLevels );
+ continue;
+ }
+
+// printf( " " );
+
+ // find resub candidates for the node
+clk = clock();
+ if ( p->pPars->fArea )
+ RetValue = Res_FilterCandidates( p->pWin, p->pAig, p->pSim, p->vResubs, p->vResubsW, nFaninsMax, 1 );
+ else
+ RetValue = Res_FilterCandidates( p->pWin, p->pAig, p->pSim, p->vResubs, p->vResubsW, nFaninsMax, 0 );
+p->timeCand += clock() - clk;
+ p->nCandSets += RetValue;
+ if ( RetValue == 0 )
+ continue;
+
+// printf( "%d(%d) ", Vec_PtrSize(p->pWin->vDivs), RetValue );
+
+ p->nWinsUsed++;
+
+ // iterate through candidate resubstitutions
+ Vec_VecForEachLevel( p->vResubs, vFanins, k )
+ {
+ if ( Vec_PtrSize(vFanins) == 0 )
+ break;
+
+ // solve the SAT problem and get clauses
+clk = clock();
+ if ( p->pCnf ) Sto_ManFree( p->pCnf );
+ p->pCnf = Res_SatProveUnsat( p->pAig, vFanins );
+ if ( p->pCnf == NULL )
+ {
+p->timeSatSat += clock() - clk;
+// printf( " Sat\n" );
+// printf( "-" );
+ continue;
+ }
+p->timeSatUnsat += clock() - clk;
+// printf( "+" );
+
+ p->nProvedSets++;
+// printf( " Unsat\n" );
+// continue;
+// printf( "Proved %d.\n", k );
+
+ // write it into a file
+// Sto_ManDumpClauses( p->pCnf, "trace.cnf" );
+
+ // interpolate the problem if it was UNSAT
+clk = clock();
+ nFanins = Int_ManInterpolate( p->pMan, p->pCnf, 0, &puTruth );
+p->timeInt += clock() - clk;
+ if ( nFanins != Vec_PtrSize(vFanins) - 2 )
+ continue;
+ assert( puTruth );
+// Extra_PrintBinary( stdout, puTruth, 1 << nFanins ); printf( "\n" );
+
+ // transform interpolant into the AIG
+ pGraph = Kit_TruthToGraph( puTruth, nFanins, p->vMem );
+
+ // derive the AIG for the decomposition tree
+ pFunc = Kit_GraphToHop( pNtk->pManFunc, pGraph );
+ Kit_GraphFree( pGraph );
+
+ // update the network
+clk = clock();
+ Res_UpdateNetwork( pObj, Vec_VecEntry(p->vResubsW, k), pFunc, p->vLevels );
+p->timeUpd += clock() - clk;
+ break;
+ }
+// printf( "\n" );
+ }
+ Extra_ProgressBarStop( pProgress );
+ Abc_NtkStopReverseLevels( pNtk );
+
+p->timeSatSim += p->pSim->timeSat;
+p->timeSatTotal = p->timeSatSat + p->timeSatUnsat + p->timeSatSim;
+
+ p->nTotalNets2 = Abc_NtkGetTotalFanins(pNtk);
+ p->nTotalNodes2 = Abc_NtkNodeNum(pNtk);
+
+ // quit resubstitution manager
+p->timeTotal = clock() - clkTotal;
+ Res_ManFree( p );
+
+s_ResynTime += clock() - clkTotal;
+ // check the resulting network
+ if ( !Abc_NtkCheck( pNtk ) )
+ {
+ fprintf( stdout, "Abc_NtkResynthesize(): Network check has failed.\n" );
+ return 0;
+ }
+ return 1;
+}
+
+////////////////////////////////////////////////////////////////////////
+/// END OF FILE ///
+////////////////////////////////////////////////////////////////////////
+
+
diff --git a/src/opt/res/resDivs.c b/src/opt/res/resDivs.c
new file mode 100644
index 00000000..cc75b90f
--- /dev/null
+++ b/src/opt/res/resDivs.c
@@ -0,0 +1,285 @@
+/**CFile****************************************************************
+
+ FileName [resDivs.c]
+
+ SystemName [ABC: Logic synthesis and verification system.]
+
+ PackageName [Resynthesis package.]
+
+ Synopsis [Collect divisors for the given window.]
+
+ Author [Alan Mishchenko]
+
+ Affiliation [UC Berkeley]
+
+ Date [Ver. 1.0. Started - January 15, 2007.]
+
+ Revision [$Id: resDivs.c,v 1.00 2007/01/15 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "abc.h"
+#include "resInt.h"
+
+////////////////////////////////////////////////////////////////////////
+/// DECLARATIONS ///
+////////////////////////////////////////////////////////////////////////
+
+static void Res_WinMarkTfi( Res_Win_t * p );
+
+////////////////////////////////////////////////////////////////////////
+/// FUNCTION DEFINITIONS ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+ Synopsis [Adds candidate divisors of the node to its window.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Res_WinDivisors( Res_Win_t * p, int nLevDivMax )
+{
+ Abc_Obj_t * pObj, * pFanout, * pFanin;
+ int k, f, m;
+
+ // set the maximum level of the divisors
+ p->nLevDivMax = nLevDivMax;
+
+ // mark the TFI with the current trav ID
+ Abc_NtkIncrementTravId( p->pNode->pNtk );
+ Res_WinMarkTfi( p );
+
+ // mark with the current trav ID those nodes that should not be divisors:
+ // (1) the node and its TFO
+ // (2) the MFFC of the node
+ // (3) the node's fanins (these are treated as a special case)
+ Abc_NtkIncrementTravId( p->pNode->pNtk );
+ Res_WinSweepLeafTfo_rec( p->pNode, p->nLevDivMax );
+ Res_WinVisitMffc( p->pNode );
+ Abc_ObjForEachFanin( p->pNode, pObj, k )
+ Abc_NodeSetTravIdCurrent( pObj );
+
+ // at this point the nodes are marked with two trav IDs:
+ // nodes to be collected as divisors are marked with previous trav ID
+ // nodes to be avoided as divisors are marked with current trav ID
+
+ // start collecting the divisors
+ Vec_PtrClear( p->vDivs );
+ Vec_PtrForEachEntry( p->vLeaves, pObj, k )
+ {
+ assert( (int)pObj->Level >= p->nLevLeafMin );
+ if ( !Abc_NodeIsTravIdPrevious(pObj) )
+ continue;
+ if ( (int)pObj->Level > p->nLevDivMax )
+ continue;
+ Vec_PtrPush( p->vDivs, pObj );
+ }
+ // add the internal nodes to the data structure
+ Vec_PtrForEachEntry( p->vNodes, pObj, k )
+ {
+ if ( !Abc_NodeIsTravIdPrevious(pObj) )
+ continue;
+ if ( (int)pObj->Level > p->nLevDivMax )
+ continue;
+ Vec_PtrPush( p->vDivs, pObj );
+ }
+
+ // explore the fanouts of already collected divisors
+ p->nDivsPlus = 0;
+ Vec_PtrForEachEntry( p->vDivs, pObj, k )
+ {
+ // consider fanouts of this node
+ Abc_ObjForEachFanout( pObj, pFanout, f )
+ {
+ // stop if there are too many fanouts
+ if ( f > 20 )
+ break;
+ // skip nodes that are already added
+ if ( Abc_NodeIsTravIdPrevious(pFanout) )
+ continue;
+ // skip nodes in the TFO or in the MFFC of node
+ if ( Abc_NodeIsTravIdCurrent(pFanout) )
+ continue;
+ // skip COs
+ if ( !Abc_ObjIsNode(pFanout) )
+ continue;
+ // skip nodes with large level
+ if ( (int)pFanout->Level >= p->nLevDivMax )
+ continue;
+ // skip nodes whose fanins are not divisors
+ Abc_ObjForEachFanin( pFanout, pFanin, m )
+ if ( !Abc_NodeIsTravIdPrevious(pFanin) )
+ break;
+ if ( m < Abc_ObjFaninNum(pFanout) )
+ continue;
+ // add the node to the divisors
+ Vec_PtrPush( p->vDivs, pFanout );
+ Vec_PtrPush( p->vNodes, pFanout );
+ Abc_NodeSetTravIdPrevious( pFanout );
+ p->nDivsPlus++;
+ }
+ }
+/*
+ printf( "Node level = %d. ", Abc_ObjLevel(p->pNode) );
+ Vec_PtrForEachEntryStart( p->vDivs, pObj, k, Vec_PtrSize(p->vDivs)-p->nDivsPlus )
+ printf( "%d ", Abc_ObjLevel(pObj) );
+ printf( "\n" );
+*/
+//printf( "%d ", p->nDivsPlus );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Marks the TFI cone of the node.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Res_WinMarkTfi_rec( Res_Win_t * p, Abc_Obj_t * pObj )
+{
+ Abc_Obj_t * pFanin;
+ int i;
+ if ( Abc_NodeIsTravIdCurrent(pObj) )
+ return;
+ Abc_NodeSetTravIdCurrent( pObj );
+ assert( Abc_ObjIsNode(pObj) );
+ // visit the fanins of the node
+ Abc_ObjForEachFanin( pObj, pFanin, i )
+ Res_WinMarkTfi_rec( p, pFanin );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Marks the TFI cone of the node.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Res_WinMarkTfi( Res_Win_t * p )
+{
+ Abc_Obj_t * pObj;
+ int i;
+ // mark the leaves
+ Vec_PtrForEachEntry( p->vLeaves, pObj, i )
+ Abc_NodeSetTravIdCurrent( pObj );
+ // start from the node
+ Res_WinMarkTfi_rec( p, p->pNode );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Marks the TFO of the collected nodes up to the given level.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Res_WinSweepLeafTfo_rec( Abc_Obj_t * pObj, int nLevelLimit )
+{
+ Abc_Obj_t * pFanout;
+ int i;
+ if ( Abc_ObjIsCo(pObj) || (int)pObj->Level > nLevelLimit )
+ return;
+ if ( Abc_NodeIsTravIdCurrent(pObj) )
+ return;
+ Abc_NodeSetTravIdCurrent( pObj );
+ Abc_ObjForEachFanout( pObj, pFanout, i )
+ Res_WinSweepLeafTfo_rec( pFanout, nLevelLimit );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Dereferences the node's MFFC.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Res_NodeDeref_rec( Abc_Obj_t * pNode )
+{
+ Abc_Obj_t * pFanin;
+ int i, Counter = 1;
+ if ( Abc_ObjIsCi(pNode) )
+ return 0;
+ Abc_NodeSetTravIdCurrent( pNode );
+ Abc_ObjForEachFanin( pNode, pFanin, i )
+ {
+ assert( pFanin->vFanouts.nSize > 0 );
+ if ( --pFanin->vFanouts.nSize == 0 )
+ Counter += Res_NodeDeref_rec( pFanin );
+ }
+ return Counter;
+}
+
+/**Function*************************************************************
+
+ Synopsis [References the node's MFFC.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Res_NodeRef_rec( Abc_Obj_t * pNode )
+{
+ Abc_Obj_t * pFanin;
+ int i, Counter = 1;
+ if ( Abc_ObjIsCi(pNode) )
+ return 0;
+ Abc_ObjForEachFanin( pNode, pFanin, i )
+ {
+ if ( pFanin->vFanouts.nSize++ == 0 )
+ Counter += Res_NodeRef_rec( pFanin );
+ }
+ return Counter;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Labels MFFC of the node with the current trav ID.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Res_WinVisitMffc( Abc_Obj_t * pNode )
+{
+ int Count1, Count2;
+ assert( Abc_ObjIsNode(pNode) );
+ // dereference the node (mark with the current trav ID)
+ Count1 = Res_NodeDeref_rec( pNode );
+ // reference it back
+ Count2 = Res_NodeRef_rec( pNode );
+ assert( Count1 == Count2 );
+ return Count1;
+}
+
+////////////////////////////////////////////////////////////////////////
+/// END OF FILE ///
+////////////////////////////////////////////////////////////////////////
+
+
diff --git a/src/opt/res/resFilter.c b/src/opt/res/resFilter.c
new file mode 100644
index 00000000..f2ca41d3
--- /dev/null
+++ b/src/opt/res/resFilter.c
@@ -0,0 +1,434 @@
+/**CFile****************************************************************
+
+ FileName [resFilter.c]
+
+ SystemName [ABC: Logic synthesis and verification system.]
+
+ PackageName [Resynthesis package.]
+
+ Synopsis [Filtering resubstitution candidates.]
+
+ Author [Alan Mishchenko]
+
+ Affiliation [UC Berkeley]
+
+ Date [Ver. 1.0. Started - January 15, 2007.]
+
+ Revision [$Id: resFilter.c,v 1.00 2007/01/15 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "abc.h"
+#include "resInt.h"
+
+////////////////////////////////////////////////////////////////////////
+/// DECLARATIONS ///
+////////////////////////////////////////////////////////////////////////
+
+static unsigned * Res_FilterCollectFaninInfo( Res_Win_t * pWin, Res_Sim_t * pSim, unsigned uMask );
+static int Res_FilterCriticalFanin( Abc_Obj_t * pNode );
+
+////////////////////////////////////////////////////////////////////////
+/// FUNCTION DEFINITIONS ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+ Synopsis [Finds sets of feasible candidates.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Res_FilterCandidates( Res_Win_t * pWin, Abc_Ntk_t * pAig, Res_Sim_t * pSim, Vec_Vec_t * vResubs, Vec_Vec_t * vResubsW, int nFaninsMax, int fArea )
+{
+ Abc_Obj_t * pFanin, * pFanin2, * pFaninTemp;
+ unsigned * pInfo, * pInfoDiv, * pInfoDiv2;
+ int Counter, RetValue, i, i2, d, d2, iDiv, iDiv2, k;
+
+ // check that the info the node is one
+ pInfo = Vec_PtrEntry( pSim->vOuts, 1 );
+ RetValue = Abc_InfoIsOne( pInfo, pSim->nWordsOut );
+ if ( RetValue == 0 )
+ {
+// printf( "Failed 1!\n" );
+ return 0;
+ }
+
+ // collect the fanin info
+ pInfo = Res_FilterCollectFaninInfo( pWin, pSim, ~0 );
+ RetValue = Abc_InfoIsOne( pInfo, pSim->nWordsOut );
+ if ( RetValue == 0 )
+ {
+// printf( "Failed 2!\n" );
+ return 0;
+ }
+
+ // try removing each fanin
+// printf( "Fanins: " );
+ Counter = 0;
+ Vec_VecClear( vResubs );
+ Vec_VecClear( vResubsW );
+ Abc_ObjForEachFanin( pWin->pNode, pFanin, i )
+ {
+ if ( fArea && Abc_ObjFanoutNum(pFanin) > 1 )
+ continue;
+ // get simulation info without this fanin
+ pInfo = Res_FilterCollectFaninInfo( pWin, pSim, ~(1 << i) );
+ RetValue = Abc_InfoIsOne( pInfo, pSim->nWordsOut );
+ if ( RetValue )
+ {
+// printf( "Node %4d. Candidate fanin %4d.\n", pWin->pNode->Id, pFanin->Id );
+ // collect the nodes
+ Vec_VecPush( vResubs, Counter, Abc_NtkPo(pAig,0) );
+ Vec_VecPush( vResubs, Counter, Abc_NtkPo(pAig,1) );
+ Abc_ObjForEachFanin( pWin->pNode, pFaninTemp, k )
+ {
+ if ( k != i )
+ {
+ Vec_VecPush( vResubs, Counter, Abc_NtkPo(pAig,2+k) );
+ Vec_VecPush( vResubsW, Counter, pFaninTemp );
+ }
+ }
+ Counter++;
+ if ( Counter == Vec_VecSize(vResubs) )
+ return Counter;
+ }
+ }
+
+ // try replacing each critical fanin by a non-critical fanin
+ Abc_ObjForEachFanin( pWin->pNode, pFanin, i )
+ {
+ if ( Abc_ObjFanoutNum(pFanin) > 1 )
+ continue;
+ // get simulation info without this fanin
+ pInfo = Res_FilterCollectFaninInfo( pWin, pSim, ~(1 << i) );
+ // go over the set of divisors
+ for ( d = Abc_ObjFaninNum(pWin->pNode) + 2; d < Abc_NtkPoNum(pAig); d++ )
+ {
+ pInfoDiv = Vec_PtrEntry( pSim->vOuts, d );
+ iDiv = d - (Abc_ObjFaninNum(pWin->pNode) + 2);
+ if ( !Abc_InfoIsOrOne( pInfo, pInfoDiv, pSim->nWordsOut ) )
+ continue;
+ // collect the nodes
+ Vec_VecPush( vResubs, Counter, Abc_NtkPo(pAig,0) );
+ Vec_VecPush( vResubs, Counter, Abc_NtkPo(pAig,1) );
+ // collect the remaning fanins and the divisor
+ Abc_ObjForEachFanin( pWin->pNode, pFaninTemp, k )
+ {
+ if ( k != i )
+ {
+ Vec_VecPush( vResubs, Counter, Abc_NtkPo(pAig,2+k) );
+ Vec_VecPush( vResubsW, Counter, pFaninTemp );
+ }
+ }
+ // collect the divisor
+ Vec_VecPush( vResubs, Counter, Abc_NtkPo(pAig,d) );
+ Vec_VecPush( vResubsW, Counter, Vec_PtrEntry(pWin->vDivs, iDiv) );
+ Counter++;
+ if ( Counter == Vec_VecSize(vResubs) )
+ return Counter;
+ }
+ }
+
+ // consider the case when two fanins can be added instead of one
+ if ( Abc_ObjFaninNum(pWin->pNode) < nFaninsMax )
+ {
+ // try to replace each critical fanin by two non-critical fanins
+ Abc_ObjForEachFanin( pWin->pNode, pFanin, i )
+ {
+ if ( Abc_ObjFanoutNum(pFanin) > 1 )
+ continue;
+ // get simulation info without this fanin
+ pInfo = Res_FilterCollectFaninInfo( pWin, pSim, ~(1 << i) );
+ // go over the set of divisors
+ for ( d = Abc_ObjFaninNum(pWin->pNode) + 2; d < Abc_NtkPoNum(pAig); d++ )
+ {
+ pInfoDiv = Vec_PtrEntry( pSim->vOuts, d );
+ iDiv = d - (Abc_ObjFaninNum(pWin->pNode) + 2);
+ // go through the second divisor
+ for ( d2 = d + 1; d2 < Abc_NtkPoNum(pAig); d2++ )
+ {
+ pInfoDiv2 = Vec_PtrEntry( pSim->vOuts, d2 );
+ iDiv2 = d2 - (Abc_ObjFaninNum(pWin->pNode) + 2);
+ if ( !Abc_InfoIsOrOne3( pInfo, pInfoDiv, pInfoDiv2, pSim->nWordsOut ) )
+ continue;
+ // collect the nodes
+ Vec_VecPush( vResubs, Counter, Abc_NtkPo(pAig,0) );
+ Vec_VecPush( vResubs, Counter, Abc_NtkPo(pAig,1) );
+ // collect the remaning fanins and the divisor
+ Abc_ObjForEachFanin( pWin->pNode, pFaninTemp, k )
+ {
+ if ( k != i )
+ {
+ Vec_VecPush( vResubs, Counter, Abc_NtkPo(pAig,2+k) );
+ Vec_VecPush( vResubsW, Counter, pFaninTemp );
+ }
+ }
+ // collect the divisor
+ Vec_VecPush( vResubs, Counter, Abc_NtkPo(pAig,d) );
+ Vec_VecPush( vResubs, Counter, Abc_NtkPo(pAig,d2) );
+ Vec_VecPush( vResubsW, Counter, Vec_PtrEntry(pWin->vDivs, iDiv) );
+ Vec_VecPush( vResubsW, Counter, Vec_PtrEntry(pWin->vDivs, iDiv2) );
+ Counter++;
+ if ( Counter == Vec_VecSize(vResubs) )
+ return Counter;
+ }
+ }
+ }
+ }
+
+ // try to replace two nets by one
+ if ( !fArea )
+ {
+ Abc_ObjForEachFanin( pWin->pNode, pFanin, i )
+ {
+ for ( i2 = i + 1; i2 < Abc_ObjFaninNum(pWin->pNode); i2++ )
+ {
+ pFanin2 = Abc_ObjFanin(pWin->pNode, i2);
+ // get simulation info without these fanins
+ pInfo = Res_FilterCollectFaninInfo( pWin, pSim, (~(1 << i)) & (~(1 << i2)) );
+ // go over the set of divisors
+ for ( d = Abc_ObjFaninNum(pWin->pNode) + 2; d < Abc_NtkPoNum(pAig); d++ )
+ {
+ pInfoDiv = Vec_PtrEntry( pSim->vOuts, d );
+ iDiv = d - (Abc_ObjFaninNum(pWin->pNode) + 2);
+ if ( !Abc_InfoIsOrOne( pInfo, pInfoDiv, pSim->nWordsOut ) )
+ continue;
+ // collect the nodes
+ Vec_VecPush( vResubs, Counter, Abc_NtkPo(pAig,0) );
+ Vec_VecPush( vResubs, Counter, Abc_NtkPo(pAig,1) );
+ // collect the remaning fanins and the divisor
+ Abc_ObjForEachFanin( pWin->pNode, pFaninTemp, k )
+ {
+ if ( k != i && k != i2 )
+ {
+ Vec_VecPush( vResubs, Counter, Abc_NtkPo(pAig,2+k) );
+ Vec_VecPush( vResubsW, Counter, pFaninTemp );
+ }
+ }
+ // collect the divisor
+ Vec_VecPush( vResubs, Counter, Abc_NtkPo(pAig,d) );
+ Vec_VecPush( vResubsW, Counter, Vec_PtrEntry(pWin->vDivs, iDiv) );
+ Counter++;
+ if ( Counter == Vec_VecSize(vResubs) )
+ return Counter;
+ }
+ }
+ }
+ }
+ return Counter;
+}
+
+
+/**Function*************************************************************
+
+ Synopsis [Finds sets of feasible candidates.]
+
+ Description [This procedure is a special case of the above.]
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Res_FilterCandidatesArea( Res_Win_t * pWin, Abc_Ntk_t * pAig, Res_Sim_t * pSim, Vec_Vec_t * vResubs, Vec_Vec_t * vResubsW, int nFaninsMax )
+{
+ Abc_Obj_t * pFanin;
+ unsigned * pInfo, * pInfoDiv, * pInfoDiv2;
+ int Counter, RetValue, d, d2, k, iDiv, iDiv2, iBest;
+
+ // check that the info the node is one
+ pInfo = Vec_PtrEntry( pSim->vOuts, 1 );
+ RetValue = Abc_InfoIsOne( pInfo, pSim->nWordsOut );
+ if ( RetValue == 0 )
+ {
+// printf( "Failed 1!\n" );
+ return 0;
+ }
+
+ // collect the fanin info
+ pInfo = Res_FilterCollectFaninInfo( pWin, pSim, ~0 );
+ RetValue = Abc_InfoIsOne( pInfo, pSim->nWordsOut );
+ if ( RetValue == 0 )
+ {
+// printf( "Failed 2!\n" );
+ return 0;
+ }
+
+ // try removing fanins
+// printf( "Fanins: " );
+ Counter = 0;
+ Vec_VecClear( vResubs );
+ Vec_VecClear( vResubsW );
+ // get the best fanins
+ iBest = Res_FilterCriticalFanin( pWin->pNode );
+ if ( iBest == -1 )
+ return 0;
+
+ // get the info without the critical fanin
+ pInfo = Res_FilterCollectFaninInfo( pWin, pSim, ~(1 << iBest) );
+ RetValue = Abc_InfoIsOne( pInfo, pSim->nWordsOut );
+ if ( RetValue )
+ {
+// printf( "Can be done without one!\n" );
+ // collect the nodes
+ Vec_VecPush( vResubs, Counter, Abc_NtkPo(pAig,0) );
+ Vec_VecPush( vResubs, Counter, Abc_NtkPo(pAig,1) );
+ Abc_ObjForEachFanin( pWin->pNode, pFanin, k )
+ {
+ if ( k != iBest )
+ {
+ Vec_VecPush( vResubs, Counter, Abc_NtkPo(pAig,2+k) );
+ Vec_VecPush( vResubsW, Counter, pFanin );
+ }
+ }
+ Counter++;
+// printf( "*" );
+ return Counter;
+ }
+
+ // go through the divisors
+ for ( d = Abc_ObjFaninNum(pWin->pNode) + 2; d < Abc_NtkPoNum(pAig); d++ )
+ {
+ pInfoDiv = Vec_PtrEntry( pSim->vOuts, d );
+ iDiv = d - (Abc_ObjFaninNum(pWin->pNode) + 2);
+ if ( !Abc_InfoIsOrOne( pInfo, pInfoDiv, pSim->nWordsOut ) )
+ continue;
+//if ( Abc_ObjLevel(pWin->pNode) <= Abc_ObjLevel( Vec_PtrEntry(pWin->vDivs, iDiv) ) )
+// printf( "Node level = %d. Divisor level = %d.\n", Abc_ObjLevel(pWin->pNode), Abc_ObjLevel( Vec_PtrEntry(pWin->vDivs, iDiv) ) );
+ // collect the nodes
+ Vec_VecPush( vResubs, Counter, Abc_NtkPo(pAig,0) );
+ Vec_VecPush( vResubs, Counter, Abc_NtkPo(pAig,1) );
+ // collect the remaning fanins and the divisor
+ Abc_ObjForEachFanin( pWin->pNode, pFanin, k )
+ {
+ if ( k != iBest )
+ {
+ Vec_VecPush( vResubs, Counter, Abc_NtkPo(pAig,2+k) );
+ Vec_VecPush( vResubsW, Counter, pFanin );
+ }
+ }
+ // collect the divisor
+ Vec_VecPush( vResubs, Counter, Abc_NtkPo(pAig,d) );
+ Vec_VecPush( vResubsW, Counter, Vec_PtrEntry(pWin->vDivs, iDiv) );
+ Counter++;
+
+ if ( Counter == Vec_VecSize(vResubs) )
+ break;
+ }
+
+ if ( Counter > 0 || Abc_ObjFaninNum(pWin->pNode) >= nFaninsMax )
+ return Counter;
+
+ // try to find the node pairs
+ for ( d = Abc_ObjFaninNum(pWin->pNode) + 2; d < Abc_NtkPoNum(pAig); d++ )
+ {
+ pInfoDiv = Vec_PtrEntry( pSim->vOuts, d );
+ iDiv = d - (Abc_ObjFaninNum(pWin->pNode) + 2);
+ // go through the second divisor
+ for ( d2 = d + 1; d2 < Abc_NtkPoNum(pAig); d2++ )
+ {
+ pInfoDiv2 = Vec_PtrEntry( pSim->vOuts, d2 );
+ iDiv2 = d2 - (Abc_ObjFaninNum(pWin->pNode) + 2);
+
+ if ( !Abc_InfoIsOrOne3( pInfo, pInfoDiv, pInfoDiv2, pSim->nWordsOut ) )
+ continue;
+ // collect the nodes
+ Vec_VecPush( vResubs, Counter, Abc_NtkPo(pAig,0) );
+ Vec_VecPush( vResubs, Counter, Abc_NtkPo(pAig,1) );
+ // collect the remaning fanins and the divisor
+ Abc_ObjForEachFanin( pWin->pNode, pFanin, k )
+ {
+ if ( k != iBest )
+ {
+ Vec_VecPush( vResubs, Counter, Abc_NtkPo(pAig,2+k) );
+ Vec_VecPush( vResubsW, Counter, pFanin );
+ }
+ }
+ // collect the divisor
+ Vec_VecPush( vResubs, Counter, Abc_NtkPo(pAig,d) );
+ Vec_VecPush( vResubs, Counter, Abc_NtkPo(pAig,d2) );
+ Vec_VecPush( vResubsW, Counter, Vec_PtrEntry(pWin->vDivs, iDiv) );
+ Vec_VecPush( vResubsW, Counter, Vec_PtrEntry(pWin->vDivs, iDiv2) );
+ Counter++;
+
+ if ( Counter == Vec_VecSize(vResubs) )
+ break;
+ }
+ if ( Counter == Vec_VecSize(vResubs) )
+ break;
+ }
+ return Counter;
+}
+
+
+/**Function*************************************************************
+
+ Synopsis [Finds sets of feasible candidates.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+unsigned * Res_FilterCollectFaninInfo( Res_Win_t * pWin, Res_Sim_t * pSim, unsigned uMask )
+{
+ Abc_Obj_t * pFanin;
+ unsigned * pInfo;
+ int i;
+ pInfo = Vec_PtrEntry( pSim->vOuts, 0 );
+ Abc_InfoClear( pInfo, pSim->nWordsOut );
+ Abc_ObjForEachFanin( pWin->pNode, pFanin, i )
+ {
+ if ( uMask & (1 << i) )
+ Abc_InfoOr( pInfo, Vec_PtrEntry(pSim->vOuts, 2+i), pSim->nWordsOut );
+ }
+ return pInfo;
+}
+
+
+/**Function*************************************************************
+
+ Synopsis [Returns the index of the most critical fanin.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Res_FilterCriticalFanin( Abc_Obj_t * pNode )
+{
+ Abc_Obj_t * pFanin;
+ int i, iBest = -1, CostMax = 0, CostCur;
+ Abc_ObjForEachFanin( pNode, pFanin, i )
+ {
+ if ( !Abc_ObjIsNode(pFanin) )
+ continue;
+ if ( Abc_ObjFanoutNum(pFanin) > 1 )
+ continue;
+ CostCur = Res_WinVisitMffc( pFanin );
+ if ( CostMax < CostCur )
+ {
+ CostMax = CostCur;
+ iBest = i;
+ }
+ }
+// if ( CostMax > 0 )
+// printf( "<%d>", CostMax );
+ return iBest;
+}
+
+
+////////////////////////////////////////////////////////////////////////
+/// END OF FILE ///
+////////////////////////////////////////////////////////////////////////
+
+
diff --git a/src/opt/res/resInt.h b/src/opt/res/resInt.h
new file mode 100644
index 00000000..5aae46cc
--- /dev/null
+++ b/src/opt/res/resInt.h
@@ -0,0 +1,137 @@
+/**CFile****************************************************************
+
+ FileName [resInt.h]
+
+ SystemName [ABC: Logic synthesis and verification system.]
+
+ PackageName [Resynthesis package.]
+
+ Synopsis [Internal declarations.]
+
+ Author [Alan Mishchenko]
+
+ Affiliation [UC Berkeley]
+
+ Date [Ver. 1.0. Started - January 15, 2007.]
+
+ Revision [$Id: resInt.h,v 1.00 2007/01/15 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#ifndef __RES_INT_H__
+#define __RES_INT_H__
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+////////////////////////////////////////////////////////////////////////
+/// INCLUDES ///
+////////////////////////////////////////////////////////////////////////
+
+#include "res.h"
+
+////////////////////////////////////////////////////////////////////////
+/// PARAMETERS ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+/// BASIC TYPES ///
+////////////////////////////////////////////////////////////////////////
+
+typedef struct Res_Win_t_ Res_Win_t;
+struct Res_Win_t_
+{
+ // windowing parameters
+ Abc_Obj_t * pNode; // the node in the center
+ int nWinTfiMax; // the fanin levels
+ int nWinTfoMax; // the fanout levels
+ int nLevDivMax; // the maximum divisor level
+ // internal windowing parameters
+ int nFanoutLimit; // the limit on the fanout count of a TFO node (if more, the node is treated as a root)
+ int nLevTfiMinus; // the number of additional levels to search from TFO below the level of leaves
+ // derived windowing parameters
+ int nLevLeafMin; // the minimum level of a leaf
+ int nLevTravMin; // the minimum level to search from TFO
+ int nDivsPlus; // the number of additional divisors
+ // the window data
+ Vec_Ptr_t * vRoots; // outputs of the window
+ Vec_Ptr_t * vLeaves; // inputs of the window
+ Vec_Ptr_t * vBranches; // side nodes of the window
+ Vec_Ptr_t * vNodes; // internal nodes of the window
+ Vec_Ptr_t * vDivs; // candidate divisors of the node
+ // temporary data
+ Vec_Vec_t * vMatrix; // TFI nodes below the given node
+};
+
+typedef struct Res_Sim_t_ Res_Sim_t;
+struct Res_Sim_t_
+{
+ Abc_Ntk_t * pAig; // AIG for simulation
+ int nTruePis; // the number of true PIs of the window
+ int fConst0; // the node can be replaced by constant 0
+ int fConst1; // the node can be replaced by constant 0
+ // simulation parameters
+ int nWords; // the number of simulation words
+ int nPats; // the number of patterns
+ int nWordsIn; // the number of simulation words in the input patterns
+ int nPatsIn; // the number of patterns in the input patterns
+ int nBytesIn; // the number of bytes in the input patterns
+ int nWordsOut; // the number of simulation words in the output patterns
+ int nPatsOut; // the number of patterns in the output patterns
+ // simulation info
+ Vec_Ptr_t * vPats; // input simulation patterns
+ Vec_Ptr_t * vPats0; // input simulation patterns
+ Vec_Ptr_t * vPats1; // input simulation patterns
+ Vec_Ptr_t * vOuts; // output simulation info
+ int nPats0; // the number of 0-patterns accumulated
+ int nPats1; // the number of 1-patterns accumulated
+ // resub candidates
+ Vec_Vec_t * vCands; // resubstitution candidates
+ // statistics
+ int timeSat;
+};
+
+////////////////////////////////////////////////////////////////////////
+/// MACRO DEFINITIONS ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+/// FUNCTION DECLARATIONS ///
+////////////////////////////////////////////////////////////////////////
+
+/*=== resDivs.c ==========================================================*/
+extern void Res_WinDivisors( Res_Win_t * p, int nLevDivMax );
+extern void Res_WinSweepLeafTfo_rec( Abc_Obj_t * pObj, int nLevelLimit );
+extern int Res_WinVisitMffc( Abc_Obj_t * pNode );
+/*=== resFilter.c ==========================================================*/
+extern int Res_FilterCandidates( Res_Win_t * pWin, Abc_Ntk_t * pAig, Res_Sim_t * pSim, Vec_Vec_t * vResubs, Vec_Vec_t * vResubsW, int nFaninsMax, int fArea );
+extern int Res_FilterCandidatesArea( Res_Win_t * pWin, Abc_Ntk_t * pAig, Res_Sim_t * pSim, Vec_Vec_t * vResubs, Vec_Vec_t * vResubsW, int nFaninsMax );
+/*=== resSat.c ==========================================================*/
+extern void * Res_SatProveUnsat( Abc_Ntk_t * pAig, Vec_Ptr_t * vFanins );
+extern int Res_SatSimulate( Res_Sim_t * p, int nPats, int fOnSet );
+/*=== resSim.c ==========================================================*/
+extern Res_Sim_t * Res_SimAlloc( int nWords );
+extern void Res_SimFree( Res_Sim_t * p );
+extern int Res_SimPrepare( Res_Sim_t * p, Abc_Ntk_t * pAig, int nTruePis, int fVerbose );
+/*=== resStrash.c ==========================================================*/
+extern Abc_Ntk_t * Res_WndStrash( Res_Win_t * p );
+/*=== resWnd.c ==========================================================*/
+extern void Res_UpdateNetwork( Abc_Obj_t * pObj, Vec_Ptr_t * vFanins, Hop_Obj_t * pFunc, Vec_Vec_t * vLevels );
+/*=== resWnd.c ==========================================================*/
+extern Res_Win_t * Res_WinAlloc();
+extern void Res_WinFree( Res_Win_t * p );
+extern int Res_WinIsTrivial( Res_Win_t * p );
+extern int Res_WinCompute( Abc_Obj_t * pNode, int nWinTfiMax, int nWinTfoMax, Res_Win_t * p );
+
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
+
+////////////////////////////////////////////////////////////////////////
+/// END OF FILE ///
+////////////////////////////////////////////////////////////////////////
+
diff --git a/src/opt/res/resSat.c b/src/opt/res/resSat.c
new file mode 100644
index 00000000..dd0e7a23
--- /dev/null
+++ b/src/opt/res/resSat.c
@@ -0,0 +1,407 @@
+/**CFile****************************************************************
+
+ FileName [resSat.c]
+
+ SystemName [ABC: Logic synthesis and verification system.]
+
+ PackageName [Resynthesis package.]
+
+ Synopsis [Interface with the SAT solver.]
+
+ Author [Alan Mishchenko]
+
+ Affiliation [UC Berkeley]
+
+ Date [Ver. 1.0. Started - January 15, 2007.]
+
+ Revision [$Id: resSat.c,v 1.00 2007/01/15 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "abc.h"
+#include "resInt.h"
+#include "hop.h"
+#include "satSolver.h"
+
+////////////////////////////////////////////////////////////////////////
+/// DECLARATIONS ///
+////////////////////////////////////////////////////////////////////////
+
+extern int Res_SatAddConst1( sat_solver * pSat, int iVar, int fCompl );
+extern int Res_SatAddEqual( sat_solver * pSat, int iVar0, int iVar1, int fCompl );
+extern int Res_SatAddAnd( sat_solver * pSat, int iVar, int iVar0, int iVar1, int fCompl0, int fCompl1 );
+
+////////////////////////////////////////////////////////////////////////
+/// FUNCTION DEFINITIONS ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+ Synopsis [Loads AIG into the SAT solver for checking resubstitution.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void * Res_SatProveUnsat( Abc_Ntk_t * pAig, Vec_Ptr_t * vFanins )
+{
+ void * pCnf = NULL;
+ sat_solver * pSat;
+ Vec_Ptr_t * vNodes;
+ Abc_Obj_t * pObj;
+ int i, nNodes, status;
+
+ // make sure fanins contain POs of the AIG
+ pObj = Vec_PtrEntry( vFanins, 0 );
+ assert( pObj->pNtk == pAig && Abc_ObjIsPo(pObj) );
+
+ // collect reachable nodes
+ vNodes = Abc_NtkDfsNodes( pAig, (Abc_Obj_t **)vFanins->pArray, vFanins->nSize );
+
+ // assign unique numbers to each node
+ nNodes = 0;
+ Abc_AigConst1(pAig)->pCopy = (void *)nNodes++;
+ Abc_NtkForEachPi( pAig, pObj, i )
+ pObj->pCopy = (void *)nNodes++;
+ Vec_PtrForEachEntry( vNodes, pObj, i )
+ pObj->pCopy = (void *)nNodes++;
+ Vec_PtrForEachEntry( vFanins, pObj, i ) // useful POs
+ pObj->pCopy = (void *)nNodes++;
+
+ // start the solver
+ pSat = sat_solver_new();
+ sat_solver_store_alloc( pSat );
+
+ // add clause for the constant node
+ Res_SatAddConst1( pSat, (int)Abc_AigConst1(pAig)->pCopy, 0 );
+ // add clauses for AND gates
+ Vec_PtrForEachEntry( vNodes, pObj, i )
+ Res_SatAddAnd( pSat, (int)pObj->pCopy,
+ (int)Abc_ObjFanin0(pObj)->pCopy, (int)Abc_ObjFanin1(pObj)->pCopy, Abc_ObjFaninC0(pObj), Abc_ObjFaninC1(pObj) );
+ Vec_PtrFree( vNodes );
+ // add clauses for POs
+ Vec_PtrForEachEntry( vFanins, pObj, i )
+ Res_SatAddEqual( pSat, (int)pObj->pCopy,
+ (int)Abc_ObjFanin0(pObj)->pCopy, Abc_ObjFaninC0(pObj) );
+ // add trivial clauses
+ pObj = Vec_PtrEntry(vFanins, 0);
+ Res_SatAddConst1( pSat, (int)pObj->pCopy, 0 ); // care-set
+ pObj = Vec_PtrEntry(vFanins, 1);
+ Res_SatAddConst1( pSat, (int)pObj->pCopy, 0 ); // on-set
+
+ // bookmark the clauses of A
+ sat_solver_store_mark_clauses_a( pSat );
+
+ // duplicate the clauses
+ pObj = Vec_PtrEntry(vFanins, 1);
+ Sat_SolverDoubleClauses( pSat, (int)pObj->pCopy );
+ // add the equality constraints
+ Vec_PtrForEachEntryStart( vFanins, pObj, i, 2 )
+ Res_SatAddEqual( pSat, (int)pObj->pCopy, ((int)pObj->pCopy) + nNodes, 0 );
+
+ // bookmark the roots
+ sat_solver_store_mark_roots( pSat );
+
+ // solve the problem
+ status = sat_solver_solve( pSat, NULL, NULL, (sint64)10000, (sint64)0, (sint64)0, (sint64)0 );
+ if ( status == l_False )
+ {
+ pCnf = sat_solver_store_release( pSat );
+// printf( "unsat\n" );
+ }
+ else if ( status == l_True )
+ {
+// printf( "sat\n" );
+ }
+ else
+ {
+// printf( "undef\n" );
+ }
+ sat_solver_delete( pSat );
+ return pCnf;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Loads AIG into the SAT solver for constrained simulation.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void * Res_SatSimulateConstr( Abc_Ntk_t * pAig, int fOnSet )
+{
+ sat_solver * pSat;
+ Vec_Ptr_t * vFanins;
+ Vec_Ptr_t * vNodes;
+ Abc_Obj_t * pObj;
+ int i, nNodes;
+
+ // start the array
+ vFanins = Vec_PtrAlloc( 2 );
+ pObj = Abc_NtkPo( pAig, 0 );
+ Vec_PtrPush( vFanins, pObj );
+ pObj = Abc_NtkPo( pAig, 1 );
+ Vec_PtrPush( vFanins, pObj );
+
+ // collect reachable nodes
+ vNodes = Abc_NtkDfsNodes( pAig, (Abc_Obj_t **)vFanins->pArray, vFanins->nSize );
+
+ // assign unique numbers to each node
+ nNodes = 0;
+ Abc_AigConst1(pAig)->pCopy = (void *)nNodes++;
+ Abc_NtkForEachPi( pAig, pObj, i )
+ pObj->pCopy = (void *)nNodes++;
+ Vec_PtrForEachEntry( vNodes, pObj, i )
+ pObj->pCopy = (void *)nNodes++;
+ Vec_PtrForEachEntry( vFanins, pObj, i ) // useful POs
+ pObj->pCopy = (void *)nNodes++;
+
+ // start the solver
+ pSat = sat_solver_new();
+
+ // add clause for the constant node
+ Res_SatAddConst1( pSat, (int)Abc_AigConst1(pAig)->pCopy, 0 );
+ // add clauses for AND gates
+ Vec_PtrForEachEntry( vNodes, pObj, i )
+ Res_SatAddAnd( pSat, (int)pObj->pCopy,
+ (int)Abc_ObjFanin0(pObj)->pCopy, (int)Abc_ObjFanin1(pObj)->pCopy, Abc_ObjFaninC0(pObj), Abc_ObjFaninC1(pObj) );
+ Vec_PtrFree( vNodes );
+ // add clauses for the first PO
+ pObj = Abc_NtkPo( pAig, 0 );
+ Res_SatAddEqual( pSat, (int)pObj->pCopy,
+ (int)Abc_ObjFanin0(pObj)->pCopy, Abc_ObjFaninC0(pObj) );
+ // add clauses for the second PO
+ pObj = Abc_NtkPo( pAig, 1 );
+ Res_SatAddEqual( pSat, (int)pObj->pCopy,
+ (int)Abc_ObjFanin0(pObj)->pCopy, Abc_ObjFaninC0(pObj) );
+
+ // add trivial clauses
+ pObj = Abc_NtkPo( pAig, 0 );
+ Res_SatAddConst1( pSat, (int)pObj->pCopy, 0 ); // care-set
+
+ pObj = Abc_NtkPo( pAig, 1 );
+ Res_SatAddConst1( pSat, (int)pObj->pCopy, !fOnSet ); // on-set
+
+ Vec_PtrFree( vFanins );
+ return pSat;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Loads AIG into the SAT solver for constrained simulation.]
+
+ Description [Returns 1 if the required number of patterns are found.
+ Returns 0 if the solver ran out of time or proved a constant.
+ In the latter, case one of the flags, fConst0 or fConst1, are set to 1.]
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Res_SatSimulate( Res_Sim_t * p, int nPatsLimit, int fOnSet )
+{
+ Vec_Int_t * vLits;
+ Vec_Ptr_t * vPats;
+ sat_solver * pSat;
+ int RetValue, i, k, value, status, Lit, Var, iPat;
+ int clk = clock();
+
+//printf( "Looking for %s: ", fOnSet? "onset " : "offset" );
+
+ // decide what problem should be solved
+ Lit = toLitCond( (int)Abc_NtkPo(p->pAig,1)->pCopy, !fOnSet );
+ if ( fOnSet )
+ {
+ iPat = p->nPats1;
+ vPats = p->vPats1;
+ }
+ else
+ {
+ iPat = p->nPats0;
+ vPats = p->vPats0;
+ }
+ assert( iPat < nPatsLimit );
+
+ // derive the SAT solver
+ pSat = Res_SatSimulateConstr( p->pAig, fOnSet );
+ pSat->fSkipSimplify = 1;
+ status = sat_solver_simplify( pSat );
+ if ( status == 0 )
+ {
+ if ( iPat == 0 )
+ {
+// if ( fOnSet )
+// p->fConst0 = 1;
+// else
+// p->fConst1 = 1;
+ RetValue = 0;
+ }
+ goto finish;
+ }
+
+ // enumerate through the SAT assignments
+ RetValue = 1;
+ vLits = Vec_IntAlloc( 32 );
+ for ( k = iPat; k < nPatsLimit; k++ )
+ {
+ // solve with the assumption
+// status = sat_solver_solve( pSat, &Lit, &Lit + 1, (sint64)10000, (sint64)0, (sint64)0, (sint64)0 );
+ status = sat_solver_solve( pSat, NULL, NULL, (sint64)10000, (sint64)0, (sint64)0, (sint64)0 );
+ if ( status == l_False )
+ {
+//printf( "Const %d\n", !fOnSet );
+ if ( k == 0 )
+ {
+ if ( fOnSet )
+ p->fConst0 = 1;
+ else
+ p->fConst1 = 1;
+ RetValue = 0;
+ }
+ break;
+ }
+ else if ( status == l_True )
+ {
+ // save the pattern
+ Vec_IntClear( vLits );
+ for ( i = 0; i < p->nTruePis; i++ )
+ {
+ Var = (int)Abc_NtkPi(p->pAig,i)->pCopy;
+ value = (int)(pSat->model.ptr[Var] == l_True);
+ if ( value )
+ Abc_InfoSetBit( Vec_PtrEntry(vPats, i), k );
+ Lit = toLitCond( Var, value );
+ Vec_IntPush( vLits, Lit );
+// printf( "%d", value );
+ }
+// printf( "\n" );
+
+ status = sat_solver_addclause( pSat, Vec_IntArray(vLits), Vec_IntArray(vLits) + Vec_IntSize(vLits) );
+ if ( status == 0 )
+ {
+ k++;
+ RetValue = 1;
+ break;
+ }
+ }
+ else
+ {
+//printf( "Undecided\n" );
+ if ( k == 0 )
+ RetValue = 0;
+ else
+ RetValue = 1;
+ break;
+ }
+ }
+ Vec_IntFree( vLits );
+//printf( "Found %d patterns\n", k - iPat );
+
+ // set the new number of patterns
+ if ( fOnSet )
+ p->nPats1 = k;
+ else
+ p->nPats0 = k;
+
+finish:
+
+ sat_solver_delete( pSat );
+p->timeSat += clock() - clk;
+ return RetValue;
+}
+
+
+/**Function*************************************************************
+
+ Synopsis [Asserts equality of the variable to a constant.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Res_SatAddConst1( sat_solver * pSat, int iVar, int fCompl )
+{
+ lit Lit = toLitCond( iVar, fCompl );
+ if ( !sat_solver_addclause( pSat, &Lit, &Lit + 1 ) )
+ return 0;
+ return 1;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Asserts equality of two variables.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Res_SatAddEqual( sat_solver * pSat, int iVar0, int iVar1, int fCompl )
+{
+ lit Lits[2];
+
+ Lits[0] = toLitCond( iVar0, 0 );
+ Lits[1] = toLitCond( iVar1, !fCompl );
+ if ( !sat_solver_addclause( pSat, Lits, Lits + 2 ) )
+ return 0;
+
+ Lits[0] = toLitCond( iVar0, 1 );
+ Lits[1] = toLitCond( iVar1, fCompl );
+ if ( !sat_solver_addclause( pSat, Lits, Lits + 2 ) )
+ return 0;
+
+ return 1;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Adds constraints for the two-input AND-gate.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Res_SatAddAnd( sat_solver * pSat, int iVar, int iVar0, int iVar1, int fCompl0, int fCompl1 )
+{
+ lit Lits[3];
+
+ Lits[0] = toLitCond( iVar, 1 );
+ Lits[1] = toLitCond( iVar0, fCompl0 );
+ if ( !sat_solver_addclause( pSat, Lits, Lits + 2 ) )
+ return 0;
+
+ Lits[0] = toLitCond( iVar, 1 );
+ Lits[1] = toLitCond( iVar1, fCompl1 );
+ if ( !sat_solver_addclause( pSat, Lits, Lits + 2 ) )
+ return 0;
+
+ Lits[0] = toLitCond( iVar, 0 );
+ Lits[1] = toLitCond( iVar0, !fCompl0 );
+ Lits[2] = toLitCond( iVar1, !fCompl1 );
+ if ( !sat_solver_addclause( pSat, Lits, Lits + 3 ) )
+ return 0;
+
+ return 1;
+}
+
+////////////////////////////////////////////////////////////////////////
+/// END OF FILE ///
+////////////////////////////////////////////////////////////////////////
+
+
diff --git a/src/opt/res/resSim.c b/src/opt/res/resSim.c
new file mode 100644
index 00000000..5c1dd2b6
--- /dev/null
+++ b/src/opt/res/resSim.c
@@ -0,0 +1,790 @@
+/**CFile****************************************************************
+
+ FileName [resSim.c]
+
+ SystemName [ABC: Logic synthesis and verification system.]
+
+ PackageName [Resynthesis package.]
+
+ Synopsis [Simulation engine.]
+
+ Author [Alan Mishchenko]
+
+ Affiliation [UC Berkeley]
+
+ Date [Ver. 1.0. Started - January 15, 2007.]
+
+ Revision [$Id: resSim.c,v 1.00 2007/01/15 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "abc.h"
+#include "resInt.h"
+
+////////////////////////////////////////////////////////////////////////
+/// DECLARATIONS ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+/// FUNCTION DEFINITIONS ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+ Synopsis [Allocate simulation engine.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Res_Sim_t * Res_SimAlloc( int nWords )
+{
+ Res_Sim_t * p;
+ p = ALLOC( Res_Sim_t, 1 );
+ memset( p, 0, sizeof(Res_Sim_t) );
+ // simulation parameters
+ p->nWords = nWords;
+ p->nPats = p->nWords * 8 * sizeof(unsigned);
+ p->nWordsIn = p->nPats;
+ p->nBytesIn = p->nPats * sizeof(unsigned);
+ p->nPatsIn = p->nPats * 8 * sizeof(unsigned);
+ p->nWordsOut = p->nPats * p->nWords;
+ p->nPatsOut = p->nPats * p->nPats;
+ // simulation info
+ p->vPats = Vec_PtrAllocSimInfo( 1024, p->nWordsIn );
+ p->vPats0 = Vec_PtrAllocSimInfo( 128, p->nWords );
+ p->vPats1 = Vec_PtrAllocSimInfo( 128, p->nWords );
+ p->vOuts = Vec_PtrAllocSimInfo( 128, p->nWordsOut );
+ // resub candidates
+ p->vCands = Vec_VecStart( 16 );
+ return p;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Allocate simulation engine.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Res_SimAdjust( Res_Sim_t * p, Abc_Ntk_t * pAig, int nTruePis )
+{
+ srand( 0xABC );
+
+ assert( Abc_NtkIsStrash(pAig) );
+ p->pAig = pAig;
+ p->nTruePis = nTruePis;
+ if ( Vec_PtrSize(p->vPats) < Abc_NtkObjNumMax(pAig)+1 )
+ {
+ Vec_PtrFree( p->vPats );
+ p->vPats = Vec_PtrAllocSimInfo( Abc_NtkObjNumMax(pAig)+1, p->nWordsIn );
+ }
+ if ( Vec_PtrSize(p->vPats0) < nTruePis )
+ {
+ Vec_PtrFree( p->vPats0 );
+ p->vPats0 = Vec_PtrAllocSimInfo( nTruePis, p->nWords );
+ }
+ if ( Vec_PtrSize(p->vPats1) < nTruePis )
+ {
+ Vec_PtrFree( p->vPats1 );
+ p->vPats1 = Vec_PtrAllocSimInfo( nTruePis, p->nWords );
+ }
+ if ( Vec_PtrSize(p->vOuts) < Abc_NtkPoNum(pAig) )
+ {
+ Vec_PtrFree( p->vOuts );
+ p->vOuts = Vec_PtrAllocSimInfo( Abc_NtkPoNum(pAig), p->nWordsOut );
+ }
+ // clean storage info for patterns
+ Abc_InfoClear( Vec_PtrEntry(p->vPats0,0), p->nWords * nTruePis );
+ Abc_InfoClear( Vec_PtrEntry(p->vPats1,0), p->nWords * nTruePis );
+ p->nPats0 = 0;
+ p->nPats1 = 0;
+ p->fConst0 = 0;
+ p->fConst1 = 0;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Free simulation engine.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Res_SimFree( Res_Sim_t * p )
+{
+ Vec_PtrFree( p->vPats );
+ Vec_PtrFree( p->vPats0 );
+ Vec_PtrFree( p->vPats1 );
+ Vec_PtrFree( p->vOuts );
+ Vec_VecFree( p->vCands );
+ free( p );
+}
+
+
+/**Function*************************************************************
+
+ Synopsis [Sets random PI simulation info.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Abc_InfoRandomBytes( unsigned * p, int nWords )
+{
+ int i, Num;
+ for ( i = nWords - 1; i >= 0; i-- )
+ {
+ Num = rand();
+ p[i] = (Num & 1)? 0xff : 0;
+ p[i] = (p[i] << 8) | ((Num & 2)? 0xff : 0);
+ p[i] = (p[i] << 8) | ((Num & 4)? 0xff : 0);
+ p[i] = (p[i] << 8) | ((Num & 8)? 0xff : 0);
+ }
+// Extra_PrintBinary( stdout, p, 32 ); printf( "\n" );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Sets random PI simulation info.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Res_SimSetRandomBytes( Res_Sim_t * p )
+{
+ Abc_Obj_t * pObj;
+ unsigned * pInfo;
+ int i;
+ Abc_NtkForEachPi( p->pAig, pObj, i )
+ {
+ pInfo = Vec_PtrEntry( p->vPats, pObj->Id );
+ if ( i < p->nTruePis )
+ Abc_InfoRandomBytes( pInfo, p->nWordsIn );
+ else
+ Abc_InfoRandom( pInfo, p->nWordsIn );
+ }
+/*
+ // double-check that all are byte-patterns
+ Abc_NtkForEachPi( p->pAig, pObj, i )
+ {
+ if ( i == p->nTruePis )
+ break;
+ pInfoC = (unsigned char *)Vec_PtrEntry( p->vPats, pObj->Id );
+ for ( k = 0; k < p->nBytesIn; k++ )
+ assert( pInfoC[k] == 0 || pInfoC[k] == 0xff );
+ }
+*/
+}
+
+/**Function*************************************************************
+
+ Synopsis [Sets random PI simulation info.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Res_SimSetDerivedBytes( Res_Sim_t * p, int fUseWalk )
+{
+ Vec_Ptr_t * vPatsSource[2];
+ int nPatsSource[2];
+ Abc_Obj_t * pObj;
+ unsigned char * pInfo;
+ int i, k, z, s, nPats;
+
+ // set several random patterns
+ assert( p->nBytesIn % 32 == 0 );
+ nPats = p->nBytesIn/8;
+ Abc_NtkForEachPi( p->pAig, pObj, i )
+ {
+ if ( i == p->nTruePis )
+ break;
+ Abc_InfoRandomBytes( Vec_PtrEntry(p->vPats, pObj->Id), nPats/4 );
+ }
+
+ // set special patterns
+ if ( fUseWalk )
+ {
+ for ( z = 0; z < 2; z++ )
+ {
+ // set the zero pattern
+ Abc_NtkForEachPi( p->pAig, pObj, i )
+ {
+ if ( i == p->nTruePis )
+ break;
+ pInfo = (unsigned char *)Vec_PtrEntry( p->vPats, pObj->Id );
+ pInfo[nPats] = z ? 0xff : 0;
+ }
+ if ( ++nPats == p->nBytesIn )
+ return;
+ // set the walking zero pattern
+ for ( k = 0; k < p->nTruePis; k++ )
+ {
+ Abc_NtkForEachPi( p->pAig, pObj, i )
+ {
+ if ( i == p->nTruePis )
+ break;
+ pInfo = (unsigned char *)Vec_PtrEntry( p->vPats, pObj->Id );
+ pInfo[nPats] = ((i == k) ^ z) ? 0xff : 0;
+ }
+ if ( ++nPats == p->nBytesIn )
+ return;
+ }
+ }
+ }
+
+ // decide what patterns to set first
+ if ( p->nPats0 < p->nPats1 )
+ {
+ nPatsSource[0] = p->nPats0;
+ vPatsSource[0] = p->vPats0;
+ nPatsSource[1] = p->nPats1;
+ vPatsSource[1] = p->vPats1;
+ }
+ else
+ {
+ nPatsSource[0] = p->nPats1;
+ vPatsSource[0] = p->vPats1;
+ nPatsSource[1] = p->nPats0;
+ vPatsSource[1] = p->vPats0;
+ }
+ for ( z = 0; z < 2; z++ )
+ {
+ for ( s = nPatsSource[z] - 1; s >= 0; s-- )
+ {
+// if ( s == 0 )
+// printf( "Patterns:\n" );
+ // set the given source pattern
+ for ( k = 0; k < p->nTruePis; k++ )
+ {
+ Abc_NtkForEachPi( p->pAig, pObj, i )
+ {
+ if ( i == p->nTruePis )
+ break;
+ pInfo = (unsigned char *)Vec_PtrEntry( p->vPats, pObj->Id );
+ if ( (i == k) ^ Abc_InfoHasBit( Vec_PtrEntry(vPatsSource[z], i), s ) )
+ {
+ pInfo[nPats] = 0xff;
+// if ( s == 0 )
+// printf( "1" );
+ }
+ else
+ {
+ pInfo[nPats] = 0;
+// if ( s == 0 )
+// printf( "0" );
+ }
+ }
+// if ( s == 0 )
+// printf( "\n" );
+ if ( ++nPats == p->nBytesIn )
+ return;
+ }
+ }
+ }
+ // clean the rest
+ for ( z = nPats; z < p->nBytesIn; z++ )
+ {
+ Abc_NtkForEachPi( p->pAig, pObj, i )
+ {
+ if ( i == p->nTruePis )
+ break;
+ pInfo = (unsigned char *)Vec_PtrEntry( p->vPats, pObj->Id );
+ memset( pInfo + nPats, 0, p->nBytesIn - nPats );
+ }
+ }
+/*
+ // double-check that all are byte-patterns
+ Abc_NtkForEachPi( p->pAig, pObj, i )
+ {
+ if ( i == p->nTruePis )
+ break;
+ pInfo = (unsigned char *)Vec_PtrEntry( p->vPats, pObj->Id );
+ for ( k = 0; k < p->nBytesIn; k++ )
+ assert( pInfo[k] == 0 || pInfo[k] == 0xff );
+ }
+*/
+}
+
+/**Function*************************************************************
+
+ Synopsis [Sets given PI simulation info.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Res_SimSetGiven( Res_Sim_t * p, Vec_Ptr_t * vInfo )
+{
+ Abc_Obj_t * pObj;
+ unsigned * pInfo, * pInfo2;
+ int i, w;
+ Abc_NtkForEachPi( p->pAig, pObj, i )
+ {
+ if ( i == p->nTruePis )
+ break;
+ pInfo = Vec_PtrEntry( p->vPats, pObj->Id );
+ pInfo2 = Vec_PtrEntry( vInfo, i );
+ for ( w = 0; w < p->nWords; w++ )
+ pInfo[w] = pInfo2[w];
+ }
+}
+
+/**Function*************************************************************
+
+ Synopsis [Simulates one node.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Res_SimPerformOne( Abc_Obj_t * pNode, Vec_Ptr_t * vSimInfo, int nSimWords )
+{
+ unsigned * pInfo, * pInfo1, * pInfo2;
+ int k, fComp1, fComp2;
+ // simulate the internal nodes
+ assert( Abc_ObjIsNode(pNode) );
+ pInfo = Vec_PtrEntry(vSimInfo, pNode->Id);
+ pInfo1 = Vec_PtrEntry(vSimInfo, Abc_ObjFaninId0(pNode));
+ pInfo2 = Vec_PtrEntry(vSimInfo, Abc_ObjFaninId1(pNode));
+ fComp1 = Abc_ObjFaninC0(pNode);
+ fComp2 = Abc_ObjFaninC1(pNode);
+ if ( fComp1 && fComp2 )
+ for ( k = 0; k < nSimWords; k++ )
+ pInfo[k] = ~pInfo1[k] & ~pInfo2[k];
+ else if ( fComp1 && !fComp2 )
+ for ( k = 0; k < nSimWords; k++ )
+ pInfo[k] = ~pInfo1[k] & pInfo2[k];
+ else if ( !fComp1 && fComp2 )
+ for ( k = 0; k < nSimWords; k++ )
+ pInfo[k] = pInfo1[k] & ~pInfo2[k];
+ else // if ( fComp1 && fComp2 )
+ for ( k = 0; k < nSimWords; k++ )
+ pInfo[k] = pInfo1[k] & pInfo2[k];
+}
+
+/**Function*************************************************************
+
+ Synopsis [Simulates one CO node.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Res_SimTransferOne( Abc_Obj_t * pNode, Vec_Ptr_t * vSimInfo, int nSimWords )
+{
+ unsigned * pInfo, * pInfo1;
+ int k, fComp1;
+ // simulate the internal nodes
+ assert( Abc_ObjIsCo(pNode) );
+ pInfo = Vec_PtrEntry(vSimInfo, pNode->Id);
+ pInfo1 = Vec_PtrEntry(vSimInfo, Abc_ObjFaninId0(pNode));
+ fComp1 = Abc_ObjFaninC0(pNode);
+ if ( fComp1 )
+ for ( k = 0; k < nSimWords; k++ )
+ pInfo[k] = ~pInfo1[k];
+ else
+ for ( k = 0; k < nSimWords; k++ )
+ pInfo[k] = pInfo1[k];
+}
+
+/**Function*************************************************************
+
+ Synopsis [Performs one round of simulation.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Res_SimPerformRound( Res_Sim_t * p, int nWords )
+{
+ Abc_Obj_t * pObj;
+ int i;
+ Abc_InfoFill( Vec_PtrEntry(p->vPats,0), nWords );
+ Abc_AigForEachAnd( p->pAig, pObj, i )
+ Res_SimPerformOne( pObj, p->vPats, nWords );
+ Abc_NtkForEachPo( p->pAig, pObj, i )
+ Res_SimTransferOne( pObj, p->vPats, nWords );
+}
+
+
+/**Function*************************************************************
+
+ Synopsis [Pads the extra space with duplicated simulation info.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Res_SimPadSimInfo( Vec_Ptr_t * vPats, int nPats, int nWords )
+{
+ unsigned * pInfo;
+ int i, w, iWords;
+ assert( nPats > 0 && nPats < nWords * 8 * (int) sizeof(unsigned) );
+ // pad the first word
+ if ( nPats < 8 * sizeof(unsigned) )
+ {
+ Vec_PtrForEachEntry( vPats, pInfo, i )
+ if ( pInfo[0] & 1 )
+ pInfo[0] |= ((~0) << nPats);
+ nPats = 8 * sizeof(unsigned);
+ }
+ // pad the empty words
+ iWords = nPats / (8 * sizeof(unsigned));
+ Vec_PtrForEachEntry( vPats, pInfo, i )
+ {
+ for ( w = iWords; w < nWords; w++ )
+ pInfo[w] = pInfo[0];
+ }
+}
+
+/**Function*************************************************************
+
+ Synopsis [Duplicates the simulation info to fill the space.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Res_SimDeriveInfoReplicate( Res_Sim_t * p )
+{
+ unsigned * pInfo, * pInfo2;
+ Abc_Obj_t * pObj;
+ int i, j, w;
+ Abc_NtkForEachPo( p->pAig, pObj, i )
+ {
+ pInfo = Vec_PtrEntry( p->vPats, pObj->Id );
+ pInfo2 = Vec_PtrEntry( p->vOuts, i );
+ for ( j = 0; j < p->nPats; j++ )
+ for ( w = 0; w < p->nWords; w++ )
+ *pInfo2++ = pInfo[w];
+ }
+}
+
+/**Function*************************************************************
+
+ Synopsis [Complement the simulation info if necessary.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Res_SimDeriveInfoComplement( Res_Sim_t * p )
+{
+ unsigned * pInfo, * pInfo2;
+ Abc_Obj_t * pObj;
+ int i, j, w;
+ Abc_NtkForEachPo( p->pAig, pObj, i )
+ {
+ pInfo = Vec_PtrEntry( p->vPats, pObj->Id );
+ pInfo2 = Vec_PtrEntry( p->vOuts, i );
+ for ( j = 0; j < p->nPats; j++, pInfo2 += p->nWords )
+ if ( Abc_InfoHasBit( pInfo, j ) )
+ for ( w = 0; w < p->nWords; w++ )
+ pInfo2[w] = ~pInfo2[w];
+ }
+}
+
+/**Function*************************************************************
+
+ Synopsis [Prints output patterns.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Res_SimPrintOutPatterns( Res_Sim_t * p, Abc_Ntk_t * pAig )
+{
+ Abc_Obj_t * pObj;
+ unsigned * pInfo2;
+ int i;
+ Abc_NtkForEachPo( pAig, pObj, i )
+ {
+ pInfo2 = Vec_PtrEntry( p->vOuts, i );
+ Extra_PrintBinary( stdout, pInfo2, p->nPatsOut );
+ printf( "\n" );
+ }
+}
+
+/**Function*************************************************************
+
+ Synopsis [Prints output patterns.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Res_SimPrintNodePatterns( Res_Sim_t * p, Abc_Ntk_t * pAig )
+{
+ unsigned * pInfo;
+ pInfo = Vec_PtrEntry( p->vPats, Abc_NtkPo(p->pAig, 1)->Id );
+ Extra_PrintBinary( stdout, pInfo, p->nPats );
+ printf( "\n" );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Counts the number of patters of different type.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Res_SimCountResults( Res_Sim_t * p, int * pnDcs, int * pnOnes, int * pnZeros, int fVerbose )
+{
+ unsigned char * pInfoCare, * pInfoNode;
+ int i, nTotal = 0;
+ pInfoCare = (unsigned char *)Vec_PtrEntry( p->vPats, Abc_NtkPo(p->pAig, 0)->Id );
+ pInfoNode = (unsigned char *)Vec_PtrEntry( p->vPats, Abc_NtkPo(p->pAig, 1)->Id );
+ for ( i = 0; i < p->nBytesIn; i++ )
+ {
+ if ( !pInfoCare[i] )
+ (*pnDcs)++;
+ else if ( !pInfoNode[i] )
+ (*pnZeros)++;
+ else
+ (*pnOnes)++;
+ }
+ nTotal += *pnDcs;
+ nTotal += *pnZeros;
+ nTotal += *pnOnes;
+ if ( fVerbose )
+ {
+ printf( "Dc = %7.2f %% ", 100.0*(*pnDcs) /nTotal );
+ printf( "On = %7.2f %% ", 100.0*(*pnOnes) /nTotal );
+ printf( "Off = %7.2f %% ", 100.0*(*pnZeros)/nTotal );
+ }
+}
+
+/**Function*************************************************************
+
+ Synopsis [Counts the number of patters of different type.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Res_SimCollectPatterns( Res_Sim_t * p, int fVerbose )
+{
+ Abc_Obj_t * pObj;
+ unsigned char * pInfoCare, * pInfoNode, * pInfo;
+ int i, j;
+ pInfoCare = (unsigned char *)Vec_PtrEntry( p->vPats, Abc_NtkPo(p->pAig, 0)->Id );
+ pInfoNode = (unsigned char *)Vec_PtrEntry( p->vPats, Abc_NtkPo(p->pAig, 1)->Id );
+ for ( i = 0; i < p->nBytesIn; i++ )
+ {
+ // skip don't-care patterns
+ if ( !pInfoCare[i] )
+ continue;
+ // separate offset and onset patterns
+ assert( pInfoNode[i] == 0 || pInfoNode[i] == 0xff );
+ if ( !pInfoNode[i] )
+ {
+ if ( p->nPats0 >= p->nPats )
+ continue;
+ Abc_NtkForEachPi( p->pAig, pObj, j )
+ {
+ if ( j == p->nTruePis )
+ break;
+ pInfo = (unsigned char *)Vec_PtrEntry( p->vPats, pObj->Id );
+ assert( pInfo[i] == 0 || pInfo[i] == 0xff );
+ if ( pInfo[i] )
+ Abc_InfoSetBit( Vec_PtrEntry(p->vPats0, j), p->nPats0 );
+ }
+ p->nPats0++;
+ }
+ else
+ {
+ if ( p->nPats1 >= p->nPats )
+ continue;
+ Abc_NtkForEachPi( p->pAig, pObj, j )
+ {
+ if ( j == p->nTruePis )
+ break;
+ pInfo = (unsigned char *)Vec_PtrEntry( p->vPats, pObj->Id );
+ assert( pInfo[i] == 0 || pInfo[i] == 0xff );
+ if ( pInfo[i] )
+ Abc_InfoSetBit( Vec_PtrEntry(p->vPats1, j), p->nPats1 );
+ }
+ p->nPats1++;
+ }
+ if ( p->nPats0 >= p->nPats && p->nPats1 >= p->nPats )
+ break;
+ }
+ if ( fVerbose )
+ {
+ printf( "| " );
+ printf( "On = %3d ", p->nPats1 );
+ printf( "Off = %3d ", p->nPats0 );
+ printf( "\n" );
+ }
+}
+
+/**Function*************************************************************
+
+ Synopsis [Verifies the last pattern.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Res_SimVerifyValue( Res_Sim_t * p, int fOnSet )
+{
+ Abc_Obj_t * pObj;
+ unsigned * pInfo, * pInfo2;
+ int i, value;
+ Abc_NtkForEachPi( p->pAig, pObj, i )
+ {
+ if ( i == p->nTruePis )
+ break;
+ if ( fOnSet )
+ {
+ pInfo2 = Vec_PtrEntry( p->vPats1, i );
+ value = Abc_InfoHasBit( pInfo2, p->nPats1 - 1 );
+ }
+ else
+ {
+ pInfo2 = Vec_PtrEntry( p->vPats0, i );
+ value = Abc_InfoHasBit( pInfo2, p->nPats0 - 1 );
+ }
+ pInfo = Vec_PtrEntry( p->vPats, pObj->Id );
+ pInfo[0] = value ? ~0 : 0;
+ }
+ Res_SimPerformRound( p, 1 );
+ pObj = Abc_NtkPo( p->pAig, 1 );
+ pInfo = Vec_PtrEntry( p->vPats, pObj->Id );
+ assert( pInfo[0] == 0 || pInfo[0] == ~0 );
+ return pInfo[0] > 0;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Prepares simulation info for candidate filtering.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Res_SimPrepare( Res_Sim_t * p, Abc_Ntk_t * pAig, int nTruePis, int fVerbose )
+{
+ int i, nOnes = 0, nZeros = 0, nDcs = 0;
+ if ( fVerbose )
+ printf( "\n" );
+ // prepare the manager
+ Res_SimAdjust( p, pAig, nTruePis );
+ // estimate the number of patterns
+ Res_SimSetRandomBytes( p );
+ Res_SimPerformRound( p, p->nWordsIn );
+ Res_SimCountResults( p, &nDcs, &nOnes, &nZeros, fVerbose );
+ // collect the patterns
+ Res_SimCollectPatterns( p, fVerbose );
+ // add more patterns using constraint simulation
+ if ( p->nPats0 < 8 )
+ {
+ if ( !Res_SatSimulate( p, 16, 0 ) )
+ return p->fConst0 || p->fConst1;
+// return 0;
+// printf( "Value0 = %d\n", Res_SimVerifyValue( p, 0 ) );
+ }
+ if ( p->nPats1 < 8 )
+ {
+ if ( !Res_SatSimulate( p, 16, 1 ) )
+ return p->fConst0 || p->fConst1;
+// return 0;
+// printf( "Value1 = %d\n", Res_SimVerifyValue( p, 1 ) );
+ }
+ // generate additional patterns
+ for ( i = 0; i < 2; i++ )
+ {
+ if ( p->nPats0 > p->nPats*7/8 && p->nPats1 > p->nPats*7/8 )
+ break;
+ Res_SimSetDerivedBytes( p, i==0 );
+ Res_SimPerformRound( p, p->nWordsIn );
+ Res_SimCountResults( p, &nDcs, &nOnes, &nZeros, fVerbose );
+ Res_SimCollectPatterns( p, fVerbose );
+ }
+ // create bit-matrix info
+ if ( p->nPats0 < p->nPats )
+ Res_SimPadSimInfo( p->vPats0, p->nPats0, p->nWords );
+ if ( p->nPats1 < p->nPats )
+ Res_SimPadSimInfo( p->vPats1, p->nPats1, p->nWords );
+ // resimulate 0-patterns
+ Res_SimSetGiven( p, p->vPats0 );
+ Res_SimPerformRound( p, p->nWords );
+//Res_SimPrintNodePatterns( p, pAig );
+ Res_SimDeriveInfoReplicate( p );
+ // resimulate 1-patterns
+ Res_SimSetGiven( p, p->vPats1 );
+ Res_SimPerformRound( p, p->nWords );
+//Res_SimPrintNodePatterns( p, pAig );
+ Res_SimDeriveInfoComplement( p );
+ // print output patterns
+// Res_SimPrintOutPatterns( p, pAig );
+ return 1;
+}
+
+////////////////////////////////////////////////////////////////////////
+/// END OF FILE ///
+////////////////////////////////////////////////////////////////////////
+
+
diff --git a/src/opt/res/resSim_old.c b/src/opt/res/resSim_old.c
new file mode 100644
index 00000000..23ce29e4
--- /dev/null
+++ b/src/opt/res/resSim_old.c
@@ -0,0 +1,521 @@
+/**CFile****************************************************************
+
+ FileName [resSim.c]
+
+ SystemName [ABC: Logic synthesis and verification system.]
+
+ PackageName [Resynthesis package.]
+
+ Synopsis [Simulation engine.]
+
+ Author [Alan Mishchenko]
+
+ Affiliation [UC Berkeley]
+
+ Date [Ver. 1.0. Started - January 15, 2007.]
+
+ Revision [$Id: resSim.c,v 1.00 2007/01/15 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "abc.h"
+#include "resInt.h"
+
+////////////////////////////////////////////////////////////////////////
+/// DECLARATIONS ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+/// FUNCTION DEFINITIONS ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+ Synopsis [Allocate simulation engine.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Res_Sim_t * Res_SimAlloc( int nWords )
+{
+ Res_Sim_t * p;
+ p = ALLOC( Res_Sim_t, 1 );
+ memset( p, 0, sizeof(Res_Sim_t) );
+ // simulation parameters
+ p->nWords = nWords;
+ p->nPats = 8 * sizeof(unsigned) * p->nWords;
+ p->nWordsOut = p->nPats * p->nWords;
+ p->nPatsOut = p->nPats * p->nPats;
+ // simulation info
+ p->vPats = Vec_PtrAllocSimInfo( 1024, p->nWords );
+ p->vPats0 = Vec_PtrAllocSimInfo( 128, p->nWords );
+ p->vPats1 = Vec_PtrAllocSimInfo( 128, p->nWords );
+ p->vOuts = Vec_PtrAllocSimInfo( 128, p->nWordsOut );
+ // resub candidates
+ p->vCands = Vec_VecStart( 16 );
+ return p;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Allocate simulation engine.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Res_SimAdjust( Res_Sim_t * p, Abc_Ntk_t * pAig )
+{
+ srand( 0xABC );
+
+ assert( Abc_NtkIsStrash(pAig) );
+ p->pAig = pAig;
+ if ( Vec_PtrSize(p->vPats) < Abc_NtkObjNumMax(pAig)+1 )
+ {
+ Vec_PtrFree( p->vPats );
+ p->vPats = Vec_PtrAllocSimInfo( Abc_NtkObjNumMax(pAig)+1, p->nWords );
+ }
+ if ( Vec_PtrSize(p->vPats0) < Abc_NtkPiNum(pAig) )
+ {
+ Vec_PtrFree( p->vPats0 );
+ p->vPats0 = Vec_PtrAllocSimInfo( Abc_NtkPiNum(pAig), p->nWords );
+ }
+ if ( Vec_PtrSize(p->vPats1) < Abc_NtkPiNum(pAig) )
+ {
+ Vec_PtrFree( p->vPats1 );
+ p->vPats1 = Vec_PtrAllocSimInfo( Abc_NtkPiNum(pAig), p->nWords );
+ }
+ if ( Vec_PtrSize(p->vOuts) < Abc_NtkPoNum(pAig) )
+ {
+ Vec_PtrFree( p->vOuts );
+ p->vOuts = Vec_PtrAllocSimInfo( Abc_NtkPoNum(pAig), p->nWordsOut );
+ }
+ // clean storage info for patterns
+ Abc_InfoClear( Vec_PtrEntry(p->vPats0,0), p->nWords * Abc_NtkPiNum(pAig) );
+ Abc_InfoClear( Vec_PtrEntry(p->vPats1,0), p->nWords * Abc_NtkPiNum(pAig) );
+ p->nPats0 = 0;
+ p->nPats1 = 0;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Free simulation engine.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Res_SimFree( Res_Sim_t * p )
+{
+ Vec_PtrFree( p->vPats );
+ Vec_PtrFree( p->vPats0 );
+ Vec_PtrFree( p->vPats1 );
+ Vec_PtrFree( p->vOuts );
+ Vec_VecFree( p->vCands );
+ free( p );
+}
+
+
+/**Function*************************************************************
+
+ Synopsis [Sets random PI simulation info.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Res_SimSetRandom( Res_Sim_t * p )
+{
+ Abc_Obj_t * pObj;
+ unsigned * pInfo;
+ int i;
+ Abc_NtkForEachPi( p->pAig, pObj, i )
+ {
+ pInfo = Vec_PtrEntry( p->vPats, pObj->Id );
+ Abc_InfoRandom( pInfo, p->nWords );
+ }
+}
+
+/**Function*************************************************************
+
+ Synopsis [Sets given PI simulation info.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Res_SimSetGiven( Res_Sim_t * p, Vec_Ptr_t * vInfo )
+{
+ Abc_Obj_t * pObj;
+ unsigned * pInfo, * pInfo2;
+ int i, w;
+ Abc_NtkForEachPi( p->pAig, pObj, i )
+ {
+ pInfo = Vec_PtrEntry( p->vPats, pObj->Id );
+ pInfo2 = Vec_PtrEntry( vInfo, i );
+ for ( w = 0; w < p->nWords; w++ )
+ pInfo[w] = pInfo2[w];
+ }
+}
+
+/**Function*************************************************************
+
+ Synopsis [Simulates one node.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Res_SimPerformOne( Abc_Obj_t * pNode, Vec_Ptr_t * vSimInfo, int nSimWords )
+{
+ unsigned * pInfo, * pInfo1, * pInfo2;
+ int k, fComp1, fComp2;
+ // simulate the internal nodes
+ assert( Abc_ObjIsNode(pNode) );
+ pInfo = Vec_PtrEntry(vSimInfo, pNode->Id);
+ pInfo1 = Vec_PtrEntry(vSimInfo, Abc_ObjFaninId0(pNode));
+ pInfo2 = Vec_PtrEntry(vSimInfo, Abc_ObjFaninId1(pNode));
+ fComp1 = Abc_ObjFaninC0(pNode);
+ fComp2 = Abc_ObjFaninC1(pNode);
+ if ( fComp1 && fComp2 )
+ for ( k = 0; k < nSimWords; k++ )
+ pInfo[k] = ~pInfo1[k] & ~pInfo2[k];
+ else if ( fComp1 && !fComp2 )
+ for ( k = 0; k < nSimWords; k++ )
+ pInfo[k] = ~pInfo1[k] & pInfo2[k];
+ else if ( !fComp1 && fComp2 )
+ for ( k = 0; k < nSimWords; k++ )
+ pInfo[k] = pInfo1[k] & ~pInfo2[k];
+ else // if ( fComp1 && fComp2 )
+ for ( k = 0; k < nSimWords; k++ )
+ pInfo[k] = pInfo1[k] & pInfo2[k];
+}
+
+/**Function*************************************************************
+
+ Synopsis [Simulates one CO node.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Res_SimTransferOne( Abc_Obj_t * pNode, Vec_Ptr_t * vSimInfo, int nSimWords )
+{
+ unsigned * pInfo, * pInfo1;
+ int k, fComp1;
+ // simulate the internal nodes
+ assert( Abc_ObjIsCo(pNode) );
+ pInfo = Vec_PtrEntry(vSimInfo, pNode->Id);
+ pInfo1 = Vec_PtrEntry(vSimInfo, Abc_ObjFaninId0(pNode));
+ fComp1 = Abc_ObjFaninC0(pNode);
+ if ( fComp1 )
+ for ( k = 0; k < nSimWords; k++ )
+ pInfo[k] = ~pInfo1[k];
+ else
+ for ( k = 0; k < nSimWords; k++ )
+ pInfo[k] = pInfo1[k];
+}
+
+/**Function*************************************************************
+
+ Synopsis [Performs one round of simulation.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Res_SimPerformRound( Res_Sim_t * p )
+{
+ Abc_Obj_t * pObj;
+ int i;
+ Abc_InfoFill( Vec_PtrEntry(p->vPats,0), p->nWords );
+ Abc_AigForEachAnd( p->pAig, pObj, i )
+ Res_SimPerformOne( pObj, p->vPats, p->nWords );
+ Abc_NtkForEachPo( p->pAig, pObj, i )
+ Res_SimTransferOne( pObj, p->vPats, p->nWords );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Processes simulation patterns.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Res_SimProcessPats( Res_Sim_t * p )
+{
+ Abc_Obj_t * pObj;
+ unsigned * pInfoCare, * pInfoNode;
+ int i, j, nDcs = 0;
+ pInfoCare = Vec_PtrEntry( p->vPats, Abc_NtkPo(p->pAig, 0)->Id );
+ pInfoNode = Vec_PtrEntry( p->vPats, Abc_NtkPo(p->pAig, 1)->Id );
+ for ( i = 0; i < p->nPats; i++ )
+ {
+ // skip don't-care patterns
+ if ( !Abc_InfoHasBit(pInfoCare, i) )
+ {
+ nDcs++;
+ continue;
+ }
+ // separate offset and onset patterns
+ if ( !Abc_InfoHasBit(pInfoNode, i) )
+ {
+ if ( p->nPats0 >= p->nPats )
+ continue;
+ Abc_NtkForEachPi( p->pAig, pObj, j )
+ if ( Abc_InfoHasBit( Vec_PtrEntry(p->vPats, pObj->Id), i ) )
+ Abc_InfoSetBit( Vec_PtrEntry(p->vPats0, j), p->nPats0 );
+ p->nPats0++;
+ }
+ else
+ {
+ if ( p->nPats1 >= p->nPats )
+ continue;
+ Abc_NtkForEachPi( p->pAig, pObj, j )
+ if ( Abc_InfoHasBit( Vec_PtrEntry(p->vPats, pObj->Id), i ) )
+ Abc_InfoSetBit( Vec_PtrEntry(p->vPats1, j), p->nPats1 );
+ p->nPats1++;
+ }
+ }
+}
+
+/**Function*************************************************************
+
+ Synopsis [Pads the extra space with duplicated simulation info.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Res_SimPadSimInfo( Vec_Ptr_t * vPats, int nPats, int nWords )
+{
+ unsigned * pInfo;
+ int i, w, iWords;
+ assert( nPats > 0 && nPats < nWords * 8 * (int) sizeof(unsigned) );
+ // pad the first word
+ if ( nPats < 8 * sizeof(unsigned) )
+ {
+ Vec_PtrForEachEntry( vPats, pInfo, i )
+ if ( pInfo[0] & 1 )
+ pInfo[0] |= ((~0) << nPats);
+ nPats = 8 * sizeof(unsigned);
+ }
+ // pad the empty words
+ iWords = nPats / (8 * sizeof(unsigned));
+ Vec_PtrForEachEntry( vPats, pInfo, i )
+ {
+ for ( w = iWords; w < nWords; w++ )
+ pInfo[w] = pInfo[0];
+ }
+}
+
+/**Function*************************************************************
+
+ Synopsis [Duplicates the simulation info to fill the space.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Res_SimDeriveInfoReplicate( Res_Sim_t * p )
+{
+ unsigned * pInfo, * pInfo2;
+ Abc_Obj_t * pObj;
+ int i, j, w;
+ Abc_NtkForEachPo( p->pAig, pObj, i )
+ {
+ pInfo = Vec_PtrEntry( p->vPats, pObj->Id );
+ pInfo2 = Vec_PtrEntry( p->vOuts, i );
+ for ( j = 0; j < p->nPats; j++ )
+ for ( w = 0; w < p->nWords; w++ )
+ *pInfo2++ = pInfo[w];
+ }
+}
+
+/**Function*************************************************************
+
+ Synopsis [Complement the simulation info if necessary.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Res_SimDeriveInfoComplement( Res_Sim_t * p )
+{
+ unsigned * pInfo, * pInfo2;
+ Abc_Obj_t * pObj;
+ int i, j, w;
+ Abc_NtkForEachPo( p->pAig, pObj, i )
+ {
+ pInfo = Vec_PtrEntry( p->vPats, pObj->Id );
+ pInfo2 = Vec_PtrEntry( p->vOuts, i );
+ for ( j = 0; j < p->nPats; j++, pInfo2 += p->nWords )
+ if ( Abc_InfoHasBit( pInfo, j ) )
+ for ( w = 0; w < p->nWords; w++ )
+ pInfo2[w] = ~pInfo2[w];
+ }
+}
+
+/**Function*************************************************************
+
+ Synopsis [Free simulation engine.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Res_SimReportOne( Res_Sim_t * p )
+{
+ unsigned * pInfoCare, * pInfoNode;
+ int i, nDcs, nOnes, nZeros;
+ pInfoCare = Vec_PtrEntry( p->vPats, Abc_NtkPo(p->pAig, 0)->Id );
+ pInfoNode = Vec_PtrEntry( p->vPats, Abc_NtkPo(p->pAig, 1)->Id );
+ nDcs = nOnes = nZeros = 0;
+ for ( i = 0; i < p->nPats; i++ )
+ {
+ // skip don't-care patterns
+ if ( !Abc_InfoHasBit(pInfoCare, i) )
+ {
+ nDcs++;
+ continue;
+ }
+ // separate offset and onset patterns
+ if ( !Abc_InfoHasBit(pInfoNode, i) )
+ nZeros++;
+ else
+ nOnes++;
+ }
+ printf( "On = %3d (%7.2f %%) ", nOnes, 100.0*nOnes/p->nPats );
+ printf( "Off = %3d (%7.2f %%) ", nZeros, 100.0*nZeros/p->nPats );
+ printf( "Dc = %3d (%7.2f %%) ", nDcs, 100.0*nDcs/p->nPats );
+ printf( "P0 = %3d ", p->nPats0 );
+ printf( "P1 = %3d ", p->nPats1 );
+ if ( p->nPats0 < 4 || p->nPats1 < 4 )
+ printf( "*" );
+ printf( "\n" );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Prints output patterns.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Res_SimPrintOutPatterns( Res_Sim_t * p, Abc_Ntk_t * pAig )
+{
+ Abc_Obj_t * pObj;
+ unsigned * pInfo2;
+ int i;
+ Abc_NtkForEachPo( pAig, pObj, i )
+ {
+ pInfo2 = Vec_PtrEntry( p->vOuts, i );
+ Extra_PrintBinary( stdout, pInfo2, p->nPatsOut );
+ printf( "\n" );
+ }
+}
+
+/**Function*************************************************************
+
+ Synopsis [Prepares simulation info for candidate filtering.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Res_SimPrepare( Res_Sim_t * p, Abc_Ntk_t * pAig, int nTruePis, int fVerbose )
+{
+ int Limit;
+ // prepare the manager
+ Res_SimAdjust( p, pAig );
+ // collect 0/1 simulation info
+ for ( Limit = 0; Limit < 10; Limit++ )
+ {
+ Res_SimSetRandom( p );
+ Res_SimPerformRound( p );
+ Res_SimProcessPats( p );
+ if ( !(p->nPats0 < p->nPats || p->nPats1 < p->nPats) )
+ break;
+ }
+// printf( "%d ", Limit );
+ // report the last set of patterns
+// Res_SimReportOne( p );
+// printf( "\n" );
+ // quit if there is not enough
+// if ( p->nPats0 < 4 || p->nPats1 < 4 )
+ if ( p->nPats0 < 4 || p->nPats1 < 4 )
+ {
+// Res_SimReportOne( p );
+ return 0;
+ }
+ // create bit-matrix info
+ if ( p->nPats0 < p->nPats )
+ Res_SimPadSimInfo( p->vPats0, p->nPats0, p->nWords );
+ if ( p->nPats1 < p->nPats )
+ Res_SimPadSimInfo( p->vPats1, p->nPats1, p->nWords );
+ // resimulate 0-patterns
+ Res_SimSetGiven( p, p->vPats0 );
+ Res_SimPerformRound( p );
+ Res_SimDeriveInfoReplicate( p );
+ // resimulate 1-patterns
+ Res_SimSetGiven( p, p->vPats1 );
+ Res_SimPerformRound( p );
+ Res_SimDeriveInfoComplement( p );
+ // print output patterns
+// Res_SimPrintOutPatterns( p, pAig );
+ return 1;
+}
+
+////////////////////////////////////////////////////////////////////////
+/// END OF FILE ///
+////////////////////////////////////////////////////////////////////////
+
+
diff --git a/src/opt/res/resStrash.c b/src/opt/res/resStrash.c
new file mode 100644
index 00000000..fde842a4
--- /dev/null
+++ b/src/opt/res/resStrash.c
@@ -0,0 +1,117 @@
+/**CFile****************************************************************
+
+ FileName [resStrash.c]
+
+ SystemName [ABC: Logic synthesis and verification system.]
+
+ PackageName [Resynthesis package.]
+
+ Synopsis [Structural hashing of the nodes in the window.]
+
+ Author [Alan Mishchenko]
+
+ Affiliation [UC Berkeley]
+
+ Date [Ver. 1.0. Started - January 15, 2007.]
+
+ Revision [$Id: resStrash.c,v 1.00 2007/01/15 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "abc.h"
+#include "resInt.h"
+
+////////////////////////////////////////////////////////////////////////
+/// DECLARATIONS ///
+////////////////////////////////////////////////////////////////////////
+
+extern Abc_Obj_t * Abc_ConvertAigToAig( Abc_Ntk_t * pAig, Abc_Obj_t * pObjOld );
+
+////////////////////////////////////////////////////////////////////////
+/// FUNCTION DEFINITIONS ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+ Synopsis [Structurally hashes the given window.]
+
+ Description [The first PO is the observability condition. The second
+ is the node's function. The remaining POs are the candidate divisors.]
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Abc_Ntk_t * Res_WndStrash( Res_Win_t * p )
+{
+ Vec_Ptr_t * vPairs;
+ Abc_Ntk_t * pAig;
+ Abc_Obj_t * pObj, * pMiter;
+ int i;
+ assert( Abc_NtkHasAig(p->pNode->pNtk) );
+// Abc_NtkCleanCopy( p->pNode->pNtk );
+ // create the network
+ pAig = Abc_NtkAlloc( ABC_NTK_STRASH, ABC_FUNC_AIG, 1 );
+ pAig->pName = Extra_UtilStrsav( "window" );
+ // create the inputs
+ Vec_PtrForEachEntry( p->vLeaves, pObj, i )
+ pObj->pCopy = Abc_NtkCreatePi( pAig );
+ Vec_PtrForEachEntry( p->vBranches, pObj, i )
+ pObj->pCopy = Abc_NtkCreatePi( pAig );
+ // go through the nodes in the topological order
+ Vec_PtrForEachEntry( p->vNodes, pObj, i )
+ {
+ pObj->pCopy = Abc_ConvertAigToAig( pAig, pObj );
+ if ( pObj == p->pNode )
+ pObj->pCopy = Abc_ObjNot( pObj->pCopy );
+ }
+ // collect the POs
+ vPairs = Vec_PtrAlloc( 2 * Vec_PtrSize(p->vRoots) );
+ Vec_PtrForEachEntry( p->vRoots, pObj, i )
+ {
+ Vec_PtrPush( vPairs, pObj->pCopy );
+ Vec_PtrPush( vPairs, NULL );
+ }
+ // mark the TFO of the node
+ Abc_NtkIncrementTravId( p->pNode->pNtk );
+ Res_WinSweepLeafTfo_rec( p->pNode, (int)p->pNode->Level + p->nWinTfoMax );
+ // update strashing of the node
+ p->pNode->pCopy = Abc_ObjNot( p->pNode->pCopy );
+ Abc_NodeSetTravIdPrevious( p->pNode );
+ // redo strashing in the TFO
+ Vec_PtrForEachEntry( p->vNodes, pObj, i )
+ {
+ if ( Abc_NodeIsTravIdCurrent(pObj) )
+ pObj->pCopy = Abc_ConvertAigToAig( pAig, pObj );
+ }
+ // collect the POs
+ Vec_PtrForEachEntry( p->vRoots, pObj, i )
+ Vec_PtrWriteEntry( vPairs, 2 * i + 1, pObj->pCopy );
+ // add the miter
+ pMiter = Abc_AigMiter( pAig->pManFunc, vPairs );
+ Abc_ObjAddFanin( Abc_NtkCreatePo(pAig), pMiter );
+ Vec_PtrFree( vPairs );
+ // add the node
+ Abc_ObjAddFanin( Abc_NtkCreatePo(pAig), p->pNode->pCopy );
+ // add the fanins
+ Abc_ObjForEachFanin( p->pNode, pObj, i )
+ Abc_ObjAddFanin( Abc_NtkCreatePo(pAig), pObj->pCopy );
+ // add the divisors
+ Vec_PtrForEachEntry( p->vDivs, pObj, i )
+ Abc_ObjAddFanin( Abc_NtkCreatePo(pAig), pObj->pCopy );
+ // add the names
+ Abc_NtkAddDummyPiNames( pAig );
+ Abc_NtkAddDummyPoNames( pAig );
+ // check the resulting network
+ if ( !Abc_NtkCheck( pAig ) )
+ fprintf( stdout, "Res_WndStrash(): Network check has failed.\n" );
+ return pAig;
+}
+
+
+////////////////////////////////////////////////////////////////////////
+/// END OF FILE ///
+////////////////////////////////////////////////////////////////////////
+
+
diff --git a/src/opt/res/resWin.c b/src/opt/res/resWin.c
new file mode 100644
index 00000000..a3648925
--- /dev/null
+++ b/src/opt/res/resWin.c
@@ -0,0 +1,485 @@
+/**CFile****************************************************************
+
+ FileName [resWin.c]
+
+ SystemName [ABC: Logic synthesis and verification system.]
+
+ PackageName [Resynthesis package.]
+
+ Synopsis [Windowing algorithm.]
+
+ Author [Alan Mishchenko]
+
+ Affiliation [UC Berkeley]
+
+ Date [Ver. 1.0. Started - January 15, 2007.]
+
+ Revision [$Id: resWin.c,v 1.00 2007/01/15 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "abc.h"
+#include "resInt.h"
+
+////////////////////////////////////////////////////////////////////////
+/// DECLARATIONS ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+/// FUNCTION DEFINITIONS ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+ Synopsis [Allocates the window.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Res_Win_t * Res_WinAlloc()
+{
+ Res_Win_t * p;
+ // start the manager
+ p = ALLOC( Res_Win_t, 1 );
+ memset( p, 0, sizeof(Res_Win_t) );
+ // set internal parameters
+ p->nFanoutLimit = 10;
+ p->nLevTfiMinus = 3;
+ // allocate storage
+ p->vRoots = Vec_PtrAlloc( 256 );
+ p->vLeaves = Vec_PtrAlloc( 256 );
+ p->vBranches = Vec_PtrAlloc( 256 );
+ p->vNodes = Vec_PtrAlloc( 256 );
+ p->vDivs = Vec_PtrAlloc( 256 );
+ p->vMatrix = Vec_VecStart( 128 );
+ return p;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Frees the window.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Res_WinFree( Res_Win_t * p )
+{
+ Vec_PtrFree( p->vRoots );
+ Vec_PtrFree( p->vLeaves );
+ Vec_PtrFree( p->vBranches );
+ Vec_PtrFree( p->vNodes );
+ Vec_PtrFree( p->vDivs );
+ Vec_VecFree( p->vMatrix );
+ free( p );
+}
+
+
+
+/**Function*************************************************************
+
+ Synopsis [Collect the limited TFI cone of the node.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Res_WinCollectLeavesAndNodes( Res_Win_t * p )
+{
+ Vec_Ptr_t * vFront;
+ Abc_Obj_t * pObj, * pTemp;
+ int i, k, m;
+
+ assert( p->nWinTfiMax > 0 );
+ assert( Vec_VecSize(p->vMatrix) > p->nWinTfiMax );
+
+ // start matrix with the node
+ Vec_VecClear( p->vMatrix );
+ Vec_VecPush( p->vMatrix, 0, p->pNode );
+ Abc_NtkIncrementTravId( p->pNode->pNtk );
+ Abc_NodeSetTravIdCurrent( p->pNode );
+
+ // collect the leaves (nodes pTemp such that "p->pNode->Level - pTemp->Level > p->nWinTfiMax")
+ Vec_PtrClear( p->vLeaves );
+ Vec_VecForEachLevelStartStop( p->vMatrix, vFront, i, 0, p->nWinTfiMax )
+ {
+ Vec_PtrForEachEntry( vFront, pObj, k )
+ {
+ Abc_ObjForEachFanin( pObj, pTemp, m )
+ {
+ if ( Abc_NodeIsTravIdCurrent( pTemp ) )
+ continue;
+ Abc_NodeSetTravIdCurrent( pTemp );
+ if ( Abc_ObjIsCi(pTemp) || (int)(p->pNode->Level - pTemp->Level) > p->nWinTfiMax )
+ Vec_PtrPush( p->vLeaves, pTemp );
+ else
+ Vec_VecPush( p->vMatrix, p->pNode->Level - pTemp->Level, pTemp );
+ }
+ }
+ }
+ if ( Vec_PtrSize(p->vLeaves) == 0 )
+ return 0;
+
+ // collect the nodes in the reverse order
+ Vec_PtrClear( p->vNodes );
+ Vec_VecForEachLevelReverseStartStop( p->vMatrix, vFront, i, p->nWinTfiMax, 0 )
+ {
+ Vec_PtrForEachEntry( vFront, pObj, k )
+ Vec_PtrPush( p->vNodes, pObj );
+ Vec_PtrClear( vFront );
+ }
+
+ // get the lowest leaf level
+ p->nLevLeafMin = ABC_INFINITY;
+ Vec_PtrForEachEntry( p->vLeaves, pObj, k )
+ p->nLevLeafMin = ABC_MIN( p->nLevLeafMin, (int)pObj->Level );
+
+ // set minimum traversal level
+ p->nLevTravMin = ABC_MAX( ((int)p->pNode->Level) - p->nWinTfiMax - p->nLevTfiMinus, p->nLevLeafMin );
+ assert( p->nLevTravMin >= 0 );
+ return 1;
+}
+
+
+
+/**Function*************************************************************
+
+ Synopsis [Returns 1 if the node should be a root.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+static inline int Res_WinComputeRootsCheck( Abc_Obj_t * pNode, int nLevelMax, int nFanoutLimit )
+{
+ Abc_Obj_t * pFanout;
+ int i;
+ // the node is the root if one of the following is true:
+ // (1) the node has more than fanouts than the limit
+ if ( Abc_ObjFanoutNum(pNode) > nFanoutLimit )
+ return 1;
+ // (2) the node has CO fanouts
+ // (3) the node has fanouts above the cutoff level
+ Abc_ObjForEachFanout( pNode, pFanout, i )
+ if ( Abc_ObjIsCo(pFanout) || (int)pFanout->Level > nLevelMax )
+ return 1;
+ return 0;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Recursively collects the root candidates.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Res_WinComputeRoots_rec( Abc_Obj_t * pNode, int nLevelMax, int nFanoutLimit, Vec_Ptr_t * vRoots )
+{
+ Abc_Obj_t * pFanout;
+ int i;
+ assert( Abc_ObjIsNode(pNode) );
+ if ( Abc_NodeIsTravIdCurrent(pNode) )
+ return;
+ Abc_NodeSetTravIdCurrent( pNode );
+ // check if the node should be the root
+ if ( Res_WinComputeRootsCheck( pNode, nLevelMax, nFanoutLimit ) )
+ Vec_PtrPush( vRoots, pNode );
+ else // if not, explore its fanouts
+ Abc_ObjForEachFanout( pNode, pFanout, i )
+ Res_WinComputeRoots_rec( pFanout, nLevelMax, nFanoutLimit, vRoots );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Recursively collects the root candidates.]
+
+ Description [Returns 1 if the only root is this node.]
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Res_WinComputeRoots( Res_Win_t * p )
+{
+ Vec_PtrClear( p->vRoots );
+ Abc_NtkIncrementTravId( p->pNode->pNtk );
+ Res_WinComputeRoots_rec( p->pNode, p->pNode->Level + p->nWinTfoMax, p->nFanoutLimit, p->vRoots );
+ assert( Vec_PtrSize(p->vRoots) > 0 );
+ if ( Vec_PtrSize(p->vRoots) == 1 && Vec_PtrEntry(p->vRoots, 0) == p->pNode )
+ return 0;
+ return 1;
+}
+
+
+
+/**Function*************************************************************
+
+ Synopsis [Marks the paths from the roots to the leaves.]
+
+ Description [Returns 1 if the the node can reach a leaf.]
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Res_WinMarkPaths_rec( Abc_Obj_t * pNode, Abc_Obj_t * pPivot, int nLevelMin )
+{
+ Abc_Obj_t * pFanin;
+ int i, RetValue;
+ // skip visited nodes
+ if ( Abc_NodeIsTravIdCurrent(pNode) )
+ return 1;
+ if ( Abc_NodeIsTravIdPrevious(pNode) )
+ return 0;
+ // assume that the node does not have access to the leaves
+ Abc_NodeSetTravIdPrevious( pNode );
+ // skip nodes below the given level
+ if ( pNode == pPivot || (int)pNode->Level <= nLevelMin )
+ return 0;
+ assert( Abc_ObjIsNode(pNode) );
+ // check if the fanins have access to the leaves
+ RetValue = 0;
+ Abc_ObjForEachFanin( pNode, pFanin, i )
+ RetValue |= Res_WinMarkPaths_rec( pFanin, pPivot, nLevelMin );
+ // relabel the node if it has access to the leaves
+ if ( RetValue )
+ Abc_NodeSetTravIdCurrent( pNode );
+ return RetValue;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Marks the paths from the roots to the leaves.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Res_WinMarkPaths( Res_Win_t * p )
+{
+ Abc_Obj_t * pObj;
+ int i;
+ // mark the leaves
+ Abc_NtkIncrementTravId( p->pNode->pNtk );
+ Abc_NtkIncrementTravId( p->pNode->pNtk );
+ Vec_PtrForEachEntry( p->vLeaves, pObj, i )
+ Abc_NodeSetTravIdCurrent( pObj );
+ // traverse from the roots and mark the nodes that can reach leaves
+ // the nodes that do not reach leaves have previous trav ID
+ // the nodes that reach leaves have current trav ID
+ Vec_PtrForEachEntry( p->vRoots, pObj, i )
+ Res_WinMarkPaths_rec( pObj, p->pNode, p->nLevTravMin );
+}
+
+
+
+
+/**Function*************************************************************
+
+ Synopsis [Recursively collects the roots.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Res_WinFinalizeRoots_rec( Abc_Obj_t * pObj, Vec_Ptr_t * vRoots )
+{
+ Abc_Obj_t * pFanout;
+ int i;
+ assert( Abc_ObjIsNode(pObj) );
+ assert( Abc_NodeIsTravIdCurrent(pObj) );
+ // check if the node has all fanouts marked
+ Abc_ObjForEachFanout( pObj, pFanout, i )
+ if ( !Abc_NodeIsTravIdCurrent(pFanout) )
+ break;
+ // if some of the fanouts are unmarked, add the node to the roots
+ if ( i < Abc_ObjFanoutNum(pObj) )
+ Vec_PtrPushUnique( vRoots, pObj );
+ else // otherwise, call recursively
+ Abc_ObjForEachFanout( pObj, pFanout, i )
+ Res_WinFinalizeRoots_rec( pFanout, vRoots );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Finalizes the roots of the window.]
+
+ Description [Roots of the window are the nodes that have at least
+ one fanout that it not in the TFO of the leaves.]
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Res_WinFinalizeRoots( Res_Win_t * p )
+{
+ assert( !Abc_NodeIsTravIdCurrent(p->pNode) );
+ // mark the node with the old traversal ID
+ Abc_NodeSetTravIdCurrent( p->pNode );
+ // recollect the roots
+ Vec_PtrClear( p->vRoots );
+ Res_WinFinalizeRoots_rec( p->pNode, p->vRoots );
+ assert( Vec_PtrSize(p->vRoots) > 0 );
+ if ( Vec_PtrSize(p->vRoots) == 1 && Vec_PtrEntry(p->vRoots, 0) == p->pNode )
+ return 0;
+ return 1;
+}
+
+
+/**Function*************************************************************
+
+ Synopsis [Recursively adds missing nodes and leaves.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Res_WinAddMissing_rec( Res_Win_t * p, Abc_Obj_t * pObj, int nLevTravMin )
+{
+ Abc_Obj_t * pFanin;
+ int i;
+ // skip the already collected leaves, nodes, and branches
+ if ( Abc_NodeIsTravIdCurrent(pObj) )
+ return;
+ // if this is not an internal node - make it a new branch
+ if ( !Abc_NodeIsTravIdPrevious(pObj) )
+ {
+ assert( Vec_PtrFind(p->vLeaves, pObj) == -1 );
+ Abc_NodeSetTravIdCurrent( pObj );
+ Vec_PtrPush( p->vBranches, pObj );
+ return;
+ }
+ assert( Abc_ObjIsNode(pObj) ); // if this is a CI, then the window is incorrect!
+ Abc_NodeSetTravIdCurrent( pObj );
+ // visit the fanins of the node
+ Abc_ObjForEachFanin( pObj, pFanin, i )
+ Res_WinAddMissing_rec( p, pFanin, nLevTravMin );
+ // collect the node
+ Vec_PtrPush( p->vNodes, pObj );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Adds to the window nodes and leaves in the TFI of the roots.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Res_WinAddMissing( Res_Win_t * p )
+{
+ Abc_Obj_t * pObj;
+ int i;
+ // mark the leaves
+ Abc_NtkIncrementTravId( p->pNode->pNtk );
+ Vec_PtrForEachEntry( p->vLeaves, pObj, i )
+ Abc_NodeSetTravIdCurrent( pObj );
+ // mark the already collected nodes
+ Vec_PtrForEachEntry( p->vNodes, pObj, i )
+ Abc_NodeSetTravIdCurrent( pObj );
+ // explore from the roots
+ Vec_PtrClear( p->vBranches );
+ Vec_PtrForEachEntry( p->vRoots, pObj, i )
+ Res_WinAddMissing_rec( p, pObj, p->nLevTravMin );
+}
+
+
+
+
+/**Function*************************************************************
+
+ Synopsis [Returns 1 if the window is trivial (without TFO).]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Res_WinIsTrivial( Res_Win_t * p )
+{
+ return Vec_PtrSize(p->vRoots) == 1 && Vec_PtrEntry(p->vRoots, 0) == p->pNode;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Computes the window.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Res_WinCompute( Abc_Obj_t * pNode, int nWinTfiMax, int nWinTfoMax, Res_Win_t * p )
+{
+ assert( Abc_ObjIsNode(pNode) );
+ assert( nWinTfiMax > 0 && nWinTfiMax < 10 );
+ assert( nWinTfoMax >= 0 && nWinTfoMax < 10 );
+
+ // initialize the window
+ p->pNode = pNode;
+ p->nWinTfiMax = nWinTfiMax;
+ p->nWinTfoMax = nWinTfoMax;
+
+ Vec_PtrClear( p->vBranches );
+ Vec_PtrClear( p->vDivs );
+ Vec_PtrClear( p->vRoots );
+ Vec_PtrPush( p->vRoots, pNode );
+
+ // compute the leaves
+ if ( !Res_WinCollectLeavesAndNodes( p ) )
+ return 0;
+
+ // compute the candidate roots
+ if ( p->nWinTfoMax > 0 && Res_WinComputeRoots(p) )
+ {
+ // mark the paths from the roots to the leaves
+ Res_WinMarkPaths( p );
+ // refine the roots and add branches and missing nodes
+ if ( Res_WinFinalizeRoots( p ) )
+ Res_WinAddMissing( p );
+ }
+
+ return 1;
+}
+
+////////////////////////////////////////////////////////////////////////
+/// END OF FILE ///
+////////////////////////////////////////////////////////////////////////
+
+
diff --git a/src/opt/res/res_.c b/src/opt/res/res_.c
new file mode 100644
index 00000000..a50affd7
--- /dev/null
+++ b/src/opt/res/res_.c
@@ -0,0 +1,50 @@
+/**CFile****************************************************************
+
+ FileName [res_.c]
+
+ SystemName [ABC: Logic synthesis and verification system.]
+
+ PackageName [Resynthesis package.]
+
+ Synopsis []
+
+ Author [Alan Mishchenko]
+
+ Affiliation [UC Berkeley]
+
+ Date [Ver. 1.0. Started - January 15, 2007.]
+
+ Revision [$Id: res_.c,v 1.00 2007/01/15 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "abc.h"
+#include "res.h"
+
+////////////////////////////////////////////////////////////////////////
+/// DECLARATIONS ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+/// FUNCTION DEFINITIONS ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+
+
+
+////////////////////////////////////////////////////////////////////////
+/// END OF FILE ///
+////////////////////////////////////////////////////////////////////////
+
+
diff --git a/src/opt/ret/module.make b/src/opt/ret/module.make
new file mode 100644
index 00000000..4b14365e
--- /dev/null
+++ b/src/opt/ret/module.make
@@ -0,0 +1,8 @@
+SRC += src/opt/ret/retArea.c \
+ src/opt/ret/retCore.c \
+ src/opt/ret/retDelay.c \
+ src/opt/ret/retFlow.c \
+ src/opt/ret/retIncrem.c \
+ src/opt/ret/retInit.c \
+ src/opt/ret/retLvalue.c
+
diff --git a/src/opt/ret/retArea.c b/src/opt/ret/retArea.c
new file mode 100644
index 00000000..5eec8e80
--- /dev/null
+++ b/src/opt/ret/retArea.c
@@ -0,0 +1,540 @@
+/**CFile****************************************************************
+
+ FileName [retArea.c]
+
+ SystemName [ABC: Logic synthesis and verification system.]
+
+ PackageName [Retiming package.]
+
+ Synopsis [Min-area retiming.]
+
+ Author [Alan Mishchenko]
+
+ Affiliation [UC Berkeley]
+
+ Date [Ver. 1.0. Started - Oct 31, 2006.]
+
+ Revision [$Id: retArea.c,v 1.00 2006/10/31 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "retInt.h"
+
+////////////////////////////////////////////////////////////////////////
+/// DECLARATIONS ///
+////////////////////////////////////////////////////////////////////////
+
+static Abc_Ntk_t * Abc_NtkRetimeMinAreaOne( Abc_Ntk_t * pNtk, int fForward, int fVerbose );
+static void Abc_NtkRetimeMinAreaPrepare( Abc_Ntk_t * pNtk, int fForward );
+static void Abc_NtkRetimeMinAreaInitValues( Abc_Ntk_t * pNtk, Vec_Ptr_t * vMinCut );
+static Abc_Ntk_t * Abc_NtkRetimeMinAreaConstructNtk( Abc_Ntk_t * pNtk, Vec_Ptr_t * vMinCut );
+static void Abc_NtkRetimeMinAreaUpdateLatches( Abc_Ntk_t * pNtk, Vec_Ptr_t * vMinCut, int fForward );
+
+extern Abc_Ntk_t * Abc_NtkAttachBottom( Abc_Ntk_t * pNtkTop, Abc_Ntk_t * pNtkBottom );
+
+////////////////////////////////////////////////////////////////////////
+/// FUNCTION DEFINITIONS ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+ Synopsis [Performs min-area retiming.]
+
+ Description [Returns the number of latches reduced.]
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Abc_NtkRetimeMinArea( Abc_Ntk_t * pNtk, int fForwardOnly, int fBackwardOnly, int fVerbose )
+{
+ Abc_Ntk_t * pNtkTotal = NULL, * pNtkBottom;
+ Vec_Int_t * vValuesNew = NULL, * vValues;
+ int nLatches = Abc_NtkLatchNum(pNtk);
+ int fOneFrame = 0;
+ assert( !fForwardOnly || !fBackwardOnly );
+ // there should not be black boxes
+ assert( Abc_NtkIsSopLogic(pNtk) );
+ assert( Abc_NtkLatchNum(pNtk) == Vec_PtrSize(pNtk->vBoxes) );
+ // reorder CI/CO/latch inputs
+ Abc_NtkOrderCisCos( pNtk );
+ // perform forward retiming
+ if ( !fBackwardOnly )
+ {
+ if ( fOneFrame )
+ Abc_NtkRetimeMinAreaOne( pNtk, 1, fVerbose );
+ else
+ while ( Abc_NtkRetimeMinAreaOne( pNtk, 1, fVerbose ) );
+ }
+ // remember initial values
+ vValues = Abc_NtkCollectLatchValues( pNtk );
+ // perform backward retiming
+ if ( !fForwardOnly )
+ {
+ if ( fOneFrame )
+ pNtkTotal = Abc_NtkRetimeMinAreaOne( pNtk, 0, fVerbose );
+ else
+ while ( pNtkBottom = Abc_NtkRetimeMinAreaOne( pNtk, 0, fVerbose ) )
+ pNtkTotal = Abc_NtkAttachBottom( pNtkTotal, pNtkBottom );
+ }
+ // compute initial values
+ vValuesNew = Abc_NtkRetimeInitialValues( pNtkTotal, vValues, fVerbose );
+ if ( pNtkTotal ) Abc_NtkDelete( pNtkTotal );
+ // insert new initial values
+ Abc_NtkInsertLatchValues( pNtk, vValuesNew );
+ if ( vValuesNew ) Vec_IntFree( vValuesNew );
+ if ( vValues ) Vec_IntFree( vValues );
+ // fix the COs (this changes the circuit structure)
+// Abc_NtkLogicMakeSimpleCos( pNtk, 0 );
+ // check for correctness
+ if ( !Abc_NtkCheck( pNtk ) )
+ fprintf( stdout, "Abc_NtkRetimeMinArea(): Network check has failed.\n" );
+ // return the number of latches saved
+ return nLatches - Abc_NtkLatchNum(pNtk);
+}
+
+/**Function*************************************************************
+
+ Synopsis [Performs min-area retiming backward.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Abc_Ntk_t * Abc_NtkRetimeMinAreaOne( Abc_Ntk_t * pNtk, int fForward, int fVerbose )
+{
+ Abc_Ntk_t * pNtkNew = NULL;
+ Vec_Ptr_t * vMinCut;
+ int nLatches = Abc_NtkLatchNum(pNtk);
+ // mark current latches and TFI(POs)
+ Abc_NtkRetimeMinAreaPrepare( pNtk, fForward );
+ // run the maximum forward flow
+ vMinCut = Abc_NtkMaxFlow( pNtk, fForward, fVerbose );
+// assert( Vec_PtrSize(vMinCut) <= Abc_NtkLatchNum(pNtk) );
+ // create new latch boundary if there is improvement
+ if ( Vec_PtrSize(vMinCut) < Abc_NtkLatchNum(pNtk) )
+ {
+ pNtkNew = (Abc_Ntk_t *)1;
+ if ( fForward )
+ Abc_NtkRetimeMinAreaInitValues( pNtk, vMinCut );
+ else
+ pNtkNew = Abc_NtkRetimeMinAreaConstructNtk( pNtk, vMinCut );
+ Abc_NtkRetimeMinAreaUpdateLatches( pNtk, vMinCut, fForward );
+ }
+ // clean up
+ Vec_PtrFree( vMinCut );
+ Abc_NtkCleanMarkA( pNtk );
+ return pNtkNew;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Marks the cone with MarkA.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Abc_NtkMarkCone_rec( Abc_Obj_t * pObj, int fForward )
+{
+ Abc_Obj_t * pNext;
+ int i;
+ if ( pObj->fMarkA )
+ return;
+ pObj->fMarkA = 1;
+ if ( fForward )
+ {
+ Abc_ObjForEachFanout( pObj, pNext, i )
+ Abc_NtkMarkCone_rec( pNext, fForward );
+ }
+ else
+ {
+ Abc_ObjForEachFanin( pObj, pNext, i )
+ Abc_NtkMarkCone_rec( pNext, fForward );
+ }
+}
+
+/**Function*************************************************************
+
+ Synopsis [Marks the cone with MarkA.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Abc_NtkUnmarkCone_rec( Abc_Obj_t * pObj, int fForward )
+{
+ Abc_Obj_t * pNext;
+ int i;
+ if ( !pObj->fMarkA || Abc_ObjIsLatch(pObj) )
+ return;
+ pObj->fMarkA = 0;
+ if ( fForward )
+ {
+ Abc_ObjForEachFanout( pObj, pNext, i )
+ Abc_NtkUnmarkCone_rec( pNext, fForward );
+ }
+ else
+ {
+ Abc_ObjForEachFanin( pObj, pNext, i )
+ Abc_NtkUnmarkCone_rec( pNext, fForward );
+ }
+}
+
+/**Function*************************************************************
+
+ Synopsis [Prepares the network for running MaxFlow.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Abc_NtkRetimeMinAreaPrepare( Abc_Ntk_t * pNtk, int fForward )
+{
+ Vec_Ptr_t * vNodes;
+ Abc_Obj_t * pObj, * pFanin;
+ int i, k;
+ if ( fForward )
+ {
+ // mark the frontier
+ Abc_NtkForEachPo( pNtk, pObj, i )
+ pObj->fMarkA = 1;
+ Abc_NtkForEachLatch( pNtk, pObj, i )
+ {
+ pObj->fMarkA = 1;
+ Abc_ObjFanin0(pObj)->fMarkA = 1;
+ }
+ // mark the nodes reachable from the PIs
+ Abc_NtkForEachPi( pNtk, pObj, i )
+ Abc_NtkMarkCone_rec( pObj, fForward );
+ // collect the unmarked fanins of the marked nodes
+ vNodes = Vec_PtrAlloc( 100 );
+ Abc_NtkForEachObj( pNtk, pObj, i )
+ if ( pObj->fMarkA )
+ Abc_ObjForEachFanin( pObj, pFanin, k )
+ if ( !pFanin->fMarkA )
+ Vec_PtrPush( vNodes, pFanin );
+ // mark these nodes
+ Vec_PtrForEachEntry( vNodes, pObj, i )
+ pObj->fMarkA = 1;
+ Vec_PtrFree( vNodes );
+ }
+ else
+ {
+ // mark the frontier
+ Abc_NtkForEachPi( pNtk, pObj, i )
+ pObj->fMarkA = 1;
+ Abc_NtkForEachLatch( pNtk, pObj, i )
+ {
+ pObj->fMarkA = 1;
+ Abc_ObjFanout0(pObj)->fMarkA = 1;
+ }
+ // mark the nodes reachable from the POs
+ Abc_NtkForEachPo( pNtk, pObj, i )
+ Abc_NtkMarkCone_rec( pObj, fForward );
+ }
+}
+
+/**Function*************************************************************
+
+ Synopsis [Compute initial values.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Abc_NtkRetimeMinAreaInitValues_rec( Abc_Obj_t * pObj )
+{
+ Abc_Obj_t * pFanin;
+ int i;
+ // skip visited nodes
+ if ( Abc_NodeIsTravIdCurrent(pObj) )
+ return (int)pObj->pCopy;
+ Abc_NodeSetTravIdCurrent(pObj);
+ // consider the case of a latch output
+ if ( Abc_ObjIsBo(pObj) )
+ {
+ assert( Abc_ObjIsLatch(Abc_ObjFanin0(pObj)) );
+ pObj->pCopy = (void *)Abc_NtkRetimeMinAreaInitValues_rec( Abc_ObjFanin0(pObj) );
+ return (int)pObj->pCopy;
+ }
+ assert( Abc_ObjIsNode(pObj) );
+ // visit the fanins
+ Abc_ObjForEachFanin( pObj, pFanin, i )
+ Abc_NtkRetimeMinAreaInitValues_rec( pFanin );
+ // compute the value of the node
+ pObj->pCopy = (void *)Abc_ObjSopSimulate(pObj);
+ return (int)pObj->pCopy;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Compute initial values.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Abc_NtkRetimeMinAreaInitValues( Abc_Ntk_t * pNtk, Vec_Ptr_t * vMinCut )
+{
+ Abc_Obj_t * pObj;
+ int i;
+ // transfer initial values to pCopy and mark the latches
+ Abc_NtkIncrementTravId(pNtk);
+ Abc_NtkForEachLatch( pNtk, pObj, i )
+ {
+ pObj->pCopy = (void *)Abc_LatchIsInit1(pObj);
+ Abc_NodeSetTravIdCurrent( pObj );
+ }
+ // propagate initial values
+ Vec_PtrForEachEntry( vMinCut, pObj, i )
+ Abc_NtkRetimeMinAreaInitValues_rec( pObj );
+ // unmark the latches
+ Abc_NtkForEachLatch( pNtk, pObj, i )
+ Abc_NodeSetTravIdPrevious( pObj );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Performs min-area retiming backward.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Abc_Obj_t * Abc_NtkRetimeMinAreaConstructNtk_rec( Abc_Ntk_t * pNtkNew, Abc_Obj_t * pObj )
+{
+ Abc_Obj_t * pFanin;
+ int i;
+ // skip visited nodes
+ if ( Abc_NodeIsTravIdCurrent(pObj) )
+ return pObj->pCopy;
+ Abc_NodeSetTravIdCurrent(pObj);
+ // consider the case of a latch output
+ if ( Abc_ObjIsBi(pObj) )
+ {
+ pObj->pCopy = Abc_NtkRetimeMinAreaConstructNtk_rec( pNtkNew, Abc_ObjFanin0(pObj) );
+ return pObj->pCopy;
+ }
+ assert( Abc_ObjIsNode(pObj) );
+ // visit the fanins
+ Abc_ObjForEachFanin( pObj, pFanin, i )
+ Abc_NtkRetimeMinAreaConstructNtk_rec( pNtkNew, pFanin );
+ // compute the value of the node
+ Abc_NtkDupObj( pNtkNew, pObj, 0 );
+ Abc_ObjForEachFanin( pObj, pFanin, i )
+ Abc_ObjAddFanin( pObj->pCopy, pFanin->pCopy );
+ return pObj->pCopy;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Creates the network from computing initial state.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Abc_Ntk_t * Abc_NtkRetimeMinAreaConstructNtk( Abc_Ntk_t * pNtk, Vec_Ptr_t * vMinCut )
+{
+ Abc_Ntk_t * pNtkNew;
+ Abc_Obj_t * pObj, * pObjNew;
+ int i;
+ // create new network
+ pNtkNew = Abc_NtkAlloc( ABC_NTK_LOGIC, ABC_FUNC_SOP, 1 );
+ // map new latches into PIs of the new network
+ Abc_NtkIncrementTravId(pNtk);
+ Vec_PtrForEachEntry( vMinCut, pObj, i )
+ {
+ pObj->pCopy = Abc_NtkCreatePi(pNtkNew);
+ Abc_NodeSetTravIdCurrent( pObj );
+ }
+ // construct the network recursively
+ Abc_NtkForEachLatch( pNtk, pObj, i )
+ {
+ pObjNew = Abc_NtkRetimeMinAreaConstructNtk_rec( pNtkNew, Abc_ObjFanin0(pObj) );
+ Abc_ObjAddFanin( Abc_NtkCreatePo(pNtkNew), pObjNew );
+ }
+ // unmark the nodes in the cut
+ Vec_PtrForEachEntry( vMinCut, pObj, i )
+ Abc_NodeSetTravIdPrevious( pObj );
+ // unmark the latches
+ Abc_NtkForEachLatch( pNtk, pObj, i )
+ Abc_NodeSetTravIdPrevious( pObj );
+ // assign dummy node names
+ Abc_NtkAddDummyPiNames( pNtkNew );
+ Abc_NtkAddDummyPoNames( pNtkNew );
+ if ( !Abc_NtkCheck( pNtkNew ) )
+ fprintf( stdout, "Abc_NtkRetimeMinAreaConstructNtk(): Network check has failed.\n" );
+ return pNtkNew;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Updates the network after backward retiming.]
+
+ Description [Assumes that fMarkA denotes all nodes reachabe from
+ the latches toward the cut.]
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Abc_NtkRetimeMinAreaUpdateLatches( Abc_Ntk_t * pNtk, Vec_Ptr_t * vMinCut, int fForward )
+{
+ Vec_Ptr_t * vCis, * vCos, * vBoxes, * vBoxesNew, * vNodes, * vBuffers;
+ Abc_Obj_t * pObj, * pLatch, * pLatchIn, * pLatchOut, * pNext, * pBuffer;
+ int i, k;
+ // create new latches
+ Vec_PtrShrink( pNtk->vCis, Abc_NtkCiNum(pNtk) - Abc_NtkLatchNum(pNtk) );
+ Vec_PtrShrink( pNtk->vCos, Abc_NtkCoNum(pNtk) - Abc_NtkLatchNum(pNtk) );
+ vCis = pNtk->vCis; pNtk->vCis = NULL;
+ vCos = pNtk->vCos; pNtk->vCos = NULL;
+ vBoxes = pNtk->vBoxes; pNtk->vBoxes = NULL;
+ // transfer boxes
+ vBoxesNew = Vec_PtrAlloc(100);
+ Vec_PtrForEachEntry( vBoxes, pObj, i )
+ if ( !Abc_ObjIsLatch(pObj) )
+ Vec_PtrPush( vBoxesNew, pObj );
+ // create or reuse latches
+ vNodes = Vec_PtrAlloc( 100 );
+ vBuffers = Vec_PtrAlloc( 100 );
+ Vec_PtrForEachEntry( vMinCut, pObj, i )
+ {
+ if ( Abc_ObjIsCi(pObj) && fForward )
+ {
+ pLatchOut = pObj;
+ pLatch = Abc_ObjFanin0(pLatchOut);
+ pLatchIn = Abc_ObjFanin0(pLatch);
+ assert( Abc_ObjIsBo(pLatchOut) && Abc_ObjIsLatch(pLatch) && Abc_ObjIsBi(pLatchIn) );
+ // mark the latch as reused
+ Abc_NodeSetTravIdCurrent( pLatch );
+
+ // check if there are marked fanouts
+ // (these are fanouts to be connected to the latch input)
+ Abc_ObjForEachFanout( pObj, pNext, k )
+ if ( pNext->fMarkA )
+ break;
+ if ( k < Abc_ObjFanoutNum(pObj) )
+ {
+ // add the buffer
+ pBuffer = Abc_NtkCreateNodeBuf( pNtk, Abc_ObjFanin0(pLatchIn) );
+ Abc_ObjPatchFanin( pLatchIn, Abc_ObjFanin0(pLatchIn), pBuffer );
+ Vec_PtrPush( vBuffers, pBuffer );
+ // redirect edges to the unvisited fanouts of the node
+ Abc_NodeCollectFanouts( pObj, vNodes );
+ Vec_PtrForEachEntry( vNodes, pNext, k )
+ if ( pNext->fMarkA )
+ Abc_ObjPatchFanin( pNext, pObj, pBuffer );
+ }
+ assert( Abc_ObjFanoutNum(pObj) > 0 );
+// if ( Abc_ObjFanoutNum(pObj) == 0 )
+// Abc_NtkDeleteObj_rec( pObj, 0 );
+ }
+ else if ( Abc_ObjIsCo(pObj) && !fForward )
+ {
+ pLatchIn = pObj;
+ pLatch = Abc_ObjFanout0(pLatchIn);
+ pLatchOut = Abc_ObjFanout0(pLatch);
+ assert( Abc_ObjIsBo(pLatchOut) && Abc_ObjIsLatch(pLatch) && Abc_ObjIsBi(pLatchIn) );
+ // mark the latch as reused
+ Abc_NodeSetTravIdCurrent( pLatch );
+ assert( !Abc_ObjFanin0(pLatchIn)->fMarkA );
+ }
+ else
+ {
+ pLatchOut = Abc_NtkCreateBo(pNtk);
+ pLatch = Abc_NtkCreateLatch(pNtk);
+ pLatchIn = Abc_NtkCreateBi(pNtk);
+ Abc_ObjAssignName( pLatchOut, Abc_ObjName(pLatch), "_out" );
+ Abc_ObjAssignName( pLatchIn, Abc_ObjName(pLatch), "_in" );
+ // connect
+ Abc_ObjAddFanin( pLatchOut, pLatch );
+ Abc_ObjAddFanin( pLatch, pLatchIn );
+ if ( fForward )
+ {
+ pLatch->pData = (void *)(pObj->pCopy? ABC_INIT_ONE : ABC_INIT_ZERO);
+ // redirect edges to the unvisited fanouts of the node
+ Abc_NodeCollectFanouts( pObj, vNodes );
+ Vec_PtrForEachEntry( vNodes, pNext, k )
+ if ( !pNext->fMarkA )
+ Abc_ObjPatchFanin( pNext, pObj, pLatchOut );
+ }
+ else
+ {
+ // redirect edges to the visited fanouts of the node
+ Abc_NodeCollectFanouts( pObj, vNodes );
+ Vec_PtrForEachEntry( vNodes, pNext, k )
+ if ( pNext->fMarkA )
+ Abc_ObjPatchFanin( pNext, pObj, pLatchOut );
+ }
+ // connect latch to the node
+ Abc_ObjAddFanin( pLatchIn, pObj );
+ }
+ Vec_PtrPush( vCis, pLatchOut );
+ Vec_PtrPush( vBoxesNew, pLatch );
+ Vec_PtrPush( vCos, pLatchIn );
+ }
+ Vec_PtrFree( vNodes );
+ // remove buffers
+ Vec_PtrForEachEntry( vBuffers, pObj, i )
+ {
+ Abc_ObjTransferFanout( pObj, Abc_ObjFanin0(pObj) );
+ Abc_NtkDeleteObj( pObj );
+ }
+ Vec_PtrFree( vBuffers );
+ // remove useless latches
+ Vec_PtrForEachEntry( vBoxes, pObj, i )
+ {
+ if ( !Abc_ObjIsLatch(pObj) )
+ continue;
+ if ( Abc_NodeIsTravIdCurrent(pObj) )
+ continue;
+ pLatchOut = Abc_ObjFanout0(pObj);
+ pLatch = pObj;
+ pLatchIn = Abc_ObjFanin0(pObj);
+ if ( Abc_ObjFanoutNum(pLatchOut) > 0 )
+ Abc_ObjTransferFanout( pLatchOut, Abc_ObjFanin0(pLatchIn) );
+ Abc_NtkDeleteObj( pLatchOut );
+ Abc_NtkDeleteObj( pObj );
+ Abc_NtkDeleteObj( pLatchIn );
+ }
+ // set the arrays
+ pNtk->vCis = vCis;
+ pNtk->vCos = vCos;
+ pNtk->vBoxes = vBoxesNew;
+ Vec_PtrFree( vBoxes );
+}
+
+
+////////////////////////////////////////////////////////////////////////
+/// END OF FILE ///
+////////////////////////////////////////////////////////////////////////
+
+
diff --git a/src/opt/ret/retCore.c b/src/opt/ret/retCore.c
new file mode 100644
index 00000000..47b2cbbc
--- /dev/null
+++ b/src/opt/ret/retCore.c
@@ -0,0 +1,132 @@
+/**CFile****************************************************************
+
+ FileName [retCore.c]
+
+ SystemName [ABC: Logic synthesis and verification system.]
+
+ PackageName [Retiming package.]
+
+ Synopsis [The core retiming procedures.]
+
+ Author [Alan Mishchenko]
+
+ Affiliation [UC Berkeley]
+
+ Date [Ver. 1.0. Started - Oct 31, 2006.]
+
+ Revision [$Id: retCore.c,v 1.00 2006/10/31 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "retInt.h"
+
+////////////////////////////////////////////////////////////////////////
+/// DECLARATIONS ///
+////////////////////////////////////////////////////////////////////////
+
+int timeRetime = 0;
+
+////////////////////////////////////////////////////////////////////////
+/// FUNCTION DEFINITIONS ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+ Synopsis [Implementation of retiming.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Abc_NtkRetime( Abc_Ntk_t * pNtk, int Mode, int fForwardOnly, int fBackwardOnly, int fOneStep, int fVerbose )
+{
+ int nLatches = Abc_NtkLatchNum(pNtk);
+ int nLevels = Abc_NtkLevel(pNtk);
+ int RetValue = 0, clkTotal = clock();
+ int nNodesOld, nLatchesOld;
+ assert( Mode > 0 && Mode < 7 );
+ assert( !fForwardOnly || !fBackwardOnly );
+
+ // cleanup the network
+ nNodesOld = Abc_NtkNodeNum(pNtk);
+ nLatchesOld = Abc_NtkLatchNum(pNtk);
+ Abc_NtkCleanupSeq(pNtk, 0, 0, 0);
+ if ( nNodesOld > Abc_NtkNodeNum(pNtk) || nLatchesOld > Abc_NtkLatchNum(pNtk) )
+ printf( "Cleanup before retiming removed %d dangling nodes and %d dangling latches.\n",
+ nNodesOld - Abc_NtkNodeNum(pNtk), nLatchesOld - Abc_NtkLatchNum(pNtk) );
+
+ // perform retiming
+ switch ( Mode )
+ {
+ case 1: // forward
+ RetValue = Abc_NtkRetimeIncremental( pNtk, 1, 0, 0, fVerbose );
+ break;
+ case 2: // backward
+ RetValue = Abc_NtkRetimeIncremental( pNtk, 0, 0, 0, fVerbose );
+ break;
+ case 3: // min-area
+ RetValue = Abc_NtkRetimeMinArea( pNtk, fForwardOnly, fBackwardOnly, fVerbose );
+ break;
+ case 4: // min-delay
+ if ( !fBackwardOnly )
+ RetValue += Abc_NtkRetimeIncremental( pNtk, 1, 1, fOneStep, fVerbose );
+ if ( !fForwardOnly )
+ RetValue += Abc_NtkRetimeIncremental( pNtk, 0, 1, fOneStep, fVerbose );
+ break;
+ case 5: // min-area + min-delay
+ RetValue = Abc_NtkRetimeMinArea( pNtk, fForwardOnly, fBackwardOnly, fVerbose );
+ if ( !fBackwardOnly )
+ RetValue += Abc_NtkRetimeIncremental( pNtk, 1, 1, 0, fVerbose );
+ if ( !fForwardOnly )
+ RetValue += Abc_NtkRetimeIncremental( pNtk, 0, 1, 0, fVerbose );
+ break;
+ case 6: // Pan's algorithm
+ RetValue = Abc_NtkRetimeLValue( pNtk, 500, fVerbose );
+ break;
+ default:
+ printf( "Unknown retiming option.\n" );
+ break;
+ }
+ if ( fVerbose )
+ {
+ printf( "Reduction in area = %3d. Reduction in delay = %3d. ",
+ nLatches - Abc_NtkLatchNum(pNtk), nLevels - Abc_NtkLevel(pNtk) );
+ PRT( "Total runtime", clock() - clkTotal );
+ }
+ timeRetime = clock() - clkTotal;
+ return RetValue;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Used for automated debugging.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Abc_NtkRetimeDebug( Abc_Ntk_t * pNtk )
+{
+ extern int Abc_NtkSecFraig( Abc_Ntk_t * pNtk1, Abc_Ntk_t * pNtk2, int nSeconds, int nFrames, int fVerbose );
+ Abc_Ntk_t * pNtkRet;
+ assert( Abc_NtkIsLogic(pNtk) );
+ Abc_NtkToSop( pNtk, 0 );
+// if ( !Abc_NtkCheck( pNtk ) )
+// fprintf( stdout, "Abc_NtkRetimeDebug(): Network check has failed.\n" );
+// Io_WriteBlifLogic( pNtk, "debug_temp.blif", 1 );
+ pNtkRet = Abc_NtkDup( pNtk );
+ Abc_NtkRetime( pNtkRet, 3, 0, 1, 0, 0 ); // debugging backward flow
+ return !Abc_NtkSecFraig( pNtk, pNtkRet, 10000, 3, 0 );
+}
+
+////////////////////////////////////////////////////////////////////////
+/// END OF FILE ///
+////////////////////////////////////////////////////////////////////////
+
+
diff --git a/src/opt/ret/retDelay.c b/src/opt/ret/retDelay.c
new file mode 100644
index 00000000..bcfe3a2e
--- /dev/null
+++ b/src/opt/ret/retDelay.c
@@ -0,0 +1,305 @@
+/**CFile****************************************************************
+
+ FileName [retDelay.c]
+
+ SystemName [ABC: Logic synthesis and verification system.]
+
+ PackageName [Retiming package.]
+
+ Synopsis [Incremental retiming for optimum delay.]
+
+ Author [Alan Mishchenko]
+
+ Affiliation [UC Berkeley]
+
+ Date [Ver. 1.0. Started - Oct 31, 2006.]
+
+ Revision [$Id: retDelay.c,v 1.00 2006/10/31 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "retInt.h"
+
+////////////////////////////////////////////////////////////////////////
+/// DECLARATIONS ///
+////////////////////////////////////////////////////////////////////////
+
+static int Abc_NtkRetimeMinDelayTry( Abc_Ntk_t * pNtk, int fForward, int fInitial, int nIterLimit, int * pIterBest, int fVerbose );
+static int Abc_NtkRetimeTiming( Abc_Ntk_t * pNtk, int fForward, Vec_Ptr_t * vCritical );
+static int Abc_NtkRetimeTiming_rec( Abc_Obj_t * pObj, int fForward );
+
+////////////////////////////////////////////////////////////////////////
+/// FUNCTION DEFINITIONS ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+ Synopsis [Retimes incrementally for minimum delay.]
+
+ Description [This procedure cannot be called in the application code
+ because it assumes that the network is preprocessed by removing LIs/LOs.]
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Abc_NtkRetimeMinDelay( Abc_Ntk_t * pNtk, Abc_Ntk_t * pNtkCopy, int nIterLimit, int fForward, int fVerbose )
+{
+ int IterBest, DelayBest;
+ int IterBest2, DelayBest2;
+ // try to find the best delay iteration on a copy
+ DelayBest = Abc_NtkRetimeMinDelayTry( pNtkCopy, fForward, 0, nIterLimit, &IterBest, fVerbose );
+ if ( IterBest == 0 )
+ return 1;
+ // perform the given number of iterations on the original network
+ DelayBest2 = Abc_NtkRetimeMinDelayTry( pNtk, fForward, 1, IterBest, &IterBest2, fVerbose );
+ assert( DelayBest == DelayBest2 );
+ assert( IterBest == IterBest2 );
+ return 1;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Returns the best delay and the number of best iteration.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Abc_NtkRetimeMinDelayTry( Abc_Ntk_t * pNtk, int fForward, int fInitial, int nIterLimit, int * pIterBest, int fVerbose )
+{
+ Abc_Ntk_t * pNtkNew = NULL;
+ Vec_Ptr_t * vCritical;
+ Vec_Int_t * vValues;
+ Abc_Obj_t * pObj;
+ int i, k, IterBest, DelayCur, DelayBest, DelayStart, LatchesBest;
+ // transfer intitial values
+ if ( fInitial )
+ {
+ if ( fForward )
+ Abc_NtkRetimeTranferToCopy( pNtk );
+ else
+ {
+ // save initial value of the latches
+ vValues = Abc_NtkRetimeCollectLatchValues( pNtk );
+ // start the network for initial value computation
+ pNtkNew = Abc_NtkRetimeBackwardInitialStart( pNtk );
+ }
+ }
+
+if ( fVerbose && !fInitial )
+ printf( "Performing analysis:\n" );
+ // find the best iteration
+ DelayBest = ABC_INFINITY; IterBest = 0; LatchesBest = Abc_NtkLatchNum(pNtk);
+ vCritical = Vec_PtrAlloc( 100 );
+ for ( i = 0; ; i++ )
+ {
+ // perform moves for the timing-critical nodes
+ DelayCur = Abc_NtkRetimeTiming( pNtk, fForward, vCritical );
+ if ( i == 0 )
+ DelayStart = DelayCur;
+ // record this position if it has the best delay
+ if ( DelayBest > DelayCur )
+ {
+if ( fVerbose && !fInitial )
+ printf( "%s Iter = %3d. Delay = %3d. Latches = %5d. Delta = %6.2f. Ratio = %4.2f %%\n",
+ fForward ? "Fwd": "Bwd", i, DelayCur, Abc_NtkLatchNum(pNtk),
+ 1.0*(Abc_NtkLatchNum(pNtk)-LatchesBest)/(DelayBest-DelayCur),
+ 100.0*(Abc_NtkLatchNum(pNtk)-LatchesBest)/Abc_NtkLatchNum(pNtk)/(DelayBest-DelayCur) );
+
+ DelayBest = DelayCur;
+ IterBest = i;
+ LatchesBest = Abc_NtkLatchNum(pNtk);
+ }
+ // quit after timing analysis
+ if ( i == nIterLimit )
+ break;
+ // skip if 10 interations did not give improvement
+ if ( i - IterBest > 20 )
+ break;
+ // try retiming to improve the delay
+ Vec_PtrForEachEntry( vCritical, pObj, k )
+ if ( Abc_NtkRetimeNodeIsEnabled(pObj, fForward) )
+ Abc_NtkRetimeNode( pObj, fForward, fInitial );
+ // share latches
+ if ( !fForward )
+ Abc_NtkRetimeShareLatches( pNtk, fInitial );
+ }
+ Vec_PtrFree( vCritical );
+ // transfer the initial state back to the latches
+ if ( fInitial )
+ {
+ if ( fForward )
+ Abc_NtkRetimeTranferFromCopy( pNtk );
+ else
+ {
+ Abc_NtkRetimeBackwardInitialFinish( pNtk, pNtkNew, vValues, fVerbose );
+ Abc_NtkDelete( pNtkNew );
+ Vec_IntFree( vValues );
+ }
+ }
+if ( fVerbose && !fInitial )
+ printf( "%s : Starting delay = %3d. Final delay = %3d. IterBest = %2d (out of %2d).\n",
+ fForward? "Forward " : "Backward", DelayStart, DelayBest, IterBest, nIterLimit );
+ *pIterBest = (nIterLimit == 1) ? 1 : IterBest;
+ return DelayBest;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Returns the set of timing-critical nodes.]
+
+ Description [Performs static timing analysis on the network. Uses
+ unit-delay model.]
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Abc_NtkRetimeTiming( Abc_Ntk_t * pNtk, int fForward, Vec_Ptr_t * vCritical )
+{
+ Vec_Ptr_t * vLatches;
+ Abc_Obj_t * pObj, * pNext;
+ int i, k, LevelCur, LevelMax = 0;
+ // mark all objects except nodes
+ Abc_NtkIncrementTravId(pNtk);
+ vLatches = Vec_PtrAlloc( Abc_NtkLatchNum(pNtk) );
+ Abc_NtkForEachObj( pNtk, pObj, i )
+ {
+ if ( Abc_ObjIsLatch(pObj) )
+ Vec_PtrPush( vLatches, pObj );
+ if ( Abc_ObjIsNode(pObj) )
+ continue;
+ pObj->Level = 0;
+ Abc_NodeSetTravIdCurrent( pObj );
+ }
+ // perform analysis from CIs/COs
+ if ( fForward )
+ {
+ Vec_PtrForEachEntry( vLatches, pObj, i )
+ {
+ Abc_ObjForEachFanout( pObj, pNext, k )
+ {
+ LevelCur = Abc_NtkRetimeTiming_rec( pNext, fForward );
+ if ( LevelMax < LevelCur )
+ LevelMax = LevelCur;
+ }
+ }
+ Abc_NtkForEachPi( pNtk, pObj, i )
+ {
+ Abc_ObjForEachFanout( pObj, pNext, k )
+ {
+ LevelCur = Abc_NtkRetimeTiming_rec( pNext, fForward );
+ if ( LevelMax < LevelCur )
+ LevelMax = LevelCur;
+ }
+ }
+ }
+ else
+ {
+ Vec_PtrForEachEntry( vLatches, pObj, i )
+ {
+ LevelCur = Abc_NtkRetimeTiming_rec( Abc_ObjFanin0(pObj), fForward );
+ if ( LevelMax < LevelCur )
+ LevelMax = LevelCur;
+ }
+ Abc_NtkForEachPo( pNtk, pObj, i )
+ {
+ LevelCur = Abc_NtkRetimeTiming_rec( Abc_ObjFanin0(pObj), fForward );
+ if ( LevelMax < LevelCur )
+ LevelMax = LevelCur;
+ }
+ }
+ // collect timing critical nodes, which should be retimed forward/backward
+ Vec_PtrClear( vCritical );
+ Abc_NtkIncrementTravId(pNtk);
+ if ( fForward )
+ {
+ Vec_PtrForEachEntry( vLatches, pObj, i )
+ {
+ Abc_ObjForEachFanout( pObj, pNext, k )
+ {
+ if ( Abc_NodeIsTravIdCurrent(pNext) )
+ continue;
+ if ( LevelMax != (int)pNext->Level )
+ continue;
+ // new critical node
+ Vec_PtrPush( vCritical, pNext );
+ Abc_NodeSetTravIdCurrent( pNext );
+ }
+ }
+ }
+ else
+ {
+ Vec_PtrForEachEntry( vLatches, pObj, i )
+ {
+ Abc_ObjForEachFanin( pObj, pNext, k )
+ {
+ if ( Abc_NodeIsTravIdCurrent(pNext) )
+ continue;
+ if ( LevelMax != (int)pNext->Level )
+ continue;
+ // new critical node
+ Vec_PtrPush( vCritical, pNext );
+ Abc_NodeSetTravIdCurrent( pNext );
+ }
+ }
+ }
+ Vec_PtrFree( vLatches );
+ return LevelMax;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Recursively performs timing analysis.]
+
+ Description [Performs static timing analysis on the network. Uses
+ unit-delay model.]
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Abc_NtkRetimeTiming_rec( Abc_Obj_t * pObj, int fForward )
+{
+ Abc_Obj_t * pNext;
+ int i, LevelCur, LevelMax = 0;
+ // skip visited nodes
+ if ( Abc_NodeIsTravIdCurrent(pObj) )
+ return pObj->Level;
+ Abc_NodeSetTravIdCurrent(pObj);
+ // visit the next nodes
+ if ( fForward )
+ {
+ Abc_ObjForEachFanout( pObj, pNext, i )
+ {
+ LevelCur = Abc_NtkRetimeTiming_rec( pNext, fForward );
+ if ( LevelMax < LevelCur )
+ LevelMax = LevelCur;
+ }
+ }
+ else
+ {
+ Abc_ObjForEachFanin( pObj, pNext, i )
+ {
+ LevelCur = Abc_NtkRetimeTiming_rec( pNext, fForward );
+ if ( LevelMax < LevelCur )
+ LevelMax = LevelCur;
+ }
+ }
+// printf( "Node %3d -> Level %3d.\n", pObj->Id, LevelMax + 1 );
+ pObj->Level = LevelMax + 1;
+ return pObj->Level;
+}
+
+////////////////////////////////////////////////////////////////////////
+/// END OF FILE ///
+////////////////////////////////////////////////////////////////////////
+
+
diff --git a/src/opt/ret/retFlow.c b/src/opt/ret/retFlow.c
new file mode 100644
index 00000000..47ee8516
--- /dev/null
+++ b/src/opt/ret/retFlow.c
@@ -0,0 +1,783 @@
+/**CFile****************************************************************
+
+ FileName [retFlow.c]
+
+ SystemName [ABC: Logic synthesis and verification system.]
+
+ PackageName [Network and node package.]
+
+ Synopsis [Implementation of maximum flow (min-area retiming).]
+
+ Author [Alan Mishchenko]
+
+ Affiliation [UC Berkeley]
+
+ Date [Ver. 1.0. Started - Oct 31, 2006.]
+
+ Revision [$Id: retFlow.c,v 1.00 2006/10/31 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "retInt.h"
+
+////////////////////////////////////////////////////////////////////////
+/// DECLARATIONS ///
+////////////////////////////////////////////////////////////////////////
+
+static inline int Abc_ObjSetPath( Abc_Obj_t * pObj, Abc_Obj_t * pNext ) { pObj->pCopy = pNext; return 1; }
+static inline Abc_Obj_t * Abc_ObjGetPath( Abc_Obj_t * pObj ) { return pObj->pCopy; }
+static inline Abc_Obj_t * Abc_ObjGetFanoutPath( Abc_Obj_t * pObj )
+{
+ Abc_Obj_t * pFanout;
+ int i;
+ assert( Abc_ObjGetPath(pObj) );
+ Abc_ObjForEachFanout( pObj, pFanout, i )
+ if ( Abc_ObjGetPath(pFanout) == pObj )
+ return pFanout;
+ return NULL;
+}
+static inline Abc_Obj_t * Abc_ObjGetFaninPath( Abc_Obj_t * pObj )
+{
+ Abc_Obj_t * pFanin;
+ int i;
+ assert( Abc_ObjGetPath(pObj) );
+ Abc_ObjForEachFanin( pObj, pFanin, i )
+ if ( Abc_ObjGetPath(pFanin) == pObj )
+ return pFanin;
+ return NULL;
+}
+static inline Abc_Obj_t * Abc_ObjGetPredecessorBwd( Abc_Obj_t * pObj )
+{
+ Abc_Obj_t * pNext;
+ int i;
+ Abc_ObjForEachFanout( pObj, pNext, i )
+ if ( Abc_ObjGetPath(pNext) == pObj )
+ return pNext;
+ Abc_ObjForEachFanin( pObj, pNext, i )
+ if ( Abc_ObjGetPath(pNext) == pObj )
+ return pNext;
+ return NULL;
+}
+static inline Abc_Obj_t * Abc_ObjGetPredecessorFwd( Abc_Obj_t * pObj )
+{
+ Abc_Obj_t * pNext;
+ int i;
+ Abc_ObjForEachFanin( pObj, pNext, i )
+ if ( Abc_ObjGetPath(pNext) == pObj )
+ return pNext;
+ Abc_ObjForEachFanout( pObj, pNext, i )
+ if ( Abc_ObjGetPath(pNext) == pObj )
+ return pNext;
+ return NULL;
+}
+
+static int Abc_NtkMaxFlowBwdPath_rec( Abc_Obj_t * pObj );
+static int Abc_NtkMaxFlowFwdPath_rec( Abc_Obj_t * pObj );
+static int Abc_NtkMaxFlowBwdPath2_rec( Abc_Obj_t * pObj );
+static int Abc_NtkMaxFlowFwdPath2_rec( Abc_Obj_t * pObj );
+//static int Abc_NtkMaxFlowBwdPath3_rec( Abc_Obj_t * pObj );
+static int Abc_NtkMaxFlowFwdPath3_rec( Abc_Obj_t * pObj, Abc_Obj_t * pPrev, int fFanin );
+static Vec_Ptr_t * Abc_NtkMaxFlowMinCut( Abc_Ntk_t * pNtk, int fForward );
+static void Abc_NtkMaxFlowMinCutUpdate( Abc_Ntk_t * pNtk, Vec_Ptr_t * vMinCut, int fForward );
+static int Abc_NtkMaxFlowVerifyCut( Abc_Ntk_t * pNtk, Vec_Ptr_t * vMinCut, int fForward );
+static void Abc_NtkMaxFlowPrintCut( Abc_Ntk_t * pNtk, Vec_Ptr_t * vMinCut );
+static void Abc_NtkMaxFlowPrintFlow( Abc_Ntk_t * pNtk, int fForward );
+
+////////////////////////////////////////////////////////////////////////
+/// FUNCTION DEFINITIONS ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+ Synopsis [Test-bench for the max-flow computation.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Abc_NtkMaxFlowTest( Abc_Ntk_t * pNtk )
+{
+ Vec_Ptr_t * vMinCut;
+ Abc_Obj_t * pObj;
+ int i;
+
+ // forward flow
+ Abc_NtkForEachPo( pNtk, pObj, i )
+ pObj->fMarkA = 1;
+ Abc_NtkForEachLatch( pNtk, pObj, i )
+ pObj->fMarkA = Abc_ObjFanin0(pObj)->fMarkA = 1;
+// Abc_ObjFanin0(pObj)->fMarkA = 1;
+ vMinCut = Abc_NtkMaxFlow( pNtk, 1, 1 );
+ Vec_PtrFree( vMinCut );
+ Abc_NtkCleanMarkA( pNtk );
+
+ // backward flow
+ Abc_NtkForEachPi( pNtk, pObj, i )
+ pObj->fMarkA = 1;
+ Abc_NtkForEachLatch( pNtk, pObj, i )
+ pObj->fMarkA = Abc_ObjFanout0(pObj)->fMarkA = 1;
+// Abc_ObjFanout0(pObj)->fMarkA = 1;
+ vMinCut = Abc_NtkMaxFlow( pNtk, 0, 1 );
+ Vec_PtrFree( vMinCut );
+ Abc_NtkCleanMarkA( pNtk );
+
+}
+
+/**Function*************************************************************
+
+ Synopsis [Implementation of max-flow/min-cut computation.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Vec_Ptr_t * Abc_NtkMaxFlow( Abc_Ntk_t * pNtk, int fForward, int fVerbose )
+{
+ Vec_Ptr_t * vMinCut;
+ Abc_Obj_t * pLatch;
+ int Flow, FlowCur, RetValue, i;
+ int clk = clock();
+ int fUseDirectedFlow = 1;
+
+ // find the max-flow
+ Abc_NtkCleanCopy( pNtk );
+ Flow = 0;
+ Abc_NtkIncrementTravId(pNtk);
+ Abc_NtkForEachLatch( pNtk, pLatch, i )
+ {
+ if ( fForward )
+ {
+// assert( !Abc_ObjFanout0(pLatch)->fMarkA );
+ FlowCur = Abc_NtkMaxFlowFwdPath2_rec( Abc_ObjFanout0(pLatch) );
+// FlowCur = Abc_NtkMaxFlowFwdPath3_rec( Abc_ObjFanout0(pLatch), pLatch, 1 );
+ Flow += FlowCur;
+ }
+ else
+ {
+ assert( !Abc_ObjFanin0(pLatch)->fMarkA );
+ FlowCur = Abc_NtkMaxFlowBwdPath2_rec( Abc_ObjFanin0(pLatch) );
+ Flow += FlowCur;
+ }
+ if ( FlowCur )
+ Abc_NtkIncrementTravId(pNtk);
+ }
+
+ if ( !fUseDirectedFlow )
+ {
+ Abc_NtkIncrementTravId(pNtk);
+ Abc_NtkForEachLatch( pNtk, pLatch, i )
+ {
+ if ( fForward )
+ {
+ // assert( !Abc_ObjFanout0(pLatch)->fMarkA );
+ FlowCur = Abc_NtkMaxFlowFwdPath_rec( Abc_ObjFanout0(pLatch) );
+ Flow += FlowCur;
+ }
+ else
+ {
+ assert( !Abc_ObjFanin0(pLatch)->fMarkA );
+ FlowCur = Abc_NtkMaxFlowBwdPath_rec( Abc_ObjFanin0(pLatch) );
+ Flow += FlowCur;
+ }
+ if ( FlowCur )
+ Abc_NtkIncrementTravId(pNtk);
+ }
+ }
+// Abc_NtkMaxFlowPrintFlow( pNtk, fForward );
+
+ // mark the nodes reachable from the latches
+ Abc_NtkIncrementTravId(pNtk);
+ Abc_NtkForEachLatch( pNtk, pLatch, i )
+ {
+ if ( fForward )
+ {
+// assert( !Abc_ObjFanout0(pLatch)->fMarkA );
+ if ( fUseDirectedFlow )
+ RetValue = Abc_NtkMaxFlowFwdPath2_rec( Abc_ObjFanout0(pLatch) );
+// RetValue = Abc_NtkMaxFlowFwdPath3_rec( Abc_ObjFanout0(pLatch), pLatch, 1 );
+ else
+ RetValue = Abc_NtkMaxFlowFwdPath_rec( Abc_ObjFanout0(pLatch) );
+ }
+ else
+ {
+ assert( !Abc_ObjFanin0(pLatch)->fMarkA );
+ if ( fUseDirectedFlow )
+ RetValue = Abc_NtkMaxFlowBwdPath2_rec( Abc_ObjFanin0(pLatch) );
+ else
+ RetValue = Abc_NtkMaxFlowBwdPath_rec( Abc_ObjFanin0(pLatch) );
+ }
+ assert( RetValue == 0 );
+ }
+
+ // find the min-cut with the smallest volume
+ vMinCut = Abc_NtkMaxFlowMinCut( pNtk, fForward );
+ // verify the cut
+ if ( !Abc_NtkMaxFlowVerifyCut(pNtk, vMinCut, fForward) )
+ printf( "Abc_NtkMaxFlow() error! The computed min-cut is not a cut!\n" );
+ // make the cut retimable
+ Abc_NtkMaxFlowMinCutUpdate( pNtk, vMinCut, fForward );
+
+ // report the results
+ if ( fVerbose )
+ {
+ printf( "L = %6d. %s max-flow = %6d. Min-cut = %6d. ",
+ Abc_NtkLatchNum(pNtk), fForward? "Forward " : "Backward", Flow, Vec_PtrSize(vMinCut) );
+PRT( "Time", clock() - clk );
+ }
+
+// Abc_NtkMaxFlowPrintCut( pNtk, vMinCut );
+ return vMinCut;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Tries to find an augmenting path originating in this node.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Abc_NtkMaxFlowBwdPath_rec( Abc_Obj_t * pObj )
+{
+ Abc_Obj_t * pNext, * pPred;
+ int i;
+ // skip visited nodes
+ if ( Abc_NodeIsTravIdCurrent(pObj) )
+ return 0;
+ Abc_NodeSetTravIdCurrent(pObj);
+ // get the predecessor
+ pPred = Abc_ObjGetPredecessorBwd( pObj );
+ // process node without flow
+ if ( !Abc_ObjGetPath(pObj) )
+ {
+ // start the path if we reached a terminal node
+ if ( pObj->fMarkA )
+ return Abc_ObjSetPath( pObj, (void *)1 );
+ // explore the fanins
+ Abc_ObjForEachFanin( pObj, pNext, i )
+ if ( pNext != pPred && !Abc_ObjIsLatch(pNext) && Abc_NtkMaxFlowBwdPath_rec(pNext) )
+ return Abc_ObjSetPath( pObj, pNext );
+ Abc_ObjForEachFanout( pObj, pNext, i )
+ if ( pNext != pPred && !Abc_ObjIsLatch(pNext) && Abc_NtkMaxFlowBwdPath_rec(pNext) )
+ return Abc_ObjSetPath( pObj, pNext );
+ return 0;
+ }
+ // pObj has flow - find the fanout with flow
+ if ( pPred == NULL )
+ return 0;
+ // go through the successors of the predecessor
+ Abc_ObjForEachFanin( pPred, pNext, i )
+ if ( !Abc_ObjIsLatch(pNext) && Abc_NtkMaxFlowBwdPath_rec( pNext ) )
+ return Abc_ObjSetPath( pPred, pNext );
+ Abc_ObjForEachFanout( pPred, pNext, i )
+ if ( !Abc_ObjIsLatch(pNext) && Abc_NtkMaxFlowBwdPath_rec( pNext ) )
+ return Abc_ObjSetPath( pPred, pNext );
+ // try the fanout
+ if ( Abc_NtkMaxFlowBwdPath_rec( pPred ) )
+ return Abc_ObjSetPath( pPred, NULL );
+ return 0;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Tries to find an augmenting path originating in this node.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Abc_NtkMaxFlowFwdPath_rec( Abc_Obj_t * pObj )
+{
+ Abc_Obj_t * pNext, * pPred;
+ int i;
+ // skip visited nodes
+ if ( Abc_NodeIsTravIdCurrent(pObj) )
+ return 0;
+ Abc_NodeSetTravIdCurrent(pObj);
+ // get the predecessor
+ pPred = Abc_ObjGetPredecessorFwd( pObj );
+ // process node without flow
+ if ( !Abc_ObjGetPath(pObj) )
+ {
+ // start the path if we reached a terminal node
+ if ( pObj->fMarkA )
+ return Abc_ObjSetPath( pObj, (void *)1 );
+ // explore the fanins
+ Abc_ObjForEachFanout( pObj, pNext, i )
+ if ( pNext != pPred && !Abc_ObjIsLatch(pNext) && Abc_NtkMaxFlowFwdPath_rec(pNext) )
+ return Abc_ObjSetPath( pObj, pNext );
+ Abc_ObjForEachFanin( pObj, pNext, i )
+ if ( pNext != pPred && !Abc_ObjIsLatch(pNext) && Abc_NtkMaxFlowFwdPath_rec(pNext) )
+ return Abc_ObjSetPath( pObj, pNext );
+ return 0;
+ }
+ // pObj has flow - find the fanout with flow
+ if ( pPred == NULL )
+ return 0;
+ // go through the successors of the predecessor
+ Abc_ObjForEachFanout( pPred, pNext, i )
+ if ( !Abc_ObjIsLatch(pNext) && Abc_NtkMaxFlowFwdPath_rec( pNext ) )
+ return Abc_ObjSetPath( pPred, pNext );
+ Abc_ObjForEachFanin( pPred, pNext, i )
+ if ( !Abc_ObjIsLatch(pNext) && Abc_NtkMaxFlowFwdPath_rec( pNext ) )
+ return Abc_ObjSetPath( pPred, pNext );
+ // try the fanout
+ if ( Abc_NtkMaxFlowFwdPath_rec( pPred ) )
+ return Abc_ObjSetPath( pPred, NULL );
+ return 0;
+}
+
+
+/**Function*************************************************************
+
+ Synopsis [Tries to find an augmenting path originating in this edge.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Abc_NtkMaxFlowFwdPath3_rec( Abc_Obj_t * pObj, Abc_Obj_t * pPrev, int fFanin )
+{
+ Abc_Obj_t * pFanin, * pFanout;
+ int i;
+ // skip visited nodes
+ if ( Abc_NodeIsTravIdCurrent(pObj) )
+ return 0;
+ Abc_NodeSetTravIdCurrent(pObj);
+ // skip the fanin which already has flow
+ if ( fFanin && Abc_ObjGetPath(pPrev) )
+ return 0;
+ // if the node has no flow, try to push through the fanouts
+ if ( !Abc_ObjGetPath(pObj) )
+ {
+ // start the path if we reached a terminal node
+ if ( pObj->fMarkA )
+ return Abc_ObjSetPath( pObj, (void *)1 );
+ // try to push flow through the fanouts
+ Abc_ObjForEachFanout( pObj, pFanout, i )
+ if ( Abc_NtkMaxFlowFwdPath3_rec(pFanout, pObj, 1) )
+ return fFanin? Abc_ObjSetPath(pPrev, pObj) : 1;
+ }
+ // try to push through the fanins
+ Abc_ObjForEachFanin( pObj, pFanin, i )
+ if ( !Abc_ObjIsLatch(pFanin) && Abc_NtkMaxFlowFwdPath3_rec(pFanin, pObj, 0) )
+ return Abc_ObjSetPath( pFanin, NULL );
+ return 0;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Tries to find an augmenting path originating in this node.]
+
+ Description [This procedure works for directed graphs only!]
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Abc_NtkMaxFlowBwdPath2_rec( Abc_Obj_t * pObj )
+{
+ Abc_Obj_t * pFanout, * pFanin;
+ int i;
+ // skip visited nodes
+ if ( Abc_NodeIsTravIdCurrent(pObj) )
+ return 0;
+ Abc_NodeSetTravIdCurrent(pObj);
+ // process node without flow
+ if ( !Abc_ObjGetPath(pObj) )
+ {
+ // start the path if we reached a terminal node
+ if ( pObj->fMarkA )
+ return Abc_ObjSetPath( pObj, (void *)1 );
+ // explore the fanins
+ Abc_ObjForEachFanin( pObj, pFanin, i )
+ if ( Abc_NtkMaxFlowBwdPath2_rec(pFanin) )
+ return Abc_ObjSetPath( pObj, pFanin );
+ return 0;
+ }
+ // pObj has flow - find the fanout with flow
+ pFanout = Abc_ObjGetFanoutPath( pObj );
+ if ( pFanout == NULL )
+ return 0;
+ // go through the fanins of the fanout with flow
+ Abc_ObjForEachFanin( pFanout, pFanin, i )
+ if ( Abc_NtkMaxFlowBwdPath2_rec( pFanin ) )
+ return Abc_ObjSetPath( pFanout, pFanin );
+ // try the fanout
+ if ( Abc_NtkMaxFlowBwdPath2_rec( pFanout ) )
+ return Abc_ObjSetPath( pFanout, NULL );
+ return 0;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Tries to find an augmenting path originating in this node.]
+
+ Description [This procedure works for directed graphs only!]
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Abc_NtkMaxFlowFwdPath2_rec( Abc_Obj_t * pObj )
+{
+ Abc_Obj_t * pFanout, * pFanin;
+ int i;
+ // skip visited nodes
+ if ( Abc_NodeIsTravIdCurrent(pObj) )
+ return 0;
+ Abc_NodeSetTravIdCurrent(pObj);
+ // process node without flow
+ if ( !Abc_ObjGetPath(pObj) )
+ {
+ // start the path if we reached a terminal node
+ if ( pObj->fMarkA )
+ return Abc_ObjSetPath( pObj, (void *)1 );
+ // explore the fanins
+ Abc_ObjForEachFanout( pObj, pFanout, i )
+ if ( Abc_NtkMaxFlowFwdPath2_rec(pFanout) )
+ return Abc_ObjSetPath( pObj, pFanout );
+ return 0;
+ }
+ // pObj has flow - find the fanout with flow
+ pFanin = Abc_ObjGetFaninPath( pObj );
+ if ( pFanin == NULL )
+ return 0;
+ // go through the fanins of the fanout with flow
+ Abc_ObjForEachFanout( pFanin, pFanout, i )
+ if ( Abc_NtkMaxFlowFwdPath2_rec( pFanout ) )
+ return Abc_ObjSetPath( pFanin, pFanout );
+ // try the fanout
+ if ( Abc_NtkMaxFlowFwdPath2_rec( pFanin ) )
+ return Abc_ObjSetPath( pFanin, NULL );
+ return 0;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Find minimum-volume minumum cut.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Vec_Ptr_t * Abc_NtkMaxFlowMinCut( Abc_Ntk_t * pNtk, int fForward )
+{
+ Vec_Ptr_t * vMinCut;
+ Abc_Obj_t * pObj;
+ int i;
+ // collect the cut nodes
+ vMinCut = Vec_PtrAlloc( Abc_NtkLatchNum(pNtk) );
+ Abc_NtkForEachObj( pNtk, pObj, i )
+ {
+ // node without flow is not a cut node
+ if ( !Abc_ObjGetPath(pObj) )
+ continue;
+ // unvisited node is below the cut
+ if ( !Abc_NodeIsTravIdCurrent(pObj) )
+ continue;
+ // add terminal with flow or node whose path is not visited
+ if ( pObj->fMarkA || !Abc_NodeIsTravIdCurrent( Abc_ObjGetPath(pObj) ) )
+ Vec_PtrPush( vMinCut, pObj );
+ }
+ return vMinCut;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Marks the TFI cone with MarkA.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Abc_NtkMaxFlowMarkCut_rec( Abc_Obj_t * pObj )
+{
+ Abc_Obj_t * pNext;
+ int i;
+ if ( pObj->fMarkA )
+ return;
+ pObj->fMarkA = 1;
+ Abc_ObjForEachFanin( pObj, pNext, i )
+ Abc_NtkMaxFlowMarkCut_rec( pNext );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Visits the TFI up to marked nodes and collects marked nodes.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Abc_NtkMaxFlowCollectCut_rec( Abc_Obj_t * pObj, Vec_Ptr_t * vNodes )
+{
+ Abc_Obj_t * pNext;
+ int i;
+ if ( Abc_NodeIsTravIdCurrent(pObj) )
+ return;
+ Abc_NodeSetTravIdCurrent(pObj);
+ if ( pObj->fMarkA )
+ {
+ Vec_PtrPush( vNodes, pObj );
+ return;
+ }
+ Abc_ObjForEachFanin( pObj, pNext, i )
+ Abc_NtkMaxFlowCollectCut_rec( pNext, vNodes );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Updates the minimum cut to be retimable.]
+
+ Description [This procedure also labels the nodes reachable from
+ the latches to the cut with fMarkA.]
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Abc_NtkMaxFlowMinCutUpdate( Abc_Ntk_t * pNtk, Vec_Ptr_t * vMinCut, int fForward )
+{
+ Abc_Obj_t * pObj, * pNext;
+ int i, k;
+ // clean marks
+ Abc_NtkForEachObj( pNtk, pObj, i )
+ pObj->fMarkA = 0;
+ // set latch outputs
+ Abc_NtkForEachLatch( pNtk, pObj, i )
+ Abc_ObjFanout0(pObj)->fMarkA = 1;
+ // traverse from cut nodes
+ Vec_PtrForEachEntry( vMinCut, pObj, i )
+ Abc_NtkMaxFlowMarkCut_rec( pObj );
+ if ( fForward )
+ {
+ // change mincut to be nodes with unmarked fanouts
+ Vec_PtrClear( vMinCut );
+ Abc_NtkForEachObj( pNtk, pObj, i )
+ {
+ if ( !pObj->fMarkA )
+ continue;
+ Abc_ObjForEachFanout( pObj, pNext, k )
+ {
+ if ( pNext->fMarkA )
+ continue;
+ Vec_PtrPush( vMinCut, pObj );
+ break;
+ }
+ }
+ }
+ else
+ {
+ // change mincut to be marked fanins of the unmarked nodes
+ Vec_PtrClear( vMinCut );
+ Abc_NtkIncrementTravId(pNtk);
+ Abc_NtkForEachLatch( pNtk, pObj, i )
+ Abc_NtkMaxFlowCollectCut_rec( Abc_ObjFanin0(pObj), vMinCut );
+ // transfer the attribute
+ Abc_NtkForEachObj( pNtk, pObj, i )
+ pObj->fMarkA = Abc_NodeIsTravIdCurrent(pObj);
+ // unmark the cut nodes
+ Vec_PtrForEachEntry( vMinCut, pObj, i )
+ pObj->fMarkA = 0;
+ }
+}
+
+/**Function*************************************************************
+
+ Synopsis [Verifies the min-cut is indeed a cut.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Abc_NtkMaxFlowVerifyCut_rec( Abc_Obj_t * pObj, int fForward )
+{
+ Abc_Obj_t * pNext;
+ int i;
+ // skip visited nodes
+ if ( Abc_NodeIsTravIdCurrent(pObj) )
+ return 1;
+ Abc_NodeSetTravIdCurrent(pObj);
+ // visit the node
+ if ( fForward )
+ {
+ if ( Abc_ObjIsCo(pObj) )
+ return 0;
+ // explore the fanouts
+ Abc_ObjForEachFanout( pObj, pNext, i )
+ if ( !Abc_NtkMaxFlowVerifyCut_rec(pNext, fForward) )
+ return 0;
+ }
+ else
+ {
+ if ( Abc_ObjIsCi(pObj) )
+ return 0;
+ // explore the fanins
+ Abc_ObjForEachFanin( pObj, pNext, i )
+ if ( !Abc_NtkMaxFlowVerifyCut_rec(pNext, fForward) )
+ return 0;
+ }
+ return 1;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Verifies the min-cut is indeed a cut.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Abc_NtkMaxFlowVerifyCut( Abc_Ntk_t * pNtk, Vec_Ptr_t * vMinCut, int fForward )
+{
+ Abc_Obj_t * pObj;
+ int i;
+ // mark the cut with the current traversal ID
+ Abc_NtkIncrementTravId(pNtk);
+ Vec_PtrForEachEntry( vMinCut, pObj, i )
+ Abc_NodeSetTravIdCurrent( pObj );
+ // search from the latches for a path to the COs/CIs
+ Abc_NtkForEachLatch( pNtk, pObj, i )
+ {
+ if ( fForward )
+ {
+ if ( !Abc_NtkMaxFlowVerifyCut_rec( Abc_ObjFanout0(pObj), fForward ) )
+ return 0;
+ }
+ else
+ {
+ if ( !Abc_NtkMaxFlowVerifyCut_rec( Abc_ObjFanin0(pObj), fForward ) )
+ return 0;
+ }
+ }
+/*
+ {
+ // count the volume of the cut
+ int Counter = 0;
+ Abc_NtkForEachObj( pNtk, pObj, i )
+ Counter += Abc_NodeIsTravIdCurrent( pObj );
+ printf( "Volume = %d.\n", Counter );
+ }
+*/
+ return 1;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Prints the flows.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Abc_NtkMaxFlowPrintFlow( Abc_Ntk_t * pNtk, int fForward )
+{
+ Abc_Obj_t * pLatch, * pNext, * pPrev;
+ int i;
+ if ( fForward )
+ {
+ Vec_PtrForEachEntry( pNtk->vBoxes, pLatch, i )
+ {
+ assert( !Abc_ObjFanout0(pLatch)->fMarkA );
+ if ( Abc_ObjGetPath(Abc_ObjFanout0(pLatch)) == NULL ) // no flow through this latch
+ continue;
+ printf( "Path = " );
+ for ( pNext = Abc_ObjFanout0(pLatch); pNext != (void *)1; pNext = Abc_ObjGetPath(pNext) )
+ {
+ printf( "%s(%d) ", Abc_ObjName(pNext), pNext->Id );
+ pPrev = pNext;
+ }
+ if ( !Abc_ObjIsPo(pPrev) )
+ printf( "%s(%d) ", Abc_ObjName(Abc_ObjFanout0(pPrev)), Abc_ObjFanout0(pPrev)->Id );
+ printf( "\n" );
+ }
+ }
+ else
+ {
+ Vec_PtrForEachEntry( pNtk->vBoxes, pLatch, i )
+ {
+ assert( !Abc_ObjFanin0(pLatch)->fMarkA );
+ if ( Abc_ObjGetPath(Abc_ObjFanin0(pLatch)) == NULL ) // no flow through this latch
+ continue;
+ printf( "Path = " );
+ for ( pNext = Abc_ObjFanin0(pLatch); pNext != (void *)1; pNext = Abc_ObjGetPath(pNext) )
+ {
+ printf( "%s(%d) ", Abc_ObjName(pNext), pNext->Id );
+ pPrev = pNext;
+ }
+ if ( !Abc_ObjIsPi(pPrev) )
+ printf( "%s(%d) ", Abc_ObjName(Abc_ObjFanin0(pPrev)), Abc_ObjFanin0(pPrev)->Id );
+ printf( "\n" );
+ }
+ }
+}
+
+/**Function*************************************************************
+
+ Synopsis [Prints the min-cut.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Abc_NtkMaxFlowPrintCut( Abc_Ntk_t * pNtk, Vec_Ptr_t * vMinCut )
+{
+ Abc_Obj_t * pObj;
+ int i;
+ printf( "Min-cut: " );
+ Vec_PtrForEachEntry( vMinCut, pObj, i )
+ printf( "%s(%d) ", Abc_ObjName(pObj), pObj->Id );
+ printf( "\n" );
+ printf( "Marked nodes: " );
+ Abc_NtkForEachObj( pNtk, pObj, i )
+ if ( pObj->fMarkA )
+ printf( "%s(%d) ", Abc_ObjName(pObj), pObj->Id );
+ printf( "\n" );
+}
+
+
+////////////////////////////////////////////////////////////////////////
+/// END OF FILE ///
+////////////////////////////////////////////////////////////////////////
+
+
diff --git a/src/opt/ret/retIncrem.c b/src/opt/ret/retIncrem.c
new file mode 100644
index 00000000..ba8104be
--- /dev/null
+++ b/src/opt/ret/retIncrem.c
@@ -0,0 +1,464 @@
+/**CFile****************************************************************
+
+ FileName [retIncrem.c]
+
+ SystemName [ABC: Logic synthesis and verification system.]
+
+ PackageName [Retiming package.]
+
+ Synopsis [Incremental retiming in one direction.]
+
+ Author [Alan Mishchenko]
+
+ Affiliation [UC Berkeley]
+
+ Date [Ver. 1.0. Started - Oct 31, 2006.]
+
+ Revision [$Id: retIncrem.c,v 1.00 2006/10/31 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "retInt.h"
+
+////////////////////////////////////////////////////////////////////////
+/// DECLARATIONS ///
+////////////////////////////////////////////////////////////////////////
+
+static int Abc_NtkRetimeOneWay( Abc_Ntk_t * pNtk, int fForward, int fVerbose );
+
+////////////////////////////////////////////////////////////////////////
+/// FUNCTION DEFINITIONS ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+ Synopsis [Performs retiming in one direction.]
+
+ Description [Currently does not retime over black boxes.]
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Abc_NtkRetimeIncremental( Abc_Ntk_t * pNtk, int fForward, int fMinDelay, int fOneStep, int fVerbose )
+{
+ Abc_Ntk_t * pNtkCopy = NULL;
+ Vec_Ptr_t * vBoxes;
+ st_table * tLatches;
+ int nLatches = Abc_NtkLatchNum(pNtk);
+ int nIdMaxStart = Abc_NtkObjNumMax(pNtk);
+ int RetValue, nIterLimit;
+ if ( Abc_NtkNodeNum(pNtk) == 0 )
+ return 0;
+ // reorder CI/CO/latch inputs
+ Abc_NtkOrderCisCos( pNtk );
+ if ( fMinDelay )
+ {
+ nIterLimit = fOneStep? 1 : 2 * Abc_NtkLevel(pNtk);
+ pNtkCopy = Abc_NtkDup( pNtk );
+ tLatches = Abc_NtkRetimePrepareLatches( pNtkCopy );
+ st_free_table( tLatches );
+ }
+ // collect latches and remove CIs/COs
+ tLatches = Abc_NtkRetimePrepareLatches( pNtk );
+ // share the latches
+ Abc_NtkRetimeShareLatches( pNtk, 0 );
+ // save boxes
+ vBoxes = pNtk->vBoxes; pNtk->vBoxes = NULL;
+ // perform the retiming
+ if ( fMinDelay )
+ Abc_NtkRetimeMinDelay( pNtk, pNtkCopy, nIterLimit, fForward, fVerbose );
+ else
+ Abc_NtkRetimeOneWay( pNtk, fForward, fVerbose );
+ if ( fMinDelay )
+ Abc_NtkDelete( pNtkCopy );
+ // share the latches
+ Abc_NtkRetimeShareLatches( pNtk, 0 );
+ // restore boxes
+ pNtk->vBoxes = vBoxes;
+ // finalize the latches
+ RetValue = Abc_NtkRetimeFinalizeLatches( pNtk, tLatches, nIdMaxStart );
+ st_free_table( tLatches );
+ if ( RetValue == 0 )
+ return 0;
+ // fix the COs
+// Abc_NtkLogicMakeSimpleCos( pNtk, 0 );
+ // check for correctness
+ if ( !Abc_NtkCheck( pNtk ) )
+ fprintf( stdout, "Abc_NtkRetimeForward(): Network check has failed.\n" );
+ // return the number of latches saved
+ return nLatches - Abc_NtkLatchNum(pNtk);
+}
+
+/**Function*************************************************************
+
+ Synopsis [Prepares the network for retiming.]
+
+ Description [Hash latches into their number in the original network.]
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+st_table * Abc_NtkRetimePrepareLatches( Abc_Ntk_t * pNtk )
+{
+ st_table * tLatches;
+ Abc_Obj_t * pLatch, * pLatchIn, * pLatchOut, * pFanin;
+ int i, nOffSet = Abc_NtkBoxNum(pNtk) - Abc_NtkLatchNum(pNtk);
+ // collect latches and remove CIs/COs
+ tLatches = st_init_table( st_ptrcmp, st_ptrhash );
+ Abc_NtkForEachLatch( pNtk, pLatch, i )
+ {
+ // map latch into its true number
+ st_insert( tLatches, (void *)pLatch, (void *)(i-nOffSet) );
+ // disconnect LI
+ pLatchIn = Abc_ObjFanin0(pLatch);
+ pFanin = Abc_ObjFanin0(pLatchIn);
+ Abc_ObjTransferFanout( pLatchIn, pFanin );
+ Abc_ObjDeleteFanin( pLatchIn, pFanin );
+ // disconnect LO
+ pLatchOut = Abc_ObjFanout0(pLatch);
+ pFanin = Abc_ObjFanin0(pLatchOut);
+ if ( Abc_ObjFanoutNum(pLatchOut) > 0 )
+ Abc_ObjTransferFanout( pLatchOut, pFanin );
+ Abc_ObjDeleteFanin( pLatchOut, pFanin );
+ }
+ return tLatches;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Finalizes the latches after retiming.]
+
+ Description [Reuses the LIs/LOs for old latches.]
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Abc_NtkRetimeFinalizeLatches( Abc_Ntk_t * pNtk, st_table * tLatches, int nIdMaxStart )
+{
+ Vec_Ptr_t * vCisOld, * vCosOld, * vBoxesOld, * vCisNew, * vCosNew, * vBoxesNew;
+ Abc_Obj_t * pObj, * pLatch, * pLatchIn, * pLatchOut;
+ int i, Index;
+ // create new arrays
+ vCisOld = pNtk->vCis; pNtk->vCis = NULL; vCisNew = Vec_PtrAlloc( 100 );
+ vCosOld = pNtk->vCos; pNtk->vCos = NULL; vCosNew = Vec_PtrAlloc( 100 );
+ vBoxesOld = pNtk->vBoxes; pNtk->vBoxes = NULL; vBoxesNew = Vec_PtrAlloc( 100 );
+ // copy boxes and their CIs/COs
+ Vec_PtrForEachEntryStop( vCisOld, pObj, i, Vec_PtrSize(vCisOld) - st_count(tLatches) )
+ Vec_PtrPush( vCisNew, pObj );
+ Vec_PtrForEachEntryStop( vCosOld, pObj, i, Vec_PtrSize(vCosOld) - st_count(tLatches) )
+ Vec_PtrPush( vCosNew, pObj );
+ Vec_PtrForEachEntryStop( vBoxesOld, pObj, i, Vec_PtrSize(vBoxesOld) - st_count(tLatches) )
+ Vec_PtrPush( vBoxesNew, pObj );
+ // go through the latches
+ Abc_NtkForEachObj( pNtk, pLatch, i )
+ {
+ if ( !Abc_ObjIsLatch(pLatch) )
+ continue;
+ if ( Abc_ObjId(pLatch) >= (unsigned)nIdMaxStart )
+ {
+ // this is a new latch
+ pLatchIn = Abc_NtkCreateBi(pNtk);
+ pLatchOut = Abc_NtkCreateBo(pNtk);
+ Abc_ObjAssignName( pLatchOut, Abc_ObjName(pLatch), "_out" );
+ Abc_ObjAssignName( pLatchIn, Abc_ObjName(pLatch), "_in" );
+ }
+ else
+ {
+ // this is an old latch
+ // get its number in the original order
+ if ( !st_lookup( tLatches, (char *)pLatch, (char **)&Index ) )
+ {
+ printf( "Abc_NtkRetimeFinalizeLatches(): Internal error.\n" );
+ return 0;
+ }
+ assert( pLatch == Vec_PtrEntry(vBoxesOld, Vec_PtrSize(vBoxesOld) - st_count(tLatches) + Index) );
+ // reconnect with the old LIs/LOs
+ pLatchIn = Vec_PtrEntry( vCosOld, Vec_PtrSize(vCosOld) - st_count(tLatches) + Index );
+ pLatchOut = Vec_PtrEntry( vCisOld, Vec_PtrSize(vCisOld) - st_count(tLatches) + Index );
+ }
+ // connect
+ Abc_ObjAddFanin( pLatchIn, Abc_ObjFanin0(pLatch) );
+ Abc_ObjPatchFanin( pLatch, Abc_ObjFanin0(pLatch), pLatchIn );
+ if ( Abc_ObjFanoutNum(pLatch) > 0 )
+ Abc_ObjTransferFanout( pLatch, pLatchOut );
+ Abc_ObjAddFanin( pLatchOut, pLatch );
+ // add to the arrays
+ Vec_PtrPush( vCisNew, pLatchOut );
+ Vec_PtrPush( vCosNew, pLatchIn );
+ Vec_PtrPush( vBoxesNew, pLatch );
+ }
+ // free useless Cis/Cos
+ Vec_PtrForEachEntry( vCisOld, pObj, i )
+ if ( !Abc_ObjIsPi(pObj) && Abc_ObjFaninNum(pObj) == 0 && Abc_ObjFanoutNum(pObj) == 0 )
+ Abc_NtkDeleteObj(pObj);
+ Vec_PtrForEachEntry( vCosOld, pObj, i )
+ if ( !Abc_ObjIsPo(pObj) && Abc_ObjFaninNum(pObj) == 0 && Abc_ObjFanoutNum(pObj) == 0 )
+ Abc_NtkDeleteObj(pObj);
+ // set the new arrays
+ pNtk->vCis = vCisNew; Vec_PtrFree( vCisOld );
+ pNtk->vCos = vCosNew; Vec_PtrFree( vCosOld );
+ pNtk->vBoxes = vBoxesNew; Vec_PtrFree( vBoxesOld );
+ return 1;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Performs retiming one way, forward or backward.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Abc_NtkRetimeOneWay( Abc_Ntk_t * pNtk, int fForward, int fVerbose )
+{
+ Abc_Ntk_t * pNtkNew;
+ Vec_Int_t * vValues;
+ Abc_Obj_t * pObj;
+ int i, fChanges, nTotalMoves = 0, nTotalMovesLimit = 10000;
+ if ( fForward )
+ Abc_NtkRetimeTranferToCopy( pNtk );
+ else
+ {
+ // save initial values of the latches
+ vValues = Abc_NtkRetimeCollectLatchValues( pNtk );
+ // start the network for initial value computation
+ pNtkNew = Abc_NtkRetimeBackwardInitialStart( pNtk );
+ }
+ // try to move latches forward whenever possible
+ do {
+ fChanges = 0;
+ Abc_NtkForEachObj( pNtk, pObj, i )
+ {
+ if ( !Abc_ObjIsNode(pObj) )
+ continue;
+ if ( Abc_NtkRetimeNodeIsEnabled( pObj, fForward ) )
+ {
+ Abc_NtkRetimeNode( pObj, fForward, 1 );
+ fChanges = 1;
+ nTotalMoves++;
+ if ( nTotalMoves >= nTotalMovesLimit )
+ {
+ printf( "Stopped after %d latch moves.\n", nTotalMoves );
+ break;
+ }
+ }
+ }
+ } while ( fChanges && nTotalMoves < nTotalMovesLimit );
+ // transfer the initial state back to the latches
+ if ( fForward )
+ Abc_NtkRetimeTranferFromCopy( pNtk );
+ else
+ {
+ Abc_NtkRetimeBackwardInitialFinish( pNtk, pNtkNew, vValues, fVerbose );
+ Abc_NtkDelete( pNtkNew );
+ Vec_IntFree( vValues );
+ }
+ return 0;
+}
+
+
+/**Function*************************************************************
+
+ Synopsis [Returns 1 if retiming forward/backward is possible.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Abc_NtkRetimeNodeIsEnabled( Abc_Obj_t * pObj, int fForward )
+{
+ Abc_Obj_t * pNext;
+ int i;
+ assert( Abc_ObjIsNode(pObj) );
+ if ( fForward )
+ {
+ Abc_ObjForEachFanin( pObj, pNext, i )
+ if ( !Abc_ObjIsLatch(pNext) )
+ return 0;
+ }
+ else
+ {
+ Abc_ObjForEachFanout( pObj, pNext, i )
+ if ( !Abc_ObjIsLatch(pNext) )
+ return 0;
+ }
+ return 1;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Retimes the node backward or forward.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Abc_NtkRetimeNode( Abc_Obj_t * pObj, int fForward, int fInitial )
+{
+ Abc_Ntk_t * pNtkNew = NULL;
+ Vec_Ptr_t * vNodes;
+ Abc_Obj_t * pNext, * pLatch;
+ int i;
+ vNodes = Vec_PtrAlloc( 10 );
+ if ( fForward )
+ {
+ // compute the initial value
+ if ( fInitial )
+ pObj->pCopy = (void *)Abc_ObjSopSimulate( pObj );
+ // collect fanins
+ Abc_NodeCollectFanins( pObj, vNodes );
+ // make the node point to the fanins fanins
+ Vec_PtrForEachEntry( vNodes, pNext, i )
+ {
+ assert( Abc_ObjIsLatch(pNext) );
+ Abc_ObjPatchFanin( pObj, pNext, Abc_ObjFanin0(pNext) );
+ if ( Abc_ObjFanoutNum(pNext) == 0 )
+ Abc_NtkDeleteObj(pNext);
+ }
+ // add a new latch on top
+ pNext = Abc_NtkCreateLatch(pObj->pNtk);
+ if ( Abc_ObjFanoutNum(pObj) > 0 )
+ Abc_ObjTransferFanout( pObj, pNext );
+ Abc_ObjAddFanin( pNext, pObj );
+ // set the initial value
+ if ( fInitial )
+ pNext->pCopy = pObj->pCopy;
+ }
+ else
+ {
+ // compute the initial value
+ if ( fInitial )
+ {
+ pNtkNew = Abc_ObjFanout0(pObj)->pCopy->pNtk;
+ Abc_NtkDupObj( pNtkNew, pObj, 0 );
+ Abc_ObjForEachFanout( pObj, pNext, i )
+ {
+ assert( Abc_ObjFaninNum(pNext->pCopy) == 0 );
+ Abc_ObjAddFanin( pNext->pCopy, pObj->pCopy );
+ }
+ }
+ // collect fanouts
+ Abc_NodeCollectFanouts( pObj, vNodes );
+ // make the fanouts fanouts point to the node
+ Vec_PtrForEachEntry( vNodes, pNext, i )
+ {
+ assert( Abc_ObjIsLatch(pNext) );
+ Abc_ObjTransferFanout( pNext, pObj );
+ Abc_NtkDeleteObj( pNext );
+ }
+ // add new latches to the fanins
+ Abc_ObjForEachFanin( pObj, pNext, i )
+ {
+ pLatch = Abc_NtkCreateLatch(pObj->pNtk);
+ Abc_ObjPatchFanin( pObj, pNext, pLatch );
+ Abc_ObjAddFanin( pLatch, pNext );
+ // create buffer isomorphic to this latch
+ if ( fInitial )
+ {
+ pLatch->pCopy = Abc_NtkCreateNodeBuf( pNtkNew, NULL );
+ Abc_ObjAddFanin( pObj->pCopy, pLatch->pCopy );
+ }
+ }
+ }
+ Vec_PtrFree( vNodes );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Returns the number of compatible fanout latches.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Abc_NtkRetimeCheckCompatibleLatchFanouts( Abc_Obj_t * pObj )
+{
+ Abc_Obj_t * pFanout;
+ int i, nLatches = 0, Init = -1;
+ Abc_ObjForEachFanout( pObj, pFanout, i )
+ {
+ if ( !Abc_ObjIsLatch(pFanout) )
+ continue;
+ if ( Init == -1 )
+ {
+ Init = (int)pObj->pData;
+ nLatches++;
+ }
+ else if ( Init == (int)pObj->pData )
+ nLatches++;
+ }
+ return nLatches;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Retimes the node backward or forward.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Abc_NtkRetimeShareLatches( Abc_Ntk_t * pNtk, int fInitial )
+{
+ Vec_Ptr_t * vNodes;
+ Abc_Obj_t * pFanin, * pLatchTop, * pLatchCur;
+ int i, k;
+ vNodes = Vec_PtrAlloc( 10 );
+ // consider latch fanins
+ Abc_NtkForEachObj( pNtk, pFanin, i )
+ {
+ if ( Abc_NtkRetimeCheckCompatibleLatchFanouts(pFanin) <= 1 )
+ continue;
+ // get the first latch
+ pLatchTop = NULL;
+ Abc_ObjForEachFanout( pFanin, pLatchTop, k )
+ if ( Abc_ObjIsLatch(pLatchTop) )
+ break;
+ assert( pLatchTop && Abc_ObjIsLatch(pLatchTop) );
+ // redirect compatible fanout latches to the first latch
+ Abc_NodeCollectFanouts( pFanin, vNodes );
+ Vec_PtrForEachEntry( vNodes, pLatchCur, k )
+ {
+ if ( !Abc_ObjIsLatch(pLatchCur) )
+ continue;
+ if ( pLatchCur == pLatchTop )
+ continue;
+ if ( pLatchCur->pData != pLatchTop->pData )
+ continue;
+ // connect the initial state
+ if ( fInitial )
+ Abc_ObjAddFanin( pLatchCur->pCopy, pLatchTop->pCopy );
+ // redirect the fanouts
+ Abc_ObjTransferFanout( pLatchCur, pLatchTop );
+ Abc_NtkDeleteObj(pLatchCur);
+ }
+ }
+ Vec_PtrFree( vNodes );
+}
+
+////////////////////////////////////////////////////////////////////////
+/// END OF FILE ///
+////////////////////////////////////////////////////////////////////////
+
+
diff --git a/src/opt/ret/retInit.c b/src/opt/ret/retInit.c
new file mode 100644
index 00000000..dcb71c60
--- /dev/null
+++ b/src/opt/ret/retInit.c
@@ -0,0 +1,349 @@
+/**CFile****************************************************************
+
+ FileName [retInit.c]
+
+ SystemName [ABC: Logic synthesis and verification system.]
+
+ PackageName [Retiming package.]
+
+ Synopsis [Initial state computation for backward retiming.]
+
+ Author [Alan Mishchenko]
+
+ Affiliation [UC Berkeley]
+
+ Date [Ver. 1.0. Started - Oct 31, 2006.]
+
+ Revision [$Id: retInit.c,v 1.00 2006/10/31 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "retInt.h"
+
+////////////////////////////////////////////////////////////////////////
+/// DECLARATIONS ///
+////////////////////////////////////////////////////////////////////////
+
+static int Abc_NtkRetimeVerifyModel( Abc_Ntk_t * pNtkCone, Vec_Int_t * vValues, int * pModel );
+
+////////////////////////////////////////////////////////////////////////
+/// FUNCTION DEFINITIONS ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+ Synopsis [Computes initial values of the new latches.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Vec_Int_t * Abc_NtkRetimeInitialValues( Abc_Ntk_t * pNtkCone, Vec_Int_t * vValues, int fVerbose )
+{
+ Vec_Int_t * vSolution;
+ Abc_Ntk_t * pNtkMiter, * pNtkLogic;
+ int RetValue, clk;
+ if ( pNtkCone == NULL )
+ return Vec_IntDup( vValues );
+ // convert the target network to AIG
+ pNtkLogic = Abc_NtkDup( pNtkCone );
+ Abc_NtkToAig( pNtkLogic );
+ // get the miter
+ pNtkMiter = Abc_NtkCreateTarget( pNtkLogic, pNtkLogic->vCos, vValues );
+ if ( fVerbose )
+ printf( "The miter for initial state computation has %d AIG nodes. ", Abc_NtkNodeNum(pNtkMiter) );
+ // solve the miter
+ clk = clock();
+ RetValue = Abc_NtkMiterSat( pNtkMiter, (sint64)500000, (sint64)50000000, 0, NULL, NULL );
+ if ( fVerbose )
+ { PRT( "SAT solving time", clock() - clk ); }
+ // analyze the result
+ if ( RetValue == 1 )
+ printf( "Abc_NtkRetimeInitialValues(): The problem is unsatisfiable. DC latch values are used.\n" );
+ else if ( RetValue == -1 )
+ printf( "Abc_NtkRetimeInitialValues(): The SAT problem timed out. DC latch values are used.\n" );
+ else if ( !Abc_NtkRetimeVerifyModel( pNtkCone, vValues, pNtkMiter->pModel ) )
+ printf( "Abc_NtkRetimeInitialValues(): The computed counter-example is incorrect.\n" );
+ // set the values of the latches
+ vSolution = RetValue? NULL : Vec_IntAllocArray( pNtkMiter->pModel, Abc_NtkPiNum(pNtkLogic) );
+ pNtkMiter->pModel = NULL;
+ Abc_NtkDelete( pNtkMiter );
+ Abc_NtkDelete( pNtkLogic );
+ return vSolution;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Computes the results of simulating one node.]
+
+ Description [Assumes that fanins have pCopy set to the input values.]
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Abc_ObjSopSimulate( Abc_Obj_t * pObj )
+{
+ char * pCube, * pSop = pObj->pData;
+ int nVars, Value, v, ResOr, ResAnd, ResVar;
+ assert( pSop && !Abc_SopIsExorType(pSop) );
+ // simulate the SOP of the node
+ ResOr = 0;
+ nVars = Abc_SopGetVarNum(pSop);
+ Abc_SopForEachCube( pSop, nVars, pCube )
+ {
+ ResAnd = 1;
+ Abc_CubeForEachVar( pCube, Value, v )
+ {
+ if ( Value == '0' )
+ ResVar = 1 ^ ((int)Abc_ObjFanin(pObj, v)->pCopy);
+ else if ( Value == '1' )
+ ResVar = (int)Abc_ObjFanin(pObj, v)->pCopy;
+ else
+ continue;
+ ResAnd &= ResVar;
+ }
+ ResOr |= ResAnd;
+ }
+ // complement the result if necessary
+ if ( !Abc_SopGetPhase(pSop) )
+ ResOr ^= 1;
+ return ResOr;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Verifies the counter-example.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Abc_NtkRetimeVerifyModel( Abc_Ntk_t * pNtkCone, Vec_Int_t * vValues, int * pModel )
+{
+ Vec_Ptr_t * vNodes;
+ Abc_Obj_t * pObj;
+ int i, Counter = 0;
+ assert( Abc_NtkIsSopLogic(pNtkCone) );
+ // set the PIs
+ Abc_NtkForEachPi( pNtkCone, pObj, i )
+ pObj->pCopy = (void *)pModel[i];
+ // simulate the internal nodes
+ vNodes = Abc_NtkDfs( pNtkCone, 0 );
+ Vec_PtrForEachEntry( vNodes, pObj, i )
+ pObj->pCopy = (void *)Abc_ObjSopSimulate( pObj );
+ Vec_PtrFree( vNodes );
+ // compare the outputs
+ Abc_NtkForEachPo( pNtkCone, pObj, i )
+ pObj->pCopy = Abc_ObjFanin0(pObj)->pCopy;
+ Abc_NtkForEachPo( pNtkCone, pObj, i )
+ Counter += (Vec_IntEntry(vValues, i) != (int)pObj->pCopy);
+ if ( Counter > 0 )
+ printf( "%d outputs (out of %d) have a value mismatch.\n", Counter, Abc_NtkPoNum(pNtkCone) );
+ return 1;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Transfer latch initial values to pCopy.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Abc_NtkRetimeTranferToCopy( Abc_Ntk_t * pNtk )
+{
+ Abc_Obj_t * pObj;
+ int i;
+ Abc_NtkForEachObj( pNtk, pObj, i )
+ if ( Abc_ObjIsLatch(pObj) )
+ pObj->pCopy = (void *)Abc_LatchIsInit1(pObj);
+}
+
+/**Function*************************************************************
+
+ Synopsis [Transfer latch initial values from pCopy.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Abc_NtkRetimeTranferFromCopy( Abc_Ntk_t * pNtk )
+{
+ Abc_Obj_t * pObj;
+ int i;
+ Abc_NtkForEachObj( pNtk, pObj, i )
+ if ( Abc_ObjIsLatch(pObj) )
+ pObj->pData = (void *)(pObj->pCopy? ABC_INIT_ONE : ABC_INIT_ZERO);
+}
+
+/**Function*************************************************************
+
+ Synopsis [Transfer latch initial values to pCopy.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Vec_Int_t * Abc_NtkRetimeCollectLatchValues( Abc_Ntk_t * pNtk )
+{
+ Vec_Int_t * vValues;
+ Abc_Obj_t * pObj;
+ int i;
+ vValues = Vec_IntAlloc( Abc_NtkLatchNum(pNtk) );
+ Abc_NtkForEachObj( pNtk, pObj, i )
+ if ( Abc_ObjIsLatch(pObj) )
+ Vec_IntPush( vValues, Abc_LatchIsInit1(pObj) );
+ return vValues;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Transfer latch initial values from pCopy.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Abc_NtkRetimeInsertLatchValues( Abc_Ntk_t * pNtk, Vec_Int_t * vValues )
+{
+ Abc_Obj_t * pObj;
+ int i, Counter = 0;
+ Abc_NtkForEachObj( pNtk, pObj, i )
+ if ( Abc_ObjIsLatch(pObj) )
+ pObj->pCopy = (void *)Counter++;
+ Abc_NtkForEachObj( pNtk, pObj, i )
+ if ( Abc_ObjIsLatch(pObj) )
+ pObj->pData = (void *)(vValues? (Vec_IntEntry(vValues,(int)pObj->pCopy)? ABC_INIT_ONE : ABC_INIT_ZERO) : ABC_INIT_DC);
+}
+
+/**Function*************************************************************
+
+ Synopsis [Transfer latch initial values to pCopy.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Abc_Ntk_t * Abc_NtkRetimeBackwardInitialStart( Abc_Ntk_t * pNtk )
+{
+ Abc_Ntk_t * pNtkNew;
+ Abc_Obj_t * pObj;
+ int i;
+ // create the network used for the initial state computation
+ pNtkNew = Abc_NtkAlloc( ABC_NTK_LOGIC, ABC_FUNC_SOP, 1 );
+ // create POs corresponding to the initial values
+ Abc_NtkForEachObj( pNtk, pObj, i )
+ if ( Abc_ObjIsLatch(pObj) )
+ pObj->pCopy = Abc_NtkCreatePo(pNtkNew);
+ return pNtkNew;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Transfer latch initial values to pCopy.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Abc_NtkRetimeBackwardInitialFinish( Abc_Ntk_t * pNtk, Abc_Ntk_t * pNtkNew, Vec_Int_t * vValuesOld, int fVerbose )
+{
+ Vec_Int_t * vValuesNew;
+ Abc_Obj_t * pObj;
+ int i;
+ // create PIs corresponding to the initial values
+ Abc_NtkForEachObj( pNtk, pObj, i )
+ if ( Abc_ObjIsLatch(pObj) )
+ Abc_ObjAddFanin( pObj->pCopy, Abc_NtkCreatePi(pNtkNew) );
+ // assign dummy node names
+ Abc_NtkAddDummyPiNames( pNtkNew );
+ Abc_NtkAddDummyPoNames( pNtkNew );
+ // check the network
+ if ( !Abc_NtkCheck( pNtkNew ) )
+ fprintf( stdout, "Abc_NtkRetimeBackwardInitialFinish(): Network check has failed.\n" );
+ // derive new initial values
+ vValuesNew = Abc_NtkRetimeInitialValues( pNtkNew, vValuesOld, fVerbose );
+ // insert new initial values
+ Abc_NtkRetimeInsertLatchValues( pNtk, vValuesNew );
+ if ( vValuesNew ) Vec_IntFree( vValuesNew );
+}
+
+
+/**Function*************************************************************
+
+ Synopsis [Cycles the circuit to create a new initial state.]
+
+ Description [Simulates the circuit with random input for the given
+ number of timeframes to get a better initial state.]
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Abc_NtkCycleInitStateSop( Abc_Ntk_t * pNtk, int nFrames, int fVerbose )
+{
+ Vec_Ptr_t * vNodes;
+ Abc_Obj_t * pObj;
+ int i, f;
+ assert( Abc_NtkIsSopLogic(pNtk) );
+ srand( 0x12341234 );
+ // initialize the values
+ Abc_NtkForEachPi( pNtk, pObj, i )
+ pObj->pCopy = (void *)(rand() & 1);
+ Abc_NtkForEachLatch( pNtk, pObj, i )
+ pObj->pCopy = (void *)Abc_LatchIsInit1(pObj);
+ // simulate for the given number of timeframes
+ vNodes = Abc_NtkDfs( pNtk, 0 );
+ for ( f = 0; f < nFrames; f++ )
+ {
+ // simulate internal nodes
+ Vec_PtrForEachEntry( vNodes, pObj, i )
+ pObj->pCopy = (void *)Abc_ObjSopSimulate( pObj );
+ // bring the results to the COs
+ Abc_NtkForEachCo( pNtk, pObj, i )
+ pObj->pCopy = Abc_ObjFanin0(pObj)->pCopy;
+ // assign PI values
+ Abc_NtkForEachPi( pNtk, pObj, i )
+ pObj->pCopy = (void *)(rand() & 1);
+ // transfer the latch values
+ Abc_NtkForEachLatch( pNtk, pObj, i )
+ Abc_ObjFanout0(pObj)->pCopy = Abc_ObjFanin0(pObj)->pCopy;
+ }
+ Vec_PtrFree( vNodes );
+ // set the final values
+ Abc_NtkForEachLatch( pNtk, pObj, i )
+ pObj->pData = (void *)(Abc_ObjFanout0(pObj)->pCopy ? ABC_INIT_ONE : ABC_INIT_ZERO);
+}
+
+////////////////////////////////////////////////////////////////////////
+/// END OF FILE ///
+////////////////////////////////////////////////////////////////////////
+
+
diff --git a/src/opt/ret/retInt.h b/src/opt/ret/retInt.h
new file mode 100644
index 00000000..51428bce
--- /dev/null
+++ b/src/opt/ret/retInt.h
@@ -0,0 +1,80 @@
+/**CFile****************************************************************
+
+ FileName [retInt.h]
+
+ SystemName [ABC: Logic synthesis and verification system.]
+
+ PackageName [Retiming package.]
+
+ Synopsis [Internal declarations.]
+
+ Author [Alan Mishchenko]
+
+ Affiliation [UC Berkeley]
+
+ Date [Ver. 1.0. Started - Oct 31, 2006.]
+
+ Revision [$Id: retInt.h,v 1.00 2006/10/31 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#ifndef __RET_INT_H__
+#define __RET_INT_H__
+
+////////////////////////////////////////////////////////////////////////
+/// INCLUDES ///
+////////////////////////////////////////////////////////////////////////
+
+#include "abc.h"
+
+////////////////////////////////////////////////////////////////////////
+/// PARAMETERS ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+/// STRUCTURE DEFINITIONS ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+/// MACRO DEFINITIONS ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+/// FUNCTION DECLARATIONS ///
+////////////////////////////////////////////////////////////////////////
+
+/*=== retArea.c ========================================================*/
+extern int Abc_NtkRetimeMinArea( Abc_Ntk_t * pNtk, int fForwardOnly, int fBackwardOnly, int fVerbose );
+/*=== retCore.c ========================================================*/
+extern int Abc_NtkRetime( Abc_Ntk_t * pNtk, int Mode, int fForwardOnly, int fBackwardOnly, int fOneStep, int fVerbose );
+/*=== retDelay.c ========================================================*/
+extern int Abc_NtkRetimeMinDelay( Abc_Ntk_t * pNtk, Abc_Ntk_t * pNtkCopy, int nIterLimit, int fForward, int fVerbose );
+/*=== retDirect.c ========================================================*/
+extern int Abc_NtkRetimeIncremental( Abc_Ntk_t * pNtk, int fForward, int fMinDelay, int fOneStep, int fVerbose );
+extern void Abc_NtkRetimeShareLatches( Abc_Ntk_t * pNtk, int fInitial );
+extern int Abc_NtkRetimeNodeIsEnabled( Abc_Obj_t * pObj, int fForward );
+extern void Abc_NtkRetimeNode( Abc_Obj_t * pObj, int fForward, int fInitial );
+extern st_table * Abc_NtkRetimePrepareLatches( Abc_Ntk_t * pNtk );
+extern int Abc_NtkRetimeFinalizeLatches( Abc_Ntk_t * pNtk, st_table * tLatches, int nIdMaxStart );
+/*=== retFlow.c ========================================================*/
+extern void Abc_NtkMaxFlowTest( Abc_Ntk_t * pNtk );
+extern Vec_Ptr_t * Abc_NtkMaxFlow( Abc_Ntk_t * pNtk, int fForward, int fVerbose );
+/*=== retInit.c ========================================================*/
+extern Vec_Int_t * Abc_NtkRetimeInitialValues( Abc_Ntk_t * pNtkSat, Vec_Int_t * vValues, int fVerbose );
+extern int Abc_ObjSopSimulate( Abc_Obj_t * pObj );
+extern void Abc_NtkRetimeTranferToCopy( Abc_Ntk_t * pNtk );
+extern void Abc_NtkRetimeTranferFromCopy( Abc_Ntk_t * pNtk );
+extern Vec_Int_t * Abc_NtkRetimeCollectLatchValues( Abc_Ntk_t * pNtk );
+extern void Abc_NtkRetimeInsertLatchValues( Abc_Ntk_t * pNtk, Vec_Int_t * vValues );
+extern Abc_Ntk_t * Abc_NtkRetimeBackwardInitialStart( Abc_Ntk_t * pNtk );
+extern void Abc_NtkRetimeBackwardInitialFinish( Abc_Ntk_t * pNtk, Abc_Ntk_t * pNtkNew, Vec_Int_t * vValuesOld, int fVerbose );
+/*=== retLvalue.c ========================================================*/
+extern int Abc_NtkRetimeLValue( Abc_Ntk_t * pNtk, int nIterLimit, int fVerbose );
+
+#endif
+
+////////////////////////////////////////////////////////////////////////
+/// END OF FILE ///
+////////////////////////////////////////////////////////////////////////
+
+
diff --git a/src/opt/ret/retLvalue.c b/src/opt/ret/retLvalue.c
new file mode 100644
index 00000000..b4d9e946
--- /dev/null
+++ b/src/opt/ret/retLvalue.c
@@ -0,0 +1,395 @@
+/**CFile****************************************************************
+
+ FileName [retLvalue.c]
+
+ SystemName [ABC: Logic synthesis and verification system.]
+
+ PackageName [Retiming package.]
+
+ Synopsis [Implementation of Pan's retiming algorithm.]
+
+ Author [Alan Mishchenko]
+
+ Affiliation [UC Berkeley]
+
+ Date [Ver. 1.0. Started - Oct 31, 2006.]
+
+ Revision [$Id: retLvalue.c,v 1.00 2006/10/31 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "retInt.h"
+
+////////////////////////////////////////////////////////////////////////
+/// DECLARATIONS ///
+////////////////////////////////////////////////////////////////////////
+
+// node status after updating its arrival time
+enum { ABC_RET_UPDATE_FAIL, ABC_RET_UPDATE_NO, ABC_RET_UPDATE_YES };
+
+// the internal procedures
+static Vec_Int_t * Abc_NtkRetimeGetLags( Abc_Ntk_t * pNtk, int nIterLimit, int fVerbose );
+static int Abc_NtkRetimeSearch_rec( Abc_Ntk_t * pNtk, Vec_Ptr_t * vNodes, Vec_Ptr_t * vLatches, int FiMin, int FiMax, int nMaxIters, int fVerbose );
+static int Abc_NtkRetimeForPeriod( Abc_Ntk_t * pNtk, Vec_Ptr_t * vNodes, Vec_Ptr_t * vLatches, int Fi, int nMaxIters, int fVerbose );
+static int Abc_NtkRetimeUpdateLValue( Abc_Ntk_t * pNtk, Vec_Ptr_t * vNodes, Vec_Ptr_t * vLatches, int Fi );
+static int Abc_NtkRetimePosOverLimit( Abc_Ntk_t * pNtk, int Fi );
+static Vec_Ptr_t * Abc_ManCollectLatches( Abc_Ntk_t * pNtk );
+static int Abc_NtkRetimeUsingLags( Abc_Ntk_t * pNtk, Vec_Int_t * vLags, int fVerbose );
+
+static inline int Abc_NodeComputeLag( int LValue, int Fi ) { return (LValue + (1<<16)*Fi)/Fi - (1<<16) - (int)(LValue % Fi == 0); }
+static inline int Abc_NodeGetLValue( Abc_Obj_t * pNode ) { return (int)pNode->pCopy; }
+static inline void Abc_NodeSetLValue( Abc_Obj_t * pNode, int Value ) { pNode->pCopy = (void *)Value; }
+
+////////////////////////////////////////////////////////////////////////
+/// FUNCTION DEFINITIONS ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+ Synopsis [Implements Pan's retiming algorithm.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Abc_NtkRetimeLValue( Abc_Ntk_t * pNtk, int nIterLimit, int fVerbose )
+{
+ Vec_Int_t * vLags;
+ int nLatches = Abc_NtkLatchNum(pNtk);
+ assert( Abc_NtkIsLogic( pNtk ) );
+ // get the lags
+ vLags = Abc_NtkRetimeGetLags( pNtk, nIterLimit, fVerbose );
+ // compute the retiming
+// Abc_NtkRetimeUsingLags( pNtk, vLags, fVerbose );
+ Vec_IntFree( vLags );
+ // fix the COs
+// Abc_NtkLogicMakeSimpleCos( pNtk, 0 );
+ // check for correctness
+ if ( !Abc_NtkCheck( pNtk ) )
+ fprintf( stdout, "Abc_NtkRetimeLValue(): Network check has failed.\n" );
+ // return the number of latches saved
+ return nLatches - Abc_NtkLatchNum(pNtk);
+}
+
+/**Function*************************************************************
+
+ Synopsis [Computes the retiming lags.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Vec_Int_t * Abc_NtkRetimeGetLags( Abc_Ntk_t * pNtk, int nIterLimit, int fVerbose )
+{
+ Vec_Int_t * vLags;
+ Vec_Ptr_t * vNodes, * vLatches;
+ Abc_Obj_t * pNode;
+ int i, FiMax, FiBest, RetValue, clk, clkIter;
+ char NodeLag;
+
+ // get the upper bound on the clock period
+ FiMax = Abc_NtkLevel(pNtk);
+
+ // make sure this clock period is feasible
+ vNodes = Abc_NtkDfs( pNtk, 0 );
+ vLatches = Abc_ManCollectLatches( pNtk );
+ if ( !Abc_NtkRetimeForPeriod( pNtk, vNodes, vLatches, FiMax, nIterLimit, fVerbose ) )
+ {
+ Vec_PtrFree( vNodes );
+ printf( "Abc_NtkRetimeGetLags() error: The upper bound on the clock period cannot be computed.\n" );
+ return Vec_IntStart( Abc_NtkObjNumMax(pNtk) + 1 );
+ }
+
+ // search for the optimal clock period between 0 and nLevelMax
+clk = clock();
+ FiBest = Abc_NtkRetimeSearch_rec( pNtk, vNodes, vLatches, 0, FiMax, nIterLimit, fVerbose );
+clkIter = clock() - clk;
+
+ // recompute the best l-values
+ RetValue = Abc_NtkRetimeForPeriod( pNtk, vNodes, vLatches, FiBest, nIterLimit, fVerbose );
+ assert( RetValue );
+
+ // fix the problem with non-converged delays
+ Abc_NtkForEachNode( pNtk, pNode, i )
+ if ( Abc_NodeGetLValue(pNode) < -ABC_INFINITY/2 )
+ Abc_NodeSetLValue( pNode, 0 );
+
+ // write the retiming lags
+ vLags = Vec_IntStart( Abc_NtkObjNumMax(pNtk) + 1 );
+ Abc_NtkForEachNode( pNtk, pNode, i )
+ {
+ NodeLag = Abc_NodeComputeLag( Abc_NodeGetLValue(pNode), FiBest );
+ Vec_IntWriteEntry( vLags, pNode->Id, NodeLag );
+ }
+/*
+ Abc_NtkForEachPo( pNtk, pNode, i )
+ printf( "%d ", Abc_NodeGetLValue(Abc_ObjFanin0(pNode)) );
+ printf( "\n" );
+ Abc_NtkForEachLatch( pNtk, pNode, i )
+ printf( "%d/%d ", Abc_NodeGetLValue(Abc_ObjFanout0(pNode)), Abc_NodeGetLValue(Abc_ObjFanout0(pNode)) + FiBest );
+ printf( "\n" );
+*/
+
+ // print the result
+// if ( fVerbose )
+ printf( "The best clock period is %3d. (Currently, network is not modified.)\n", FiBest );
+/*
+ {
+ FILE * pTable;
+ pTable = fopen( "iscas/seqmap__stats2.txt", "a+" );
+ fprintf( pTable, "%d ", FiBest );
+ fprintf( pTable, "\n" );
+ fclose( pTable );
+ }
+*/
+ Vec_PtrFree( vNodes );
+ Vec_PtrFree( vLatches );
+ return vLags;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Performs binary search for the optimal clock period.]
+
+ Description [Assumes that FiMin is infeasible while FiMax is feasible.]
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Abc_NtkRetimeSearch_rec( Abc_Ntk_t * pNtk, Vec_Ptr_t * vNodes, Vec_Ptr_t * vLatches, int FiMin, int FiMax, int nMaxIters, int fVerbose )
+{
+ int Median;
+ assert( FiMin < FiMax );
+ if ( FiMin + 1 == FiMax )
+ return FiMax;
+ Median = FiMin + (FiMax - FiMin)/2;
+ if ( Abc_NtkRetimeForPeriod( pNtk, vNodes, vLatches, Median, nMaxIters, fVerbose ) )
+ return Abc_NtkRetimeSearch_rec( pNtk, vNodes, vLatches, FiMin, Median, nMaxIters, fVerbose ); // Median is feasible
+ else
+ return Abc_NtkRetimeSearch_rec( pNtk, vNodes, vLatches, Median, FiMax, nMaxIters, fVerbose ); // Median is infeasible
+}
+
+/**Function*************************************************************
+
+ Synopsis [Returns 1 if retiming with this clock period is feasible.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Abc_NtkRetimeForPeriod( Abc_Ntk_t * pNtk, Vec_Ptr_t * vNodes, Vec_Ptr_t * vLatches, int Fi, int nMaxIters, int fVerbose )
+{
+ Abc_Obj_t * pObj;
+ int c, i, fConverged;
+ // set l-values of all nodes to be minus infinity, except PIs and constants
+ Abc_NtkForEachObj( pNtk, pObj, i )
+ if ( Abc_ObjFaninNum(pObj) == 0 )
+ Abc_NodeSetLValue( pObj, 0 );
+ else
+ Abc_NodeSetLValue( pObj, -ABC_INFINITY );
+ // update all values iteratively
+ fConverged = 0;
+ for ( c = 1; c <= nMaxIters; c++ )
+ {
+ if ( !Abc_NtkRetimeUpdateLValue( pNtk, vNodes, vLatches, Fi ) )
+ {
+ fConverged = 1;
+ break;
+ }
+ if ( Abc_NtkRetimePosOverLimit(pNtk, Fi) )
+ break;
+ }
+ // report the results
+ if ( fVerbose )
+ {
+ if ( !fConverged )
+ printf( "Period = %3d. Iterations = %3d. Infeasible %s\n", Fi, c, (c > nMaxIters)? "(timeout)" : "" );
+ else
+ printf( "Period = %3d. Iterations = %3d. Feasible\n", Fi, c );
+ }
+/*
+ // check if any AND gates have infinite delay
+ Counter = 0;
+ Abc_NtkForEachNode( pNtk, pObj, i )
+ Counter += (Abc_NodeGetLValue(pObj) < -ABC_INFINITY/2);
+ if ( Counter > 0 )
+ printf( "Warning: %d internal nodes have wrong l-values!\n", Counter );
+*/
+ return fConverged;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Performs one iteration of l-value computation for the nodes.]
+
+ Description [Experimentally it was found that checking POs changes
+ is not enough to detect the convergence of l-values in the network.]
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Abc_NtkRetimeUpdateLValue( Abc_Ntk_t * pNtk, Vec_Ptr_t * vNodes, Vec_Ptr_t * vLatches, int Fi )
+{
+ Abc_Obj_t * pObj, * pFanin;
+ int i, k, lValueNew, fChange;
+ // go through the nodes and detect change
+ fChange = 0;
+ Vec_PtrForEachEntry( vNodes, pObj, i )
+ {
+ assert( Abc_ObjIsNode(pObj) );
+ lValueNew = -ABC_INFINITY;
+ Abc_ObjForEachFanin( pObj, pFanin, k )
+ {
+ if ( lValueNew < Abc_NodeGetLValue(pFanin) )
+ lValueNew = Abc_NodeGetLValue(pFanin);
+ }
+ lValueNew++;
+ if ( Abc_NodeGetLValue(pObj) < lValueNew )
+ {
+ Abc_NodeSetLValue( pObj, lValueNew );
+ fChange = 1;
+ }
+ }
+ // propagate values through the latches
+ Vec_PtrForEachEntry( vLatches, pObj, i )
+ Abc_NodeSetLValue( Abc_ObjFanout0(pObj), Abc_NodeGetLValue(Abc_ObjFanin0(Abc_ObjFanin0(pObj))) - Fi );
+ return fChange;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Detects the case when l-values exceeded the limit.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Abc_NtkRetimePosOverLimit( Abc_Ntk_t * pNtk, int Fi )
+{
+ Abc_Obj_t * pObj;
+ int i;
+ Abc_NtkForEachPo( pNtk, pObj, i )
+ if ( Abc_NodeGetLValue(Abc_ObjFanin0(pObj)) > Fi )
+ return 1;
+ return 0;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Collects latches in the topological order.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Abc_ManCollectLatches_rec( Abc_Obj_t * pObj, Vec_Ptr_t * vLatches )
+{
+ Abc_Obj_t * pDriver;
+ if ( !Abc_ObjIsLatch(pObj) )
+ return;
+ // skip already collected latches
+ if ( Abc_NodeIsTravIdCurrent(pObj) )
+ return;
+ Abc_NodeSetTravIdCurrent(pObj);
+ // get the driver node feeding into the latch
+ pDriver = Abc_ObjFanin0(Abc_ObjFanin0(pObj));
+ // call recursively if the driver looks like a latch output
+ if ( Abc_ObjIsBo(pDriver) )
+ Abc_ManCollectLatches_rec( Abc_ObjFanin0(pDriver), vLatches );
+ // collect the latch
+ Vec_PtrPush( vLatches, pObj );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Collects latches in the topological order.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Vec_Ptr_t * Abc_ManCollectLatches( Abc_Ntk_t * pNtk )
+{
+ Vec_Ptr_t * vLatches;
+ Abc_Obj_t * pObj;
+ int i;
+ vLatches = Vec_PtrAlloc( Abc_NtkLatchNum(pNtk) );
+ Abc_NtkIncrementTravId( pNtk );
+ Abc_NtkForEachLatch( pNtk, pObj, i )
+ Abc_ManCollectLatches_rec( pObj, vLatches );
+ assert( Vec_PtrSize(vLatches) == Abc_NtkLatchNum(pNtk) );
+ return vLatches;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Implements the retiming given as the array of retiming lags.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Abc_NtkRetimeUsingLags( Abc_Ntk_t * pNtk, Vec_Int_t * vLags, int fVerbose )
+{
+ Abc_Obj_t * pObj;
+ int fChanges, fForward, nTotalMoves, Lag, Counter, i;
+ // iterate over the nodes
+ nTotalMoves = 0;
+ do {
+ fChanges = 0;
+ Abc_NtkForEachNode( pNtk, pObj, i )
+ {
+ Lag = Vec_IntEntry( vLags, pObj->Id );
+ if ( !Lag )
+ continue;
+ fForward = (Lag < 0);
+ if ( Abc_NtkRetimeNodeIsEnabled( pObj, fForward ) )
+ {
+ Abc_NtkRetimeNode( pObj, fForward, 0 );
+ fChanges = 1;
+ nTotalMoves++;
+ Vec_IntAddToEntry( vLags, pObj->Id, fForward? 1 : -1 );
+ }
+ }
+ } while ( fChanges );
+ if ( fVerbose )
+ printf( "Total latch moves = %d.\n", nTotalMoves );
+ // check if there are remaining lags
+ Counter = 0;
+ Abc_NtkForEachNode( pNtk, pObj, i )
+ Counter += (Vec_IntEntry( vLags, pObj->Id ) != 0);
+ if ( Counter )
+ printf( "Warning! The number of nodes with unrealized lag = %d.\n", Counter );
+ return 1;
+}
+
+////////////////////////////////////////////////////////////////////////
+/// END OF FILE ///
+////////////////////////////////////////////////////////////////////////
+
+
diff --git a/src/opt/ret/ret_.c b/src/opt/ret/ret_.c
new file mode 100644
index 00000000..89625e17
--- /dev/null
+++ b/src/opt/ret/ret_.c
@@ -0,0 +1,48 @@
+/**CFile****************************************************************
+
+ FileName [ret_.c]
+
+ SystemName [ABC: Logic synthesis and verification system.]
+
+ PackageName [Retiming package.]
+
+ Synopsis []
+
+ Author [Alan Mishchenko]
+
+ Affiliation [UC Berkeley]
+
+ Date [Ver. 1.0. Started - Oct 31, 2006.]
+
+ Revision [$Id: ret_.c,v 1.00 2006/10/31 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "retInt.h"
+
+////////////////////////////////////////////////////////////////////////
+/// DECLARATIONS ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+/// FUNCTION DEFINITIONS ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+
+
+////////////////////////////////////////////////////////////////////////
+/// END OF FILE ///
+////////////////////////////////////////////////////////////////////////
+
+
diff --git a/src/opt/rwr/rwr.h b/src/opt/rwr/rwr.h
index 6d1a6c06..f24f9535 100644
--- a/src/opt/rwr/rwr.h
+++ b/src/opt/rwr/rwr.h
@@ -21,6 +21,10 @@
#ifndef __RWR_H__
#define __RWR_H__
+#ifdef __cplusplus
+extern "C" {
+#endif
+
////////////////////////////////////////////////////////////////////////
/// INCLUDES ///
////////////////////////////////////////////////////////////////////////
@@ -49,6 +53,7 @@ struct Rwr_Man_t_
char * pPhases; // canonical phases
char * pPerms; // canonical permutations
unsigned char * pMap; // mapping of functions into class numbers
+ unsigned short * pMapInv; // mapping of classes into functions
char * pPractical; // practical NPN classes
char ** pPerms4; // four-var permutations
// node space
@@ -63,14 +68,17 @@ struct Rwr_Man_t_
int nClasses; // the number of NN classes
// the result of resynthesis
int fCompl; // indicates if the output of FF should be complemented
- void * pGraph; // the decomposition tree (temporary)
+ void * pGraph; // the decomposition tree (temporary)
Vec_Ptr_t * vFanins; // the fanins array (temporary)
Vec_Ptr_t * vFaninsCur; // the fanins array (temporary)
Vec_Int_t * vLevNums; // the array of levels (temporary)
+ Vec_Ptr_t * vNodesTemp; // the nodes in MFFC (temporary)
// node statistics
int nNodesConsidered;
int nNodesRewritten;
int nNodesGained;
+ int nNodesBeg;
+ int nNodesEnd;
int nScores[222];
int nCutsGood;
int nCutsBad;
@@ -80,6 +88,8 @@ struct Rwr_Man_t_
int timeCut;
int timeRes;
int timeEval;
+ int timeMffc;
+ int timeUpdate;
int timeTotal;
};
@@ -87,6 +97,9 @@ struct Rwr_Node_t_ // 24 bytes
{
int Id; // ID
int TravId; // traversal ID
+ short nScore;
+ short nGain;
+ short nAdded;
unsigned uTruth : 16; // truth table
unsigned Volume : 8; // volume
unsigned Level : 6; // level
@@ -98,13 +111,13 @@ struct Rwr_Node_t_ // 24 bytes
};
// manipulation of complemented attributes
-static inline bool Rwr_IsComplement( Rwr_Node_t * p ) { return (bool)(((unsigned)p) & 01); }
-static inline Rwr_Node_t * Rwr_Regular( Rwr_Node_t * p ) { return (Rwr_Node_t *)((unsigned)(p) & ~01); }
-static inline Rwr_Node_t * Rwr_Not( Rwr_Node_t * p ) { return (Rwr_Node_t *)((unsigned)(p) ^ 01); }
-static inline Rwr_Node_t * Rwr_NotCond( Rwr_Node_t * p, int c ) { return (Rwr_Node_t *)((unsigned)(p) ^ (c)); }
+static inline bool Rwr_IsComplement( Rwr_Node_t * p ) { return (bool)(((unsigned long)p) & 01); }
+static inline Rwr_Node_t * Rwr_Regular( Rwr_Node_t * p ) { return (Rwr_Node_t *)((unsigned long)(p) & ~01); }
+static inline Rwr_Node_t * Rwr_Not( Rwr_Node_t * p ) { return (Rwr_Node_t *)((unsigned long)(p) ^ 01); }
+static inline Rwr_Node_t * Rwr_NotCond( Rwr_Node_t * p, int c ) { return (Rwr_Node_t *)((unsigned long)(p) ^ (c)); }
////////////////////////////////////////////////////////////////////////
-/// MACRO DEFITIONS ///
+/// MACRO DEFINITIONS ///
////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////
@@ -114,7 +127,9 @@ static inline Rwr_Node_t * Rwr_NotCond( Rwr_Node_t * p, int c ) { return (Rwr_N
/*=== rwrDec.c ========================================================*/
extern void Rwr_ManPreprocess( Rwr_Man_t * p );
/*=== rwrEva.c ========================================================*/
-extern int Rwr_NodeRewrite( Rwr_Man_t * p, Cut_Man_t * pManCut, Abc_Obj_t * pNode, int fUseZeros );
+extern int Rwr_NodeRewrite( Rwr_Man_t * p, Cut_Man_t * pManCut, Abc_Obj_t * pNode, int fUpdateLevel, int fUseZeros, int fPlaceEnable );
+extern void Rwr_ScoresClean( Rwr_Man_t * p );
+extern void Rwr_ScoresReport( Rwr_Man_t * p );
/*=== rwrLib.c ========================================================*/
extern void Rwr_ManPrecompute( Rwr_Man_t * p );
extern Rwr_Node_t * Rwr_ManAddVar( Rwr_Man_t * p, unsigned uTruth, int fPrecompute );
@@ -125,9 +140,12 @@ extern void Rwr_ManIncTravId( Rwr_Man_t * p );
extern Rwr_Man_t * Rwr_ManStart( bool fPrecompute );
extern void Rwr_ManStop( Rwr_Man_t * p );
extern void Rwr_ManPrintStats( Rwr_Man_t * p );
+extern void Rwr_ManPrintStatsFile( Rwr_Man_t * p );
extern void * Rwr_ManReadDecs( Rwr_Man_t * p );
+extern Vec_Ptr_t * Rwr_ManReadLeaves( Rwr_Man_t * p );
extern int Rwr_ManReadCompl( Rwr_Man_t * p );
extern void Rwr_ManAddTimeCuts( Rwr_Man_t * p, int Time );
+extern void Rwr_ManAddTimeUpdate( Rwr_Man_t * p, int Time );
extern void Rwr_ManAddTimeTotal( Rwr_Man_t * p, int Time );
/*=== rwrPrint.c ========================================================*/
extern void Rwr_ManPrint( Rwr_Man_t * p );
@@ -139,9 +157,13 @@ extern void Rwr_ManLoadFromFile( Rwr_Man_t * p, char * pFileName );
extern void Rwr_ListAddToTail( Rwr_Node_t ** ppList, Rwr_Node_t * pNode );
extern char * Rwr_ManGetPractical( Rwr_Man_t * p );
+#ifdef __cplusplus
+}
+#endif
+
+#endif
+
////////////////////////////////////////////////////////////////////////
/// END OF FILE ///
////////////////////////////////////////////////////////////////////////
-#endif
-
diff --git a/src/opt/rwr/rwrDec.c b/src/opt/rwr/rwrDec.c
index d072879d..ef7af34f 100644
--- a/src/opt/rwr/rwrDec.c
+++ b/src/opt/rwr/rwrDec.c
@@ -29,7 +29,7 @@ static Dec_Graph_t * Rwr_NodePreprocess( Rwr_Man_t * p, Rwr_Node_t * pNode );
static Dec_Edge_t Rwr_TravCollect_rec( Rwr_Man_t * p, Rwr_Node_t * pNode, Dec_Graph_t * pGraph );
////////////////////////////////////////////////////////////////////////
-/// FUNCTION DEFITIONS ///
+/// FUNCTION DEFINITIONS ///
////////////////////////////////////////////////////////////////////////
/**Function*************************************************************
@@ -49,6 +49,8 @@ void Rwr_ManPreprocess( Rwr_Man_t * p )
Rwr_Node_t * pNode;
int i, k;
// put the nodes into the structure
+ p->pMapInv = ALLOC( unsigned short, 222 );
+ memset( p->pMapInv, 0, sizeof(unsigned short) * 222 );
p->vClasses = Vec_VecStart( 222 );
for ( i = 0; i < p->nFuncs; i++ )
{
@@ -60,6 +62,7 @@ void Rwr_ManPreprocess( Rwr_Man_t * p )
assert( pNode->uTruth == p->pTable[i]->uTruth );
assert( p->pMap[pNode->uTruth] >= 0 && p->pMap[pNode->uTruth] < 222 );
Vec_VecPush( p->vClasses, p->pMap[pNode->uTruth], pNode );
+ p->pMapInv[ p->pMap[pNode->uTruth] ] = p->puCanons[pNode->uTruth];
}
}
// compute decomposition forms for each node and verify them
@@ -132,7 +135,7 @@ Dec_Edge_t Rwr_TravCollect_rec( Rwr_Man_t * p, Rwr_Node_t * pNode, Dec_Graph_t *
eNode1.fCompl = !eNode1.fCompl;
// create the decomposition node(s)
if ( pNode->fExor )
- eNode = Dec_GraphAddNodeXor( pGraph, eNode0, eNode1 );
+ eNode = Dec_GraphAddNodeXor( pGraph, eNode0, eNode1, 0 );
else
eNode = Dec_GraphAddNodeAnd( pGraph, eNode0, eNode1 );
// save the result
diff --git a/src/opt/rwr/rwrEva.c b/src/opt/rwr/rwrEva.c
index c934dfd8..396a659c 100644
--- a/src/opt/rwr/rwrEva.c
+++ b/src/opt/rwr/rwrEva.c
@@ -25,10 +25,13 @@
/// DECLARATIONS ///
////////////////////////////////////////////////////////////////////////
-static Dec_Graph_t * Rwr_CutEvaluate( Rwr_Man_t * p, Abc_Obj_t * pRoot, Cut_Cut_t * pCut, Vec_Ptr_t * vFaninsCur, int nNodesSaved, int LevelMax, int * pGainBest );
+static Dec_Graph_t * Rwr_CutEvaluate( Rwr_Man_t * p, Abc_Obj_t * pRoot, Cut_Cut_t * pCut, Vec_Ptr_t * vFaninsCur, int nNodesSaved, int LevelMax, int * pGainBest, int fPlaceEnable );
+static int Rwr_CutIsBoolean( Abc_Obj_t * pObj, Vec_Ptr_t * vLeaves );
+static int Rwr_CutCountNumNodes( Abc_Obj_t * pObj, Cut_Cut_t * pCut );
+static int Rwr_NodeGetDepth_rec( Abc_Obj_t * pObj, Vec_Ptr_t * vLeaves );
////////////////////////////////////////////////////////////////////////
-/// FUNCTION DEFITIONS ///
+/// FUNCTION DEFINITIONS ///
////////////////////////////////////////////////////////////////////////
/**Function*************************************************************
@@ -49,27 +52,35 @@ static Dec_Graph_t * Rwr_CutEvaluate( Rwr_Man_t * p, Abc_Obj_t * pRoot, Cut_Cut_
SeeAlso []
***********************************************************************/
-int Rwr_NodeRewrite( Rwr_Man_t * p, Cut_Man_t * pManCut, Abc_Obj_t * pNode, int fUseZeros )
+int Rwr_NodeRewrite( Rwr_Man_t * p, Cut_Man_t * pManCut, Abc_Obj_t * pNode, int fUpdateLevel, int fUseZeros, int fPlaceEnable )
{
int fVeryVerbose = 0;
Dec_Graph_t * pGraph;
- Cut_Cut_t * pCut;
+ Cut_Cut_t * pCut;//, * pTemp;
Abc_Obj_t * pFanin;
- unsigned uPhase, uTruthBest;
+ unsigned uPhase, uTruthBest, uTruth;
char * pPerm;
- int Required, nNodesSaved;
+ int Required, nNodesSaved, nNodesSaveCur;
int i, GainCur, GainBest = -1;
- int clk, clk2;
+ int clk, clk2;//, Counter;
p->nNodesConsidered++;
// get the required times
- Required = Abc_NodeReadRequiredLevel( pNode );
+ Required = fUpdateLevel? Abc_ObjRequiredLevel(pNode) : ABC_INFINITY;
+
// get the node's cuts
clk = clock();
- pCut = (Cut_Cut_t *)Abc_NodeGetCutsRecursive( pManCut, pNode );
+ pCut = (Cut_Cut_t *)Abc_NodeGetCutsRecursive( pManCut, pNode, 0, 0 );
assert( pCut != NULL );
p->timeCut += clock() - clk;
+//printf( " %d", Rwr_CutCountNumNodes(pNode, pCut) );
+/*
+ Counter = 0;
+ for ( pTemp = pCut->pNext; pTemp; pTemp = pTemp->pNext )
+ Counter++;
+ printf( "%d ", Counter );
+*/
// go through the cuts
clk = clock();
for ( pCut = pCut->pNext; pCut; pCut = pCut->pNext )
@@ -77,9 +88,12 @@ clk = clock();
// consider only 4-input cuts
if ( pCut->nLeaves < 4 )
continue;
+// Cut_CutPrint( pCut, 0 ), printf( "\n" );
+
// get the fanin permutation
- pPerm = p->pPerms4[ p->pPerms[pCut->uTruth] ];
- uPhase = p->pPhases[pCut->uTruth];
+ uTruth = 0xFFFF & *Cut_CutReadTruth(pCut);
+ pPerm = p->pPerms4[ p->pPerms[uTruth] ];
+ uPhase = p->pPhases[uTruth];
// collect fanins with the corresponding permutation/phase
Vec_PtrClear( p->vFaninsCur );
Vec_PtrFill( p->vFaninsCur, (int)pCut->nLeaves, 0 );
@@ -98,29 +112,48 @@ clk = clock();
}
p->nCutsGood++;
+ {
+ int Counter = 0;
+ Vec_PtrForEachEntry( p->vFaninsCur, pFanin, i )
+ if ( Abc_ObjFanoutNum(Abc_ObjRegular(pFanin)) == 1 )
+ Counter++;
+ if ( Counter > 2 )
+ continue;
+ }
+
+clk2 = clock();
+/*
+ printf( "Considering: (" );
+ Vec_PtrForEachEntry( p->vFaninsCur, pFanin, i )
+ printf( "%d ", Abc_ObjFanoutNum(Abc_ObjRegular(pFanin)) );
+ printf( ")\n" );
+*/
// mark the fanin boundary
Vec_PtrForEachEntry( p->vFaninsCur, pFanin, i )
Abc_ObjRegular(pFanin)->vFanouts.nSize++;
+
// label MFFC with current ID
Abc_NtkIncrementTravId( pNode->pNtk );
- nNodesSaved = Abc_NodeMffcLabel( pNode );
+ nNodesSaved = Abc_NodeMffcLabelAig( pNode );
// unmark the fanin boundary
Vec_PtrForEachEntry( p->vFaninsCur, pFanin, i )
Abc_ObjRegular(pFanin)->vFanouts.nSize--;
+p->timeMffc += clock() - clk2;
// evaluate the cut
clk2 = clock();
- pGraph = Rwr_CutEvaluate( p, pNode, pCut, p->vFaninsCur, nNodesSaved, Required, &GainCur );
+ pGraph = Rwr_CutEvaluate( p, pNode, pCut, p->vFaninsCur, nNodesSaved, Required, &GainCur, fPlaceEnable );
p->timeEval += clock() - clk2;
// check if the cut is better than the current best one
if ( pGraph != NULL && GainBest < GainCur )
{
// save this form
+ nNodesSaveCur = nNodesSaved;
GainBest = GainCur;
p->pGraph = pGraph;
p->fCompl = ((uPhase & (1<<4)) > 0);
- uTruthBest = pCut->uTruth;
+ uTruthBest = 0xFFFF & *Cut_CutReadTruth(pCut);
// collect fanins in the
Vec_PtrClear( p->vFanins );
Vec_PtrForEachEntry( p->vFaninsCur, pFanin, i )
@@ -131,22 +164,69 @@ p->timeRes += clock() - clk;
if ( GainBest == -1 )
return -1;
+/*
+ if ( GainBest > 0 )
+ {
+ printf( "Class %d ", p->pMap[uTruthBest] );
+ printf( "Gain = %d. Node %d : ", GainBest, pNode->Id );
+ Vec_PtrForEachEntry( p->vFanins, pFanin, i )
+ printf( "%d ", Abc_ObjRegular(pFanin)->Id );
+ Dec_GraphPrint( stdout, p->pGraph, NULL, NULL );
+ printf( "\n" );
+ }
+*/
+
+// printf( "%d", nNodesSaveCur - GainBest );
+/*
+ if ( GainBest > 0 )
+ {
+ if ( Rwr_CutIsBoolean( pNode, p->vFanins ) )
+ printf( "b" );
+ else
+ {
+ printf( "Node %d : ", pNode->Id );
+ Vec_PtrForEachEntry( p->vFanins, pFanin, i )
+ printf( "%d ", Abc_ObjRegular(pFanin)->Id );
+ printf( "a" );
+ }
+ }
+*/
+/*
+ if ( GainBest > 0 )
+ if ( p->fCompl )
+ printf( "c" );
+ else
+ printf( "." );
+*/
// copy the leaves
Vec_PtrForEachEntry( p->vFanins, pFanin, i )
Dec_GraphNode(p->pGraph, i)->pFunc = pFanin;
+/*
+ printf( "(" );
+ Vec_PtrForEachEntry( p->vFanins, pFanin, i )
+ printf( " %d", Abc_ObjRegular(pFanin)->vFanouts.nSize - 1 );
+ printf( " ) " );
+*/
+// printf( "%d ", Rwr_NodeGetDepth_rec( pNode, p->vFanins ) );
p->nScores[p->pMap[uTruthBest]]++;
- p->nNodesRewritten++;
p->nNodesGained += GainBest;
+ if ( fUseZeros || GainBest > 0 )
+ {
+ p->nNodesRewritten++;
+ }
// report the progress
- if ( fVeryVerbose )
+ if ( fVeryVerbose && GainBest > 0 )
{
printf( "Node %6s : ", Abc_ObjName(pNode) );
printf( "Fanins = %d. ", p->vFanins->nSize );
- printf( "Cone = %2d. ", Dec_GraphNodeNum(p->pGraph) );
- printf( "GAIN = %2d. ", GainBest );
+ printf( "Save = %d. ", nNodesSaveCur );
+ printf( "Add = %d. ", nNodesSaveCur-GainBest );
+ printf( "GAIN = %d. ", GainBest );
+ printf( "Cone = %d. ", p->pGraph? Dec_GraphNodeNum(p->pGraph) : 0 );
+ printf( "Class = %d. ", p->pMap[uTruthBest] );
printf( "\n" );
}
return GainBest;
@@ -163,17 +243,22 @@ p->timeRes += clock() - clk;
SeeAlso []
***********************************************************************/
-Dec_Graph_t * Rwr_CutEvaluate( Rwr_Man_t * p, Abc_Obj_t * pRoot, Cut_Cut_t * pCut, Vec_Ptr_t * vFaninsCur, int nNodesSaved, int LevelMax, int * pGainBest )
+Dec_Graph_t * Rwr_CutEvaluate( Rwr_Man_t * p, Abc_Obj_t * pRoot, Cut_Cut_t * pCut, Vec_Ptr_t * vFaninsCur, int nNodesSaved, int LevelMax, int * pGainBest, int fPlaceEnable )
{
+ extern int Dec_GraphToNetworkCount( Abc_Obj_t * pRoot, Dec_Graph_t * pGraph, int NodeMax, int LevelMax );
Vec_Ptr_t * vSubgraphs;
Dec_Graph_t * pGraphBest, * pGraphCur;
Rwr_Node_t * pNode, * pFanin;
int nNodesAdded, GainBest, i, k;
+ unsigned uTruth;
+ float CostBest;//, CostCur;
// find the matching class of subgraphs
- vSubgraphs = Vec_VecEntry( p->vClasses, p->pMap[pCut->uTruth] );
+ uTruth = 0xFFFF & *Cut_CutReadTruth(pCut);
+ vSubgraphs = Vec_VecEntry( p->vClasses, p->pMap[uTruth] );
p->nSubgraphs += vSubgraphs->nSize;
// determine the best subgraph
GainBest = -1;
+ CostBest = ABC_INFINITY;
Vec_PtrForEachEntry( vSubgraphs, pNode, i )
{
// get the current graph
@@ -186,11 +271,58 @@ Dec_Graph_t * Rwr_CutEvaluate( Rwr_Man_t * p, Abc_Obj_t * pRoot, Cut_Cut_t * pCu
if ( nNodesAdded == -1 )
continue;
assert( nNodesSaved >= nNodesAdded );
- // count the gain at this node
- if ( GainBest < nNodesSaved - nNodesAdded )
+/*
+ // evaluate the cut
+ if ( fPlaceEnable )
+ {
+ extern float Abc_PlaceEvaluateCut( Abc_Obj_t * pRoot, Vec_Ptr_t * vFanins );
+
+ float Alpha = 0.5; // ???
+ float PlaceCost;
+
+ // get the placement cost of the cut
+ PlaceCost = Abc_PlaceEvaluateCut( pRoot, vFaninsCur );
+
+ // get the weigted cost of the cut
+ CostCur = nNodesSaved - nNodesAdded + Alpha * PlaceCost;
+
+ // do not allow uphill moves
+ if ( nNodesSaved - nNodesAdded < 0 )
+ continue;
+
+ // decide what cut to use
+ if ( CostBest > CostCur )
+ {
+ GainBest = nNodesSaved - nNodesAdded; // pure node cost
+ CostBest = CostCur; // cost with placement
+ pGraphBest = pGraphCur; // subgraph to be used for rewriting
+
+ // score the graph
+ if ( nNodesSaved - nNodesAdded > 0 )
+ {
+ pNode->nScore++;
+ pNode->nGain += GainBest;
+ pNode->nAdded += nNodesAdded;
+ }
+ }
+ }
+ else
+*/
{
- GainBest = nNodesSaved - nNodesAdded;
- pGraphBest = pGraphCur;
+ // count the gain at this node
+ if ( GainBest < nNodesSaved - nNodesAdded )
+ {
+ GainBest = nNodesSaved - nNodesAdded;
+ pGraphBest = pGraphCur;
+
+ // score the graph
+ if ( nNodesSaved - nNodesAdded > 0 )
+ {
+ pNode->nScore++;
+ pNode->nGain += GainBest;
+ pNode->nAdded += nNodesAdded;
+ }
+ }
}
}
if ( GainBest == -1 )
@@ -199,6 +331,257 @@ Dec_Graph_t * Rwr_CutEvaluate( Rwr_Man_t * p, Abc_Obj_t * pRoot, Cut_Cut_t * pCu
return pGraphBest;
}
+/**Function*************************************************************
+
+ Synopsis [Checks the type of the cut.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Rwr_CutIsBoolean_rec( Abc_Obj_t * pObj, Vec_Ptr_t * vLeaves, int fMarkA )
+{
+ if ( Vec_PtrFind(vLeaves, pObj) >= 0 || Vec_PtrFind(vLeaves, Abc_ObjNot(pObj)) >= 0 )
+ {
+ if ( fMarkA )
+ pObj->fMarkA = 1;
+ else
+ pObj->fMarkB = 1;
+ return;
+ }
+ assert( !Abc_ObjIsCi(pObj) );
+ Rwr_CutIsBoolean_rec( Abc_ObjFanin0(pObj), vLeaves, fMarkA );
+ Rwr_CutIsBoolean_rec( Abc_ObjFanin1(pObj), vLeaves, fMarkA );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Checks the type of the cut.]
+
+ Description [Returns 1(0) if the cut is Boolean (algebraic).]
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Rwr_CutIsBoolean( Abc_Obj_t * pObj, Vec_Ptr_t * vLeaves )
+{
+ Abc_Obj_t * pTemp;
+ int i, RetValue;
+ Vec_PtrForEachEntry( vLeaves, pTemp, i )
+ {
+ pTemp = Abc_ObjRegular(pTemp);
+ assert( !pTemp->fMarkA && !pTemp->fMarkB );
+ }
+ Rwr_CutIsBoolean_rec( Abc_ObjFanin0(pObj), vLeaves, 1 );
+ Rwr_CutIsBoolean_rec( Abc_ObjFanin1(pObj), vLeaves, 0 );
+ RetValue = 0;
+ Vec_PtrForEachEntry( vLeaves, pTemp, i )
+ {
+ pTemp = Abc_ObjRegular(pTemp);
+ RetValue |= pTemp->fMarkA && pTemp->fMarkB;
+ pTemp->fMarkA = pTemp->fMarkB = 0;
+ }
+ return RetValue;
+}
+
+
+/**Function*************************************************************
+
+ Synopsis [Count the nodes in the cut space of a node.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Rwr_CutCountNumNodes_rec( Abc_Obj_t * pObj, Cut_Cut_t * pCut, Vec_Ptr_t * vNodes )
+{
+ int i;
+ for ( i = 0; i < (int)pCut->nLeaves; i++ )
+ if ( pCut->pLeaves[i] == pObj->Id )
+ {
+ // check if the node is collected
+ if ( pObj->fMarkC == 0 )
+ {
+ pObj->fMarkC = 1;
+ Vec_PtrPush( vNodes, pObj );
+ }
+ return;
+ }
+ assert( Abc_ObjIsNode(pObj) );
+ // check if the node is collected
+ if ( pObj->fMarkC == 0 )
+ {
+ pObj->fMarkC = 1;
+ Vec_PtrPush( vNodes, pObj );
+ }
+ // traverse the fanins
+ Rwr_CutCountNumNodes_rec( Abc_ObjFanin0(pObj), pCut, vNodes );
+ Rwr_CutCountNumNodes_rec( Abc_ObjFanin1(pObj), pCut, vNodes );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Count the nodes in the cut space of a node.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Rwr_CutCountNumNodes( Abc_Obj_t * pObj, Cut_Cut_t * pCut )
+{
+ Vec_Ptr_t * vNodes;
+ int i, Counter;
+ // collect all nodes
+ vNodes = Vec_PtrAlloc( 100 );
+ for ( pCut = pCut->pNext; pCut; pCut = pCut->pNext )
+ Rwr_CutCountNumNodes_rec( pObj, pCut, vNodes );
+ // clean all nodes
+ Vec_PtrForEachEntry( vNodes, pObj, i )
+ pObj->fMarkC = 0;
+ // delete and return
+ Counter = Vec_PtrSize(vNodes);
+ Vec_PtrFree( vNodes );
+ return Counter;
+}
+
+
+/**Function*************************************************************
+
+ Synopsis [Returns depth of the cut.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Rwr_NodeGetDepth_rec( Abc_Obj_t * pObj, Vec_Ptr_t * vLeaves )
+{
+ Abc_Obj_t * pLeaf;
+ int i, Depth0, Depth1;
+ if ( Abc_ObjIsCi(pObj) )
+ return 0;
+ Vec_PtrForEachEntry( vLeaves, pLeaf, i )
+ if ( pObj == Abc_ObjRegular(pLeaf) )
+ return 0;
+ Depth0 = Rwr_NodeGetDepth_rec( Abc_ObjFanin0(pObj), vLeaves );
+ Depth1 = Rwr_NodeGetDepth_rec( Abc_ObjFanin1(pObj), vLeaves );
+ return 1 + ABC_MAX( Depth0, Depth1 );
+}
+
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Rwr_ScoresClean( Rwr_Man_t * p )
+{
+ Vec_Ptr_t * vSubgraphs;
+ Rwr_Node_t * pNode;
+ int i, k;
+ for ( i = 0; i < p->vClasses->nSize; i++ )
+ {
+ vSubgraphs = Vec_VecEntry( p->vClasses, i );
+ Vec_PtrForEachEntry( vSubgraphs, pNode, k )
+ pNode->nScore = pNode->nGain = pNode->nAdded = 0;
+ }
+}
+
+static int Gains[222];
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Rwr_ScoresCompare( int * pNum1, int * pNum2 )
+{
+ if ( Gains[*pNum1] > Gains[*pNum2] )
+ return -1;
+ if ( Gains[*pNum1] < Gains[*pNum2] )
+ return 1;
+ return 0;
+}
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Rwr_ScoresReport( Rwr_Man_t * p )
+{
+ extern void Ivy_TruthDsdComputePrint( unsigned uTruth );
+ int Perm[222];
+ Vec_Ptr_t * vSubgraphs;
+ Rwr_Node_t * pNode;
+ int i, iNew, k;
+ unsigned uTruth;
+ // collect total gains
+ assert( p->vClasses->nSize == 222 );
+ for ( i = 0; i < p->vClasses->nSize; i++ )
+ {
+ Perm[i] = i;
+ Gains[i] = 0;
+ vSubgraphs = Vec_VecEntry( p->vClasses, i );
+ Vec_PtrForEachEntry( vSubgraphs, pNode, k )
+ Gains[i] += pNode->nGain;
+ }
+ // sort the gains
+ qsort( Perm, 222, sizeof(int), (int (*)(const void *, const void *))Rwr_ScoresCompare );
+
+ // print classes
+ for ( i = 0; i < p->vClasses->nSize; i++ )
+ {
+ iNew = Perm[i];
+ if ( Gains[iNew] == 0 )
+ break;
+ vSubgraphs = Vec_VecEntry( p->vClasses, iNew );
+ printf( "CLASS %3d: Subgr = %3d. Total gain = %6d. ", iNew, Vec_PtrSize(vSubgraphs), Gains[iNew] );
+ uTruth = (unsigned)p->pMapInv[iNew];
+ Extra_PrintBinary( stdout, &uTruth, 16 );
+ printf( " " );
+ Ivy_TruthDsdComputePrint( (unsigned)p->pMapInv[iNew] | ((unsigned)p->pMapInv[iNew] << 16) );
+ Vec_PtrForEachEntry( vSubgraphs, pNode, k )
+ {
+ if ( pNode->nScore == 0 )
+ continue;
+ printf( " %2d: S=%5d. A=%5d. G=%6d. ", k, pNode->nScore, pNode->nAdded, pNode->nGain );
+ Dec_GraphPrint( stdout, (Dec_Graph_t *)pNode->pNext, NULL, NULL );
+ }
+ }
+}
+
////////////////////////////////////////////////////////////////////////
/// END OF FILE ///
////////////////////////////////////////////////////////////////////////
diff --git a/src/opt/rwr/rwrExp.c b/src/opt/rwr/rwrExp.c
index e93a2611..2d00bb1c 100644
--- a/src/opt/rwr/rwrExp.c
+++ b/src/opt/rwr/rwrExp.c
@@ -47,7 +47,7 @@ static Rwr_Man4_t * s_pManRwrExp4 = NULL;
static Rwr_Man5_t * s_pManRwrExp5 = NULL;
////////////////////////////////////////////////////////////////////////
-/// FUNCTION DEFITIONS ///
+/// FUNCTION DEFINITIONS ///
////////////////////////////////////////////////////////////////////////
/**Function*************************************************************
diff --git a/src/opt/rwr/rwrLib.c b/src/opt/rwr/rwrLib.c
index fbcb8916..1cdf350e 100644
--- a/src/opt/rwr/rwrLib.c
+++ b/src/opt/rwr/rwrLib.c
@@ -28,7 +28,7 @@ static Rwr_Node_t * Rwr_ManTryNode( Rwr_Man_t * p, Rwr_Node_t * p0, Rwr_N
static void Rwr_MarkUsed_rec( Rwr_Man_t * p, Rwr_Node_t * pNode );
////////////////////////////////////////////////////////////////////////
-/// FUNCTION DEFITIONS ///
+/// FUNCTION DEFINITIONS ///
////////////////////////////////////////////////////////////////////////
/**Function*************************************************************
diff --git a/src/opt/rwr/rwrMan.c b/src/opt/rwr/rwrMan.c
index a21dd520..87a080c7 100644
--- a/src/opt/rwr/rwrMan.c
+++ b/src/opt/rwr/rwrMan.c
@@ -27,7 +27,7 @@
////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////
-/// FUNCTION DEFITIONS ///
+/// FUNCTION DEFINITIONS ///
////////////////////////////////////////////////////////////////////////
/**Function*************************************************************
@@ -50,7 +50,7 @@ clk = clock();
p = ALLOC( Rwr_Man_t, 1 );
memset( p, 0, sizeof(Rwr_Man_t) );
p->nFuncs = (1<<16);
- pManDec = Abc_FrameReadManDec(Abc_FrameGetGlobalFrame());
+ pManDec = Abc_FrameReadManDec();
p->puCanons = pManDec->puCanons;
p->pPhases = pManDec->pPhases;
p->pPerms = pManDec->pPerms;
@@ -75,6 +75,7 @@ clk = clock();
p->vLevNums = Vec_IntAlloc( 50 );
p->vFanins = Vec_PtrAlloc( 50 );
p->vFaninsCur = Vec_PtrAlloc( 50 );
+ p->vNodesTemp = Vec_PtrAlloc( 50 );
if ( fPrecompute )
{ // precompute subgraphs
Rwr_ManPrecompute( p );
@@ -112,11 +113,13 @@ void Rwr_ManStop( Rwr_Man_t * p )
Dec_GraphFree( (Dec_Graph_t *)pNode->pNext );
}
if ( p->vClasses ) Vec_VecFree( p->vClasses );
+ Vec_PtrFree( p->vNodesTemp );
Vec_PtrFree( p->vForest );
Vec_IntFree( p->vLevNums );
Vec_PtrFree( p->vFanins );
Vec_PtrFree( p->vFaninsCur );
- Extra_MmFixedStop( p->pMmNode, 0 );
+ Extra_MmFixedStop( p->pMmNode );
+ FREE( p->pMapInv );
free( p->pTable );
free( p->pPractical );
free( p->pPerms4 );
@@ -147,20 +150,50 @@ void Rwr_ManPrintStats( Rwr_Man_t * p )
printf( "Used NPN classes = %8d.\n", Counter );
printf( "Nodes considered = %8d.\n", p->nNodesConsidered );
printf( "Nodes rewritten = %8d.\n", p->nNodesRewritten );
- printf( "Calculated gain = %8d.\n", p->nNodesGained );
+ printf( "Gain = %8d. (%6.2f %%).\n", p->nNodesBeg-p->nNodesEnd, 100.0*(p->nNodesBeg-p->nNodesEnd)/p->nNodesBeg );
PRT( "Start ", p->timeStart );
PRT( "Cuts ", p->timeCut );
PRT( "Resynthesis ", p->timeRes );
+ PRT( " Mffc ", p->timeMffc );
PRT( " Eval ", p->timeEval );
+ PRT( "Update ", p->timeUpdate );
PRT( "TOTAL ", p->timeTotal );
/*
- printf( "The scores are : " );
+ printf( "The scores are:\n" );
for ( i = 0; i < 222; i++ )
if ( p->nScores[i] > 0 )
- printf( "%d=%d ", i, p->nScores[i] );
- printf( "\n" );
+ {
+ extern void Ivy_TruthDsdComputePrint( unsigned uTruth );
+ printf( "%3d = %8d canon = %5d ", i, p->nScores[i], p->pMapInv[i] );
+ Ivy_TruthDsdComputePrint( (unsigned)p->pMapInv[i] | ((unsigned)p->pMapInv[i] << 16) );
+ }
*/
+ printf( "\n" );
+
+}
+
+/**Function*************************************************************
+
+ Synopsis [Stops the resynthesis manager.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Rwr_ManPrintStatsFile( Rwr_Man_t * p )
+{
+ FILE * pTable;
+ pTable = fopen( "stats.txt", "a+" );
+ fprintf( pTable, "%d ", p->nCutsGood );
+ fprintf( pTable, "%d ", p->nSubgraphs );
+ fprintf( pTable, "%d ", p->nNodesRewritten );
+ fprintf( pTable, "%d", p->nNodesGained );
+ fprintf( pTable, "\n" );
+ fclose( pTable );
}
/**Function*************************************************************
@@ -190,6 +223,22 @@ void * Rwr_ManReadDecs( Rwr_Man_t * p )
SeeAlso []
***********************************************************************/
+Vec_Ptr_t * Rwr_ManReadLeaves( Rwr_Man_t * p )
+{
+ return p->vFanins;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Stops the resynthesis manager.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
int Rwr_ManReadCompl( Rwr_Man_t * p )
{
return p->fCompl;
@@ -222,6 +271,22 @@ void Rwr_ManAddTimeCuts( Rwr_Man_t * p, int Time )
SeeAlso []
***********************************************************************/
+void Rwr_ManAddTimeUpdate( Rwr_Man_t * p, int Time )
+{
+ p->timeUpdate += Time;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Stops the resynthesis manager.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
void Rwr_ManAddTimeTotal( Rwr_Man_t * p, int Time )
{
p->timeTotal += Time;
diff --git a/src/opt/rwr/rwrPrint.c b/src/opt/rwr/rwrPrint.c
index 30c99f00..82ad2a90 100644
--- a/src/opt/rwr/rwrPrint.c
+++ b/src/opt/rwr/rwrPrint.c
@@ -25,7 +25,7 @@
////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////
-/// FUNCTION DEFITIONS ///
+/// FUNCTION DEFINITIONS ///
////////////////////////////////////////////////////////////////////////
/**Function*************************************************************
@@ -79,6 +79,33 @@ void Rwr_GetBushVolume( Rwr_Man_t * p, int Entry, int * pVolume, int * pnFuncs )
/**Function*************************************************************
+ Synopsis [Adds the node to the end of the list.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Rwr_GetBushSumOfVolumes( Rwr_Man_t * p, int Entry )
+{
+ Rwr_Node_t * pNode;
+ int Volume, VolumeTotal = 0;
+ for ( pNode = p->pTable[Entry]; pNode; pNode = pNode->pNext )
+ {
+ if ( pNode->uTruth != p->puCanons[pNode->uTruth] )
+ continue;
+ Volume = 0;
+ Rwr_ManIncTravId( p );
+ Rwr_Trav2_rec( p, pNode, &Volume );
+ VolumeTotal += Volume;
+ }
+ return VolumeTotal;
+}
+
+/**Function*************************************************************
+
Synopsis [Prints one rwr node.]
Description []
@@ -219,9 +246,9 @@ void Rwr_ManPrint( Rwr_Man_t * p )
continue;
if ( i != p->puCanons[i] )
continue;
- fprintf( pFile, "\nClass %3d. Func %6d. ", p->pMap[i], Counter++ );
+ fprintf( pFile, "\nClass %3d. Func %6d. ", p->pMap[i], Counter++ );
Rwr_GetBushVolume( p, i, &Volume, &nFuncs );
- fprintf( pFile, "Functions = %2d. Volume = %2d. ", nFuncs, Volume );
+ fprintf( pFile, "Roots = %3d. Vol = %3d. Sum = %3d. ", nFuncs, Volume, Rwr_GetBushSumOfVolumes(p, i) );
uTruth = i;
Extra_PrintBinary( pFile, &uTruth, 16 );
fprintf( pFile, "\n" );
diff --git a/src/opt/rwr/rwrTemp.c b/src/opt/rwr/rwrTemp.c
new file mode 100644
index 00000000..3ffbd408
--- /dev/null
+++ b/src/opt/rwr/rwrTemp.c
@@ -0,0 +1,121 @@
+/**CFile****************************************************************
+
+ FileName [rwrCut.c]
+
+ SystemName [ABC: Logic synthesis and verification system.]
+
+ PackageName [DAG-aware AIG rewriting package.]
+
+ Synopsis [Cut computation.]
+
+ Author [Alan Mishchenko]
+
+ Affiliation [UC Berkeley]
+
+ Date [Ver. 1.0. Started - June 20, 2005.]
+
+ Revision [$Id: rwrCut.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "rwr.h"
+
+////////////////////////////////////////////////////////////////////////
+/// DECLARATIONS ///
+////////////////////////////////////////////////////////////////////////
+
+static int pTruths[13719];
+static int pFreqs[13719];
+static int pPerm[13719];
+
+////////////////////////////////////////////////////////////////////////
+/// FUNCTION DEFINITIONS ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Rwr_TempCompare( int * pNum1, int * pNum2 )
+{
+ int Freq1 = pFreqs[*pNum1];
+ int Freq2 = pFreqs[*pNum2];
+ if ( Freq1 < Freq2 )
+ return 1;
+ if ( Freq1 > Freq2 )
+ return -1;
+ return 0;
+}
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Rwr_Temp()
+{
+ char Buffer[32];
+ int nFuncs = 13719;
+ int nEntries = 100;
+ unsigned uTruth;
+ int i, k;
+ FILE * pFile;
+
+ pFile = fopen( "nnclass_stats5.txt", "r" );
+ for ( i = 0; i < 13719; i++ )
+ {
+ fscanf( pFile, "%s%d", Buffer, &pFreqs[i] );
+ Extra_ReadHexadecimal( &uTruth, Buffer+2, 5 );
+ pTruths[i] = uTruth;
+ }
+ fclose( pFile );
+
+ for ( i = 0; i < 13719; i++ )
+ pPerm[i] = i;
+
+ qsort( (void *)pPerm, 13719, sizeof(int),
+ (int (*)(const void *, const void *)) Rwr_TempCompare );
+
+
+ pFile = fopen( "5npn_100.blif", "w" );
+ fprintf( pFile, "# Most frequent NPN classes of 5 vars.\n" );
+ fprintf( pFile, ".model 5npn\n" );
+ fprintf( pFile, ".inputs a b c d e\n" );
+ fprintf( pFile, ".outputs" );
+ for ( i = 0; i < nEntries; i++ )
+ fprintf( pFile, " %02d", i );
+ fprintf( pFile, "\n" );
+
+ for ( i = 0; i < nEntries; i++ )
+ {
+ fprintf( pFile, ".names a b c d e %02d\n", i );
+ uTruth = pTruths[pPerm[i]];
+ for ( k = 0; k < 32; k++ )
+ if ( uTruth & (1 << k) )
+ {
+ Extra_PrintBinary( pFile, &k, 5 );
+ fprintf( pFile, " 1\n" );
+ }
+ }
+ fprintf( pFile, ".end\n" );
+ fclose( pFile );
+}
+
+////////////////////////////////////////////////////////////////////////
+/// END OF FILE ///
+////////////////////////////////////////////////////////////////////////
+
+
diff --git a/src/opt/rwr/rwrUtil.c b/src/opt/rwr/rwrUtil.c
index 65b2bd6f..b2add2bf 100644
--- a/src/opt/rwr/rwrUtil.c
+++ b/src/opt/rwr/rwrUtil.c
@@ -34,7 +34,7 @@ static unsigned short s_RwtAigSubgraphs[];
#endif
////////////////////////////////////////////////////////////////////////
-/// FUNCTION DEFITIONS ///
+/// FUNCTION DEFINITIONS ///
////////////////////////////////////////////////////////////////////////
/**Function*************************************************************
diff --git a/src/opt/sim/module.make b/src/opt/sim/module.make
index 43d0a125..54058402 100644
--- a/src/opt/sim/module.make
+++ b/src/opt/sim/module.make
@@ -1,5 +1,6 @@
SRC += src/opt/sim/simMan.c \
src/opt/sim/simSat.c \
+ src/opt/sim/simSeq.c \
src/opt/sim/simSupp.c \
src/opt/sim/simSwitch.c \
src/opt/sim/simSym.c \
diff --git a/src/opt/sim/sim.h b/src/opt/sim/sim.h
index afed7190..7fcf5ae6 100644
--- a/src/opt/sim/sim.h
+++ b/src/opt/sim/sim.h
@@ -17,10 +17,14 @@
Revision [$Id: sim.h,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
***********************************************************************/
-
+
#ifndef __SIM_H__
#define __SIM_H__
+#ifdef __cplusplus
+extern "C" {
+#endif
+
/*
The ideas realized in this package are described in the paper:
"Detecting Symmetries in Boolean Functions using Circuit Representation,
@@ -98,6 +102,7 @@ struct Sim_Man_t_
Abc_Ntk_t * pNtk;
int nInputs;
int nOutputs;
+ int fLightweight;
// internal simulation information
int nSimBits; // the number of bits in simulation info
int nSimWords; // the number of words in simulation info
@@ -135,11 +140,11 @@ struct Sim_Pat_t_
};
////////////////////////////////////////////////////////////////////////
-/// MACRO DEFITIONS ///
+/// MACRO DEFINITIONS ///
////////////////////////////////////////////////////////////////////////
-#define SIM_NUM_WORDS(n) ((n)/32 + (((n)%32) > 0))
-#define SIM_LAST_BITS(n) ((((n)%32) > 0)? (n)%32 : 32)
+#define SIM_NUM_WORDS(n) (((n)>>5) + (((n)&31) > 0))
+#define SIM_LAST_BITS(n) ((((n)&31) > 0)? (n)&31 : 32)
#define SIM_MASK_FULL (0xFFFFFFFF)
#define SIM_MASK_BEG(n) (SIM_MASK_FULL >> (32-n))
@@ -162,6 +167,7 @@ struct Sim_Pat_t_
#define Sim_SuppFunHasVar(vSupps,Output,v) Sim_HasBit((unsigned*)(vSupps)->pArray[Output],(v))
#define Sim_SimInfoSetVar(vSupps,pNode,v) Sim_SetBit((unsigned*)(vSupps)->pArray[(pNode)->Id],(v))
#define Sim_SimInfoHasVar(vSupps,pNode,v) Sim_HasBit((unsigned*)(vSupps)->pArray[(pNode)->Id],(v))
+#define Sim_SimInfoGet(vInfo,pNode) ((unsigned *)((vInfo)->pArray[(pNode)->Id]))
////////////////////////////////////////////////////////////////////////
/// FUNCTION DECLARATIONS ///
@@ -171,11 +177,14 @@ struct Sim_Pat_t_
extern Sym_Man_t * Sym_ManStart( Abc_Ntk_t * pNtk, int fVerbose );
extern void Sym_ManStop( Sym_Man_t * p );
extern void Sym_ManPrintStats( Sym_Man_t * p );
-extern Sim_Man_t * Sim_ManStart( Abc_Ntk_t * pNtk );
+extern Sim_Man_t * Sim_ManStart( Abc_Ntk_t * pNtk, int fLightweight );
extern void Sim_ManStop( Sim_Man_t * p );
extern void Sim_ManPrintStats( Sim_Man_t * p );
extern Sim_Pat_t * Sim_ManPatAlloc( Sim_Man_t * p );
extern void Sim_ManPatFree( Sim_Man_t * p, Sim_Pat_t * pPat );
+/*=== simSeq.c ==========================================================*/
+extern Vec_Ptr_t * Sim_SimulateSeqRandom( Abc_Ntk_t * pNtk, int nFrames, int nWords );
+extern Vec_Ptr_t * Sim_SimulateSeqModel( Abc_Ntk_t * pNtk, int nFrames, int * pModel );
/*=== simSupp.c ==========================================================*/
extern Vec_Ptr_t * Sim_ComputeStrSupp( Abc_Ntk_t * pNtk );
extern Vec_Ptr_t * Sim_ComputeFunSupp( Abc_Ntk_t * pNtk, int fVerbose );
@@ -197,17 +206,28 @@ extern void Sim_UtilInfoFlip( Sim_Man_t * p, Abc_Obj_t * pNode );
extern bool Sim_UtilInfoCompare( Sim_Man_t * p, Abc_Obj_t * pNode );
extern void Sim_UtilSimulate( Sim_Man_t * p, bool fFirst );
extern void Sim_UtilSimulateNode( Sim_Man_t * p, Abc_Obj_t * pNode, bool fType, bool fType1, bool fType2 );
-extern void Sim_UtilSimulateNodeOne( Abc_Obj_t * pNode, Vec_Ptr_t * vSimInfo, int nSimWords );
+extern void Sim_UtilSimulateNodeOne( Abc_Obj_t * pNode, Vec_Ptr_t * vSimInfo, int nSimWords, int nOffset );
+extern void Sim_UtilTransferNodeOne( Abc_Obj_t * pNode, Vec_Ptr_t * vSimInfo, int nSimWords, int nOffset, int fShift );
extern int Sim_UtilCountSuppSizes( Sim_Man_t * p, int fStruct );
extern int Sim_UtilCountOnes( unsigned * pSimInfo, int nSimWords );
-extern void Sim_UtilGetRandom( unsigned * pPatRand, int nSimWords );
+extern Vec_Int_t * Sim_UtilCountOnesArray( Vec_Ptr_t * vInfo, int nSimWords );
+extern void Sim_UtilSetRandom( unsigned * pPatRand, int nSimWords );
+extern void Sim_UtilSetCompl( unsigned * pPatRand, int nSimWords );
+extern void Sim_UtilSetConst( unsigned * pPatRand, int nSimWords, int fConst1 );
+extern int Sim_UtilInfoIsEqual( unsigned * pPats1, unsigned * pPats2, int nSimWords );
+extern int Sim_UtilInfoIsImp( unsigned * pPats1, unsigned * pPats2, int nSimWords );
+extern int Sim_UtilInfoIsClause( unsigned * pPats1, unsigned * pPats2, int nSimWords );
extern int Sim_UtilCountAllPairs( Vec_Ptr_t * vSuppFun, int nSimWords, Vec_Int_t * vCounters );
extern void Sim_UtilCountPairsAll( Sym_Man_t * p );
extern int Sim_UtilMatrsAreDisjoint( Sym_Man_t * p );
+#ifdef __cplusplus
+}
+#endif
+
+#endif
+
////////////////////////////////////////////////////////////////////////
/// END OF FILE ///
////////////////////////////////////////////////////////////////////////
-#endif
-
diff --git a/src/opt/sim/simMan.c b/src/opt/sim/simMan.c
index 780ecfd8..3b50ad84 100644
--- a/src/opt/sim/simMan.c
+++ b/src/opt/sim/simMan.c
@@ -26,12 +26,12 @@
////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////
-/// FUNCTION DEFITIONS ///
+/// FUNCTION DEFINITIONS ///
////////////////////////////////////////////////////////////////////////
/**Function*************************************************************
- Synopsis [Starts the simulatin manager.]
+ Synopsis [Starts the simulation manager.]
Description []
@@ -83,7 +83,7 @@ Sym_Man_t * Sym_ManStart( Abc_Ntk_t * pNtk, int fVerbose )
/**Function*************************************************************
- Synopsis [Stops the simulatin manager.]
+ Synopsis [Stops the simulation manager.]
Description []
@@ -149,11 +149,9 @@ void Sym_ManPrintStats( Sym_Man_t * p )
}
-
-
/**Function*************************************************************
- Synopsis [Starts the simulatin manager.]
+ Synopsis [Starts the simulation manager.]
Description []
@@ -162,7 +160,7 @@ void Sym_ManPrintStats( Sym_Man_t * p )
SeeAlso []
***********************************************************************/
-Sim_Man_t * Sim_ManStart( Abc_Ntk_t * pNtk )
+Sim_Man_t * Sim_ManStart( Abc_Ntk_t * pNtk, int fLightweight )
{
Sim_Man_t * p;
// start the manager
@@ -175,24 +173,27 @@ Sim_Man_t * Sim_ManStart( Abc_Ntk_t * pNtk )
p->nSimBits = 2048;
p->nSimWords = SIM_NUM_WORDS(p->nSimBits);
p->vSim0 = Sim_UtilInfoAlloc( Abc_NtkObjNumMax(pNtk), p->nSimWords, 0 );
- p->vSim1 = Sim_UtilInfoAlloc( Abc_NtkObjNumMax(pNtk), p->nSimWords, 0 );
- // support information
- p->nSuppBits = Abc_NtkCiNum(pNtk);
- p->nSuppWords = SIM_NUM_WORDS(p->nSuppBits);
- p->vSuppStr = Sim_ComputeStrSupp( pNtk );
- p->vSuppFun = Sim_UtilInfoAlloc( Abc_NtkCoNum(p->pNtk), p->nSuppWords, 1 );
- // other data
- p->pMmPat = Extra_MmFixedStart( sizeof(Sim_Pat_t) + p->nSuppWords * sizeof(unsigned) );
- p->vFifo = Vec_PtrAlloc( 100 );
- p->vDiffs = Vec_IntAlloc( 100 );
- // allocate support targets (array of unresolved outputs for each input)
- p->vSuppTargs = Vec_VecStart( p->nInputs );
+ p->fLightweight = fLightweight;
+ if (!p->fLightweight) {
+ p->vSim1 = Sim_UtilInfoAlloc( Abc_NtkObjNumMax(pNtk), p->nSimWords, 0 );
+ // support information
+ p->nSuppBits = Abc_NtkCiNum(pNtk);
+ p->nSuppWords = SIM_NUM_WORDS(p->nSuppBits);
+ p->vSuppStr = Sim_ComputeStrSupp( pNtk );
+ p->vSuppFun = Sim_UtilInfoAlloc( Abc_NtkCoNum(p->pNtk), p->nSuppWords, 1 );
+ // other data
+ p->pMmPat = Extra_MmFixedStart( sizeof(Sim_Pat_t) + p->nSuppWords * sizeof(unsigned) );
+ p->vFifo = Vec_PtrAlloc( 100 );
+ p->vDiffs = Vec_IntAlloc( 100 );
+ // allocate support targets (array of unresolved outputs for each input)
+ p->vSuppTargs = Vec_VecStart( p->nInputs );
+ }
return p;
}
/**Function*************************************************************
- Synopsis [Stops the simulatin manager.]
+ Synopsis [Stops the simulation manager.]
Description []
@@ -209,7 +210,7 @@ void Sim_ManStop( Sim_Man_t * p )
if ( p->vSuppStr ) Sim_UtilInfoFree( p->vSuppStr );
// if ( p->vSuppFun ) Sim_UtilInfoFree( p->vSuppFun );
if ( p->vSuppTargs ) Vec_VecFree( p->vSuppTargs );
- if ( p->pMmPat ) Extra_MmFixedStop( p->pMmPat, 0 );
+ if ( p->pMmPat ) Extra_MmFixedStop( p->pMmPat );
if ( p->vFifo ) Vec_PtrFree( p->vFifo );
if ( p->vDiffs ) Vec_IntFree( p->vDiffs );
free( p );
diff --git a/src/opt/sim/simSat.c b/src/opt/sim/simSat.c
index b4e080fe..d514f7f2 100644
--- a/src/opt/sim/simSat.c
+++ b/src/opt/sim/simSat.c
@@ -26,7 +26,7 @@
////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////
-/// FUNCTION DEFITIONS ///
+/// FUNCTION DEFINITIONS ///
////////////////////////////////////////////////////////////////////////
/**Function*************************************************************
diff --git a/src/opt/sim/simSeq.c b/src/opt/sim/simSeq.c
new file mode 100644
index 00000000..49fb939f
--- /dev/null
+++ b/src/opt/sim/simSeq.c
@@ -0,0 +1,171 @@
+/**CFile****************************************************************
+
+ FileName [simSeq.c]
+
+ SystemName [ABC: Logic synthesis and verification system.]
+
+ PackageName [Network and node package.]
+
+ Synopsis [Simulation for sequential circuits.]
+
+ Author [Alan Mishchenko]
+
+ Affiliation [UC Berkeley]
+
+ Date [Ver. 1.0. Started - June 20, 2005.]
+
+ Revision [$Id: simUtils.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "abc.h"
+#include "sim.h"
+
+////////////////////////////////////////////////////////////////////////
+/// DECLARATIONS ///
+////////////////////////////////////////////////////////////////////////
+
+static void Sim_SimulateSeqFrame( Vec_Ptr_t * vInfo, Abc_Ntk_t * pNtk, int iFrames, int nWords, int fTransfer );
+
+////////////////////////////////////////////////////////////////////////
+/// FUNCTION DEFINITIONS ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+ Synopsis [Simulates sequential circuit.]
+
+ Description [Takes sequential circuit (pNtk). Simulates the given number
+ (nFrames) of the circuit with the given number of machine words (nWords)
+ of random simulation data, starting from the initial state. If the initial
+ state of some latches is a don't-care, uses random input for that latch.]
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Vec_Ptr_t * Sim_SimulateSeqRandom( Abc_Ntk_t * pNtk, int nFrames, int nWords )
+{
+ Vec_Ptr_t * vInfo;
+ Abc_Obj_t * pNode;
+ int i;
+ assert( Abc_NtkIsStrash(pNtk) );
+ vInfo = Sim_UtilInfoAlloc( Abc_NtkObjNumMax(pNtk), nWords * nFrames, 0 );
+ // set the constant data
+ pNode = Abc_AigConst1(pNtk);
+ Sim_UtilSetConst( Sim_SimInfoGet(vInfo,pNode), nWords * nFrames, 1 );
+ // set the random PI data
+ Abc_NtkForEachPi( pNtk, pNode, i )
+ Sim_UtilSetRandom( Sim_SimInfoGet(vInfo,pNode), nWords * nFrames );
+ // set the initial state data
+ Abc_NtkForEachLatch( pNtk, pNode, i )
+ if ( Abc_LatchIsInit0(pNode) )
+ Sim_UtilSetConst( Sim_SimInfoGet(vInfo,pNode), nWords, 0 );
+ else if ( Abc_LatchIsInit1(pNode) )
+ Sim_UtilSetConst( Sim_SimInfoGet(vInfo,pNode), nWords, 1 );
+ else
+ Sim_UtilSetRandom( Sim_SimInfoGet(vInfo,pNode), nWords );
+ // simulate the nodes for the given number of timeframes
+ for ( i = 0; i < nFrames; i++ )
+ Sim_SimulateSeqFrame( vInfo, pNtk, i, nWords, (int)(i < nFrames-1) );
+ return vInfo;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Simulates sequential circuit.]
+
+ Description [Takes sequential circuit (pNtk). Simulates the given number
+ (nFrames) of the circuit with the given model. The model is assumed to
+ contain values of PIs for each frame. The latches are initialized to
+ the initial state. One word of data is simulated.]
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Vec_Ptr_t * Sim_SimulateSeqModel( Abc_Ntk_t * pNtk, int nFrames, int * pModel )
+{
+ Vec_Ptr_t * vInfo;
+ Abc_Obj_t * pNode;
+ unsigned * pUnsigned;
+ int i, k;
+ vInfo = Sim_UtilInfoAlloc( Abc_NtkObjNumMax(pNtk), nFrames, 0 );
+ // set the constant data
+ pNode = Abc_AigConst1(pNtk);
+ Sim_UtilSetConst( Sim_SimInfoGet(vInfo,pNode), nFrames, 1 );
+ // set the random PI data
+ Abc_NtkForEachPi( pNtk, pNode, i )
+ {
+ pUnsigned = Sim_SimInfoGet(vInfo,pNode);
+ for ( k = 0; k < nFrames; k++ )
+ pUnsigned[k] = pModel[k * Abc_NtkPiNum(pNtk) + i] ? ~((unsigned)0) : 0;
+ }
+ // set the initial state data
+ Abc_NtkForEachLatch( pNtk, pNode, i )
+ {
+ pUnsigned = Sim_SimInfoGet(vInfo,pNode);
+ if ( Abc_LatchIsInit0(pNode) )
+ pUnsigned[0] = 0;
+ else if ( Abc_LatchIsInit1(pNode) )
+ pUnsigned[0] = ~((unsigned)0);
+ else
+ pUnsigned[0] = SIM_RANDOM_UNSIGNED;
+ }
+ // simulate the nodes for the given number of timeframes
+ for ( i = 0; i < nFrames; i++ )
+ Sim_SimulateSeqFrame( vInfo, pNtk, i, 1, (int)(i < nFrames-1) );
+/*
+ // print the simulated values
+ for ( i = 0; i < nFrames; i++ )
+ {
+ printf( "Frame %d : ", i+1 );
+ Abc_NtkForEachPi( pNtk, pNode, k )
+ printf( "%d", Sim_SimInfoGet(vInfo,pNode)[i] > 0 );
+ printf( " " );
+ Abc_NtkForEachLatch( pNtk, pNode, k )
+ printf( "%d", Sim_SimInfoGet(vInfo,pNode)[i] > 0 );
+ printf( " " );
+ Abc_NtkForEachPo( pNtk, pNode, k )
+ printf( "%d", Sim_SimInfoGet(vInfo,pNode)[i] > 0 );
+ printf( "\n" );
+ }
+ printf( "\n" );
+*/
+ return vInfo;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Simulates one frame of sequential circuit.]
+
+ Description [Assumes that the latches and POs are already initialized.
+ In the end transfers the data to the latches of the next frame.]
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Sim_SimulateSeqFrame( Vec_Ptr_t * vInfo, Abc_Ntk_t * pNtk, int iFrames, int nWords, int fTransfer )
+{
+ Abc_Obj_t * pNode;
+ int i;
+ Abc_NtkForEachNode( pNtk, pNode, i )
+ Sim_UtilSimulateNodeOne( pNode, vInfo, nWords, iFrames * nWords );
+ Abc_NtkForEachPo( pNtk, pNode, i )
+ Sim_UtilTransferNodeOne( pNode, vInfo, nWords, iFrames * nWords, 0 );
+ if ( !fTransfer )
+ return;
+ Abc_NtkForEachLatch( pNtk, pNode, i )
+ Sim_UtilTransferNodeOne( pNode, vInfo, nWords, iFrames * nWords, 1 );
+}
+
+
+////////////////////////////////////////////////////////////////////////
+/// END OF FILE ///
+////////////////////////////////////////////////////////////////////////
+
+
diff --git a/src/opt/sim/simSupp.c b/src/opt/sim/simSupp.c
index 576e19cc..f7048f4a 100644
--- a/src/opt/sim/simSupp.c
+++ b/src/opt/sim/simSupp.c
@@ -35,10 +35,8 @@ static void Sim_UtilAssignFromFifo( Sim_Man_t * p );
static void Sim_SolveTargetsUsingSat( Sim_Man_t * p, int nCounters );
static int Sim_SolveSuppModelVerify( Abc_Ntk_t * pNtk, int * pModel, int Input, int Output );
-extern Fraig_Man_t * Abc_NtkToFraig( Abc_Ntk_t * pNtk, Fraig_Params_t * pParams, int fAllNodes );
-
////////////////////////////////////////////////////////////////////////
-/// FUNCTION DEFITIONS ///
+/// FUNCTION DEFINITIONS ///
////////////////////////////////////////////////////////////////////////
/**Function*************************************************************
@@ -68,8 +66,8 @@ Vec_Ptr_t * Sim_ComputeStrSupp( Abc_Ntk_t * pNtk )
// derive the structural supports of the internal nodes
Abc_NtkForEachNode( pNtk, pNode, i )
{
- if ( Abc_NodeIsConst(pNode) )
- continue;
+// if ( Abc_NodeIsConst(pNode) )
+// continue;
pSimmNode = vSuppStr->pArray[ pNode->Id ];
pSimmNode1 = vSuppStr->pArray[ Abc_ObjFaninId0(pNode) ];
pSimmNode2 = vSuppStr->pArray[ Abc_ObjFaninId1(pNode) ];
@@ -108,7 +106,7 @@ Vec_Ptr_t * Sim_ComputeFunSupp( Abc_Ntk_t * pNtk, int fVerbose )
srand( 0xABC );
// start the simulation manager
- p = Sim_ManStart( pNtk );
+ p = Sim_ManStart( pNtk, 0 );
// compute functional support using one round of random simulation
Sim_UtilAssignRandom( p );
@@ -469,9 +467,10 @@ void Sim_SolveTargetsUsingSat( Sim_Man_t * p, int Limit )
// transform the miter into a fraig
Fraig_ParamsSetDefault( &Params );
+ Params.nSeconds = ABC_INFINITY;
Params.fInternal = 1;
clk = clock();
- pMan = Abc_NtkToFraig( pMiter, &Params, 0 );
+ pMan = Abc_NtkToFraig( pMiter, &Params, 0, 0 );
p->timeFraig += clock() - clk;
clk = clock();
Fraig_ManProveMiter( pMan );
@@ -587,10 +586,6 @@ int Sim_SolveSuppModelVerify( Abc_Ntk_t * pNtk, int * pModel, int Input, int Out
}
// perform the traversal
RetValue = 3 & Sim_NtkSimTwoPats_rec( Abc_ObjFanin0( Abc_NtkCo(pNtk,Output) ) );
- if ( RetValue == 0 || RetValue == 3 )
- {
- int x = 0;
- }
// assert( RetValue == 1 || RetValue == 2 );
return RetValue == 1 || RetValue == 2;
}
diff --git a/src/opt/sim/simSwitch.c b/src/opt/sim/simSwitch.c
index b43597f3..218d4d59 100644
--- a/src/opt/sim/simSwitch.c
+++ b/src/opt/sim/simSwitch.c
@@ -29,7 +29,7 @@ static void Sim_NodeSimulate( Abc_Obj_t * pNode, Vec_Ptr_t * vSimInfo, int nSimW
static float Sim_ComputeSwitching( unsigned * pSimInfo, int nSimWords );
////////////////////////////////////////////////////////////////////////
-/// FUNCTION DEFITIONS ///
+/// FUNCTION DEFINITIONS ///
////////////////////////////////////////////////////////////////////////
/**Function*************************************************************
@@ -65,7 +65,7 @@ Vec_Int_t * Sim_NtkComputeSwitching( Abc_Ntk_t * pNtk, int nPatterns )
Abc_NtkForEachCi( pNtk, pNode, i )
{
pSimInfo = Vec_PtrEntry(vSimInfo, pNode->Id);
- Sim_UtilGetRandom( pSimInfo, nSimWords );
+ Sim_UtilSetRandom( pSimInfo, nSimWords );
pSwitching[pNode->Id] = Sim_ComputeSwitching( pSimInfo, nSimWords );
}
// simulate the internal nodes
@@ -73,7 +73,7 @@ Vec_Int_t * Sim_NtkComputeSwitching( Abc_Ntk_t * pNtk, int nPatterns )
Vec_PtrForEachEntry( vNodes, pNode, i )
{
pSimInfo = Vec_PtrEntry(vSimInfo, pNode->Id);
- Sim_UtilSimulateNodeOne( pNode, vSimInfo, nSimWords );
+ Sim_UtilSimulateNodeOne( pNode, vSimInfo, nSimWords, 0 );
pSwitching[pNode->Id] = Sim_ComputeSwitching( pSimInfo, nSimWords );
}
Vec_PtrFree( vNodes );
diff --git a/src/opt/sim/simSym.c b/src/opt/sim/simSym.c
index c452bb1b..71de5b05 100644
--- a/src/opt/sim/simSym.c
+++ b/src/opt/sim/simSym.c
@@ -26,7 +26,7 @@
////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////
-/// FUNCTION DEFITIONS ///
+/// FUNCTION DEFINITIONS ///
////////////////////////////////////////////////////////////////////////
/**Function*************************************************************
@@ -71,7 +71,7 @@ p->timeStruct = clock() - clk;
for ( i = 1; i <= 1000; i++ )
{
// simulate this pattern
- Sim_UtilGetRandom( p->uPatRand, p->nSimWords );
+ Sim_UtilSetRandom( p->uPatRand, p->nSimWords );
Sim_SymmsSimulate( p, p->uPatRand, p->vMatrNonSymms );
if ( i % 50 != 0 )
continue;
@@ -125,6 +125,7 @@ p->timeStruct = clock() - clk;
if ( fVerbose )
printf( "Total = %8d. Sym = %8d. NonSym = %8d. Remaining = %8d.\n",
p->nPairsTotal, p->nPairsSymm, p->nPairsNonSymm, p->nPairsRem );
+// Sim_UtilCountPairsAllPrint( p );
Result = p->nPairsSymm;
vResult = p->vMatrSymms;
diff --git a/src/opt/sim/simSymSat.c b/src/opt/sim/simSymSat.c
index db9917b3..7690a891 100644
--- a/src/opt/sim/simSymSat.c
+++ b/src/opt/sim/simSymSat.c
@@ -26,11 +26,10 @@
/// DECLARATIONS ///
////////////////////////////////////////////////////////////////////////
-extern int Sim_SymmsSatProveOne( Sym_Man_t * p, int Out, int Var1, int Var2, unsigned * pPattern );
-extern Fraig_Man_t * Abc_NtkToFraig( Abc_Ntk_t * pNtk, Fraig_Params_t * pParams, int fAllNodes );
+static int Sim_SymmsSatProveOne( Sym_Man_t * p, int Out, int Var1, int Var2, unsigned * pPattern );
////////////////////////////////////////////////////////////////////////
-/// FUNCTION DEFITIONS ///
+/// FUNCTION DEFINITIONS ///
////////////////////////////////////////////////////////////////////////
/**Function*************************************************************
@@ -145,9 +144,10 @@ int Sim_SymmsSatProveOne( Sym_Man_t * p, int Out, int Var1, int Var2, unsigned *
Params.fInternal = 1;
Params.nPatsRand = 512;
Params.nPatsDyna = 512;
+ Params.nSeconds = ABC_INFINITY;
clk = clock();
- pMan = Abc_NtkToFraig( pMiter, &Params, 0 );
+ pMan = Abc_NtkToFraig( pMiter, &Params, 0, 0 );
p->timeFraig += clock() - clk;
clk = clock();
Fraig_ManProveMiter( pMan );
diff --git a/src/opt/sim/simSymSim.c b/src/opt/sim/simSymSim.c
index 94028c47..2282825b 100644
--- a/src/opt/sim/simSymSim.c
+++ b/src/opt/sim/simSymSim.c
@@ -29,7 +29,7 @@ static void Sim_SymmsCreateSquare( Sym_Man_t * p, unsigned * pPat );
static void Sim_SymmsDeriveInfo( Sym_Man_t * p, unsigned * pPat, Abc_Obj_t * pNode, Vec_Ptr_t * vMatrsNonSym, int Output );
////////////////////////////////////////////////////////////////////////
-/// FUNCTION DEFITIONS ///
+/// FUNCTION DEFINITIONS ///
////////////////////////////////////////////////////////////////////////
/**Function*************************************************************
@@ -55,9 +55,9 @@ void Sim_SymmsSimulate( Sym_Man_t * p, unsigned * pPat, Vec_Ptr_t * vMatrsNonSym
clk = clock();
Vec_PtrForEachEntry( p->vNodes, pNode, i )
{
- if ( Abc_NodeIsConst(pNode) )
- continue;
- Sim_UtilSimulateNodeOne( pNode, p->vSim, p->nSimWords );
+// if ( Abc_NodeIsConst(pNode) )
+// continue;
+ Sim_UtilSimulateNodeOne( pNode, p->vSim, p->nSimWords, 0 );
}
p->timeSim += clock() - clk;
// collect info into the CO matrices
@@ -65,8 +65,8 @@ clk = clock();
Abc_NtkForEachCo( p->pNtk, pNode, i )
{
pNode = Abc_ObjFanin0(pNode);
- if ( Abc_ObjIsCi(pNode) || Abc_NodeIsConst(pNode) )
- continue;
+// if ( Abc_ObjIsCi(pNode) || Abc_AigNodeIsConst(pNode) )
+// continue;
nPairsTotal = Vec_IntEntry(p->vPairsTotal, i);
nPairsSym = Vec_IntEntry(p->vPairsSym, i);
nPairsNonSym = Vec_IntEntry(p->vPairsNonSym,i);
diff --git a/src/opt/sim/simSymStr.c b/src/opt/sim/simSymStr.c
index ed7e93bf..d52c4328 100644
--- a/src/opt/sim/simSymStr.c
+++ b/src/opt/sim/simSymStr.c
@@ -41,7 +41,7 @@ static void Sim_SymmsTransferToMatrix( Extra_BitMat_t * pMatSymm, Vec_Int_t * v
static int * Sim_SymmsCreateMap( Abc_Ntk_t * pNtk );
////////////////////////////////////////////////////////////////////////
-/// FUNCTION DEFITIONS ///
+/// FUNCTION DEFINITIONS ///
////////////////////////////////////////////////////////////////////////
/**Function*************************************************************
@@ -74,15 +74,16 @@ void Sim_SymmsStructCompute( Abc_Ntk_t * pNtk, Vec_Ptr_t * vMatrs, Vec_Ptr_t * v
vNodes = Abc_NtkDfs( pNtk, 0 );
Vec_PtrForEachEntry( vNodes, pTemp, i )
{
- if ( Abc_NodeIsConst(pTemp) )
- continue;
+// if ( Abc_NodeIsConst(pTemp) )
+// continue;
Sim_SymmsStructComputeOne( pNtk, pTemp, pMap );
}
// collect the results for the COs;
Abc_NtkForEachCo( pNtk, pTemp, i )
{
+//printf( "Output %d:\n", i );
pTemp = Abc_ObjFanin0(pTemp);
- if ( Abc_ObjIsCi(pTemp) || Abc_NodeIsConst(pTemp) )
+ if ( Abc_ObjIsCi(pTemp) || Abc_AigNodeIsConst(pTemp) )
continue;
Sim_SymmsTransferToMatrix( Vec_PtrEntry(vMatrs, i), SIM_READ_SYMMS(pTemp), Vec_PtrEntry(vSuppFun, i) );
}
@@ -92,7 +93,7 @@ void Sim_SymmsStructCompute( Abc_Ntk_t * pNtk, Vec_Ptr_t * vMatrs, Vec_Ptr_t * v
Abc_NtkForEachCi( pNtk, pTemp, i )
Vec_IntFree( SIM_READ_SYMMS(pTemp) );
Vec_PtrForEachEntry( vNodes, pTemp, i )
- if ( !Abc_NodeIsConst(pTemp) )
+// if ( !Abc_NodeIsConst(pTemp) )
Vec_IntFree( SIM_READ_SYMMS(pTemp) );
Vec_PtrFree( vNodes );
free( pMap );
@@ -444,6 +445,7 @@ void Sim_SymmsTransferToMatrix( Extra_BitMat_t * pMatSymm, Vec_Int_t * vSymms, u
uSymm = (unsigned)vSymms->pArray[i];
Ind1 = (uSymm & 0xffff);
Ind2 = (uSymm >> 16);
+//printf( "%d,%d ", Ind1, Ind2 );
// skip variables that are not in the true support
assert( Sim_HasBit(pSupport, Ind1) == Sim_HasBit(pSupport, Ind2) );
if ( !Sim_HasBit(pSupport, Ind1) || !Sim_HasBit(pSupport, Ind2) )
diff --git a/src/opt/sim/simUtils.c b/src/opt/sim/simUtils.c
index 4b89c650..b0660001 100644
--- a/src/opt/sim/simUtils.c
+++ b/src/opt/sim/simUtils.c
@@ -37,7 +37,7 @@ static int bit_count[256] = {
};
////////////////////////////////////////////////////////////////////////
-/// FUNCTION DEFITIONS ///
+/// FUNCTION DEFINITIONS ///
////////////////////////////////////////////////////////////////////////
/**Function*************************************************************
@@ -232,9 +232,6 @@ void Sim_UtilSimulateNode( Sim_Man_t * p, Abc_Obj_t * pNode, bool fType, bool fT
// simulate the internal nodes
if ( Abc_ObjIsNode(pNode) )
{
- if ( Abc_NodeIsConst(pNode) )
- return;
-
if ( fType )
pSimmNode = p->vSim1->pArray[ pNode->Id ];
else
@@ -299,17 +296,18 @@ void Sim_UtilSimulateNode( Sim_Man_t * p, Abc_Obj_t * pNode, bool fType, bool fT
SeeAlso []
***********************************************************************/
-void Sim_UtilSimulateNodeOne( Abc_Obj_t * pNode, Vec_Ptr_t * vSimInfo, int nSimWords )
+void Sim_UtilSimulateNodeOne( Abc_Obj_t * pNode, Vec_Ptr_t * vSimInfo, int nSimWords, int nOffset )
{
unsigned * pSimmNode, * pSimmNode1, * pSimmNode2;
int k, fComp1, fComp2;
// simulate the internal nodes
assert( Abc_ObjIsNode(pNode) );
- if ( Abc_NodeIsConst(pNode) )
- return;
pSimmNode = Vec_PtrEntry(vSimInfo, pNode->Id);
pSimmNode1 = Vec_PtrEntry(vSimInfo, Abc_ObjFaninId0(pNode));
pSimmNode2 = Vec_PtrEntry(vSimInfo, Abc_ObjFaninId1(pNode));
+ pSimmNode += nOffset;
+ pSimmNode1 += nOffset;
+ pSimmNode2 += nOffset;
fComp1 = Abc_ObjFaninC0(pNode);
fComp2 = Abc_ObjFaninC1(pNode);
if ( fComp1 && fComp2 )
@@ -328,6 +326,36 @@ void Sim_UtilSimulateNodeOne( Abc_Obj_t * pNode, Vec_Ptr_t * vSimInfo, int nSimW
/**Function*************************************************************
+ Synopsis [Simulates one node.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Sim_UtilTransferNodeOne( Abc_Obj_t * pNode, Vec_Ptr_t * vSimInfo, int nSimWords, int nOffset, int fShift )
+{
+ unsigned * pSimmNode, * pSimmNode1;
+ int k, fComp1;
+ // simulate the internal nodes
+ assert( Abc_ObjIsCo(pNode) );
+ pSimmNode = Vec_PtrEntry(vSimInfo, pNode->Id);
+ pSimmNode1 = Vec_PtrEntry(vSimInfo, Abc_ObjFaninId0(pNode));
+ pSimmNode += nOffset + (fShift > 0)*nSimWords;
+ pSimmNode1 += nOffset;
+ fComp1 = Abc_ObjFaninC0(pNode);
+ if ( fComp1 )
+ for ( k = 0; k < nSimWords; k++ )
+ pSimmNode[k] = ~pSimmNode1[k];
+ else
+ for ( k = 0; k < nSimWords; k++ )
+ pSimmNode[k] = pSimmNode1[k];
+}
+
+/**Function*************************************************************
+
Synopsis [Returns 1 if the simulation infos are equal.]
Description []
@@ -380,10 +408,31 @@ int Sim_UtilCountOnes( unsigned * pSimInfo, int nSimWords )
return nOnes;
}
+/**Function*************************************************************
+
+ Synopsis [Counts the number of 1's in the bitstring.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Vec_Int_t * Sim_UtilCountOnesArray( Vec_Ptr_t * vInfo, int nSimWords )
+{
+ Vec_Int_t * vCounters;
+ unsigned * pSimInfo;
+ int i;
+ vCounters = Vec_IntStart( Vec_PtrSize(vInfo) );
+ Vec_PtrForEachEntry( vInfo, pSimInfo, i )
+ Vec_IntWriteEntry( vCounters, i, Sim_UtilCountOnes(pSimInfo, nSimWords) );
+ return vCounters;
+}
/**Function*************************************************************
- Synopsis [Returns the random pattern.]
+ Synopsis [Returns random patterns.]
Description []
@@ -392,7 +441,7 @@ int Sim_UtilCountOnes( unsigned * pSimInfo, int nSimWords )
SeeAlso []
***********************************************************************/
-void Sim_UtilGetRandom( unsigned * pPatRand, int nSimWords )
+void Sim_UtilSetRandom( unsigned * pPatRand, int nSimWords )
{
int k;
for ( k = 0; k < nSimWords; k++ )
@@ -401,6 +450,104 @@ void Sim_UtilGetRandom( unsigned * pPatRand, int nSimWords )
/**Function*************************************************************
+ Synopsis [Returns complemented patterns.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Sim_UtilSetCompl( unsigned * pPatRand, int nSimWords )
+{
+ int k;
+ for ( k = 0; k < nSimWords; k++ )
+ pPatRand[k] = ~pPatRand[k];
+}
+
+/**Function*************************************************************
+
+ Synopsis [Returns constant patterns.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Sim_UtilSetConst( unsigned * pPatRand, int nSimWords, int fConst1 )
+{
+ int k;
+ for ( k = 0; k < nSimWords; k++ )
+ pPatRand[k] = 0;
+ if ( fConst1 )
+ Sim_UtilSetCompl( pPatRand, nSimWords );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Returns 1 if equal.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Sim_UtilInfoIsEqual( unsigned * pPats1, unsigned * pPats2, int nSimWords )
+{
+ int k;
+ for ( k = 0; k < nSimWords; k++ )
+ if ( pPats1[k] != pPats2[k] )
+ return 0;
+ return 1;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Returns 1 if Node1 implies Node2.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Sim_UtilInfoIsImp( unsigned * pPats1, unsigned * pPats2, int nSimWords )
+{
+ int k;
+ for ( k = 0; k < nSimWords; k++ )
+ if ( pPats1[k] & ~pPats2[k] )
+ return 0;
+ return 1;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Returns 1 if Node1 v Node2 is always true.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Sim_UtilInfoIsClause( unsigned * pPats1, unsigned * pPats2, int nSimWords )
+{
+ int k;
+ for ( k = 0; k < nSimWords; k++ )
+ if ( ~pPats1[k] & ~pPats2[k] )
+ return 0;
+ return 1;
+}
+
+/**Function*************************************************************
+
Synopsis [Counts the total number of pairs.]
Description []
@@ -460,6 +607,51 @@ int Sim_UtilCountPairsOne( Extra_BitMat_t * pMat, Vec_Int_t * vSupport )
SeeAlso []
***********************************************************************/
+int Sim_UtilCountPairsOnePrint( Extra_BitMat_t * pMat, Vec_Int_t * vSupport )
+{
+ int i, k, Index1, Index2;
+ Vec_IntForEachEntry( vSupport, i, Index1 )
+ Vec_IntForEachEntryStart( vSupport, k, Index2, Index1+1 )
+ if ( Extra_BitMatrixLookup1( pMat, i, k ) )
+ printf( "(%d,%d) ", i, k );
+ return 0;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Counts the number of entries in the array of matrices.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Sim_UtilCountPairsAllPrint( Sym_Man_t * p )
+{
+ int i, clk;
+clk = clock();
+ for ( i = 0; i < p->nOutputs; i++ )
+ {
+ printf( "Output %2d :", i );
+ Sim_UtilCountPairsOnePrint( Vec_PtrEntry(p->vMatrSymms, i), Vec_VecEntry(p->vSupports, i) );
+ printf( "\n" );
+ }
+p->timeCount += clock() - clk;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Counts the number of entries in the array of matrices.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
void Sim_UtilCountPairsAll( Sym_Man_t * p )
{
int nPairsTotal, nPairsSym, nPairsNonSym, i, clk;
diff --git a/src/phys/place/Makefile b/src/phys/place/Makefile
new file mode 100644
index 00000000..1f700105
--- /dev/null
+++ b/src/phys/place/Makefile
@@ -0,0 +1,30 @@
+TARGETS = place_test BookshelfView.class
+
+CFLAGS = -g -pedantic -Wall
+
+STATIC_LIBS = libhmetis.a
+DYNAMIC_LIBS = -lm
+
+OBJECTS = place_test.o place_qpsolver.o place_base.o place_pads.o place_genqp.o place_gordian.o \
+ place_partition.o place_legalize.o place_bin.o
+
+
+# For hMetis free code, uncomment the following lines
+#
+# CFLAGS = -g -pedantic -Wall -DNO_HMETIS
+# STATIC_LIBS =
+
+
+all: $(TARGETS)
+
+%.o: %.c *.h
+ gcc $(CFLAGS) -c -o $@ $<
+
+place_test: $(OBJECTS)
+ gcc *.o $(STATIC_LIBS) $(DYNAMIC_LIBS) -o place_test
+
+BookshelfView.class: BookshelfView.java
+ javac BookshelfView.java
+
+clean:
+ rm -rf *.o place_test *.class *~
diff --git a/src/phys/place/README b/src/phys/place/README
new file mode 100644
index 00000000..d4f8ac8f
--- /dev/null
+++ b/src/phys/place/README
@@ -0,0 +1,50 @@
+/*===================================================================*/
+//
+// GORDIAN-like placement package
+//
+// Aaron P. Hurst (ahurst@eecs.berkeley.edu)
+// Addl code from Philip Chong (pchong@cadence.com)
+// hMetis partitioner (www.cs.umn.edu/~metis)
+//
+/*===================================================================*/
+
+1. Requirements
+
+An i386 Linux system (though others will certainly work with some tweaks).
+A standard ANSI C development platform.
+
+The following are optional, but useful:
+
+- hMetis partitioner. This can be obtained from (www.cs.umn.edu/~metis)
+ Place (links to) the files "libhmetis.a" and "libhtmetis.h" in this directory.
+ Otherwise, #define NO_HMETIS in the file "place_gordian.h"
+- Java SDK, if compiling BookshelfView is desired.
+- Perl, if additional script utilities are desired.
+
+2. Descriptions of contents:
+
+place_base.h contains the basic data structures and "external" API.
+place_gordian.h contains the "internal" API and configuration options.
+
+There are also several utilities:
+
+i) place_test
+
+Reads a netlist description in GSRC Bookshelf format, performs global placement,
+and rewrites the placement file. An example usage:
+
+./place_test ac97_emap.nodes ac97_emap.nets ac97_emap.pl
+
+ii) BookshelfView
+
+A simple Java GUI to view the resulting placements. It has been tested with
+Java 5 and 6. Usage:
+
+java BookshelfView ac97_emap.nodes ac97_emap.pl
+
+iii) hpwl
+
+A perl script to print the half-perimeter wirelength of a placement. Usage:
+
+./hpwl ac97_emap.nets ac97_emal.pl
+
diff --git a/src/phys/place/hpwl b/src/phys/place/hpwl
new file mode 100644
index 00000000..f69a1d05
--- /dev/null
+++ b/src/phys/place/hpwl
@@ -0,0 +1,57 @@
+#! /usr/bin/perl
+
+$netsfile = shift;
+$plfile = shift;
+
+# ------------------------------ read placement
+
+open FILE, $plfile;
+while (<FILE>) {
+ chop;
+ if (/(\w+)\s+([\-\d\.]+)\s+([\-\d\.]+)\s+\:/) {
+ $loc{$1} = "$2 $3";
+ }
+}
+close FILE;
+
+open FILE, $netsfile;
+while (<FILE>) {
+ chop;
+ $net = $2 if /NetDegree\s+\:\s+(\d+)\s+(\w+)/;
+ if (/(\w+)\s+(\w+)\s+\:/) {
+ $netconn{$net} .= "$1 ";
+ $cellconn{$1} .= "$net ";
+ }
+}
+close FILE;
+
+# ----------------------------- compute HPWL
+
+$hpwl = 0;
+foreach $net (keys %netconn) {
+ @conns = split ' ',$netconn{$net};
+ $min_x = $min_y = 1e12;
+ $max_x = $max_y = -1e12;
+ foreach $cell (@conns) {
+ if (!exists $loc{$cell}) {
+ print "WARNING: Unknown cell location: $cell\n";
+ } else {
+ ($x, $y) = split ' ',$loc{$cell};
+ $min_x = $x if $x < $min_x;
+ $min_y = $y if $y < $min_y;
+ $max_x = $x if $x > $max_x;
+ $max_y = $y if $y > $max_y;
+ }
+ }
+
+ if ($min_x eq 1e12 or $min_y eq 1e12 or
+ $max_x eq -1e12 or $max_y eq -1e12) {
+ print "WARNING: Unbounded box\n";
+ } else {
+ $hpwl = $hpwl + $max_x - $min_x + $max_y - $min_y;
+ }
+}
+
+print "HPWL = ";
+printf "%e",$hpwl;
+print "\n";
diff --git a/src/phys/place/libhmetis.h b/src/phys/place/libhmetis.h
new file mode 100644
index 00000000..051079d4
--- /dev/null
+++ b/src/phys/place/libhmetis.h
@@ -0,0 +1,31 @@
+// A. Hurst ahurst@eecs.berkeley.edu
+
+#ifndef LIBHMETIS_H_
+#define LIBHMETIS_H_
+
+static void HMETIS_PartRecursive(int nvtxs,
+ int nhedges,
+ int *vwgts,
+ int *eptr,
+ int *eind,
+ int *hewgts,
+ int nparts,
+ int nbfactor,
+ int *options,
+ int *part,
+ int *edgecnt ) {} //;
+
+
+static void HMETIS_PartKway(int nvtxs,
+ int nhedges,
+ int *vwgts,
+ int *eptr,
+ int *eind,
+ int *hewgts,
+ int nparts,
+ int nbfactor,
+ int *options,
+ int *part,
+ int *edgecnt ) {} //;
+
+#endif
diff --git a/src/phys/place/module.make b/src/phys/place/module.make
new file mode 100644
index 00000000..98930fbe
--- /dev/null
+++ b/src/phys/place/module.make
@@ -0,0 +1,10 @@
+SRC += src/phys/place/place_base.c \
+ src/phys/place/place_bin.c \
+ src/phys/place/place_genqp.c \
+ src/phys/place/place_gordian.c \
+ src/phys/place/place_legalize.c \
+ src/phys/place/place_pads.c \
+ src/phys/place/place_partition.c \
+ src/phys/place/place_qpsolver.c \
+ src/phys/place/place_io.c \
+ src/phys/place/place_inc.c
diff --git a/src/phys/place/place_base.c b/src/phys/place/place_base.c
new file mode 100644
index 00000000..4e38f1d1
--- /dev/null
+++ b/src/phys/place/place_base.c
@@ -0,0 +1,345 @@
+/*===================================================================*/
+//
+// place_base.c
+//
+// Aaron P. Hurst, 2003-2007
+// ahurst@eecs.berkeley.edu
+//
+/*===================================================================*/
+
+#include <stdlib.h>
+#include <limits.h>
+#include <assert.h>
+#include <string.h>
+
+#include "place_base.h"
+#include "place_gordian.h"
+
+// --------------------------------------------------------------------
+// Global variables
+//
+// --------------------------------------------------------------------
+
+int g_place_numCells = 0;
+int g_place_numNets = 0;
+float g_place_rowHeight = 1.0;
+
+Rect g_place_coreBounds;
+Rect g_place_padBounds;
+
+ConcreteCell **g_place_concreteCells = NULL;
+int g_place_concreteCellsSize = 0;
+ConcreteNet **g_place_concreteNets = NULL;
+int g_place_concreteNetsSize = 0;
+
+
+// --------------------------------------------------------------------
+// getNetBBox()
+//
+/// \brief Returns the bounding box of a net.
+//
+// --------------------------------------------------------------------
+Rect getNetBBox(const ConcreteNet *net) {
+ int t;
+ Rect r;
+
+ assert(net);
+
+ r.x = r.y = INT_MAX;
+ r.w = r.h = -INT_MAX;
+ for(t=0; t<net->m_numTerms; t++) {
+ r.x = net->m_terms[t]->m_x < r.x ? net->m_terms[t]->m_x : r.x;
+ r.y = net->m_terms[t]->m_y < r.y ? net->m_terms[t]->m_y : r.y;
+ r.w = net->m_terms[t]->m_x > r.w ? net->m_terms[t]->m_x : r.w;
+ r.h = net->m_terms[t]->m_y > r.h ? net->m_terms[t]->m_y : r.h;
+ }
+ r.w -= r.x; r.h -= r.y;
+ return r;
+}
+
+
+// --------------------------------------------------------------------
+// getNetWirelength()
+//
+/// \brief Returns the half-perimeter wirelength of a net.
+//
+// --------------------------------------------------------------------
+float getNetWirelength(const ConcreteNet *net) {
+ Rect r;
+
+ assert(net);
+
+ r = getNetBBox(net);
+ return r.w+r.h;
+}
+
+
+// --------------------------------------------------------------------
+// getTotalWirelength()
+//
+/// \brief Returns the total HPWL of all nets.
+//
+// --------------------------------------------------------------------
+float getTotalWirelength() {
+ float r = 0;
+ int n;
+ for(n=0; n<g_place_numNets; n++) if (g_place_concreteNets[n])
+ r += getNetWirelength(g_place_concreteNets[n]);
+ return r;
+}
+
+
+// --------------------------------------------------------------------
+// getCellArea()
+//
+// --------------------------------------------------------------------
+float getCellArea(const ConcreteCell *cell) {
+ assert(cell);
+ return cell->m_parent->m_width*cell->m_parent->m_height;
+}
+
+
+// --------------------------------------------------------------------
+// addConcreteNet()
+//
+/// \brief Adds a net to the placement database.
+///
+/// The net object must already be allocated and the ID must be set
+/// appropriately.
+//
+// --------------------------------------------------------------------
+void addConcreteNet(ConcreteNet *net) {
+ assert(net);
+ assert(net->m_id >= 0);
+ if (net->m_id >= g_place_concreteNetsSize) {
+ g_place_concreteNetsSize = (net->m_id > g_place_concreteNetsSize ?
+ net->m_id : g_place_concreteNetsSize);
+ g_place_concreteNetsSize *= 1.5;
+ g_place_concreteNetsSize += 20;
+ g_place_concreteNets = (ConcreteNet**)realloc(g_place_concreteNets,
+ sizeof(ConcreteNet*)*g_place_concreteNetsSize);
+ assert(g_place_concreteNets);
+ }
+ if (net->m_id >= g_place_numNets) {
+ memset(&(g_place_concreteNets[g_place_numNets]), 0,
+ sizeof(ConcreteNet*)*(net->m_id+1-g_place_numNets));
+ g_place_numNets = net->m_id+1;
+ assert(g_place_numNets <= g_place_concreteNetsSize);
+ }
+ g_place_concreteNets[net->m_id] = net;
+}
+
+
+// --------------------------------------------------------------------
+// delConcreteNet()
+//
+/// Does not deallocate memory.
+// --------------------------------------------------------------------
+void delConcreteNet(ConcreteNet *net) {
+ assert(net);
+ g_place_concreteNets[net->m_id] = 0;
+ while(!g_place_concreteNets[g_place_numNets-1]) g_place_numNets--;
+}
+
+
+// --------------------------------------------------------------------
+// addConcreteCell()
+//
+/// The cell object must already be allocated and the ID must be set
+/// appropriately.
+//
+// --------------------------------------------------------------------
+void addConcreteCell(ConcreteCell *cell) {
+ assert(cell);
+ assert(cell->m_id >= 0);
+ if (cell->m_id >= g_place_concreteCellsSize) {
+ g_place_concreteCellsSize = (cell->m_id > g_place_concreteCellsSize ?
+ cell->m_id : g_place_concreteCellsSize);
+ g_place_concreteCellsSize *= 1.5;
+ g_place_concreteCellsSize += 20;
+ g_place_concreteCells = (ConcreteCell**)realloc(g_place_concreteCells,
+ sizeof(ConcreteCell*)*g_place_concreteCellsSize);
+ assert(g_place_concreteCells);
+ }
+ if (cell->m_id >= g_place_numCells) {
+ memset(&(g_place_concreteCells[g_place_numCells]), 0,
+ sizeof(ConcreteCell*)*(cell->m_id+1-g_place_numCells));
+ g_place_numCells = cell->m_id+1;
+ }
+ g_place_concreteCells[cell->m_id] = cell;
+}
+
+
+// --------------------------------------------------------------------
+// delCellFromPartition()
+//
+// --------------------------------------------------------------------
+void delCellFromPartition(ConcreteCell *cell, Partition *p) {
+ int c;
+ bool found = false;
+
+ assert(cell);
+ assert(p);
+
+ for(c=0; c<p->m_numMembers; c++)
+ if (p->m_members[c] == cell) {
+ p->m_members[c] = 0;
+ p->m_area -= getCellArea(cell);
+ found = true;
+ break;
+ }
+
+ if (!found) return;
+
+ if (!p->m_leaf) {
+ delCellFromPartition(cell, p->m_sub1);
+ delCellFromPartition(cell, p->m_sub2);
+ }
+}
+
+
+// --------------------------------------------------------------------
+// delConcreteCell()
+//
+/// \brief Removes a cell from the placement database.
+///
+/// Does not deallocate memory.
+///
+/// Important: does not modify nets that may point to this
+/// cell. If these are connections are not removed, segmentation faults
+/// and other nasty errors will occur.
+//
+// --------------------------------------------------------------------
+void delConcreteCell(ConcreteCell *cell) {
+ assert(cell);
+ g_place_concreteCells[cell->m_id] = 0;
+ while(!g_place_concreteCells[g_place_numCells-1]) g_place_numCells--;
+
+ if (g_place_rootPartition) delCellFromPartition(cell, g_place_rootPartition);
+}
+
+
+// --------------------------------------------------------------------
+// netSortByX...
+//
+/// \brief Sorts nets by position of one of its corners.
+//
+/// These are for use with qsort().
+///
+/// Can tolerate pointers to NULL objects.
+///
+// --------------------------------------------------------------------
+int netSortByL(const void *a, const void *b) {
+ const ConcreteNet *pa = *(const ConcreteNet **)a;
+ const ConcreteNet *pb = *(const ConcreteNet **)b;
+ Rect ba, bb;
+
+ if (!pa && !pb) return 0;
+ else if (!pa) return -1;
+ else if (!pb) return 1;
+ ba = getNetBBox(pa), bb = getNetBBox(pb);
+ if (ba.x < bb.x) return -1;
+ if (ba.x > bb.x) return 1;
+ return 0;
+}
+
+int netSortByR(const void *a, const void *b) {
+ const ConcreteNet *pa = *(const ConcreteNet **)a;
+ const ConcreteNet *pb = *(const ConcreteNet **)b;
+ Rect ba, bb;
+
+ if (!pa && !pb) return 0;
+ else if (!pa) return -1;
+ else if (!pb) return 1;
+ ba = getNetBBox(pa), bb = getNetBBox(pb);
+ if (ba.x + ba.w < bb.x + bb.w) return -1;
+ if (ba.x + ba.w > bb.x + bb.w) return 1;
+ return 0;
+}
+
+int netSortByB(const void *a, const void *b) {
+ const ConcreteNet *pa = *(const ConcreteNet **)a;
+ const ConcreteNet *pb = *(const ConcreteNet **)b;
+ Rect ba, bb;
+
+ if (!pa && !pb) return 0;
+ else if (!pa) return -1;
+ else if (!pb) return 1;
+ ba = getNetBBox(pa), bb = getNetBBox(pb);
+ if (ba.y + ba.h < bb.y + bb.h) return -1;
+ if (ba.y + ba.h > bb.y + bb.h) return 1;
+ return 0;
+}
+
+int netSortByT(const void *a, const void *b) {
+ const ConcreteNet *pa = *(const ConcreteNet **)a;
+ const ConcreteNet *pb = *(const ConcreteNet **)b;
+ Rect ba, bb;
+
+ if (!pa && !pb) return 0;
+ else if (!pa) return -1;
+ else if (!pb) return 1;
+ ba = getNetBBox(pa), bb = getNetBBox(pb);
+ if (ba.y < bb.y) return -1;
+ if (ba.y > bb.y) return 1;
+ return 0;
+}
+
+int netSortByID(const void *a, const void *b) {
+ const ConcreteNet *pa = *(const ConcreteNet **)a;
+ const ConcreteNet *pb = *(const ConcreteNet **)b;
+
+ if (!pa && !pb) return 0;
+ else if (!pa) return -1;
+ else if (!pb) return 1;
+ if (pa->m_id < pb->m_id) return -1;
+ if (pa->m_id > pb->m_id) return 1;
+ return 0;
+}
+
+
+// --------------------------------------------------------------------
+// cellSortByX...
+//
+/// \brief Sorts cells by either position coordinate.
+//
+/// These are for use with qsort().
+///
+/// Can tolerate pointers to NULL objects.
+//
+// --------------------------------------------------------------------
+int cellSortByX(const void *a, const void *b) {
+ const ConcreteCell *pa = *(const ConcreteCell **)a;
+ const ConcreteCell *pb = *(const ConcreteCell **)b;
+
+ if (!pa && !pb) return 0;
+ else if (!pa) return -1;
+ else if (!pb) return 1;
+ if (pa->m_x < pb->m_x) return -1;
+ if (pa->m_x > pb->m_x) return 1;
+ return 0;
+}
+
+int cellSortByY(const void *a, const void *b) {
+ const ConcreteCell *pa = *(const ConcreteCell **)a;
+ const ConcreteCell *pb = *(const ConcreteCell **)b;
+
+ if (!pa && !pb) return 0;
+ else if (!pa) return -1;
+ else if (!pb) return 1;
+ if (pa->m_y < pb->m_y) return -1;
+ if (pa->m_y > pb->m_y) return 1;
+ return 0;
+}
+
+int cellSortByID(const void *a, const void *b) {
+ const ConcreteCell *pa = *(const ConcreteCell **)a;
+ const ConcreteCell *pb = *(const ConcreteCell **)b;
+
+ if (!pa && !pb) return 0;
+ else if (!pa) return -1;
+ else if (!pb) return 1;
+ if (pa->m_id < pb->m_id) return -1;
+ if (pa->m_id > pb->m_id) return 1;
+ return 0;
+}
diff --git a/src/phys/place/place_base.h b/src/phys/place/place_base.h
new file mode 100644
index 00000000..e5e7ecef
--- /dev/null
+++ b/src/phys/place/place_base.h
@@ -0,0 +1,137 @@
+/*===================================================================*/
+//
+// place_base.h
+//
+// Aaron P. Hurst, 2003-2007
+// ahurst@eecs.berkeley.edu
+//
+/*===================================================================*/
+
+#if !defined(PLACE_BASE_H_)
+#define PLACE_BASE_H_
+
+// --------------------------------------------------------------------
+// Data structures
+//
+// --------------------------------------------------------------------
+
+// --- a C++ bool-like type
+//typedef char bool;
+#ifndef bool
+#define bool int
+#endif
+
+#define true 1
+#define false 0
+
+
+// --- Rect - rectangle
+
+typedef struct Rect {
+ float x, y;
+ float w, h;
+} Rect;
+
+
+// --- AbstractCell - a definition of a cell type
+
+typedef struct AbstractCell {
+ char *m_label; // string description
+
+ float m_width, m_height; // dimensions
+
+ bool m_pad; // a pad (external I/O) cell?
+} AbstractCell;
+
+
+// --- ConcreteCell - a design object
+
+typedef struct ConcreteCell {
+ int m_id; // a unique ID (see below)
+ char *m_label; // string description
+
+ AbstractCell *m_parent; // cell type
+
+ bool m_fixed; // position is fixed?
+ float m_x, m_y; // center of cell
+
+ int m_data;
+} ConcreteCell;
+
+
+// --- ConcreteNet - a design net
+
+typedef struct ConcreteNet {
+ int m_id; // a unique ID (see below)
+
+ int m_numTerms; // num. of connected cells
+ ConcreteCell **m_terms; // connected cells
+
+ float m_weight; // relative weight
+
+ int m_data;
+} ConcreteNet;
+
+
+// A note about IDs - the IDs are non-nonegative integers. They need not
+// be contiguous, but this is certainly a good idea, as they are stored
+// in a non-sparse array.
+// Cells and nets have separate ID spaces.
+
+// --------------------------------------------------------------------
+// Global variable prototypes
+//
+// --------------------------------------------------------------------
+
+// NOTE: None of these need to be managed externally.
+
+extern int g_place_numCells; // number of cells
+extern int g_place_numNets; // number of nets
+extern float g_place_rowHeight; // height of placement row
+extern Rect g_place_coreBounds; // border of placeable area
+ // (x,y) = corner
+extern Rect g_place_padBounds; // border of total die area
+ // (x,y) = corner
+
+extern ConcreteCell **g_place_concreteCells; // all concrete cells
+extern ConcreteNet **g_place_concreteNets; // all concrete nets
+
+
+// --------------------------------------------------------------------
+// Function prototypes
+//
+// --------------------------------------------------------------------
+
+void addConcreteNet(ConcreteNet *net);
+void addConcreteCell(ConcreteCell *cell);
+void delConcreteNet(ConcreteNet *net);
+void delConcreteCell(ConcreteCell *cell);
+
+void globalPreplace(float utilization);
+void globalPlace();
+void globalIncremental();
+void globalFixDensity(int numBins, float maxMovement);
+
+float fastEstimate(ConcreteCell *cell,
+ int numNets, ConcreteNet *nets[]);
+float fastTopoPlace(int numCells, ConcreteCell *cells[],
+ int numNets, ConcreteNet *nets[]);
+
+Rect getNetBBox(const ConcreteNet *net);
+float getNetWirelength(const ConcreteNet *net);
+float getTotalWirelength();
+float getCellArea(const ConcreteCell *cell);
+
+void writeBookshelf(const char *filename);
+
+// comparative qsort-style functions
+int netSortByL(const void *a, const void *b);
+int netSortByR(const void *a, const void *b);
+int netSortByB(const void *a, const void *b);
+int netSortByT(const void *a, const void *b);
+int netSortByID(const void *a, const void *b);
+int cellSortByX(const void *a, const void *b);
+int cellSortByY(const void *a, const void *b);
+int cellSortByID(const void *a, const void *b);
+
+#endif
diff --git a/src/phys/place/place_bin.c b/src/phys/place/place_bin.c
new file mode 100644
index 00000000..86ec3506
--- /dev/null
+++ b/src/phys/place/place_bin.c
@@ -0,0 +1,277 @@
+/*===================================================================*/
+//
+// place_bin.c
+//
+// Aaron P. Hurst, 2007
+// ahurst@eecs.berkeley.edu
+//
+/*===================================================================*/
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <limits.h>
+#include <assert.h>
+
+//#define DEBUG
+
+#include "place_base.h"
+
+// --------------------------------------------------------------------
+// Global variables
+//
+// --------------------------------------------------------------------
+
+
+// --------------------------------------------------------------------
+// Function prototypes and local data structures
+//
+// --------------------------------------------------------------------
+
+void spreadDensityX(int numBins, float maxMovement);
+void spreadDensityY(int numBins, float maxMovement);
+
+
+// --------------------------------------------------------------------
+// globalFixDensity()
+//
+/// Doesn't deal well with fixed cells in the core area.
+// --------------------------------------------------------------------
+void globalFixDensity(int numBins, float maxMovement) {
+
+ printf("QCLN-10 : \tbin-based density correction\n");
+
+ spreadDensityX(numBins, maxMovement);
+ // spreadDensityY(numBins, maxMovement);
+}
+
+
+// --------------------------------------------------------------------
+// spreadDensityX()
+//
+// --------------------------------------------------------------------
+void spreadDensityX(int numBins, float maxMovement) {
+
+ int c, c2, c3, x, y;
+ float totalArea = 0;
+ int moveableCells = 0;
+ float yBinArea = 0, yCumArea = 0;
+ int yBinStart = 0, yBinCount = 0;
+ int xBinCount, xBinStart;
+ float xBinArea, xCumArea;
+ float lastOldEdge;
+ float lastNewEdge;
+ float curOldEdge, curNewEdge;
+ float stretch, w;
+ ConcreteCell *xCell, *yCell;
+ ConcreteCell **binCells;
+ ConcreteCell **allCells;
+
+ binCells = (ConcreteCell **)malloc(sizeof(ConcreteCell*)*g_place_numCells);
+ allCells = (ConcreteCell **)malloc(sizeof(ConcreteCell*)*g_place_numCells);
+
+ for(c=0; c<g_place_numCells; c++) if (g_place_concreteCells[c]) {
+ ConcreteCell *cell = g_place_concreteCells[c];
+ if (!cell->m_fixed && !cell->m_parent->m_pad) {
+ allCells[moveableCells++] = cell;
+ totalArea += getCellArea(cell);
+ }
+ }
+
+ // spread X
+ qsort(allCells, moveableCells, sizeof(ConcreteCell*), cellSortByY);
+
+ y = 0;
+
+ // for each y-bin...
+ for(c=0; c<moveableCells; c++) {
+ yCell = allCells[c];
+ yBinArea += getCellArea(yCell);
+ yCumArea += getCellArea(yCell);
+ yBinCount++;
+
+ // have we filled up a y-bin?
+ if (yCumArea >= totalArea*(y+1)/numBins && yBinArea > 0) {
+ memcpy(binCells, &(allCells[yBinStart]), sizeof(ConcreteCell*)*yBinCount);
+ qsort(binCells, yBinCount, sizeof(ConcreteCell*), cellSortByX);
+
+#if defined(DEBUG)
+ printf("y-bin %d count=%d area=%f\n",y,yBinCount, yBinArea);
+#endif
+
+ x = 0;
+ xBinCount = 0, xBinStart = 0;
+ xBinArea = 0, xCumArea = 0;
+ lastOldEdge = g_place_coreBounds.x;
+ lastNewEdge = g_place_coreBounds.x;
+
+ // for each x-bin...
+ for(c2=0; c2<yBinCount; c2++) {
+ xCell = binCells[c2];
+ xBinArea += getCellArea(xCell);
+ xCumArea += getCellArea(xCell);
+ xBinCount++;
+ curOldEdge = xCell->m_x;
+
+ printf("%.3f ", xCell->m_x);
+
+ // have we filled up an x-bin?
+ if (xCumArea >= yBinArea*(x+1)/numBins && xBinArea > 0) {
+ curNewEdge = lastNewEdge + g_place_coreBounds.w*xBinArea/yBinArea;
+
+ if (curNewEdge > g_place_coreBounds.x+g_place_coreBounds.w)
+ curNewEdge = g_place_coreBounds.x+g_place_coreBounds.w;
+ if ((curNewEdge-curOldEdge)>maxMovement) curNewEdge = curOldEdge + maxMovement;
+ if ((curOldEdge-curNewEdge)>maxMovement) curNewEdge = curOldEdge - maxMovement;
+
+#if defined(DEBUG)
+ printf("->\tx-bin %d count=%d area=%f (%f,%f)->(%f,%f)\n",x, xBinCount, xBinArea,
+ curOldEdge, lastOldEdge, curNewEdge, lastNewEdge);
+#endif
+
+ stretch = (curNewEdge-lastNewEdge)/(curOldEdge-lastOldEdge);
+
+ // stretch!
+ for(c3=xBinStart; c3<xBinStart+xBinCount; c3++) {
+ if (curOldEdge == lastOldEdge)
+ binCells[c3]->m_x = lastNewEdge+(c3-xBinStart)*(curNewEdge-lastNewEdge);
+ else
+ binCells[c3]->m_x = lastNewEdge+(binCells[c3]->m_x-lastOldEdge)*stretch;
+
+ // force within core
+ w = binCells[c3]->m_parent->m_width*0.5;
+ if (binCells[c3]->m_x-w < g_place_coreBounds.x)
+ binCells[c3]->m_x = g_place_coreBounds.x+w;
+ if (binCells[c3]->m_x+w > g_place_coreBounds.x+g_place_coreBounds.w)
+ binCells[c3]->m_x = g_place_coreBounds.x+g_place_coreBounds.w-w;
+ }
+
+ lastOldEdge = curOldEdge;
+ lastNewEdge = curNewEdge;
+ x++;
+ xBinCount = 0;
+ xBinArea = 0;
+ xBinStart = c2+1;
+ }
+ }
+
+ y++;
+ yBinCount = 0;
+ yBinArea = 0;
+ yBinStart = c+1;
+ }
+ }
+
+ free(binCells);
+ free(allCells);
+}
+
+
+// --------------------------------------------------------------------
+// spreadDensityY()
+//
+// --------------------------------------------------------------------
+void spreadDensityY(int numBins, float maxMovement) {
+
+ int c, c2, c3, x, y;
+ float totalArea = 0;
+ int moveableCells = 0;
+ float xBinArea = 0, xCumArea = 0;
+ int xBinStart = 0, xBinCount = 0;
+ int yBinCount, yBinStart;
+ float yBinArea, yCumArea;
+ float lastOldEdge;
+ float lastNewEdge;
+ float curOldEdge, curNewEdge;
+ float stretch, h;
+ ConcreteCell *xCell, *yCell;
+ ConcreteCell **binCells;
+ ConcreteCell **allCells;
+
+ binCells = (ConcreteCell **)malloc(sizeof(ConcreteCell*)*g_place_numCells);
+ allCells = (ConcreteCell **)malloc(sizeof(ConcreteCell*)*g_place_numCells);
+
+ for(c=0; c<g_place_numCells; c++) if (g_place_concreteCells[c]) {
+ ConcreteCell *cell = g_place_concreteCells[c];
+ if (!cell->m_fixed && !cell->m_parent->m_pad) {
+ allCells[moveableCells++] = cell;
+ totalArea += getCellArea(cell);
+ }
+ }
+
+ // spread Y
+ qsort(allCells, moveableCells, sizeof(ConcreteCell*), cellSortByX);
+
+ x = 0;
+
+ // for each x-bin...
+ for(c=0; c<moveableCells; c++) {
+ xCell = allCells[c];
+ xBinArea += getCellArea(xCell);
+ xCumArea += getCellArea(xCell);
+ xBinCount++;
+
+ // have we filled up an x-bin?
+ if (xCumArea >= totalArea*(x+1)/numBins && xBinArea > 0) {
+ memcpy(binCells, &(allCells[xBinStart]), sizeof(ConcreteCell*)*xBinCount);
+ qsort(binCells, xBinCount, sizeof(ConcreteCell*), cellSortByY);
+
+ // printf("x-bin %d count=%d area=%f\n",y,yBinCount, yBinArea);
+
+ y = 0;
+ yBinCount = 0, yBinStart = 0;
+ yBinArea = 0, yCumArea = 0;
+ lastOldEdge = g_place_coreBounds.y;
+ lastNewEdge = g_place_coreBounds.y;
+
+ // for each y-bin...
+ for(c2=0; c2<xBinCount; c2++) {
+ yCell = binCells[c2];
+ yBinArea += getCellArea(yCell);
+ yCumArea += getCellArea(yCell);
+ yBinCount++;
+ curOldEdge = yCell->m_y;
+
+ // have we filled up an x-bin?
+ if (yCumArea >= xBinArea*(y+1)/numBins && yBinArea > 0) {
+ curNewEdge = lastNewEdge + g_place_coreBounds.h*yBinArea/xBinArea;
+
+ if (curNewEdge > g_place_coreBounds.y+g_place_coreBounds.h)
+ curNewEdge = g_place_coreBounds.y+g_place_coreBounds.h;
+ if ((curNewEdge-curOldEdge)>maxMovement) curNewEdge = curOldEdge + maxMovement;
+ if ((curOldEdge-curNewEdge)>maxMovement) curNewEdge = curOldEdge - maxMovement;
+
+ if (curOldEdge == lastOldEdge) continue; // hmmm
+ stretch = (curNewEdge-lastNewEdge)/(curOldEdge-lastOldEdge);
+
+ // stretch!
+ for(c3=yBinStart; c3<yBinStart+yBinCount; c3++) {
+ binCells[c3]->m_y = lastNewEdge+(binCells[c3]->m_y-lastOldEdge)*stretch;
+
+ // force within core
+ h = binCells[c3]->m_parent->m_height;
+ if (binCells[c3]->m_y-h < g_place_coreBounds.y)
+ binCells[c3]->m_y = g_place_coreBounds.y+h;
+ if (binCells[c3]->m_y+h > g_place_coreBounds.y+g_place_coreBounds.h)
+ binCells[c3]->m_y = g_place_coreBounds.y+g_place_coreBounds.h-h;
+ }
+
+ lastOldEdge = curOldEdge;
+ lastNewEdge = curNewEdge;
+ y++;
+ yBinCount = 0;
+ yBinArea = 0;
+ yBinStart = c2+1;
+ }
+ }
+
+ x++;
+ xBinCount = 0;
+ xBinArea = 0;
+ xBinStart = c+1;
+ }
+ }
+
+ free(binCells);
+ free(allCells);
+}
diff --git a/src/phys/place/place_genqp.c b/src/phys/place/place_genqp.c
new file mode 100644
index 00000000..5b6c7027
--- /dev/null
+++ b/src/phys/place/place_genqp.c
@@ -0,0 +1,309 @@
+/*===================================================================*/
+//
+// place_genqp.c
+//
+// Aaron P. Hurst, 2003-2007
+// ahurst@eecs.berkeley.edu
+//
+/*===================================================================*/
+
+#include <stdlib.h>
+#include <math.h>
+#include <stdio.h>
+#include <string.h>
+#include <assert.h>
+
+#include "place_base.h"
+#include "place_qpsolver.h"
+#include "place_gordian.h"
+
+// --------------------------------------------------------------------
+// Global variables
+//
+// --------------------------------------------------------------------
+
+qps_problem_t *g_place_qpProb = NULL;
+
+
+// --------------------------------------------------------------------
+// splitPenalty()
+//
+/// \brief Returns a weight for all of the edges in the clique for a multipin net.
+//
+// --------------------------------------------------------------------
+float splitPenalty(int pins) {
+
+ if (pins > 1) {
+ return 1.0 + CLIQUE_PENALTY/(pins - 1);
+ // return pow(pins - 1, CLIQUE_PENALTY);
+ }
+ return 1.0 + CLIQUE_PENALTY;
+}
+
+
+// --------------------------------------------------------------------
+// constructQuadraticProblem()
+//
+/// \brief Constructs the matrices necessary to do analytical placement.
+//
+// --------------------------------------------------------------------
+void constructQuadraticProblem() {
+ int maxConnections = 1;
+ int ignoreNum = 0;
+ int n,t,c,c2,p;
+ ConcreteCell *cell;
+ ConcreteNet *net;
+ int *cell_numTerms = calloc(g_place_numCells, sizeof(int));
+ ConcreteNet ***cell_terms = calloc(g_place_numCells, sizeof(ConcreteNet**));
+ bool incremental = false;
+ int nextIndex = 1;
+ int *seen = calloc(g_place_numCells, sizeof(int));
+ float weight;
+ int last_index;
+
+ // create problem object
+ if (!g_place_qpProb) {
+ g_place_qpProb = malloc(sizeof(qps_problem_t));
+ g_place_qpProb->area = NULL;
+ g_place_qpProb->x = NULL;
+ g_place_qpProb->y = NULL;
+ g_place_qpProb->fixed = NULL;
+ g_place_qpProb->connect = NULL;
+ g_place_qpProb->edge_weight = NULL;
+ }
+
+ // count the maximum possible number of non-sparse entries
+ for(n=0; n<g_place_numNets; n++) if (g_place_concreteNets[n]) {
+ ConcreteNet *net = g_place_concreteNets[n];
+ if (net->m_numTerms > IGNORE_NETSIZE) {
+ ignoreNum++;
+ }
+ else {
+ maxConnections += net->m_numTerms*(net->m_numTerms-1);
+ for(t=0; t<net->m_numTerms; t++) {
+ c = net->m_terms[t]->m_id;
+ p = ++cell_numTerms[c];
+ cell_terms[c] = (ConcreteNet**)realloc(cell_terms[c], p*sizeof(ConcreteNet*));
+ cell_terms[c][p-1] = net;
+ }
+ }
+ }
+ if(ignoreNum) {
+ printf("QMAN-10 : \t\t%d large nets ignored\n", ignoreNum);
+ }
+
+ // initialize the data structures
+ g_place_qpProb->num_cells = g_place_numCells;
+ maxConnections += g_place_numCells + 1;
+
+ g_place_qpProb->area = realloc(g_place_qpProb->area,
+ sizeof(float)*g_place_numCells);// "area" matrix
+ g_place_qpProb->edge_weight = realloc(g_place_qpProb->edge_weight,
+ sizeof(float)*maxConnections); // "weight" matrix
+ g_place_qpProb->connect = realloc(g_place_qpProb->connect,
+ sizeof(int)*maxConnections); // "connectivity" matrix
+ g_place_qpProb->fixed = realloc(g_place_qpProb->fixed,
+ sizeof(int)*g_place_numCells); // "fixed" matrix
+
+ // initialize or keep preexisting locations
+ if (g_place_qpProb->x != NULL && g_place_qpProb->y != NULL) {
+ printf("QMAN-10 :\tperforming incremental placement\n");
+ incremental = true;
+ }
+ g_place_qpProb->x = (float*)realloc(g_place_qpProb->x, sizeof(float)*g_place_numCells);
+ g_place_qpProb->y = (float*)realloc(g_place_qpProb->y, sizeof(float)*g_place_numCells);
+
+ // form a row for each cell
+ // build data
+ for(c = 0; c < g_place_numCells; c++) if (g_place_concreteCells[c]) {
+ cell = g_place_concreteCells[c];
+
+ // fill in the characteristics for this cell
+ g_place_qpProb->area[c] = getCellArea(cell);
+ if (cell->m_fixed || cell->m_parent->m_pad) {
+ g_place_qpProb->x[c] = cell->m_x;
+ g_place_qpProb->y[c] = cell->m_y;
+ g_place_qpProb->fixed[c] = 1;
+ } else {
+ if (!incremental) {
+ g_place_qpProb->x[c] = g_place_coreBounds.x+g_place_coreBounds.w*0.5;
+ g_place_qpProb->y[c] = g_place_coreBounds.y+g_place_coreBounds.h*0.5;
+ }
+ g_place_qpProb->fixed[c] = 0;
+ }
+
+ // update connectivity matrices
+ last_index = nextIndex;
+ for(n=0; n<cell_numTerms[c]; n++) {
+ net = cell_terms[c][n];
+ weight = net->m_weight / splitPenalty(net->m_numTerms);
+ for(t=0; t<net->m_numTerms; t++) {
+ c2 = net->m_terms[t]->m_id;
+ if (c2 == c) continue;
+ if (seen[c2] < last_index) {
+ // not seen
+ g_place_qpProb->connect[nextIndex-1] = c2;
+ g_place_qpProb->edge_weight[nextIndex-1] = weight;
+ seen[c2] = nextIndex;
+ nextIndex++;
+ } else {
+ // seen
+ g_place_qpProb->edge_weight[seen[c2]-1] += weight;
+ }
+ }
+ }
+ g_place_qpProb->connect[nextIndex-1] = -1;
+ g_place_qpProb->edge_weight[nextIndex-1] = -1.0;
+ nextIndex++;
+ } else {
+ // fill in dummy values for connectivity matrices
+ g_place_qpProb->connect[nextIndex-1] = -1;
+ g_place_qpProb->edge_weight[nextIndex-1] = -1.0;
+ nextIndex++;
+ }
+
+ free(cell_numTerms);
+ free(cell_terms);
+ free(seen);
+}
+
+typedef struct reverseCOG {
+ float x,y;
+ Partition *part;
+ float delta;
+} reverseCOG;
+
+
+// --------------------------------------------------------------------
+// generateCoGConstraints()
+//
+/// \brief Generates center of gravity constraints.
+//
+// --------------------------------------------------------------------
+int generateCoGConstraints(reverseCOG COG_rev[]) {
+ int numConstraints = 0; // actual num contraints
+ int cogRevNum = 0;
+ Partition **stack = malloc(sizeof(Partition*)*g_place_numPartitions*2);
+ int stackPtr = 0;
+ Partition *p;
+ float cgx, cgy;
+ int next_index = 0, last_constraint = 0;
+ bool isTrueConstraint = false;
+ int i, m;
+ float totarea;
+ ConcreteCell *cell;
+
+ // each partition may give rise to a center-of-gravity constraint
+ stack[stackPtr] = g_place_rootPartition;
+ while(stackPtr >= 0) {
+ p = stack[stackPtr--];
+ assert(p);
+
+ // traverse down the partition tree to leaf nodes-only
+ if (!p->m_leaf) {
+ stack[++stackPtr] = p->m_sub1;
+ stack[++stackPtr] = p->m_sub2;
+ } else {
+ /*
+ cout << "adding a COG constraint for box "
+ << p->bounds.x << ","
+ << p->bounds.y << " of size"
+ << p->bounds.w << "x"
+ << p->bounds.h
+ << endl;
+ */
+ cgx = p->m_bounds.x + p->m_bounds.w*0.5;
+ cgy = p->m_bounds.y + p->m_bounds.h*0.5;
+ COG_rev[cogRevNum].x = cgx;
+ COG_rev[cogRevNum].y = cgy;
+ COG_rev[cogRevNum].part = p;
+ COG_rev[cogRevNum].delta = 0;
+
+ cogRevNum++;
+ }
+ }
+
+ assert(cogRevNum == g_place_numPartitions);
+
+ for (i = 0; i < g_place_numPartitions; i++) {
+ p = COG_rev[i].part;
+ assert(p);
+ g_place_qpProb->cog_x[numConstraints] = COG_rev[i].x;
+ g_place_qpProb->cog_y[numConstraints] = COG_rev[i].y;
+ totarea = 0.0;
+ for(m=0; m<p->m_numMembers; m++) if (p->m_members[m]) {
+ cell = p->m_members[m];
+ assert(cell);
+
+ if (!cell->m_fixed && !cell->m_parent->m_pad) {
+ isTrueConstraint = true;
+ }
+ else {
+ continue;
+ }
+ g_place_qpProb->cog_list[next_index++] = cell->m_id;
+ totarea += getCellArea(cell);
+ }
+ if (totarea == 0.0) {
+ isTrueConstraint = false;
+ }
+ if (isTrueConstraint) {
+ numConstraints++;
+ g_place_qpProb->cog_list[next_index++] = -1;
+ last_constraint = next_index;
+ }
+ else {
+ next_index = last_constraint;
+ }
+ }
+
+ free(stack);
+
+ return --numConstraints;
+}
+
+
+// --------------------------------------------------------------------
+// solveQuadraticProblem()
+//
+/// \brief Calls quadratic solver.
+//
+// --------------------------------------------------------------------
+void solveQuadraticProblem(bool useCOG) {
+ int c;
+
+ reverseCOG *COG_rev = malloc(sizeof(reverseCOG)*g_place_numPartitions);
+
+ g_place_qpProb->cog_list = malloc(sizeof(int)*(g_place_numPartitions+g_place_numCells));
+ g_place_qpProb->cog_x = malloc(sizeof(float)*g_place_numPartitions);
+ g_place_qpProb->cog_y = malloc(sizeof(float)*g_place_numPartitions);
+
+ // memset(g_place_qpProb->x, 0, sizeof(float)*g_place_numCells);
+ // memset(g_place_qpProb->y, 0, sizeof(float)*g_place_numCells);
+
+ qps_init(g_place_qpProb);
+
+ if (useCOG)
+ g_place_qpProb->cog_num = generateCoGConstraints(COG_rev);
+ else
+ g_place_qpProb->cog_num = 0;
+
+ g_place_qpProb->loop_num = 0;
+
+ qps_solve(g_place_qpProb);
+
+ qps_clean(g_place_qpProb);
+
+ // set the positions
+ for(c = 0; c < g_place_numCells; c++) if (g_place_concreteCells[c]) {
+ g_place_concreteCells[c]->m_x = g_place_qpProb->x[c];
+ g_place_concreteCells[c]->m_y = g_place_qpProb->y[c];
+ }
+
+ // clean up
+ free(g_place_qpProb->cog_list);
+ free(g_place_qpProb->cog_x);
+ free(g_place_qpProb->cog_y);
+
+ free(COG_rev);
+}
diff --git a/src/phys/place/place_gordian.c b/src/phys/place/place_gordian.c
new file mode 100644
index 00000000..2929bf95
--- /dev/null
+++ b/src/phys/place/place_gordian.c
@@ -0,0 +1,160 @@
+/*===================================================================*/
+//
+// place_gordian.c
+//
+// Aaron P. Hurst, 2003-2007
+// ahurst@eecs.berkeley.edu
+//
+/*===================================================================*/
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <math.h>
+#include <assert.h>
+#include <limits.h>
+
+#include "place_gordian.h"
+#include "place_base.h"
+
+
+// --------------------------------------------------------------------
+// Global variables
+//
+// --------------------------------------------------------------------
+
+int g_place_numPartitions;
+
+
+// --------------------------------------------------------------------
+// globalPlace()
+//
+/// \brief Performs analytic placement using a GORDIAN-like algorithm.
+//
+/// Updates the positions of all non-fixed non-pad cells.
+///
+// --------------------------------------------------------------------
+void globalPlace() {
+ bool completionFlag = false;
+ int iteration = 0;
+
+ printf("PLAC-10 : Global placement (wirelength-driven Gordian)\n");
+
+ initPartitioning();
+
+ // build matrices representing interconnections
+ printf("QMAN-00 : \tconstructing initial quadratic problem...\n");
+ constructQuadraticProblem();
+
+ // iterate placement until termination condition is met
+ while(!completionFlag) {
+ printf("QMAN-01 : \titeration %d numPartitions = %d\n",iteration,g_place_numPartitions);
+
+ // do the global optimization in each direction
+ printf("QMAN-01 : \t\tglobal optimization\n");
+ solveQuadraticProblem(!IGNORE_COG);
+
+ // -------- PARTITIONING BASED CELL SPREADING ------
+
+ // bisection
+ printf("QMAN-01 : \t\tpartition refinement\n");
+ if (REALLOCATE_PARTITIONS) reallocPartitions();
+ completionFlag |= refinePartitions();
+
+ printf("QMAN-01 : \t\twirelength = %e\n", getTotalWirelength());
+
+ iteration++;
+ }
+
+ // final global optimization
+ printf("QMAN-02 : \t\tfinal pass\n");
+ if (FINAL_REALLOCATE_PARTITIONS) reallocPartitions();
+ solveQuadraticProblem(!IGNORE_COG);
+ printf("QMAN-01 : \t\twirelength = %e\n", getTotalWirelength());
+
+ // clean up
+ sanitizePlacement();
+ printf("QMAN-01 : \t\twirelength = %e\n", getTotalWirelength());
+ globalFixDensity(25, g_place_rowHeight*5);
+ printf("QMAN-01 : \t\twirelength = %e\n", getTotalWirelength());
+}
+
+
+// --------------------------------------------------------------------
+// globalIncremental()
+//
+/// \brief Performs analytic placement using a GORDIAN-like algorithm.
+//
+/// Requires a valid set of partitions.
+///
+// --------------------------------------------------------------------
+
+void globalIncremental() {
+ if (!g_place_rootPartition) {
+ printf("WARNING: Can not perform incremental placement\n");
+ globalPlace();
+ return;
+ }
+
+ printf("PLAC-10 : Incremental global placement\n");
+
+ incrementalPartition();
+
+ printf("QMAN-00 : \tconstructing initial quadratic problem...\n");
+ constructQuadraticProblem();
+
+ solveQuadraticProblem(!IGNORE_COG);
+ printf("QMAN-01 : \t\twirelength = %e\n", getTotalWirelength());
+
+ // clean up
+ sanitizePlacement();
+ printf("QMAN-01 : \t\twirelength = %e\n", getTotalWirelength());
+ globalFixDensity(25, g_place_rowHeight*5);
+ printf("QMAN-01 : \t\twirelength = %e\n", getTotalWirelength());
+}
+
+
+// --------------------------------------------------------------------
+// sanitizePlacement()
+//
+/// \brief Moves any cells that are outside of the core bounds to the nearest location within.
+//
+// --------------------------------------------------------------------
+void sanitizePlacement() {
+ int c;
+ float order_width = g_place_rowHeight;
+ float x, y, edge, w, h;
+
+ printf("QCLN-10 : \tsanitizing placement\n");
+
+ for(c=0; c<g_place_numCells; c++) if (g_place_concreteCells[c]) {
+ ConcreteCell *cell = g_place_concreteCells[c];
+ if (cell->m_fixed || cell->m_parent->m_pad) {
+ continue;
+ }
+ // the new locations of the cells will be distributed within
+ // a small margin inside the border so that ordering is preserved
+ order_width = g_place_rowHeight;
+
+ x = cell->m_x, y = cell->m_y,
+ w = cell->m_parent->m_width, h = cell->m_parent->m_height;
+
+ if ((edge=x-w*0.5) < g_place_coreBounds.x) {
+ x = g_place_coreBounds.x+w*0.5 +
+ order_width/(1.0+g_place_coreBounds.x-edge);
+ }
+ else if ((edge=x+w*0.5) > g_place_coreBounds.x+g_place_coreBounds.w) {
+ x = g_place_coreBounds.x+g_place_coreBounds.w-w*0.5 -
+ order_width/(1.0+edge-g_place_coreBounds.x-g_place_coreBounds.w);
+ }
+ if ((edge=y-h*0.5) < g_place_coreBounds.y) {
+ y = g_place_coreBounds.y+h*0.5 +
+ order_width/(1.0+g_place_coreBounds.y-edge);
+ }
+ else if ((edge=y+h*0.5) > g_place_coreBounds.y+g_place_coreBounds.h) {
+ y = g_place_coreBounds.y+g_place_coreBounds.h-h*0.5 -
+ order_width/(1.0+edge-g_place_coreBounds.x-g_place_coreBounds.w);
+ }
+ cell->m_x = x;
+ cell->m_y = y;
+ }
+}
diff --git a/src/phys/place/place_gordian.h b/src/phys/place/place_gordian.h
new file mode 100644
index 00000000..67eb1479
--- /dev/null
+++ b/src/phys/place/place_gordian.h
@@ -0,0 +1,78 @@
+/*===================================================================*/
+//
+// place_gordian.h
+//
+// Aaron P. Hurst, 2003-2007
+// ahurst@eecs.berkeley.edu
+//
+/*===================================================================*/
+
+#if !defined(PLACE_GORDIAN_H_)
+#define PLACE_GORDIAN_H_
+
+#include "place_base.h"
+#include "place_qpsolver.h"
+
+// Parameters for analytic placement
+#define CLIQUE_PENALTY 1.0
+#define IGNORE_NETSIZE 20
+
+// Parameters for partitioning
+#define LARGEST_FINAL_SIZE 20
+#define PARTITION_AREA_ONLY true
+#define REALLOCATE_PARTITIONS false
+#define FINAL_REALLOCATE_PARTITIONS false
+#define IGNORE_COG false
+#define MAX_PARTITION_NONSYMMETRY 0.30
+
+// Parameters for re-partitioning
+#define REPARTITION_LEVEL_DEPTH 4
+#define REPARTITION_TARGET_FRACTION 0.15
+#define REPARTITION_FM false
+#define REPARTITION_HMETIS true
+
+// Parameters for F-M re-partitioning
+#define FM_MAX_BIN 10
+#define FM_MAX_PASSES 10
+
+extern int g_place_numPartitions;
+
+extern qps_problem_t *g_place_qpProb;
+
+typedef struct Partition {
+
+ int m_numMembers;
+ ConcreteCell **m_members;
+ Rect m_bounds;
+ bool m_done,
+ m_leaf,
+ m_vertical;
+ float m_area;
+ int m_level;
+ struct Partition *m_sub1, *m_sub2;
+} Partition;
+
+extern Partition *g_place_rootPartition;
+
+void initPartitioning();
+
+void incrementalPartition();
+
+bool refinePartitions();
+void reallocPartitions();
+bool refinePartition(Partition *p);
+void resizePartition(Partition *p);
+void reallocPartition(Partition *p);
+
+void repartitionHMetis(Partition *parent);
+void repartitionFM(Partition *parent);
+
+void partitionScanlineMincut(Partition *parent);
+void partitionEqualArea(Partition *parent);
+
+void sanitizePlacement();
+
+void constructQuadraticProblem();
+void solveQuadraticProblem(bool useCOG);
+
+#endif
diff --git a/src/phys/place/place_inc.c b/src/phys/place/place_inc.c
new file mode 100644
index 00000000..7e2d847c
--- /dev/null
+++ b/src/phys/place/place_inc.c
@@ -0,0 +1,106 @@
+/*===================================================================*/
+//
+// place_inc.c
+//
+// Aaron P. Hurst, 2003-2007
+// ahurst@eecs.berkeley.edu
+//
+/*===================================================================*/
+
+#include <stdlib.h>
+#include <limits.h>
+#include <assert.h>
+#include <string.h>
+
+#include "place_base.h"
+#include "place_gordian.h"
+
+inline int sqHashId(int id, int max) {
+ return ((id * (id+17)) % max);
+}
+
+#if 0
+// --------------------------------------------------------------------
+// fastPlace()
+//
+/// The first cell is assumed to be the "output".
+// --------------------------------------------------------------------
+float fastPlace(int numCells, ConcreteCell *cells[],
+ int numNets, ConcreteNet *nets[]) {
+
+ int n, t, c, i, local_id = 0, pass;
+ const int NUM_PASSES = 4;
+ int *cell_numTerms = calloc(numCells, sizeof(int));
+ ConcreteNet **cell_terms;
+ ConcreteNet *net;
+ Rect outputBox;
+
+ outputBox = getNetBBox(nets[0]);
+
+ // assign local ids
+ // put cells in reasonable initial location
+ for(n=0; n<numNets; n++)
+ for(t=0; nets[n]->m_numTerms; t++)
+ nets[n]->m_terms[t]->m_data = -1;
+
+ for(c=0; c<numCells; c++) {
+ cells[c]->m_data = local_id;
+ cells[c]->m_x = outputBox.x + 0.5*outputBox.w;
+ cells[c]->m_y = outputBox.y + 0.5*outputBox.h;
+ }
+
+ // build reverse map of cells to nets
+ for(n=0; n<numNets; n++)
+ for(t=0; nets[n]->m_numTerms; t++) {
+ local_id = nets[n]->m_terms[t]->m_data;
+ if (local_id >= 0)
+ cell_numTerms[local_id]++;
+ }
+
+ for(c=0; c<numCells; c++) {
+ cell_terms[c] = malloc(sizeof(ConcreteNet*)*cell_numTerms[c]);
+ cell_numTerms[c] = 0;
+ }
+
+ for(n=0; n<numNets; n++)
+ for(t=0; nets[n]->m_numTerms; t++) {
+ local_id = nets[n]->m_terms[t]->m_data;
+ if (local_id >= 0)
+ cell_terms[cell_numTerms[local_id]++] = nets[n];
+ }
+
+ // topological order?
+
+ // iterative linear
+ for(pass=0; pass<NUM_PASSES; pass++)
+ for(c=0; c<numCells; c++) {
+ for(n=0; n<cell_numTerms[c]; n++) {
+ net = cell_terms[c];
+ for(t=0; t<net->m_numTerms; t++);
+ }
+ }
+}
+#endif
+
+// --------------------------------------------------------------------
+// fastEstimate()
+//
+// --------------------------------------------------------------------
+float fastEstimate(ConcreteCell *cell,
+ int numNets, ConcreteNet *nets[]) {
+ float len = 0;
+ int n;
+ Rect box;
+
+ assert(cell);
+
+ for(n=0; n<numNets; n++) {
+ box = getNetBBox(nets[n]);
+ if (cell->m_x < box.x) len += (box.x - cell->m_x);
+ if (cell->m_x > box.x+box.w) len += (cell->m_x-box.x-box.w);
+ if (cell->m_y < box.y) len += (box.x - cell->m_y);
+ if (cell->m_y > box.y+box.h) len += (cell->m_y-box.y-box.h);
+ }
+
+ return len;
+}
diff --git a/src/phys/place/place_io.c b/src/phys/place/place_io.c
new file mode 100644
index 00000000..8e24ef4a
--- /dev/null
+++ b/src/phys/place/place_io.c
@@ -0,0 +1,94 @@
+/*===================================================================*/
+//
+// place_io.c
+//
+// Aaron P. Hurst, 2003-2007
+// ahurst@eecs.berkeley.edu
+//
+/*===================================================================*/
+
+#include <stdlib.h>
+#include <limits.h>
+#include <assert.h>
+#include <string.h>
+#include <stdio.h>
+
+#include "place_base.h"
+
+
+// --------------------------------------------------------------------
+// writeBookshelfNodes()
+//
+// --------------------------------------------------------------------
+void writeBookshelfNodes(const char *filename) {
+
+ int c = 0;
+ int numNodes, numTerms;
+
+ FILE *nodesFile = fopen(filename, "w");
+ if (!nodesFile) {
+ printf("ERROR: Could not open .nodes file\n");
+ exit(1);
+ }
+
+ numNodes = numTerms = 0;
+ for(c=0; c<g_place_numCells; c++) if (g_place_concreteCells[c]) {
+ numNodes++;
+ if (g_place_concreteCells[c]->m_parent->m_pad)
+ numTerms++;
+ }
+
+
+
+ fprintf(nodesFile, "UCLA nodes 1.0\n");
+ fprintf(nodesFile, "NumNodes : %d\n", numNodes);
+ fprintf(nodesFile, "NumTerminals : %d\n", numTerms);
+
+ for(c=0; c<g_place_numCells; c++) if (g_place_concreteCells[c]) {
+ fprintf(nodesFile, "CELL%d %f %f %s\n",
+ g_place_concreteCells[c]->m_id,
+ g_place_concreteCells[c]->m_parent->m_width,
+ g_place_concreteCells[c]->m_parent->m_height,
+ (g_place_concreteCells[c]->m_parent->m_pad ? " terminal" : ""));
+ }
+
+ fclose(nodesFile);
+}
+
+
+// --------------------------------------------------------------------
+// writeBookshelfPl()
+//
+// --------------------------------------------------------------------
+void writeBookshelfPl(const char *filename) {
+
+ int c = 0;
+
+ FILE *plFile = fopen(filename, "w");
+ if (!plFile) {
+ printf("ERROR: Could not open .pl file\n");
+ exit(1);
+ }
+
+ fprintf(plFile, "UCLA pl 1.0\n");
+ for(c=0; c<g_place_numCells; c++) if (g_place_concreteCells[c]) {
+ fprintf(plFile, "CELL%d %f %f : N %s\n",
+ g_place_concreteCells[c]->m_id,
+ g_place_concreteCells[c]->m_x,
+ g_place_concreteCells[c]->m_y,
+ (g_place_concreteCells[c]->m_fixed ? "\\FIXED" : ""));
+ }
+
+ fclose(plFile);
+
+}
+
+
+// --------------------------------------------------------------------
+// writeBookshelf()
+//
+// --------------------------------------------------------------------
+void writeBookshelf(const char *filename) {
+ writeBookshelfNodes("out.nodes");
+ writeBookshelfPl("out.pl");
+}
diff --git a/src/phys/place/place_legalize.c b/src/phys/place/place_legalize.c
new file mode 100644
index 00000000..950902f4
--- /dev/null
+++ b/src/phys/place/place_legalize.c
@@ -0,0 +1,23 @@
+/*===================================================================*/
+//
+// place_legalize.c
+//
+// Aaron P. Hurst, 2007
+// ahurst@eecs.berkeley.edu
+//
+/*===================================================================*/
+
+#include <limits.h>
+#include <assert.h>
+
+#include "place_base.h"
+
+
+// --------------------------------------------------------------------
+// legalize()
+//
+// --------------------------------------------------------------------
+void legalize() {
+ // UNIMPLEMENTED
+}
+
diff --git a/src/phys/place/place_pads.c b/src/phys/place/place_pads.c
new file mode 100644
index 00000000..361fac7f
--- /dev/null
+++ b/src/phys/place/place_pads.c
@@ -0,0 +1,141 @@
+/*===================================================================*/
+//
+// place_pads.c
+//
+// Aaron P. Hurst, 2003-2007
+// ahurst@eecs.berkeley.edu
+//
+/*===================================================================*/
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <math.h>
+#include <limits.h>
+
+#include "place_base.h"
+
+// --------------------------------------------------------------------
+// globalPreplace()
+//
+/// \brief Place pad ring, leaving a core area to meet a desired utilization.
+//
+/// Sets the position of pads that aren't already fixed.
+///
+/// Computes g_place_coreBounds and g_place_padBounds. Determines
+/// g_place_rowHeight.
+//
+// --------------------------------------------------------------------
+void globalPreplace(float utilization) {
+ int i, c, h, numRows;
+ float coreArea = 0, totalArea = 0;
+ int padCount = 0;
+ float area;
+ ConcreteCell **padCells = NULL;
+ AbstractCell *padType = NULL;
+ ConcreteCell *cell;
+ float nextPos;
+ int remainingPads, northPads, southPads, eastPads, westPads;
+
+ printf("PLAC-00 : Placing IO pads\n");;
+
+ // identify the pads and compute the total core area
+ g_place_coreBounds.x = g_place_coreBounds.y = 0;
+ g_place_coreBounds.w = g_place_coreBounds.h = -INT_MAX;
+
+ for(c=0; c<g_place_numCells; c++) if (g_place_concreteCells[c]) {
+ cell = g_place_concreteCells[c];
+ area = getCellArea(cell);
+ if (cell->m_parent->m_pad) {
+ padType = cell->m_parent;
+ } else {
+ coreArea += area;
+ g_place_rowHeight = cell->m_parent->m_height;
+ }
+
+ if (cell->m_fixed) {
+ g_place_coreBounds.x = g_place_coreBounds.x < cell->m_x ? g_place_coreBounds.x : cell->m_x;
+ g_place_coreBounds.y = g_place_coreBounds.y < cell->m_y ? g_place_coreBounds.y : cell->m_y;
+ g_place_coreBounds.w = g_place_coreBounds.w > cell->m_x ? g_place_coreBounds.w : cell->m_x;
+ g_place_coreBounds.h = g_place_coreBounds.h > cell->m_y ? g_place_coreBounds.h : cell->m_y;
+ } else if (cell->m_parent->m_pad) {
+ padCells = realloc(padCells, sizeof(ConcreteCell **)*(padCount+1));
+ padCells[padCount++] = cell;
+ }
+ totalArea += area;
+ }
+ if (!padType) {
+ printf("ERROR: No pad cells\n");
+ exit(1);
+ }
+ g_place_padBounds.w -= g_place_padBounds.x;
+ g_place_padBounds.h -= g_place_padBounds.y;
+
+ coreArea /= utilization;
+
+ // create the design boundaries
+ numRows = sqrt(coreArea)/g_place_rowHeight+1;
+ h = numRows * g_place_rowHeight;
+ g_place_coreBounds.h = g_place_coreBounds.h > h ? g_place_coreBounds.h : h;
+ g_place_coreBounds.w = g_place_coreBounds.w > coreArea/g_place_coreBounds.h ?
+ g_place_coreBounds.w : coreArea/g_place_coreBounds.h;
+ // increase the dimensions by the width of the padring
+ g_place_padBounds = g_place_coreBounds;
+ if (padCount) {
+ printf("PLAC-05 : \tpreplacing %d pad cells\n", padCount);
+ g_place_padBounds.x -= padType->m_width;
+ g_place_padBounds.y -= padType->m_height;
+ g_place_padBounds.w = g_place_coreBounds.w+2*padType->m_width;
+ g_place_padBounds.h = g_place_coreBounds.h+2*padType->m_height;
+ }
+
+ printf("PLAC-05 : \tplaceable rows : %d\n", numRows);
+ printf("PLAC-05 : \tcore dimensions : %.0fx%.0f\n",
+ g_place_coreBounds.w, g_place_coreBounds.h);
+ printf("PLAC-05 : \tchip dimensions : %.0fx%.0f\n",
+ g_place_padBounds.w, g_place_padBounds.h);
+
+ remainingPads = padCount;
+ c = 0;
+
+ // north pads
+ northPads = remainingPads/4; remainingPads -= northPads;
+ nextPos = 0;
+ for(i=0; i<northPads; i++) {
+ cell = padCells[c++];
+ cell->m_x = g_place_padBounds.x+cell->m_parent->m_width*0.5 + nextPos;
+ cell->m_y = g_place_padBounds.y+cell->m_parent->m_height*0.5;
+ nextPos += (g_place_padBounds.w-padType->m_width) / northPads;
+ }
+
+ // south pads
+ southPads = remainingPads/3; remainingPads -= southPads;
+ nextPos = 0;
+ for(i=0; i<southPads; i++) {
+ cell = padCells[c++];
+ cell->m_x = g_place_padBounds.w+g_place_padBounds.x-cell->m_parent->m_width*0.5 - nextPos;
+ cell->m_y = g_place_padBounds.h+g_place_padBounds.y-cell->m_parent->m_height*0.5;
+ nextPos += (g_place_padBounds.w-2*padType->m_width) / southPads;
+ }
+
+ // east pads
+ eastPads = remainingPads/2; remainingPads -= eastPads;
+ nextPos = 0;
+ for(i=0; i<eastPads; i++) {
+ cell = padCells[c++];
+ cell->m_x = g_place_padBounds.w+g_place_padBounds.x-cell->m_parent->m_width*0.5;
+ cell->m_y = g_place_padBounds.y+cell->m_parent->m_height*0.5 + nextPos;
+ nextPos += (g_place_padBounds.h-padType->m_height) / eastPads;
+ }
+
+ // west pads
+ westPads = remainingPads;
+ nextPos = 0;
+ for(i=0; i<westPads; i++) {
+ cell = padCells[c++];
+ cell->m_x = g_place_padBounds.x+cell->m_parent->m_width*0.5;
+ cell->m_y = g_place_padBounds.h+g_place_padBounds.y-cell->m_parent->m_height*0.5 - nextPos;
+ nextPos += (g_place_padBounds.h-padType->m_height) / westPads;
+ }
+
+}
+
diff --git a/src/phys/place/place_partition.c b/src/phys/place/place_partition.c
new file mode 100644
index 00000000..ea57cd1c
--- /dev/null
+++ b/src/phys/place/place_partition.c
@@ -0,0 +1,1135 @@
+/*===================================================================*/
+//
+// place_partition.c
+//
+// Aaron P. Hurst, 2003-2007
+// ahurst@eecs.berkeley.edu
+//
+/*===================================================================*/
+
+#include <stdlib.h>
+#include <math.h>
+#include <string.h>
+#include <stdio.h>
+#include <limits.h>
+#include <assert.h>
+//#include <sys/stat.h>
+//#include <unistd.h>
+
+#include "place_base.h"
+#include "place_gordian.h"
+
+#if !defined(NO_HMETIS)
+#include "libhmetis.h"
+#endif
+
+// --------------------------------------------------------------------
+// Global variables
+//
+// --------------------------------------------------------------------
+
+Partition *g_place_rootPartition = NULL;
+ConcreteNet **allNetsR2 = NULL,
+ **allNetsL2 = NULL,
+ **allNetsB2 = NULL,
+ **allNetsT2 = NULL;
+
+
+// --------------------------------------------------------------------
+// Function prototypes and local data structures
+//
+// --------------------------------------------------------------------
+
+typedef struct FM_cell {
+ int loc;
+ int gain;
+ ConcreteCell *cell;
+ struct FM_cell *next, *prev;
+ bool locked;
+} FM_cell;
+
+void FM_updateGains(ConcreteNet *net, int partition, int inc,
+ FM_cell target [], FM_cell *bin [],
+ int count_1 [], int count_2 []);
+
+
+// --------------------------------------------------------------------
+// initPartitioning()
+//
+/// \brief Initializes data structures necessary for partitioning.
+//
+/// Creates a valid g_place_rootPartition.
+///
+// --------------------------------------------------------------------
+void initPartitioning() {
+ int i;
+ float area;
+
+ // create root partition
+ g_place_numPartitions = 1;
+ if (g_place_rootPartition) free(g_place_rootPartition);
+ g_place_rootPartition = malloc(sizeof(Partition));
+ g_place_rootPartition->m_level = 0;
+ g_place_rootPartition->m_area = 0;
+ g_place_rootPartition->m_bounds = g_place_coreBounds;
+ g_place_rootPartition->m_vertical = false;
+ g_place_rootPartition->m_done = false;
+ g_place_rootPartition->m_leaf = true;
+
+ // add all of the cells to this partition
+ g_place_rootPartition->m_members = malloc(sizeof(ConcreteCell*)*g_place_numCells);
+ g_place_rootPartition->m_numMembers = 0;
+ for (i=0; i<g_place_numCells; i++)
+ if (g_place_concreteCells[i]) {
+ if (!g_place_concreteCells[i]->m_fixed) {
+ area = getCellArea(g_place_concreteCells[i]);
+ g_place_rootPartition->m_members[g_place_rootPartition->m_numMembers++] =
+ g_place_concreteCells[i];
+ g_place_rootPartition->m_area += area;
+ }
+ }
+}
+
+
+// --------------------------------------------------------------------
+// presortNets()
+//
+/// \brief Sorts nets by corner positions.
+//
+/// Allocates allNetsX2 structures.
+///
+// --------------------------------------------------------------------
+void presortNets() {
+ allNetsL2 = (ConcreteNet**)realloc(allNetsL2, sizeof(ConcreteNet*)*g_place_numNets);
+ allNetsR2 = (ConcreteNet**)realloc(allNetsR2, sizeof(ConcreteNet*)*g_place_numNets);
+ allNetsB2 = (ConcreteNet**)realloc(allNetsB2, sizeof(ConcreteNet*)*g_place_numNets);
+ allNetsT2 = (ConcreteNet**)realloc(allNetsT2, sizeof(ConcreteNet*)*g_place_numNets);
+ memcpy(allNetsL2, g_place_concreteNets, sizeof(ConcreteNet*)*g_place_numNets);
+ memcpy(allNetsR2, g_place_concreteNets, sizeof(ConcreteNet*)*g_place_numNets);
+ memcpy(allNetsB2, g_place_concreteNets, sizeof(ConcreteNet*)*g_place_numNets);
+ memcpy(allNetsT2, g_place_concreteNets, sizeof(ConcreteNet*)*g_place_numNets);
+ qsort(allNetsL2, g_place_numNets, sizeof(ConcreteNet*), netSortByL);
+ qsort(allNetsR2, g_place_numNets, sizeof(ConcreteNet*), netSortByR);
+ qsort(allNetsB2, g_place_numNets, sizeof(ConcreteNet*), netSortByB);
+ qsort(allNetsT2, g_place_numNets, sizeof(ConcreteNet*), netSortByT);
+}
+
+// --------------------------------------------------------------------
+// refinePartitions()
+//
+/// \brief Splits large leaf partitions.
+//
+// --------------------------------------------------------------------
+bool refinePartitions() {
+
+ return refinePartition(g_place_rootPartition);
+}
+
+
+// --------------------------------------------------------------------
+// reallocPartitions()
+//
+/// \brief Reallocates the partitions based on placement information.
+//
+// --------------------------------------------------------------------
+void reallocPartitions() {
+
+ reallocPartition(g_place_rootPartition);
+}
+
+
+// --------------------------------------------------------------------
+// refinePartition()
+//
+/// \brief Splits any large leaves within a partition.
+//
+// --------------------------------------------------------------------
+bool refinePartition(Partition *p) {
+ bool degenerate = false;
+ int nonzeroCount = 0;
+ int i;
+
+ assert(p);
+
+ // is this partition completed?
+ if (p->m_done) return true;
+
+ // is this partition a non-leaf node?
+ if (!p->m_leaf) {
+ p->m_done = refinePartition(p->m_sub1);
+ p->m_done &= refinePartition(p->m_sub2);
+ return p->m_done;
+ }
+
+ // leaf...
+ // create two new subpartitions
+ g_place_numPartitions++;
+ p->m_sub1 = malloc(sizeof(Partition));
+ p->m_sub1->m_level = p->m_level+1;
+ p->m_sub1->m_leaf = true;
+ p->m_sub1->m_done = false;
+ p->m_sub1->m_area = 0;
+ p->m_sub1->m_vertical = !p->m_vertical;
+ p->m_sub1->m_numMembers = 0;
+ p->m_sub1->m_members = NULL;
+ p->m_sub2 = malloc(sizeof(Partition));
+ p->m_sub2->m_level = p->m_level+1;
+ p->m_sub2->m_leaf = true;
+ p->m_sub2->m_done = false;
+ p->m_sub2->m_area = 0;
+ p->m_sub2->m_vertical = !p->m_vertical;
+ p->m_sub2->m_numMembers = 0;
+ p->m_sub2->m_members = NULL;
+ p->m_leaf = false;
+
+ // --- INITIAL PARTITION
+
+ if (PARTITION_AREA_ONLY)
+ partitionEqualArea(p);
+ else
+ partitionScanlineMincut(p);
+
+ resizePartition(p);
+
+ // --- PARTITION IMPROVEMENT
+
+ if (p->m_level < REPARTITION_LEVEL_DEPTH) {
+ if (REPARTITION_FM)
+ repartitionFM(p);
+ else if (REPARTITION_HMETIS)
+ repartitionHMetis(p);
+ }
+
+ resizePartition(p);
+
+ // fix imbalances due to zero-area cells
+ for(i=0; i<p->m_sub1->m_numMembers; i++)
+ if (p->m_sub1->m_members[i])
+ if (getCellArea(p->m_sub1->m_members[i]) > 0) {
+ nonzeroCount++;
+ }
+
+ // is this leaf now done?
+ if (nonzeroCount <= LARGEST_FINAL_SIZE)
+ p->m_sub1->m_done = true;
+ if (nonzeroCount == 0)
+ degenerate = true;
+
+ nonzeroCount = 0;
+ for(i=0; i<p->m_sub2->m_numMembers; i++)
+ if (p->m_sub2->m_members[i])
+ if (getCellArea(p->m_sub2->m_members[i]) > 0) {
+ nonzeroCount++;
+ }
+
+ // is this leaf now done?
+ if (nonzeroCount <= LARGEST_FINAL_SIZE)
+ p->m_sub2->m_done = true;
+ if (nonzeroCount == 0)
+ degenerate = true;
+
+ // have we found a degenerate partitioning?
+ if (degenerate) {
+ printf("QPART-35 : WARNING: degenerate partition generated\n");
+ partitionEqualArea(p);
+ resizePartition(p);
+ p->m_sub1->m_done = true;
+ p->m_sub2->m_done = true;
+ }
+
+ // is this parent now finished?
+ if (p->m_sub1->m_done && p->m_sub2->m_done) p->m_done = true;
+
+ return p->m_done;
+}
+
+
+// --------------------------------------------------------------------
+// repartitionHMetis()
+//
+/// \brief Repartitions the two subpartitions using the hMetis min-cut library.
+///
+/// The number of cut nets between the two partitions will be minimized.
+//
+// --------------------------------------------------------------------
+void repartitionHMetis(Partition *parent) {
+#if defined(NO_HMETIS)
+ printf("QPAR_02 : \t\tERROR: hMetis not available. Ignoring.\n");
+#else
+
+ int n,c,t, i;
+ float area;
+ int *edgeConnections = NULL;
+ int *partitionAssignment = (int *)calloc(g_place_numCells, sizeof(int));
+ int *vertexWeights = (int *)calloc(g_place_numCells, sizeof(int));
+ int *edgeDegree = (int *)malloc(sizeof(int)*(g_place_numNets+1));
+ int numConnections = 0;
+ int numEdges = 0;
+ float initial_cut;
+ int targets = 0;
+ ConcreteCell *cell = NULL;
+ int options[9];
+ int afterCuts = 0;
+
+ assert(parent);
+ assert(parent->m_sub1);
+ assert(parent->m_sub2);
+
+ printf("QPAR-02 : \t\trepartitioning with hMetis\n");
+
+ // count edges
+ edgeDegree[0] = 0;
+ for(n=0; n<g_place_numNets; n++) if (g_place_concreteNets[n])
+ if (g_place_concreteNets[n]->m_numTerms > 1) {
+ numConnections += g_place_concreteNets[n]->m_numTerms;
+ edgeDegree[++numEdges] = numConnections;
+ }
+
+ if (parent->m_vertical) {
+ // vertical
+ initial_cut = parent->m_sub2->m_bounds.x;
+
+ // initialize all cells
+ for(c=0; c<g_place_numCells; c++) if (g_place_concreteCells[c]) {
+ if (g_place_concreteCells[c]->m_x < initial_cut)
+ partitionAssignment[c] = 0;
+ else
+ partitionAssignment[c] = 1;
+ }
+
+ // initialize cells in partition 1
+ for(t=0; t<parent->m_sub1->m_numMembers; t++) if (parent->m_sub1->m_members[t]) {
+ cell = parent->m_sub1->m_members[t];
+ vertexWeights[cell->m_id] = getCellArea(cell);
+ // pay attention to cells that are close to the cut
+ if (abs(cell->m_x-initial_cut) < parent->m_bounds.w*REPARTITION_TARGET_FRACTION) {
+ targets++;
+ partitionAssignment[cell->m_id] = -1;
+ }
+ }
+
+ // initialize cells in partition 2
+ for(t=0; t<parent->m_sub2->m_numMembers; t++) if (parent->m_sub2->m_members[t]) {
+ cell = parent->m_sub2->m_members[t];
+ vertexWeights[cell->m_id] = getCellArea(cell);
+ // pay attention to cells that are close to the cut
+ if (abs(cell->m_x-initial_cut) < parent->m_bounds.w*REPARTITION_TARGET_FRACTION) {
+ targets++;
+ partitionAssignment[cell->m_id] = -1;
+ }
+ }
+
+ } else {
+ // horizontal
+ initial_cut = parent->m_sub2->m_bounds.y;
+
+ // initialize all cells
+ for(c=0; c<g_place_numCells; c++) if (g_place_concreteCells[c]) {
+ if (g_place_concreteCells[c]->m_y < initial_cut)
+ partitionAssignment[c] = 0;
+ else
+ partitionAssignment[c] = 1;
+ }
+
+ // initialize cells in partition 1
+ for(t=0; t<parent->m_sub1->m_numMembers; t++) if (parent->m_sub1->m_members[t]) {
+ cell = parent->m_sub1->m_members[t];
+ vertexWeights[cell->m_id] = getCellArea(cell);
+ // pay attention to cells that are close to the cut
+ if (abs(cell->m_y-initial_cut) < parent->m_bounds.h*REPARTITION_TARGET_FRACTION) {
+ targets++;
+ partitionAssignment[cell->m_id] = -1;
+ }
+ }
+
+ // initialize cells in partition 2
+ for(t=0; t<parent->m_sub2->m_numMembers; t++) if (parent->m_sub2->m_members[t]) {
+ cell = parent->m_sub2->m_members[t];
+ vertexWeights[cell->m_id] = getCellArea(cell);
+ // pay attention to cells that are close to the cut
+ if (abs(cell->m_y-initial_cut) < parent->m_bounds.h*REPARTITION_TARGET_FRACTION) {
+ targets++;
+ partitionAssignment[cell->m_id] = -1;
+ }
+ }
+ }
+
+ options[0] = 1; // any non-default values?
+ options[1] = 3; // num bisections
+ options[2] = 1; // grouping scheme
+ options[3] = 1; // refinement scheme
+ options[4] = 1; // cycle refinement scheme
+ options[5] = 0; // reconstruction scheme
+ options[6] = 0; // fixed assignments?
+ options[7] = 12261980; // random seed
+ options[8] = 0; // debugging level
+
+ edgeConnections = (int *)malloc(sizeof(int)*numConnections);
+
+ i = 0;
+ for(n=0; n<g_place_numNets; n++) if (g_place_concreteNets[n]) {
+ if (g_place_concreteNets[n]->m_numTerms > 1)
+ for(t=0; t<g_place_concreteNets[n]->m_numTerms; t++)
+ edgeConnections[i++] = g_place_concreteNets[n]->m_terms[t]->m_id;
+ }
+
+ HMETIS_PartRecursive(g_place_numCells, numEdges, vertexWeights,
+ edgeDegree, edgeConnections, NULL,
+ 2, (int)(100*MAX_PARTITION_NONSYMMETRY),
+ options, partitionAssignment, &afterCuts);
+
+ /*
+ printf("HMET-20 : \t\t\tbalance before %d / %d ... ", parent->m_sub1->m_numMembers,
+ parent->m_sub2->m_numMembers);
+ */
+
+ // reassign members to subpartitions
+ parent->m_sub1->m_numMembers = 0;
+ parent->m_sub1->m_area = 0;
+ parent->m_sub2->m_numMembers = 0;
+ parent->m_sub2->m_area = 0;
+ parent->m_sub1->m_members = (ConcreteCell**)realloc(parent->m_sub1->m_members,
+ sizeof(ConcreteCell*)*parent->m_numMembers);
+ parent->m_sub2->m_members = (ConcreteCell**)realloc(parent->m_sub2->m_members,
+ sizeof(ConcreteCell*)*parent->m_numMembers);
+
+ for(t=0; t<parent->m_numMembers; t++) if (parent->m_members[t]) {
+ cell = parent->m_members[t];
+ area = getCellArea(cell);
+ if (partitionAssignment[cell->m_id] == 0) {
+ parent->m_sub1->m_members[parent->m_sub1->m_numMembers++] = cell;
+ parent->m_sub1->m_area += area;
+ }
+ else {
+ parent->m_sub2->m_members[parent->m_sub2->m_numMembers++] = cell;
+ parent->m_sub2->m_area += area;
+ }
+ }
+ /*
+ printf("after %d / %d\n", parent->m_sub1->m_numMembers,
+ parent->m_sub2->m_numMembers);
+ */
+
+ // cout << "HMET-21 : \t\t\tloc: " << initial_cut << " targetting: " << targets*100/parent->m_members.length() << "%" << endl;
+ // cout << "HMET-22 : \t\t\tstarting cuts= " << beforeCuts << " final cuts= " << afterCuts << endl;
+
+ free(edgeConnections);
+ free(vertexWeights);
+ free(edgeDegree);
+ free(partitionAssignment);
+#endif
+}
+
+
+// --------------------------------------------------------------------
+// repartitionFM()
+//
+/// \brief Fiduccia-Matheyses mincut partitioning algorithm.
+//
+/// UNIMPLEMENTED (well, un-C-ified)
+//
+// --------------------------------------------------------------------
+void repartitionFM(Partition *parent) {
+#if 0
+ assert(!parent->leaf && parent->m_sub1->leaf && parent->m_sub2->leaf);
+
+ // count of each net's number of cells in each bipartition
+ int count_1[m_design->nets.length()];
+ memset(count_1, 0, sizeof(int)*m_design->nets.length());
+ int count_2[m_design->nets.length()];
+ memset(count_2, 0, sizeof(int)*m_design->nets.length());
+
+ FM_cell target[m_design->cells.length()];
+ memset(target, 0, sizeof(FM_cell)*m_design->cells.length());
+ FM_cell *bin[FM_MAX_BIN+1];
+ FM_cell *locked = 0;
+ memset(bin, 0, sizeof(FM_cell *)*(FM_MAX_BIN+1));
+
+ int max_gain = 0;
+ int before_cuts = 0, current_cuts = 0;
+ double initial_cut;
+ int targets = 0;
+ long cell_id;
+ double halfArea = parent->m_area / 2.0;
+ double areaFlexibility = parent->m_area * MAX_PARTITION_NONSYMMETRY;
+ ConcreteNet *net;
+
+ // INITIALIZATION
+ // select cells to partition
+
+ if (parent->vertical) {
+ // vertical
+
+ initial_cut = parent->m_sub2->m_bounds.x;
+
+ // initialize all cells
+ for(h::list<ConcreteCell *>::iterator it = rootPartition->m_members.begin(); !it; it++) {
+ cell_id = (*it)->getID();
+ if ((*it)->temp_x < initial_cut)
+ target[cell_id].loc = -1;
+ else
+ target[cell_id].loc = -2;
+ target[cell_id].cell = *it;
+ target[cell_id].gain = 0;
+ }
+
+ // initialize cells in partition 1
+ for(h::list<ConcreteCell *>::iterator it = parent->m_sub1->m_members.begin(); !it; it++) {
+ cell_id = (*it)->getID();
+ // pay attention to cells that are close to the cut
+ if (abs((*it)->temp_x-initial_cut) < parent->m_bounds.w*REPARTITION_TARGET_FRACTION) {
+ targets++;
+ target[cell_id].loc = 1;
+ }
+ }
+
+ // initialize cells in partition 2
+ for(h::list<ConcreteCell *>::iterator it = parent->m_sub2->m_members.begin(); !it; it++) {
+ cell_id = (*it)->getID();
+ // pay attention to cells that are close to the cut
+ if (abs((*it)->temp_x-initial_cut) < parent->m_bounds.w*REPARTITION_TARGET_FRACTION) {
+ targets++;
+ target[cell_id].loc = 2;
+ }
+ }
+
+ // count the number of cells on each side of the partition for every net
+ for(h::hash_map<ConcreteNet *>::iterator n_it = m_design->nets.begin(); !n_it; n_it++) {
+ for(ConcretePinList::iterator p_it = (net = *n_it)->getPins().begin(); !p_it; p_it++)
+ if (abs(target[(*p_it)->getCell()->getID()].loc) == 1)
+ count_1[net->getID()]++;
+ else if (abs(target[(*p_it)->getCell()->getID()].loc) == 2)
+ count_2[net->getID()]++;
+ else if ((*p_it)->getCell()->temp_x < initial_cut)
+ count_1[net->getID()]++;
+ else
+ count_2[net->getID()]++;
+ if (count_1[net->getID()] > 0 && count_2[net->getID()] > 0) before_cuts++;
+ }
+
+ } else {
+ // horizontal
+
+ initial_cut = parent->m_sub2->m_bounds.y;
+
+ // initialize all cells
+ for(h::list<ConcreteCell *>::iterator it = rootPartition->m_members.begin(); !it; it++) {
+ cell_id = (*it)->getID();
+ if ((*it)->temp_y < initial_cut)
+ target[cell_id].loc = -1;
+ else
+ target[cell_id].loc = -2;
+ target[cell_id].cell = *it;
+ target[cell_id].gain = 0;
+ }
+
+ // initialize cells in partition 1
+ for(h::list<ConcreteCell *>::iterator it = parent->m_sub1->m_members.begin(); !it; it++) {
+ cell_id = (*it)->getID();
+ // pay attention to cells that are close to the cut
+ if (abs((*it)->temp_y-initial_cut) < parent->m_bounds.h*REPARTITION_TARGET_FRACTION) {
+ targets++;
+ target[cell_id].loc = 1;
+ }
+ }
+
+ // initialize cells in partition 2
+ for(h::list<ConcreteCell *>::iterator it = parent->m_sub2->m_members.begin(); !it; it++) {
+ cell_id = (*it)->getID();
+ // pay attention to cells that are close to the cut
+ if (abs((*it)->temp_y-initial_cut) < parent->m_bounds.h*REPARTITION_TARGET_FRACTION) {
+ targets++;
+ target[cell_id].loc = 2;
+ }
+ }
+
+ // count the number of cells on each side of the partition for every net
+ for(h::hash_map<ConcreteNet *>::iterator n_it = m_design->nets.begin(); !n_it; n_it++) {
+ for(ConcretePinList::iterator p_it = (net = *n_it)->getPins().begin(); !p_it; p_it++)
+ if (abs(target[(*p_it)->getCell()->getID()].loc) == 1)
+ count_1[net->getID()]++;
+ else if (abs(target[(*p_it)->getCell()->getID()].loc) == 2)
+ count_2[net->getID()]++;
+ else if ((*p_it)->getCell()->temp_y < initial_cut)
+ count_1[net->getID()]++;
+ else
+ count_2[net->getID()]++;
+ if (count_1[net->getID()] > 0 && count_2[net->getID()] > 0) before_cuts++;
+ }
+ }
+
+ // INITIAL GAIN CALCULATION
+ for(long id=0; id < m_design->cells.length(); id++)
+ if (target[id].loc > 0) {
+ assert(target[id].cell != 0);
+ assert(target[id].gain == 0);
+
+ // examine counts for the net on each pin
+ for(ConcretePinMap::iterator p_it = target[id].cell->getPins().begin(); !p_it; p_it++)
+ if ((*p_it)->isAttached()) {
+ int n_id = (*p_it)->getNet()->getID();
+ if (target[id].loc == 1 && count_1[n_id] == 1) target[id].gain++;
+ if (target[id].loc == 1 && count_2[n_id] == 0) target[id].gain--;
+ if (target[id].loc == 2 && count_1[n_id] == 0) target[id].gain--;
+ if (target[id].loc == 2 && count_2[n_id] == 1) target[id].gain++;
+ }
+
+ assert(target[id].cell->getPins().length() >= abs(target[id].gain));
+
+ // add it to a bin
+ int bin_num = min(max(0, target[id].gain),FM_MAX_BIN);
+ max_gain = max(max_gain, bin_num);
+
+ assert(bin_num >= 0 && bin_num <= FM_MAX_BIN);
+ target[id].next = bin[bin_num];
+ target[id].prev = 0;
+ if (bin[bin_num] != 0)
+ bin[bin_num]->prev = &target[id];
+ bin[bin_num] = &target[id];
+ }
+
+ // OUTER F-M LOOP
+ current_cuts = before_cuts;
+ int num_moves = 1;
+ int pass = 0;
+ while(num_moves > 0 && pass < FM_MAX_PASSES) {
+ pass++;
+ num_moves = 0;
+
+ // check_list(bin, locked, targets); // DEBUG
+
+ // move all locked cells back
+ int moved_back = 0;
+ while(locked != 0) {
+ FM_cell *current = locked;
+ current->locked = false;
+
+ int bin_num = min(max(0, current->gain),FM_MAX_BIN);
+ max_gain = max(max_gain, bin_num);
+
+ locked = current->next;
+ if (locked != 0)
+ locked->prev = 0;
+
+ if (bin[bin_num] != 0)
+ bin[bin_num]->prev = current;
+ current->next = bin[bin_num];
+ bin[bin_num] = current;
+
+ moved_back++;
+ }
+ // cout << "\tmoved back: " << moved_back << endl;
+ // check_list(bin, locked, targets); // DEBUG
+
+ max_gain = FM_MAX_BIN;
+ while(bin[max_gain] == 0 && max_gain > 0) max_gain--;
+
+ // INNER F-M LOOP (single pass)
+ while(1) {
+
+ int bin_num = FM_MAX_BIN;
+ FM_cell *current = bin[bin_num];
+
+ // look for next cell to move
+ while (bin_num > 0 && (current == 0 ||
+ (current->loc==1 && current->cell->getArea()+parent->m_sub2->m_area > halfArea+areaFlexibility) ||
+ (current->loc==2 && current->cell->getArea()+parent->m_sub1->m_area > halfArea+areaFlexibility))) {
+
+ if (current == 0) current = bin[--bin_num]; else current = current->next;
+ }
+ if (bin_num == 0)
+ break;
+
+ num_moves++;
+ current->locked = true;
+ // cout << "moving cell " << current->cell->getID() << " gain=" << current->gain << " pins= " << current->cell->getPins().length() << " from " << current->loc;
+
+ // change partition marking and areas
+ if (current->loc == 1) {
+ current->loc = 2;
+ parent->m_sub1->m_area -= current->cell->getArea();
+ parent->m_sub2->m_area += current->cell->getArea();
+
+ // update partition counts on all nets attached to this cell
+ for(ConcretePinMap::iterator p_it = current->cell->getPins().begin();
+ !p_it; p_it++) {
+
+ if (!(*p_it)->isAttached()) // ignore unattached pins
+ continue;
+ net = (*p_it)->getNet();
+
+ count_1[net->getID()]--;
+ count_2[net->getID()]++;
+
+ // cout << "\tnet " << net->getID() << " was " << count_1[net->getID()]+1 << "/" << count_2[net->getID()]-1 << " now " << count_1[net->getID()] << "/" << count_2[net->getID()] << endl;
+
+ // if net becomes critical, update gains on attached cells and resort bins
+ if (count_1[net->getID()] == 0) { current_cuts--; FM_updateGains(net, 2, -1, target, bin, count_1, count_2); }
+ if (count_2[net->getID()] == 1) { current_cuts++; FM_updateGains(net, 1, -1, target, bin, count_1, count_2); }
+
+ // check_list(bin, locked, targets); // DEBUG
+ }
+
+ } else {
+ current->loc = 1;
+ parent->m_sub2->m_area -= current->cell->getArea();
+ parent->m_sub1->m_area += current->cell->getArea();
+
+ // update gains on all nets attached to this cell
+ for(ConcretePinMap::iterator p_it = current->cell->getPins().begin();
+ !p_it; p_it++) {
+
+ if (!(*p_it)->isAttached()) // ignore unattached pins
+ continue;
+ net = (*p_it)->getNet();
+ count_2[net->getID()]--;
+ count_1[net->getID()]++;
+
+ // cout << "\tnet " << net->getID() << " was " << count_1[net->getID()]-1 << "/" << count_2[net->getID()]+1 << " now " << count_1[net->getID()] << "/" << count_2[net->getID()] << endl;
+
+ if (count_2[net->getID()] == 0) { current_cuts--; FM_updateGains(net, 2, -1, target, bin, count_1, count_2); }
+ if (count_1[net->getID()] == 1) { current_cuts++; FM_updateGains(net, 1, -1, target, bin, count_1, count_2); }
+
+ // check_list(bin, locked, targets); // DEBUG
+ }
+ }
+
+ //cout << " cuts=" << current_cuts << endl;
+
+ // move current to locked
+
+/*
+ cout << "b=" << bin[bin_num] << " ";
+ cout << current->prev << "-> ";
+ if (current->prev == 0)
+ cout << "X";
+ else cout << current->prev->next;
+ cout << "=" << current << "=";
+ if (current->next == 0)
+ cout << "X";
+ else
+ cout << current->next->prev;
+ cout << " ->" << current->next << endl;
+*/
+
+ if (bin[bin_num] == current)
+ bin[bin_num] = current->next;
+ if (current->prev != 0)
+ current->prev->next = current->next;
+ if (current->next != 0)
+ current->next->prev = current->prev;
+
+/*
+ cout << "b=" << bin[bin_num] << " ";
+ cout << current->prev << "-> ";
+ if (current->prev == 0)
+ cout << "X";
+ else cout << current->prev->next;
+ cout << "=" << current << "=";
+ if (current->next == 0)
+ cout << "X";
+ else
+ cout << current->next->prev;
+ cout << " ->" << current->next << endl;
+*/
+
+ current->prev = 0;
+ current->next = locked;
+ if (locked != 0)
+ locked->prev = current;
+ locked = current;
+
+ // check_list(bin, locked, targets); // DEBUG
+
+ // update max_gain
+ max_gain = FM_MAX_BIN;
+ while(bin[max_gain] == 0 && max_gain > 0) max_gain--;
+ }
+
+ // cout << "\tcurrent cuts= " << current_cuts << " moves= " << num_moves << endl;
+ }
+
+ // reassign members to subpartitions
+ cout << "FIDM-20 : \tbalance before " << parent->m_sub1->m_members.length() << "/"
+ << parent->m_sub2->m_members.length() << " ";
+ parent->m_sub1->m_members.clear();
+ parent->m_sub1->m_area = 0;
+ parent->m_sub2->m_members.clear();
+ parent->m_sub2->m_area = 0;
+ for(h::list<ConcreteCell *>::iterator it = parent->m_members.begin(); !it; it++) {
+ if (target[(*it)->getID()].loc == 1 || target[(*it)->getID()].loc == -1) {
+ parent->m_sub1->m_members.push_back(*it);
+ parent->m_sub1->m_area += (*it)->getArea();
+ }
+ else {
+ parent->m_sub2->m_members.push_back(*it);
+ parent->m_sub2->m_area += (*it)->getArea();
+ }
+ }
+ cout << " after " << parent->m_sub1->m_members.length() << "/"
+ << parent->m_sub2->m_members.length() << endl;
+
+
+ cout << "FIDM-21 : \tloc: " << initial_cut << " targetting: " << targets*100/parent->m_members.length() << "%" << endl;
+ cout << "FIDM-22 : \tstarting cuts= " << before_cuts << " final cuts= " << current_cuts << endl;
+#endif
+}
+
+// ----- FM_updateGains()
+// moves a cell between bins
+#if 0
+void FM_updateGains(ConcreteNet *net, int partition, int inc,
+ FM_cell target [], FM_cell *bin [],
+ int count_1 [], int count_2 []) {
+
+ for(ConcretePinList::iterator it = net->getPins().begin(); !it; it++) {
+ FM_cell *current = &(target[(*it)->getCell()->getID()]);
+ assert(current->cell != 0);
+
+ int old_gain = current->gain;
+ current->gain = 0;
+
+ // examine counts for the net on each pin
+ for(ConcretePinMap::iterator p_it = current->cell->getPins().begin(); !p_it; p_it++)
+ if ((*p_it)->isAttached()) {
+ int n_id = (*p_it)->getNet()->getID();
+ if (current->loc == 1 && count_1[n_id] == 1) current->gain++;
+ if (current->loc == 1 && count_2[n_id] == 0) current->gain--;
+ if (current->loc == 2 && count_1[n_id] == 0) current->gain--;
+ if (current->loc == 2 && count_2[n_id] == 1) current->gain++;
+ }
+
+ if (!current->locked) {
+ // remove cell from existing bin
+ int bin_num = min(max(0, old_gain),FM_MAX_BIN);
+ if (bin[bin_num] == current)
+ bin[bin_num] = current->next;
+ if (current->prev != 0)
+ current->prev->next = current->next;
+ if (current->next != 0)
+ current->next->prev = current->prev;
+ // add cell to correct bin
+ bin_num = min(max(0, current->gain),FM_MAX_BIN);
+ current->prev = 0;
+ current->next = bin[bin_num];
+ if (bin[bin_num] != 0)
+ bin[bin_num]->prev = current;
+ bin[bin_num] = current;
+ }
+ }
+
+}
+#endif
+
+
+// --------------------------------------------------------------------
+// partitionEqualArea()
+//
+/// \brief Splits a partition into two halves of equal area.
+//
+// --------------------------------------------------------------------
+void partitionEqualArea(Partition *parent) {
+ float halfArea, area;
+ int i=0;
+
+ // which way to sort?
+ if (parent->m_vertical)
+ // sort by X position
+ qsort(parent->m_members, parent->m_numMembers, sizeof(ConcreteCell*), cellSortByX);
+ else
+ // sort by Y position
+ qsort(parent->m_members, parent->m_numMembers, sizeof(ConcreteCell*), cellSortByY);
+
+ // split the list
+ halfArea = parent->m_area*0.5;
+ parent->m_sub1->m_area = 0.0;
+ parent->m_sub1->m_numMembers = 0;
+ parent->m_sub1->m_members = (ConcreteCell**)realloc(parent->m_sub1->m_members,
+ sizeof(ConcreteCell*)*parent->m_numMembers);
+ parent->m_sub2->m_area = 0.0;
+ parent->m_sub2->m_numMembers = 0;
+ parent->m_sub2->m_members = (ConcreteCell**)realloc(parent->m_sub2->m_members,
+ sizeof(ConcreteCell*)*parent->m_numMembers);
+
+ for(; parent->m_sub1->m_area < halfArea; i++)
+ if (parent->m_members[i]) {
+ area = getCellArea(parent->m_members[i]);
+ parent->m_sub1->m_members[parent->m_sub1->m_numMembers++] = parent->m_members[i];
+ parent->m_sub1->m_area += area;
+ }
+ for(; i<parent->m_numMembers; i++)
+ if (parent->m_members[i]) {
+ area = getCellArea(parent->m_members[i]);
+ parent->m_sub2->m_members[parent->m_sub2->m_numMembers++] = parent->m_members[i];
+ parent->m_sub2->m_area += area;
+ }
+
+}
+
+
+// --------------------------------------------------------------------
+// partitionScanlineMincut()
+//
+/// \brief Scans the cells within a partition from left to right and chooses the min-cut.
+//
+// --------------------------------------------------------------------
+void partitionScanlineMincut(Partition *parent) {
+#if 0
+ int current_cuts = 0;
+ int minimum_cuts = INT_MAX;
+ ConcreteCell *minimum_location = NULL;
+ double currentArea = 0, halfArea = parent->m_area * 0.5;
+ double areaFlexibility = parent->m_area * MAX_PARTITION_NONSYMMETRY;
+ double newLine, oldLine = -DBL_MAX;
+
+ for(ConcreteNetList::iterator n_it = m_design->nets.begin(); !n_it; n_it++)
+ (*n_it)->m_mark = 0;
+ for(h::list<ConcreteCell *>::iterator i = parent->m_members.begin();
+ !i.isDone(); i++) {
+ assert(*i);
+ for(ConcretePinMap::iterator j = (*i)->getPins().begin();
+ !j.isDone(); j++) {
+ assert(*j);
+ if((*j)->isAttached()) {
+ (*j)->getNet()->m_mark = 1;
+ }
+ }
+ }
+
+ if (parent->vertical) {
+ parent->m_members.sort(sortByX);
+ int all1 = 0, all2 = 0;
+ h::list<ConcreteCell *>::iterator local = parent->m_members.begin();
+ for(; !local.isDone(); local++) {
+ currentArea += (*local)->getArea();
+ if (currentArea < halfArea-areaFlexibility)
+ continue;
+ if (currentArea > halfArea+areaFlexibility)
+ break;
+ newLine = (*local)->temp_x;
+ while(all1 < g_place_numNets && allNetsL2[all1]->getBoundingBox().left() <= newLine) {
+ if(allNetsL2[all1]->m_mark) {
+ current_cuts++;
+ }
+ all1++;
+ }
+ while(all2 < g_place_numNets && allNetsR2[all2]->getBoundingBox().right() <= newLine) {
+ if(allNetsR2[all2]->m_mark) {
+ current_cuts--;
+ }
+ all2++;
+ }
+ if (current_cuts < minimum_cuts) {
+ minimum_cuts = current_cuts;
+ minimum_location = *local;
+ }
+ oldLine = newLine;
+ }
+ }
+ else {
+ parent->m_members.sort(sortByY);
+ int all1 = 0, all2 = 0;
+ h::list<ConcreteCell *>::iterator local = parent->m_members.begin();
+ for(; !local.isDone(); local++) {
+ currentArea += (*local)->getArea();
+ if (currentArea < halfArea-areaFlexibility)
+ continue;
+ if (currentArea > halfArea+areaFlexibility)
+ break;
+ newLine = (*local)->temp_y;
+ while(all1 < g_place_numNets && allNetsB2[all1]->getBoundingBox().top() <= newLine) {
+ if(allNetsB2[all1]->m_mark) {
+ current_cuts++;
+ }
+ all1++;
+ }
+ while(all2 < g_place_numNets && allNetsT2[all2]->getBoundingBox().bottom() <= newLine) {
+ if(allNetsT2[all2]->m_mark) {
+ current_cuts--;
+ }
+ all2++;
+ }
+ if (current_cuts < minimum_cuts) {
+ minimum_cuts = current_cuts;
+ minimum_location = *local;
+ }
+ oldLine = newLine;
+ }
+ }
+ if (minimum_location == NULL) {
+ return partitionEqualArea(parent);
+ }
+ h::list<ConcreteCell *>::iterator it = parent->m_members.begin();
+ parent->m_sub1->m_members.clear();
+ parent->m_sub1->m_area = 0;
+ for(; *it != minimum_location; it++) {
+ parent->m_sub1->m_members.push_front(*it);
+ parent->m_sub1->m_area += (*it)->getArea();
+ }
+ parent->m_sub2->m_members.clear();
+ parent->m_sub2->m_area = 0;
+ for(; !it; it++) {
+ parent->m_sub2->m_members.push_front(*it);
+ parent->m_sub2->m_area += (*it)->getArea();
+ }
+#endif
+}
+
+
+// --------------------------------------------------------------------
+// reallocPartition()
+//
+/// \brief Reallocates a partition and all of its children.
+//
+// --------------------------------------------------------------------
+void reallocPartition(Partition *p) {
+
+ if (p->m_leaf) {
+ return;
+ }
+
+ // --- INITIAL PARTITION
+
+ if (PARTITION_AREA_ONLY)
+ partitionEqualArea(p);
+ else
+ partitionScanlineMincut(p);
+
+ resizePartition(p);
+
+ // --- PARTITION IMPROVEMENT
+ if (p->m_level < REPARTITION_LEVEL_DEPTH) {
+ if (REPARTITION_HMETIS)
+ repartitionHMetis(p);
+
+ resizePartition(p);
+ }
+
+ reallocPartition(p->m_sub1);
+ reallocPartition(p->m_sub2);
+}
+
+
+// --------------------------------------------------------------------
+// resizePartition()
+//
+/// \brief Recomputes the bounding boxes of the child partitions based on their relative areas.
+//
+// --------------------------------------------------------------------
+void resizePartition(Partition *p) {
+ // compute the new bounding box
+ p->m_sub1->m_bounds.x = p->m_bounds.x;
+ p->m_sub1->m_bounds.y = p->m_bounds.y;
+ if (p->m_vertical) {
+ p->m_sub1->m_bounds.w = p->m_bounds.w*(p->m_sub1->m_area/p->m_area);
+ p->m_sub1->m_bounds.h = p->m_bounds.h;
+ p->m_sub2->m_bounds.x = p->m_bounds.x + p->m_sub1->m_bounds.w;
+ p->m_sub2->m_bounds.w = p->m_bounds.w*(p->m_sub2->m_area/p->m_area);
+ p->m_sub2->m_bounds.y = p->m_bounds.y;
+ p->m_sub2->m_bounds.h = p->m_bounds.h;
+ } else {
+ p->m_sub1->m_bounds.h = p->m_bounds.h*(p->m_sub1->m_area/p->m_area);
+ p->m_sub1->m_bounds.w = p->m_bounds.w;
+ p->m_sub2->m_bounds.y = p->m_bounds.y + p->m_sub1->m_bounds.h;
+ p->m_sub2->m_bounds.h = p->m_bounds.h*(p->m_sub2->m_area/p->m_area);
+ p->m_sub2->m_bounds.x = p->m_bounds.x;
+ p->m_sub2->m_bounds.w = p->m_bounds.w;
+ }
+}
+
+
+// --------------------------------------------------------------------
+// incrementalSubpartition()
+//
+/// \brief Adds new cells to an existing partition. Partition sizes/locations are unchanged.
+///
+/// The function recurses, adding new cells to appropriate subpartitions.
+//
+// --------------------------------------------------------------------
+void incrementalSubpartition(Partition *p, ConcreteCell *newCells [], const int numNewCells) {
+ int c;
+ ConcreteCell **newCells1 = (ConcreteCell **)malloc(sizeof(ConcreteCell*)*numNewCells),
+ **newCells2 = (ConcreteCell **)malloc(sizeof(ConcreteCell*)*numNewCells);
+ int numNewCells1 = 0, numNewCells2 = 0;
+ float cut_loc;
+
+ assert(p);
+
+ // add new cells to partition list
+ p->m_members = (ConcreteCell**)realloc(p->m_members,
+ sizeof(ConcreteCell*)*(p->m_numMembers+numNewCells));
+ memcpy(&(p->m_members[p->m_numMembers]), newCells, sizeof(ConcreteCell*)*numNewCells);
+ p->m_numMembers += numNewCells;
+
+ // if is a leaf partition, finished
+ if (p->m_leaf) return;
+
+ // split new cells into sub-partitions based on location
+ if (p->m_vertical) {
+ cut_loc = p->m_sub2->m_bounds.x;
+ for(c=0; c<numNewCells; c++)
+ if (newCells[c]->m_x < cut_loc)
+ newCells1[numNewCells1++] = newCells[c];
+ else
+ newCells2[numNewCells2++] = newCells[c];
+ } else {
+ cut_loc = p->m_sub2->m_bounds.y;
+ for(c=0; c<numNewCells; c++)
+ if (newCells[c]->m_y < cut_loc)
+ newCells1[numNewCells1++] = newCells[c];
+ else
+ newCells2[numNewCells2++] = newCells[c];
+ }
+
+ if (numNewCells1 > 0) incrementalSubpartition(p->m_sub1, newCells1, numNewCells1);
+ if (numNewCells2 > 0) incrementalSubpartition(p->m_sub2, newCells2, numNewCells2);
+
+ free(newCells1);
+ free(newCells2);
+}
+
+
+// --------------------------------------------------------------------
+// incrementalPartition()
+//
+/// \brief Adds new cells to an existing partition. Partition sizes/locations are unchanged.
+///
+/// The function recurses, adding new cells to appropriate subpartitions.
+//
+// --------------------------------------------------------------------
+void incrementalPartition() {
+ int c = 0, c2 = 0;
+ int numNewCells = 0;
+ ConcreteCell **allCells = (ConcreteCell **)malloc(sizeof(ConcreteCell*)*g_place_numCells),
+ **newCells = (ConcreteCell **)malloc(sizeof(ConcreteCell*)*g_place_numCells);
+
+ assert(g_place_rootPartition);
+
+ // update cell list of root partition
+ memcpy(allCells, g_place_concreteCells, sizeof(ConcreteCell*)*g_place_numCells);
+ qsort(allCells, g_place_numCells, sizeof(ConcreteCell*), cellSortByID);
+ qsort(g_place_rootPartition->m_members, g_place_rootPartition->m_numMembers,
+ sizeof(ConcreteCell*), cellSortByID);
+
+ // scan sorted lists and collect cells not in partitions
+ while(!allCells[c++]);
+ while(!g_place_rootPartition->m_members[c2++]);
+
+ for(; c<g_place_numCells; c++, c2++) {
+ while(c2 < g_place_rootPartition->m_numMembers &&
+ allCells[c]->m_id > g_place_rootPartition->m_members[c2]->m_id) c2++;
+ while(c < g_place_numCells &&
+ (c2 >= g_place_rootPartition->m_numMembers ||
+ allCells[c]->m_id < g_place_rootPartition->m_members[c2]->m_id)) {
+ // a new cell!
+ newCells[numNewCells++] = allCells[c];
+ c++;
+ }
+ }
+
+ printf("QPRT-50 : \tincremental partitioning with %d new cells\n", numNewCells);
+ if (numNewCells>0) incrementalSubpartition(g_place_rootPartition, newCells, numNewCells);
+
+ free(allCells);
+ free(newCells);
+}
diff --git a/src/phys/place/place_qpsolver.c b/src/phys/place/place_qpsolver.c
new file mode 100644
index 00000000..9df9c6dc
--- /dev/null
+++ b/src/phys/place/place_qpsolver.c
@@ -0,0 +1,1270 @@
+/*===================================================================*/
+//
+// place_qpsolver.c
+//
+// Philip Chong
+// pchong@cadence.com
+//
+/*===================================================================*/
+
+#include <assert.h>
+#include <math.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+#include "place_qpsolver.h"
+
+#undef QPS_DEBUG
+
+#define QPS_TOL 1.0e-3
+#define QPS_EPS (QPS_TOL * QPS_TOL)
+
+#define QPS_MAX_TOL 0.1
+#define QPS_LOOP_TOL 1.0e-3
+
+#define QPS_RELAX_ITER 180
+#define QPS_MAX_ITER 200
+#define QPS_STEPSIZE_RETRIES 2
+#define QPS_MINSTEP 1.0e-6
+#define QPS_DEC_CHANGE 0.01
+
+#define QPS_PRECON
+#define QPS_PRECON_EPS 1.0e-9
+
+#undef QPS_HOIST
+
+#if defined(QPS_DEBUG)
+#define QPS_DEBUG_FILE "/tmp/qps_debug.log"
+#endif
+
+#if 0
+ /* ii is an array [0..p->num_cells-1] of indices from cells of original
+ problem to modified problem variables. If ii[k] >= 0, cell is an
+ independent cell; ii[k], ii[k]+1 are the indices of the corresponding
+ variables for the modified problem. If ii[k] == -1, cell is a fixed
+ cell. If ii[k] <= -2, cell is a dependent cell; -(ii[k]+2) is the index
+ of the corresponding COG constraint. */
+int *ii;
+
+ /* gt is an array [0..p->cog_num-1] of indices from COG constraints to
+ locations in the gl array (in qps_problem_t). gt[k] is the offset into
+ gl where the kth constraint begins. */
+int *gt;
+
+ /* n is the number of variables in the modified problem. n should be twice
+ the number of independent cells. */
+int n;
+
+qps_float_t *cp; /* current location during CG iteration */
+qps_float_t f; /* value of cost function at p */
+
+#endif
+
+/**********************************************************************/
+
+static void
+qps_settp(qps_problem_t * p)
+{
+ /* Fill in the p->priv_tp array with the current locations of all cells
+ (independent, dependent and fixed). */
+
+ int i;
+ int t, u;
+ int pr;
+ qps_float_t rx, ry;
+ qps_float_t ta;
+
+ int *ii = p->priv_ii;
+ qps_float_t *tp = p->priv_tp;
+ qps_float_t *cp = p->priv_cp;
+
+ /* do independent and fixed cells first */
+ for (i = p->num_cells; i--;) {
+ t = ii[i];
+ if (t >= 0) { /* indep cell */
+ tp[i * 2] = cp[t];
+ tp[i * 2 + 1] = cp[t + 1];
+ }
+ else if (t == -1) { /* fixed cell */
+ tp[i * 2] = p->x[i];
+ tp[i * 2 + 1] = p->y[i];
+ }
+ }
+ /* now do dependent cells */
+ for (i = p->num_cells; i--;) {
+ if (ii[i] < -1) {
+ t = -(ii[i] + 2); /* index of COG constraint */
+ ta = 0.0;
+ rx = 0.0;
+ ry = 0.0;
+ pr = p->priv_gt[t];
+ while ((u = p->cog_list[pr++]) >= 0) {
+ ta += p->area[u];
+ if (u != i) {
+ rx -= p->area[u] * tp[u * 2];
+ ry -= p->area[u] * tp[u * 2 + 1];
+ }
+ }
+ rx += p->cog_x[t] * ta;
+ ry += p->cog_y[t] * ta;
+ tp[i * 2] = rx / p->area[i];
+ tp[i * 2 + 1] = ry / p->area[i];
+ }
+ }
+
+#if (QPS_DEBUG > 5)
+ fprintf(p->priv_fp, "### qps_settp()\n");
+ for (i = 0; i < p->num_cells; i++) {
+ fprintf(p->priv_fp, "%f %f\n", tp[i * 2], tp[i * 2 + 1]);
+ }
+#endif
+}
+
+/**********************************************************************/
+
+static qps_float_t
+qps_func(qps_problem_t * p)
+{
+ /* Return f(p). qps_settp() should have already been called before
+ entering here */
+
+ int j, k;
+ int pr;
+ qps_float_t jx, jy, tx, ty;
+ qps_float_t f;
+ qps_float_t w;
+
+#if !defined(QPS_HOIST)
+ int i;
+ int st;
+ qps_float_t kx, ky, sx, sy;
+ qps_float_t t;
+#endif
+
+ qps_float_t *tp = p->priv_tp;
+
+ f = 0.0;
+ pr = 0;
+ for (j = 0; j < p->num_cells; j++) {
+ jx = tp[j * 2];
+ jy = tp[j * 2 + 1];
+ while ((k = p->priv_cc[pr]) >= 0) {
+ w = p->priv_cw[pr];
+ tx = tp[k * 2] - jx;
+ ty = tp[k * 2 + 1] - jy;
+ f += w * (tx * tx + ty * ty);
+ pr++;
+ }
+ pr++;
+ }
+ p->f = f;
+
+#if !defined(QPS_HOIST)
+ /* loop penalties */
+ pr = 0;
+ for (i = 0; i < p->loop_num; i++) {
+ t = 0.0;
+ j = st = p->loop_list[pr++];
+ jx = sx = tp[j * 2];
+ jy = sy = tp[j * 2 + 1];
+ while ((k = p->loop_list[pr]) >= 0) {
+ kx = tp[k * 2];
+ ky = tp[k * 2 + 1];
+ tx = jx - kx;
+ ty = jy - ky;
+ t += tx * tx + ty * ty;
+ j = k;
+ jx = kx;
+ jy = ky;
+ pr++;
+ }
+ tx = jx - sx;
+ ty = jy - sy;
+ t += tx * tx + ty * ty;
+ t -= p->loop_max[i];
+#if (QPS_DEBUG > 5)
+ fprintf(p->priv_fp, "### qps_penalty() %d %f %f\n",
+ i, p->loop_max[i], t);
+#endif
+ p->priv_lt[i] = t;
+ f += p->loop_penalty[i] * t;
+ pr++;
+ }
+#endif /* QPS_HOIST */
+
+ if (p->max_enable) {
+ for (j = p->num_cells; j--;) {
+ f += p->priv_mxl[j] * (-tp[j * 2]);
+ f += p->priv_mxh[j] * (tp[j * 2] - p->max_x);
+ f += p->priv_myl[j] * (-tp[j * 2 + 1]);
+ f += p->priv_myh[j] * (tp[j * 2 + 1] - p->max_y);
+ }
+ }
+
+#if (QPS_DEBUG > 5)
+ fprintf(p->priv_fp, "### qps_func() %f %f\n", f, p->f);
+#endif
+ return f;
+}
+
+/**********************************************************************/
+
+static void
+qps_dfunc(qps_problem_t * p, qps_float_t * d)
+{
+ /* Set d to grad f(p). First computes partial derivatives wrt all cells
+ then finds gradient wrt only the independent cells. qps_settp() should
+ have already been called before entering here */
+
+ int i, j, k;
+ int pr = 0;
+ qps_float_t jx, jy, kx, ky, tx, ty;
+ int ji, ki;
+ qps_float_t w;
+
+#if !defined(QPS_HOIST)
+ qps_float_t sx, sy;
+ int st;
+#endif
+
+ qps_float_t *tp = p->priv_tp;
+ qps_float_t *tp2 = p->priv_tp2;
+
+ /* compute partials and store in tp2 */
+ for (i = p->num_cells; i--;) {
+ tp2[i * 2] = 0.0;
+ tp2[i * 2 + 1] = 0.0;
+ }
+ for (j = 0; j < p->num_cells; j++) {
+ jx = tp[j * 2];
+ jy = tp[j * 2 + 1];
+ while ((k = p->priv_cc[pr]) >= 0) {
+ w = 2.0 * p->priv_cw[pr];
+ kx = tp[k * 2];
+ ky = tp[k * 2 + 1];
+ tx = w * (jx - kx);
+ ty = w * (jy - ky);
+ tp2[j * 2] += tx;
+ tp2[k * 2] -= tx;
+ tp2[j * 2 + 1] += ty;
+ tp2[k * 2 + 1] -= ty;
+ pr++;
+ }
+ pr++;
+ }
+
+#if !defined(QPS_HOIST)
+ /* loop penalties */
+ pr = 0;
+ for (i = 0; i < p->loop_num; i++) {
+ j = st = p->loop_list[pr++];
+ jx = sx = tp[j * 2];
+ jy = sy = tp[j * 2 + 1];
+ w = 2.0 * p->loop_penalty[i];
+ while ((k = p->loop_list[pr]) >= 0) {
+ kx = tp[k * 2];
+ ky = tp[k * 2 + 1];
+ tx = w * (jx - kx);
+ ty = w * (jy - ky);
+ tp2[j * 2] += tx;
+ tp2[k * 2] -= tx;
+ tp2[j * 2 + 1] += ty;
+ tp2[k * 2 + 1] -= ty;
+ j = k;
+ jx = kx;
+ jy = ky;
+ pr++;
+ }
+ tx = w * (jx - sx);
+ ty = w * (jy - sy);
+ tp2[j * 2] += tx;
+ tp2[st * 2] -= tx;
+ tp2[j * 2 + 1] += ty;
+ tp2[st * 2 + 1] -= ty;
+ pr++;
+ }
+#endif /* QPS_HOIST */
+
+ if (p->max_enable) {
+ for (j = p->num_cells; j--;) {
+ tp2[j * 2] += p->priv_mxh[j] - p->priv_mxl[j];
+ tp2[j * 2 + 1] += p->priv_myh[j] - p->priv_myl[j];
+ }
+ }
+
+#if (QPS_DEBUG > 5)
+ fprintf(p->priv_fp, "### qps_dfunc() partials\n");
+ for (j = 0; j < p->num_cells; j++) {
+ fprintf(p->priv_fp, "%f %f\n", tp2[j * 2], tp2[j * 2 + 1]);
+ }
+#endif
+
+ /* translate partials to independent variables */
+ for (j = p->priv_n; j--;) {
+ d[j] = 0.0;
+ }
+ for (j = p->num_cells; j--;) {
+ ji = p->priv_ii[j];
+ if (ji >= 0) { /* indep var */
+ d[ji] += tp2[j * 2];
+ d[ji + 1] += tp2[j * 2 + 1];
+ }
+ else if (ji < -1) { /* dependent variable */
+ ji = -(ji + 2); /* get COG index */
+ pr = p->priv_gt[ji];
+ while ((k = p->cog_list[pr]) >= 0) {
+ ki = p->priv_ii[k];
+ if (ki >= 0) {
+ w = p->priv_gw[pr];
+#if (QPS_DEBUG > 0)
+ assert(fabs(w - p->area[k] / p->area[j]) < 1.0e-6);
+#endif
+ d[ki] -= tp2[j * 2] * w;
+ d[ki + 1] -= tp2[j * 2 + 1] * w;
+ }
+ pr++;
+ }
+ }
+ }
+
+#if (QPS_DEBUG > 5)
+ fprintf(p->priv_fp, "### qps_dfunc() gradient\n");
+ for (j = 0; j < p->priv_n; j++) {
+ fprintf(p->priv_fp, "%f\n", d[j]);
+ }
+#endif
+}
+
+/**********************************************************************/
+
+static void
+qps_linmin(qps_problem_t * p, qps_float_t dgg, qps_float_t * h)
+{
+ /* Perform line minimization. p->priv_cp is the current location, h is
+ direction of the gradient. Updates p->priv_cp to line minimal position
+ based on formulas from "Handbook of Applied Optimization", Pardalos and
+ Resende, eds., Oxford Univ. Press, 2002. qps_settp() should have
+ already been called before entering here. Since p->priv_cp is changed,
+ p->priv_tp array becomes invalid following this routine. */
+
+ int i, j, k;
+ int pr;
+ int ji, ki;
+ qps_float_t jx, jy, kx, ky;
+ qps_float_t f = 0.0;
+ qps_float_t w;
+
+#if !defined(QPS_HOIST)
+ int st;
+ qps_float_t sx, sy, tx, ty;
+ qps_float_t t;
+#endif
+
+ qps_float_t *tp = p->priv_tp;
+
+ /* translate h vector to partials over all variables and store in tp */
+ for (i = p->num_cells; i--;) {
+ tp[i * 2] = 0.0;
+ tp[i * 2 + 1] = 0.0;
+ }
+ for (j = p->num_cells; j--;) {
+ ji = p->priv_ii[j];
+ if (ji >= 0) { /* indep cell */
+ tp[j * 2] = h[ji];
+ tp[j * 2 + 1] = h[ji + 1];
+ }
+ else if (ji < -1) { /* dep cell */
+ ji = -(ji + 2); /* get COG index */
+ pr = p->priv_gt[ji];
+ while ((k = p->cog_list[pr]) >= 0) {
+ ki = p->priv_ii[k];
+ if (ki >= 0) {
+ w = p->priv_gw[pr];
+#if (QPS_DEBUG > 0)
+ assert(fabs(w - p->area[k] / p->area[j]) < 1.0e-6);
+#endif
+ tp[j * 2] -= h[ki] * w;
+ tp[j * 2 + 1] -= h[ki + 1] * w;
+ }
+ pr++;
+ }
+ }
+ }
+
+ /* take product x^T Z^T C Z x */
+ pr = 0;
+ for (j = 0; j < p->num_cells; j++) {
+ jx = tp[j * 2];
+ jy = tp[j * 2 + 1];
+ while ((k = p->priv_cc[pr]) >= 0) {
+ w = p->priv_cw[pr];
+ kx = tp[k * 2] - jx;
+ ky = tp[k * 2 + 1] - jy;
+ f += w * (kx * kx + ky * ky);
+ pr++;
+ }
+ pr++;
+ }
+
+#if !defined(QPS_HOIST)
+ /* add loop penalties */
+ pr = 0;
+ for (i = 0; i < p->loop_num; i++) {
+ t = 0.0;
+ j = st = p->loop_list[pr++];
+ jx = sx = tp[j * 2];
+ jy = sy = tp[j * 2 + 1];
+ while ((k = p->loop_list[pr]) >= 0) {
+ kx = tp[k * 2];
+ ky = tp[k * 2 + 1];
+ tx = jx - kx;
+ ty = jy - ky;
+ t += tx * tx + ty * ty;
+ j = k;
+ jx = kx;
+ jy = ky;
+ pr++;
+ }
+ tx = jx - sx;
+ ty = jy - sy;
+ t += tx * tx + ty * ty;
+ f += p->loop_penalty[i] * t;
+ pr++;
+ }
+#endif /* QPS_HOIST */
+
+#if (QPS_DEBUG > 0)
+ assert(f);
+#endif
+
+ /* compute step size */
+ f = (dgg / f) / 2.0;
+ for (j = p->priv_n; j--;) {
+ p->priv_cp[j] += f * h[j];
+ }
+#if (QPS_DEBUG > 5)
+ fprintf(p->priv_fp, "### qps_linmin() step %f\n", f);
+ for (j = 0; j < p->priv_n; j++) {
+ fprintf(p->priv_fp, "%f\n", p->priv_cp[j]);
+ }
+#endif
+}
+
+/**********************************************************************/
+
+static void
+qps_cgmin(qps_problem_t * p)
+{
+ /* Perform CG minimization. Mostly from "Numerical Recipes", Press et al.,
+ Cambridge Univ. Press, 1992, with some changes to help performance in
+ our restricted problem domain. */
+
+ qps_float_t fp, gg, dgg, gam;
+ qps_float_t t;
+ int i, j;
+
+ int n = p->priv_n;
+ qps_float_t *g = p->priv_g;
+ qps_float_t *h = p->priv_h;
+ qps_float_t *xi = p->priv_xi;
+
+ qps_settp(p);
+ fp = qps_func(p);
+ qps_dfunc(p, g);
+
+ dgg = 0.0;
+ for (j = n; j--;) {
+ g[j] = -g[j];
+ h[j] = g[j];
+#if defined(QPS_PRECON)
+ h[j] *= p->priv_pcgt[j];
+#endif
+ dgg += g[j] * h[j];
+ }
+
+ for (i = 0; i < 2 * n; i++) {
+
+#if (QPS_DEBUG > 5)
+ fprintf(p->priv_fp, "### qps_cgmin() top\n");
+ for (j = 0; j < p->priv_n; j++) {
+ fprintf(p->priv_fp, "%f\n", p->priv_cp[j]);
+ }
+#endif
+
+ if (dgg == 0.0) {
+ break;
+ }
+ qps_linmin(p, dgg, h);
+ qps_settp(p);
+ p->priv_f = qps_func(p);
+ if (fabs((p->priv_f) - fp) <=
+ (fabs(p->priv_f) + fabs(fp) + QPS_EPS) * QPS_TOL / 2.0) {
+ break;
+ }
+ fp = p->priv_f;
+ qps_dfunc(p, xi);
+ gg = dgg;
+ dgg = 0.0;
+ for (j = n; j--;) {
+ t = xi[j] * xi[j];
+#if defined(QPS_PRECON)
+ t *= p->priv_pcgt[j];
+#endif
+ dgg += t;
+ }
+ gam = dgg / gg;
+ for (j = n; j--;) {
+ g[j] = -xi[j];
+ t = g[j];
+#if defined(QPS_PRECON)
+ t *= p->priv_pcgt[j];
+#endif
+ h[j] = t + gam * h[j];
+ }
+ }
+#if (QPS_DEBUG > 0)
+ fprintf(p->priv_fp, "### CG ITERS=%d %d %d\n", i, p->cog_num, p->loop_num);
+#endif
+ if (i == 2 * n) {
+ fprintf(stderr, "### Too many iterations in qps_cgmin()\n");
+#if defined(QPS_DEBUG)
+ fprintf(p->priv_fp, "### Too many iterations in qps_cgmin()\n");
+#endif
+ }
+}
+
+/**********************************************************************/
+
+void
+qps_init(qps_problem_t * p)
+{
+ int i, j;
+ int pr, pw;
+
+#if defined(QPS_DEBUG)
+ p->priv_fp = fopen(QPS_DEBUG_FILE, "a");
+ assert(p->priv_fp);
+#endif
+
+#if (QPS_DEBUG > 5)
+ fprintf(p->priv_fp, "### n=%d gn=%d ln=%d\n", p->num_cells, p->cog_num,
+ p->loop_num);
+ pr = 0;
+ fprintf(p->priv_fp, "### (c w) values\n");
+ for (i = 0; i < p->num_cells; i++) {
+ fprintf(p->priv_fp, "net %d: ", i);
+ while (p->connect[pr] >= 0) {
+ fprintf(p->priv_fp, "(%d %f) ", p->connect[pr], p->edge_weight[pr]);
+ pr++;
+ }
+ fprintf(p->priv_fp, "(-1 -1.0)\n");
+ pr++;
+ }
+ fprintf(p->priv_fp, "### (x y f) values\n");
+ for (i = 0; i < p->num_cells; i++) {
+ fprintf(p->priv_fp, "cell %d: (%f %f %d)\n", i, p->x[i], p->y[i],
+ p->fixed[i]);
+ }
+#if 0
+ if (p->cog_num) {
+ fprintf(p->priv_fp, "### ga values\n");
+ for (i = 0; i < p->num_cells; i++) {
+ fprintf(p->priv_fp, "cell %d: (%f)\n", i, p->area[i]);
+ }
+ }
+ pr = 0;
+ fprintf(p->priv_fp, "### gl values\n");
+ for (i = 0; i < p->cog_num; i++) {
+ fprintf(p->priv_fp, "cog %d: ", i);
+ while (p->cog_list[pr] >= 0) {
+ fprintf(p->priv_fp, "%d ", p->cog_list[pr]);
+ pr++;
+ }
+ fprintf(p->priv_fp, "-1\n");
+ pr++;
+ }
+ fprintf(p->priv_fp, "### (gx gy) values\n");
+ for (i = 0; i < p->cog_num; i++) {
+ fprintf(p->priv_fp, "cog %d: (%f %f)\n", i, p->cog_x[i], p->cog_y[i]);
+ }
+#endif
+#endif /* QPS_DEBUG */
+
+ p->priv_ii = (int *)malloc(p->num_cells * sizeof(int));
+ assert(p->priv_ii);
+
+ p->max_enable = 0;
+
+ p->priv_fopt = 0.0;
+
+ /* canonify c and w */
+ pr = pw = 0;
+ for (i = 0; i < p->num_cells; i++) {
+ while ((j = p->connect[pr]) >= 0) {
+ if (j > i) {
+ pw++;
+ }
+ pr++;
+ }
+ pw++;
+ pr++;
+ }
+ p->priv_cc = (int *)malloc(pw * sizeof(int));
+ assert(p->priv_cc);
+ p->priv_cr = (int *)malloc(p->num_cells * sizeof(int));
+ assert(p->priv_cr);
+ p->priv_cw = (qps_float_t*)malloc(pw * sizeof(qps_float_t));
+ assert(p->priv_cw);
+ p->priv_ct = (qps_float_t*)malloc(pw * sizeof(qps_float_t));
+ assert(p->priv_ct);
+ p->priv_cm = pw;
+ pr = pw = 0;
+ for (i = 0; i < p->num_cells; i++) {
+ p->priv_cr[i] = pw;
+ while ((j = p->connect[pr]) >= 0) {
+ if (j > i) {
+ p->priv_cc[pw] = p->connect[pr];
+ p->priv_ct[pw] = p->edge_weight[pr];
+ pw++;
+ }
+ pr++;
+ }
+ p->priv_cc[pw] = -1;
+ p->priv_ct[pw] = -1.0;
+ pw++;
+ pr++;
+ }
+ assert(pw == p->priv_cm);
+
+ /* temp arrays for function eval */
+ p->priv_tp = (qps_float_t *) malloc(4 * p->num_cells * sizeof(qps_float_t));
+ assert(p->priv_tp);
+ p->priv_tp2 = p->priv_tp + 2 * p->num_cells;
+}
+
+/**********************************************************************/
+
+static qps_float_t
+qps_estopt(qps_problem_t * p)
+{
+ int i, j, cell;
+ qps_float_t r;
+ qps_float_t *t1, *t2;
+ qps_float_t t;
+
+ if (p->max_enable) {
+ r = 0.0;
+ t1 = (qps_float_t *) malloc(2 * p->num_cells * sizeof(qps_float_t));
+#if (QPS_DEBUG > 0)
+ assert(t1);
+#endif
+ for (i = 2 * p->num_cells; i--;) {
+ t1[i] = 0.0;
+ }
+ j = 0;
+ for (i = 0; i < p->cog_num; i++) {
+ while ((cell = p->cog_list[j]) >= 0) {
+ t1[cell * 2] = p->cog_x[i];
+ t1[cell * 2 + 1] = p->cog_y[i];
+ j++;
+ }
+ j++;
+ }
+ t2 = p->priv_tp;
+ p->priv_tp = t1;
+ r = qps_func(p);
+ p->priv_tp = t2;
+ free(t1);
+ t = (p->max_x * p->max_x + p->max_y * p->max_y);
+ t *= p->num_cells;
+ for (i = p->num_cells; i--;) {
+ if (p->fixed[i]) {
+ r += t;
+ }
+ }
+ }
+ else {
+ r = p->priv_f;
+ }
+ if (p->loop_num) {
+ /* FIXME hacky */
+ r *= 8.0;
+ }
+ return r;
+}
+
+/**********************************************************************/
+
+static void
+qps_solve_inner(qps_problem_t * p)
+{
+ int i;
+ qps_float_t t;
+ qps_float_t z;
+ qps_float_t pm1, pm2, tp;
+ qps_float_t *tw;
+#if defined(QPS_HOIST)
+ int j, k;
+ qps_float_t jx, jy, kx, ky, sx, sy, tx, ty;
+ int pr, st;
+#endif
+
+ tw = p->priv_cw;
+#if defined(QPS_HOIST)
+ if (!p->loop_num) {
+ p->priv_cw = p->priv_ct;
+ }
+ else {
+ for(i=p->priv_cm; i--;) {
+ p->priv_cw[i] = p->priv_ct[i];
+ }
+ /* augment with loop penalties */
+ pr = 0;
+ for (i = 0; i < p->loop_num; i++) {
+ while ((j = p->priv_la[pr++]) != -1) {
+ if (j >= 0) {
+ p->priv_cw[j] += p->loop_penalty[i];
+ }
+ }
+ pr++;
+ }
+ }
+#else /* !QPS_HOIST */
+ p->priv_cw = p->priv_ct;
+#endif /* QPS_HOIST */
+
+ qps_cgmin(p);
+
+ if (p->max_enable || p->loop_num) {
+ if (p->max_enable == 1 || (p->loop_num && p->loop_k == 0)) {
+ p->priv_eps = 2.0;
+ p->priv_fmax = p->priv_f;
+ p->priv_fprev = p->priv_f;
+ p->priv_fopt = qps_estopt(p);
+ p->priv_pn = 0;
+ p->loop_fail = 0;
+ }
+ else {
+ if (p->priv_f < p->priv_fprev &&
+ (p->priv_fprev - p->priv_f) >
+ QPS_DEC_CHANGE * fabs(p->priv_fprev)) {
+ if (p->priv_pn++ >= QPS_STEPSIZE_RETRIES) {
+ p->priv_eps /= 2.0;
+ p->priv_pn = 0;
+ }
+ }
+ p->priv_fprev = p->priv_f;
+ if (p->priv_fmax < p->priv_f) {
+ p->priv_fmax = p->priv_f;
+ }
+ if (p->priv_f >= p->priv_fopt) {
+ p->priv_fopt = p->priv_fmax * 2.0;
+ p->loop_fail |= 2;
+#if (QPS_DEBUG > 0)
+ fprintf(p->priv_fp, "### warning: changing fopt\n");
+#endif
+ }
+ }
+#if (QPS_DEBUG > 0)
+ fprintf(p->priv_fp, "### max_stat %.2e %.2e %.2e %.2e\n",
+ p->priv_f, p->priv_eps, p->priv_fmax, p->priv_fopt);
+ fflush(p->priv_fp);
+#endif
+ }
+
+ p->loop_done = 1;
+ if (p->loop_num) {
+#if (QPS_DEBUG > 0)
+ fprintf(p->priv_fp, "### begin_update %d\n", p->loop_k);
+#endif
+ p->loop_k++;
+
+#if defined(QPS_HOIST)
+ /* calc loop penalties */
+ pr = 0;
+ for (i = 0; i < p->loop_num; i++) {
+ t = 0.0;
+ j = st = p->loop_list[pr++];
+ jx = sx = p->priv_tp[j * 2];
+ jy = sy = p->priv_tp[j * 2 + 1];
+ while ((k = p->loop_list[pr]) >= 0) {
+ kx = p->priv_tp[k * 2];
+ ky = p->priv_tp[k * 2 + 1];
+ tx = jx - kx;
+ ty = jy - ky;
+ t += tx * tx + ty * ty;
+ j = k;
+ jx = kx;
+ jy = ky;
+ pr++;
+ }
+ tx = jx - sx;
+ ty = jy - sy;
+ t += tx * tx + ty * ty;
+ p->priv_lt[i] = t - p->loop_max[i];
+ pr++;
+ }
+#endif /* QPS_HOIST */
+
+ /* check KKT conditions */
+#if (QPS_DEBUG > 1)
+ for (i = p->loop_num; i--;) {
+ if (p->loop_penalty[i] != 0.0) {
+ fprintf(p->priv_fp, "### penalty %d %.2e\n", i, p->loop_penalty[i]);
+ }
+ }
+#endif
+ t = 0.0;
+ for (i = p->loop_num; i--;) {
+ if (p->priv_lt[i] > 0.0 || p->loop_penalty[i] > 0.0) {
+ t += p->priv_lt[i] * p->priv_lt[i];
+ }
+ if (fabs(p->priv_lt[i]) < QPS_LOOP_TOL) {
+#if (QPS_DEBUG > 4)
+ fprintf(p->priv_fp, "### skip %d %f\n", i, p->priv_lt[i]);
+#endif
+ continue;
+ }
+ z = QPS_LOOP_TOL * p->loop_max[i];
+ if (p->priv_lt[i] > z || (p->loop_k < QPS_RELAX_ITER &&
+ p->loop_penalty[i] * p->priv_lt[i] < -z)) {
+ p->loop_done = 0;
+#if (QPS_DEBUG > 1)
+ fprintf(p->priv_fp, "### not_done %d %f %f %f %f\n", i,
+ p->priv_lt[i], z, p->loop_max[i], p->loop_penalty[i]);
+#endif
+ }
+#if (QPS_DEBUG > 5)
+ else {
+ fprintf(p->priv_fp, "### done %d %f %f %f %f\n", i,
+ p->priv_lt[i], z, p->loop_max[i], p->loop_penalty[i]);
+ }
+#endif
+ }
+ /* update penalties */
+ if (!p->loop_done) {
+ t = p->priv_eps * (p->priv_fopt - p->priv_f) / t;
+ tp = 0.0;
+ for (i = p->loop_num; i--;) {
+ pm1 = p->loop_penalty[i];
+#if (QPS_DEBUG > 5)
+ fprintf(p->priv_fp, "### update %d %.2e %.2e %.2e %.2e %.2e\n", i,
+ t, p->priv_lt[i], t * p->priv_lt[i], pm1, p->loop_max[i]);
+#endif
+ p->loop_penalty[i] += t * p->priv_lt[i];
+ if (p->loop_penalty[i] < 0.0) {
+ p->loop_penalty[i] = 0.0;
+ }
+ pm2 = p->loop_penalty[i];
+ tp += fabs(pm1 - pm2);
+ }
+#if (QPS_DEBUG > 4)
+ fprintf(p->priv_fp, "### penalty mag %f\n", tp);
+#endif
+ }
+ }
+
+ p->max_done = 1;
+ if (p->max_enable) {
+#if (QPS_DEBUG > 4)
+ fprintf(p->priv_fp, "### begin_max_update %d\n", p->max_enable);
+#endif
+ t = 0.0;
+ for (i = p->num_cells; i--;) {
+ z = -(p->x[i]);
+ t += z * z;
+ if (z > QPS_TOL || (p->max_enable < QPS_RELAX_ITER &&
+ p->priv_mxl[i] * z < -QPS_MAX_TOL)) {
+ p->max_done = 0;
+#if (QPS_DEBUG > 4)
+ fprintf(p->priv_fp, "### nxl %d %f %f\n", i, z, p->priv_mxl[i]);
+#endif
+ }
+ z = (p->x[i] - p->max_x);
+ t += z * z;
+ if (z > QPS_TOL || (p->max_enable < QPS_RELAX_ITER &&
+ p->priv_mxh[i] * z < -QPS_MAX_TOL)) {
+ p->max_done = 0;
+#if (QPS_DEBUG > 4)
+ fprintf(p->priv_fp, "### nxh %d %f %f\n", i, z, p->priv_mxh[i]);
+#endif
+ }
+ z = -(p->y[i]);
+ t += z * z;
+ if (z > QPS_TOL || (p->max_enable < QPS_RELAX_ITER &&
+ p->priv_myl[i] * z < -QPS_MAX_TOL)) {
+ p->max_done = 0;
+#if (QPS_DEBUG > 4)
+ fprintf(p->priv_fp, "### nyl %d %f %f\n", i, z, p->priv_myl[i]);
+#endif
+ }
+ z = (p->y[i] - p->max_y);
+ t += z * z;
+ if (z > QPS_TOL || (p->max_enable < QPS_RELAX_ITER &&
+ p->priv_myh[i] * z < -QPS_MAX_TOL)) {
+ p->max_done = 0;
+#if (QPS_DEBUG > 4)
+ fprintf(p->priv_fp, "### nyh %d %f %f\n", i, z, p->priv_myh[i]);
+#endif
+ }
+ }
+#if (QPS_DEBUG > 4)
+ fprintf(p->priv_fp, "### max_done %d %f\n", p->max_done, t);
+#endif
+ if (!p->max_done) {
+ t = p->priv_eps * (p->priv_fopt - p->priv_f) / t;
+ tp = 0.0;
+ for (i = p->num_cells; i--;) {
+ z = -(p->x[i]);
+ pm1 = p->priv_mxl[i];
+ p->priv_mxl[i] += t * z;
+ if (p->priv_mxl[i] < 0.0) {
+ p->priv_mxl[i] = 0.0;
+ }
+ pm2 = p->priv_mxl[i];
+ tp += fabs(pm1 - pm2);
+
+ z = (p->x[i] - p->max_x);
+ pm1 = p->priv_mxh[i];
+ p->priv_mxh[i] += t * z;
+ if (p->priv_mxh[i] < 0.0) {
+ p->priv_mxh[i] = 0.0;
+ }
+ pm2 = p->priv_mxh[i];
+ tp += fabs(pm1 - pm2);
+
+ z = -(p->y[i]);
+ pm1 = p->priv_myl[i];
+ p->priv_myl[i] += t * z;
+ if (p->priv_myl[i] < 0.0) {
+ p->priv_myl[i] = 0.0;
+ }
+ pm2 = p->priv_myl[i];
+ tp += fabs(pm1 - pm2);
+
+ z = (p->y[i] - p->max_y);
+ pm1 = p->priv_myh[i];
+ p->priv_myh[i] += t * z;
+ if (p->priv_myh[i] < 0.0) {
+ p->priv_myh[i] = 0.0;
+ }
+ pm2 = p->priv_myh[i];
+ tp += fabs(pm1 - pm2);
+ }
+ }
+#if (QPS_DEBUG > 4)
+ for (i = p->num_cells; i--;) {
+ fprintf(p->priv_fp, "### max_penalty %d %f %f %f %f\n", i,
+ p->priv_mxl[i], p->priv_mxh[i], p->priv_myl[i], p->priv_myh[i]);
+ }
+#endif
+ p->max_enable++;
+ }
+
+ if (p->loop_k >= QPS_MAX_ITER || p->priv_eps < QPS_MINSTEP) {
+ p->loop_fail |= 1;
+ }
+
+ if (p->loop_fail) {
+ p->loop_done = 1;
+ }
+
+ p->priv_cw = tw;
+}
+
+/**********************************************************************/
+
+void
+qps_solve(qps_problem_t * p)
+{
+ int i, j;
+ int pr, pw;
+ qps_float_t bk;
+ int tk;
+
+#if defined(QPS_PRECON)
+ int c;
+ qps_float_t t;
+#endif
+
+#if defined(QPS_HOIST)
+ int k;
+ int st;
+ int m1, m2;
+#endif
+
+ if (p->max_enable) {
+ p->priv_mxl = (qps_float_t *)
+ malloc(4 * p->num_cells * sizeof(qps_float_t));
+ assert(p->priv_mxl);
+ p->priv_mxh = p->priv_mxl + p->num_cells;
+ p->priv_myl = p->priv_mxl + 2 * p->num_cells;
+ p->priv_myh = p->priv_mxl + 3 * p->num_cells;
+ for (i = 4 * p->num_cells; i--;) {
+ p->priv_mxl[i] = 0.0;
+ }
+ }
+
+ /* flag fixed cells with -1 */
+ for (i = p->num_cells; i--;) {
+ p->priv_ii[i] = (p->fixed[i]) ? (-1) : (0);
+ }
+
+ /* read gl and set up dependent variables */
+ if (p->cog_num) {
+ p->priv_gt = (int *)malloc(p->cog_num * sizeof(int));
+ assert(p->priv_gt);
+ p->priv_gm = (qps_float_t*)malloc(p->cog_num * sizeof(qps_float_t));
+ assert(p->priv_gm);
+ pr = 0;
+ for (i = 0; i < p->cog_num; i++) {
+ tk = -1;
+ bk = -1.0;
+ pw = pr;
+ while ((j = p->cog_list[pr++]) >= 0) {
+ if (!p->fixed[j]) {
+ /* use largest entry for numerical stability; see Gordian paper */
+ if (p->area[j] > bk) {
+ tk = j;
+ bk = p->area[j];
+ }
+ }
+ }
+ assert(bk > 0.0);
+ /* dependent variables have index=(-2-COG_constraint) */
+ p->priv_ii[tk] = -2 - i;
+ p->priv_gt[i] = pw;
+ p->priv_gm[i] = bk;
+ }
+ p->priv_gw = (qps_float_t*)malloc(pr * sizeof(qps_float_t));
+ assert(p->priv_gw);
+ pr = 0;
+ for (i = 0; i < p->cog_num; i++) {
+ while ((j = p->cog_list[pr]) >= 0) {
+ p->priv_gw[pr] = p->area[j] / p->priv_gm[i];
+ pr++;
+ }
+ p->priv_gw[pr] = -1.0;
+ pr++;
+ }
+ }
+
+ /* set up indexes from independent floating cells to variables */
+ p->priv_n = 0;
+ for (i = p->num_cells; i--;) {
+ if (!p->priv_ii[i]) {
+ p->priv_ii[i] = 2 * (p->priv_n++);
+ }
+ }
+ p->priv_n *= 2;
+
+#if (QPS_DEBUG > 5)
+ for (i = 0; i < p->num_cells; i++) {
+ fprintf(p->priv_fp, "### ii %d %d\n", i, p->priv_ii[i]);
+ }
+#endif
+
+#if defined(QPS_PRECON)
+ p->priv_pcg = (qps_float_t *) malloc(p->num_cells * sizeof(qps_float_t));
+ assert(p->priv_pcg);
+ p->priv_pcgt = (qps_float_t *) malloc(p->priv_n * sizeof(qps_float_t));
+ assert(p->priv_pcgt);
+ for (i = p->num_cells; i--;) {
+ p->priv_pcg[i] = 0.0;
+ }
+ pr = 0;
+ for (i = 0; i < p->num_cells; i++) {
+ while ((c = p->priv_cc[pr]) >= 0) {
+ t = p->priv_ct[pr];
+ p->priv_pcg[i] += t;
+ p->priv_pcg[c] += t;
+ pr++;
+ }
+ pr++;
+ }
+ pr = 0;
+ for (i = 0; i < p->loop_num; i++) {
+ t = 2.0 * p->loop_penalty[i];
+ while ((c = p->loop_list[pr++]) >= 0) {
+ p->priv_pcg[c] += t;
+ }
+ pr++;
+ }
+#if (QPS_DEBUG > 6)
+ for (i = p->num_cells; i--;) {
+ fprintf(p->priv_fp, "### precon %d %.2e\n", i, p->priv_pcg[i]);
+ }
+#endif
+ for (i = p->priv_n; i--;) {
+ p->priv_pcgt[i] = 0.0;
+ }
+ for (i = 0; i < p->num_cells; i++) {
+ c = p->priv_ii[i];
+ if (c >= 0) {
+ t = p->priv_pcg[i];
+ p->priv_pcgt[c] += t;
+ p->priv_pcgt[c + 1] += t;
+ }
+#if 0
+ else if (c < -1) {
+ pr = p->priv_gt[-(c+2)];
+ while ((j = p->cog_list[pr++]) >= 0) {
+ ji = p->priv_ii[j];
+ if (ji >= 0) {
+ w = p->area[j] / p->area[i];
+ t = w * w * p->priv_pcg[i];
+ p->priv_pcgt[ji] += t;
+ p->priv_pcgt[ji + 1] += t;
+ }
+ }
+ }
+#endif
+ }
+ for (i = 0; i < p->priv_n; i++) {
+ t = p->priv_pcgt[i];
+ if (fabs(t) < QPS_PRECON_EPS || fabs(t) > 1.0/QPS_PRECON_EPS) {
+ p->priv_pcgt[i] = 1.0;
+ }
+ else {
+ p->priv_pcgt[i] = 1.0 / p->priv_pcgt[i];
+ }
+ }
+#endif
+
+ /* allocate variable storage */
+ p->priv_cp = (qps_float_t *) malloc(4 * p->priv_n * sizeof(qps_float_t));
+ assert(p->priv_cp);
+
+ /* temp arrays for cg */
+ p->priv_g = p->priv_cp + p->priv_n;
+ p->priv_h = p->priv_cp + 2 * p->priv_n;
+ p->priv_xi = p->priv_cp + 3 * p->priv_n;
+
+ /* set values */
+ for (i = p->num_cells; i--;) {
+ if (p->priv_ii[i] >= 0) {
+ p->priv_cp[p->priv_ii[i]] = p->x[i];
+ p->priv_cp[p->priv_ii[i] + 1] = p->y[i];
+ }
+ }
+
+ if (p->loop_num) {
+ p->priv_lt = (qps_float_t *) malloc(p->loop_num * sizeof(qps_float_t));
+ assert(p->priv_lt);
+#if defined(QPS_HOIST)
+ pr = 0;
+ for (i=p->loop_num; i--;) {
+ while (p->loop_list[pr++] >= 0) {
+ }
+ pr++;
+ }
+ p->priv_lm = pr;
+ p->priv_la = (int *) malloc(pr * sizeof(int));
+ assert(p->priv_la);
+ pr = 0;
+ for (i = 0; i < p->loop_num; i++) {
+ j = st = p->loop_list[pr++];
+ while ((k = p->loop_list[pr]) >= 0) {
+ if (j > k) {
+ m1 = k;
+ m2 = j;
+ }
+ else {
+ assert(k > j);
+ m1 = j;
+ m2 = k;
+ }
+ pw = p->priv_cr[m1];
+ while (p->priv_cc[pw] != m2) {
+/* assert(p->priv_cc[pw] >= 0); */
+ if (p->priv_cc[pw] < 0) {
+ pw = -2;
+ break;
+ }
+ pw++;
+ }
+ p->priv_la[pr-1] = pw;
+ j = k;
+ pr++;
+ }
+ if (j > st) {
+ m1 = st;
+ m2 = j;
+ }
+ else {
+ assert(st > j);
+ m1 = j;
+ m2 = st;
+ }
+ pw = p->priv_cr[m1];
+ while (p->priv_cc[pw] != m2) {
+/* assert(p->priv_cc[pw] >= 0); */
+ if (p->priv_cc[pw] < 0) {
+ pw = -2;
+ break;
+ }
+ pw++;
+ }
+ p->priv_la[pr-1] = pw;
+ p->priv_la[pr] = -1;
+ pr++;
+ }
+#endif /* QPS_HOIST */
+ }
+
+ do {
+ qps_solve_inner(p);
+ } while (!p->loop_done || !p->max_done);
+
+ /* retrieve values */
+ /* qps_settp() should have already been called at this point */
+ for (i = p->num_cells; i--;) {
+ p->x[i] = p->priv_tp[i * 2];
+ p->y[i] = p->priv_tp[i * 2 + 1];
+ }
+#if (QPS_DEBUG > 5)
+ for (i = p->num_cells; i--;) {
+ fprintf(p->priv_fp, "### cloc %d %f %f\n", i, p->x[i], p->y[i]);
+ }
+#endif
+
+ free(p->priv_cp);
+ if (p->max_enable) {
+ free(p->priv_mxl);
+ }
+ if (p->cog_num) {
+ free(p->priv_gt);
+ free(p->priv_gm);
+ free(p->priv_gw);
+ }
+ if(p->loop_num) {
+ free(p->priv_lt);
+#if defined(QPS_HOIST)
+ free(p->priv_la);
+#endif
+ }
+
+#if defined(QPS_PRECON)
+ free(p->priv_pcg);
+ free(p->priv_pcgt);
+#endif
+}
+
+/**********************************************************************/
+
+void
+qps_clean(qps_problem_t * p)
+{
+ free(p->priv_tp);
+ free(p->priv_ii);
+ free(p->priv_cc);
+ free(p->priv_cr);
+ free(p->priv_cw);
+ free(p->priv_ct);
+
+#if defined(QPS_DEBUG)
+ fclose(p->priv_fp);
+#endif /* QPS_DEBUG */
+}
+
+/**********************************************************************/
diff --git a/src/phys/place/place_qpsolver.h b/src/phys/place/place_qpsolver.h
new file mode 100644
index 00000000..08771d6b
--- /dev/null
+++ b/src/phys/place/place_qpsolver.h
@@ -0,0 +1,140 @@
+/*===================================================================*/
+//
+// place_qpsolver.h
+//
+// Philip Chong
+// pchong@cadence.com
+//
+/*===================================================================*/
+
+#if !defined(_QPS_H)
+#define _QPS_H
+
+#include <stdio.h>
+
+#if defined(__cplusplus)
+extern "C" {
+#endif /* __cplusplus */
+
+ typedef float qps_float_t;
+
+ typedef struct qps_problem {
+
+ /* Basic stuff */
+ int num_cells; /* Total number of cells (both fixed and
+ floating) to be placed. */
+ int *connect; /* Connectivity array. Must contain at least
+ num_cells elements with value -1. The
+ entries which precede the first element
+ with value -1 are the indices of the cells
+ which connect to cell 0; the entries
+ which lie between the first and second
+ elements with value -1 are the indices of
+ the cells which connect to cell 1; etc.
+ Example: cells 0 and 1 are connected
+ together, and 1 and 2 are connected as
+ well. *connect = { 1, -1, 0, 2, -1, 1, -1
+ }. */
+ qps_float_t *edge_weight; /* Same structure as connectivity array, but
+ giving the weights assigned to each edge
+ instead. */
+ qps_float_t *x; /* num_cells element array which contains the
+ x-coordinates of the cells. This is used
+ for the initial values in the iterative
+ solution of floating cells, and for the
+ fixed location of fixed cells. */
+ qps_float_t *y; /* num_cells element array of
+ y-coordinates. */
+ int *fixed; /* num_cells element array with value 1 if
+ corresponding cell is fixed, 0 if
+ floating. */
+ qps_float_t f; /* return value for sum-of-square
+ wirelengths. */
+
+ /* COG stuff */
+ int cog_num; /* Number of COG constraints. */
+ int *cog_list; /* Array indicating for each COG constraint
+ which cells belong to that constraint.
+ Format is similar to c array: there must
+ be at least cog_num elements with value
+ -1. The entries of cog_list preceding the
+ first -1 element are the indices of the
+ cells which belong to the first COG
+ constraint; etc. Example: cells 0 and 1
+ belong to one COG constraint, cells 4 and
+ 5 belong to another. *cog_list= { 0, 1,
+ -1, 4, 5, -1 }. */
+ qps_float_t *cog_x; /* cog_num element array whose values are the
+ x-coordinates for the corresponding COG
+ constraints. */
+ qps_float_t *cog_y; /* cog_num element array whose values are the
+ y-coordinates for the corresponding COG
+ constraints. */
+ qps_float_t *area; /* num_cells element array whose values are
+ the areas for the corresponding cells;
+ only useful with COG constraints. */
+
+ /* Loop constraint stuff */
+ int loop_num; /* Number of loop constraints. */
+ int *loop_list; /* Array with list of cells for each loop
+ constraint. Format is similar to cog_list.
+ */
+ qps_float_t *loop_max; /* loop_num element array indicating maximum
+ distance for each loop. */
+ qps_float_t *loop_penalty; /* loop_num element array indicating penalty
+ for each loop. */
+ int loop_k; /* Current iteration for loop optimization. */
+ int loop_done; /* Done flag for loop optimization. */
+ int loop_fail;
+
+ /* max_x/max_y stuff */
+ qps_float_t max_x; /* max x location; only used in
+ constrained optimization. */
+ qps_float_t max_y; /* max y location; only used in
+ constrained optimization. */
+ int max_enable; /* Set to 1 after qps_init() to enable
+ max_x/max_y. */
+ int max_done; /* Done flag for max optimization. */
+
+ /* Private stuff */
+ int *priv_ii;
+ int *priv_cc, *priv_cr;
+ qps_float_t *priv_cw, *priv_ct;
+ int priv_cm;
+ int *priv_gt;
+ int *priv_la;
+ int priv_lm;
+ qps_float_t *priv_gm, *priv_gw;
+ qps_float_t *priv_g, *priv_h, *priv_xi;
+ qps_float_t *priv_tp, *priv_tp2;
+ int priv_n;
+ qps_float_t *priv_cp;
+ qps_float_t priv_f;
+ qps_float_t *priv_lt;
+ qps_float_t *priv_pcg, *priv_pcgt;
+ qps_float_t priv_fmax;
+ qps_float_t priv_fprev;
+ qps_float_t priv_fopt;
+ qps_float_t priv_eps;
+ int priv_pn;
+ qps_float_t *priv_mxl, *priv_mxh, *priv_myl, *priv_myh;
+ int priv_ik;
+ FILE *priv_fp;
+
+ } qps_problem_t;
+
+ /* call qps_init() as soon as the qps_problem_t has been set up */
+ /* this initializes some private data structures */
+ extern void qps_init(qps_problem_t *);
+
+ /* call qps_solve() to solve the given qp problem */
+ extern void qps_solve(qps_problem_t *);
+
+ /* call qps_clean() when finished with the qps_problem_t */
+ /* this discards the private data structures assigned by qps_init() */
+ extern void qps_clean(qps_problem_t *);
+
+#if defined(__cplusplus)
+}
+#endif /* __cplusplus */
+#endif /* _QPS_H */
diff --git a/src/phys/place/place_test.c b/src/phys/place/place_test.c
new file mode 100644
index 00000000..ea706a09
--- /dev/null
+++ b/src/phys/place/place_test.c
@@ -0,0 +1,360 @@
+/*===================================================================*/
+//
+// place_test.c
+//
+// Aaron P. Hurst, 2003-2007
+// ahurst@eecs.berkeley.edu
+//
+/*===================================================================*/
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <assert.h>
+#include "place_base.h"
+
+
+// --------------------------------------------------------------------
+// Hash type/functions
+//
+// --------------------------------------------------------------------
+
+struct hash_element {
+ ConcreteCell *obj;
+ struct hash_element *next;
+} hash_element;
+
+int hash_string(int hash_max, const char *str) {
+ unsigned int hash = 0;
+ int p;
+ for(p = 0; p<strlen(str); p++)
+ hash += str[p]*p;
+ return hash % hash_max;
+}
+
+void hash_add(struct hash_element **hash, int hash_max,
+ ConcreteCell *cell) {
+ int key = hash_string(hash_max, cell->m_label);
+ // printf("adding %s key = %d\n", cell->m_label, key);
+ struct hash_element *element = malloc(sizeof(struct hash_element));
+ assert(element);
+ element->obj = cell;
+ element->next = hash[key];
+ hash[key] = element;
+}
+
+ConcreteCell *hash_find(struct hash_element **hash, int hash_max, const char *str) {
+ int key = hash_string(hash_max, str);
+ // printf("looking for %s key = %d\n", str, key);
+ struct hash_element *next = hash[key];
+ while(next) {
+ if (!strcmp(str, next->obj->m_label))
+ return next->obj;
+ next = next->next;
+ }
+ return 0;
+}
+
+// --------------------------------------------------------------------
+// Global variables
+//
+// --------------------------------------------------------------------
+
+struct hash_element **hash_cellname;
+
+int numCells = 0, numNets = 0;
+
+AbstractCell *abstractCells;
+ConcreteCell *concreteCells;
+ConcreteNet *concreteNets;
+
+// --------------------------------------------------------------------
+// Function implementations
+//
+// --------------------------------------------------------------------
+
+void readBookshelfNets(char *filename) {
+ char *tok;
+ char buf[1024];
+ const char *DELIMITERS = " \n\t:";
+ int id = 0;
+ int t;
+ ConcreteCell *cell;
+
+ FILE *netsFile = fopen(filename, "r");
+ if (!netsFile) {
+ printf("ERROR: Could not open .nets file\n");
+ exit(1);
+ }
+
+ // line 1 : version
+ while (fgets(buf, 1024, netsFile) && (buf[0] == '\n' || buf[0] == '#'));
+
+ // line 2 : number of nets
+ while (fgets(buf, 1024, netsFile) && (buf[0] == '\n' || buf[0] == '#'));
+ tok = strtok(buf, DELIMITERS);
+ tok = strtok(NULL, DELIMITERS);
+ numNets = atoi(tok);
+ printf("READ-20 : number of nets = %d\n", numNets);
+ concreteNets = malloc(sizeof(ConcreteNet)*numNets);
+
+ // line 3 : number of pins
+ while (fgets(buf, 1024, netsFile) && (buf[0] == '\n' || buf[0] == '#'));
+
+ // line XXX : net definitions
+ while(fgets(buf, 1024, netsFile)) {
+ if (buf[0] == '\n' || buf[0] == '#') continue;
+
+ concreteNets[id].m_id = id;
+ concreteNets[id].m_weight = 1.0;
+
+ tok = strtok(buf, DELIMITERS);
+ if (!!strcmp(tok, "NetDegree")) {
+ printf("%s\n",buf);
+ printf("ERROR: Incorrect format in .nets file\n");
+ exit(1);
+ }
+
+ tok = strtok(NULL, DELIMITERS);
+ concreteNets[id].m_numTerms = atoi(tok);
+ if (concreteNets[id].m_numTerms < 0 ||
+ concreteNets[id].m_numTerms > 100000) {
+ printf("ERROR: Bad net degree\n");
+ exit(1);
+ }
+ concreteNets[id].m_terms = malloc(sizeof(ConcreteCell*)*
+ concreteNets[id].m_numTerms);
+
+ // read terms
+ t = 0;
+ while(t < concreteNets[id].m_numTerms &&
+ fgets(buf, 1024, netsFile)) {
+ if (buf[0] == '\n' || buf[0] == '#') continue;
+
+ // cell name
+ tok = strtok(buf, DELIMITERS);
+ cell = hash_find(hash_cellname, numCells, tok);
+ if (!cell) {
+ printf("ERROR: Could not find cell %s in .nodes file\n", tok);
+ exit(1);
+ }
+ concreteNets[id].m_terms[t] = cell;
+ t++;
+ }
+
+ // add!
+ addConcreteNet(&(concreteNets[id]));
+
+ id++;
+ }
+
+ fclose(netsFile);
+}
+
+void readBookshelfNodes(char *filename) {
+ char *tok;
+ char buf[1024];
+ const char *DELIMITERS = " \n\t:";
+ int id = 0;
+
+ FILE *nodesFile = fopen(filename, "r");
+ if (!nodesFile) {
+ printf("ERROR: Could not open .nodes file\n");
+ exit(1);
+ }
+
+ // line 1 : version
+ while (fgets(buf, 1024, nodesFile) && (buf[0] == '\n' || buf[0] == '#'));
+
+ // line 2 : num nodes
+ while (fgets(buf, 1024, nodesFile) && (buf[0] == '\n' || buf[0] == '#'));
+ tok = strtok(buf, DELIMITERS);
+ tok = strtok(NULL, DELIMITERS);
+ numCells = atoi(tok);
+ printf("READ-10 : number of cells = %d\n", numCells);
+ concreteCells = malloc(sizeof(ConcreteCell)*numCells);
+ abstractCells = malloc(sizeof(AbstractCell)*numCells);
+ hash_cellname = calloc(numCells, sizeof(struct hash_element*));
+
+ // line 3 : num terminals
+ while (fgets(buf, 1024, nodesFile) && (buf[0] == '\n' || buf[0] == '#'));
+
+ // line XXX : cell definitions
+ while(fgets(buf, 1024, nodesFile)) {
+ if (buf[0] == '\n' || buf[0] == '#') continue;
+
+ tok = strtok(buf, DELIMITERS);
+ concreteCells[id].m_id = id;;
+
+ // label
+ concreteCells[id].m_parent = &(abstractCells[id]);
+ concreteCells[id].m_label = malloc(sizeof(char)*strlen(tok)+1);
+ strcpy(concreteCells[id].m_label, tok);
+ abstractCells[id].m_label = concreteCells[id].m_label;
+ hash_add(hash_cellname, numCells,
+ &(concreteCells[id]));
+
+ // dimensions
+ tok = strtok(NULL, DELIMITERS);
+ abstractCells[id].m_width = atof(tok);
+ tok = strtok(NULL, DELIMITERS);
+ abstractCells[id].m_height = atof(tok);
+ tok = strtok(NULL, DELIMITERS);
+ // terminal
+ abstractCells[id].m_pad = tok && !strcmp(tok, "terminal");
+
+ // add!
+ addConcreteCell(&(concreteCells[id]));
+
+ // DEBUG
+ /*
+ printf("\"%s\" : %f x %f\n", concreteCells[id].m_label,
+ abstractCells[id].m_width,
+ abstractCells[id].m_height);
+ */
+ id++;
+ }
+
+ fclose(nodesFile);
+}
+
+void readBookshelfPlacement(char *filename) {
+ char *tok;
+ char buf[1024];
+ const char *DELIMITERS = " \n\t:";
+ ConcreteCell *cell;
+
+ FILE *plFile = fopen(filename, "r");
+ FILE *netsFile = fopen(filename, "r");
+ if (!plFile) {
+ printf("ERROR: Could not open .pl file\n");
+ exit(1);
+ }
+ if (!netsFile) {
+ printf("ERROR: Could not open .nets file\n");
+ exit(1);
+ }
+
+ // line 1 : version
+ while (fgets(buf, 1024, plFile) && (buf[0] == '\n' || buf[0] == '#'));
+
+ // line XXX : placement definitions
+ while(fgets(buf, 1024, plFile)) {
+ if (buf[0] == '\n' || buf[0] == '#') continue;
+
+ tok = strtok(buf, DELIMITERS);
+
+ // cell name
+ cell = hash_find(hash_cellname, numCells, tok);
+ if (!cell) {
+ printf("ERROR: Could not find cell %s in .nodes file\n",tok);
+ exit(1);
+ }
+
+ // position
+ tok = strtok(NULL, DELIMITERS);
+ cell->m_x = atof(tok);
+ tok = strtok(NULL, DELIMITERS);
+ cell->m_y = atof(tok);
+
+ // hfixed
+ cell->m_fixed = strtok(NULL, DELIMITERS) &&
+ (tok = strtok(NULL, DELIMITERS)) &&
+ !strcmp(tok, "\\FIXED");
+ }
+
+ fclose(plFile);
+}
+
+void writeBookshelfPlacement(char *filename) {
+ int c = 0;
+
+ FILE *plFile = fopen(filename, "w");
+ if (!plFile) {
+ printf("ERROR: Could not open .pl file\n");
+ exit(1);
+ }
+
+ fprintf(plFile, "UCLA pl 1.0\n");
+ for(c=0; c<numCells; c++) {
+ fprintf(plFile, "%s %f %f : N %s\n",
+ concreteCells[c].m_label,
+ concreteCells[c].m_x,
+ concreteCells[c].m_y,
+ (concreteCells[c].m_fixed ? "\\FIXED" : ""));
+ }
+
+ fclose(plFile);
+}
+
+// deletes all connections to a cell
+void delNetConnections(ConcreteCell *cell) {
+ int n, t, t2, count = 0;
+ ConcreteCell **old = malloc(sizeof(ConcreteCell*)*g_place_numCells);
+
+ for(n=0; n<g_place_numNets; n++) if (g_place_concreteNets[n]) {
+ ConcreteNet *net = g_place_concreteNets[n];
+ count = 0;
+ for(t=0; t<net->m_numTerms; t++)
+ if (net->m_terms[t] == cell) count++;
+ if (count) {
+ memcpy(old, net->m_terms, sizeof(ConcreteCell*)*net->m_numTerms);
+ net->m_terms = realloc(net->m_terms,
+ sizeof(ConcreteCell*)*(net->m_numTerms-count));
+ t2 = 0;
+ for(t=0; t<net->m_numTerms; t++)
+ if (old[t] != cell) net->m_terms[t2++] = old[t];
+ net->m_numTerms -= count;
+ }
+ }
+ free(old);
+}
+
+int main(int argc, char **argv) {
+
+ if (argc != 4) {
+ printf("Usage: %s [nodes] [nets] [pl]\n", argv[0]);
+ exit(1);
+ }
+
+ readBookshelfNodes(argv[1]);
+ readBookshelfNets(argv[2]);
+ readBookshelfPlacement(argv[3]);
+
+ globalPreplace(0.8);
+ globalPlace();
+
+ // DEBUG net/cell removal/addition
+ /*
+ int i;
+ for(i=1000; i<2000; i++) {
+ delConcreteNet(g_place_concreteNets[i]);
+ delNetConnections(g_place_concreteCells[i]);
+ delConcreteCell(g_place_concreteCells[i]);
+ }
+
+ ConcreteCell newCell[2];
+ newCell[0].m_id = g_place_numCells+1;
+ newCell[0].m_x = 1000;
+ newCell[0].m_y = 1000;
+ newCell[0].m_fixed = false;
+ newCell[0].m_parent = &(abstractCells[1000]);
+ newCell[0].m_label = " ";
+ addConcreteCell(&newCell[0]);
+ newCell[1].m_id = g_place_numCells+3;
+ newCell[1].m_x = 1000;
+ newCell[1].m_y = 1000;
+ newCell[1].m_fixed = false;
+ newCell[1].m_parent = &(abstractCells[1000]);
+ newCell[1].m_label = " ";
+ addConcreteCell(&newCell[1]);
+ */
+
+ globalIncremental();
+
+ writeBookshelfPlacement(argv[3]);
+
+ free(hash_cellname);
+
+ return 0;
+}
diff --git a/src/sat/asat/added.c b/src/sat/asat/added.c
deleted file mode 100644
index d7f5b104..00000000
--- a/src/sat/asat/added.c
+++ /dev/null
@@ -1,126 +0,0 @@
-/**CFile****************************************************************
-
- FileName [added.c]
-
- SystemName [ABC: Logic synthesis and verification system.]
-
- PackageName [C-language MiniSat solver.]
-
- Synopsis [Additional SAT solver procedures.]
-
- Author [Alan Mishchenko]
-
- Affiliation [UC Berkeley]
-
- Date [Ver. 1.0. Started - June 20, 2005.]
-
- Revision [$Id: added.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
-
-***********************************************************************/
-
-#include <stdio.h>
-#include <assert.h>
-#include "solver.h"
-#include "extra.h"
-
-////////////////////////////////////////////////////////////////////////
-/// DECLARATIONS ///
-////////////////////////////////////////////////////////////////////////
-
-struct clause_t
-{
- int size_learnt;
- lit lits[0];
-};
-
-static inline int clause_size (clause* c) { return c->size_learnt >> 1; }
-static inline lit* clause_begin (clause* c) { return c->lits; }
-
-static inline int lit_var(lit l) { return l >> 1; }
-static inline int lit_sign(lit l) { return (l & 1); }
-
-static void Asat_ClauseWriteDimacs( FILE * pFile, clause * pC, bool fIncrement );
-
-
-////////////////////////////////////////////////////////////////////////
-/// FUNCTION DEFITIONS ///
-////////////////////////////////////////////////////////////////////////
-
-/**Function*************************************************************
-
- Synopsis [Write the clauses in the solver into a file in DIMACS format.]
-
- Description []
-
- SideEffects []
-
- SeeAlso []
-
-***********************************************************************/
-void Asat_SolverWriteDimacs( solver * p, char * pFileName )
-{
- FILE * pFile;
- void ** pClauses;
- int nClauses, i;
-
- // count the number of clauses
- nClauses = p->clauses.size + p->learnts.size;
- for ( i = 0; i < p->size; i++ )
- if ( p->levels[i] == 0 && p->assigns[i] != l_Undef )
- nClauses++;
-
- // start the file
- pFile = fopen( pFileName, "wb" );
- fprintf( pFile, "c CNF generated by ABC on %s\n", Extra_TimeStamp() );
- fprintf( pFile, "p cnf %d %d\n", p->size, nClauses );
-
- // write the original clauses
- nClauses = p->clauses.size;
- pClauses = p->clauses.ptr;
- for ( i = 0; i < nClauses; i++ )
- Asat_ClauseWriteDimacs( pFile, pClauses[i], 1 );
-
- // write the learned clauses
- nClauses = p->learnts.size;
- pClauses = p->learnts.ptr;
- for ( i = 0; i < nClauses; i++ )
- Asat_ClauseWriteDimacs( pFile, pClauses[i], 1 );
-
- // write zero-level assertions
- for ( i = 0; i < p->size; i++ )
- if ( p->levels[i] == 0 && p->assigns[i] != l_Undef )
- fprintf( pFile, "%s%d 0\n", (p->assigns[i] == l_False)? "-": "", i + 1 );
-
- fprintf( pFile, "\n" );
- fclose( pFile );
-}
-
-/**Function*************************************************************
-
- Synopsis [Writes the given clause in a file in DIMACS format.]
-
- Description []
-
- SideEffects []
-
- SeeAlso []
-
-***********************************************************************/
-void Asat_ClauseWriteDimacs( FILE * pFile, clause * pC, bool fIncrement )
-{
- lit * pLits = clause_begin(pC);
- int nLits = clause_size(pC);
- int i;
-
- for ( i = 0; i < nLits; i++ )
- fprintf( pFile, "%s%d ", (lit_sign(pLits[i])? "-": ""), lit_var(pLits[i]) + (int)(fIncrement>0) );
- if ( fIncrement )
- fprintf( pFile, "0" );
- fprintf( pFile, "\n" );
-}
-
-////////////////////////////////////////////////////////////////////////
-/// END OF FILE ///
-////////////////////////////////////////////////////////////////////////
-
-
diff --git a/src/sat/asat/main.c b/src/sat/asat/main.c
deleted file mode 100644
index cbad5ba1..00000000
--- a/src/sat/asat/main.c
+++ /dev/null
@@ -1,195 +0,0 @@
-/**************************************************************************************************
-MiniSat -- Copyright (c) 2005, Niklas Sorensson
-http://www.cs.chalmers.se/Cs/Research/FormalMethods/MiniSat/
-
-Permission is hereby granted, free of charge, to any person obtaining a copy of this software and
-associated documentation files (the "Software"), to deal in the Software without restriction,
-including without limitation the rights to use, copy, modify, merge, publish, distribute,
-sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is
-furnished to do so, subject to the following conditions:
-
-The above copyright notice and this permission notice shall be included in all copies or
-substantial portions of the Software.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT
-NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
-NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
-DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT
-OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
-**************************************************************************************************/
-// Modified to compile with MS Visual Studio 6.0 by Alan Mishchenko
-
-#include "solver.h"
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <time.h>
-//#include <unistd.h>
-//#include <signal.h>
-//#include <zlib.h>
-//#include <sys/time.h>
-//#include <sys/resource.h>
-
-//=================================================================================================
-// Helpers:
-
-
-// Reads an input stream to end-of-file and returns the result as a 'char*' terminated by '\0'
-// (dynamic allocation in case 'in' is standard input).
-//
-char* readFile(FILE * in)
-{
- char* data = malloc(65536);
- int cap = 65536;
- int size = 0;
-
- while (!feof(in)){
- if (size == cap){
- cap *= 2;
- data = realloc(data, cap); }
- size += fread(&data[size], 1, 65536, in);
- }
- data = realloc(data, size+1);
- data[size] = '\0';
-
- return data;
-}
-
-//static inline double cpuTime(void) {
-// struct rusage ru;
-// getrusage(RUSAGE_SELF, &ru);
-// return (double)ru.ru_utime.tv_sec + (double)ru.ru_utime.tv_usec / 1000000; }
-
-
-//=================================================================================================
-// DIMACS Parser:
-
-
-static inline void skipWhitespace(char** in) {
- while ((**in >= 9 && **in <= 13) || **in == 32)
- (*in)++; }
-
-static inline void skipLine(char** in) {
- for (;;){
- if (**in == 0) return;
- if (**in == '\n') { (*in)++; return; }
- (*in)++; } }
-
-static inline int parseInt(char** in) {
- int val = 0;
- int _neg = 0;
- skipWhitespace(in);
- if (**in == '-') _neg = 1, (*in)++;
- else if (**in == '+') (*in)++;
- if (**in < '0' || **in > '9') fprintf(stderr, "PARSE ERROR! Unexpected char: %c\n", **in), exit(1);
- while (**in >= '0' && **in <= '9')
- val = val*10 + (**in - '0'),
- (*in)++;
- return _neg ? -val : val; }
-
-static void readClause(char** in, solver* s, vec* lits) {
- int parsed_lit, var;
- vec_resize(lits,0);
- for (;;){
- parsed_lit = parseInt(in);
- if (parsed_lit == 0) break;
- var = abs(parsed_lit)-1;
- vec_push(lits, (void*)(parsed_lit > 0 ? toLit(var) : neg(toLit(var))));
- }
-}
-
-static lbool parse_DIMACS_main(char* in, solver* s) {
- vec lits;
- vec_new(&lits);
-
- for (;;){
- skipWhitespace(&in);
- if (*in == 0)
- break;
- else if (*in == 'c' || *in == 'p')
- skipLine(&in);
- else{
- lit* begin;
- readClause(&in, s, &lits);
- begin = (lit*)vec_begin(&lits);
- if (solver_addclause(s, begin, begin+vec_size(&lits)) == l_False){
- vec_delete(&lits);
- return l_False;
- }
- }
- }
- vec_delete(&lits);
- return solver_simplify(s);
-}
-
-
-// Inserts problem into solver. Returns FALSE upon immediate conflict.
-//
-static lbool parse_DIMACS(FILE * in, solver* s) {
- char* text = readFile(in);
- lbool ret = parse_DIMACS_main(text, s);
- free(text);
- return ret; }
-
-
-//=================================================================================================
-
-
-void printStats(stats* stats, int cpu_time)
-{
- double Time = (float)(cpu_time)/(float)(CLOCKS_PER_SEC);
- printf("restarts : %12d\n", stats->starts);
- printf("conflicts : %12.0f (%9.0f / sec )\n", (double)stats->conflicts , (double)stats->conflicts /Time);
- printf("decisions : %12.0f (%9.0f / sec )\n", (double)stats->decisions , (double)stats->decisions /Time);
- printf("propagations : %12.0f (%9.0f / sec )\n", (double)stats->propagations, (double)stats->propagations/Time);
- printf("inspects : %12.0f (%9.0f / sec )\n", (double)stats->inspects , (double)stats->inspects /Time);
- printf("conflict literals : %12.0f (%9.2f %% deleted )\n", (double)stats->tot_literals, (double)(stats->max_literals - stats->tot_literals) * 100.0 / (double)stats->max_literals);
- printf("CPU time : %12.2f sec\n", Time);
-}
-
-//solver* slv;
-//static void SIGINT_handler(int signum) {
-// printf("\n"); printf("*** INTERRUPTED ***\n");
-// printStats(&slv->stats, cpuTime());
-// printf("\n"); printf("*** INTERRUPTED ***\n");
-// exit(0); }
-
-
-//=================================================================================================
-
-
-int main(int argc, char** argv)
-{
- solver* s = solver_new();
- lbool st;
- FILE * in;
- int clk = clock();
-
- if (argc != 2)
- fprintf(stderr, "ERROR! Not enough command line arguments.\n"),
- exit(1);
-
- in = fopen(argv[1], "rb");
- if (in == NULL)
- fprintf(stderr, "ERROR! Could not open file: %s\n", argc == 1 ? "<stdin>" : argv[1]),
- exit(1);
- st = parse_DIMACS(in, s);
- fclose(in);
-
- if (st == l_False){
- solver_delete(s);
- printf("Trivial problem\nUNSATISFIABLE\n");
- exit(20);
- }
-
- s->verbosity = 1;
-// slv = s;
-// signal(SIGINT,SIGINT_handler);
- st = solver_solve(s,0,0);
- printStats(&s->stats, clock() - clk);
- printf("\n");
- printf(st == l_True ? "SATISFIABLE\n" : "UNSATISFIABLE\n");
-
- solver_delete(s);
- return 0;
-}
diff --git a/src/sat/asat/module.make b/src/sat/asat/module.make
deleted file mode 100644
index 882176fa..00000000
--- a/src/sat/asat/module.make
+++ /dev/null
@@ -1,2 +0,0 @@
-SRC += src/sat/asat/added.c \
- src/sat/asat/solver.c
diff --git a/src/sat/asat/solver.c b/src/sat/asat/solver.c
deleted file mode 100644
index c9dadcb4..00000000
--- a/src/sat/asat/solver.c
+++ /dev/null
@@ -1,1167 +0,0 @@
-/**************************************************************************************************
-MiniSat -- Copyright (c) 2005, Niklas Sorensson
-http://www.cs.chalmers.se/Cs/Research/FormalMethods/MiniSat/
-
-Permission is hereby granted, free of charge, to any person obtaining a copy of this software and
-associated documentation files (the "Software"), to deal in the Software without restriction,
-including without limitation the rights to use, copy, modify, merge, publish, distribute,
-sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is
-furnished to do so, subject to the following conditions:
-
-The above copyright notice and this permission notice shall be included in all copies or
-substantial portions of the Software.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT
-NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
-NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
-DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT
-OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
-**************************************************************************************************/
-// Modified to compile with MS Visual Studio 6.0 by Alan Mishchenko
-
-#include <stdio.h>
-#include <assert.h>
-#include <math.h>
-
-#include "solver.h"
-
-//=================================================================================================
-// Simple (var/literal) helpers:
-
-static inline int lit_var(lit l) { return l >> 1; }
-static inline int lit_sign(lit l) { return (l & 1); }
-
-//=================================================================================================
-// Debug:
-
-//#define VERBOSEDEBUG
-
-// For derivation output (verbosity level 2)
-#define L_IND "%-*d"
-#define L_ind solver_dlevel(s)*3+3,solver_dlevel(s)
-#define L_LIT "%sx%d"
-#define L_lit(p) lit_sign(p)?"~":"", (lit_var(p))
-
-// Just like 'assert()' but expression will be evaluated in the release version as well.
-static inline void check(int expr) { assert(expr); }
-
-static void printlits(lit* begin, lit* end)
-{
- int i;
- for (i = 0; i < end - begin; i++)
- printf(L_LIT" ",L_lit(begin[i]));
-}
-
-//=================================================================================================
-// Random numbers:
-
-
-// Returns a random float 0 <= x < 1. Seed must never be 0.
-static inline double drand(double* seed) {
- int q;
- *seed *= 1389796;
- q = (int)(*seed / 2147483647);
- *seed -= (double)q * 2147483647;
- return *seed / 2147483647; }
-
-
-// Returns a random integer 0 <= x < size. Seed must never be 0.
-static inline int irand(double* seed, int size) {
- return (int)(drand(seed) * size); }
-
-
-//=================================================================================================
-// Predeclarations:
-
-void sort(void** array, int size, int(*comp)(const void *, const void *));
-
-//=================================================================================================
-// Clause datatype + minor functions:
-
-struct clause_t
-{
- int size_learnt;
- lit lits[0];
-};
-
-static inline int clause_size (clause* c) { return c->size_learnt >> 1; }
-static inline lit* clause_begin (clause* c) { return c->lits; }
-static inline int clause_learnt (clause* c) { return c->size_learnt & 1; }
-static inline float clause_activity (clause* c) { return *((float*)&c->lits[c->size_learnt>>1]); }
-static inline void clause_setactivity(clause* c, float a) { *((float*)&c->lits[c->size_learnt>>1]) = a; }
-
-//=================================================================================================
-// Encode literals in clause pointers:
-
-clause* clause_from_lit (lit l) { return (clause*)(l + l + 1); }
-bool clause_is_lit (clause* c) { return ((unsigned int)c & 1); }
-lit clause_read_lit (clause* c) { return (lit)((unsigned int)c >> 1); }
-
-//=================================================================================================
-// Simple helpers:
-
-static inline int solver_dlevel(solver* s) { return vec_size(&s->trail_lim); }
-static inline vec* solver_read_wlist (solver* s, lit l){ return &s->wlists[l]; }
-static inline void vec_remove(vec* v, void* e)
-{
- void** ws = vec_begin(v);
- int j = 0;
-
- for (; ws[j] != e ; j++);
- assert(j < vec_size(v));
- for (; j < vec_size(v)-1; j++) ws[j] = ws[j+1];
- vec_resize(v,vec_size(v)-1);
-}
-
-//=================================================================================================
-// Variable order functions:
-
-static inline void order_update(solver* s, int v) // updateorder
-{
- int* orderpos = s->orderpos;
- double* activity = s->activity;
- int* heap = (int*)vec_begin(&s->order);
- int i = orderpos[v];
- int x = heap[i];
- int parent = (i - 1) / 2;
-
- assert(s->orderpos[v] != -1);
-
- while (i != 0 && activity[x] > activity[heap[parent]]){
- heap[i] = heap[parent];
- orderpos[heap[i]] = i;
- i = parent;
- parent = (i - 1) / 2;
- }
- heap[i] = x;
- orderpos[x] = i;
-}
-
-static inline void order_assigned(solver* s, int v)
-{
-}
-
-static inline void order_unassigned(solver* s, int v) // undoorder
-{
- int* orderpos = s->orderpos;
- if (orderpos[v] == -1){
- orderpos[v] = vec_size(&s->order);
- vec_push(&s->order,(void*)v);
- order_update(s,v);
- }
-}
-
-static int order_select(solver* s, float random_var_freq) // selectvar
-{
- int* heap;
- double* activity;
- int* orderpos;
-
- lbool* values = s->assigns;
-
- // Random decision:
- if (drand(&s->random_seed) < random_var_freq){
- int next = irand(&s->random_seed,s->size);
- assert(next >= 0 && next < s->size);
- if (values[next] == l_Undef)
- return next;
- }
-
- // Activity based decision:
-
- heap = (int*)vec_begin(&s->order);
- activity = s->activity;
- orderpos = s->orderpos;
-
-
- while (vec_size(&s->order) > 0){
- int next = heap[0];
- int size = vec_size(&s->order)-1;
- int x = heap[size];
-
- vec_resize(&s->order,size);
-
- orderpos[next] = -1;
-
- if (size > 0){
- double act = activity[x];
-
- int i = 0;
- int child = 1;
-
-
- while (child < size){
- if (child+1 < size && activity[heap[child]] < activity[heap[child+1]])
- child++;
-
- assert(child < size);
-
- if (act >= activity[heap[child]])
- break;
-
- heap[i] = heap[child];
- orderpos[heap[i]] = i;
- i = child;
- child = 2 * child + 1;
- }
- heap[i] = x;
- orderpos[heap[i]] = i;
- }
-
- if (values[next] == l_Undef)
- return next;
- }
-
- return var_Undef;
-}
-
-//=================================================================================================
-// Activity functions:
-
-static inline void act_var_rescale(solver* s) {
- double* activity = s->activity;
- int i;
- for (i = 0; i < s->size; i++)
- activity[i] *= 1e-100;
- s->var_inc *= 1e-100;
-}
-
-static inline void act_var_bump(solver* s, int v) {
- double* activity = s->activity;
- if ((activity[v] += s->var_inc) > 1e100)
- act_var_rescale(s);
-
- //printf("bump %d %f\n", v-1, activity[v]);
-
- if (s->orderpos[v] != -1)
- order_update(s,v);
-
-}
-
-static inline void act_var_decay(solver* s) { s->var_inc *= s->var_decay; }
-
-static inline void act_clause_rescale(solver* s) {
- clause** cs = (clause**)vec_begin(&s->learnts);
- int i;
- for (i = 0; i < vec_size(&s->learnts); i++){
- float a = clause_activity(cs[i]);
- clause_setactivity(cs[i], a * (float)1e-20);
- }
- s->cla_inc *= (float)1e-20;
-}
-
-
-static inline void act_clause_bump(solver* s, clause *c) {
- float a = clause_activity(c) + s->cla_inc;
- clause_setactivity(c,a);
- if (a > 1e20) act_clause_rescale(s);
-}
-
-static inline void act_clause_decay(solver* s) { s->cla_inc *= s->cla_decay; }
-
-
-//=================================================================================================
-// Clause functions:
-
-/* pre: size > 1 && no variable occurs twice
- */
-static clause* clause_new(solver* s, lit* begin, lit* end, int learnt)
-{
- int size;
- clause* c;
- int i;
-
- assert(end - begin > 1);
- assert(learnt >= 0 && learnt < 2);
- size = end - begin;
- c = (clause*)malloc(sizeof(clause) + sizeof(lit) * size + learnt * sizeof(float));
- c->size_learnt = (size << 1) | learnt;
- assert(((unsigned int)c & 1) == 0);
-
- for (i = 0; i < size; i++)
- c->lits[i] = begin[i];
-
- if (learnt)
- *((float*)&c->lits[size]) = 0.0;
-
- assert(begin[0] >= 0);
- assert(begin[0] < s->size*2);
- assert(begin[1] >= 0);
- assert(begin[1] < s->size*2);
-
- assert(neg(begin[0]) < s->size*2);
- assert(neg(begin[1]) < s->size*2);
-
- //vec_push(solver_read_wlist(s,neg(begin[0])),(void*)c);
- //vec_push(solver_read_wlist(s,neg(begin[1])),(void*)c);
-
- vec_push(solver_read_wlist(s,neg(begin[0])),(void*)(size > 2 ? c : clause_from_lit(begin[1])));
- vec_push(solver_read_wlist(s,neg(begin[1])),(void*)(size > 2 ? c : clause_from_lit(begin[0])));
-
- return c;
-}
-
-
-static void clause_remove(solver* s, clause* c)
-{
- lit* lits = clause_begin(c);
- assert(neg(lits[0]) < s->size*2);
- assert(neg(lits[1]) < s->size*2);
-
- //vec_remove(solver_read_wlist(s,neg(lits[0])),(void*)c);
- //vec_remove(solver_read_wlist(s,neg(lits[1])),(void*)c);
-
- assert(lits[0] < s->size*2);
- vec_remove(solver_read_wlist(s,neg(lits[0])),(void*)(clause_size(c) > 2 ? c : clause_from_lit(lits[1])));
- vec_remove(solver_read_wlist(s,neg(lits[1])),(void*)(clause_size(c) > 2 ? c : clause_from_lit(lits[0])));
-
- if (clause_learnt(c)){
- s->stats.learnts--;
- s->stats.learnts_literals -= clause_size(c);
- }else{
- s->stats.clauses--;
- s->stats.clauses_literals -= clause_size(c);
- }
-
- free(c);
-}
-
-
-static lbool clause_simplify(solver* s, clause* c)
-{
- lit* lits = clause_begin(c);
- lbool* values = s->assigns;
- int i;
-
- assert(solver_dlevel(s) == 0);
-
- for (i = 0; i < clause_size(c); i++){
- lbool sig = !lit_sign(lits[i]); sig += sig - 1;
- if (values[lit_var(lits[i])] == sig)
- return l_True;
- }
- return l_False;
-}
-
-//=================================================================================================
-// Minor (solver) functions:
-
-static void solver_setnvars(solver* s,int n)
-{
- int var;
- if (s->cap < n){
-
- while (s->cap < n) s->cap = s->cap*2+1;
-
- s->wlists = (vec*) realloc(s->wlists, sizeof(vec)*s->cap*2);
- s->activity = (double*) realloc(s->activity, sizeof(double)*s->cap);
- s->assigns = (lbool*) realloc(s->assigns, sizeof(lbool)*s->cap);
- s->orderpos = (int*) realloc(s->orderpos, sizeof(int)*s->cap);
- s->reasons = (clause**)realloc(s->reasons, sizeof(clause*)*s->cap);
- s->levels = (int*) realloc(s->levels, sizeof(int)*s->cap);
- s->tags = (lbool*) realloc(s->tags, sizeof(lbool)*s->cap);
- s->trail = (lit*) realloc(s->trail, sizeof(lit)*s->cap);
- }
-
- for (var = s->size; var < n; var++){
- vec_new(&s->wlists[2*var]);
- vec_new(&s->wlists[2*var+1]);
- s->activity [var] = 0;
- s->assigns [var] = l_Undef;
- s->orderpos [var] = var;
- s->reasons [var] = (clause*)0;
- s->levels [var] = 0;
- s->tags [var] = l_Undef;
-
- assert(vec_size(&s->order) == var);
- vec_push(&s->order,(void*)var);
- order_update(s,var);
- }
-
- s->size = n > s->size ? n : s->size;
-}
-
-
-static inline bool enqueue(solver* s, lit l, clause* from)
-{
- lbool* values = s->assigns;
- int v = lit_var(l);
- lbool val = values[v];
-#ifdef VERBOSEDEBUG
- printf(L_IND"enqueue("L_LIT")\n", L_ind, L_lit(l));
-#endif
-
- lbool sig = !lit_sign(l); sig += sig - 1;
- if (val != l_Undef){
- return val == sig;
- }else{
- // New fact -- store it.
-#ifdef VERBOSEDEBUG
- printf(L_IND"bind("L_LIT")\n", L_ind, L_lit(l));
-#endif
- int* levels = s->levels;
- clause** reasons = s->reasons;
-
- values [v] = sig;
- levels [v] = solver_dlevel(s);
- reasons[v] = from;
- s->trail[s->qtail++] = l;
-
- order_assigned(s, v);
- return true;
- }
-}
-
-
-static inline void assume(solver* s, lit l){
- assert(s->qtail == s->qhead);
- assert(s->assigns[lit_var(l)] == l_Undef);
-#ifdef VERBOSEDEBUG
- printf(L_IND"assume("L_LIT")\n", L_ind, L_lit(l));
-#endif
- vec_push(&s->trail_lim,(void*)s->qtail);
- enqueue(s,l,(clause*)0);
-}
-
-
-static inline void solver_canceluntil(solver* s, int level) {
- lit* trail;
- lbool* values;
- clause** reasons;
- int bound;
- int c;
-
- if (solver_dlevel(s) <= level)
- return;
-
- trail = s->trail;
- values = s->assigns;
- reasons = s->reasons;
- bound = ((int*)vec_begin(&s->trail_lim))[level];
-
- for (c = s->qtail-1; c >= bound; c--) {
- int x = lit_var(trail[c]);
- values [x] = l_Undef;
- reasons[x] = (clause*)0;
- }
-
- for (c = s->qhead-1; c >= bound; c--)
- order_unassigned(s,lit_var(trail[c]));
-
- s->qhead = s->qtail = bound;
- vec_resize(&s->trail_lim,level);
-}
-
-static void solver_record(solver* s, vec* cls)
-{
- lit* begin = (lit*)vec_begin(cls);
- lit* end = begin + vec_size(cls);
- clause* c = (vec_size(cls) > 1) ? clause_new(s,begin,end,1) : (clause*)0;
- enqueue(s,*begin,c);
-
- assert(vec_size(cls) > 0);
-
- if (c != 0) {
- vec_push(&s->learnts,(void*)c);
- act_clause_bump(s,c);
- s->stats.learnts++;
- s->stats.learnts_literals += vec_size(cls);
- }
-}
-
-
-static double solver_progress(solver* s)
-{
- lbool* values = s->assigns;
- int* levels = s->levels;
- int i;
-
- double progress = 0;
- double F = 1.0 / s->size;
- for (i = 0; i < s->size; i++)
- if (values[i] != l_Undef)
- progress += pow(F, levels[i]);
- return progress / s->size;
-}
-
-//=================================================================================================
-// Major methods:
-
-static bool solver_lit_removable(solver* s, lit l, int minl)
-{
- lbool* tags = s->tags;
- clause** reasons = s->reasons;
- int* levels = s->levels;
- int top = vec_size(&s->tagged);
-
- assert(lit_var(l) >= 0 && lit_var(l) < s->size);
- assert(reasons[lit_var(l)] != 0);
- vec_resize(&s->stack,0);
- vec_push(&s->stack,(void*)lit_var(l));
-
- while (vec_size(&s->stack) > 0){
- clause* c;
- int v = (int)vec_begin(&s->stack)[vec_size(&s->stack)-1];
- assert(v >= 0 && v < s->size);
- vec_resize(&s->stack,vec_size(&s->stack)-1);
- assert(reasons[v] != 0);
- c = reasons[v];
-
- if (clause_is_lit(c)){
- int v = lit_var(clause_read_lit(c));
- if (tags[v] == l_Undef && levels[v] != 0){
- if (reasons[v] != 0 && ((1 << (levels[v] & 31)) & minl)){
- vec_push(&s->stack,(void*)v);
- tags[v] = l_True;
- vec_push(&s->tagged,(void*)v);
- }else{
- int* tagged = (int*)vec_begin(&s->tagged);
- int j;
- for (j = top; j < vec_size(&s->tagged); j++)
- tags[tagged[j]] = l_Undef;
- vec_resize(&s->tagged,top);
- return false;
- }
- }
- }else{
- lit* lits = clause_begin(c);
- int i, j;
-
- for (i = 1; i < clause_size(c); i++){
- int v = lit_var(lits[i]);
- if (tags[v] == l_Undef && levels[v] != 0){
- if (reasons[v] != 0 && ((1 << (levels[v] & 31)) & minl)){
-
- vec_push(&s->stack,(void*)lit_var(lits[i]));
- tags[v] = l_True;
- vec_push(&s->tagged,(void*)v);
- }else{
- int* tagged = (int*)vec_begin(&s->tagged);
- for (j = top; j < vec_size(&s->tagged); j++)
- tags[tagged[j]] = l_Undef;
- vec_resize(&s->tagged,top);
- return false;
- }
- }
- }
- }
- }
-
- return true;
-}
-
-static void solver_analyze(solver* s, clause* c, vec* learnt)
-{
- lit* trail = s->trail;
- lbool* tags = s->tags;
- clause** reasons = s->reasons;
- int* levels = s->levels;
- int cnt = 0;
- lit p = lit_Undef;
- int ind = s->qtail-1;
- lit* lits;
- int i, j, minl;
- int* tagged;
-
- vec_push(learnt,(void*)lit_Undef);
-
- do{
- assert(c != 0);
-
- if (clause_is_lit(c)){
- lit q = clause_read_lit(c);
- assert(lit_var(q) >= 0 && lit_var(q) < s->size);
- if (tags[lit_var(q)] == l_Undef && levels[lit_var(q)] > 0){
- tags[lit_var(q)] = l_True;
- vec_push(&s->tagged,(void*)lit_var(q));
- act_var_bump(s,lit_var(q));
- if (levels[lit_var(q)] == solver_dlevel(s))
- cnt++;
- else
- vec_push(learnt,(void*)q);
- }
- }else{
-
- if (clause_learnt(c))
- act_clause_bump(s,c);
-
- lits = clause_begin(c);
- //printlits(lits,lits+clause_size(c)); printf("\n");
- for (j = (p == lit_Undef ? 0 : 1); j < clause_size(c); j++){
- lit q = lits[j];
- assert(lit_var(q) >= 0 && lit_var(q) < s->size);
- if (tags[lit_var(q)] == l_Undef && levels[lit_var(q)] > 0){
- tags[lit_var(q)] = l_True;
- vec_push(&s->tagged,(void*)lit_var(q));
- act_var_bump(s,lit_var(q));
- if (levels[lit_var(q)] == solver_dlevel(s))
- cnt++;
- else
- vec_push(learnt,(void*)q);
- }
- }
- }
-
- while (tags[lit_var(trail[ind--])] == l_Undef);
-
- p = trail[ind+1];
- c = reasons[lit_var(p)];
- cnt--;
-
- }while (cnt > 0);
-
- *(lit*)vec_begin(learnt) = neg(p);
-
- lits = (lit*)vec_begin(learnt);
- minl = 0;
- for (i = 1; i < vec_size(learnt); i++){
- int lev = levels[lit_var(lits[i])];
- minl |= 1 << (lev & 31);
- }
-
- // simplify (full)
- for (i = j = 1; i < vec_size(learnt); i++){
- if (reasons[lit_var(lits[i])] == 0 || !solver_lit_removable(s,lits[i],minl))
- lits[j++] = lits[i];
- }
-
- // update size of learnt + statistics
- s->stats.max_literals += vec_size(learnt);
- vec_resize(learnt,j);
- s->stats.tot_literals += j;
-
- // clear tags
- tagged = (int*)vec_begin(&s->tagged);
- for (i = 0; i < vec_size(&s->tagged); i++)
- tags[tagged[i]] = l_Undef;
- vec_resize(&s->tagged,0);
-
-#ifdef DEBUG
- for (i = 0; i < s->size; i++)
- assert(tags[i] == l_Undef);
-#endif
-
-#ifdef VERBOSEDEBUG
- printf(L_IND"Learnt {", L_ind);
- for (i = 0; i < vec_size(learnt); i++) printf(" "L_LIT, L_lit(lits[i]));
-#endif
- if (vec_size(learnt) > 1){
- int max_i = 1;
- int max = levels[lit_var(lits[1])];
- lit tmp;
-
- for (i = 2; i < vec_size(learnt); i++)
- if (levels[lit_var(lits[i])] > max){
- max = levels[lit_var(lits[i])];
- max_i = i;
- }
-
- tmp = lits[1];
- lits[1] = lits[max_i];
- lits[max_i] = tmp;
- }
-#ifdef VERBOSEDEBUG
- {
- int lev = vec_size(learnt) > 1 ? levels[lit_var(lits[1])] : 0;
- printf(" } at level %d\n", lev);
- }
-#endif
-}
-
-
-clause* solver_propagate(solver* s)
-{
- lbool* values = s->assigns;
- clause* confl = (clause*)0;
- lit* lits;
-
- //printf("solver_propagate\n");
- while (confl == 0 && s->qtail - s->qhead > 0){
- lit p = s->trail[s->qhead++];
- vec* ws = solver_read_wlist(s,p);
- clause **begin = (clause**)vec_begin(ws);
- clause **end = begin + vec_size(ws);
- clause **i, **j;
-
- s->stats.propagations++;
- s->simpdb_props--;
-
- //printf("checking lit %d: "L_LIT"\n", vec_size(ws), L_lit(p));
- for (i = j = begin; i < end; ){
- if (clause_is_lit(*i)){
- *j++ = *i;
- if (!enqueue(s,clause_read_lit(*i),clause_from_lit(p))){
- confl = s->binary;
- (clause_begin(confl))[1] = neg(p);
- (clause_begin(confl))[0] = clause_read_lit(*i++);
-
- // Copy the remaining watches:
- while (i < end)
- *j++ = *i++;
- }
- }else{
- lit false_lit;
- lbool sig;
-
- lits = clause_begin(*i);
-
- // Make sure the false literal is data[1]:
- false_lit = neg(p);
- if (lits[0] == false_lit){
- lits[0] = lits[1];
- lits[1] = false_lit;
- }
- assert(lits[1] == false_lit);
- //printf("checking clause: "); printlits(lits, lits+clause_size(*i)); printf("\n");
-
- // If 0th watch is true, then clause is already satisfied.
- sig = !lit_sign(lits[0]); sig += sig - 1;
- if (values[lit_var(lits[0])] == sig){
- *j++ = *i;
- }else{
- // Look for new watch:
- lit* stop = lits + clause_size(*i);
- lit* k;
- for (k = lits + 2; k < stop; k++){
- lbool sig = lit_sign(*k); sig += sig - 1;
- if (values[lit_var(*k)] != sig){
- lits[1] = *k;
- *k = false_lit;
- vec_push(solver_read_wlist(s,neg(lits[1])),*i);
- goto next; }
- }
-
- *j++ = *i;
- // Clause is unit under assignment:
- if (!enqueue(s,lits[0], *i)){
- confl = *i++;
- // Copy the remaining watches:
- while (i < end)
- *j++ = *i++;
- }
- }
- }
- next:
- i++;
- }
-
- s->stats.inspects += j - (clause**)vec_begin(ws);
- vec_resize(ws,j - (clause**)vec_begin(ws));
- }
-
- return confl;
-}
-
-static inline int clause_cmp (const void* x, const void* y) {
- return clause_size((clause*)x) > 2 && (clause_size((clause*)y) == 2 || clause_activity((clause*)x) < clause_activity((clause*)y)) ? -1 : 1; }
-
-void solver_reducedb(solver* s)
-{
- int i, j;
- double extra_lim = s->cla_inc / vec_size(&s->learnts); // Remove any clause below this activity
- clause** learnts = (clause**)vec_begin(&s->learnts);
- clause** reasons = s->reasons;
-
- sort(vec_begin(&s->learnts), vec_size(&s->learnts), &clause_cmp);
-
- for (i = j = 0; i < vec_size(&s->learnts) / 2; i++){
- if (clause_size(learnts[i]) > 2 && reasons[lit_var(*clause_begin(learnts[i]))] != learnts[i])
- clause_remove(s,learnts[i]);
- else
- learnts[j++] = learnts[i];
- }
- for (; i < vec_size(&s->learnts); i++){
- if (clause_size(learnts[i]) > 2 && reasons[lit_var(*clause_begin(learnts[i]))] != learnts[i] && clause_activity(learnts[i]) < extra_lim)
- clause_remove(s,learnts[i]);
- else
- learnts[j++] = learnts[i];
- }
-
- //printf("reducedb deleted %d\n", vec_size(&s->learnts) - j);
-
-
- vec_resize(&s->learnts,j);
-}
-
-static lbool solver_search(solver* s, int nof_conflicts, int nof_learnts)
-{
- int* levels = s->levels;
- double var_decay = 0.95;
- double clause_decay = 0.999;
- double random_var_freq = 0.02;
-
- int conflictC = 0;
- vec learnt_clause;
-
- assert(s->root_level == solver_dlevel(s));
-
- s->stats.starts++;
- s->var_decay = (float)(1 / var_decay );
- s->cla_decay = (float)(1 / clause_decay);
- vec_resize(&s->model,0);
- vec_new(&learnt_clause);
-
- for (;;){
- clause* confl = solver_propagate(s);
- if (confl != 0){
- // CONFLICT
- int blevel;
-
-#ifdef VERBOSEDEBUG
- printf(L_IND"**CONFLICT**\n", L_ind);
-#endif
- s->stats.conflicts++; conflictC++;
- if (solver_dlevel(s) == s->root_level){
- vec_delete(&learnt_clause);
- return l_False;
- }
-
- vec_resize(&learnt_clause,0);
- solver_analyze(s, confl, &learnt_clause);
- blevel = vec_size(&learnt_clause) > 1 ? levels[lit_var(((lit*)vec_begin(&learnt_clause))[1])] : s->root_level;
- solver_canceluntil(s,blevel);
- solver_record(s,&learnt_clause);
- act_var_decay(s);
- act_clause_decay(s);
-
- }else{
- // NO CONFLICT
- int next;
-
- if (nof_conflicts >= 0 && conflictC >= nof_conflicts){
- // Reached bound on number of conflicts:
- s->progress_estimate = solver_progress(s);
- solver_canceluntil(s,s->root_level);
- vec_delete(&learnt_clause);
- return l_Undef; }
-
- if (solver_dlevel(s) == 0)
- // Simplify the set of problem clauses:
- solver_simplify(s);
-
- if (nof_learnts >= 0 && vec_size(&s->learnts) - s->qtail >= nof_learnts)
- // Reduce the set of learnt clauses:
- solver_reducedb(s);
-
- // New variable decision:
- s->stats.decisions++;
- next = order_select(s,(float)random_var_freq);
-
- if (next == var_Undef){
- // Model found:
- lbool* values = s->assigns;
- int i;
- for (i = 0; i < s->size; i++) vec_push(&s->model,(void*)((int)values[i]));
- solver_canceluntil(s,s->root_level);
- vec_delete(&learnt_clause);
- return l_True;
- }
-
- assume(s,neg(toLit(next)));
- }
- }
-
- return l_Undef; // cannot happen
-}
-
-//=================================================================================================
-// External solver functions:
-
-solver* solver_new(void)
-{
- solver* s = (solver*)malloc(sizeof(solver));
-
- // initialize vectors
- vec_new(&s->clauses);
- vec_new(&s->learnts);
- vec_new(&s->order);
- vec_new(&s->trail_lim);
- vec_new(&s->tagged);
- vec_new(&s->stack);
- vec_new(&s->model);
-
- // initialize arrays
- s->wlists = 0;
- s->activity = 0;
- s->assigns = 0;
- s->orderpos = 0;
- s->reasons = 0;
- s->levels = 0;
- s->tags = 0;
- s->trail = 0;
-
-
- // initialize other vars
- s->size = 0;
- s->cap = 0;
- s->qhead = 0;
- s->qtail = 0;
- s->cla_inc = 1;
- s->cla_decay = 1;
- s->var_inc = 1;
- s->var_decay = 1;
- s->root_level = 0;
- s->simpdb_assigns = 0;
- s->simpdb_props = 0;
- s->random_seed = 91648253;
- s->progress_estimate = 0;
- s->binary = (clause*)malloc(sizeof(clause) + sizeof(lit)*2);
- s->binary->size_learnt = (2 << 1);
- s->verbosity = 0;
-
- s->stats.starts = 0;
- s->stats.decisions = 0;
- s->stats.propagations = 0;
- s->stats.inspects = 0;
- s->stats.conflicts = 0;
- s->stats.clauses = 0;
- s->stats.clauses_literals = 0;
- s->stats.learnts = 0;
- s->stats.learnts_literals = 0;
- s->stats.max_literals = 0;
- s->stats.tot_literals = 0;
-
- return s;
-}
-
-
-void solver_delete(solver* s)
-{
- int i;
- for (i = 0; i < vec_size(&s->clauses); i++)
- free(vec_begin(&s->clauses)[i]);
-
- for (i = 0; i < vec_size(&s->learnts); i++)
- free(vec_begin(&s->learnts)[i]);
-
- // delete vectors
- vec_delete(&s->clauses);
- vec_delete(&s->learnts);
- vec_delete(&s->order);
- vec_delete(&s->trail_lim);
- vec_delete(&s->tagged);
- vec_delete(&s->stack);
- vec_delete(&s->model);
- free(s->binary);
-
- // delete arrays
- if (s->wlists != 0){
- int i;
- for (i = 0; i < s->size*2; i++)
- vec_delete(&s->wlists[i]);
-
- // if one is different from null, all are
- free(s->wlists);
- free(s->activity );
- free(s->assigns );
- free(s->orderpos );
- free(s->reasons );
- free(s->levels );
- free(s->trail );
- free(s->tags );
- }
-
- free(s);
-}
-
-
-bool solver_addclause(solver* s, lit* begin, lit* end)
-{
- lit *i,*j;
- int maxvar;
- lbool* values;
- lit last;
-
- if (begin == end) return false;
-
- //printlits(begin,end); printf("\n");
- // insertion sort
- maxvar = lit_var(*begin);
- for (i = begin + 1; i < end; i++){
- lit l = *i;
- maxvar = lit_var(l) > maxvar ? lit_var(l) : maxvar;
- for (j = i; j > begin && *(j-1) > l; j--)
- *j = *(j-1);
- *j = l;
- }
- solver_setnvars(s,maxvar+1);
-
- //printlits(begin,end); printf("\n");
- values = s->assigns;
-
- // delete duplicates
- last = lit_Undef;
- for (i = j = begin; i < end; i++){
- //printf("lit: "L_LIT", value = %d\n", L_lit(*i), (lit_sign(*i) ? -values[lit_var(*i)] : values[lit_var(*i)]));
- lbool sig = !lit_sign(*i); sig += sig - 1;
- if (*i == neg(last) || sig == values[lit_var(*i)])
- return true; // tautology
- else if (*i != last && values[lit_var(*i)] == l_Undef)
- last = *j++ = *i;
- }
-
- //printf("final: "); printlits(begin,j); printf("\n");
-
- if (j == begin) // empty clause
- return false;
- else if (j - begin == 1) // unit clause
- return enqueue(s,*begin,(clause*)0);
-
- // create new clause
- vec_push(&s->clauses,clause_new(s,begin,j,0));
-
-
- s->stats.clauses++;
- s->stats.clauses_literals += j - begin;
-
- return true;
-}
-
-
-bool solver_simplify(solver* s)
-{
- clause** reasons;
- int type;
-
- assert(solver_dlevel(s) == 0);
-
- if (solver_propagate(s) != 0)
- return false;
-
- if (s->qhead == s->simpdb_assigns || s->simpdb_props > 0)
- return true;
-
- reasons = s->reasons;
- for (type = 0; type < 2; type++){
- vec* cs = type ? &s->learnts : &s->clauses;
- clause** cls = (clause**)vec_begin(cs);
-
- int i, j;
- for (j = i = 0; i < vec_size(cs); i++){
- if (reasons[lit_var(*clause_begin(cls[i]))] != cls[i] &&
- clause_simplify(s,cls[i]) == l_True)
- clause_remove(s,cls[i]);
- else
- cls[j++] = cls[i];
- }
- vec_resize(cs,j);
- }
-
- s->simpdb_assigns = s->qhead;
- // (shouldn't depend on 'stats' really, but it will do for now)
- s->simpdb_props = (int)(s->stats.clauses_literals + s->stats.learnts_literals);
-
- return true;
-}
-
-
-bool solver_solve(solver* s, lit* begin, lit* end)
-{
- double nof_conflicts = 100;
- double nof_learnts = solver_nclauses(s) / 3;
- lbool status = l_Undef;
- lbool* values = s->assigns;
- lit* i;
-
- for (i = begin; i < end; i++)
- if ((lit_sign(*i) ? -values[lit_var(*i)] : values[lit_var(*i)]) == l_False || (assume(s,*i), solver_propagate(s) != 0)){
- solver_canceluntil(s,0);
- return false; }
-
- s->root_level = solver_dlevel(s);
-
- if (s->verbosity >= 1){
- printf("==================================[MINISAT]===================================\n");
- printf("| Conflicts | ORIGINAL | LEARNT | Progress |\n");
- printf("| | Clauses Literals | Limit Clauses Literals Lit/Cl | |\n");
- printf("==============================================================================\n");
- }
-
- while (status == l_Undef){
- double Ratio = (s->stats.learnts == 0)? 0.0 :
- s->stats.learnts_literals / (double)s->stats.learnts;
-
- if (s->verbosity >= 1){
- printf("| %9.0f | %7.0f %8.0f | %7.0f %7.0f %8.0f %7.1f | %6.3f %% |\n",
- (double)s->stats.conflicts,
- (double)s->stats.clauses,
- (double)s->stats.clauses_literals,
- (double)nof_learnts,
- (double)s->stats.learnts,
- (double)s->stats.learnts_literals,
- Ratio,
- s->progress_estimate*100);
- fflush(stdout);
- }
- status = solver_search(s,(int)nof_conflicts, (int)nof_learnts);
- nof_conflicts *= 1.5;
- nof_learnts *= 1.1;
- }
- if (s->verbosity >= 1)
- printf("==============================================================================\n");
-
- solver_canceluntil(s,0);
- return status != l_False;
-}
-
-
-int solver_nvars(solver* s)
-{
- return s->size;
-}
-
-
-int solver_nclauses(solver* s)
-{
- return vec_size(&s->clauses);
-}
-
-//=================================================================================================
-// Sorting functions (sigh):
-
-static inline void selectionsort(void** array, int size, int(*comp)(const void *, const void *))
-{
- int i, j, best_i;
- void* tmp;
-
- for (i = 0; i < size-1; i++){
- best_i = i;
- for (j = i+1; j < size; j++){
- if (comp(array[j], array[best_i]) < 0)
- best_i = j;
- }
- tmp = array[i]; array[i] = array[best_i]; array[best_i] = tmp;
- }
-}
-
-
-static void sortrnd(void** array, int size, int(*comp)(const void *, const void *), double* seed)
-{
- if (size <= 15)
- selectionsort(array, size, comp);
-
- else{
- void* pivot = array[irand(seed, size)];
- void* tmp;
- int i = -1;
- int j = size;
-
- for(;;){
- do i++; while(comp(array[i], pivot)<0);
- do j--; while(comp(pivot, array[j])<0);
-
- if (i >= j) break;
-
- tmp = array[i]; array[i] = array[j]; array[j] = tmp;
- }
-
- sortrnd(array , i , comp, seed);
- sortrnd(&array[i], size-i, comp, seed);
- }
-}
-
-void sort(void** array, int size, int(*comp)(const void *, const void *))
-{
- double seed = 91648253;
- sortrnd(array,size,comp,&seed);
-}
diff --git a/src/sat/asat/solver.h b/src/sat/asat/solver.h
deleted file mode 100644
index e04d5780..00000000
--- a/src/sat/asat/solver.h
+++ /dev/null
@@ -1,137 +0,0 @@
-/**************************************************************************************************
-MiniSat -- Copyright (c) 2005, Niklas Sorensson
-http://www.cs.chalmers.se/Cs/Research/FormalMethods/MiniSat/
-
-Permission is hereby granted, free of charge, to any person obtaining a copy of this software and
-associated documentation files (the "Software"), to deal in the Software without restriction,
-including without limitation the rights to use, copy, modify, merge, publish, distribute,
-sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is
-furnished to do so, subject to the following conditions:
-
-The above copyright notice and this permission notice shall be included in all copies or
-substantial portions of the Software.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT
-NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
-NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
-DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT
-OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
-**************************************************************************************************/
-// Modified to compile with MS Visual Studio 6.0 by Alan Mishchenko
-
-#ifndef solver_h
-#define solver_h
-
-#ifdef _WIN32
-#define inline __inline // compatible with MS VS 6.0
-#endif
-
-#include "solver_vec.h"
-
-//=================================================================================================
-// Simple types:
-
-//typedef int bool;
-#ifndef bool
-#define bool int
-#endif
-
-static const bool true = 1;
-static const bool false = 0;
-
-typedef int lit;
-typedef char lbool;
-
-#ifdef _WIN32
-typedef signed __int64 uint64; // compatible with MS VS 6.0
-#else
-typedef unsigned long long uint64;
-#endif
-
-static const int var_Undef = -1;
-static const lit lit_Undef = -2;
-
-static const lbool l_Undef = 0;
-static const lbool l_True = 1;
-static const lbool l_False = -1;
-
-static inline lit neg (lit l) { return l ^ 1; }
-static inline lit toLit (int v) { return v + v; }
-
-//=================================================================================================
-// Public interface:
-
-struct solver_t;
-typedef struct solver_t solver;
-
-extern solver* solver_new(void);
-extern void solver_delete(solver* s);
-
-extern bool solver_addclause(solver* s, lit* begin, lit* end);
-extern bool solver_simplify(solver* s);
-extern bool solver_solve(solver* s, lit* begin, lit* end);
-
-extern int solver_nvars(solver* s);
-extern int solver_nclauses(solver* s);
-
-// additional procedures
-extern void Asat_SolverWriteDimacs( solver * pSat, char * pFileName );
-
-struct stats_t
-{
- uint64 starts, decisions, propagations, inspects, conflicts;
- uint64 clauses, clauses_literals, learnts, learnts_literals, max_literals, tot_literals;
-};
-typedef struct stats_t stats;
-
-//=================================================================================================
-// Solver representation:
-
-struct clause_t;
-typedef struct clause_t clause;
-
-struct solver_t
-{
- int size; // nof variables
- int cap; // size of varmaps
- int qhead; // Head index of queue.
- int qtail; // Tail index of queue.
-
- // clauses
- vec clauses; // List of problem constraints. (contains: clause*)
- vec learnts; // List of learnt clauses. (contains: clause*)
-
- // activities
- double var_inc; // Amount to bump next variable with.
- double var_decay; // INVERSE decay factor for variable activity: stores 1/decay.
- float cla_inc; // Amount to bump next clause with.
- float cla_decay; // INVERSE decay factor for clause activity: stores 1/decay.
-
- vec* wlists; //
- double* activity; // A heuristic measurement of the activity of a variable.
- lbool* assigns; // Current values of variables.
- int* orderpos; // Index in variable order.
- clause** reasons; //
- int* levels; //
- lit* trail;
-
- clause* binary; // A temporary binary clause
- lbool* tags; //
- vec tagged; // (contains: var)
- vec stack; // (contains: var)
-
- vec order; // Variable order. (heap) (contains: var)
- vec trail_lim; // Separator indices for different decision levels in 'trail'. (contains: int)
- vec model; // If problem is solved, this vector contains the model (contains: lbool).
-
- int root_level; // Level of first proper decision.
- int simpdb_assigns;// Number of top-level assignments at last 'simplifyDB()'.
- int simpdb_props; // Number of propagations before next 'simplifyDB()'.
- double random_seed;
- double progress_estimate;
- int verbosity; // Verbosity level. 0=silent, 1=some progress report, 2=everything
-
- stats stats;
-};
-
-#endif
diff --git a/src/sat/asat/solver_vec.h b/src/sat/asat/solver_vec.h
deleted file mode 100644
index fae313d0..00000000
--- a/src/sat/asat/solver_vec.h
+++ /dev/null
@@ -1,53 +0,0 @@
-/**************************************************************************************************
-MiniSat -- Copyright (c) 2005, Niklas Sorensson
-http://www.cs.chalmers.se/Cs/Research/FormalMethods/MiniSat/
-
-Permission is hereby granted, free of charge, to any person obtaining a copy of this software and
-associated documentation files (the "Software"), to deal in the Software without restriction,
-including without limitation the rights to use, copy, modify, merge, publish, distribute,
-sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is
-furnished to do so, subject to the following conditions:
-
-The above copyright notice and this permission notice shall be included in all copies or
-substantial portions of the Software.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT
-NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
-NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
-DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT
-OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
-**************************************************************************************************/
-// Modified to compile with MS Visual Studio 6.0 by Alan Mishchenko
-
-#ifndef vec_h
-#define vec_h
-
-#include <stdlib.h>
-
-struct vec_t {
- int size;
- int cap;
- void** ptr;
-};
-typedef struct vec_t vec;
-
-static inline void vec_new (vec* v) {
- v->size = 0;
- v->cap = 4;
- v->ptr = (void**)malloc(sizeof(void*)*v->cap);
-}
-
-static inline void vec_delete (vec* v) { free(v->ptr); }
-static inline void** vec_begin (vec* v) { return v->ptr; }
-static inline int vec_size (vec* v) { return v->size; }
-static inline void vec_resize (vec* v, int k) { v->size = k; } // only safe to shrink !!
-static inline void vec_push (vec* v, void* e)
-{
- if (v->size == v->cap) {
- int newsize = v->cap * 2+1;
- v->ptr = (void**)realloc(v->ptr,sizeof(void*)*newsize);
- v->cap = newsize; }
- v->ptr[v->size++] = e;
-}
-
-#endif
diff --git a/src/abc8/bsat/module.make b/src/sat/bsat/module.make
index 563c8dfc..1e52cc0a 100644
--- a/src/abc8/bsat/module.make
+++ b/src/sat/bsat/module.make
@@ -1,5 +1,6 @@
SRC += src/sat/bsat/satMem.c \
src/sat/bsat/satInter.c \
+ src/sat/bsat/satInterA.c \
src/sat/bsat/satSolver.c \
src/sat/bsat/satStore.c \
src/sat/bsat/satTrace.c \
diff --git a/src/abc8/bsat/satInter.c b/src/sat/bsat/satInter.c
index 8e07e9f6..8e07e9f6 100644
--- a/src/abc8/bsat/satInter.c
+++ b/src/sat/bsat/satInter.c
diff --git a/src/abc8/bsat/satInterA.c b/src/sat/bsat/satInterA.c
index 513a9044..513a9044 100644
--- a/src/abc8/bsat/satInterA.c
+++ b/src/sat/bsat/satInterA.c
diff --git a/src/abc8/bsat/satMem.c b/src/sat/bsat/satMem.c
index 7fa1a824..7fa1a824 100644
--- a/src/abc8/bsat/satMem.c
+++ b/src/sat/bsat/satMem.c
diff --git a/src/abc8/bsat/satMem.h b/src/sat/bsat/satMem.h
index 22b7a87c..22b7a87c 100644
--- a/src/abc8/bsat/satMem.h
+++ b/src/sat/bsat/satMem.h
diff --git a/src/abc8/bsat/satSolver.c b/src/sat/bsat/satSolver.c
index fbc9874d..fbc9874d 100644
--- a/src/abc8/bsat/satSolver.c
+++ b/src/sat/bsat/satSolver.c
diff --git a/src/abc8/bsat/satSolver.h b/src/sat/bsat/satSolver.h
index c1bf32a7..c1bf32a7 100644
--- a/src/abc8/bsat/satSolver.h
+++ b/src/sat/bsat/satSolver.h
diff --git a/src/abc8/bsat/satStore.c b/src/sat/bsat/satStore.c
index f968162e..f968162e 100644
--- a/src/abc8/bsat/satStore.c
+++ b/src/sat/bsat/satStore.c
diff --git a/src/abc8/bsat/satStore.h b/src/sat/bsat/satStore.h
index b66abc8f..b66abc8f 100644
--- a/src/abc8/bsat/satStore.h
+++ b/src/sat/bsat/satStore.h
diff --git a/src/abc8/bsat/satTrace.c b/src/sat/bsat/satTrace.c
index 111e8dfb..111e8dfb 100644
--- a/src/abc8/bsat/satTrace.c
+++ b/src/sat/bsat/satTrace.c
diff --git a/src/abc8/bsat/satUtil.c b/src/sat/bsat/satUtil.c
index 3961cf7e..3961cf7e 100644
--- a/src/abc8/bsat/satUtil.c
+++ b/src/sat/bsat/satUtil.c
diff --git a/src/abc8/bsat/satVec.h b/src/sat/bsat/satVec.h
index d7fce5c0..d7fce5c0 100644
--- a/src/abc8/bsat/satVec.h
+++ b/src/sat/bsat/satVec.h
diff --git a/src/sat/csat/csat_apis.c b/src/sat/csat/csat_apis.c
index b030caef..5872f5bc 100644
--- a/src/sat/csat/csat_apis.c
+++ b/src/sat/csat/csat_apis.c
@@ -24,7 +24,11 @@
/// DECLARATIONS ///
////////////////////////////////////////////////////////////////////////
-struct CSAT_ManagerStruct_t
+#define ABC_DEFAULT_CONF_LIMIT 0 // limit on conflicts
+#define ABC_DEFAULT_IMP_LIMIT 0 // limit on implications
+
+
+struct ABC_ManagerStruct_t
{
// information about the problem
stmm_table * tName2Node; // the hash table mapping names to nodes
@@ -32,9 +36,10 @@ struct CSAT_ManagerStruct_t
Abc_Ntk_t * pNtk; // the starting ABC network
Abc_Ntk_t * pTarget; // the AIG representing the target
char * pDumpFileName; // the name of the file to dump the target network
+ Extra_MmFlex_t * pMmNames; // memory manager for signal names
// solving parameters
- int mode; // 0 = baseline; 1 = resource-aware fraiging
- Fraig_Params_t Params; // the set of parameters to call FRAIG package
+ int mode; // 0 = resource-aware integration; 1 = brute-force SAT
+ Prove_Params_t Params; // integrated CEC parameters
// information about the target
int nog; // the numbers of gates in the target
Vec_Ptr_t * vNodes; // the gates in the target
@@ -43,16 +48,18 @@ struct CSAT_ManagerStruct_t
CSAT_Target_ResultT * pResult; // the result of solving the target
};
-static CSAT_Target_ResultT * CSAT_TargetResAlloc( int nVars );
-static void CSAT_TargetResFree( CSAT_Target_ResultT * p );
-static char * CSAT_GetNodeName( CSAT_Manager mng, Abc_Obj_t * pNode );
+static CSAT_Target_ResultT * ABC_TargetResAlloc( int nVars );
+static char * ABC_GetNodeName( ABC_Manager mng, Abc_Obj_t * pNode );
+
+// procedures to start and stop the ABC framework
+extern void Abc_Start();
+extern void Abc_Stop();
// some external procedures
-extern Fraig_Man_t * Abc_NtkToFraig( Abc_Ntk_t * pNtk, Fraig_Params_t * pParams, int fAllNodes );
extern int Io_WriteBench( Abc_Ntk_t * pNtk, char * FileName );
////////////////////////////////////////////////////////////////////////
-/// FUNCTION DEFITIONS ///
+/// FUNCTION DEFINITIONS ///
////////////////////////////////////////////////////////////////////////
/**Function*************************************************************
@@ -66,17 +73,24 @@ extern int Io_WriteBench( Abc_Ntk_t * pNtk, char * FileName );
SeeAlso []
***********************************************************************/
-CSAT_Manager CSAT_InitManager()
+ABC_Manager ABC_InitManager()
{
- CSAT_Manager_t * mng;
- mng = ALLOC( CSAT_Manager_t, 1 );
- memset( mng, 0, sizeof(CSAT_Manager_t) );
- mng->pNtk = Abc_NtkAlloc( ABC_TYPE_LOGIC, ABC_FUNC_SOP );
- mng->pNtk->pName = util_strsav("csat_network");
+ ABC_Manager_t * mng;
+ Abc_Start();
+ mng = ALLOC( ABC_Manager_t, 1 );
+ memset( mng, 0, sizeof(ABC_Manager_t) );
+ mng->pNtk = Abc_NtkAlloc( ABC_NTK_LOGIC, ABC_FUNC_SOP, 1 );
+ mng->pNtk->pName = Extra_UtilStrsav("csat_network");
mng->tName2Node = stmm_init_table(strcmp, stmm_strhash);
mng->tNode2Name = stmm_init_table(stmm_ptrcmp, stmm_ptrhash);
+ mng->pMmNames = Extra_MmFlexStart();
mng->vNodes = Vec_PtrAlloc( 100 );
mng->vValues = Vec_IntAlloc( 100 );
+ mng->mode = 0; // set "resource-aware integration" as the default mode
+ // set default parameters for CEC
+ Prove_ParamsSetDefault( &mng->Params );
+ // set infinite resource limit for the final mitering
+// mng->Params.nMiteringLimitLast = ABC_INFINITY;
return mng;
}
@@ -91,40 +105,52 @@ CSAT_Manager CSAT_InitManager()
SeeAlso []
***********************************************************************/
-void CSAT_QuitManager( CSAT_Manager mng )
+void ABC_ReleaseManager( ABC_Manager mng )
{
+ CSAT_Target_ResultT * p_res = ABC_Get_Target_Result( mng,0 );
+ ABC_TargetResFree(p_res);
if ( mng->tNode2Name ) stmm_free_table( mng->tNode2Name );
if ( mng->tName2Node ) stmm_free_table( mng->tName2Node );
+ if ( mng->pMmNames ) Extra_MmFlexStop( mng->pMmNames );
if ( mng->pNtk ) Abc_NtkDelete( mng->pNtk );
if ( mng->pTarget ) Abc_NtkDelete( mng->pTarget );
if ( mng->vNodes ) Vec_PtrFree( mng->vNodes );
if ( mng->vValues ) Vec_IntFree( mng->vValues );
FREE( mng->pDumpFileName );
free( mng );
+ Abc_Stop();
}
/**Function*************************************************************
Synopsis [Sets solver options for learning.]
- Description [0 = baseline; 1 = resource-aware solving.]
+ Description []
SideEffects []
SeeAlso []
***********************************************************************/
-void CSAT_SetSolveOption( CSAT_Manager mng, enum CSAT_OptionT option )
+void ABC_SetSolveOption( ABC_Manager mng, enum CSAT_OptionT option )
{
- mng->mode = option;
- if ( option == 0 )
- printf( "CSAT_SetSolveOption: Setting baseline solving mode.\n" );
- else if ( option == 1 )
- printf( "CSAT_SetSolveOption: Setting resource-aware solving mode.\n" );
- else
- printf( "CSAT_SetSolveOption: Unknown option.\n" );
}
+/**Function*************************************************************
+
+ Synopsis [Sets solving mode by brute-force SAT.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void ABC_UseOnlyCoreSatSolver( ABC_Manager mng )
+{
+ mng->mode = 1; // switch to "brute-force SAT" as the solving option
+}
/**Function*************************************************************
@@ -141,18 +167,24 @@ void CSAT_SetSolveOption( CSAT_Manager mng, enum CSAT_OptionT option )
SeeAlso []
***********************************************************************/
-int CSAT_AddGate( CSAT_Manager mng, enum GateType type, char * name, int nofi, char ** fanins, int dc_attr )
+int ABC_AddGate( ABC_Manager mng, enum GateType type, char * name, int nofi, char ** fanins, int dc_attr )
{
Abc_Obj_t * pObj, * pFanin;
- char * pSop;
+ char * pSop, * pNewName;
int i;
+ // save the name in the local memory manager
+ pNewName = Extra_MmFlexEntryFetch( mng->pMmNames, strlen(name) + 1 );
+ strcpy( pNewName, name );
+ name = pNewName;
+
+ // consider different cases, create the node, and map the node into the name
switch( type )
{
case CSAT_BPI:
case CSAT_BPPI:
if ( nofi != 0 )
- { printf( "CSAT_AddGate: The PI/PPI gate \"%s\" has fanins.\n", name ); return 0; }
+ { printf( "ABC_AddGate: The PI/PPI gate \"%s\" has fanins.\n", name ); return 0; }
// create the PI
pObj = Abc_NtkCreatePi( mng->pNtk );
stmm_insert( mng->tNode2Name, (char *)pObj, name );
@@ -172,7 +204,7 @@ int CSAT_AddGate( CSAT_Manager mng, enum GateType type, char * name, int nofi, c
for ( i = 0; i < nofi; i++ )
{
if ( !stmm_lookup( mng->tName2Node, fanins[i], (char **)&pFanin ) )
- { printf( "CSAT_AddGate: The fanin gate \"%s\" is not in the network.\n", fanins[i] ); return 0; }
+ { printf( "ABC_AddGate: The fanin gate \"%s\" is not in the network.\n", fanins[i] ); return 0; }
Abc_ObjAddFanin( pObj, pFanin );
}
// create the node function
@@ -180,51 +212,51 @@ int CSAT_AddGate( CSAT_Manager mng, enum GateType type, char * name, int nofi, c
{
case CSAT_CONST:
if ( nofi != 0 )
- { printf( "CSAT_AddGate: The constant gate \"%s\" has fanins.\n", name ); return 0; }
+ { printf( "ABC_AddGate: The constant gate \"%s\" has fanins.\n", name ); return 0; }
pSop = Abc_SopCreateConst1( mng->pNtk->pManFunc );
break;
case CSAT_BAND:
if ( nofi < 1 )
- { printf( "CSAT_AddGate: The AND gate \"%s\" no fanins.\n", name ); return 0; }
- pSop = Abc_SopCreateAnd( mng->pNtk->pManFunc, nofi );
+ { printf( "ABC_AddGate: The AND gate \"%s\" no fanins.\n", name ); return 0; }
+ pSop = Abc_SopCreateAnd( mng->pNtk->pManFunc, nofi, NULL );
break;
case CSAT_BNAND:
if ( nofi < 1 )
- { printf( "CSAT_AddGate: The NAND gate \"%s\" no fanins.\n", name ); return 0; }
+ { printf( "ABC_AddGate: The NAND gate \"%s\" no fanins.\n", name ); return 0; }
pSop = Abc_SopCreateNand( mng->pNtk->pManFunc, nofi );
break;
case CSAT_BOR:
if ( nofi < 1 )
- { printf( "CSAT_AddGate: The OR gate \"%s\" no fanins.\n", name ); return 0; }
+ { printf( "ABC_AddGate: The OR gate \"%s\" no fanins.\n", name ); return 0; }
pSop = Abc_SopCreateOr( mng->pNtk->pManFunc, nofi, NULL );
break;
case CSAT_BNOR:
if ( nofi < 1 )
- { printf( "CSAT_AddGate: The NOR gate \"%s\" no fanins.\n", name ); return 0; }
+ { printf( "ABC_AddGate: The NOR gate \"%s\" no fanins.\n", name ); return 0; }
pSop = Abc_SopCreateNor( mng->pNtk->pManFunc, nofi );
break;
case CSAT_BXOR:
if ( nofi < 1 )
- { printf( "CSAT_AddGate: The XOR gate \"%s\" no fanins.\n", name ); return 0; }
+ { printf( "ABC_AddGate: The XOR gate \"%s\" no fanins.\n", name ); return 0; }
if ( nofi > 2 )
- { printf( "CSAT_AddGate: The XOR gate \"%s\" has more than two fanins.\n", name ); return 0; }
+ { printf( "ABC_AddGate: The XOR gate \"%s\" has more than two fanins.\n", name ); return 0; }
pSop = Abc_SopCreateXor( mng->pNtk->pManFunc, nofi );
break;
case CSAT_BXNOR:
if ( nofi < 1 )
- { printf( "CSAT_AddGate: The XNOR gate \"%s\" no fanins.\n", name ); return 0; }
+ { printf( "ABC_AddGate: The XNOR gate \"%s\" no fanins.\n", name ); return 0; }
if ( nofi > 2 )
- { printf( "CSAT_AddGate: The XNOR gate \"%s\" has more than two fanins.\n", name ); return 0; }
+ { printf( "ABC_AddGate: The XNOR gate \"%s\" has more than two fanins.\n", name ); return 0; }
pSop = Abc_SopCreateNxor( mng->pNtk->pManFunc, nofi );
break;
case CSAT_BINV:
if ( nofi != 1 )
- { printf( "CSAT_AddGate: The inverter gate \"%s\" does not have exactly one fanin.\n", name ); return 0; }
+ { printf( "ABC_AddGate: The inverter gate \"%s\" does not have exactly one fanin.\n", name ); return 0; }
pSop = Abc_SopCreateInv( mng->pNtk->pManFunc );
break;
case CSAT_BBUF:
if ( nofi != 1 )
- { printf( "CSAT_AddGate: The buffer gate \"%s\" does not have exactly one fanin.\n", name ); return 0; }
+ { printf( "ABC_AddGate: The buffer gate \"%s\" does not have exactly one fanin.\n", name ); return 0; }
pSop = Abc_SopCreateBuf( mng->pNtk->pManFunc );
break;
default :
@@ -235,66 +267,85 @@ int CSAT_AddGate( CSAT_Manager mng, enum GateType type, char * name, int nofi, c
case CSAT_BPPO:
case CSAT_BPO:
if ( nofi != 1 )
- { printf( "CSAT_AddGate: The PO/PPO gate \"%s\" does not have exactly one fanin.\n", name ); return 0; }
+ { printf( "ABC_AddGate: The PO/PPO gate \"%s\" does not have exactly one fanin.\n", name ); return 0; }
// create the PO
pObj = Abc_NtkCreatePo( mng->pNtk );
stmm_insert( mng->tNode2Name, (char *)pObj, name );
// connect to the PO fanin
if ( !stmm_lookup( mng->tName2Node, fanins[0], (char **)&pFanin ) )
- { printf( "CSAT_AddGate: The fanin gate \"%s\" is not in the network.\n", fanins[0] ); return 0; }
+ { printf( "ABC_AddGate: The fanin gate \"%s\" is not in the network.\n", fanins[0] ); return 0; }
Abc_ObjAddFanin( pObj, pFanin );
break;
default:
- printf( "CSAT_AddGate: Unknown gate type.\n" );
+ printf( "ABC_AddGate: Unknown gate type.\n" );
break;
}
+
+ // map the name into the node
if ( stmm_insert( mng->tName2Node, name, (char *)pObj ) )
- { printf( "CSAT_AddGate: The same gate \"%s\" is added twice.\n", name ); return 0; }
+ { printf( "ABC_AddGate: The same gate \"%s\" is added twice.\n", name ); return 0; }
return 1;
}
/**Function*************************************************************
- Synopsis [Checks integraty of the manager.]
+ Synopsis [This procedure also finalizes construction of the ABC network.]
- Description [Checks if there are gates that are not used by any primary output.
- If no such gates exist, return 1 else return 0.]
+ Description []
SideEffects []
SeeAlso []
***********************************************************************/
-int CSAT_Check_Integrity( CSAT_Manager mng )
+void ABC_Network_Finalize( ABC_Manager mng )
{
Abc_Ntk_t * pNtk = mng->pNtk;
Abc_Obj_t * pObj;
int i;
-
- // this procedure also finalizes construction of the ABC network
- Abc_NtkFixNonDrivenNets( pNtk );
Abc_NtkForEachPi( pNtk, pObj, i )
- Abc_NtkLogicStoreName( pObj, CSAT_GetNodeName(mng, pObj) );
+ Abc_ObjAssignName( pObj, ABC_GetNodeName(mng, pObj), NULL );
Abc_NtkForEachPo( pNtk, pObj, i )
- Abc_NtkLogicStoreName( pObj, CSAT_GetNodeName(mng, pObj) );
+ Abc_ObjAssignName( pObj, ABC_GetNodeName(mng, pObj), NULL );
assert( Abc_NtkLatchNum(pNtk) == 0 );
+}
- // make sure everything is okay with the network structure
- if ( !Abc_NtkCheckRead( pNtk ) )
- {
- printf( "CSAT_Check_Integrity: The internal network check has failed.\n" );
- return 0;
- }
+/**Function*************************************************************
+
+ Synopsis [Checks integraty of the manager.]
+
+ Description [Checks if there are gates that are not used by any primary output.
+ If no such gates exist, return 1 else return 0.]
+
+ SideEffects []
- // check that there is no dangling nodes
+ SeeAlso []
+
+***********************************************************************/
+int ABC_Check_Integrity( ABC_Manager mng )
+{
+ Abc_Ntk_t * pNtk = mng->pNtk;
+ Abc_Obj_t * pObj;
+ int i;
+
+ // check that there are no dangling nodes
Abc_NtkForEachNode( pNtk, pObj, i )
{
+ if ( i == 0 )
+ continue;
if ( Abc_ObjFanoutNum(pObj) == 0 )
{
- printf( "CSAT_Check_Integrity: The network has dangling nodes.\n" );
+// printf( "ABC_Check_Integrity: The network has dangling nodes.\n" );
return 0;
}
}
+
+ // make sure everything is okay with the network structure
+ if ( !Abc_NtkDoCheck( pNtk ) )
+ {
+ printf( "ABC_Check_Integrity: The internal network check has failed.\n" );
+ return 0;
+ }
return 1;
}
@@ -309,9 +360,9 @@ int CSAT_Check_Integrity( CSAT_Manager mng )
SeeAlso []
***********************************************************************/
-void CSAT_SetTimeLimit( CSAT_Manager mng, int runtime )
+void ABC_SetTimeLimit( ABC_Manager mng, int runtime )
{
- printf( "CSAT_SetTimeLimit: The resource limit is not implemented (warning).\n" );
+// printf( "ABC_SetTimeLimit: The resource limit is not implemented (warning).\n" );
}
/**Function*************************************************************
@@ -325,9 +376,9 @@ void CSAT_SetTimeLimit( CSAT_Manager mng, int runtime )
SeeAlso []
***********************************************************************/
-void CSAT_SetLearnLimit( CSAT_Manager mng, int num )
+void ABC_SetLearnLimit( ABC_Manager mng, int num )
{
- printf( "CSAT_SetLearnLimit: The resource limit is not implemented (warning).\n" );
+// printf( "ABC_SetLearnLimit: The resource limit is not implemented (warning).\n" );
}
/**Function*************************************************************
@@ -341,9 +392,9 @@ void CSAT_SetLearnLimit( CSAT_Manager mng, int num )
SeeAlso []
***********************************************************************/
-void CSAT_SetSolveBacktrackLimit( CSAT_Manager mng, int num )
+void ABC_SetLearnBacktrackLimit( ABC_Manager mng, int num )
{
- printf( "CSAT_SetSolveBacktrackLimit: The resource limit is not implemented (warning).\n" );
+// printf( "ABC_SetLearnBacktrackLimit: The resource limit is not implemented (warning).\n" );
}
/**Function*************************************************************
@@ -357,9 +408,88 @@ void CSAT_SetSolveBacktrackLimit( CSAT_Manager mng, int num )
SeeAlso []
***********************************************************************/
-void CSAT_SetLearnBacktrackLimit( CSAT_Manager mng, int num )
+void ABC_SetSolveBacktrackLimit( ABC_Manager mng, int num )
{
- printf( "CSAT_SetLearnBacktrackLimit: The resource limit is not implemented (warning).\n" );
+ mng->Params.nMiteringLimitLast = num;
+}
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void ABC_SetSolveImplicationLimit( ABC_Manager mng, int num )
+{
+// printf( "ABC_SetSolveImplicationLimit: The resource limit is not implemented (warning).\n" );
+}
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void ABC_SetTotalBacktrackLimit( ABC_Manager mng, uint64 num )
+{
+ mng->Params.nTotalBacktrackLimit = num;
+}
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void ABC_SetTotalInspectLimit( ABC_Manager mng, uint64 num )
+{
+ mng->Params.nTotalInspectLimit = num;
+}
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+uint64 ABC_GetTotalBacktracksMade( ABC_Manager mng )
+{
+ return mng->Params.nTotalBacktracksMade;
+}
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+uint64 ABC_GetTotalInspectsMade( ABC_Manager mng )
+{
+ return mng->Params.nTotalInspectsMade;
}
/**Function*************************************************************
@@ -373,10 +503,10 @@ void CSAT_SetLearnBacktrackLimit( CSAT_Manager mng, int num )
SeeAlso []
***********************************************************************/
-void CSAT_EnableDump( CSAT_Manager mng, char * dump_file )
+void ABC_EnableDump( ABC_Manager mng, char * dump_file )
{
FREE( mng->pDumpFileName );
- mng->pDumpFileName = util_strsav( dump_file );
+ mng->pDumpFileName = Extra_UtilStrsav( dump_file );
}
/**Function*************************************************************
@@ -394,12 +524,12 @@ void CSAT_EnableDump( CSAT_Manager mng, char * dump_file )
SeeAlso []
***********************************************************************/
-int CSAT_AddTarget( CSAT_Manager mng, int nog, char ** names, int * values )
+int ABC_AddTarget( ABC_Manager mng, int nog, char ** names, int * values )
{
Abc_Obj_t * pObj;
int i;
if ( nog < 1 )
- { printf( "CSAT_AddTarget: The target has no gates.\n" ); return 0; }
+ { printf( "ABC_AddTarget: The target has no gates.\n" ); return 0; }
// clear storage for the target
mng->nog = 0;
Vec_PtrClear( mng->vNodes );
@@ -408,10 +538,10 @@ int CSAT_AddTarget( CSAT_Manager mng, int nog, char ** names, int * values )
for ( i = 0; i < nog; i++ )
{
if ( !stmm_lookup( mng->tName2Node, names[i], (char **)&pObj ) )
- { printf( "CSAT_AddTarget: The target gate \"%s\" is not in the network.\n", names[i] ); return 0; }
+ { printf( "ABC_AddTarget: The target gate \"%s\" is not in the network.\n", names[i] ); return 0; }
Vec_PtrPush( mng->vNodes, pObj );
if ( values[i] < 0 || values[i] > 1 )
- { printf( "CSAT_AddTarget: The value of gate \"%s\" is not 0 or 1.\n", names[i] ); return 0; }
+ { printf( "ABC_AddTarget: The value of gate \"%s\" is not 0 or 1.\n", names[i] ); return 0; }
Vec_IntPush( mng->vValues, values[i] );
}
mng->nog = nog;
@@ -423,50 +553,26 @@ int CSAT_AddTarget( CSAT_Manager mng, int nog, char ** names, int * values )
Synopsis [Initialize the solver internal data structure.]
Description [Prepares the solver to work on one specific target
- set by calling CSAT_AddTarget before.]
+ set by calling ABC_AddTarget before.]
SideEffects []
SeeAlso []
***********************************************************************/
-void CSAT_SolveInit( CSAT_Manager mng )
+void ABC_SolveInit( ABC_Manager mng )
{
- Fraig_Params_t * pParams = &mng->Params;
- int nWords1, nWords2, nWordsMin;
-
// check if the target is available
assert( mng->nog == Vec_PtrSize(mng->vNodes) );
if ( mng->nog == 0 )
- { printf( "CSAT_SolveInit: Target is not specified by CSAT_AddTarget().\n" ); return; }
+ { printf( "ABC_SolveInit: Target is not specified by ABC_AddTarget().\n" ); return; }
// free the previous target network if present
if ( mng->pTarget ) Abc_NtkDelete( mng->pTarget );
// set the new target network
- mng->pTarget = Abc_NtkCreateCone( mng->pNtk, mng->vNodes, mng->vValues );
-
- // to determine the number of simulation patterns
- // use the following strategy
- // at least 64 words (32 words random and 32 words dynamic)
- // no more than 256M for one circuit (128M + 128M)
- nWords1 = 32;
- nWords2 = (1<<27) / (Abc_NtkNodeNum(mng->pTarget) + Abc_NtkCiNum(mng->pTarget));
- nWordsMin = ABC_MIN( nWords1, nWords2 );
-
- // set parameters for fraiging
- memset( pParams, 0, sizeof(Fraig_Params_t) );
- pParams->nPatsRand = nWordsMin * 32; // the number of words of random simulation info
- pParams->nPatsDyna = nWordsMin * 32; // the number of words of dynamic simulation info
- pParams->nBTLimit = 99; // the max number of backtracks to perform at a node
- pParams->fFuncRed = mng->mode; // performs only one level hashing
- pParams->fFeedBack = 1; // enables solver feedback
- pParams->fDist1Pats = 1; // enables distance-1 patterns
- pParams->fDoSparse = 0; // performs equiv tests for sparse functions
- pParams->fChoicing = 0; // enables recording structural choices
- pParams->fTryProve = 1; // tries to solve the final miter
- pParams->fVerbose = 0; // the verbosiness flag
- pParams->fVerboseP = 0; // the verbosiness flag for proof reporting
+// mng->pTarget = Abc_NtkCreateTarget( mng->pNtk, mng->vNodes, mng->vValues );
+ mng->pTarget = Abc_NtkStrash( mng->pNtk, 0, 1, 0 );
}
/**Function*************************************************************
@@ -480,13 +586,13 @@ void CSAT_SolveInit( CSAT_Manager mng )
SeeAlso []
***********************************************************************/
-void CSAT_AnalyzeTargets( CSAT_Manager mng )
+void ABC_AnalyzeTargets( ABC_Manager mng )
{
}
/**Function*************************************************************
- Synopsis [Solves the targets added by CSAT_AddTarget().]
+ Synopsis [Solves the targets added by ABC_AddTarget().]
Description []
@@ -495,23 +601,24 @@ void CSAT_AnalyzeTargets( CSAT_Manager mng )
SeeAlso []
***********************************************************************/
-enum CSAT_StatusT CSAT_Solve( CSAT_Manager mng )
+enum CSAT_StatusT ABC_Solve( ABC_Manager mng )
{
- Fraig_Man_t * pMan;
- int * pModel;
+ Prove_Params_t * pParams = &mng->Params;
int RetValue, i;
// check if the target network is available
if ( mng->pTarget == NULL )
- { printf( "CSAT_Solve: Target network is not derived by CSAT_SolveInit().\n" ); return UNDETERMINED; }
+ { printf( "ABC_Solve: Target network is not derived by ABC_SolveInit().\n" ); return UNDETERMINED; }
- // transform the target into a fraig
- pMan = Abc_NtkToFraig( mng->pTarget, &mng->Params, 0 );
- Fraig_ManProveMiter( pMan );
+ // try to prove the miter using a number of techniques
+ if ( mng->mode )
+ RetValue = Abc_NtkMiterSat( mng->pTarget, (sint64)pParams->nMiteringLimitLast, (sint64)0, 0, NULL, NULL );
+ else
+// RetValue = Abc_NtkMiterProve( &mng->pTarget, pParams ); // old CEC engine
+ RetValue = Abc_NtkIvyProve( &mng->pTarget, pParams ); // new CEC engine
// analyze the result
- mng->pResult = CSAT_TargetResAlloc( Abc_NtkCiNum(mng->pTarget) );
- RetValue = Fraig_ManCheckMiter( pMan );
+ mng->pResult = ABC_TargetResAlloc( Abc_NtkCiNum(mng->pTarget) );
if ( RetValue == -1 )
mng->pResult->status = UNDETERMINED;
else if ( RetValue == 1 )
@@ -519,20 +626,16 @@ enum CSAT_StatusT CSAT_Solve( CSAT_Manager mng )
else if ( RetValue == 0 )
{
mng->pResult->status = SATISFIABLE;
- pModel = Fraig_ManReadModel( pMan );
- assert( pModel != NULL );
// create the array of PI names and values
for ( i = 0; i < mng->pResult->no_sig; i++ )
{
- mng->pResult->names[i] = CSAT_GetNodeName(mng, Abc_NtkCi(mng->pNtk, i)); // returns the same string that was given
- mng->pResult->values[i] = pModel[i];
+ mng->pResult->names[i] = Extra_UtilStrsav( ABC_GetNodeName(mng, Abc_NtkCi(mng->pNtk, i)) );
+ mng->pResult->values[i] = mng->pTarget->pModel[i];
}
+ FREE( mng->pTarget->pModel );
}
- else
- assert( 0 );
+ else assert( 0 );
- // delete the fraig manager
- Fraig_ManFree( pMan );
// delete the target
Abc_NtkDelete( mng->pTarget );
mng->pTarget = NULL;
@@ -544,38 +647,40 @@ enum CSAT_StatusT CSAT_Solve( CSAT_Manager mng )
Synopsis [Gets the solve status of a target.]
- Description [TargetID: the target id returned by CSAT_AddTarget().]
+ Description [TargetID: the target id returned by ABC_AddTarget().]
SideEffects []
SeeAlso []
***********************************************************************/
-CSAT_Target_ResultT * CSAT_Get_Target_Result( CSAT_Manager mng, int TargetID )
+CSAT_Target_ResultT * ABC_Get_Target_Result( ABC_Manager mng, int TargetID )
{
return mng->pResult;
}
/**Function*************************************************************
- Synopsis [Dumps the target AIG into the BENCH file.]
+ Synopsis [Dumps the original network into the BENCH file.]
- Description []
+ Description [This procedure should be modified to dump the target.]
SideEffects []
- SeeAlso []
+ SeeAlso []
***********************************************************************/
-void CSAT_Dump_Bench_File( CSAT_Manager mng )
+void ABC_Dump_Bench_File( ABC_Manager mng )
{
- Abc_Ntk_t * pNtkTemp;
+ Abc_Ntk_t * pNtkTemp, * pNtkAig;
char * pFileName;
-
+
// derive the netlist
- pNtkTemp = Abc_NtkLogicToNetlistBench( mng->pTarget );
+ pNtkAig = Abc_NtkStrash( mng->pNtk, 0, 0, 0 );
+ pNtkTemp = Abc_NtkToNetlistBench( pNtkAig );
+ Abc_NtkDelete( pNtkAig );
if ( pNtkTemp == NULL )
- { printf( "CSAT_Dump_Bench_File: Dumping BENCH has failed.\n" ); return; }
+ { printf( "ABC_Dump_Bench_File: Dumping BENCH has failed.\n" ); return; }
pFileName = mng->pDumpFileName? mng->pDumpFileName: "abc_test.bench";
Io_WriteBench( pNtkTemp, pFileName );
Abc_NtkDelete( pNtkTemp );
@@ -594,7 +699,7 @@ void CSAT_Dump_Bench_File( CSAT_Manager mng )
SeeAlso []
***********************************************************************/
-CSAT_Target_ResultT * CSAT_TargetResAlloc( int nVars )
+CSAT_Target_ResultT * ABC_TargetResAlloc( int nVars )
{
CSAT_Target_ResultT * p;
p = ALLOC( CSAT_Target_ResultT, 1 );
@@ -618,10 +723,18 @@ CSAT_Target_ResultT * CSAT_TargetResAlloc( int nVars )
SeeAlso []
***********************************************************************/
-void CSAT_TargetResFree( CSAT_Target_ResultT * p )
+void ABC_TargetResFree( CSAT_Target_ResultT * p )
{
if ( p == NULL )
return;
+ if( p->names )
+ {
+ int i = 0;
+ for ( i = 0; i < p->no_sig; i++ )
+ {
+ FREE(p->names[i]);
+ }
+ }
FREE( p->names );
FREE( p->values );
free( p );
@@ -638,7 +751,7 @@ void CSAT_TargetResFree( CSAT_Target_ResultT * p )
SeeAlso []
***********************************************************************/
-char * CSAT_GetNodeName( CSAT_Manager mng, Abc_Obj_t * pNode )
+char * ABC_GetNodeName( ABC_Manager mng, Abc_Obj_t * pNode )
{
char * pName = NULL;
if ( !stmm_lookup( mng->tNode2Name, (char *)pNode, (char **)&pName ) )
@@ -648,6 +761,7 @@ char * CSAT_GetNodeName( CSAT_Manager mng, Abc_Obj_t * pNode )
return pName;
}
+
////////////////////////////////////////////////////////////////////////
/// END OF FILE ///
////////////////////////////////////////////////////////////////////////
diff --git a/src/sat/csat/csat_apis.h b/src/sat/csat/csat_apis.h
index 124ca266..b80eddbf 100644
--- a/src/sat/csat/csat_apis.h
+++ b/src/sat/csat/csat_apis.h
@@ -12,12 +12,16 @@
Date [Ver. 1.0. Started - August 28, 2005]
- Revision [$Id: csat_apis.h,v 1.00 2005/08/28 00:00:00 alanmi Exp $]
+ Revision [$Id: csat_apis.h,v 1.5 2005/12/30 10:54:40 rmukherj Exp $]
***********************************************************************/
-#ifndef __CSAT_APIS_H__
-#define __CSAT_APIS_H__
+#ifndef __ABC_APIS_H__
+#define __ABC_APIS_H__
+
+#ifdef __cplusplus
+extern "C" {
+#endif
////////////////////////////////////////////////////////////////////////
/// INCLUDES ///
@@ -32,36 +36,44 @@
////////////////////////////////////////////////////////////////////////
-typedef struct CSAT_ManagerStruct_t CSAT_Manager_t;
-typedef struct CSAT_ManagerStruct_t * CSAT_Manager;
+typedef struct ABC_ManagerStruct_t ABC_Manager_t;
+typedef struct ABC_ManagerStruct_t * ABC_Manager;
// GateType defines the gate type that can be added to circuit by
-// CSAT_AddGate();
-#ifndef _CSAT_GATE_TYPE_
-#define _CSAT_GATE_TYPE_
+// ABC_AddGate();
+#ifndef _ABC_GATE_TYPE_
+#define _ABC_GATE_TYPE_
enum GateType
{
CSAT_CONST = 0, // constant gate
- CSAT_BPI, // boolean PI
- CSAT_BPPI, // bit level PSEUDO PRIMARY INPUT
- CSAT_BAND, // bit level AND
- CSAT_BNAND, // bit level NAND
- CSAT_BOR, // bit level OR
- CSAT_BNOR, // bit level NOR
- CSAT_BXOR, // bit level XOR
- CSAT_BXNOR, // bit level XNOR
- CSAT_BINV, // bit level INVERTER
- CSAT_BBUF, // bit level BUFFER
- CSAT_BPPO, // bit level PSEUDO PRIMARY OUTPUT
- CSAT_BPO // boolean PO
+ CSAT_BPI, // boolean PI
+ CSAT_BPPI, // bit level PSEUDO PRIMARY INPUT
+ CSAT_BAND, // bit level AND
+ CSAT_BNAND, // bit level NAND
+ CSAT_BOR, // bit level OR
+ CSAT_BNOR, // bit level NOR
+ CSAT_BXOR, // bit level XOR
+ CSAT_BXNOR, // bit level XNOR
+ CSAT_BINV, // bit level INVERTER
+ CSAT_BBUF, // bit level BUFFER
+ CSAT_BMUX, // bit level MUX --not supported
+ CSAT_BDFF, // bit level D-type FF
+ CSAT_BSDFF, // bit level scan FF --not supported
+ CSAT_BTRIH, // bit level TRISTATE gate with active high control --not supported
+ CSAT_BTRIL, // bit level TRISTATE gate with active low control --not supported
+ CSAT_BBUS, // bit level BUS --not supported
+ CSAT_BPPO, // bit level PSEUDO PRIMARY OUTPUT
+ CSAT_BPO, // boolean PO
+ CSAT_BCNF, // boolean constraint
+ CSAT_BDC, // boolean don't care gate (2 input)
};
#endif
-//CSAT_StatusT defines the return value by CSAT_Solve();
-#ifndef _CSAT_STATUS_
-#define _CSAT_STATUS_
+//CSAT_StatusT defines the return value by ABC_Solve();
+#ifndef _ABC_STATUS_
+#define _ABC_STATUS_
enum CSAT_StatusT
{
UNDETERMINED = 0,
@@ -76,10 +88,22 @@ enum CSAT_StatusT
#endif
+// to identify who called the CSAT solver
+#ifndef _ABC_CALLER_
+#define _ABC_CALLER_
+enum CSAT_CallerT
+{
+ BLS = 0,
+ SATORI,
+ NONE
+};
+#endif
+
+
// CSAT_OptionT defines the solver option about learning
-// which is used by CSAT_SetSolveOption();
-#ifndef _CSAT_OPTION_
-#define _CSAT_OPTION_
+// which is used by ABC_SetSolveOption();
+#ifndef _ABC_OPTION_
+#define _ABC_OPTION_
enum CSAT_OptionT
{
BASE_LINE = 0,
@@ -89,8 +113,8 @@ enum CSAT_OptionT
#endif
-#ifndef _CSAT_Target_Result
-#define _CSAT_Target_Result
+#ifndef _ABC_Target_Result
+#define _ABC_Target_Result
typedef struct _CSAT_Target_ResultT CSAT_Target_ResultT;
struct _CSAT_Target_ResultT
{
@@ -114,14 +138,21 @@ struct _CSAT_Target_ResultT
#endif
////////////////////////////////////////////////////////////////////////
-/// FUNCTION DEFITIONS ///
+/// FUNCTION DEFINITIONS ///
////////////////////////////////////////////////////////////////////////
// create a new manager
-extern CSAT_Manager CSAT_InitManager(void);
+extern ABC_Manager ABC_InitManager(void);
+
+// release a manager
+extern void ABC_ReleaseManager(ABC_Manager mng);
// set solver options for learning
-extern void CSAT_SetSolveOption(CSAT_Manager mng, enum CSAT_OptionT option);
+extern void ABC_SetSolveOption(ABC_Manager mng, enum CSAT_OptionT option);
+
+// enable checking by brute-force SAT solver (MiniSat-1.14)
+extern void ABC_UseOnlyCoreSatSolver(ABC_Manager mng);
+
// add a gate to the circuit
// the meaning of the parameters are:
@@ -129,46 +160,63 @@ extern void CSAT_SetSolveOption(CSAT_Manager mng, enum CSAT_Opt
// name: the name of the gate to be added, name should be unique in a circuit.
// nofi: number of fanins of the gate to be added;
// fanins: the name array of fanins of the gate to be added
-extern int CSAT_AddGate(CSAT_Manager mng,
- enum GateType type,
- char* name,
- int nofi,
- char** fanins,
- int dc_attr);
+extern int ABC_AddGate(ABC_Manager mng,
+ enum GateType type,
+ char* name,
+ int nofi,
+ char** fanins,
+ int dc_attr);
// check if there are gates that are not used by any primary ouput.
// if no such gates exist, return 1 else return 0;
-extern int CSAT_Check_Integrity(CSAT_Manager mng);
+extern int ABC_Check_Integrity(ABC_Manager mng);
+
+// THIS PROCEDURE SHOULD BE CALLED AFTER THE NETWORK IS CONSTRUCTED!!!
+extern void ABC_Network_Finalize( ABC_Manager mng );
// set time limit for solving a target.
// runtime: time limit (in second).
-extern void CSAT_SetTimeLimit(CSAT_Manager mng, int runtime);
-extern void CSAT_SetLearnLimit(CSAT_Manager mng, int num);
-extern void CSAT_SetSolveBacktrackLimit(CSAT_Manager mng, int num);
-extern void CSAT_SetLearnBacktrackLimit(CSAT_Manager mng, int num);
-extern void CSAT_EnableDump(CSAT_Manager mng, char* dump_file);
+extern void ABC_SetTimeLimit(ABC_Manager mng, int runtime);
+extern void ABC_SetLearnLimit(ABC_Manager mng, int num);
+extern void ABC_SetSolveBacktrackLimit(ABC_Manager mng, int num);
+extern void ABC_SetLearnBacktrackLimit(ABC_Manager mng, int num);
+extern void ABC_EnableDump(ABC_Manager mng, char* dump_file);
+
+extern void ABC_SetTotalBacktrackLimit( ABC_Manager mng, uint64 num );
+extern void ABC_SetTotalInspectLimit( ABC_Manager mng, uint64 num );
+extern uint64 ABC_GetTotalBacktracksMade( ABC_Manager mng );
+extern uint64 ABC_GetTotalInspectsMade( ABC_Manager mng );
// the meaning of the parameters are:
// nog: number of gates that are in the targets
// names: name array of gates
// values: value array of the corresponding gates given in "names" to be
// solved. the relation of them is AND.
-extern int CSAT_AddTarget(CSAT_Manager mng, int nog, char**names, int* values);
+extern int ABC_AddTarget(ABC_Manager mng, int nog, char**names, int* values);
// initialize the solver internal data structure.
-extern void CSAT_SolveInit(CSAT_Manager mng);
-extern void CSAT_AnalyzeTargets(CSAT_Manager mng);
+extern void ABC_SolveInit(ABC_Manager mng);
+extern void ABC_AnalyzeTargets(ABC_Manager mng);
-// solve the targets added by CSAT_AddTarget()
-extern enum CSAT_StatusT CSAT_Solve(CSAT_Manager mng);
+// solve the targets added by ABC_AddTarget()
+extern enum CSAT_StatusT ABC_Solve(ABC_Manager mng);
// get the solve status of a target
-// TargetID: the target id returned by CSAT_AddTarget().
-extern CSAT_Target_ResultT * CSAT_Get_Target_Result(CSAT_Manager mng, int TargetID);
-extern void CSAT_Dump_Bench_File(CSAT_Manager mng);
+// TargetID: the target id returned by ABC_AddTarget().
+extern CSAT_Target_ResultT * ABC_Get_Target_Result(ABC_Manager mng, int TargetID);
+extern void ABC_Dump_Bench_File(ABC_Manager mng);
+
+// ADDED PROCEDURES:
+extern void ABC_TargetResFree( CSAT_Target_ResultT * p );
+
+extern void CSAT_SetCaller(ABC_Manager mng, enum CSAT_CallerT caller);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
////////////////////////////////////////////////////////////////////////
/// END OF FILE ///
////////////////////////////////////////////////////////////////////////
-
-#endif
diff --git a/src/sat/fraig/fraig.h b/src/sat/fraig/fraig.h
index 901bbac9..1dad21e2 100644
--- a/src/sat/fraig/fraig.h
+++ b/src/sat/fraig/fraig.h
@@ -18,11 +18,26 @@
#ifndef __FRAIG_H__
#define __FRAIG_H__
-
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
////////////////////////////////////////////////////////////////////////
/// INCLUDES ///
////////////////////////////////////////////////////////////////////////
+#ifndef SINT64
+#define SINT64
+
+#ifdef _WIN32
+typedef signed __int64 sint64; // compatible with MS VS 6.0
+#else
+typedef long long sint64;
+#endif
+
+#endif
+
////////////////////////////////////////////////////////////////////////
/// PARAMETERS ///
////////////////////////////////////////////////////////////////////////
@@ -37,12 +52,14 @@ 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
@@ -52,6 +69,39 @@ struct Fraig_ParamsStruct_t_
int fVerbose; // the verbosiness flag
int fVerboseP; // the verbosiness flag (for proof reporting)
int fInternal; // is set to 1 for internal fraig calls
+ int nConfLimit; // the limit on the number of conflicts
+ sint64 nInspLimit; // the limit on the number of inspections
+};
+
+struct Prove_ParamsStruct_t_
+{
+ // general parameters
+ int fUseFraiging; // enables fraiging
+ int fUseRewriting; // enables rewriting
+ int fUseBdds; // enables BDD construction when other methods fail
+ int fVerbose; // prints verbose stats
+ // iterations
+ int nItersMax; // the number of iterations
+ // mitering
+ int nMiteringLimitStart; // starting mitering limit
+ float nMiteringLimitMulti; // multiplicative coefficient to increase the limit in each iteration
+ // rewriting
+ int nRewritingLimitStart; // the number of rewriting iterations
+ float nRewritingLimitMulti; // multiplicative coefficient to increase the limit in each iteration
+ // fraiging
+ int nFraigingLimitStart; // starting backtrack(conflict) limit
+ float nFraigingLimitMulti; // multiplicative coefficient to increase the limit in each iteration
+ // last-gasp BDD construction
+ int nBddSizeLimit; // the number of BDD nodes when construction is aborted
+ int fBddReorder; // enables dynamic BDD variable reordering
+ // last-gasp mitering
+ int nMiteringLimitLast; // final mitering limit
+ // global SAT solver limits
+ sint64 nTotalBacktrackLimit; // global limit on the number of backtracks
+ sint64 nTotalInspectLimit; // global limit on the number of clause inspects
+ // global resources applied
+ sint64 nTotalBacktracksMade; // the total number of backtracks made
+ sint64 nTotalInspectsMade; // the total number of inspects made
};
////////////////////////////////////////////////////////////////////////
@@ -59,14 +109,14 @@ struct Fraig_ParamsStruct_t_
////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////
-/// MACRO DEFITIONS ///
+/// MACRO DEFINITIONS ///
////////////////////////////////////////////////////////////////////////
// macros working with complemented attributes of the nodes
-#define Fraig_IsComplement(p) (((int)((long) (p) & 01)))
-#define Fraig_Regular(p) ((Fraig_Node_t *)((unsigned)(p) & ~01))
-#define Fraig_Not(p) ((Fraig_Node_t *)((long)(p) ^ 01))
-#define Fraig_NotCond(p,c) ((Fraig_Node_t *)((long)(p) ^ (c)))
+#define Fraig_IsComplement(p) (((int)((unsigned long) (p) & 01)))
+#define Fraig_Regular(p) ((Fraig_Node_t *)((unsigned long)(p) & ~01))
+#define Fraig_Not(p) ((Fraig_Node_t *)((unsigned long)(p) ^ 01))
+#define Fraig_NotCond(p,c) ((Fraig_Node_t *)((unsigned long)(p) ^ (c)))
// these are currently not used
#define Fraig_Ref(p)
@@ -74,7 +124,7 @@ struct Fraig_ParamsStruct_t_
#define Fraig_RecursiveDeref(p,c)
////////////////////////////////////////////////////////////////////////
-/// FUNCTION DEFITIONS ///
+/// FUNCTION DEFINITIONS ///
////////////////////////////////////////////////////////////////////////
/*=== fraigApi.c =============================================================*/
@@ -103,6 +153,9 @@ 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 );
@@ -147,10 +200,15 @@ extern Fraig_Node_t * Fraig_NodeMux( Fraig_Man_t * p, Fraig_Node_t * pNode,
extern void Fraig_NodeSetChoice( Fraig_Man_t * pMan, Fraig_Node_t * pNodeOld, Fraig_Node_t * pNodeNew );
/*=== fraigMan.c =============================================================*/
+extern void Prove_ParamsSetDefault( Prove_Params_t * pParams );
extern void Fraig_ParamsSetDefault( Fraig_Params_t * pParams );
+extern void Fraig_ParamsSetDefaultFull( Fraig_Params_t * pParams );
extern Fraig_Man_t * Fraig_ManCreate( Fraig_Params_t * pParams );
extern void Fraig_ManFree( Fraig_Man_t * pMan );
extern void Fraig_ManPrintStats( Fraig_Man_t * p );
+extern Fraig_NodeVec_t * Fraig_ManGetSimInfo( Fraig_Man_t * p );
+extern int Fraig_ManCheckClauseUsingSimInfo( Fraig_Man_t * p, Fraig_Node_t * pNode1, Fraig_Node_t * pNode2 );
+extern void Fraig_ManAddClause( Fraig_Man_t * p, Fraig_Node_t ** ppNodes, int nNodes );
/*=== fraigDfs.c =============================================================*/
extern Fraig_NodeVec_t * Fraig_Dfs( Fraig_Man_t * pMan, int fEquiv );
@@ -162,10 +220,11 @@ extern int Fraig_CheckTfi( Fraig_Man_t * pMan, Fraig_Node_t * pO
extern int Fraig_CountLevels( Fraig_Man_t * pMan );
/*=== fraigSat.c =============================================================*/
-extern int Fraig_NodesAreEqual( Fraig_Man_t * p, Fraig_Node_t * pNode1, Fraig_Node_t * pNode2, int nBTLimit );
-extern int Fraig_NodeIsEquivalent( Fraig_Man_t * p, Fraig_Node_t * pOld, Fraig_Node_t * pNew, int nBTLimit );
+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 );
@@ -200,4 +259,9 @@ extern Fraig_NodeVec_t * Fraig_CollectSupergate( Fraig_Node_t * pNode, int fSt
////////////////////////////////////////////////////////////////////////
/// END OF FILE ///
////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
+
#endif
diff --git a/src/sat/fraig/fraigApi.c b/src/sat/fraig/fraigApi.c
index b92f6afd..79a7c224 100644
--- a/src/sat/fraig/fraigApi.c
+++ b/src/sat/fraig/fraigApi.c
@@ -23,7 +23,7 @@
////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////
-/// FUNCTION DEFITIONS ///
+/// FUNCTION DEFINITIONS ///
////////////////////////////////////////////////////////////////////////
/**Function*************************************************************
@@ -64,6 +64,12 @@ int Fraig_ManReadPatternNumRandom( Fraig_Man_t * p ) {
int Fraig_ManReadPatternNumDynamic( Fraig_Man_t * p ) { return p->iWordStart * 32; }
// returns the number of dynamic patterns proved useful to distinquish some FRAIG nodes (this number is more than 0 after the first garbage collection of patterns)
int Fraig_ManReadPatternNumDynamicFiltered( Fraig_Man_t * p ) { return p->iPatsPerm; }
+// returns the number of times FRAIG package timed out
+int Fraig_ManReadSatFails( Fraig_Man_t * p ) { return p->nSatFailsReal; }
+// returns the number of conflicts in the SAT solver
+int Fraig_ManReadConflicts( Fraig_Man_t * p ) { return p->pSat? Msat_SolverReadBackTracks(p->pSat) : 0; }
+// returns the number of inspections in the SAT solver
+int Fraig_ManReadInspects( Fraig_Man_t * p ) { return p->pSat? Msat_SolverReadInspects(p->pSat) : 0; }
/**Function*************************************************************
diff --git a/src/sat/fraig/fraigCanon.c b/src/sat/fraig/fraigCanon.c
index 5a7d0563..89bc924f 100644
--- a/src/sat/fraig/fraigCanon.c
+++ b/src/sat/fraig/fraigCanon.c
@@ -24,7 +24,7 @@
////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////
-/// FUNCTION DEFITIONS ///
+/// FUNCTION DEFINITIONS ///
////////////////////////////////////////////////////////////////////////
/**Function*************************************************************
@@ -49,7 +49,8 @@
Fraig_Node_t * Fraig_NodeAndCanon( Fraig_Man_t * pMan, Fraig_Node_t * p1, Fraig_Node_t * p2 )
{
Fraig_Node_t * pNodeNew, * pNodeOld, * pNodeRepr;
- int RetValue;
+ int fUseSatCheck;
+// int RetValue;
// check for trivial cases
if ( p1 == p2 )
@@ -68,7 +69,7 @@ Fraig_Node_t * Fraig_NodeAndCanon( Fraig_Man_t * pMan, Fraig_Node_t * p1, Fraig_
return p1;
return Fraig_Not(pMan->pConst1);
}
-
+/*
// check for less trivial cases
if ( Fraig_IsComplement(p1) )
{
@@ -125,7 +126,7 @@ Fraig_Node_t * Fraig_NodeAndCanon( Fraig_Man_t * pMan, Fraig_Node_t * p1, Fraig_
return Fraig_Not(pMan->pConst1);
}
}
-
+*/
// perform level-one structural hashing
if ( Fraig_HashTableLookupS( pMan, p1, p2, &pNodeNew ) ) // the node with these children is found
{
@@ -167,7 +168,8 @@ Fraig_Node_t * Fraig_NodeAndCanon( Fraig_Man_t * pMan, Fraig_Node_t * p1, Fraig_
// there is another node which looks the same according to simulation
// use SAT to resolve the ambiguity
- if ( Fraig_NodeIsEquivalent( pMan, pNodeOld, pNodeNew, pMan->nBTLimit ) )
+ 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
diff --git a/src/sat/fraig/fraigChoice.c b/src/sat/fraig/fraigChoice.c
new file mode 100644
index 00000000..896e5d2d
--- /dev/null
+++ b/src/sat/fraig/fraigChoice.c
@@ -0,0 +1,241 @@
+/**CFile****************************************************************
+
+ FileName [fraigTrans.c]
+
+ PackageName [MVSIS 1.3: Multi-valued logic synthesis system.]
+
+ Synopsis [Adds the additive and distributive choices to the AIG.]
+
+ Author [MVSIS Group]
+
+ Affiliation [UC Berkeley]
+
+ Date [Ver. 1.0. Started - February 1, 2003.]
+
+ Revision [$Id: fraigTrans.c,v 1.1 2005/02/28 05:34:34 alanmi Exp $]
+
+***********************************************************************/
+
+#include "fraigInt.h"
+
+////////////////////////////////////////////////////////////////////////
+/// DECLARATIONS ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+/// FUNCTION DEFITIONS ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+ Synopsis [Adds choice nodes based on associativity.]
+
+ Description [Make nLimit big AND gates and add all decompositions
+ to the Fraig.]
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Fraig_ManAddChoices( Fraig_Man_t * pMan, int fVerbose, int nLimit )
+{
+// ProgressBar * pProgress;
+ char Buffer[100];
+ int clkTotal = clock();
+ int i, nNodesBefore, nNodesAfter, nInputs, nMaxNodes;
+ int /*nMaxLevel,*/ nDistributive;
+ Fraig_Node_t *pNode, *pRepr;
+ Fraig_Node_t *pX, *pA, *pB, *pC, /* *pD,*/ *pN, /* *pQ, *pR,*/ *pT;
+ int fShortCut = 0;
+
+ nDistributive = 0;
+
+// Fraig_ManSetApprox( pMan, 1 );
+
+ // NO functional reduction
+ if (fShortCut) Fraig_ManSetFuncRed( pMan, 0 );
+
+ // First we mark critical functions i.e. compute those
+ // nodes which lie on the critical path. Note that this
+ // doesn't update the required times on any choice nodes
+ // which are not the representatives
+/*
+ nMaxLevel = Fraig_GetMaxLevel( pMan );
+ for ( i = 0; i < pMan->nOutputs; i++ )
+ {
+ Fraig_SetNodeRequired( pMan, pMan->pOutputs[i], nMaxLevel );
+ }
+*/
+ nNodesBefore = Fraig_ManReadNodeNum( pMan );
+ nInputs = Fraig_ManReadInputNum( pMan );
+ nMaxNodes = nInputs + nLimit * ( nNodesBefore - nInputs );
+
+ printf ("Limit = %d, Before = %d\n", nMaxNodes, nNodesBefore );
+
+ if (0)
+ {
+ char buffer[128];
+ sprintf (buffer, "test" );
+// Fraig_MappingShow( pMan, buffer );
+ }
+
+// pProgress = Extra_ProgressBarStart( stdout, nMaxNodes );
+Fraig_ManCheckConsistency( pMan );
+
+ for ( i = nInputs+1; (i < Fraig_ManReadNodeNum( pMan ))
+ && (nMaxNodes > Fraig_ManReadNodeNum( pMan )); ++i )
+ {
+// if ( i == nNodesBefore )
+// break;
+
+ pNode = Fraig_ManReadIthNode( pMan, i );
+ assert ( pNode );
+
+ pRepr = pNode->pRepr ? pNode->pRepr : pNode;
+ //printf ("Slack: %d\n", Fraig_NodeReadSlack( pRepr ));
+
+ // All the new associative choices we add will have huge slack
+ // since we do not redo timing, and timing doesnt handle choices
+ // well anyway. However every newly added node is a choice of an
+ // existing critical node, so they are considered critical.
+// if ( (Fraig_NodeReadSlack( pRepr ) > 3) && (i < nNodesBefore) )
+// continue;
+
+// if ( pNode->pRepr )
+// continue;
+
+ // Try ((ab)c), x = ab -> (a(bc)) and (b(ac))
+ pX = Fraig_NodeReadOne(pNode);
+ pC = Fraig_NodeReadTwo(pNode);
+ if (Fraig_NodeIsAnd(pX) && !Fraig_IsComplement(pX))
+ {
+ pA = Fraig_NodeReadOne(Fraig_Regular(pX));
+ pB = Fraig_NodeReadTwo(Fraig_Regular(pX));
+
+// pA = Fraig_NodeGetRepr( pA );
+// pB = Fraig_NodeGetRepr( pB );
+// pC = Fraig_NodeGetRepr( pC );
+
+ if (fShortCut)
+ {
+ pT = Fraig_NodeAnd(pMan, pB, pC);
+ if ( !pT->pRepr )
+ {
+ pN = Fraig_NodeAnd(pMan, pA, pT);
+// Fraig_NodeAddChoice( pMan, pNode, pN );
+ }
+ }
+ else
+ pN = Fraig_NodeAnd(pMan, pA, Fraig_NodeAnd(pMan, pB, pC));
+ // assert ( Fraig_NodesEqual(pN, pNode) );
+
+
+ if (fShortCut)
+ {
+ pT = Fraig_NodeAnd(pMan, pA, pC);
+ if ( !pT->pRepr )
+ {
+ pN = Fraig_NodeAnd(pMan, pB, pT);
+// Fraig_NodeAddChoice( pMan, pNode, pN );
+ }
+ }
+ else
+ pN = Fraig_NodeAnd(pMan, pB, Fraig_NodeAnd(pMan, pA, pC));
+ // assert ( Fraig_NodesEqual(pN, pNode) );
+ }
+
+
+ // Try (a(bc)), x = bc -> ((ab)c) and ((ac)b)
+ pA = Fraig_NodeReadOne(pNode);
+ pX = Fraig_NodeReadTwo(pNode);
+ if (Fraig_NodeIsAnd(pX) && !Fraig_IsComplement(pX))
+ {
+ pB = Fraig_NodeReadOne(Fraig_Regular(pX));
+ pC = Fraig_NodeReadTwo(Fraig_Regular(pX));
+
+// pA = Fraig_NodeGetRepr( pA );
+// pB = Fraig_NodeGetRepr( pB );
+// pC = Fraig_NodeGetRepr( pC );
+
+ if (fShortCut)
+ {
+ pT = Fraig_NodeAnd(pMan, pA, pB);
+ if ( !pT->pRepr )
+ {
+ pN = Fraig_NodeAnd(pMan, pC, pT);
+// Fraig_NodeAddChoice( pMan, pNode, pN );
+ }
+ }
+ else
+ pN = Fraig_NodeAnd(pMan, Fraig_NodeAnd(pMan, pA, pB), pC);
+ // assert ( Fraig_NodesEqual(pN, pNode) );
+
+ if (fShortCut)
+ {
+ pT = Fraig_NodeAnd(pMan, pA, pC);
+ if ( !pT->pRepr )
+ {
+ pN = Fraig_NodeAnd(pMan, pB, pT);
+// Fraig_NodeAddChoice( pMan, pNode, pN );
+ }
+ }
+ else
+ pN = Fraig_NodeAnd(pMan, Fraig_NodeAnd(pMan, pA, pC), pB);
+ // assert ( Fraig_NodesEqual(pN, pNode) );
+ }
+
+
+/*
+ // Try distributive transform
+ pQ = Fraig_NodeReadOne(pNode);
+ pR = Fraig_NodeReadTwo(pNode);
+ if ( (Fraig_IsComplement(pQ) && Fraig_NodeIsAnd(pQ))
+ && (Fraig_IsComplement(pR) && Fraig_NodeIsAnd(pR)) )
+ {
+ pA = Fraig_NodeReadOne(Fraig_Regular(pQ));
+ pB = Fraig_NodeReadTwo(Fraig_Regular(pQ));
+ pC = Fraig_NodeReadOne(Fraig_Regular(pR));
+ pD = Fraig_NodeReadTwo(Fraig_Regular(pR));
+
+ // Now detect the !(xy + xz) pattern, store
+ // x in pA, y in pB and z in pC and set pD = 0 to indicate
+ // pattern was found
+ assert (pD != 0);
+ if (pA == pC) { pC = pD; pD = 0; }
+ if (pA == pD) { pD = 0; }
+ if (pB == pC) { pB = pA; pA = pC; pC = pD; pD = 0; }
+ if (pB == pD) { pB = pA; pA = pD; pD = 0; }
+ if (pD == 0)
+ {
+ nDistributive++;
+ pN = Fraig_Not(Fraig_NodeAnd(pMan, pA,
+ Fraig_NodeOr(pMan, pB, pC)));
+ if (fShortCut) Fraig_NodeAddChoice( pMan, pNode, pN );
+ // assert ( Fraig_NodesEqual(pN, pNode) );
+ }
+ }
+*/
+ if ( i % 1000 == 0 )
+ {
+ sprintf( Buffer, "Adding choice %6d...", i - nNodesBefore );
+// Extra_ProgressBarUpdate( pProgress, i, Buffer );
+ }
+ }
+
+// Extra_ProgressBarStop( pProgress );
+
+Fraig_ManCheckConsistency( pMan );
+
+ nNodesAfter = Fraig_ManReadNodeNum( pMan );
+ printf ( "Nodes before = %6d. Nodes with associative choices = %6d. Increase = %4.2f %%.\n",
+ nNodesBefore, nNodesAfter, ((float)(nNodesAfter - nNodesBefore)) * 100.0/(nNodesBefore - nInputs) );
+ printf ( "Distributive = %d\n", nDistributive );
+
+}
+
+////////////////////////////////////////////////////////////////////////
+/// END OF FILE ///
+////////////////////////////////////////////////////////////////////////
+
+
diff --git a/src/sat/fraig/fraigFanout.c b/src/sat/fraig/fraigFanout.c
index b44bacd7..789bffca 100644
--- a/src/sat/fraig/fraigFanout.c
+++ b/src/sat/fraig/fraigFanout.c
@@ -25,7 +25,7 @@
////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////
-/// FUNCTION DEFITIONS ///
+/// FUNCTION DEFINITIONS ///
////////////////////////////////////////////////////////////////////////
/**Function*************************************************************
diff --git a/src/sat/fraig/fraigFeed.c b/src/sat/fraig/fraigFeed.c
index 73640387..8a3cc6c7 100644
--- a/src/sat/fraig/fraigFeed.c
+++ b/src/sat/fraig/fraigFeed.c
@@ -37,7 +37,7 @@ static void Fraig_ReallocateSimulationInfo( Fraig_Man_t * p );
////////////////////////////////////////////////////////////////////////
-/// FUNCTION DEFITIONS ///
+/// FUNCTION DEFINITIONS ///
////////////////////////////////////////////////////////////////////////
/**Function*************************************************************
@@ -463,6 +463,10 @@ Fraig_NodeVec_t * Fraig_FeedBackCoveringStart( Fraig_Man_t * p )
Fraig_NodeVecPush( p->vCones, pEntD );
if ( p->vCones->nSize == 1 )
continue;
+ //////////////////////////////// bug fix by alanmi, September 14, 2006
+ if ( p->vCones->nSize > 20 )
+ continue;
+ ////////////////////////////////
for ( k = 0; k < p->vCones->nSize; k++ )
for ( m = k+1; m < p->vCones->nSize; m++ )
diff --git a/src/sat/fraig/fraigInt.h b/src/sat/fraig/fraigInt.h
index 131b750c..9c6e0d47 100644
--- a/src/sat/fraig/fraigInt.h
+++ b/src/sat/fraig/fraigInt.h
@@ -47,7 +47,7 @@
*/
////////////////////////////////////////////////////////////////////////
-/// MACRO DEFITIONS ///
+/// MACRO DEFINITIONS ///
////////////////////////////////////////////////////////////////////////
// enable this macro to support the fanouts
@@ -66,7 +66,7 @@
// the bit masks
#define FRAIG_MASK(n) ((~((unsigned)0)) >> (32-(n)))
#define FRAIG_FULL (~((unsigned)0))
-#define FRAIG_NUM_WORDS(n) ((n)/32 + (((n)%32) > 0))
+#define FRAIG_NUM_WORDS(n) (((n)>>5) + (((n)&31) > 0))
// maximum/minimum operators
#define FRAIG_MIN(a,b) (((a) < (b))? (a) : (b))
@@ -143,6 +143,7 @@ struct Fraig_ManStruct_t_
int nWordsRand; // the number of words of random simulation info
int nWordsDyna; // the number of words of dynamic simulation info
int nBTLimit; // the max number of backtracks to perform
+ int nSeconds; // the runtime limit for the miter proof
int fFuncRed; // performs only one level hashing
int fFeedBack; // enables solver feedback
int fDist1Pats; // enables solver feedback
@@ -151,6 +152,7 @@ struct Fraig_ManStruct_t_
int fTryProve; // tries to solve the final miter
int fVerbose; // the verbosiness flag
int fVerboseP; // the verbosiness flag
+ sint64 nInspLimit; // the inspection limit
int nTravIds; // the traversal counter
int nTravIds2; // the traversal counter
@@ -188,7 +190,8 @@ struct Fraig_ManStruct_t_
int nSatCalls; // the number of times equivalence checking was called
int nSatProof; // the number of times a proof was found
int nSatCounter; // the number of times a counter example was found
- int nSatFails; // the number of times the SAT solver failed to complete
+ 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
@@ -242,8 +245,9 @@ struct Fraig_NodeStruct_t_
unsigned fMark3 : 1; // the mark used for traversals
unsigned fFeedUse : 1; // the presence of the variable in the feedback
unsigned fFeedVal : 1; // the value of the variable in the feedback
+ unsigned fFailTfo : 1; // the node is in the TFO of the failed SAT run
unsigned nFanouts : 2; // the indicator of fanouts (none, one, or many)
- unsigned nOnes : 21; // the number of 1's in the random sim info
+ 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
@@ -279,9 +283,9 @@ struct Fraig_NodeStruct_t_
// the vector of nodes
struct Fraig_NodeVecStruct_t_
{
- Fraig_Node_t ** pArray; // the array of nodes
- int nSize; // the number of entries in the array
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
@@ -364,7 +368,7 @@ struct Fraig_HashTableStruct_t_
////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////
-/// FUNCTION DEFITIONS ///
+/// FUNCTION DEFINITIONS ///
////////////////////////////////////////////////////////////////////////
/*=== fraigCanon.c =============================================================*/
@@ -380,6 +384,8 @@ 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 );
@@ -438,8 +444,8 @@ extern int Fraig_NodeIsTravIdPrevious( Fraig_Man_t * pMan, Fraig
/*=== fraigVec.c ===============================================================*/
extern void Fraig_NodeVecSortByRefCount( Fraig_NodeVec_t * p );
+#endif
+
////////////////////////////////////////////////////////////////////////
/// END OF FILE ///
////////////////////////////////////////////////////////////////////////
-
-#endif
diff --git a/src/sat/fraig/fraigMan.c b/src/sat/fraig/fraigMan.c
index e5979c93..7fd937d5 100644
--- a/src/sat/fraig/fraigMan.c
+++ b/src/sat/fraig/fraigMan.c
@@ -26,7 +26,7 @@ int timeSelect;
int timeAssign;
////////////////////////////////////////////////////////////////////////
-/// FUNCTION DEFITIONS ///
+/// FUNCTION DEFINITIONS ///
////////////////////////////////////////////////////////////////////////
/**Function*************************************************************
@@ -40,12 +40,89 @@ int timeAssign;
SeeAlso []
***********************************************************************/
+void Prove_ParamsSetDefault( Prove_Params_t * pParams )
+{
+ // clean the parameter structure
+ memset( pParams, 0, sizeof(Prove_Params_t) );
+ // general parameters
+ pParams->fUseFraiging = 1; // enables fraiging
+ pParams->fUseRewriting = 1; // enables rewriting
+ pParams->fUseBdds = 0; // enables BDD construction when other methods fail
+ pParams->fVerbose = 0; // prints verbose stats
+ // iterations
+ pParams->nItersMax = 6; // the number of iterations
+ // mitering
+ pParams->nMiteringLimitStart = 300; // starting mitering limit
+ pParams->nMiteringLimitMulti = 2.0; // multiplicative coefficient to increase the limit in each iteration
+ // rewriting (currently not used)
+ pParams->nRewritingLimitStart = 3; // the number of rewriting iterations
+ pParams->nRewritingLimitMulti = 1.0; // multiplicative coefficient to increase the limit in each iteration
+ // fraiging
+ pParams->nFraigingLimitStart = 2; // starting backtrack(conflict) limit
+ pParams->nFraigingLimitMulti = 8.0; // multiplicative coefficient to increase the limit in each iteration
+ // last-gasp BDD construction
+ pParams->nBddSizeLimit = 1000000; // the number of BDD nodes when construction is aborted
+ pParams->fBddReorder = 1; // enables dynamic BDD variable reordering
+ // last-gasp mitering
+// pParams->nMiteringLimitLast = 1000000; // final mitering limit
+ pParams->nMiteringLimitLast = 0; // final mitering limit
+ // global SAT solver limits
+ pParams->nTotalBacktrackLimit = 0; // global limit on the number of backtracks
+ pParams->nTotalInspectLimit = 0; // global limit on the number of clause inspects
+// pParams->nTotalInspectLimit = 100000000; // global limit on the number of clause inspects
+}
+
+/**Function*************************************************************
+
+ Synopsis [Prints out the current values of CEC engine parameters.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Prove_ParamsPrint( Prove_Params_t * pParams )
+{
+ printf( "CEC enging parameters:\n" );
+ printf( "Fraiging enabled: %s\n", pParams->fUseFraiging? "yes":"no" );
+ printf( "Rewriting enabled: %s\n", pParams->fUseRewriting? "yes":"no" );
+ printf( "BDD construction enabled: %s\n", pParams->fUseBdds? "yes":"no" );
+ printf( "Verbose output enabled: %s\n", pParams->fVerbose? "yes":"no" );
+ printf( "Solver iterations: %d\n", pParams->nItersMax );
+ printf( "Starting mitering limit: %d\n", pParams->nMiteringLimitStart );
+ printf( "Multiplicative coeficient for mitering: %.2f\n", pParams->nMiteringLimitMulti );
+ printf( "Starting number of rewriting iterations: %d\n", pParams->nRewritingLimitStart );
+ printf( "Multiplicative coeficient for rewriting: %.2f\n", pParams->nRewritingLimitMulti );
+ printf( "Starting number of conflicts in fraiging: %d\n", pParams->nFraigingLimitMulti );
+ printf( "Multiplicative coeficient for fraiging: %.2f\n", pParams->nRewritingLimitMulti );
+ printf( "BDD size limit for bailing out: %.2f\n", pParams->nBddSizeLimit );
+ printf( "BDD reordering enabled: %s\n", pParams->fBddReorder? "yes":"no" );
+ printf( "Last-gasp mitering limit: %d\n", pParams->nMiteringLimitLast );
+ printf( "Total conflict limit: %d\n", pParams->nTotalBacktrackLimit );
+ printf( "Total inspection limit: %d\n", pParams->nTotalInspectLimit );
+ printf( "Parameter dump complete.\n" );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Sets the default parameters of the package.]
+
+ Description [This set of parameters is tuned for equivalence checking.]
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
void Fraig_ParamsSetDefault( Fraig_Params_t * pParams )
{
memset( pParams, 0, sizeof(Fraig_Params_t) );
pParams->nPatsRand = FRAIG_PATTERNS_RANDOM; // the number of words of random simulation info
pParams->nPatsDyna = FRAIG_PATTERNS_DYNAMIC; // the number of words of dynamic simulation info
pParams->nBTLimit = 99; // the max number of backtracks to perform
+ pParams->nSeconds = 20; // the max number of seconds to solve the miter
pParams->fFuncRed = 1; // performs only one level hashing
pParams->fFeedBack = 1; // enables solver feedback
pParams->fDist1Pats = 1; // enables distance-1 patterns
@@ -55,6 +132,39 @@ void Fraig_ParamsSetDefault( Fraig_Params_t * pParams )
pParams->fVerbose = 0; // the verbosiness flag
pParams->fVerboseP = 0; // the verbose flag for reporting the proof
pParams->fInternal = 0; // the flag indicates the internal run
+ pParams->nConfLimit = 0; // the limit on the number of conflicts
+ pParams->nInspLimit = 0; // the limit on the number of inspections
+}
+
+/**Function*************************************************************
+
+ Synopsis [Sets the default parameters of the package.]
+
+ Description [This set of parameters is tuned for complete FRAIGing.]
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Fraig_ParamsSetDefaultFull( Fraig_Params_t * pParams )
+{
+ memset( pParams, 0, sizeof(Fraig_Params_t) );
+ pParams->nPatsRand = FRAIG_PATTERNS_RANDOM; // the number of words of random simulation info
+ pParams->nPatsDyna = FRAIG_PATTERNS_DYNAMIC; // the number of words of dynamic simulation info
+ pParams->nBTLimit = -1; // the max number of backtracks to perform
+ pParams->nSeconds = 20; // the max number of seconds to solve the miter
+ pParams->fFuncRed = 1; // performs only one level hashing
+ pParams->fFeedBack = 1; // enables solver feedback
+ pParams->fDist1Pats = 1; // enables distance-1 patterns
+ pParams->fDoSparse = 1; // performs equiv tests for sparse functions
+ pParams->fChoicing = 0; // enables recording structural choices
+ pParams->fTryProve = 0; // tries to solve the final miter
+ pParams->fVerbose = 0; // the verbosiness flag
+ pParams->fVerboseP = 0; // the verbose flag for reporting the proof
+ pParams->fInternal = 0; // the flag indicates the internal run
+ pParams->nConfLimit = 0; // the limit on the number of conflicts
+ pParams->nInspLimit = 0; // the limit on the number of inspections
}
/**Function*************************************************************
@@ -74,7 +184,8 @@ Fraig_Man_t * Fraig_ManCreate( Fraig_Params_t * pParams )
Fraig_Man_t * p;
// set the random seed for simulation
- srand( 0xFEEDDEAF );
+// srand( 0xFEEDDEAF );
+ srand( 0xDEADCAFE );
// set parameters for equivalence checking
if ( pParams == NULL )
@@ -100,6 +211,7 @@ Fraig_Man_t * Fraig_ManCreate( Fraig_Params_t * pParams )
p->nWordsRand = FRAIG_NUM_WORDS( pParams->nPatsRand ); // the number of words of random simulation info
p->nWordsDyna = FRAIG_NUM_WORDS( pParams->nPatsDyna ); // the number of patterns for dynamic simulation info
p->nBTLimit = pParams->nBTLimit; // -1 means infinite backtrack limit
+ p->nSeconds = pParams->nSeconds; // the timeout for the final miter
p->fFuncRed = pParams->fFuncRed; // enables functional reduction (otherwise, only one-level hashing is performed)
p->fFeedBack = pParams->fFeedBack; // enables solver feedback (the use of counter-examples in simulation)
p->fDist1Pats = pParams->fDist1Pats; // enables solver feedback (the use of counter-examples in simulation)
@@ -108,6 +220,7 @@ Fraig_Man_t * Fraig_ManCreate( Fraig_Params_t * pParams )
p->fTryProve = pParams->fTryProve; // disable accumulation of structural choices (keeps only the first choice)
p->fVerbose = pParams->fVerbose; // disable verbose output
p->fVerboseP = pParams->fVerboseP; // disable verbose output
+ p->nInspLimit = pParams->nInspLimit; // the limit on the number of inspections
// start memory managers
p->mmNodes = Fraig_MemFixedStart( sizeof(Fraig_Node_t) );
@@ -153,7 +266,7 @@ void Fraig_ManFree( Fraig_Man_t * p )
// Fraig_TablePrintStatsF( p );
// Fraig_TablePrintStatsF0( p );
}
-
+
for ( i = 0; i < p->vNodes->nSize; i++ )
if ( p->vNodes->pArray[i]->vFanins )
{
@@ -194,6 +307,31 @@ void Fraig_ManFree( Fraig_Man_t * p )
FREE( p );
}
+/**Function*************************************************************
+
+ Synopsis [Prepares the SAT solver to run on the two nodes.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Fraig_ManCreateSolver( Fraig_Man_t * p )
+{
+ extern int timeSelect;
+ extern int timeAssign;
+ assert( p->pSat == NULL );
+ // allocate data for SAT solving
+ p->pSat = Msat_SolverAlloc( 500, 1, 1, 1, 1, 0 );
+ p->vVarsInt = Msat_SolverReadConeVars( p->pSat );
+ p->vAdjacents = Msat_SolverReadAdjacents( p->pSat );
+ p->vVarsUsed = Msat_SolverReadVarsUsed( p->pSat );
+ timeSelect = 0;
+ timeAssign = 0;
+}
+
/**Function*************************************************************
@@ -214,8 +352,8 @@ void Fraig_ManPrintStats( Fraig_Man_t * p )
(sizeof(Fraig_Node_t) + sizeof(unsigned)*(p->nWordsRand + p->nWordsDyna) /*+ p->nSuppWords*sizeof(unsigned)*/))/(1<<20);
printf( "Words: Random = %d. Dynamic = %d. Used = %d. Memory = %0.2f Mb.\n",
p->nWordsRand, p->nWordsDyna, p->iWordPerm, nMemory );
- printf( "Proof = %d. Counter-example = %d. Fail = %d. Zero = %d.\n",
- p->nSatProof, p->nSatCounter, p->nSatFails, p->nSatZeros );
+ 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 );
@@ -233,6 +371,168 @@ void Fraig_ManPrintStats( Fraig_Man_t * p )
// PRT( "Assignment", timeAssign );
}
+/**Function*************************************************************
+
+ Synopsis [Allocates simulation information for all nodes.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Fraig_NodeVec_t * Fraig_UtilInfoAlloc( int nSize, int nWords, bool fClean )
+{
+ Fraig_NodeVec_t * vInfo;
+ unsigned * pUnsigned;
+ int i;
+ assert( nSize > 0 && nWords > 0 );
+ vInfo = Fraig_NodeVecAlloc( nSize );
+ pUnsigned = ALLOC( unsigned, nSize * nWords );
+ vInfo->pArray[0] = (Fraig_Node_t *)pUnsigned;
+ if ( fClean )
+ memset( pUnsigned, 0, sizeof(unsigned) * nSize * nWords );
+ for ( i = 1; i < nSize; i++ )
+ vInfo->pArray[i] = (Fraig_Node_t *)(((unsigned *)vInfo->pArray[i-1]) + nWords);
+ vInfo->nSize = nSize;
+ return vInfo;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Returns simulation info of all nodes.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Fraig_NodeVec_t * Fraig_ManGetSimInfo( Fraig_Man_t * p )
+{
+ Fraig_NodeVec_t * vInfo;
+ Fraig_Node_t * pNode;
+ unsigned * pUnsigned;
+ int nRandom, nDynamic;
+ int i, k, nWords;
+
+ nRandom = Fraig_ManReadPatternNumRandom( p );
+ nDynamic = Fraig_ManReadPatternNumDynamic( p );
+ nWords = nRandom / 32 + nDynamic / 32;
+
+ vInfo = Fraig_UtilInfoAlloc( p->vNodes->nSize, nWords, 0 );
+ for ( i = 0; i < p->vNodes->nSize; i++ )
+ {
+ pNode = p->vNodes->pArray[i];
+ assert( i == pNode->Num );
+ pUnsigned = (unsigned *)vInfo->pArray[i];
+ for ( k = 0; k < nRandom / 32; k++ )
+ pUnsigned[k] = pNode->puSimR[k];
+ for ( k = 0; k < nDynamic / 32; k++ )
+ pUnsigned[nRandom / 32 + k] = pNode->puSimD[k];
+ }
+ return vInfo;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Returns 1 if A v B is always true based on the siminfo.]
+
+ Description [A v B is always true iff A' * B' is always false.]
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Fraig_ManCheckClauseUsingSimInfo( Fraig_Man_t * p, Fraig_Node_t * pNode1, Fraig_Node_t * pNode2 )
+{
+ int fCompl1, fCompl2, i;
+
+ fCompl1 = 1 ^ Fraig_IsComplement(pNode1) ^ Fraig_Regular(pNode1)->fInv;
+ fCompl2 = 1 ^ Fraig_IsComplement(pNode2) ^ Fraig_Regular(pNode2)->fInv;
+
+ pNode1 = Fraig_Regular(pNode1);
+ pNode2 = Fraig_Regular(pNode2);
+ assert( pNode1 != pNode2 );
+
+ // check the simulation info
+ if ( fCompl1 && fCompl2 )
+ {
+ for ( i = 0; i < p->nWordsRand; i++ )
+ if ( ~pNode1->puSimR[i] & ~pNode2->puSimR[i] )
+ return 0;
+ for ( i = 0; i < p->iWordStart; i++ )
+ if ( ~pNode1->puSimD[i] & ~pNode2->puSimD[i] )
+ return 0;
+ return 1;
+ }
+ if ( !fCompl1 && fCompl2 )
+ {
+ for ( i = 0; i < p->nWordsRand; i++ )
+ if ( pNode1->puSimR[i] & ~pNode2->puSimR[i] )
+ return 0;
+ for ( i = 0; i < p->iWordStart; i++ )
+ if ( pNode1->puSimD[i] & ~pNode2->puSimD[i] )
+ return 0;
+ return 1;
+ }
+ if ( fCompl1 && !fCompl2 )
+ {
+ for ( i = 0; i < p->nWordsRand; i++ )
+ if ( ~pNode1->puSimR[i] & pNode2->puSimR[i] )
+ return 0;
+ for ( i = 0; i < p->iWordStart; i++ )
+ if ( ~pNode1->puSimD[i] & pNode2->puSimD[i] )
+ return 0;
+ return 1;
+ }
+// if ( fCompl1 && fCompl2 )
+ {
+ for ( i = 0; i < p->nWordsRand; i++ )
+ if ( pNode1->puSimR[i] & pNode2->puSimR[i] )
+ return 0;
+ for ( i = 0; i < p->iWordStart; i++ )
+ if ( pNode1->puSimD[i] & pNode2->puSimD[i] )
+ return 0;
+ return 1;
+ }
+}
+
+/**Function*************************************************************
+
+ Synopsis [Adds clauses to the solver.]
+
+ Description [This procedure is used to add external clauses to the solver.
+ The clauses are given by sets of nodes. Each node stands for one literal.
+ If the node is complemented, the literal is negated.]
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Fraig_ManAddClause( Fraig_Man_t * p, Fraig_Node_t ** ppNodes, int nNodes )
+{
+ Fraig_Node_t * pNode;
+ int i, fComp, RetValue;
+ if ( p->pSat == NULL )
+ Fraig_ManCreateSolver( p );
+ // create four clauses
+ Msat_IntVecClear( p->vProj );
+ for ( i = 0; i < nNodes; i++ )
+ {
+ pNode = Fraig_Regular(ppNodes[i]);
+ fComp = Fraig_IsComplement(ppNodes[i]);
+ Msat_IntVecPush( p->vProj, MSAT_VAR2LIT(pNode->Num, fComp) );
+// printf( "%d(%d) ", pNode->Num, fComp );
+ }
+// printf( "\n" );
+ RetValue = Msat_SolverAddClause( p->pSat, p->vProj );
+ assert( RetValue );
+}
////////////////////////////////////////////////////////////////////////
/// END OF FILE ///
diff --git a/src/sat/fraig/fraigMem.c b/src/sat/fraig/fraigMem.c
index dbf42da4..500431c6 100644
--- a/src/sat/fraig/fraigMem.c
+++ b/src/sat/fraig/fraigMem.c
@@ -43,7 +43,7 @@ struct Fraig_MemFixed_t_
};
////////////////////////////////////////////////////////////////////////
-/// FUNCTION DEFITIONS ///
+/// FUNCTION DEFINITIONS ///
////////////////////////////////////////////////////////////////////////
/**Function*************************************************************
@@ -201,7 +201,7 @@ void Fraig_MemFixedRestart( Fraig_MemFixed_t * p )
int i;
char * pTemp;
- // delocate all chunks except the first one
+ // deallocate all chunks except the first one
for ( i = 1; i < p->nChunks; i++ )
free( p->pChunks[i] );
p->nChunks = 1;
diff --git a/src/sat/fraig/fraigNode.c b/src/sat/fraig/fraigNode.c
index a6c1d5a6..6e3d3c7d 100644
--- a/src/sat/fraig/fraigNode.c
+++ b/src/sat/fraig/fraigNode.c
@@ -26,7 +26,7 @@
#define Fraig_NodeIsSimComplement(p) (Fraig_IsComplement(p)? !(Fraig_Regular(p)->fInv) : (p)->fInv)
////////////////////////////////////////////////////////////////////////
-/// FUNCTION DEFITIONS ///
+/// FUNCTION DEFINITIONS ///
////////////////////////////////////////////////////////////////////////
/**Function*************************************************************
@@ -176,6 +176,7 @@ Fraig_Node_t * Fraig_NodeCreate( Fraig_Man_t * p, Fraig_Node_t * p1, Fraig_Node_
// compute the level of this node
pNode->Level = 1 + FRAIG_MAX(Fraig_Regular(p1)->Level, Fraig_Regular(p2)->Level);
pNode->fInv = Fraig_NodeIsSimComplement(p1) & Fraig_NodeIsSimComplement(p2);
+ pNode->fFailTfo = Fraig_Regular(p1)->fFailTfo | Fraig_Regular(p2)->fFailTfo;
// derive the simulation info
clk = clock();
diff --git a/src/sat/fraig/fraigPrime.c b/src/sat/fraig/fraigPrime.c
index 0f37a586..127ad478 100644
--- a/src/sat/fraig/fraigPrime.c
+++ b/src/sat/fraig/fraigPrime.c
@@ -22,7 +22,7 @@
/// DECLARATIONS ///
////////////////////////////////////////////////////////////////////////
-// The 1,000 smallest prime numbers used to compute the hash value
+// 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,
@@ -93,10 +93,12 @@ int s_FraigPrimes[FRAIG_MAX_PRIMES] = { 2, 3, 5,
7523, 7529, 7537, 7541, 7547, 7549, 7559, 7561, 7573, 7577, 7583, 7589, 7591, 7603,
7607, 7621, 7639, 7643, 7649, 7669, 7673, 7681, 7687, 7691, 7699, 7703, 7717, 7723,
7727, 7741, 7753, 7757, 7759, 7789, 7793, 7817, 7823, 7829, 7841, 7853, 7867, 7873,
-7877, 7879, 7883, 7901, 7907, 7919 };
+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 DEFITIONS ///
+/// FUNCTION DEFINITIONS ///
////////////////////////////////////////////////////////////////////////
/**Function********************************************************************
diff --git a/src/sat/fraig/fraigSat.c b/src/sat/fraig/fraigSat.c
index 17201e58..53057fc3 100644
--- a/src/sat/fraig/fraigSat.c
+++ b/src/sat/fraig/fraigSat.c
@@ -17,6 +17,7 @@
***********************************************************************/
#include "fraigInt.h"
+#include "math.h"
////////////////////////////////////////////////////////////////////////
/// DECLARATIONS ///
@@ -33,6 +34,7 @@ static void Fraig_SupergateAddClausesExor( Fraig_Man_t * pMan, Fraig_Node_t * pN
static void Fraig_SupergateAddClausesMux( Fraig_Man_t * pMan, Fraig_Node_t * pNode );
//static void Fraig_DetectFanoutFreeCone( Fraig_Man_t * pMan, Fraig_Node_t * pNode );
static void Fraig_DetectFanoutFreeConeMux( Fraig_Man_t * pMan, Fraig_Node_t * pNode );
+static void Fraig_SetActivity( Fraig_Man_t * pMan, Fraig_Node_t * pOld, Fraig_Node_t * pNew );
extern void * Msat_ClauseVecReadEntry( void * p, int i );
@@ -41,8 +43,10 @@ extern void * Msat_ClauseVecReadEntry( void * p, int i );
// The best way seems to be fanins followed by fanouts. Slight changes to this order
// leads to big degradation in quality.
+static int nMuxes;
+
////////////////////////////////////////////////////////////////////////
-/// FUNCTION DEFITIONS ///
+/// FUNCTION DEFINITIONS ///
////////////////////////////////////////////////////////////////////////
/**Function*************************************************************
@@ -56,13 +60,13 @@ extern void * Msat_ClauseVecReadEntry( void * p, int i );
SeeAlso []
***********************************************************************/
-int Fraig_NodesAreEqual( Fraig_Man_t * p, Fraig_Node_t * pNode1, Fraig_Node_t * pNode2, int nBTLimit )
+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 );
+ return Fraig_NodeIsEquivalent( p, Fraig_Regular(pNode1), Fraig_Regular(pNode2), nBTLimit, nTimeLimit );
}
/**Function*************************************************************
@@ -95,9 +99,9 @@ void Fraig_ManProveMiter( Fraig_Man_t * p )
// skip nodes that are different according to simulation
if ( !Fraig_CompareSimInfo( pNode, p->pConst1, p->nWordsRand, 1 ) )
continue;
- if ( Fraig_NodeIsEquivalent( p, p->pConst1, pNode, -1 ) )
+ if ( Fraig_NodeIsEquivalent( p, p->pConst1, pNode, -1, p->nSeconds ) )
{
- if ( Fraig_IsComplement(p->vOutputs->pArray[i]) )
+ 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;
@@ -105,7 +109,7 @@ void Fraig_ManProveMiter( Fraig_Man_t * p )
}
if ( p->fVerboseP )
{
- PRT( "Final miter proof time", clock() - clk );
+// PRT( "Final miter proof time", clock() - clk );
}
}
@@ -123,26 +127,158 @@ void Fraig_ManProveMiter( Fraig_Man_t * p )
int Fraig_ManCheckMiter( Fraig_Man_t * p )
{
Fraig_Node_t * pNode;
+ int i;
FREE( p->pModel );
- // get the output node (it can be complemented!)
- pNode = p->vOutputs->pArray[0];
- // if the miter is constant 0, the problem is UNSAT
- if ( pNode == Fraig_Not(p->pConst1) )
+ 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;
- // consider the special case when the miter is constant 1
- if ( pNode == p->pConst1 )
+ // skip the boundary node
+ if ( pNode->TravId == pMan->nTravIds-1 )
{
- // 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 );
+ 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;
}
- // save the counter example
- p->pModel = Fraig_ManSaveCounterExample( p, pNode );
- // if the model is not found, return undecided
- if ( p->pModel == NULL )
- return -1;
- return 0;
+
+ // 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? '+':'-' );
}
@@ -160,34 +296,40 @@ int Fraig_ManCheckMiter( Fraig_Man_t * p )
SeeAlso []
***********************************************************************/
-int Fraig_NodeIsEquivalent( Fraig_Man_t * p, Fraig_Node_t * pOld, Fraig_Node_t * pNew, int nBTLimit )
+int Fraig_NodeIsEquivalent( Fraig_Man_t * p, Fraig_Node_t * pOld, Fraig_Node_t * pNew, int nBTLimit, int nTimeLimit )
{
int RetValue, RetValue1, i, fComp, clk;
int fVerbose = 0;
+ int fSwitch = 0;
// make sure the nodes are not complemented
assert( !Fraig_IsComplement(pNew) );
assert( !Fraig_IsComplement(pOld) );
assert( pNew != pOld );
+ // if at least one of the nodes is a failed node, perform adjustments:
+ // if the backtrack limit is small, simply skip this node
+ // if the backtrack limit is > 10, take the quare root of the limit
+ if ( nBTLimit > 0 && (pOld->fFailTfo || pNew->fFailTfo) )
+ {
+ p->nSatFails++;
+// return 0;
+// if ( nBTLimit > 10 )
+// nBTLimit /= 10;
+ if ( nBTLimit <= 10 )
+ return 0;
+ nBTLimit = (int)sqrt(nBTLimit);
+// fSwitch = 1;
+ }
+
p->nSatCalls++;
// make sure the solver is allocated and has enough variables
if ( p->pSat == NULL )
- {
- extern int timeSelect;
- extern int timeAssign;
- // allocate data for SAT solving
- p->pSat = Msat_SolverAlloc( 500, 1, 1, 1, 1, 0 );
- p->vVarsInt = Msat_SolverReadConeVars( p->pSat );
- p->vAdjacents = Msat_SolverReadAdjacents( p->pSat );
- p->vVarsUsed = Msat_SolverReadVarsUsed( p->pSat );
- timeSelect = 0;
- timeAssign = 0;
- }
+ 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 );
+ Msat_SolverAddVar( p->pSat, p->vNodes->pArray[i]->Level );
@@ -199,17 +341,26 @@ int Fraig_NodeIsEquivalent( Fraig_Man_t * p, Fraig_Node_t * pOld, Fraig_Node_t *
}
*/
+ nMuxes = 0;
+
// get the logic cone
clk = clock();
+// Fraig_VarsStudy( p, pOld, pNew );
Fraig_OrderVariables( p, pOld, pNew );
// Fraig_PrepareCones( p, pOld, pNew );
p->timeTrav += clock() - clk;
+// printf( "The number of MUXes detected = %d (%5.2f %% of logic). ", nMuxes, 300.0*nMuxes/(p->vNodes->nSize - p->vInputs->nSize) );
+// PRT( "Time", clock() - clk );
+
if ( fVerbose )
printf( "%d(%d) - ", Fraig_CountPis(p,p->vVarsInt), Msat_IntVecReadSize(p->vVarsInt) );
+ // prepare variable activity
+ Fraig_SetActivity( p, pOld, pNew );
+
// get the complemented attribute
fComp = Fraig_NodeComparePhase( pOld, pNew );
//Msat_SolverPrintClauses( p->pSat );
@@ -220,14 +371,18 @@ if ( fVerbose )
Msat_SolverPrepare( p->pSat, p->vVarsInt );
//p->time3 += clock() - clk;
+
// solve under assumptions
// A = 1; B = 0 OR A = 1; B = 1
Msat_IntVecClear( p->vProj );
Msat_IntVecPush( p->vProj, MSAT_VAR2LIT(pOld->Num, 0) );
Msat_IntVecPush( p->vProj, MSAT_VAR2LIT(pNew->Num, !fComp) );
+
+//Msat_SolverWriteDimacs( p->pSat, "temp_fraig.cnf" );
+
// run the solver
clk = clock();
- RetValue1 = Msat_SolverSolve( p->pSat, p->vProj, nBTLimit );
+ RetValue1 = Msat_SolverSolve( p->pSat, p->vProj, nBTLimit, nTimeLimit );
p->timeSat += clock() - clk;
if ( RetValue1 == MSAT_FALSE )
@@ -260,13 +415,31 @@ 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;
- p->nSatFails++;
+
+// 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;
}
@@ -286,8 +459,9 @@ p->time3 += clock() - clk;
Msat_IntVecPush( p->vProj, MSAT_VAR2LIT(pNew->Num, fComp) );
// run the solver
clk = clock();
- RetValue1 = Msat_SolverSolve( p->pSat, p->vProj, nBTLimit );
+ RetValue1 = Msat_SolverSolve( p->pSat, p->vProj, nBTLimit, nTimeLimit );
p->timeSat += clock() - clk;
+
if ( RetValue1 == MSAT_FALSE )
{
//p->time1 += clock() - clk;
@@ -319,17 +493,42 @@ 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;
- p->nSatFails++;
+
+// 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;
}
@@ -359,32 +558,12 @@ int Fraig_NodeIsImplication( Fraig_Man_t * p, Fraig_Node_t * pOld, Fraig_Node_t
// make sure the solver is allocated and has enough variables
if ( p->pSat == NULL )
- {
- extern int timeSelect;
- extern int timeAssign;
- // allocate data for SAT solving
- p->pSat = Msat_SolverAlloc( 500, 1, 1, 1, 1, 0 );
- p->vVarsInt = Msat_SolverReadConeVars( p->pSat );
- p->vAdjacents = Msat_SolverReadAdjacents( p->pSat );
- p->vVarsUsed = Msat_SolverReadVarsUsed( p->pSat );
- timeSelect = 0;
- timeAssign = 0;
- }
+ 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 );
-
+ 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" );
- }
-*/
-
-
- // get the logic cone
+ // get the logic cone
clk = clock();
Fraig_OrderVariables( p, pOld, pNew );
// Fraig_PrepareCones( p, pOld, pNew );
@@ -411,7 +590,7 @@ if ( fVerbose )
Msat_IntVecPush( p->vProj, MSAT_VAR2LIT(pNew->Num, !fComp) );
// run the solver
clk = clock();
- RetValue1 = Msat_SolverSolve( p->pSat, p->vProj, nBTLimit );
+ RetValue1 = Msat_SolverSolve( p->pSat, p->vProj, nBTLimit, 1000000 );
p->timeSat += clock() - clk;
if ( RetValue1 == MSAT_FALSE )
@@ -443,8 +622,8 @@ if ( fVerbose )
PRT( "time", clock() - clk );
}
// record the counter example
-// Fraig_FeedBack( p, Msat_SolverReadModelArray(p->pSat), p->vVarsInt, pOld, pNew );
-// p->nSatCounterImp++;
+ Fraig_FeedBack( p, Msat_SolverReadModelArray(p->pSat), p->vVarsInt, pOld, pNew );
+ p->nSatCounterImp++;
return 0;
}
else // if ( RetValue1 == MSAT_UNKNOWN )
@@ -455,6 +634,96 @@ p->time3 += clock() - clk;
}
}
+/**Function*************************************************************
+
+ Synopsis [Prepares the SAT solver to run on the two nodes.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Fraig_ManCheckClauseUsingSat( Fraig_Man_t * p, Fraig_Node_t * pNode1, Fraig_Node_t * pNode2, int nBTLimit )
+{
+ Fraig_Node_t * pNode1R, * pNode2R;
+ int RetValue, RetValue1, i, clk;
+ int fVerbose = 0;
+
+ pNode1R = Fraig_Regular(pNode1);
+ pNode2R = Fraig_Regular(pNode2);
+ assert( pNode1R != pNode2R );
+
+ // make sure the solver is allocated and has enough variables
+ if ( p->pSat == NULL )
+ Fraig_ManCreateSolver( p );
+ // make sure the SAT solver has enough variables
+ for ( i = Msat_SolverReadVarNum(p->pSat); i < p->vNodes->nSize; i++ )
+ Msat_SolverAddVar( p->pSat, p->vNodes->pArray[i]->Level );
+
+ // get the logic cone
+clk = clock();
+ Fraig_OrderVariables( p, pNode1R, pNode2R );
+// Fraig_PrepareCones( p, pNode1R, pNode2R );
+p->timeTrav += clock() - clk;
+
+ ////////////////////////////////////////////
+ // prepare the solver to run incrementally on these variables
+//clk = clock();
+ Msat_SolverPrepare( p->pSat, p->vVarsInt );
+//p->time3 += clock() - clk;
+
+ // solve under assumptions
+ // A = 1; B = 0 OR A = 1; B = 1
+ Msat_IntVecClear( p->vProj );
+ Msat_IntVecPush( p->vProj, MSAT_VAR2LIT(pNode1R->Num, !Fraig_IsComplement(pNode1)) );
+ Msat_IntVecPush( p->vProj, MSAT_VAR2LIT(pNode2R->Num, !Fraig_IsComplement(pNode2)) );
+ // run the solver
+clk = clock();
+ RetValue1 = Msat_SolverSolve( p->pSat, p->vProj, nBTLimit, 1000000 );
+p->timeSat += clock() - clk;
+
+ if ( RetValue1 == MSAT_FALSE )
+ {
+//p->time1 += clock() - clk;
+
+if ( fVerbose )
+{
+ printf( "unsat %d ", Msat_SolverReadBackTracks(p->pSat) );
+PRT( "time", clock() - clk );
+}
+
+ // add the clause
+ Msat_IntVecClear( p->vProj );
+ Msat_IntVecPush( p->vProj, MSAT_VAR2LIT(pNode1R->Num, Fraig_IsComplement(pNode1)) );
+ Msat_IntVecPush( p->vProj, MSAT_VAR2LIT(pNode2R->Num, Fraig_IsComplement(pNode2)) );
+ RetValue = Msat_SolverAddClause( p->pSat, p->vProj );
+ assert( RetValue );
+// p->nSatProofImp++;
+ return 1;
+ }
+ else if ( RetValue1 == MSAT_TRUE )
+ {
+//p->time2 += clock() - clk;
+
+if ( fVerbose )
+{
+ printf( "sat %d ", Msat_SolverReadBackTracks(p->pSat) );
+PRT( "time", clock() - clk );
+}
+ // record the counter example
+// Fraig_FeedBack( p, Msat_SolverReadModelArray(p->pSat), p->vVarsInt, pNode1R, pNode2R );
+ p->nSatCounterImp++;
+ return 0;
+ }
+ else // if ( RetValue1 == MSAT_UNKNOWN )
+ {
+p->time3 += clock() - clk;
+ p->nSatFailsImp++;
+ return 0;
+ }
+}
/**Function*************************************************************
@@ -486,6 +755,7 @@ void Fraig_PrepareCones( Fraig_Man_t * pMan, Fraig_Node_t * pOld, Fraig_Node_t *
Fraig_PrepareCones_rec( pMan, pNew );
Fraig_PrepareCones_rec( pMan, pOld );
+
/*
nVars = Msat_IntVecReadSize( pMan->vVarsInt );
pVars = Msat_IntVecReadArray( pMan->vVarsInt );
@@ -649,6 +919,8 @@ void Fraig_OrderVariables( Fraig_Man_t * pMan, Fraig_Node_t * pOld, Fraig_Node_t
Fraig_NodeVecPushUnique( pNode->vFanins, Fraig_Regular(Fraig_Regular(pNode->p2)->p2) );
Fraig_SupergateAddClausesMux( pMan, pNode );
// Fraig_DetectFanoutFreeConeMux( pMan, pNode );
+
+ nMuxes++;
}
else
{
@@ -983,6 +1255,33 @@ void Fraig_SupergateAddClausesMux( Fraig_Man_t * p, Fraig_Node_t * pNode )
Msat_IntVecPush( p->vProj, MSAT_VAR2LIT(VarF, 1) );
RetValue = Msat_SolverAddClause( p->pSat, p->vProj );
assert( RetValue );
+
+ // two additional clauses
+ // t' & e' -> f'
+ // t & e -> f
+
+ // t + e + f'
+ // t' + e' + f
+
+ if ( VarT == VarE )
+ {
+// assert( fCompT == !fCompE );
+ return;
+ }
+
+ Msat_IntVecClear( p->vProj );
+ Msat_IntVecPush( p->vProj, MSAT_VAR2LIT(VarT, 0^fCompT) );
+ Msat_IntVecPush( p->vProj, MSAT_VAR2LIT(VarE, 0^fCompE) );
+ Msat_IntVecPush( p->vProj, MSAT_VAR2LIT(VarF, 1) );
+ RetValue = Msat_SolverAddClause( p->pSat, p->vProj );
+ assert( RetValue );
+ Msat_IntVecClear( p->vProj );
+ Msat_IntVecPush( p->vProj, MSAT_VAR2LIT(VarT, 1^fCompT) );
+ Msat_IntVecPush( p->vProj, MSAT_VAR2LIT(VarE, 1^fCompE) );
+ Msat_IntVecPush( p->vProj, MSAT_VAR2LIT(VarF, 0) );
+ RetValue = Msat_SolverAddClause( p->pSat, p->vProj );
+ assert( RetValue );
+
}
@@ -1115,6 +1414,40 @@ printf( "%d(%d)", vFanins->nSize, nCubes );
}
+
+/**Function*************************************************************
+
+ Synopsis [Collect variables using their proximity from the nodes.]
+
+ Description [This procedure creates a variable order based on collecting
+ first the nodes that are the closest to the given two target nodes.]
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Fraig_SetActivity( Fraig_Man_t * pMan, Fraig_Node_t * pOld, Fraig_Node_t * pNew )
+{
+ Fraig_Node_t * pNode;
+ int i, Number, MaxLevel;
+ float * pFactors = Msat_SolverReadFactors(pMan->pSat);
+ if ( pFactors == NULL )
+ return;
+ MaxLevel = FRAIG_MAX( pOld->Level, pNew->Level );
+ // create the variable order
+ for ( i = 0; i < Msat_IntVecReadSize(pMan->vVarsInt); i++ )
+ {
+ // get the new node on the frontier
+ Number = Msat_IntVecReadEntry(pMan->vVarsInt, i);
+ pNode = pMan->vNodes->pArray[Number];
+ pFactors[pNode->Num] = (float)pow( 0.97, MaxLevel - pNode->Level );
+// if ( pNode->Num % 50 == 0 )
+// printf( "(%d) %.2f ", MaxLevel - pNode->Level, pFactors[pNode->Num] );
+ }
+// printf( "\n" );
+}
+
////////////////////////////////////////////////////////////////////////
/// END OF FILE ///
////////////////////////////////////////////////////////////////////////
diff --git a/src/sat/fraig/fraigTable.c b/src/sat/fraig/fraigTable.c
index d0f22acd..b68bbe0e 100644
--- a/src/sat/fraig/fraigTable.c
+++ b/src/sat/fraig/fraigTable.c
@@ -26,7 +26,7 @@ static void Fraig_TableResizeS( Fraig_HashTable_t * p );
static void Fraig_TableResizeF( Fraig_HashTable_t * p, int fUseSimR );
////////////////////////////////////////////////////////////////////////
-/// FUNCTION DEFITIONS ///
+/// FUNCTION DEFINITIONS ///
////////////////////////////////////////////////////////////////////////
/**Function*************************************************************
diff --git a/src/sat/fraig/fraigUtil.c b/src/sat/fraig/fraigUtil.c
index 2155c4a3..342a7111 100644
--- a/src/sat/fraig/fraigUtil.c
+++ b/src/sat/fraig/fraigUtil.c
@@ -38,7 +38,7 @@ static void Fraig_Dfs_rec( Fraig_Man_t * pMan, Fraig_Node_t * pNode, Fraig_NodeV
static int Fraig_CheckTfi_rec( Fraig_Man_t * pMan, Fraig_Node_t * pNode, Fraig_Node_t * pOld );
////////////////////////////////////////////////////////////////////////
-/// FUNCTION DEFITIONS ///
+/// FUNCTION DEFINITIONS ///
////////////////////////////////////////////////////////////////////////
/**Function*************************************************************
diff --git a/src/sat/fraig/fraigVec.c b/src/sat/fraig/fraigVec.c
index 2e2603b0..ba3feecd 100644
--- a/src/sat/fraig/fraigVec.c
+++ b/src/sat/fraig/fraigVec.c
@@ -23,7 +23,7 @@
////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////
-/// FUNCTION DEFITIONS ///
+/// FUNCTION DEFINITIONS ///
////////////////////////////////////////////////////////////////////////
/**Function*************************************************************
diff --git a/src/sat/msat/msat.h b/src/sat/msat/msat.h
index 21ddcb81..53353ba6 100644
--- a/src/sat/msat/msat.h
+++ b/src/sat/msat/msat.h
@@ -21,6 +21,10 @@
#ifndef __MSAT_H__
#define __MSAT_H__
+#ifdef __cplusplus
+extern "C" {
+#endif
+
////////////////////////////////////////////////////////////////////////
/// INCLUDES ///
////////////////////////////////////////////////////////////////////////
@@ -65,7 +69,7 @@ typedef enum { MSAT_FALSE = -1, MSAT_UNKNOWN = 0, MSAT_TRUE = 1 } Msat_Type_t;
////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////
-/// MACRO DEFITIONS ///
+/// MACRO DEFINITIONS ///
////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////
@@ -76,10 +80,10 @@ typedef enum { MSAT_FALSE = -1, MSAT_UNKNOWN = 0, MSAT_TRUE = 1 } Msat_Type_t;
extern bool Msat_SolverParseDimacs( FILE * pFile, Msat_Solver_t ** p, int fVerbose );
/*=== satSolver.c ===========================================================*/
// adding vars, clauses, simplifying the database, and solving
-extern bool Msat_SolverAddVar( Msat_Solver_t * p );
+extern bool Msat_SolverAddVar( Msat_Solver_t * p, int Level );
extern bool Msat_SolverAddClause( Msat_Solver_t * p, Msat_IntVec_t * pLits );
extern bool Msat_SolverSimplifyDB( Msat_Solver_t * p );
-extern bool Msat_SolverSolve( Msat_Solver_t * p, Msat_IntVec_t * pVecAssumps, int nBackTrackLimit );
+extern bool Msat_SolverSolve( Msat_Solver_t * p, Msat_IntVec_t * pVecAssumps, int nBackTrackLimit, int nTimeLimit );
// printing stats, assignments, and clauses
extern void Msat_SolverPrintStats( Msat_Solver_t * p );
extern void Msat_SolverPrintAssignment( Msat_Solver_t * p );
@@ -87,17 +91,20 @@ extern void Msat_SolverPrintClauses( Msat_Solver_t * p );
extern void Msat_SolverWriteDimacs( Msat_Solver_t * p, char * pFileName );
// access to the solver internal data
extern int Msat_SolverReadVarNum( Msat_Solver_t * p );
+extern int Msat_SolverReadClauseNum( Msat_Solver_t * p );
extern int Msat_SolverReadVarAllocNum( Msat_Solver_t * p );
extern int * Msat_SolverReadAssignsArray( Msat_Solver_t * p );
extern int * Msat_SolverReadModelArray( Msat_Solver_t * p );
extern unsigned Msat_SolverReadTruth( Msat_Solver_t * p );
extern int Msat_SolverReadBackTracks( Msat_Solver_t * p );
+extern int Msat_SolverReadInspects( Msat_Solver_t * p );
extern void Msat_SolverSetVerbosity( Msat_Solver_t * p, int fVerbose );
extern void Msat_SolverSetProofWriting( Msat_Solver_t * p, int fProof );
extern void Msat_SolverSetVarTypeA( Msat_Solver_t * p, int Var );
extern void Msat_SolverSetVarMap( Msat_Solver_t * p, Msat_IntVec_t * vVarMap );
extern void Msat_SolverMarkLastClauseTypeA( Msat_Solver_t * p );
extern void Msat_SolverMarkClausesStart( Msat_Solver_t * p );
+extern float * Msat_SolverReadFactors( Msat_Solver_t * p );
// returns the solution after incremental solving
extern int Msat_SolverReadSolutions( Msat_Solver_t * p );
extern int * Msat_SolverReadSolutionsArray( Msat_Solver_t * p );
@@ -153,8 +160,13 @@ extern double Msat_VarHeapReadMaxWeight( Msat_VarHeap_t * p );
extern int Msat_VarHeapCountNodes( Msat_VarHeap_t * p, double WeightLimit );
extern int Msat_VarHeapReadMax( Msat_VarHeap_t * p );
extern int Msat_VarHeapGetMax( Msat_VarHeap_t * p );
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
////////////////////////////////////////////////////////////////////////
/// END OF FILE ///
////////////////////////////////////////////////////////////////////////
-#endif
diff --git a/src/sat/msat/msatActivity.c b/src/sat/msat/msatActivity.c
index c9a518ce..1cd795bd 100644
--- a/src/sat/msat/msatActivity.c
+++ b/src/sat/msat/msatActivity.c
@@ -25,7 +25,7 @@
////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////
-/// FUNCTION DEFITIONS ///
+/// FUNCTION DEFINITIONS ///
////////////////////////////////////////////////////////////////////////
/**Function*************************************************************
@@ -45,7 +45,9 @@ void Msat_SolverVarBumpActivity( Msat_Solver_t * p, Msat_Lit_t Lit )
if ( p->dVarDecay < 0 ) // (negative decay means static variable order -- don't bump)
return;
Var = MSAT_LIT2VAR(Lit);
- if ( (p->pdActivity[Var] += p->dVarInc) > 1e100 )
+ p->pdActivity[Var] += p->dVarInc;
+// p->pdActivity[Var] += p->dVarInc * p->pFactors[Var];
+ if ( p->pdActivity[Var] > 1e100 )
Msat_SolverVarRescaleActivity( p );
Msat_OrderUpdate( p->pOrder, Var );
}
diff --git a/src/sat/msat/msatClause.c b/src/sat/msat/msatClause.c
index dc39bee6..2ba8cd32 100644
--- a/src/sat/msat/msatClause.c
+++ b/src/sat/msat/msatClause.c
@@ -36,7 +36,7 @@ struct Msat_Clause_t_
};
////////////////////////////////////////////////////////////////////////
-/// FUNCTION DEFITIONS ///
+/// FUNCTION DEFINITIONS ///
////////////////////////////////////////////////////////////////////////
/**Function*************************************************************
@@ -82,6 +82,10 @@ bool Msat_ClauseCreate( Msat_Solver_t * p, Msat_IntVec_t * vLits, bool fLearned,
// nSeenId - 1 stands for negative
// nSeenId stands for positive
// Remove false literals
+
+ // there is a bug here!!!!
+ // when the same var in opposite polarities is given, it drops one polarity!!!
+
for ( i = j = 0; i < nLits; i++ ) {
// get the corresponding variable
Var = MSAT_LIT2VAR(pLits[i]);
@@ -190,6 +194,7 @@ bool Msat_ClauseCreate( Msat_Solver_t * p, Msat_IntVec_t * vLits, bool fLearned,
{
Msat_SolverVarBumpActivity( p, pLits[i] );
// Msat_SolverVarBumpActivity( p, pLits[i] );
+// p->pFreq[ MSAT_LIT2VAR(pLits[i]) ]++;
}
}
diff --git a/src/sat/msat/msatClauseVec.c b/src/sat/msat/msatClauseVec.c
index 7c24619f..04691cf2 100644
--- a/src/sat/msat/msatClauseVec.c
+++ b/src/sat/msat/msatClauseVec.c
@@ -25,7 +25,7 @@
////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////
-/// FUNCTION DEFITIONS ///
+/// FUNCTION DEFINITIONS ///
////////////////////////////////////////////////////////////////////////
/**Function*************************************************************
diff --git a/src/sat/msat/msatInt.h b/src/sat/msat/msatInt.h
index 037616f6..03903abe 100644
--- a/src/sat/msat/msatInt.h
+++ b/src/sat/msat/msatInt.h
@@ -56,10 +56,10 @@ typedef long long int64;
#define ALLOC(type, num) \
((type *) malloc(sizeof(type) * (num)))
#define REALLOC(type, obj, num) \
- (obj) ? ((type *) realloc((char *) obj, sizeof(type) * (num))) : \
- ((type *) malloc(sizeof(type) * (num)))
+ ((obj) ? ((type *) realloc((char *)(obj), sizeof(type) * (num))) : \
+ ((type *) malloc(sizeof(type) * (num))))
#define FREE(obj) \
- ((obj) ? (free((char *) (obj)), (obj) = 0) : 0)
+ ((obj) ? (free((char *)(obj)), (obj) = 0) : 0)
// By default, custom memory management is used
// which guarantees constant time allocation/deallocation
@@ -119,6 +119,7 @@ struct Msat_Solver_t_
double dClaDecay; // INVERSE decay factor for clause activity: stores 1/decay.
double * pdActivity; // A heuristic measurement of the activity of a variable.
+ float * pFactors; // the multiplicative factors of variable activity
double dVarInc; // Amount to bump next variable with.
double dVarDecay; // INVERSE decay factor for variable activity: stores 1/decay. Use negative value for static variable order.
Msat_Order_t * pOrder; // Keeps track of the decision variable order.
@@ -151,6 +152,7 @@ struct Msat_Solver_t_
int nSeenId; // the id of current seeing
Msat_IntVec_t * vReason; // the temporary array of literals
Msat_IntVec_t * vTemp; // the temporary array of literals
+ int * pFreq; // the number of times each var participated in conflicts
// the memory manager
Msat_MmStep_t * pMem;
@@ -184,7 +186,7 @@ struct Msat_IntVec_t_
////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////
-/// MACRO DEFITIONS ///
+/// MACRO DEFINITIONS ///
////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////
diff --git a/src/sat/msat/msatMem.c b/src/sat/msat/msatMem.c
index 2d178094..30bf4a96 100644
--- a/src/sat/msat/msatMem.c
+++ b/src/sat/msat/msatMem.c
@@ -72,7 +72,7 @@ struct Msat_MmStep_t_
};
////////////////////////////////////////////////////////////////////////
-/// FUNCTION DEFITIONS ///
+/// FUNCTION DEFINITIONS ///
////////////////////////////////////////////////////////////////////////
/**Function*************************************************************
@@ -231,7 +231,7 @@ void Msat_MmFixedRestart( Msat_MmFixed_t * p )
int i;
char * pTemp;
- // delocate all chunks except the first one
+ // deallocate all chunks except the first one
for ( i = 1; i < p->nChunks; i++ )
free( p->pChunks[i] );
p->nChunks = 1;
diff --git a/src/sat/msat/msatOrderH.c b/src/sat/msat/msatOrderH.c
index ca034233..956e7fc6 100644
--- a/src/sat/msat/msatOrderH.c
+++ b/src/sat/msat/msatOrderH.c
@@ -58,7 +58,7 @@ static void Msat_HeapPercolateDown( Msat_Order_t * p, int i );
extern int timeSelect;
////////////////////////////////////////////////////////////////////////
-/// FUNCTION DEFITIONS ///
+/// FUNCTION DEFINITIONS ///
////////////////////////////////////////////////////////////////////////
/**Function*************************************************************
diff --git a/src/sat/msat/msatOrderJ.c b/src/sat/msat/msatOrderJ.c
index 6067b40f..4db7ff7b 100644
--- a/src/sat/msat/msatOrderJ.c
+++ b/src/sat/msat/msatOrderJ.c
@@ -38,7 +38,7 @@ struct Msat_OrderVar_t_
{
Msat_OrderVar_t * pNext;
Msat_OrderVar_t * pPrev;
- int Num;
+ int Num;
};
// the ring of variables data structure (J-boundary)
@@ -82,7 +82,7 @@ extern int timeSelect;
extern int timeAssign;
////////////////////////////////////////////////////////////////////////
-/// FUNCTION DEFITIONS ///
+/// FUNCTION DEFINITIONS ///
////////////////////////////////////////////////////////////////////////
/**Function*************************************************************
@@ -170,7 +170,8 @@ int Msat_OrderCheck( Msat_Order_t * p )
Msat_OrderVar_t * pVar, * pNext;
Msat_IntVec_t * vRound;
int * pRound, nRound;
- int * pVars, nVars, i;
+ int * pVars, nVars, i, k;
+ int Counter = 0;
// go through all the variables in the boundary
Msat_OrderRingForEachEntry( p->rVars.pRoot, pVar, pNext )
@@ -188,10 +189,14 @@ int Msat_OrderCheck( Msat_Order_t * p )
if ( Msat_OrderVarIsAssigned(p, pRound[i]) )
break;
}
- assert( i != nRound );
- if ( i != nRound )
- return 0;
+// assert( i != nRound );
+// if ( i == nRound )
+// return 0;
+ if ( i == nRound )
+ Counter++;
}
+ if ( Counter > 0 )
+ printf( "%d(%d) ", Counter, p->rVars.nItems );
// we may also check other unassigned variables in the cone
// to make sure that if they are not in J-boundary,
@@ -209,16 +214,16 @@ int Msat_OrderCheck( Msat_Order_t * p )
vRound = (Msat_IntVec_t *)Msat_ClauseVecReadEntry( p->pSat->vAdjacents, pVars[i] );
nRound = Msat_IntVecReadSize( vRound );
pRound = Msat_IntVecReadArray( vRound );
- for ( i = 0; i < nRound; i++ )
+ for ( k = 0; k < nRound; k++ )
{
- if ( !Msat_OrderVarIsUsedInCone(p, pRound[i]) )
+ if ( !Msat_OrderVarIsUsedInCone(p, pRound[k]) )
continue;
- if ( Msat_OrderVarIsAssigned(p, pRound[i]) )
+ if ( Msat_OrderVarIsAssigned(p, pRound[k]) )
break;
}
- assert( i == nRound );
- if ( i == nRound )
- return 0;
+// assert( k == nRound );
+// if ( k != nRound )
+// return 0;
}
return 1;
}
@@ -256,7 +261,7 @@ int Msat_OrderVarSelect( Msat_Order_t * p )
Msat_OrderVar_t * pVar, * pNext, * pVarBest;
double * pdActs = p->pSat->pdActivity;
double dfActBest;
- int clk = clock();
+// int clk = clock();
pVarBest = NULL;
dfActBest = -1.0;
@@ -268,12 +273,13 @@ int Msat_OrderVarSelect( Msat_Order_t * p )
pVarBest = pVar;
}
}
-timeSelect += clock() - clk;
-timeAssign += clock() - clk;
+//timeSelect += clock() - clk;
+//timeAssign += clock() - clk;
//if ( pVarBest && pVarBest->Num % 1000 == 0 )
//printf( "%d ", p->rVars.nItems );
+// Msat_OrderCheck( p );
if ( pVarBest )
{
assert( Msat_OrderVarIsUsedInCone(p, pVarBest->Num) );
@@ -296,7 +302,7 @@ timeAssign += clock() - clk;
void Msat_OrderVarAssigned( Msat_Order_t * p, int Var )
{
Msat_IntVec_t * vRound;
- int i, clk = clock();
+ int i;//, clk = clock();
// make sure the variable is in the boundary
assert( Var < p->nVarsAlloc );
@@ -316,7 +322,7 @@ void Msat_OrderVarAssigned( Msat_Order_t * p, int Var )
continue;
Msat_OrderRingAddLast( &p->rVars, &p->pVars[vRound->pArray[i]] );
}
-timeSelect += clock() - clk;
+//timeSelect += clock() - clk;
// Msat_OrderCheck( p );
}
@@ -334,7 +340,7 @@ timeSelect += clock() - clk;
void Msat_OrderVarUnassigned( Msat_Order_t * p, int Var )
{
Msat_IntVec_t * vRound, * vRound2;
- int i, k, clk = clock();
+ int i, k;//, clk = clock();
// make sure the variable is not in the boundary
assert( Var < p->nVarsAlloc );
@@ -363,7 +369,7 @@ void Msat_OrderVarUnassigned( Msat_Order_t * p, int Var )
if ( k == vRound2->nSize ) // there is no assigned vars, delete this one
Msat_OrderRingRemove( &p->rVars, &p->pVars[vRound->pArray[i]] );
}
-timeSelect += clock() - clk;
+//timeSelect += clock() - clk;
// Msat_OrderCheck( p );
}
@@ -450,7 +456,7 @@ void Msat_OrderRingRemove( Msat_OrderRing_t * pRing, Msat_OrderVar_t * pVar )
pRing->pRoot = pVar->pNext;
// move the root to the next entry after pVar
// this way all the additions to the list will be traversed first
-// pRing->pRoot = pVar->pNext;
+// pRing->pRoot = pVar->pPrev;
// delete the node
pVar->pPrev->pNext = pVar->pNext;
pVar->pNext->pPrev = pVar->pPrev;
diff --git a/src/sat/msat/msatQueue.c b/src/sat/msat/msatQueue.c
index c12cc75d..5938e042 100644
--- a/src/sat/msat/msatQueue.c
+++ b/src/sat/msat/msatQueue.c
@@ -33,7 +33,7 @@ struct Msat_Queue_t_
};
////////////////////////////////////////////////////////////////////////
-/// FUNCTION DEFITIONS ///
+/// FUNCTION DEFINITIONS ///
////////////////////////////////////////////////////////////////////////
/**Function*************************************************************
diff --git a/src/sat/msat/msatRead.c b/src/sat/msat/msatRead.c
index b8e585a4..738562ef 100644
--- a/src/sat/msat/msatRead.c
+++ b/src/sat/msat/msatRead.c
@@ -27,7 +27,7 @@
static char * Msat_FileRead( FILE * pFile );
////////////////////////////////////////////////////////////////////////
-/// FUNCTION DEFITIONS ///
+/// FUNCTION DEFINITIONS ///
////////////////////////////////////////////////////////////////////////
/**Function*************************************************************
diff --git a/src/sat/msat/msatSolverApi.c b/src/sat/msat/msatSolverApi.c
index ba506993..ee3507a6 100644
--- a/src/sat/msat/msatSolverApi.c
+++ b/src/sat/msat/msatSolverApi.c
@@ -27,7 +27,7 @@
static void Msat_SolverSetupTruthTables( unsigned uTruths[][2] );
////////////////////////////////////////////////////////////////////////
-/// FUNCTION DEFITIONS ///
+/// FUNCTION DEFINITIONS ///
////////////////////////////////////////////////////////////////////////
/**Function*************************************************************
@@ -41,27 +41,30 @@ static void Msat_SolverSetupTruthTables( unsigned uTruths[][2] );
SeeAlso []
***********************************************************************/
-int Msat_SolverReadVarNum( Msat_Solver_t * p ) { return p->nVars; }
-int Msat_SolverReadVarAllocNum( Msat_Solver_t * p ) { return p->nVarsAlloc;}
+int Msat_SolverReadVarNum( Msat_Solver_t * p ) { return p->nVars; }
+int Msat_SolverReadClauseNum( Msat_Solver_t * p ) { return p->nClauses; }
+int Msat_SolverReadVarAllocNum( Msat_Solver_t * p ) { return p->nVarsAlloc; }
int Msat_SolverReadDecisionLevel( Msat_Solver_t * p ) { return Msat_IntVecReadSize(p->vTrailLim); }
-int * Msat_SolverReadDecisionLevelArray( Msat_Solver_t * p ) { return p->pLevel; }
-Msat_Clause_t ** Msat_SolverReadReasonArray( Msat_Solver_t * p ) { return p->pReasons; }
+int * Msat_SolverReadDecisionLevelArray( Msat_Solver_t * p ) { return p->pLevel; }
+Msat_Clause_t ** Msat_SolverReadReasonArray( Msat_Solver_t * p ) { return p->pReasons; }
Msat_Lit_t Msat_SolverReadVarValue( Msat_Solver_t * p, Msat_Var_t Var ) { return p->pAssigns[Var]; }
-Msat_ClauseVec_t * Msat_SolverReadLearned( Msat_Solver_t * p ) { return p->vLearned; }
-Msat_ClauseVec_t ** Msat_SolverReadWatchedArray( Msat_Solver_t * p ) { return p->pvWatched; }
-int * Msat_SolverReadAssignsArray( Msat_Solver_t * p ) { return p->pAssigns; }
-int * Msat_SolverReadModelArray( Msat_Solver_t * p ) { return p->pModel; }
-int Msat_SolverReadBackTracks( Msat_Solver_t * p ) { return p->nBackTracks; }
-Msat_MmStep_t * Msat_SolverReadMem( Msat_Solver_t * p ) { return p->pMem; }
-int * Msat_SolverReadSeenArray( Msat_Solver_t * p ) { return p->pSeen; }
-int Msat_SolverIncrementSeenId( Msat_Solver_t * p ) { return ++p->nSeenId; }
+Msat_ClauseVec_t * Msat_SolverReadLearned( Msat_Solver_t * p ) { return p->vLearned; }
+Msat_ClauseVec_t ** Msat_SolverReadWatchedArray( Msat_Solver_t * p ) { return p->pvWatched; }
+int * Msat_SolverReadAssignsArray( Msat_Solver_t * p ) { return p->pAssigns; }
+int * Msat_SolverReadModelArray( Msat_Solver_t * p ) { return p->pModel; }
+int Msat_SolverReadBackTracks( Msat_Solver_t * p ) { return (int)p->Stats.nConflicts; }
+int Msat_SolverReadInspects( Msat_Solver_t * p ) { return (int)p->Stats.nInspects; }
+Msat_MmStep_t * Msat_SolverReadMem( Msat_Solver_t * p ) { return p->pMem; }
+int * Msat_SolverReadSeenArray( Msat_Solver_t * p ) { return p->pSeen; }
+int Msat_SolverIncrementSeenId( Msat_Solver_t * p ) { return ++p->nSeenId; }
void Msat_SolverSetVerbosity( Msat_Solver_t * p, int fVerbose ) { p->fVerbose = fVerbose; }
-void Msat_SolverClausesIncrement( Msat_Solver_t * p ) { p->nClausesAlloc++; }
-void Msat_SolverClausesDecrement( Msat_Solver_t * p ) { p->nClausesAlloc--; }
-void Msat_SolverClausesIncrementL( Msat_Solver_t * p ) { p->nClausesAllocL++; }
-void Msat_SolverClausesDecrementL( Msat_Solver_t * p ) { p->nClausesAllocL--; }
+void Msat_SolverClausesIncrement( Msat_Solver_t * p ) { p->nClausesAlloc++; }
+void Msat_SolverClausesDecrement( Msat_Solver_t * p ) { p->nClausesAlloc--; }
+void Msat_SolverClausesIncrementL( Msat_Solver_t * p ) { p->nClausesAllocL++; }
+void Msat_SolverClausesDecrementL( Msat_Solver_t * p ) { p->nClausesAllocL--; }
void Msat_SolverMarkLastClauseTypeA( Msat_Solver_t * p ) { Msat_ClauseSetTypeA( Msat_ClauseVecReadEntry( p->vClauses, Msat_ClauseVecReadSize(p->vClauses)-1 ), 1 ); }
void Msat_SolverMarkClausesStart( Msat_Solver_t * p ) { p->nClausesStart = Msat_ClauseVecReadSize(p->vClauses); }
+float * Msat_SolverReadFactors( Msat_Solver_t * p ) { return p->pFactors; }
/**Function*************************************************************
@@ -172,8 +175,12 @@ Msat_Solver_t * Msat_SolverAlloc( int nVarsAlloc,
p->dVarDecay = dVarDecay;
p->pdActivity = ALLOC( double, p->nVarsAlloc );
+ p->pFactors = ALLOC( float, p->nVarsAlloc );
for ( i = 0; i < p->nVarsAlloc; i++ )
- p->pdActivity[i] = 0;
+ {
+ p->pdActivity[i] = 0.0;
+ p->pFactors[i] = 1.0;
+ }
p->pAssigns = ALLOC( int, p->nVarsAlloc );
p->pModel = ALLOC( int, p->nVarsAlloc );
@@ -237,8 +244,12 @@ void Msat_SolverResize( Msat_Solver_t * p, int nVarsAlloc )
p->nVarsAlloc = nVarsAlloc;
p->pdActivity = REALLOC( double, p->pdActivity, p->nVarsAlloc );
+ p->pFactors = REALLOC( float, p->pFactors, p->nVarsAlloc );
for ( i = nVarsAllocOld; i < p->nVarsAlloc; i++ )
- p->pdActivity[i] = 0;
+ {
+ p->pdActivity[i] = 0.0;
+ p->pFactors[i] = 1.0;
+ }
p->pAssigns = REALLOC( int, p->pAssigns, p->nVarsAlloc );
p->pModel = REALLOC( int, p->pModel, p->nVarsAlloc );
@@ -392,6 +403,7 @@ void Msat_SolverFree( Msat_Solver_t * p )
Msat_ClauseVecFree( p->vLearned );
FREE( p->pdActivity );
+ FREE( p->pFactors );
Msat_OrderFree( p->pOrder );
for ( i = 0; i < 2 * p->nVarsAlloc; i++ )
diff --git a/src/sat/msat/msatSolverCore.c b/src/sat/msat/msatSolverCore.c
index b8d9f328..f9fee73c 100644
--- a/src/sat/msat/msatSolverCore.c
+++ b/src/sat/msat/msatSolverCore.c
@@ -25,7 +25,7 @@
////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////
-/// FUNCTION DEFITIONS ///
+/// FUNCTION DEFINITIONS ///
////////////////////////////////////////////////////////////////////////
/**Function*************************************************************
@@ -39,10 +39,11 @@
SeeAlso []
***********************************************************************/
-bool Msat_SolverAddVar( Msat_Solver_t * p )
+bool Msat_SolverAddVar( Msat_Solver_t * p, int Level )
{
if ( p->nVars == p->nVarsAlloc )
Msat_SolverResize( p, 2 * p->nVarsAlloc );
+ p->pLevel[p->nVars] = Level;
p->nVars++;
return 1;
}
@@ -131,14 +132,18 @@ void Msat_SolverPrintStats( Msat_Solver_t * p )
SeeAlso []
***********************************************************************/
-bool Msat_SolverSolve( Msat_Solver_t * p, Msat_IntVec_t * vAssumps, int nBackTrackLimit )
+bool Msat_SolverSolve( Msat_Solver_t * p, Msat_IntVec_t * vAssumps, int nBackTrackLimit, int nTimeLimit )
{
Msat_SearchParams_t Params = { 0.95, 0.999 };
double nConflictsLimit, nLearnedLimit;
Msat_Type_t Status;
+ int timeStart = clock();
int64 nConflictsOld = p->Stats.nConflicts;
int64 nDecisionsOld = p->Stats.nDecisions;
+// p->pFreq = ALLOC( int, p->nVarsAlloc );
+// memset( p->pFreq, 0, sizeof(int) * p->nVarsAlloc );
+
if ( vAssumps )
{
int * pAssumps, nAssumps, i;
@@ -172,11 +177,31 @@ bool Msat_SolverSolve( Msat_Solver_t * p, Msat_IntVec_t * vAssumps, int nBackTra
nConflictsLimit *= 1.5;
nLearnedLimit *= 1.1;
// if the limit on the number of backtracks is given, quit the restart loop
- if ( nBackTrackLimit > 0 )
+ if ( nBackTrackLimit > 0 && (int)p->Stats.nConflicts - p->nBackTracks > nBackTrackLimit )
+ break;
+ // if the runtime limit is exceeded, quit the restart loop
+ if ( nTimeLimit > 0 && clock() - timeStart >= nTimeLimit * CLOCKS_PER_SEC )
break;
}
Msat_SolverCancelUntil( p, 0 );
p->nBackTracks = (int)p->Stats.nConflicts - p->nBackTracks;
+/*
+ PRT( "True solver runtime", clock() - timeStart );
+ // print the statistics
+ {
+ int i, Counter = 0;
+ for ( i = 0; i < p->nVars; i++ )
+ if ( p->pFreq[i] > 0 )
+ {
+ printf( "%d ", p->pFreq[i] );
+ Counter++;
+ }
+ if ( Counter )
+ printf( "\n" );
+ printf( "Total = %d. Used = %d. Decisions = %d. Imps = %d. Conflicts = %d. ", p->nVars, Counter, (int)p->Stats.nDecisions, (int)p->Stats.nPropagations, (int)p->Stats.nConflicts );
+ PRT( "Time", clock() - timeStart );
+ }
+*/
return Status;
}
diff --git a/src/sat/msat/msatSolverIo.c b/src/sat/msat/msatSolverIo.c
index f17595a7..05b7f6a9 100644
--- a/src/sat/msat/msatSolverIo.c
+++ b/src/sat/msat/msatSolverIo.c
@@ -27,7 +27,7 @@
static char * Msat_TimeStamp();
////////////////////////////////////////////////////////////////////////
-/// FUNCTION DEFITIONS ///
+/// FUNCTION DEFINITIONS ///
////////////////////////////////////////////////////////////////////////
/**Function*************************************************************
diff --git a/src/sat/msat/msatSolverSearch.c b/src/sat/msat/msatSolverSearch.c
index 13a0c403..11a6540c 100644
--- a/src/sat/msat/msatSolverSearch.c
+++ b/src/sat/msat/msatSolverSearch.c
@@ -31,7 +31,7 @@ static void Msat_SolverAnalyze( Msat_Solver_t * p, Msat_Clause_t * pC
static void Msat_SolverReduceDB( Msat_Solver_t * p );
////////////////////////////////////////////////////////////////////////
-/// FUNCTION DEFITIONS ///
+/// FUNCTION DEFINITIONS ///
////////////////////////////////////////////////////////////////////////
/**Function*************************************************************
@@ -534,12 +534,18 @@ Msat_Type_t Msat_SolverSearch( Msat_Solver_t * p, int nConfLimit, int nLearnedLi
Msat_Clause_t * pConf;
Msat_Var_t Var;
int nLevelBack, nConfs, nAssigns, Value;
+ int i;
assert( Msat_SolverReadDecisionLevel(p) == p->nLevelRoot );
p->Stats.nStarts++;
p->dVarDecay = 1 / pPars->dVarDecay;
p->dClaDecay = 1 / pPars->dClaDecay;
+ // reset the activities
+ for ( i = 0; i < p->nVars; i++ )
+ p->pdActivity[i] = (double)p->pFactors[i];
+// p->pdActivity[i] = 0.0;
+
nConfs = 0;
while ( 1 )
{
@@ -599,7 +605,7 @@ Msat_Type_t Msat_SolverSearch( Msat_Solver_t * p, int nConfLimit, int nLearnedLi
Msat_SolverCancelUntil( p, p->nLevelRoot );
return MSAT_UNKNOWN;
}
- else if ( nBackTrackLimit > 0 && nConfs > nBackTrackLimit ) {
+ else if ( nBackTrackLimit > 0 && (int)p->Stats.nConflicts - p->nBackTracks > nBackTrackLimit ) {
// Reached bound on number of conflicts:
Msat_QueueClear( p->pQueue );
Msat_SolverCancelUntil( p, p->nLevelRoot );
diff --git a/src/sat/msat/msatSort.c b/src/sat/msat/msatSort.c
index 2198d303..3b89d102 100644
--- a/src/sat/msat/msatSort.c
+++ b/src/sat/msat/msatSort.c
@@ -41,7 +41,7 @@ static int irand(double seed, int size) {
static void Msat_SolverSort( Msat_Clause_t ** array, int size, double seed );
////////////////////////////////////////////////////////////////////////
-/// FUNCTION DEFITIONS ///
+/// FUNCTION DEFINITIONS ///
////////////////////////////////////////////////////////////////////////
/**Function*************************************************************
diff --git a/src/sat/msat/msatVec.c b/src/sat/msat/msatVec.c
index 951969cf..75f53047 100644
--- a/src/sat/msat/msatVec.c
+++ b/src/sat/msat/msatVec.c
@@ -28,7 +28,7 @@ static int Msat_IntVecSortCompare1( int * pp1, int * pp2 );
static int Msat_IntVecSortCompare2( int * pp1, int * pp2 );
////////////////////////////////////////////////////////////////////////
-/// FUNCTION DEFITIONS ///
+/// FUNCTION DEFINITIONS ///
////////////////////////////////////////////////////////////////////////
/**Function*************************************************************
diff --git a/src/sat/proof/pr.c b/src/sat/proof/pr.c
new file mode 100644
index 00000000..2d1ab2d1
--- /dev/null
+++ b/src/sat/proof/pr.c
@@ -0,0 +1,1263 @@
+/**CFile****************************************************************
+
+ FileName [pr.c]
+
+ SystemName [ABC: Logic synthesis and verification system.]
+
+ PackageName [Proof recording.]
+
+ Synopsis [Core procedures of the package.]
+
+ Author [Alan Mishchenko]
+
+ Affiliation [UC Berkeley]
+
+ Date [Ver. 1.0. Started - June 20, 2005.]
+
+ Revision [$Id: pr.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <assert.h>
+#include <time.h>
+//#include "vec.h"
+#include "pr.h"
+
+////////////////////////////////////////////////////////////////////////
+/// DECLARATIONS ///
+////////////////////////////////////////////////////////////////////////
+
+typedef unsigned lit;
+
+typedef struct Pr_Cls_t_ Pr_Cls_t;
+struct Pr_Cls_t_
+{
+ unsigned uTruth; // interpolant
+ void * pProof; // the proof node
+// void * pAntis; // the anticedents
+ Pr_Cls_t * pNext; // the next clause
+ Pr_Cls_t * pNext0; // the next 0-watch
+ Pr_Cls_t * pNext1; // the next 0-watch
+ int Id; // the clause ID
+ unsigned fA : 1; // belongs to A
+ unsigned fRoot : 1; // original clause
+ unsigned fVisit : 1; // visited clause
+ unsigned nLits : 24; // the number of literals
+ lit pLits[0]; // literals of this clause
+};
+
+struct Pr_Man_t_
+{
+ // general data
+ int fProofWrite; // writes the proof file
+ int fProofVerif; // verifies the proof
+ int nVars; // the number of variables
+ int nVarsAB; // the number of global variables
+ int nRoots; // the number of root clauses
+ int nClauses; // the number of all clauses
+ int nClausesA; // the number of clauses of A
+ Pr_Cls_t * pHead; // the head clause
+ Pr_Cls_t * pTail; // the tail clause
+ Pr_Cls_t * pLearnt; // the tail clause
+ Pr_Cls_t * pEmpty; // the empty clause
+ // internal BCP
+ int nRootSize; // the number of root level assignments
+ int nTrailSize; // the number of assignments made
+ lit * pTrail; // chronological order of assignments (size nVars)
+ lit * pAssigns; // assignments by variable (size nVars)
+ char * pSeens; // temporary mark (size nVars)
+ char * pVarTypes; // variable type (size nVars) [1=A, 0=B, <0=AB]
+ Pr_Cls_t ** pReasons; // reasons for each assignment (size nVars)
+ Pr_Cls_t ** pWatches; // watched clauses for each literal (size 2*nVars)
+ int nVarsAlloc; // the allocated size of arrays
+ // proof recording
+ void * pManProof; // proof manager
+ int Counter; // counter of resolved clauses
+ // memory management
+ int nChunkSize; // the number of bytes in a chunk
+ int nChunkUsed; // the number of bytes used in the last chunk
+ char * pChunkLast; // the last memory chunk
+ // internal verification
+ lit * pResLits; // the literals of the resolvent
+ int nResLits; // the number of literals of the resolvent
+ int nResLitsAlloc;// the number of literals of the resolvent
+ // runtime stats
+ int timeBcp;
+ int timeTrace;
+ int timeRead;
+ int timeTotal;
+};
+
+#ifndef PRT
+#define PRT(a,t) printf("%s = ", (a)); printf("%6.2f sec\n", (float)(t)/(float)(CLOCKS_PER_SEC))
+#endif
+
+// variable assignments
+static const lit LIT_UNDEF = 0xffffffff;
+
+// variable/literal conversions (taken from MiniSat)
+static inline lit toLit (int v) { return v + v; }
+static inline lit toLitCond(int v, int c) { return v + v + (c != 0); }
+static inline lit lit_neg (lit l) { return l ^ 1; }
+static inline int lit_var (lit l) { return l >> 1; }
+static inline int lit_sign (lit l) { return l & 1; }
+static inline int lit_print(lit l) { return lit_sign(l)? -lit_var(l)-1 : lit_var(l)+1; }
+static inline lit lit_read (int s) { return s > 0 ? toLit(s-1) : lit_neg(toLit(-s-1)); }
+static inline int lit_check(lit l, int n) { return l >= 0 && lit_var(l) < n; }
+
+// iterators through the clauses
+#define Pr_ManForEachClause( p, pCls ) for( pCls = p->pHead; pCls; pCls = pCls->pNext )
+#define Pr_ManForEachClauseRoot( p, pCls ) for( pCls = p->pHead; pCls != p->pLearnt; pCls = pCls->pNext )
+#define Pr_ManForEachClauseLearnt( p, pCls ) for( pCls = p->pLearnt; pCls; pCls = pCls->pNext )
+
+// static procedures
+static char * Pr_ManMemoryFetch( Pr_Man_t * p, int nBytes );
+static void Pr_ManMemoryStop( Pr_Man_t * p );
+static void Pr_ManResize( Pr_Man_t * p, int nVarsNew );
+
+// exported procedures
+extern Pr_Man_t * Pr_ManAlloc( int nVarsAlloc );
+extern void Pr_ManFree( Pr_Man_t * p );
+extern int Pr_ManAddClause( Pr_Man_t * p, lit * pBeg, lit * pEnd, int fRoot, int fClauseA );
+extern int Pr_ManProofWrite( Pr_Man_t * p );
+
+////////////////////////////////////////////////////////////////////////
+/// FUNCTION DEFINITIONS ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+ Synopsis [Allocate proof manager.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Pr_Man_t * Pr_ManAlloc( int nVarsAlloc )
+{
+ Pr_Man_t * p;
+ // allocate the manager
+ p = (Pr_Man_t *)malloc( sizeof(Pr_Man_t) );
+ memset( p, 0, sizeof(Pr_Man_t) );
+ // allocate internal arrays
+ Pr_ManResize( p, nVarsAlloc? nVarsAlloc : 256 );
+ // set the starting number of variables
+ p->nVars = 0;
+ // memory management
+ p->nChunkSize = (1<<16); // use 64K chunks
+ // verification
+ p->nResLitsAlloc = (1<<16);
+ p->pResLits = malloc( sizeof(lit) * p->nResLitsAlloc );
+ // parameters
+ p->fProofWrite = 0;
+ p->fProofVerif = 0;
+ return p;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Resize proof manager.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Pr_ManResize( Pr_Man_t * p, int nVarsNew )
+{
+ // check if resizing is needed
+ if ( p->nVarsAlloc < nVarsNew )
+ {
+ int nVarsAllocOld = p->nVarsAlloc;
+ // find the new size
+ if ( p->nVarsAlloc == 0 )
+ p->nVarsAlloc = 1;
+ while ( p->nVarsAlloc < nVarsNew )
+ p->nVarsAlloc *= 2;
+ // resize the arrays
+ p->pTrail = (lit *) realloc( p->pTrail, sizeof(lit) * p->nVarsAlloc );
+ p->pAssigns = (lit *) realloc( p->pAssigns, sizeof(lit) * p->nVarsAlloc );
+ p->pSeens = (char *) realloc( p->pSeens, sizeof(char) * p->nVarsAlloc );
+ p->pVarTypes = (char *) realloc( p->pVarTypes, sizeof(char) * p->nVarsAlloc );
+ p->pReasons = (Pr_Cls_t **)realloc( p->pReasons, sizeof(Pr_Cls_t *) * p->nVarsAlloc );
+ p->pWatches = (Pr_Cls_t **)realloc( p->pWatches, sizeof(Pr_Cls_t *) * p->nVarsAlloc*2 );
+ // clean the free space
+ memset( p->pAssigns + nVarsAllocOld, 0xff, sizeof(lit) * (p->nVarsAlloc - nVarsAllocOld) );
+ memset( p->pSeens + nVarsAllocOld, 0, sizeof(char) * (p->nVarsAlloc - nVarsAllocOld) );
+ memset( p->pVarTypes + nVarsAllocOld, 0, sizeof(char) * (p->nVarsAlloc - nVarsAllocOld) );
+ memset( p->pReasons + nVarsAllocOld, 0, sizeof(Pr_Cls_t *) * (p->nVarsAlloc - nVarsAllocOld) );
+ memset( p->pWatches + nVarsAllocOld, 0, sizeof(Pr_Cls_t *) * (p->nVarsAlloc - nVarsAllocOld)*2 );
+ }
+ // adjust the number of variables
+ if ( p->nVars < nVarsNew )
+ p->nVars = nVarsNew;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Deallocate proof manager.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Pr_ManFree( Pr_Man_t * p )
+{
+ printf( "Runtime stats:\n" );
+PRT( "Reading ", p->timeRead );
+PRT( "BCP ", p->timeBcp );
+PRT( "Trace ", p->timeTrace );
+PRT( "TOTAL ", p->timeTotal );
+
+ Pr_ManMemoryStop( p );
+ free( p->pTrail );
+ free( p->pAssigns );
+ free( p->pSeens );
+ free( p->pVarTypes );
+ free( p->pReasons );
+ free( p->pWatches );
+ free( p->pResLits );
+ free( p );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Adds one clause to the watcher list.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+static inline void Pr_ManWatchClause( Pr_Man_t * p, Pr_Cls_t * pClause, lit Lit )
+{
+ assert( lit_check(Lit, p->nVars) );
+ if ( pClause->pLits[0] == Lit )
+ pClause->pNext0 = p->pWatches[lit_neg(Lit)];
+ else
+ {
+ assert( pClause->pLits[1] == Lit );
+ pClause->pNext1 = p->pWatches[lit_neg(Lit)];
+ }
+ p->pWatches[lit_neg(Lit)] = pClause;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Adds one clause to the manager.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Pr_ManAddClause( Pr_Man_t * p, lit * pBeg, lit * pEnd, int fRoot, int fClauseA )
+{
+ Pr_Cls_t * pClause;
+ lit Lit, * i, * j;
+ int nSize, VarMax;
+
+ // process the literals
+ if ( pBeg < pEnd )
+ {
+ // insertion sort
+ VarMax = lit_var( *pBeg );
+ for ( i = pBeg + 1; i < pEnd; i++ )
+ {
+ Lit = *i;
+ VarMax = lit_var(Lit) > VarMax ? lit_var(Lit) : VarMax;
+ for ( j = i; j > pBeg && *(j-1) > Lit; j-- )
+ *j = *(j-1);
+ *j = Lit;
+ }
+ // make sure there is no duplicated variables
+ for ( i = pBeg + 1; i < pEnd; i++ )
+ assert( lit_var(*(i-1)) != lit_var(*i) );
+ // resize the manager
+ Pr_ManResize( p, VarMax+1 );
+ }
+
+ // get memory for the clause
+ nSize = sizeof(Pr_Cls_t) + sizeof(lit) * (pEnd - pBeg);
+ pClause = (Pr_Cls_t *)Pr_ManMemoryFetch( p, nSize );
+ memset( pClause, 0, sizeof(Pr_Cls_t) );
+
+ // assign the clause
+ assert( !fClauseA || fRoot ); // clause of A is always a root clause
+ p->nRoots += fRoot;
+ p->nClausesA += fClauseA;
+ pClause->Id = p->nClauses++;
+ pClause->fA = fClauseA;
+ pClause->fRoot = fRoot;
+ pClause->nLits = pEnd - pBeg;
+ memcpy( pClause->pLits, pBeg, sizeof(lit) * (pEnd - pBeg) );
+
+ // add the clause to the list
+ if ( p->pHead == NULL )
+ p->pHead = pClause;
+ if ( p->pTail == NULL )
+ p->pTail = pClause;
+ else
+ {
+ p->pTail->pNext = pClause;
+ p->pTail = pClause;
+ }
+
+ // mark the first learnt clause
+ if ( p->pLearnt == NULL && !pClause->fRoot )
+ p->pLearnt = pClause;
+
+ // add the empty clause
+ if ( pClause->nLits == 0 )
+ {
+ if ( p->pEmpty )
+ printf( "More than one empty clause!\n" );
+ p->pEmpty = pClause;
+ }
+ return 1;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Fetches memory.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+char * Pr_ManMemoryFetch( Pr_Man_t * p, int nBytes )
+{
+ char * pMem;
+ if ( p->pChunkLast == NULL || nBytes > p->nChunkSize - p->nChunkUsed )
+ {
+ pMem = (char *)malloc( p->nChunkSize );
+ *(char **)pMem = p->pChunkLast;
+ p->pChunkLast = pMem;
+ p->nChunkUsed = sizeof(char *);
+ }
+ pMem = p->pChunkLast + p->nChunkUsed;
+ p->nChunkUsed += nBytes;
+ return pMem;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Frees memory manager.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Pr_ManMemoryStop( Pr_Man_t * p )
+{
+ char * pMem, * pNext;
+ if ( p->pChunkLast == NULL )
+ return;
+ for ( pMem = p->pChunkLast; pNext = *(char **)pMem; pMem = pNext )
+ free( pMem );
+ free( pMem );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Reports memory usage in bytes.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Pr_ManMemoryReport( Pr_Man_t * p )
+{
+ int Total;
+ char * pMem, * pNext;
+ if ( p->pChunkLast == NULL )
+ return 0;
+ Total = p->nChunkUsed;
+ for ( pMem = p->pChunkLast; pNext = *(char **)pMem; pMem = pNext )
+ Total += p->nChunkSize;
+ return Total;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Records the proof.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Extra_PrintBinary_( FILE * pFile, unsigned Sign[], int nBits )
+{
+ int Remainder, nWords;
+ int w, i;
+
+ Remainder = (nBits%(sizeof(unsigned)*8));
+ nWords = (nBits/(sizeof(unsigned)*8)) + (Remainder>0);
+
+ for ( w = nWords-1; w >= 0; w-- )
+ for ( i = ((w == nWords-1 && Remainder)? Remainder-1: 31); i >= 0; i-- )
+ fprintf( pFile, "%c", '0' + (int)((Sign[w] & (1<<i)) > 0) );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Prints the interpolant for one clause.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Pr_ManPrintInterOne( Pr_Man_t * p, Pr_Cls_t * pClause )
+{
+ printf( "Clause %2d : ", pClause->Id );
+ Extra_PrintBinary_( stdout, &pClause->uTruth, (1 << p->nVarsAB) );
+ printf( "\n" );
+}
+
+
+
+/**Function*************************************************************
+
+ Synopsis [Records implication.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+static inline int Pr_ManEnqueue( Pr_Man_t * p, lit Lit, Pr_Cls_t * pReason )
+{
+ int Var = lit_var(Lit);
+ if ( p->pAssigns[Var] != LIT_UNDEF )
+ return p->pAssigns[Var] == Lit;
+ p->pAssigns[Var] = Lit;
+ p->pReasons[Var] = pReason;
+ p->pTrail[p->nTrailSize++] = Lit;
+//printf( "assigning var %d value %d\n", Var, !lit_sign(Lit) );
+ return 1;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Records implication.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+static inline void Pr_ManCancelUntil( Pr_Man_t * p, int Level )
+{
+ lit Lit;
+ int i, Var;
+ for ( i = p->nTrailSize - 1; i >= Level; i-- )
+ {
+ Lit = p->pTrail[i];
+ Var = lit_var( Lit );
+ p->pReasons[Var] = NULL;
+ p->pAssigns[Var] = LIT_UNDEF;
+//printf( "cancelling var %d\n", Var );
+ }
+ p->nTrailSize = Level;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Propagate one assignment.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+static inline Pr_Cls_t * Pr_ManPropagateOne( Pr_Man_t * p, lit Lit )
+{
+ Pr_Cls_t ** ppPrev, * pCur, * pTemp;
+ lit LitF = lit_neg(Lit);
+ int i;
+ // iterate through the literals
+ ppPrev = p->pWatches + Lit;
+ for ( pCur = p->pWatches[Lit]; pCur; pCur = *ppPrev )
+ {
+ // make sure the false literal is in the second literal of the clause
+ if ( pCur->pLits[0] == LitF )
+ {
+ pCur->pLits[0] = pCur->pLits[1];
+ pCur->pLits[1] = LitF;
+ pTemp = pCur->pNext0;
+ pCur->pNext0 = pCur->pNext1;
+ pCur->pNext1 = pTemp;
+ }
+ assert( pCur->pLits[1] == LitF );
+
+ // if the first literal is true, the clause is satisfied
+ if ( pCur->pLits[0] == p->pAssigns[lit_var(pCur->pLits[0])] )
+ {
+ ppPrev = &pCur->pNext1;
+ continue;
+ }
+
+ // look for a new literal to watch
+ for ( i = 2; i < (int)pCur->nLits; i++ )
+ {
+ // skip the case when the literal is false
+ if ( lit_neg(pCur->pLits[i]) == p->pAssigns[lit_var(pCur->pLits[i])] )
+ continue;
+ // the literal is either true or unassigned - watch it
+ pCur->pLits[1] = pCur->pLits[i];
+ pCur->pLits[i] = LitF;
+ // remove this clause from the watch list of Lit
+ *ppPrev = pCur->pNext1;
+ // add this clause to the watch list of pCur->pLits[i] (now it is pCur->pLits[1])
+ Pr_ManWatchClause( p, pCur, pCur->pLits[1] );
+ break;
+ }
+ if ( i < (int)pCur->nLits ) // found new watch
+ continue;
+
+ // clause is unit - enqueue new implication
+ if ( Pr_ManEnqueue(p, pCur->pLits[0], pCur) )
+ {
+ ppPrev = &pCur->pNext1;
+ continue;
+ }
+
+ // conflict detected - return the conflict clause
+ return pCur;
+ }
+ return NULL;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Propagate the current assignments.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Pr_Cls_t * Pr_ManPropagate( Pr_Man_t * p, int Start )
+{
+ Pr_Cls_t * pClause;
+ int i;
+ int clk = clock();
+ for ( i = Start; i < p->nTrailSize; i++ )
+ {
+ pClause = Pr_ManPropagateOne( p, p->pTrail[i] );
+ if ( pClause )
+ {
+p->timeBcp += clock() - clk;
+ return pClause;
+ }
+ }
+p->timeBcp += clock() - clk;
+ return NULL;
+}
+
+
+/**Function*************************************************************
+
+ Synopsis [Prints the clause.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Pr_ManPrintClause( Pr_Cls_t * pClause )
+{
+ int i;
+ printf( "Clause ID = %d. Proof = %d. {", pClause->Id, (int)pClause->pProof );
+ for ( i = 0; i < (int)pClause->nLits; i++ )
+ printf( " %d", pClause->pLits[i] );
+ printf( " }\n" );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Prints the resolvent.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Pr_ManPrintResolvent( lit * pResLits, int nResLits )
+{
+ int i;
+ printf( "Resolvent: {" );
+ for ( i = 0; i < nResLits; i++ )
+ printf( " %d", pResLits[i] );
+ printf( " }\n" );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Writes one root clause into a file.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Pr_ManProofWriteOne( Pr_Man_t * p, Pr_Cls_t * pClause )
+{
+ pClause->pProof = (void *)++p->Counter;
+
+ if ( p->fProofWrite )
+ {
+ int v;
+ fprintf( p->pManProof, "%d", (int)pClause->pProof );
+ for ( v = 0; v < (int)pClause->nLits; v++ )
+ fprintf( p->pManProof, " %d", lit_print(pClause->pLits[v]) );
+ fprintf( p->pManProof, " 0 0\n" );
+ }
+}
+
+/**Function*************************************************************
+
+ Synopsis [Traces the proof for one clause.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Pr_ManProofTraceOne( Pr_Man_t * p, Pr_Cls_t * pConflict, Pr_Cls_t * pFinal )
+{
+ Pr_Cls_t * pReason;
+ int i, v, Var, PrevId;
+ int fPrint = 0;
+ int clk = clock();
+
+ // collect resolvent literals
+ if ( p->fProofVerif )
+ {
+ assert( (int)pConflict->nLits <= p->nResLitsAlloc );
+ memcpy( p->pResLits, pConflict->pLits, sizeof(lit) * pConflict->nLits );
+ p->nResLits = pConflict->nLits;
+ }
+
+ // mark all the variables in the conflict as seen
+ for ( v = 0; v < (int)pConflict->nLits; v++ )
+ p->pSeens[lit_var(pConflict->pLits[v])] = 1;
+
+ // start the anticedents
+// pFinal->pAntis = Vec_PtrAlloc( 32 );
+// Vec_PtrPush( pFinal->pAntis, pConflict );
+
+ if ( p->nClausesA )
+ pFinal->uTruth = pConflict->uTruth;
+
+ // follow the trail backwards
+ PrevId = (int)pConflict->pProof;
+ for ( i = p->nTrailSize - 1; i >= 0; i-- )
+ {
+ // skip literals that are not involved
+ Var = lit_var(p->pTrail[i]);
+ if ( !p->pSeens[Var] )
+ continue;
+ p->pSeens[Var] = 0;
+
+ // skip literals of the resulting clause
+ pReason = p->pReasons[Var];
+ if ( pReason == NULL )
+ continue;
+ assert( p->pTrail[i] == pReason->pLits[0] );
+
+ // add the variables to seen
+ for ( v = 1; v < (int)pReason->nLits; v++ )
+ p->pSeens[lit_var(pReason->pLits[v])] = 1;
+
+
+ // record the reason clause
+ assert( pReason->pProof > 0 );
+ p->Counter++;
+ if ( p->fProofWrite )
+ fprintf( p->pManProof, "%d * %d %d 0\n", p->Counter, PrevId, (int)pReason->pProof );
+ PrevId = p->Counter;
+
+ if ( p->nClausesA )
+ {
+ if ( p->pVarTypes[Var] == 1 ) // var of A
+ pFinal->uTruth |= pReason->uTruth;
+ else
+ pFinal->uTruth &= pReason->uTruth;
+ }
+
+ // resolve the temporary resolvent with the reason clause
+ if ( p->fProofVerif )
+ {
+ int v1, v2;
+ if ( fPrint )
+ Pr_ManPrintResolvent( p->pResLits, p->nResLits );
+ // check that the var is present in the resolvent
+ for ( v1 = 0; v1 < p->nResLits; v1++ )
+ if ( lit_var(p->pResLits[v1]) == Var )
+ break;
+ if ( v1 == p->nResLits )
+ printf( "Recording clause %d: Cannot find variable %d in the temporary resolvent.\n", pFinal->Id, Var );
+ if ( p->pResLits[v1] != lit_neg(pReason->pLits[0]) )
+ printf( "Recording clause %d: The resolved variable %d is in the wrong polarity.\n", pFinal->Id, Var );
+ // remove this variable from the resolvent
+ assert( lit_var(p->pResLits[v1]) == Var );
+ p->nResLits--;
+ for ( ; v1 < p->nResLits; v1++ )
+ p->pResLits[v1] = p->pResLits[v1+1];
+ // add variables of the reason clause
+ for ( v2 = 1; v2 < (int)pReason->nLits; v2++ )
+ {
+ for ( v1 = 0; v1 < p->nResLits; v1++ )
+ if ( lit_var(p->pResLits[v1]) == lit_var(pReason->pLits[v2]) )
+ break;
+ // if it is a new variable, add it to the resolvent
+ if ( v1 == p->nResLits )
+ {
+ if ( p->nResLits == p->nResLitsAlloc )
+ printf( "Recording clause %d: Ran out of space for intermediate resolvent.\n, pFinal->Id" );
+ p->pResLits[ p->nResLits++ ] = pReason->pLits[v2];
+ continue;
+ }
+ // if the variable is the same, the literal should be the same too
+ if ( p->pResLits[v1] == pReason->pLits[v2] )
+ continue;
+ // the literal is different
+ printf( "Recording clause %d: Trying to resolve the clause with more than one opposite literal.\n", pFinal->Id );
+ }
+ }
+
+// Vec_PtrPush( pFinal->pAntis, pReason );
+ }
+
+ // unmark all seen variables
+// for ( i = p->nTrailSize - 1; i >= 0; i-- )
+// p->pSeens[lit_var(p->pTrail[i])] = 0;
+ // check that the literals are unmarked
+// for ( i = p->nTrailSize - 1; i >= 0; i-- )
+// assert( p->pSeens[lit_var(p->pTrail[i])] == 0 );
+
+ // use the resulting clause to check the correctness of resolution
+ if ( p->fProofVerif )
+ {
+ int v1, v2;
+ if ( fPrint )
+ Pr_ManPrintResolvent( p->pResLits, p->nResLits );
+ for ( v1 = 0; v1 < p->nResLits; v1++ )
+ {
+ for ( v2 = 0; v2 < (int)pFinal->nLits; v2++ )
+ if ( pFinal->pLits[v2] == p->pResLits[v1] )
+ break;
+ if ( v2 < (int)pFinal->nLits )
+ continue;
+ break;
+ }
+ if ( v1 < p->nResLits )
+ {
+ printf( "Recording clause %d: The final resolvent is wrong.\n", pFinal->Id );
+ Pr_ManPrintClause( pConflict );
+ Pr_ManPrintResolvent( p->pResLits, p->nResLits );
+ Pr_ManPrintClause( pFinal );
+ }
+ }
+p->timeTrace += clock() - clk;
+
+ // return the proof pointer
+ if ( p->nClausesA )
+ {
+ Pr_ManPrintInterOne( p, pFinal );
+ }
+ return p->Counter;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Records the proof for one clause.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Pr_ManProofRecordOne( Pr_Man_t * p, Pr_Cls_t * pClause )
+{
+ Pr_Cls_t * pConflict;
+ int i;
+
+ // empty clause never ends up there
+ assert( pClause->nLits > 0 );
+ if ( pClause->nLits == 0 )
+ printf( "Error: Empty clause is attempted.\n" );
+
+ // add assumptions to the trail
+ assert( !pClause->fRoot );
+ assert( p->nTrailSize == p->nRootSize );
+ for ( i = 0; i < (int)pClause->nLits; i++ )
+ if ( !Pr_ManEnqueue( p, lit_neg(pClause->pLits[i]), NULL ) )
+ {
+ assert( 0 ); // impossible
+ return 0;
+ }
+
+ // propagate the assumptions
+ pConflict = Pr_ManPropagate( p, p->nRootSize );
+ if ( pConflict == NULL )
+ {
+ assert( 0 ); // cannot prove
+ return 0;
+ }
+
+ // construct the proof
+ pClause->pProof = (void *)Pr_ManProofTraceOne( p, pConflict, pClause );
+
+ // undo to the root level
+ Pr_ManCancelUntil( p, p->nRootSize );
+
+ // add large clauses to the watched lists
+ if ( pClause->nLits > 1 )
+ {
+ Pr_ManWatchClause( p, pClause, pClause->pLits[0] );
+ Pr_ManWatchClause( p, pClause, pClause->pLits[1] );
+ return 1;
+ }
+ assert( pClause->nLits == 1 );
+
+ // if the clause proved is unit, add it and propagate
+ if ( !Pr_ManEnqueue( p, pClause->pLits[0], pClause ) )
+ {
+ assert( 0 ); // impossible
+ return 0;
+ }
+
+ // propagate the assumption
+ pConflict = Pr_ManPropagate( p, p->nRootSize );
+ if ( pConflict )
+ {
+ // construct the proof
+ p->pEmpty->pProof = (void *)Pr_ManProofTraceOne( p, pConflict, p->pEmpty );
+ printf( "Found last conflict after adding unit clause number %d!\n", pClause->Id );
+ return 0;
+ }
+
+ // update the root level
+ p->nRootSize = p->nTrailSize;
+ return 1;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Propagate the root clauses.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Pr_ManProcessRoots( Pr_Man_t * p )
+{
+ Pr_Cls_t * pClause;
+ int Counter;
+
+ // make sure the root clauses are preceeding the learnt clauses
+ Counter = 0;
+ Pr_ManForEachClause( p, pClause )
+ {
+ assert( (int)pClause->fA == (Counter < (int)p->nClausesA) );
+ assert( (int)pClause->fRoot == (Counter < (int)p->nRoots) );
+ Counter++;
+ }
+ assert( p->nClauses == Counter );
+
+ // make sure the last clause if empty
+ assert( p->pTail->nLits == 0 );
+
+ // go through the root unit clauses
+ p->nTrailSize = 0;
+ Pr_ManForEachClauseRoot( p, pClause )
+ {
+ // create watcher lists for the root clauses
+ if ( pClause->nLits > 1 )
+ {
+ Pr_ManWatchClause( p, pClause, pClause->pLits[0] );
+ Pr_ManWatchClause( p, pClause, pClause->pLits[1] );
+ }
+ // empty clause and large clauses
+ if ( pClause->nLits != 1 )
+ continue;
+ // unit clause
+ assert( lit_check(pClause->pLits[0], p->nVars) );
+ if ( !Pr_ManEnqueue( p, pClause->pLits[0], pClause ) )
+ {
+ // detected root level conflict
+ printf( "Pr_ManProcessRoots(): Detected a root-level conflict\n" );
+ assert( 0 );
+ return 0;
+ }
+ }
+
+ // propagate the root unit clauses
+ pClause = Pr_ManPropagate( p, 0 );
+ if ( pClause )
+ {
+ // detected root level conflict
+ printf( "Pr_ManProcessRoots(): Detected a root-level conflict\n" );
+ assert( 0 );
+ return 0;
+ }
+
+ // set the root level
+ p->nRootSize = p->nTrailSize;
+ return 1;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Records the proof.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Pr_ManPrepareInter( Pr_Man_t * p )
+{
+ unsigned uTruths[5] = { 0xAAAAAAAA, 0xCCCCCCCC, 0xF0F0F0F0, 0xFF00FF00, 0xFFFF0000 };
+ Pr_Cls_t * pClause;
+ int Var, v;
+
+ // mark the variable encountered in the clauses of A
+ Pr_ManForEachClauseRoot( p, pClause )
+ {
+ if ( !pClause->fA )
+ break;
+ for ( v = 0; v < (int)pClause->nLits; v++ )
+ p->pVarTypes[lit_var(pClause->pLits[v])] = 1;
+ }
+
+ // check variables that appear in clauses of B
+ p->nVarsAB = 0;
+ Pr_ManForEachClauseRoot( p, pClause )
+ {
+ if ( pClause->fA )
+ continue;
+ for ( v = 0; v < (int)pClause->nLits; v++ )
+ {
+ Var = lit_var(pClause->pLits[v]);
+ if ( p->pVarTypes[Var] == 1 ) // var of A
+ {
+ // change it into a global variable
+ p->nVarsAB++;
+ p->pVarTypes[Var] = -1;
+ }
+ }
+ }
+
+ // order global variables
+ p->nVarsAB = 0;
+ for ( v = 0; v < p->nVars; v++ )
+ if ( p->pVarTypes[v] == -1 )
+ p->pVarTypes[v] -= p->nVarsAB++;
+printf( "There are %d global variables.\n", p->nVarsAB );
+
+ // set interpolants for root clauses
+ Pr_ManForEachClauseRoot( p, pClause )
+ {
+ if ( !pClause->fA ) // clause of B
+ {
+ pClause->uTruth = ~0;
+ Pr_ManPrintInterOne( p, pClause );
+ continue;
+ }
+ // clause of A
+ pClause->uTruth = 0;
+ for ( v = 0; v < (int)pClause->nLits; v++ )
+ {
+ Var = lit_var(pClause->pLits[v]);
+ if ( p->pVarTypes[Var] < 0 ) // global var
+ {
+ if ( lit_sign(pClause->pLits[v]) ) // negative var
+ pClause->uTruth |= ~uTruths[ -p->pVarTypes[Var]-1 ];
+ else
+ pClause->uTruth |= uTruths[ -p->pVarTypes[Var]-1 ];
+ }
+ }
+ Pr_ManPrintInterOne( p, pClause );
+ }
+}
+
+/**Function*************************************************************
+
+ Synopsis [Records the proof.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Pr_ManProofWrite( Pr_Man_t * p )
+{
+ Pr_Cls_t * pClause;
+ int RetValue = 1;
+
+ // propagate root level assignments
+ Pr_ManProcessRoots( p );
+
+ // prepare the interpolant computation
+ if ( p->nClausesA )
+ Pr_ManPrepareInter( p );
+
+ // construct proof for each clause
+ // start the proof
+ if ( p->fProofWrite )
+ p->pManProof = fopen( "proof.cnf_", "w" );
+ p->Counter = 0;
+
+ // write the root clauses
+ Pr_ManForEachClauseRoot( p, pClause )
+ Pr_ManProofWriteOne( p, pClause );
+
+ // consider each learned clause
+ Pr_ManForEachClauseLearnt( p, pClause )
+ {
+ if ( !Pr_ManProofRecordOne( p, pClause ) )
+ {
+ RetValue = 0;
+ break;
+ }
+ }
+
+ if ( p->nClausesA )
+ {
+ printf( "Interpolant: " );
+ }
+
+
+ // stop the proof
+ if ( p->fProofWrite )
+ {
+ fclose( p->pManProof );
+ p->pManProof = NULL;
+ }
+ return RetValue;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Reads clauses from file.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Pr_Man_t * Pr_ManProofRead( char * pFileName )
+{
+ Pr_Man_t * p = NULL;
+ char * pCur, * pBuffer = NULL;
+ int * pArray = NULL;
+ FILE * pFile;
+ int RetValue, Counter, nNumbers, Temp;
+ int nClauses, nClausesA, nRoots, nVars;
+
+ // open the file
+ pFile = fopen( pFileName, "r" );
+ if ( pFile == NULL )
+ {
+ printf( "Count not open input file \"%s\".\n", pFileName );
+ return NULL;
+ }
+
+ // read the file
+ pBuffer = (char *)malloc( (1<<16) );
+ for ( Counter = 0; fgets( pBuffer, (1<<16), pFile ); )
+ {
+ if ( pBuffer[0] == 'c' )
+ continue;
+ if ( pBuffer[0] == 'p' )
+ {
+ assert( p == NULL );
+ nClausesA = 0;
+ RetValue = sscanf( pBuffer + 1, "%d %d %d %d", &nVars, &nClauses, &nRoots, &nClausesA );
+ if ( RetValue != 3 && RetValue != 4 )
+ {
+ printf( "Wrong input file format.\n" );
+ }
+ p = Pr_ManAlloc( nVars );
+ pArray = (int *)malloc( sizeof(int) * (nVars + 10) );
+ continue;
+ }
+ // skip empty lines
+ for ( pCur = pBuffer; *pCur; pCur++ )
+ if ( !(*pCur == ' ' || *pCur == '\t' || *pCur == '\r' || *pCur == '\n') )
+ break;
+ if ( *pCur == 0 )
+ continue;
+ // scan the numbers from file
+ nNumbers = 0;
+ pCur = pBuffer;
+ while ( *pCur )
+ {
+ // skip spaces
+ for ( ; *pCur && *pCur == ' '; pCur++ );
+ // read next number
+ Temp = 0;
+ sscanf( pCur, "%d", &Temp );
+ if ( Temp == 0 )
+ break;
+ pArray[ nNumbers++ ] = lit_read( Temp );
+ // skip non-spaces
+ for ( ; *pCur && *pCur != ' '; pCur++ );
+ }
+ // add the clause
+ if ( !Pr_ManAddClause( p, pArray, pArray + nNumbers, Counter < nRoots, Counter < nClausesA ) )
+ {
+ printf( "Bad clause number %d.\n", Counter );
+ return NULL;
+ }
+ // count the clauses
+ Counter++;
+ }
+ // check the number of clauses
+ if ( Counter != nClauses )
+ printf( "Expected %d clauses but read %d.\n", nClauses, Counter );
+
+ // finish
+ if ( pArray ) free( pArray );
+ if ( pBuffer ) free( pBuffer );
+ fclose( pFile );
+ return p;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Records the proof.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+/*
+int Pr_ManProofCount_rec( Pr_Cls_t * pClause )
+{
+ Pr_Cls_t * pNext;
+ int i, Counter;
+ if ( pClause->fRoot )
+ return 0;
+ if ( pClause->fVisit )
+ return 0;
+ pClause->fVisit = 1;
+ // count the number of visited clauses
+ Counter = 1;
+ Vec_PtrForEachEntry( pClause->pAntis, pNext, i )
+ Counter += Pr_ManProofCount_rec( pNext );
+ return Counter;
+}
+*/
+
+/**Function*************************************************************
+
+ Synopsis [Records the proof.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Pr_ManProofTest( char * pFileName )
+{
+ Pr_Man_t * p;
+ int clk, clkTotal = clock();
+
+clk = clock();
+ p = Pr_ManProofRead( pFileName );
+p->timeRead = clock() - clk;
+ if ( p == NULL )
+ return 0;
+
+ Pr_ManProofWrite( p );
+
+ // print stats
+/*
+ nUsed = Pr_ManProofCount_rec( p->pEmpty );
+ printf( "Roots = %d. Learned = %d. Total = %d. Steps = %d. Ave = %.2f. Used = %d. Ratio = %.2f. \n",
+ p->nRoots, p->nClauses-p->nRoots, p->nClauses, p->Counter,
+ 1.0*(p->Counter-p->nRoots)/(p->nClauses-p->nRoots),
+ nUsed, 1.0*nUsed/(p->nClauses-p->nRoots) );
+*/
+ printf( "Vars = %d. Roots = %d. Learned = %d. Resol steps = %d. Ave = %.2f. Mem = %.2f Mb\n",
+ p->nVars, p->nRoots, p->nClauses-p->nRoots, p->Counter,
+ 1.0*(p->Counter-p->nRoots)/(p->nClauses-p->nRoots),
+ 1.0*Pr_ManMemoryReport(p)/(1<<20) );
+
+p->timeTotal = clock() - clkTotal;
+ Pr_ManFree( p );
+ return 1;
+}
+
+
+////////////////////////////////////////////////////////////////////////
+/// END OF FILE ///
+////////////////////////////////////////////////////////////////////////
+
+
diff --git a/src/sat/proof/pr.h b/src/sat/proof/pr.h
new file mode 100644
index 00000000..1e71a2d3
--- /dev/null
+++ b/src/sat/proof/pr.h
@@ -0,0 +1,65 @@
+/**CFile****************************************************************
+
+ FileName [pr.h]
+
+ SystemName [ABC: Logic synthesis and verification system.]
+
+ PackageName [Proof recording.]
+
+ Synopsis [External declarations.]
+
+ Author [Alan Mishchenko]
+
+ Affiliation [UC Berkeley]
+
+ Date [Ver. 1.0. Started - June 20, 2005.]
+
+ Revision [$Id: pr.h,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#ifndef __PR_H__
+#define __PR_H__
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#ifdef _WIN32
+#define inline __inline // compatible with MS VS 6.0
+#endif
+
+////////////////////////////////////////////////////////////////////////
+/// INCLUDES ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+/// PARAMETERS ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+/// BASIC TYPES ///
+////////////////////////////////////////////////////////////////////////
+
+typedef struct Pr_Man_t_ Pr_Man_t;
+
+////////////////////////////////////////////////////////////////////////
+/// MACRO DEFINITIONS ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+/// FUNCTION DECLARATIONS ///
+////////////////////////////////////////////////////////////////////////
+
+/*=== pr.c ==========================================================*/
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
+
+////////////////////////////////////////////////////////////////////////
+/// END OF FILE ///
+////////////////////////////////////////////////////////////////////////
+
diff --git a/src/sat/proof/stats.txt b/src/sat/proof/stats.txt
new file mode 100644
index 00000000..470b1630
--- /dev/null
+++ b/src/sat/proof/stats.txt
@@ -0,0 +1,66 @@
+UC Berkeley, ABC 1.01 (compiled Jan 20 2007 16:47:34)
+abc.rc: No such file or directory
+Loaded "abc.rc" from the parent directory.
+abc 01> test
+Found last conflict after adding unit clause number 10229!
+Roots = 7184. Learned = 3047. Total = 10231. Steps = 196361. Ave = 62.09. Used = 2224. Ratio = 0.73.
+Runtime stats:
+Reading = 0.03 sec
+BCP = 0.32 sec
+Trace = 0.06 sec
+TOTAL = 0.43 sec
+abc 01> test
+Found last conflict after adding unit clause number 7676!
+Roots = 6605. Learned = 1073. Total = 7678. Steps = 52402. Ave = 42.68. Used = 1011. Ratio = 0.94.
+Runtime stats:
+Reading = 0.01 sec
+BCP = 0.02 sec
+Trace = 0.02 sec
+TOTAL = 0.06 sec
+abc 01> test
+Found last conflict after adding unit clause number 37868!
+Roots = 15443. Learned = 22427. Total = 37870. Steps = 2365472. Ave = 104.79. Used = 19763. Ratio = 0.88.
+Runtime stats:
+Reading = 0.20 sec
+BCP = 14.67 sec
+Trace = 0.56 sec
+TOTAL = 15.74 sec
+abc 01>
+
+
+abc 05> wb ibm_bmc/len25u_renc.blif
+abc 05> ps
+(no name) : i/o = 348/ 1 lat = 0 nd = 3648 bdd = 15522 lev = 246
+abc 05> sat -v
+==================================[MINISAT]===================================
+| Conflicts | ORIGINAL | LEARNT | Progress |
+| | Clauses Literals | Limit Clauses Literals Lit/Cl | |
+==============================================================================
+| 0 | 17413 54996 | 5804 0 0 0.0 | 0.000 % |
+| 100 | 17413 54996 | 6384 100 606 6.1 | 0.417 % |
+| 250 | 17413 54996 | 7023 250 1586 6.3 | 0.417 % |
+| 476 | 17413 54996 | 7725 476 3288 6.9 | 0.417 % |
+| 813 | 17413 54996 | 8498 813 7586 9.3 | 0.417 % |
+| 1319 | 17403 54970 | 9347 1318 14848 11.3 | 0.442 % |
+| 2078 | 17403 54970 | 10282 2076 40186 19.4 | 0.466 % |
+| 3217 | 17397 54948 | 11310 3208 99402 31.0 | 0.466 % |
+| 4926 | 17392 54930 | 12441 4911 131848 26.8 | 0.491 % |
+| 7489 | 17392 54930 | 13686 7474 204217 27.3 | 0.491 % |
+| 11336 | 17357 54829 | 15054 11310 332863 29.4 | 0.638 % |
+| 17103 | 17346 54794 | 16559 9130 203029 22.2 | 0.687 % |
+| 25752 | 17288 54606 | 18215 9083 176982 19.5 | 0.834 % |
+| 38727 | 17266 54536 | 20037 12674 278949 22.0 | 0.883 % |
+| 58188 | 17240 54453 | 22041 11905 255255 21.4 | 0.957 % |
+==============================================================================
+Start = 15. Conf = 79435. Dec = 130967. Prop = 24083434. Insp = 136774586.
+Total runtime = 18.66 sec. Var select = 0.00 sec. Var update = 0.00 sec.
+UNSATISFIABLE Time = 18.69 sec
+abc 05>
+abc 05> test
+Found last conflict after adding unit clause number 96902!
+Roots = 17469. Learned = 79435. Total = 96904. Steps = 9700042. Ave = 121.89. Used = 57072. Ratio = 0.72.
+Runtime stats:
+Reading = 1.26 sec
+BCP = 204.99 sec
+Trace = 2.85 sec
+TOTAL = 209.85 sec \ No newline at end of file
diff --git a/todo.txt b/todo.txt
new file mode 100644
index 00000000..3ab59b8c
--- /dev/null
+++ b/todo.txt
@@ -0,0 +1,26 @@
+- required time support
+- printing ABC version/platform in the output files
+- fix gcc compiler warnings
+- port "mfs" from MVSIS
+- improve AIG rewriting package
+- unify functional representation of local functions
+- additional rewriting options for delay optimization
+- experiment with yield-aware standard-cell mapping
+- improving area recovery in integrated sequential synthesis
+- high-effort logic synthesis for hard miters (cofactoring, Boolean division)
+- mapping into MV cells
+- SAT solver with linear constraints
+- specialized synthesis for EXORs and large MUXes
+- sequential AIG rewriting initial state computation
+- placement-aware mapping
+- sequential equivalence checking
+- parser for Verilog netlists
+- hierarchy manager (hierarchical BLIF/BLIF-MV parser)
+
+- required time based on all cuts
+- comparing tts of differently derived the same cut
+- area flow based AIG rewriting
+- cut frontier adjustment
+
+
+